From b5af667b01458e9083256f2614df175916c73e5a Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Sun, 12 May 2024 17:11:09 -0700 Subject: [PATCH 001/578] [BOLT] Map branch source address to the containing basic block in BAT YAML Fix an issue where the profile for all branches that have a BRANCHENTRY is dropped. If the branch has an entry in BAT, it will be translated to its input offset. We used to only permit the basic block offset as a branch source. Perform a lookup of containing basic block instead. Test Plan: Updated bolt-address-translation-yaml.test Reviewers: maksfb, dcci, rafaelauler, ayermolo Reviewed By: maksfb Pull Request: https://github.com/llvm/llvm-project/pull/91273 --- bolt/lib/Profile/DataAggregator.cpp | 21 ++++++++++++------- .../blarge_new_bat_branchentry.preagg.txt | 1 + .../X86/bolt-address-translation-yaml.test | 11 ++++++++++ 3 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 bolt/test/X86/Inputs/blarge_new_bat_branchentry.preagg.txt diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index 2f6380e186e1..9a71e227f233 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -23,6 +23,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" @@ -2378,10 +2379,19 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC, return CSI; }; + // Lookup containing basic block offset and index + auto getBlock = [&BlockMap](uint32_t Offset) { + auto BlockIt = BlockMap.upper_bound(Offset); + if (LLVM_UNLIKELY(BlockIt == BlockMap.begin())) { + errs() << "BOLT-ERROR: invalid BAT section\n"; + exit(1); + } + --BlockIt; + return std::pair(BlockIt->first, BlockIt->second.getBBIndex()); + }; + for (const auto &[FromOffset, SuccKV] : Branches.IntraIndex) { - if (!BlockMap.isInputBlock(FromOffset)) - continue; - const unsigned Index = BlockMap.getBBIndex(FromOffset); + const auto &[_, Index] = getBlock(FromOffset); yaml::bolt::BinaryBasicBlockProfile &YamlBB = YamlBF.Blocks[Index]; for (const auto &[SuccOffset, SuccDataIdx] : SuccKV) if (BlockMap.isInputBlock(SuccOffset)) @@ -2389,10 +2399,7 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC, getSuccessorInfo(SuccOffset, SuccDataIdx)); } for (const auto &[FromOffset, CallTo] : Branches.InterIndex) { - auto BlockIt = BlockMap.upper_bound(FromOffset); - --BlockIt; - const unsigned BlockOffset = BlockIt->first; - const unsigned BlockIndex = BlockIt->second.getBBIndex(); + const auto &[BlockOffset, BlockIndex] = getBlock(FromOffset); yaml::bolt::BinaryBasicBlockProfile &YamlBB = YamlBF.Blocks[BlockIndex]; const uint32_t Offset = FromOffset - BlockOffset; for (const auto &[CallToLoc, CallToIdx] : CallTo) diff --git a/bolt/test/X86/Inputs/blarge_new_bat_branchentry.preagg.txt b/bolt/test/X86/Inputs/blarge_new_bat_branchentry.preagg.txt new file mode 100644 index 000000000000..546da92f94db --- /dev/null +++ b/bolt/test/X86/Inputs/blarge_new_bat_branchentry.preagg.txt @@ -0,0 +1 @@ +B 80010c 800194 1 0 diff --git a/bolt/test/X86/bolt-address-translation-yaml.test b/bolt/test/X86/bolt-address-translation-yaml.test index 38a50f6cacaf..c15d6ce15ed0 100644 --- a/bolt/test/X86/bolt-address-translation-yaml.test +++ b/bolt/test/X86/bolt-address-translation-yaml.test @@ -5,6 +5,17 @@ RUN: llvm-bolt %t.exe -o %t.out --pa -p %p/Inputs/blarge_new.preagg.txt \ RUN: --reorder-blocks=ext-tsp --split-functions --split-strategy=cdsplit \ RUN: --reorder-functions=cdsort --enable-bat --dyno-stats --skip-funcs=main \ RUN: 2>&1 | FileCheck --check-prefix WRITE-BAT-CHECK %s +# Check that branch with entry in BAT is accounted for. +RUN: perf2bolt %t.out --pa -p %p/Inputs/blarge_new_bat_branchentry.preagg.txt \ +RUN: -w %t.yaml -o %t.fdata +RUN: llvm-bolt %t.exe -data %t.fdata -w %t.yaml-fdata -o %t.null +RUN: FileCheck --input-file %t.yaml --check-prefix BRANCHENTRY-YAML-CHECK %s +RUN: FileCheck --input-file %t.yaml-fdata --check-prefix BRANCHENTRY-YAML-CHECK %s +BRANCHENTRY-YAML-CHECK: - name: SolveCubic +BRANCHENTRY-YAML-CHECK: bid: 0 +BRANCHENTRY-YAML-CHECK: hash: 0x700F19D24600000 +BRANCHENTRY-YAML-CHECK-NEXT: succ: [ { bid: 7, cnt: 1 } +# Large profile test RUN: perf2bolt %t.out --pa -p %p/Inputs/blarge_new_bat.preagg.txt -w %t.yaml -o %t.fdata \ RUN: 2>&1 | FileCheck --check-prefix READ-BAT-CHECK %s RUN: FileCheck --input-file %t.yaml --check-prefix YAML-BAT-CHECK %s -- GitLab From 5bde8017a1109128d011510dcf4ba79140a224fe Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Mon, 13 May 2024 08:31:49 +0800 Subject: [PATCH 002/578] [X86][vectorcall] Pass built types byval when xmm0~6 exhausted (#91846) This is how MSVC handles it. https://godbolt.org/z/fG386bjnf --- clang/lib/CodeGen/Targets/X86.cpp | 2 ++ clang/test/CodeGen/vectorcall.c | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 717a27fc9c57..29d98aad8fcb 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -792,6 +792,8 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, return ABIArgInfo::getDirect(); return ABIArgInfo::getExpand(); } + if (IsVectorCall && Ty->isBuiltinType()) + return ABIArgInfo::getDirect(); return getIndirectResult(Ty, /*ByVal=*/false, State); } diff --git a/clang/test/CodeGen/vectorcall.c b/clang/test/CodeGen/vectorcall.c index cb53ecc70351..71dc3b0b9585 100644 --- a/clang/test/CodeGen/vectorcall.c +++ b/clang/test/CodeGen/vectorcall.c @@ -140,4 +140,20 @@ void __vectorcall vectorcall_indirect_vec( // X86-SAME: ptr inreg noundef %0, // X86-SAME: i32 inreg noundef %edx, // X86-SAME: ptr noundef %1) + +void __vectorcall vectorcall_indirect_fp( + double xmm0, double xmm1, double xmm2, double xmm3, double xmm4, + v4f32 xmm5, v4f32 ecx, int edx, double mem) { +} + +// X86: define dso_local x86_vectorcallcc void @"\01vectorcall_indirect_fp@@{{[0-9]+}}" +// X86-SAME: (double inreg noundef %xmm0, +// X86-SAME: double inreg noundef %xmm1, +// X86-SAME: double inreg noundef %xmm2, +// X86-SAME: double inreg noundef %xmm3, +// X86-SAME: double inreg noundef %xmm4, +// X86-SAME: <4 x float> inreg noundef %xmm5, +// X86-SAME: ptr inreg noundef %0, +// X86-SAME: i32 inreg noundef %edx, +// X86-SAME: double noundef %mem) #endif -- GitLab From 626025ac7796b70cde9fc0fd4f688c3441949d04 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 12 May 2024 17:23:19 -0700 Subject: [PATCH 003/578] Revert "[clang-format] Fix buildbot failures" This reverts commit 0869204cff22831d0bb19a82c99bf85e4deb4ae3, which caused a buildbot failure: https://lab.llvm.org/buildbot/#/builders/5/builds/43322 --- clang/lib/Format/QualifierAlignmentFixer.cpp | 18 ++-- clang/lib/Format/QualifierAlignmentFixer.h | 4 +- clang/unittests/Format/QualifierFixerTest.cpp | 92 +++++++++++-------- 3 files changed, 62 insertions(+), 52 deletions(-) diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp index 077ce5e597a2..a904f0b773c6 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.cpp +++ b/clang/lib/Format/QualifierAlignmentFixer.cpp @@ -281,7 +281,7 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( const FormatToken *LastSimpleTypeSpecifier = TypeToken; while (isQualifierOrType(LastSimpleTypeSpecifier->getNextNonComment(), - &LangOpts)) { + LangOpts)) { LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment(); } @@ -414,7 +414,7 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft( const FormatToken *LastSimpleTypeSpecifier = TypeToken; while (isConfiguredQualifierOrType( LastSimpleTypeSpecifier->getPreviousNonComment(), - ConfiguredQualifierTokens, &LangOpts)) { + ConfiguredQualifierTokens, LangOpts)) { LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getPreviousNonComment(); } @@ -613,18 +613,16 @@ void prepareLeftRightOrderingForQualifierAlignmentFixer( } bool LeftRightQualifierAlignmentFixer::isQualifierOrType( - const FormatToken *Tok, const LangOptions *LangOpts) { - return Tok && - (Tok->isTypeName(LangOpts ? *LangOpts : getFormattingLangOpts()) || - Tok->is(tok::kw_auto) || isQualifier(Tok)); + const FormatToken *Tok, const LangOptions &LangOpts) { + return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) || + isQualifier(Tok)); } bool LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( const FormatToken *Tok, const std::vector &Qualifiers, - const LangOptions *LangOpts) { - return Tok && - (Tok->isTypeName(LangOpts ? *LangOpts : getFormattingLangOpts()) || - Tok->is(tok::kw_auto) || isConfiguredQualifier(Tok, Qualifiers)); + const LangOptions &LangOpts) { + return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) || + isConfiguredQualifier(Tok, Qualifiers)); } // If a token is an identifier and it's upper case, it could diff --git a/clang/lib/Format/QualifierAlignmentFixer.h b/clang/lib/Format/QualifierAlignmentFixer.h index 97fcb42e4b2e..710fa2dc0030 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.h +++ b/clang/lib/Format/QualifierAlignmentFixer.h @@ -72,11 +72,11 @@ public: // Is the Token a simple or qualifier type static bool isQualifierOrType(const FormatToken *Tok, - const LangOptions *LangOpts = nullptr); + const LangOptions &LangOpts); static bool isConfiguredQualifierOrType(const FormatToken *Tok, const std::vector &Qualifiers, - const LangOptions *LangOpts = nullptr); + const LangOptions &LangOpts); // Is the Token likely a Macro static bool isPossibleMacro(const FormatToken *Tok); diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index 792d8f3c3a98..5463bfbb65ca 100644 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -1055,70 +1055,82 @@ TEST_F(QualifierFixerTest, IsQualifierType) { ConfiguredTokens.push_back(tok::kw_constexpr); ConfiguredTokens.push_back(tok::kw_friend); + LangOptions LangOpts{getFormattingLangOpts()}; + auto Tokens = annotate( "const static inline auto restrict int double long constexpr friend"); ASSERT_EQ(Tokens.size(), 11u) << Tokens; EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[0], ConfiguredTokens)); + Tokens[0], ConfiguredTokens, LangOpts)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[1], ConfiguredTokens)); + Tokens[1], ConfiguredTokens, LangOpts)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[2], ConfiguredTokens)); + Tokens[2], ConfiguredTokens, LangOpts)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[3], ConfiguredTokens)); + Tokens[3], ConfiguredTokens, LangOpts)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[4], ConfiguredTokens)); + Tokens[4], ConfiguredTokens, LangOpts)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[5], ConfiguredTokens)); + Tokens[5], ConfiguredTokens, LangOpts)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[6], ConfiguredTokens)); + Tokens[6], ConfiguredTokens, LangOpts)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[7], ConfiguredTokens)); + Tokens[7], ConfiguredTokens, LangOpts)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[8], ConfiguredTokens)); + Tokens[8], ConfiguredTokens, LangOpts)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[9], ConfiguredTokens)); - - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[0])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[1])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[2])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[3])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[4])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[5])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[6])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[7])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[8])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[9])); + Tokens[9], ConfiguredTokens, LangOpts)); + + EXPECT_TRUE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[0], LangOpts)); + EXPECT_TRUE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[1], LangOpts)); + EXPECT_TRUE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[2], LangOpts)); + EXPECT_TRUE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[3], LangOpts)); + EXPECT_TRUE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[4], LangOpts)); + EXPECT_TRUE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[5], LangOpts)); + EXPECT_TRUE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[6], LangOpts)); + EXPECT_TRUE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[7], LangOpts)); + EXPECT_TRUE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[8], LangOpts)); + EXPECT_TRUE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[9], LangOpts)); auto NotTokens = annotate("for while do Foo Bar "); ASSERT_EQ(NotTokens.size(), 6u) << Tokens; EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[0], ConfiguredTokens)); + NotTokens[0], ConfiguredTokens, LangOpts)); EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[1], ConfiguredTokens)); + NotTokens[1], ConfiguredTokens, LangOpts)); EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[2], ConfiguredTokens)); + NotTokens[2], ConfiguredTokens, LangOpts)); EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[3], ConfiguredTokens)); + NotTokens[3], ConfiguredTokens, LangOpts)); EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[4], ConfiguredTokens)); + NotTokens[4], ConfiguredTokens, LangOpts)); EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[5], ConfiguredTokens)); - - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[0])); - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[1])); - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[2])); - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[3])); - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[4])); - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[5])); + NotTokens[5], ConfiguredTokens, LangOpts)); + + EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[0], + LangOpts)); + EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[1], + LangOpts)); + EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[2], + LangOpts)); + EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[3], + LangOpts)); + EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[4], + LangOpts)); + EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[5], + LangOpts)); } TEST_F(QualifierFixerTest, IsMacro) { -- GitLab From ed16e7aac44f2024b45d8c6c9dc2817d77d0ea97 Mon Sep 17 00:00:00 2001 From: Shih-Po Hung Date: Mon, 13 May 2024 09:47:57 +0800 Subject: [PATCH 004/578] [RISCV][TTI] Support fdiv/udiv/sdiv/srem/urem in getArithmeticInstrCost (#89170) This patch made following changes: 1. Support ISD FDIV/UDIV/SDIV/UREM/SREM 2. Classify instructions which cost the same --- .../Target/RISCV/RISCVTargetTransformInfo.cpp | 47 +- .../test/Analysis/CostModel/RISCV/arith-fp.ll | 48 +- .../Analysis/CostModel/RISCV/arith-int.ll | 828 ++++++++++++++---- 3 files changed, 710 insertions(+), 213 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index 5f84175da703..984638c1e50d 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -1619,29 +1619,58 @@ InstructionCost RISCVTTIImpl::getArithmeticInstrCost( if (Op2Info.isConstant()) ConstantMatCost += getConstantMatCost(1, Op2Info); + unsigned Op; switch (TLI->InstructionOpcodeToISD(Opcode)) { case ISD::ADD: case ISD::SUB: - case ISD::AND: - case ISD::OR: - case ISD::XOR: + Op = RISCV::VADD_VV; + break; case ISD::SHL: case ISD::SRL: case ISD::SRA: + Op = RISCV::VSLL_VV; + break; + case ISD::AND: + case ISD::OR: + case ISD::XOR: + Op = (Ty->getScalarSizeInBits() == 1) ? RISCV::VMAND_MM : RISCV::VAND_VV; + break; case ISD::MUL: case ISD::MULHS: case ISD::MULHU: + Op = RISCV::VMUL_VV; + break; + case ISD::SDIV: + case ISD::UDIV: + Op = RISCV::VDIV_VV; + break; + case ISD::SREM: + case ISD::UREM: + Op = RISCV::VREM_VV; + break; case ISD::FADD: case ISD::FSUB: + // TODO: Address FP16 with VFHMIN + Op = RISCV::VFADD_VV; case ISD::FMUL: - case ISD::FNEG: { - return ConstantMatCost + TLI->getLMULCost(LT.second) * LT.first * 1; - } + // TODO: Address FP16 with VFHMIN + Op = RISCV::VFMUL_VV; + break; + case ISD::FDIV: + Op = RISCV::VFDIV_VV; + break; + case ISD::FNEG: + Op = RISCV::VFSGNJN_VV; + break; default: - return ConstantMatCost + - BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info, - Args, CxtI); + // Assuming all other instructions have the same cost until a need arises to + // differentiate them. + return ConstantMatCost + BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, + Op1Info, Op2Info, + Args, CxtI); } + return ConstantMatCost + + LT.first * getRISCVInstructionCost(Op, LT.second, CostKind); } // TODO: Deduplicate from TargetTransformInfoImplCRTPBase. diff --git a/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll b/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll index 1dde88f366a3..d1e8bb015491 100644 --- a/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll +++ b/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll @@ -248,36 +248,36 @@ define i32 @fdiv() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %F16 = fdiv half undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %F32 = fdiv float undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %F64 = fdiv double undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V1F16 = fdiv <1 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V2F16 = fdiv <2 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4F16 = fdiv <4 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8F16 = fdiv <8 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16F16 = fdiv <16 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1F16 = fdiv <1 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2F16 = fdiv <2 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4F16 = fdiv <4 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8F16 = fdiv <8 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16F16 = fdiv <16 x half> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32F16 = fdiv <32 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4F16 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV16F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV32F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V1F32 = fdiv <1 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V2F32 = fdiv <2 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4F32 = fdiv <4 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8F32 = fdiv <8 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1F32 = fdiv <1 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2F32 = fdiv <2 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4F32 = fdiv <4 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8F32 = fdiv <8 x float> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16F32 = fdiv <16 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2F32 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV16F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V1F64 = fdiv <1 x double> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V2F64 = fdiv <2 x double> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4F64 = fdiv <4 x double> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1F64 = fdiv <1 x double> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2F64 = fdiv <2 x double> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4F64 = fdiv <4 x double> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8F64 = fdiv <8 x double> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1F64 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1F64 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2F64 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4F64 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8F64 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4F64 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8F64 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %F16 = fdiv half undef, undef diff --git a/llvm/test/Analysis/CostModel/RISCV/arith-int.ll b/llvm/test/Analysis/CostModel/RISCV/arith-int.ll index b4afbb513166..c976f483fdfe 100644 --- a/llvm/test/Analysis/CostModel/RISCV/arith-int.ll +++ b/llvm/test/Analysis/CostModel/RISCV/arith-int.ll @@ -705,72 +705,72 @@ define i32 @udiv() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = udiv i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = udiv i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = udiv i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = udiv <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = udiv <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = udiv <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = udiv <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = udiv <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = udiv <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = udiv <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = udiv <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = udiv <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = udiv <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = udiv <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = udiv <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = udiv <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = udiv <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = udiv <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = udiv <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = udiv <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = udiv <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = udiv <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = udiv <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = udiv <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = udiv <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = udiv <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = udiv <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = udiv <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = udiv <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = udiv <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'udiv' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = udiv i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = udiv i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = udiv i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = udiv <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = udiv <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = udiv <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = udiv <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = udiv <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = udiv <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = udiv <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = udiv <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = udiv <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = udiv <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = udiv <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = udiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = udiv <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = udiv <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = udiv <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = udiv <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = udiv <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = udiv <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = udiv <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = udiv <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = udiv <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = udiv <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = udiv <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = udiv <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = udiv <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = udiv <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = udiv <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = udiv <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = udiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = udiv i16 undef, undef @@ -821,72 +821,72 @@ define i32 @urem() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = urem i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = urem i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = urem i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = urem <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = urem <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = urem <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = urem <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = urem <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = urem <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = urem <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = urem <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = urem <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = urem <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = urem <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = urem <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = urem <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = urem <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = urem <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = urem <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = urem <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = urem <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = urem <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = urem <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = urem <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = urem <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = urem <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = urem <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = urem <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = urem <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = urem <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'urem' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = urem i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = urem i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = urem i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = urem <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = urem <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = urem <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = urem <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = urem <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = urem <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = urem <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = urem <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = urem <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = urem <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = urem <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = urem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = urem <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = urem <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = urem <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = urem <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = urem <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = urem <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = urem <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = urem <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = urem <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = urem <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = urem <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = urem <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = urem <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = urem <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = urem <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = urem <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = urem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = urem i16 undef, undef @@ -937,72 +937,72 @@ define i32 @sdiv() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = sdiv i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = sdiv i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = sdiv i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = sdiv <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = sdiv <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = sdiv <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = sdiv <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = sdiv <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = sdiv <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = sdiv <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = sdiv <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = sdiv <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = sdiv <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = sdiv <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = sdiv <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = sdiv <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = sdiv <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = sdiv <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = sdiv <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = sdiv <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = sdiv <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = sdiv <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = sdiv <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = sdiv <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = sdiv <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = sdiv <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = sdiv <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = sdiv <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = sdiv <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = sdiv <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'sdiv' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = sdiv i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = sdiv i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = sdiv i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = sdiv <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = sdiv <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = sdiv <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = sdiv <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = sdiv <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = sdiv <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = sdiv <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = sdiv <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = sdiv <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = sdiv <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = sdiv <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = sdiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = sdiv <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = sdiv <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = sdiv <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = sdiv <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = sdiv <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = sdiv <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = sdiv <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = sdiv <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = sdiv <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = sdiv <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = sdiv <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = sdiv <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = sdiv <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = sdiv <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = sdiv <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = sdiv <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = sdiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = sdiv i16 undef, undef @@ -1053,72 +1053,72 @@ define i32 @srem() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = srem i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = srem i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = srem i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = srem <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = srem <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = srem <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = srem <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = srem <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = srem <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = srem <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = srem <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = srem <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = srem <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = srem <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = srem <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = srem <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = srem <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = srem <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = srem <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = srem <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = srem <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = srem <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = srem <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = srem <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = srem <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = srem <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = srem <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = srem <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = srem <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = srem <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'srem' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = srem i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = srem i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = srem i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = srem <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = srem <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = srem <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = srem <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = srem <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = srem <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = srem <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = srem <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = srem <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = srem <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = srem <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = srem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = srem <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = srem <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = srem <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = srem <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = srem <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = srem <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = srem <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = srem <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = srem <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = srem <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = srem <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = srem <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = srem <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = srem <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = srem <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = srem <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = srem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = srem i16 undef, undef @@ -1232,3 +1232,471 @@ define void @add_of_constant() { ret void } + +define i32 @and() { +; CHECK-LABEL: 'and' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = and i1 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = and i16 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = and i32 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = and i64 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = and <1 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = and <2 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = and <4 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = and <8 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = and <16 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = and <32 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = and <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = and <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = and <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = and <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = and <16 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %16 = and <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = and <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = and <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = and <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %20 = and <8 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %21 = and <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = and <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = and <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = and <4 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = and <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %35 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %36 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %37 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %40 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %41 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %42 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %43 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %44 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %45 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %46 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; +; SIFIVE-X280-LABEL: 'and' +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = and i1 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = and i16 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = and i32 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = and i64 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = and <1 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = and <2 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = and <4 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = and <8 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = and <16 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = and <32 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = and <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = and <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = and <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = and <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = and <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %16 = and <32 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = and <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = and <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = and <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = and <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = and <16 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = and <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = and <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = and <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %25 = and <8 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %34 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %35 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %36 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %37 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %39 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %40 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %41 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %42 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %43 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %44 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %45 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %46 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; + and i1 undef, undef + and i16 undef, undef + and i32 undef, undef + and i64 undef, undef + + and <1 x i1> undef, undef + and <2 x i1> undef, undef + and <4 x i1> undef, undef + and <8 x i1> undef, undef + and <16 x i1> undef, undef + and <32 x i1> undef, undef + + and <1 x i16> undef, undef + and <2 x i16> undef, undef + and <4 x i16> undef, undef + and <8 x i16> undef, undef + and <16 x i16> undef, undef + and <32 x i16> undef, undef + + and <1 x i32> undef, undef + and <2 x i32> undef, undef + and <4 x i32> undef, undef + and <8 x i32> undef, undef + and <16 x i32> undef, undef + + and <1 x i64> undef, undef + and <2 x i64> undef, undef + and <4 x i64> undef, undef + and <8 x i64> undef, undef + + and undef, undef + and undef, undef + and undef, undef + and undef, undef + and undef, undef + and undef, undef + + and undef, undef + and undef, undef + and undef, undef + and undef, undef + and undef, undef + and undef, undef + + and undef, undef + and undef, undef + and undef, undef + and undef, undef + and undef, undef + + and undef, undef + and undef, undef + and undef, undef + and undef, undef + ret i32 undef +} + +define i32 @or() { +; CHECK-LABEL: 'or' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = or i1 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = or i16 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = or i32 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = or i64 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = or <1 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = or <2 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = or <4 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = or <8 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = or <16 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = or <32 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = or <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = or <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = or <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = or <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = or <16 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %16 = or <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = or <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = or <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = or <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %20 = or <8 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %21 = or <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = or <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = or <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = or <4 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = or <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %35 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %36 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %37 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %40 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %41 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %42 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %43 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %44 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %45 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %46 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; +; SIFIVE-X280-LABEL: 'or' +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = or i1 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = or i16 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = or i32 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = or i64 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = or <1 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = or <2 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = or <4 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = or <8 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = or <16 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = or <32 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = or <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = or <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = or <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = or <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = or <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %16 = or <32 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = or <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = or <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = or <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = or <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = or <16 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = or <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = or <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = or <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %25 = or <8 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %34 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %35 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %36 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %37 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %39 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %40 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %41 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %42 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %43 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %44 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %45 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %46 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; + or i1 undef, undef + or i16 undef, undef + or i32 undef, undef + or i64 undef, undef + + or <1 x i1> undef, undef + or <2 x i1> undef, undef + or <4 x i1> undef, undef + or <8 x i1> undef, undef + or <16 x i1> undef, undef + or <32 x i1> undef, undef + + or <1 x i16> undef, undef + or <2 x i16> undef, undef + or <4 x i16> undef, undef + or <8 x i16> undef, undef + or <16 x i16> undef, undef + or <32 x i16> undef, undef + + or <1 x i32> undef, undef + or <2 x i32> undef, undef + or <4 x i32> undef, undef + or <8 x i32> undef, undef + or <16 x i32> undef, undef + + or <1 x i64> undef, undef + or <2 x i64> undef, undef + or <4 x i64> undef, undef + or <8 x i64> undef, undef + + or undef, undef + or undef, undef + or undef, undef + or undef, undef + or undef, undef + or undef, undef + + or undef, undef + or undef, undef + or undef, undef + or undef, undef + or undef, undef + or undef, undef + + or undef, undef + or undef, undef + or undef, undef + or undef, undef + or undef, undef + + or undef, undef + or undef, undef + or undef, undef + or undef, undef + ret i32 undef +} + +define i32 @xor() { +; CHECK-LABEL: 'xor' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = xor i1 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = xor i16 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = xor i32 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = xor i64 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = xor <1 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = xor <2 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = xor <4 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = xor <8 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = xor <16 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = xor <32 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = xor <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = xor <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = xor <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = xor <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = xor <16 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %16 = xor <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = xor <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = xor <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = xor <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %20 = xor <8 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %21 = xor <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = xor <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = xor <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = xor <4 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = xor <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %35 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %36 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %37 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %40 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %41 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %42 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %43 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %44 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %45 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %46 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; +; SIFIVE-X280-LABEL: 'xor' +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = xor i1 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = xor i16 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = xor i32 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = xor i64 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = xor <1 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = xor <2 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = xor <4 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = xor <8 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = xor <16 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = xor <32 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = xor <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = xor <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = xor <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = xor <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = xor <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %16 = xor <32 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = xor <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = xor <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = xor <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = xor <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = xor <16 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = xor <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = xor <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = xor <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %25 = xor <8 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %34 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %35 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %36 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %37 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %39 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %40 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %41 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %42 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %43 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %44 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %45 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %46 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; + xor i1 undef, undef + xor i16 undef, undef + xor i32 undef, undef + xor i64 undef, undef + + xor <1 x i1> undef, undef + xor <2 x i1> undef, undef + xor <4 x i1> undef, undef + xor <8 x i1> undef, undef + xor <16 x i1> undef, undef + xor <32 x i1> undef, undef + + xor <1 x i16> undef, undef + xor <2 x i16> undef, undef + xor <4 x i16> undef, undef + xor <8 x i16> undef, undef + xor <16 x i16> undef, undef + xor <32 x i16> undef, undef + + xor <1 x i32> undef, undef + xor <2 x i32> undef, undef + xor <4 x i32> undef, undef + xor <8 x i32> undef, undef + xor <16 x i32> undef, undef + + xor <1 x i64> undef, undef + xor <2 x i64> undef, undef + xor <4 x i64> undef, undef + xor <8 x i64> undef, undef + + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + ret i32 undef +} -- GitLab From de641e289269061f8bdb138bb5c50e27ef4b354f Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 12 May 2024 18:53:05 -0700 Subject: [PATCH 005/578] [clang-format] Fix buildbot failures Fix the following buildbot failures by making LangOpts in the unit test static: https://lab.llvm.org/buildbot/#/builders/236/builds/11223 https://lab.llvm.org/buildbot/#/builders/239/builds/6968 --- clang/unittests/Format/QualifierFixerTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index 5463bfbb65ca..fdc392e5d948 100644 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -1055,7 +1055,7 @@ TEST_F(QualifierFixerTest, IsQualifierType) { ConfiguredTokens.push_back(tok::kw_constexpr); ConfiguredTokens.push_back(tok::kw_friend); - LangOptions LangOpts{getFormattingLangOpts()}; + static const LangOptions LangOpts{getFormattingLangOpts()}; auto Tokens = annotate( "const static inline auto restrict int double long constexpr friend"); -- GitLab From abe3c5ac19e455d8a6df3120fa5e7a6e5f9005a6 Mon Sep 17 00:00:00 2001 From: AdityaK Date: Sun, 12 May 2024 19:41:54 -0700 Subject: [PATCH 006/578] [GVNSink] Fix non-determinisms by using a deterministic ordering (#90995) GVNSink used to order instructions based on their pointer values and was prone to non-determinism because of that. This patch ensures all the values stored are using a deterministic order. I have also added a verfier(`ModelledPHI::verifyModelledPHI`) to assert when ordering isn't preserved. Additionally, I have added a test case (mirror graph image of an existing test) that would have failed before this patch. Fixes: #77852 --- llvm/lib/Transforms/Scalar/GVNSink.cpp | 78 +++++++++++++++---- .../test/Transforms/GVNSink/int_sideeffect.ll | 26 +++++++ 2 files changed, 91 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/GVNSink.cpp b/llvm/lib/Transforms/Scalar/GVNSink.cpp index d4907326eb0a..ddf01dc612bb 100644 --- a/llvm/lib/Transforms/Scalar/GVNSink.cpp +++ b/llvm/lib/Transforms/Scalar/GVNSink.cpp @@ -226,12 +226,22 @@ class ModelledPHI { public: ModelledPHI() = default; - ModelledPHI(const PHINode *PN) { - // BasicBlock comes first so we sort by basic block pointer order, then by value pointer order. - SmallVector, 4> Ops; + ModelledPHI(const PHINode *PN, + const DenseMap &BlockOrder) { + // BasicBlock comes first so we sort by basic block pointer order, + // then by value pointer order. No need to call `verifyModelledPHI` + // As the Values and Blocks are populated in a deterministic order. + using OpsType = std::pair; + SmallVector Ops; for (unsigned I = 0, E = PN->getNumIncomingValues(); I != E; ++I) Ops.push_back({PN->getIncomingBlock(I), PN->getIncomingValue(I)}); - llvm::sort(Ops); + + auto ComesBefore = [BlockOrder](OpsType O1, OpsType O2) { + return BlockOrder.lookup(O1.first) < BlockOrder.lookup(O2.first); + }; + // Sort in a deterministic order. + llvm::sort(Ops, ComesBefore); + for (auto &P : Ops) { Blocks.push_back(P.first); Values.push_back(P.second); @@ -247,16 +257,38 @@ public: return M; } + void + verifyModelledPHI(const DenseMap &BlockOrder) { + assert(Values.size() > 1 && Blocks.size() > 1 && + "Modelling PHI with less than 2 values"); + auto ComesBefore = [BlockOrder](const BasicBlock *BB1, + const BasicBlock *BB2) { + return BlockOrder.lookup(BB1) < BlockOrder.lookup(BB2); + }; + assert(llvm::is_sorted(Blocks, ComesBefore)); + int C = 0; + llvm::for_each(Values, [&C, this](const Value *V) { + if (!isa(V)) { + const Instruction *I = cast(V); + assert(I->getParent() == this->Blocks[C]); + } + C++; + }); + } /// Create a PHI from an array of incoming values and incoming blocks. - template - ModelledPHI(const VArray &V, const BArray &B) { + ModelledPHI(SmallVectorImpl &V, + SmallSetVector &B, + const DenseMap &BlockOrder) { + // The order of Values and Blocks are already ordered by the caller. llvm::copy(V, std::back_inserter(Values)); llvm::copy(B, std::back_inserter(Blocks)); + verifyModelledPHI(BlockOrder); } /// Create a PHI from [I[OpNum] for I in Insts]. - template - ModelledPHI(ArrayRef Insts, unsigned OpNum, const BArray &B) { + /// TODO: Figure out a way to verifyModelledPHI in this constructor. + ModelledPHI(ArrayRef Insts, unsigned OpNum, + SmallSetVector &B) { llvm::copy(B, std::back_inserter(Blocks)); for (auto *I : Insts) Values.push_back(I->getOperand(OpNum)); @@ -297,7 +329,8 @@ public: // Hash functor unsigned hash() const { - return (unsigned)hash_combine_range(Values.begin(), Values.end()); + // Is deterministic because Values are saved in a specific order. + return (unsigned)hash_combine_range(Values.begin(), Values.end()); } bool operator==(const ModelledPHI &Other) const { @@ -566,7 +599,7 @@ public: class GVNSink { public: - GVNSink() = default; + GVNSink() {} bool run(Function &F) { LLVM_DEBUG(dbgs() << "GVNSink: running on function @" << F.getName() @@ -575,6 +608,16 @@ public: unsigned NumSunk = 0; ReversePostOrderTraversal RPOT(&F); VN.setReachableBBs(BasicBlocksSet(RPOT.begin(), RPOT.end())); + // Populate reverse post-order to order basic blocks in deterministic + // order. Any arbitrary ordering will work in this case as long as they are + // deterministic. The node ordering of newly created basic blocks + // are irrelevant because RPOT(for computing sinkable candidates) is also + // obtained ahead of time and only their order are relevant for this pass. + unsigned NodeOrdering = 0; + RPOTOrder[*RPOT.begin()] = ++NodeOrdering; + for (auto *BB : RPOT) + if (!pred_empty(BB)) + RPOTOrder[BB] = ++NodeOrdering; for (auto *N : RPOT) NumSunk += sinkBB(N); @@ -583,6 +626,7 @@ public: private: ValueTable VN; + DenseMap RPOTOrder; bool shouldAvoidSinkingInstruction(Instruction *I) { // These instructions may change or break semantics if moved. @@ -603,7 +647,7 @@ private: void analyzeInitialPHIs(BasicBlock *BB, ModelledPHISet &PHIs, SmallPtrSetImpl &PHIContents) { for (PHINode &PN : BB->phis()) { - auto MPHI = ModelledPHI(&PN); + auto MPHI = ModelledPHI(&PN, RPOTOrder); PHIs.insert(MPHI); for (auto *V : MPHI.getValues()) PHIContents.insert(V); @@ -691,7 +735,7 @@ GVNSink::analyzeInstructionForSinking(LockstepReverseIterator &LRI, } // The sunk instruction's results. - ModelledPHI NewPHI(NewInsts, ActivePreds); + ModelledPHI NewPHI(NewInsts, ActivePreds, RPOTOrder); // Does sinking this instruction render previous PHIs redundant? if (NeededPHIs.erase(NewPHI)) @@ -766,6 +810,9 @@ unsigned GVNSink::sinkBB(BasicBlock *BBEnd) { BBEnd->printAsOperand(dbgs()); dbgs() << "\n"); SmallVector Preds; for (auto *B : predecessors(BBEnd)) { + // Bailout on basic blocks without predecessor(PR42346). + if (!RPOTOrder.count(B)) + return 0; auto *T = B->getTerminator(); if (isa(T) || isa(T)) Preds.push_back(B); @@ -774,7 +821,11 @@ unsigned GVNSink::sinkBB(BasicBlock *BBEnd) { } if (Preds.size() < 2) return 0; - llvm::sort(Preds); + auto ComesBefore = [this](const BasicBlock *BB1, const BasicBlock *BB2) { + return RPOTOrder.lookup(BB1) < RPOTOrder.lookup(BB2); + }; + // Sort in a deterministic order. + llvm::sort(Preds, ComesBefore); unsigned NumOrigPreds = Preds.size(); // We can only sink instructions through unconditional branches. @@ -889,5 +940,6 @@ PreservedAnalyses GVNSinkPass::run(Function &F, FunctionAnalysisManager &AM) { GVNSink G; if (!G.run(F)) return PreservedAnalyses::all(); + return PreservedAnalyses::none(); } diff --git a/llvm/test/Transforms/GVNSink/int_sideeffect.ll b/llvm/test/Transforms/GVNSink/int_sideeffect.ll index 3cc54e84f17c..9a3bc062dd94 100644 --- a/llvm/test/Transforms/GVNSink/int_sideeffect.ll +++ b/llvm/test/Transforms/GVNSink/int_sideeffect.ll @@ -28,3 +28,29 @@ if.end: ret float %phi } +; CHECK-LABEL: scalarsSinkingReverse +; CHECK-NOT: fmul +; CHECK: = phi +; CHECK: = fmul +define float @scalarsSinkingReverse(float %d, float %m, float %a, i1 %cmp) { +; This test is just a reverse(graph mirror) of the test +; above to ensure GVNSink doesn't depend on the order of branches. +entry: + br i1 %cmp, label %if.then, label %if.else + +if.then: + %add = fadd float %m, %a + %mul1 = fmul float %add, %d + br label %if.end + +if.else: + call void @llvm.sideeffect() + %sub = fsub float %m, %a + %mul0 = fmul float %sub, %d + br label %if.end + +if.end: + %phi = phi float [ %mul1, %if.then ], [ %mul0, %if.else ] + ret float %phi +} + -- GitLab From d67c3a4b1f465da681b829fda54619ff0b5bd1b5 Mon Sep 17 00:00:00 2001 From: ShihPo Hung Date: Sun, 12 May 2024 19:57:40 -0700 Subject: [PATCH 007/578] Revert "[RISCV][TTI] Support fdiv/udiv/sdiv/srem/urem in getArithmeticInstrCost (#89170)" This reverts commit ed16e7aac44f2024b45d8c6c9dc2817d77d0ea97. --- .../Target/RISCV/RISCVTargetTransformInfo.cpp | 47 +- .../test/Analysis/CostModel/RISCV/arith-fp.ll | 48 +- .../Analysis/CostModel/RISCV/arith-int.ll | 828 ++++-------------- 3 files changed, 213 insertions(+), 710 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index 984638c1e50d..5f84175da703 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -1619,58 +1619,29 @@ InstructionCost RISCVTTIImpl::getArithmeticInstrCost( if (Op2Info.isConstant()) ConstantMatCost += getConstantMatCost(1, Op2Info); - unsigned Op; switch (TLI->InstructionOpcodeToISD(Opcode)) { case ISD::ADD: case ISD::SUB: - Op = RISCV::VADD_VV; - break; - case ISD::SHL: - case ISD::SRL: - case ISD::SRA: - Op = RISCV::VSLL_VV; - break; case ISD::AND: case ISD::OR: case ISD::XOR: - Op = (Ty->getScalarSizeInBits() == 1) ? RISCV::VMAND_MM : RISCV::VAND_VV; - break; + case ISD::SHL: + case ISD::SRL: + case ISD::SRA: case ISD::MUL: case ISD::MULHS: case ISD::MULHU: - Op = RISCV::VMUL_VV; - break; - case ISD::SDIV: - case ISD::UDIV: - Op = RISCV::VDIV_VV; - break; - case ISD::SREM: - case ISD::UREM: - Op = RISCV::VREM_VV; - break; case ISD::FADD: case ISD::FSUB: - // TODO: Address FP16 with VFHMIN - Op = RISCV::VFADD_VV; case ISD::FMUL: - // TODO: Address FP16 with VFHMIN - Op = RISCV::VFMUL_VV; - break; - case ISD::FDIV: - Op = RISCV::VFDIV_VV; - break; - case ISD::FNEG: - Op = RISCV::VFSGNJN_VV; - break; + case ISD::FNEG: { + return ConstantMatCost + TLI->getLMULCost(LT.second) * LT.first * 1; + } default: - // Assuming all other instructions have the same cost until a need arises to - // differentiate them. - return ConstantMatCost + BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, - Op1Info, Op2Info, - Args, CxtI); + return ConstantMatCost + + BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info, + Args, CxtI); } - return ConstantMatCost + - LT.first * getRISCVInstructionCost(Op, LT.second, CostKind); } // TODO: Deduplicate from TargetTransformInfoImplCRTPBase. diff --git a/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll b/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll index d1e8bb015491..1dde88f366a3 100644 --- a/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll +++ b/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll @@ -248,36 +248,36 @@ define i32 @fdiv() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %F16 = fdiv half undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %F32 = fdiv float undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %F64 = fdiv double undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1F16 = fdiv <1 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2F16 = fdiv <2 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4F16 = fdiv <4 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8F16 = fdiv <8 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16F16 = fdiv <16 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V1F16 = fdiv <1 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V2F16 = fdiv <2 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4F16 = fdiv <4 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8F16 = fdiv <8 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16F16 = fdiv <16 x half> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32F16 = fdiv <32 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4F16 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1F32 = fdiv <1 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2F32 = fdiv <2 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4F32 = fdiv <4 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8F32 = fdiv <8 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV16F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV32F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V1F32 = fdiv <1 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V2F32 = fdiv <2 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4F32 = fdiv <4 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8F32 = fdiv <8 x float> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16F32 = fdiv <16 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2F32 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1F64 = fdiv <1 x double> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2F64 = fdiv <2 x double> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4F64 = fdiv <4 x double> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV16F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V1F64 = fdiv <1 x double> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V2F64 = fdiv <2 x double> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4F64 = fdiv <4 x double> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8F64 = fdiv <8 x double> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1F64 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1F64 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2F64 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4F64 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8F64 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4F64 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8F64 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %F16 = fdiv half undef, undef diff --git a/llvm/test/Analysis/CostModel/RISCV/arith-int.ll b/llvm/test/Analysis/CostModel/RISCV/arith-int.ll index c976f483fdfe..b4afbb513166 100644 --- a/llvm/test/Analysis/CostModel/RISCV/arith-int.ll +++ b/llvm/test/Analysis/CostModel/RISCV/arith-int.ll @@ -705,72 +705,72 @@ define i32 @udiv() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = udiv i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = udiv i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = udiv i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = udiv <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = udiv <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = udiv <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = udiv <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = udiv <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = udiv <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = udiv <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = udiv <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = udiv <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = udiv <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = udiv <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = udiv <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = udiv <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = udiv <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = udiv <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = udiv <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = udiv <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = udiv <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = udiv <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = udiv <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = udiv <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = udiv <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = udiv <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = udiv <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = udiv <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = udiv <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = udiv <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'udiv' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = udiv i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = udiv i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = udiv i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = udiv <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = udiv <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = udiv <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = udiv <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = udiv <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = udiv <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = udiv <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = udiv <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = udiv <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = udiv <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = udiv <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = udiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = udiv <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = udiv <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = udiv <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = udiv <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = udiv <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = udiv <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = udiv <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = udiv <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = udiv <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = udiv <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = udiv <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = udiv <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = udiv <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = udiv <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = udiv <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = udiv <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = udiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = udiv i16 undef, undef @@ -821,72 +821,72 @@ define i32 @urem() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = urem i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = urem i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = urem i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = urem <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = urem <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = urem <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = urem <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = urem <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = urem <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = urem <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = urem <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = urem <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = urem <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = urem <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = urem <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = urem <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = urem <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = urem <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = urem <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = urem <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = urem <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = urem <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = urem <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = urem <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = urem <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = urem <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = urem <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = urem <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = urem <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = urem <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'urem' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = urem i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = urem i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = urem i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = urem <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = urem <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = urem <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = urem <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = urem <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = urem <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = urem <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = urem <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = urem <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = urem <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = urem <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = urem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = urem <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = urem <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = urem <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = urem <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = urem <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = urem <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = urem <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = urem <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = urem <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = urem <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = urem <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = urem <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = urem <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = urem <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = urem <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = urem <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = urem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = urem i16 undef, undef @@ -937,72 +937,72 @@ define i32 @sdiv() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = sdiv i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = sdiv i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = sdiv i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = sdiv <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = sdiv <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = sdiv <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = sdiv <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = sdiv <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = sdiv <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = sdiv <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = sdiv <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = sdiv <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = sdiv <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = sdiv <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = sdiv <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = sdiv <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = sdiv <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = sdiv <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = sdiv <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = sdiv <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = sdiv <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = sdiv <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = sdiv <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = sdiv <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = sdiv <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = sdiv <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = sdiv <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = sdiv <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = sdiv <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = sdiv <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'sdiv' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = sdiv i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = sdiv i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = sdiv i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = sdiv <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = sdiv <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = sdiv <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = sdiv <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = sdiv <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = sdiv <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = sdiv <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = sdiv <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = sdiv <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = sdiv <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = sdiv <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = sdiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = sdiv <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = sdiv <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = sdiv <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = sdiv <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = sdiv <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = sdiv <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = sdiv <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = sdiv <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = sdiv <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = sdiv <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = sdiv <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = sdiv <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = sdiv <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = sdiv <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = sdiv <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = sdiv <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = sdiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = sdiv i16 undef, undef @@ -1053,72 +1053,72 @@ define i32 @srem() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = srem i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = srem i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = srem i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = srem <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = srem <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = srem <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = srem <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = srem <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = srem <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = srem <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = srem <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = srem <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = srem <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = srem <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = srem <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = srem <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = srem <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = srem <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = srem <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = srem <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = srem <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = srem <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = srem <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = srem <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = srem <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = srem <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = srem <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = srem <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = srem <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = srem <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'srem' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = srem i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = srem i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = srem i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = srem <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = srem <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = srem <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = srem <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = srem <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = srem <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = srem <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = srem <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = srem <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = srem <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = srem <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = srem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = srem <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = srem <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = srem <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = srem <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = srem <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = srem <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = srem <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = srem <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = srem <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = srem <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = srem <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = srem <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = srem <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = srem <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = srem <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = srem <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = srem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = srem i16 undef, undef @@ -1232,471 +1232,3 @@ define void @add_of_constant() { ret void } - -define i32 @and() { -; CHECK-LABEL: 'and' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = and i1 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = and i16 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = and i32 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = and i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = and <1 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = and <2 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = and <4 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = and <8 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = and <16 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = and <32 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = and <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = and <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = and <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = and <8 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = and <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %16 = and <32 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = and <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = and <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = and <4 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %20 = and <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %21 = and <16 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = and <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = and <2 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = and <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = and <8 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %35 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %36 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %37 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %40 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %41 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %42 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %43 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %44 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %45 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %46 = and undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef -; -; SIFIVE-X280-LABEL: 'and' -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = and i1 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = and i16 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = and i32 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = and i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = and <1 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = and <2 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = and <4 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = and <8 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = and <16 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = and <32 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = and <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = and <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = and <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = and <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = and <16 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %16 = and <32 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = and <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = and <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = and <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = and <8 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = and <16 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = and <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = and <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = and <4 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %25 = and <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %34 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %35 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %36 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %37 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %39 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %40 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %41 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %42 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %43 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %44 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %45 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %46 = and undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef -; - and i1 undef, undef - and i16 undef, undef - and i32 undef, undef - and i64 undef, undef - - and <1 x i1> undef, undef - and <2 x i1> undef, undef - and <4 x i1> undef, undef - and <8 x i1> undef, undef - and <16 x i1> undef, undef - and <32 x i1> undef, undef - - and <1 x i16> undef, undef - and <2 x i16> undef, undef - and <4 x i16> undef, undef - and <8 x i16> undef, undef - and <16 x i16> undef, undef - and <32 x i16> undef, undef - - and <1 x i32> undef, undef - and <2 x i32> undef, undef - and <4 x i32> undef, undef - and <8 x i32> undef, undef - and <16 x i32> undef, undef - - and <1 x i64> undef, undef - and <2 x i64> undef, undef - and <4 x i64> undef, undef - and <8 x i64> undef, undef - - and undef, undef - and undef, undef - and undef, undef - and undef, undef - and undef, undef - and undef, undef - - and undef, undef - and undef, undef - and undef, undef - and undef, undef - and undef, undef - and undef, undef - - and undef, undef - and undef, undef - and undef, undef - and undef, undef - and undef, undef - - and undef, undef - and undef, undef - and undef, undef - and undef, undef - ret i32 undef -} - -define i32 @or() { -; CHECK-LABEL: 'or' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = or i1 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = or i16 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = or i32 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = or i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = or <1 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = or <2 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = or <4 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = or <8 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = or <16 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = or <32 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = or <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = or <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = or <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = or <8 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = or <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %16 = or <32 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = or <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = or <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = or <4 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %20 = or <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %21 = or <16 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = or <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = or <2 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = or <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = or <8 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %35 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %36 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %37 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %40 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %41 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %42 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %43 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %44 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %45 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %46 = or undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef -; -; SIFIVE-X280-LABEL: 'or' -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = or i1 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = or i16 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = or i32 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = or i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = or <1 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = or <2 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = or <4 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = or <8 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = or <16 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = or <32 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = or <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = or <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = or <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = or <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = or <16 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %16 = or <32 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = or <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = or <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = or <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = or <8 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = or <16 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = or <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = or <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = or <4 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %25 = or <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %34 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %35 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %36 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %37 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %39 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %40 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %41 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %42 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %43 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %44 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %45 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %46 = or undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef -; - or i1 undef, undef - or i16 undef, undef - or i32 undef, undef - or i64 undef, undef - - or <1 x i1> undef, undef - or <2 x i1> undef, undef - or <4 x i1> undef, undef - or <8 x i1> undef, undef - or <16 x i1> undef, undef - or <32 x i1> undef, undef - - or <1 x i16> undef, undef - or <2 x i16> undef, undef - or <4 x i16> undef, undef - or <8 x i16> undef, undef - or <16 x i16> undef, undef - or <32 x i16> undef, undef - - or <1 x i32> undef, undef - or <2 x i32> undef, undef - or <4 x i32> undef, undef - or <8 x i32> undef, undef - or <16 x i32> undef, undef - - or <1 x i64> undef, undef - or <2 x i64> undef, undef - or <4 x i64> undef, undef - or <8 x i64> undef, undef - - or undef, undef - or undef, undef - or undef, undef - or undef, undef - or undef, undef - or undef, undef - - or undef, undef - or undef, undef - or undef, undef - or undef, undef - or undef, undef - or undef, undef - - or undef, undef - or undef, undef - or undef, undef - or undef, undef - or undef, undef - - or undef, undef - or undef, undef - or undef, undef - or undef, undef - ret i32 undef -} - -define i32 @xor() { -; CHECK-LABEL: 'xor' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = xor i1 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = xor i16 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = xor i32 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = xor i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = xor <1 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = xor <2 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = xor <4 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = xor <8 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = xor <16 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = xor <32 x i1> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = xor <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = xor <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = xor <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = xor <8 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = xor <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %16 = xor <32 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = xor <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = xor <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = xor <4 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %20 = xor <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %21 = xor <16 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = xor <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = xor <2 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = xor <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = xor <8 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %35 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %36 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %37 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %40 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %41 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %42 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %43 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %44 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %45 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %46 = xor undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef -; -; SIFIVE-X280-LABEL: 'xor' -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = xor i1 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = xor i16 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = xor i32 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = xor i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = xor <1 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = xor <2 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = xor <4 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = xor <8 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = xor <16 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = xor <32 x i1> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = xor <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = xor <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = xor <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = xor <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = xor <16 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %16 = xor <32 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = xor <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = xor <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = xor <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = xor <8 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = xor <16 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = xor <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = xor <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = xor <4 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %25 = xor <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %34 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %35 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %36 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %37 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %39 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %40 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %41 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %42 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %43 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %44 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %45 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %46 = xor undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef -; - xor i1 undef, undef - xor i16 undef, undef - xor i32 undef, undef - xor i64 undef, undef - - xor <1 x i1> undef, undef - xor <2 x i1> undef, undef - xor <4 x i1> undef, undef - xor <8 x i1> undef, undef - xor <16 x i1> undef, undef - xor <32 x i1> undef, undef - - xor <1 x i16> undef, undef - xor <2 x i16> undef, undef - xor <4 x i16> undef, undef - xor <8 x i16> undef, undef - xor <16 x i16> undef, undef - xor <32 x i16> undef, undef - - xor <1 x i32> undef, undef - xor <2 x i32> undef, undef - xor <4 x i32> undef, undef - xor <8 x i32> undef, undef - xor <16 x i32> undef, undef - - xor <1 x i64> undef, undef - xor <2 x i64> undef, undef - xor <4 x i64> undef, undef - xor <8 x i64> undef, undef - - xor undef, undef - xor undef, undef - xor undef, undef - xor undef, undef - xor undef, undef - xor undef, undef - - xor undef, undef - xor undef, undef - xor undef, undef - xor undef, undef - xor undef, undef - xor undef, undef - - xor undef, undef - xor undef, undef - xor undef, undef - xor undef, undef - xor undef, undef - - xor undef, undef - xor undef, undef - xor undef, undef - xor undef, undef - ret i32 undef -} -- GitLab From 22213d58832e8fce344a7222ed705e4c7f4eb6b1 Mon Sep 17 00:00:00 2001 From: Shih-Po Hung Date: Mon, 13 May 2024 09:47:57 +0800 Subject: [PATCH 008/578] Recommit [RISCV][TTI] Support fdiv/udiv/sdiv/srem/urem in getArithmeticInstrCost (#89170) Insert a break to fix the implicit-fallthrough caught by sanitizer. Original commit message: This patch made following changes: 1. Support ISD FDIV/UDIV/SDIV/UREM/SREM 2. Classify instructions which cost the same --- .../Target/RISCV/RISCVTargetTransformInfo.cpp | 48 +- .../test/Analysis/CostModel/RISCV/arith-fp.ll | 48 +- .../Analysis/CostModel/RISCV/arith-int.ll | 828 ++++++++++++++---- 3 files changed, 711 insertions(+), 213 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index 5f84175da703..d94dff5f2b1f 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -1619,29 +1619,59 @@ InstructionCost RISCVTTIImpl::getArithmeticInstrCost( if (Op2Info.isConstant()) ConstantMatCost += getConstantMatCost(1, Op2Info); + unsigned Op; switch (TLI->InstructionOpcodeToISD(Opcode)) { case ISD::ADD: case ISD::SUB: - case ISD::AND: - case ISD::OR: - case ISD::XOR: + Op = RISCV::VADD_VV; + break; case ISD::SHL: case ISD::SRL: case ISD::SRA: + Op = RISCV::VSLL_VV; + break; + case ISD::AND: + case ISD::OR: + case ISD::XOR: + Op = (Ty->getScalarSizeInBits() == 1) ? RISCV::VMAND_MM : RISCV::VAND_VV; + break; case ISD::MUL: case ISD::MULHS: case ISD::MULHU: + Op = RISCV::VMUL_VV; + break; + case ISD::SDIV: + case ISD::UDIV: + Op = RISCV::VDIV_VV; + break; + case ISD::SREM: + case ISD::UREM: + Op = RISCV::VREM_VV; + break; case ISD::FADD: case ISD::FSUB: + // TODO: Address FP16 with VFHMIN + Op = RISCV::VFADD_VV; + break; case ISD::FMUL: - case ISD::FNEG: { - return ConstantMatCost + TLI->getLMULCost(LT.second) * LT.first * 1; - } + // TODO: Address FP16 with VFHMIN + Op = RISCV::VFMUL_VV; + break; + case ISD::FDIV: + Op = RISCV::VFDIV_VV; + break; + case ISD::FNEG: + Op = RISCV::VFSGNJN_VV; + break; default: - return ConstantMatCost + - BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info, - Args, CxtI); + // Assuming all other instructions have the same cost until a need arises to + // differentiate them. + return ConstantMatCost + BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, + Op1Info, Op2Info, + Args, CxtI); } + return ConstantMatCost + + LT.first * getRISCVInstructionCost(Op, LT.second, CostKind); } // TODO: Deduplicate from TargetTransformInfoImplCRTPBase. diff --git a/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll b/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll index 1dde88f366a3..d1e8bb015491 100644 --- a/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll +++ b/llvm/test/Analysis/CostModel/RISCV/arith-fp.ll @@ -248,36 +248,36 @@ define i32 @fdiv() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %F16 = fdiv half undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %F32 = fdiv float undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %F64 = fdiv double undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V1F16 = fdiv <1 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V2F16 = fdiv <2 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4F16 = fdiv <4 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8F16 = fdiv <8 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16F16 = fdiv <16 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1F16 = fdiv <1 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2F16 = fdiv <2 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4F16 = fdiv <4 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8F16 = fdiv <8 x half> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16F16 = fdiv <16 x half> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32F16 = fdiv <32 x half> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4F16 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV16F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV32F16 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V1F32 = fdiv <1 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V2F32 = fdiv <2 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4F32 = fdiv <4 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8F32 = fdiv <8 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32F16 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1F32 = fdiv <1 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2F32 = fdiv <2 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4F32 = fdiv <4 x float> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8F32 = fdiv <8 x float> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16F32 = fdiv <16 x float> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2F32 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV16F32 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V1F64 = fdiv <1 x double> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V2F64 = fdiv <2 x double> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4F64 = fdiv <4 x double> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16F32 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1F64 = fdiv <1 x double> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2F64 = fdiv <2 x double> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4F64 = fdiv <4 x double> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8F64 = fdiv <8 x double> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1F64 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1F64 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2F64 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4F64 = fdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8F64 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4F64 = fdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8F64 = fdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %F16 = fdiv half undef, undef diff --git a/llvm/test/Analysis/CostModel/RISCV/arith-int.ll b/llvm/test/Analysis/CostModel/RISCV/arith-int.ll index b4afbb513166..c976f483fdfe 100644 --- a/llvm/test/Analysis/CostModel/RISCV/arith-int.ll +++ b/llvm/test/Analysis/CostModel/RISCV/arith-int.ll @@ -705,72 +705,72 @@ define i32 @udiv() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = udiv i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = udiv i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = udiv i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = udiv <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = udiv <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = udiv <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = udiv <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = udiv <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = udiv <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = udiv <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = udiv <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = udiv <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = udiv <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = udiv <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = udiv <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = udiv <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = udiv <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = udiv <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = udiv <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = udiv <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = udiv <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = udiv <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = udiv <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = udiv <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = udiv <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = udiv <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = udiv <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = udiv <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = udiv <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = udiv <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = udiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = udiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = udiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'udiv' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = udiv i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = udiv i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = udiv i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = udiv <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = udiv <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = udiv <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = udiv <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = udiv <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = udiv <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = udiv <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = udiv <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = udiv <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = udiv <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = udiv <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = udiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = udiv <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = udiv <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = udiv <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = udiv <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = udiv <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = udiv <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = udiv <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = udiv <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = udiv <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = udiv <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = udiv <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = udiv <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = udiv <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = udiv <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = udiv <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = udiv <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = udiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = udiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = udiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = udiv i16 undef, undef @@ -821,72 +821,72 @@ define i32 @urem() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = urem i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = urem i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = urem i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = urem <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = urem <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = urem <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = urem <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = urem <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = urem <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = urem <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = urem <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = urem <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = urem <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = urem <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = urem <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = urem <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = urem <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = urem <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = urem <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = urem <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = urem <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = urem <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = urem <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = urem <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = urem <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = urem <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = urem <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = urem <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = urem <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = urem <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = urem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = urem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = urem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'urem' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = urem i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = urem i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = urem i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = urem <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = urem <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = urem <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = urem <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = urem <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = urem <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = urem <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = urem <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = urem <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = urem <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = urem <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = urem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = urem <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = urem <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = urem <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = urem <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = urem <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = urem <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = urem <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = urem <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = urem <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = urem <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = urem <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = urem <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = urem <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = urem <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = urem <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = urem <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = urem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = urem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = urem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = urem i16 undef, undef @@ -937,72 +937,72 @@ define i32 @sdiv() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = sdiv i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = sdiv i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = sdiv i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = sdiv <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = sdiv <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = sdiv <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = sdiv <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = sdiv <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = sdiv <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = sdiv <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = sdiv <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = sdiv <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = sdiv <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = sdiv <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = sdiv <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = sdiv <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = sdiv <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = sdiv <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = sdiv <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = sdiv <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = sdiv <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = sdiv <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = sdiv <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = sdiv <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = sdiv <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = sdiv <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = sdiv <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = sdiv <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = sdiv <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = sdiv <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = sdiv undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = sdiv undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = sdiv undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'sdiv' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = sdiv i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = sdiv i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = sdiv i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = sdiv <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = sdiv <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = sdiv <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = sdiv <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = sdiv <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = sdiv <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = sdiv <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = sdiv <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = sdiv <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = sdiv <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = sdiv <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = sdiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = sdiv <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = sdiv <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = sdiv <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = sdiv <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = sdiv <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = sdiv <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = sdiv <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = sdiv <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = sdiv <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = sdiv <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = sdiv <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = sdiv <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = sdiv <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = sdiv <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = sdiv <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = sdiv <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = sdiv undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = sdiv undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = sdiv undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = sdiv i16 undef, undef @@ -1053,72 +1053,72 @@ define i32 @srem() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = srem i16 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = srem i32 undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = srem i64 undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = srem <1 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = srem <2 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = srem <4 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = srem <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = srem <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = srem <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = srem <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = srem <8 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = srem <16 x i16> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = srem <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V32I16 = srem <32 x i16> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = srem <1 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = srem <2 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = srem <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV8I16 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV16I16 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV32I16 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = srem <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = srem <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = srem <4 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = srem <8 x i32> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = srem <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V16I32 = srem <16 x i32> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = srem <1 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = srem <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I32 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I32 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I32 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = srem <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = srem <2 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = srem <4 x i64> undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = srem <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V8I64 = srem <8 x i64> undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = srem undef, undef -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I64 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I64 = srem undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I64 = srem undef, undef ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIFIVE-X280-LABEL: 'srem' ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I16 = srem i16 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I32 = srem i32 undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %I64 = srem i64 undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I16 = srem <1 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I16 = srem <2 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I16 = srem <4 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I16 = srem <8 x i16> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I16 = srem <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I16 = srem <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I16 = srem <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I16 = srem <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I16 = srem <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V16I16 = srem <16 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32I16 = srem <32 x i16> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I16 = srem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV32I16 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I32 = srem <1 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I32 = srem <2 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I32 = srem <4 x i32> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I32 = srem <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV4I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV8I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV16I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV32I16 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I32 = srem <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I32 = srem <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I32 = srem <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V8I32 = srem <8 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16I32 = srem <16 x i32> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV16I32 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1I64 = srem <1 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2I64 = srem <2 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4I64 = srem <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV2I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV4I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV8I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV16I32 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V1I64 = srem <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V2I64 = srem <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %V4I64 = srem <4 x i64> undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8I64 = srem <8 x i64> undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV1I64 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV2I64 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV4I64 = srem undef, undef -; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %NXV8I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %NXV1I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %NXV2I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %NXV4I64 = srem undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %NXV8I64 = srem undef, undef ; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; %I16 = srem i16 undef, undef @@ -1232,3 +1232,471 @@ define void @add_of_constant() { ret void } + +define i32 @and() { +; CHECK-LABEL: 'and' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = and i1 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = and i16 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = and i32 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = and i64 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = and <1 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = and <2 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = and <4 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = and <8 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = and <16 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = and <32 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = and <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = and <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = and <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = and <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = and <16 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %16 = and <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = and <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = and <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = and <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %20 = and <8 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %21 = and <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = and <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = and <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = and <4 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = and <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %35 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %36 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %37 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %40 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %41 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %42 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %43 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %44 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %45 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %46 = and undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; +; SIFIVE-X280-LABEL: 'and' +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = and i1 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = and i16 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = and i32 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = and i64 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = and <1 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = and <2 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = and <4 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = and <8 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = and <16 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = and <32 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = and <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = and <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = and <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = and <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = and <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %16 = and <32 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = and <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = and <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = and <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = and <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = and <16 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = and <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = and <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = and <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %25 = and <8 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %34 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %35 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %36 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %37 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %39 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %40 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %41 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %42 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %43 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %44 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %45 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %46 = and undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; + and i1 undef, undef + and i16 undef, undef + and i32 undef, undef + and i64 undef, undef + + and <1 x i1> undef, undef + and <2 x i1> undef, undef + and <4 x i1> undef, undef + and <8 x i1> undef, undef + and <16 x i1> undef, undef + and <32 x i1> undef, undef + + and <1 x i16> undef, undef + and <2 x i16> undef, undef + and <4 x i16> undef, undef + and <8 x i16> undef, undef + and <16 x i16> undef, undef + and <32 x i16> undef, undef + + and <1 x i32> undef, undef + and <2 x i32> undef, undef + and <4 x i32> undef, undef + and <8 x i32> undef, undef + and <16 x i32> undef, undef + + and <1 x i64> undef, undef + and <2 x i64> undef, undef + and <4 x i64> undef, undef + and <8 x i64> undef, undef + + and undef, undef + and undef, undef + and undef, undef + and undef, undef + and undef, undef + and undef, undef + + and undef, undef + and undef, undef + and undef, undef + and undef, undef + and undef, undef + and undef, undef + + and undef, undef + and undef, undef + and undef, undef + and undef, undef + and undef, undef + + and undef, undef + and undef, undef + and undef, undef + and undef, undef + ret i32 undef +} + +define i32 @or() { +; CHECK-LABEL: 'or' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = or i1 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = or i16 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = or i32 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = or i64 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = or <1 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = or <2 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = or <4 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = or <8 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = or <16 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = or <32 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = or <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = or <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = or <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = or <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = or <16 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %16 = or <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = or <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = or <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = or <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %20 = or <8 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %21 = or <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = or <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = or <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = or <4 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = or <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %35 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %36 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %37 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %40 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %41 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %42 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %43 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %44 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %45 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %46 = or undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; +; SIFIVE-X280-LABEL: 'or' +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = or i1 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = or i16 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = or i32 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = or i64 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = or <1 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = or <2 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = or <4 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = or <8 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = or <16 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = or <32 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = or <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = or <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = or <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = or <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = or <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %16 = or <32 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = or <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = or <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = or <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = or <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = or <16 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = or <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = or <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = or <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %25 = or <8 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %34 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %35 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %36 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %37 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %39 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %40 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %41 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %42 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %43 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %44 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %45 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %46 = or undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; + or i1 undef, undef + or i16 undef, undef + or i32 undef, undef + or i64 undef, undef + + or <1 x i1> undef, undef + or <2 x i1> undef, undef + or <4 x i1> undef, undef + or <8 x i1> undef, undef + or <16 x i1> undef, undef + or <32 x i1> undef, undef + + or <1 x i16> undef, undef + or <2 x i16> undef, undef + or <4 x i16> undef, undef + or <8 x i16> undef, undef + or <16 x i16> undef, undef + or <32 x i16> undef, undef + + or <1 x i32> undef, undef + or <2 x i32> undef, undef + or <4 x i32> undef, undef + or <8 x i32> undef, undef + or <16 x i32> undef, undef + + or <1 x i64> undef, undef + or <2 x i64> undef, undef + or <4 x i64> undef, undef + or <8 x i64> undef, undef + + or undef, undef + or undef, undef + or undef, undef + or undef, undef + or undef, undef + or undef, undef + + or undef, undef + or undef, undef + or undef, undef + or undef, undef + or undef, undef + or undef, undef + + or undef, undef + or undef, undef + or undef, undef + or undef, undef + or undef, undef + + or undef, undef + or undef, undef + or undef, undef + or undef, undef + ret i32 undef +} + +define i32 @xor() { +; CHECK-LABEL: 'xor' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = xor i1 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = xor i16 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = xor i32 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = xor i64 undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = xor <1 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = xor <2 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = xor <4 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = xor <8 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = xor <16 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = xor <32 x i1> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = xor <1 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = xor <2 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = xor <4 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = xor <8 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = xor <16 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %16 = xor <32 x i16> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = xor <1 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = xor <2 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = xor <4 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %20 = xor <8 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %21 = xor <16 x i32> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = xor <1 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = xor <2 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = xor <4 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = xor <8 x i64> undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %35 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %36 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %37 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %40 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %41 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %42 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %43 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %44 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %45 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %46 = xor undef, undef +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; +; SIFIVE-X280-LABEL: 'xor' +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = xor i1 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = xor i16 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = xor i32 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = xor i64 undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = xor <1 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = xor <2 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = xor <4 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = xor <8 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = xor <16 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = xor <32 x i1> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %11 = xor <1 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = xor <2 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = xor <4 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = xor <8 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = xor <16 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %16 = xor <32 x i16> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = xor <1 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = xor <2 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = xor <4 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = xor <8 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = xor <16 x i32> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = xor <1 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = xor <2 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = xor <4 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %25 = xor <8 x i64> undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %31 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %34 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %35 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %36 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %37 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %39 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %40 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %41 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %42 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %43 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %44 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %45 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %46 = xor undef, undef +; SIFIVE-X280-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef +; + xor i1 undef, undef + xor i16 undef, undef + xor i32 undef, undef + xor i64 undef, undef + + xor <1 x i1> undef, undef + xor <2 x i1> undef, undef + xor <4 x i1> undef, undef + xor <8 x i1> undef, undef + xor <16 x i1> undef, undef + xor <32 x i1> undef, undef + + xor <1 x i16> undef, undef + xor <2 x i16> undef, undef + xor <4 x i16> undef, undef + xor <8 x i16> undef, undef + xor <16 x i16> undef, undef + xor <32 x i16> undef, undef + + xor <1 x i32> undef, undef + xor <2 x i32> undef, undef + xor <4 x i32> undef, undef + xor <8 x i32> undef, undef + xor <16 x i32> undef, undef + + xor <1 x i64> undef, undef + xor <2 x i64> undef, undef + xor <4 x i64> undef, undef + xor <8 x i64> undef, undef + + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + + xor undef, undef + xor undef, undef + xor undef, undef + xor undef, undef + ret i32 undef +} -- GitLab From b1f04d57f5818914d7db506985e2932f217844bd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 12 May 2024 21:15:36 -0700 Subject: [PATCH 009/578] [ELF,test] Fix typo in check prefixes --- lld/test/ELF/aarch64-thunk-reuse2.s | 2 +- lld/test/ELF/linkerscript/orphan-phdrs2.test | 2 +- lld/test/ELF/mips-got-page-script.s | 52 ++++++++++---------- lld/test/ELF/ttext-tdata-tbss.s | 12 ++--- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/lld/test/ELF/aarch64-thunk-reuse2.s b/lld/test/ELF/aarch64-thunk-reuse2.s index e9dd385605ad..c2cfee6f876c 100644 --- a/lld/test/ELF/aarch64-thunk-reuse2.s +++ b/lld/test/ELF/aarch64-thunk-reuse2.s @@ -14,7 +14,7 @@ # CHECK: <__AArch64ADRPThunk_>: # CHECK-NEXT: 8010708: adrp x16, 0x10000 # CHECK-NEXT: add x16, x16, #1792 -# CHECk-NEXT: br x16 +# CHECK-NEXT: br x16 # CHECK-LABEL: : # CHECK-NEXT: 8010714: bl 0x8010708 <__AArch64ADRPThunk_> # CHECK-NEXT: b 0x8010708 <__AArch64ADRPThunk_> diff --git a/lld/test/ELF/linkerscript/orphan-phdrs2.test b/lld/test/ELF/linkerscript/orphan-phdrs2.test index c302e0e70b2b..d75c76da87e8 100644 --- a/lld/test/ELF/linkerscript/orphan-phdrs2.test +++ b/lld/test/ELF/linkerscript/orphan-phdrs2.test @@ -12,7 +12,7 @@ # CHECK-NEXT: Type {{.*}} Flg Align # CHECK-NEXT: LOAD {{.*}} R E 0x # CHECK-NEXT: LOAD {{.*}} RW 0x -# CHECK-MEXT: LOAD {{.*}} R 0x +# CHECK-NEXT: LOAD {{.*}} R 0x # CHECK: Segment Sections... # CHECK-NEXT: 00 .text {{$}} diff --git a/lld/test/ELF/mips-got-page-script.s b/lld/test/ELF/mips-got-page-script.s index 4055fb6dabef..3caf5cc03afc 100644 --- a/lld/test/ELF/mips-got-page-script.s +++ b/lld/test/ELF/mips-got-page-script.s @@ -19,32 +19,32 @@ # CHECK-NEXT: Value: 0x40000 # CHECK: Local entries [ -# CHECK-BEXT: Entry { -# CHECK-BEXT: Address: -# CHECK-BEXT: Access: -# CHECK-BEXT: Initial: 0x10000 -# CHECK-BEXT: } -# CHECK-BEXT: Entry { -# CHECK-BEXT: Address: -# CHECK-BEXT: Access: -# CHECK-BEXT: Initial: 0x20000 -# CHECK-BEXT: } -# CHECK-BEXT: Entry { -# CHECK-BEXT: Address: -# CHECK-BEXT: Access: -# CHECK-BEXT: Initial: 0x30000 -# CHECK-BEXT: } -# CHECK-BEXT: Entry { -# CHECK-BEXT: Address: -# CHECK-BEXT: Access: -# CHECK-BEXT: Initial: 0x40000 -# CHECK-BEXT: } -# CHECK-BEXT: Entry { -# CHECK-BEXT: Address: -# CHECK-BEXT: Access: -# CHECK-BEXT: Initial: 0x50000 -# CHECK-BEXT: } -# CHECK-BEXT: ] +# CHECK-NEXT: Entry { +# CHECK-NEXT: Address: +# CHECK-NEXT: Access: +# CHECK-NEXT: Initial: 0x10000 +# CHECK-NEXT: } +# CHECK-NEXT: Entry { +# CHECK-NEXT: Address: +# CHECK-NEXT: Access: +# CHECK-NEXT: Initial: 0x20000 +# CHECK-NEXT: } +# CHECK-NEXT: Entry { +# CHECK-NEXT: Address: +# CHECK-NEXT: Access: +# CHECK-NEXT: Initial: 0x30000 +# CHECK-NEXT: } +# CHECK-NEXT: Entry { +# CHECK-NEXT: Address: +# CHECK-NEXT: Access: +# CHECK-NEXT: Initial: 0x40000 +# CHECK-NEXT: } +# CHECK-NEXT: Entry { +# CHECK-NEXT: Address: +# CHECK-NEXT: Access: +# CHECK-NEXT: Initial: 0x50000 +# CHECK-NEXT: } +# CHECK-NEXT: ] .option pic2 .text diff --git a/lld/test/ELF/ttext-tdata-tbss.s b/lld/test/ELF/ttext-tdata-tbss.s index fb9c4d513174..c8254d696929 100644 --- a/lld/test/ELF/ttext-tdata-tbss.s +++ b/lld/test/ELF/ttext-tdata-tbss.s @@ -42,13 +42,13 @@ # USER2-NEXT: LOAD 0x001000 0x0000000000001000 ## With .text well above 200000 we don't need to change the image base -# RUN: ld.lld -Ttext 0x201000 %t.o -o %t4 +# RUN: ld.lld -Ttext 0x201000 -z separate-loadable-segments %t.o -o %t4 # RUN: llvm-readelf -S -l %t4 | FileCheck %s --check-prefix=USER3 -# USER3: .text PROGBITS 0000000000201000 001000 000001 -# USER3-NEX: .rodata PROGBITS 0000000000202000 002000 000008 -# USER3-NEX: .aw PROGBITS 0000000000203000 003000 000008 -# USER3-NEX: .data PROGBITS 0000000000203008 003008 000008 -# USER3-NEX: .bss NOBITS 0000000000203010 003010 000008 +# USER3: .text PROGBITS 0000000000201000 001000 000001 +# USER3-NEXT: .rodata PROGBITS 0000000000202000 002000 000008 +# USER3-NEXT: .aw PROGBITS 0000000000203000 003000 000008 +# USER3-NEXT: .data PROGBITS 0000000000203008 003008 000008 +# USER3-NEXT: .bss NOBITS 0000000000203010 003010 000008 # USER3: Type # USER3-NEXT: PHDR 0x000040 0x0000000000200040 # USER3-NEXT: LOAD 0x000000 0x0000000000200000 -- GitLab From cb4fca929bd10a5c160a0f9bd58f2d7499669a89 Mon Sep 17 00:00:00 2001 From: Vikram Hegde <115221833+vikramRH@users.noreply.github.com> Date: Mon, 13 May 2024 10:20:37 +0530 Subject: [PATCH 010/578] [AMDGPU] Extend llvm.amdgcn.update.dpp intrinsic to support f64 (#91190) Follow up patch to https://github.com/llvm/llvm-project/pull/89217, before we make changes to atomic optimizer. --- llvm/lib/Target/AMDGPU/SIInstructions.td | 4 +- llvm/lib/Target/AMDGPU/SIRegisterInfo.td | 1 + llvm/lib/Target/AMDGPU/VOP1Instructions.td | 9 +- .../GlobalISel/llvm.amdgcn.update.dpp.ll | 337 +++++++++++++++++- .../CodeGen/AMDGPU/llvm.amdgcn.update.dpp.ll | 123 ++++++- 5 files changed, 457 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/SIInstructions.td b/llvm/lib/Target/AMDGPU/SIInstructions.td index f9a660e334a0..f9e811f54d05 100644 --- a/llvm/lib/Target/AMDGPU/SIInstructions.td +++ b/llvm/lib/Target/AMDGPU/SIInstructions.td @@ -3325,13 +3325,15 @@ def : GCNPat < (as_i1timm $bound_ctrl)) >; +foreach vt = Reg64Types.types in { def : GCNPat < - (i64 (int_amdgcn_update_dpp i64:$old, i64:$src, timm:$dpp_ctrl, timm:$row_mask, + (vt (int_amdgcn_update_dpp vt:$old, vt:$src, timm:$dpp_ctrl, timm:$row_mask, timm:$bank_mask, timm:$bound_ctrl)), (V_MOV_B64_DPP_PSEUDO VReg_64_Align2:$old, VReg_64_Align2:$src, (as_i32timm $dpp_ctrl), (as_i32timm $row_mask), (as_i32timm $bank_mask), (as_i1timm $bound_ctrl)) >; +} //===----------------------------------------------------------------------===// // Fract Patterns diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.td b/llvm/lib/Target/AMDGPU/SIRegisterInfo.td index 01ed565bb756..caac7126068e 100644 --- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.td +++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.td @@ -586,6 +586,7 @@ class RegisterTypes reg_types> { def Reg16Types : RegisterTypes<[i16, f16, bf16]>; def Reg32Types : RegisterTypes<[i32, f32, v2i16, v2f16, v2bf16, p2, p3, p5, p6]>; +def Reg64Types : RegisterTypes<[i64, f64, v2i32, v2f32, p0]>; let HasVGPR = 1 in { // VOP3 and VINTERP can access 256 lo and 256 hi registers. diff --git a/llvm/lib/Target/AMDGPU/VOP1Instructions.td b/llvm/lib/Target/AMDGPU/VOP1Instructions.td index 012dca22eb4f..4a56fad0cd60 100644 --- a/llvm/lib/Target/AMDGPU/VOP1Instructions.td +++ b/llvm/lib/Target/AMDGPU/VOP1Instructions.td @@ -1341,7 +1341,8 @@ def : GCNPat < (as_i1timm $bound_ctrl)) >; -class UpdateDPPPat : GCNPat < +foreach vt = Reg32Types.types in { +def : GCNPat < (vt (int_amdgcn_update_dpp vt:$old, vt:$src, timm:$dpp_ctrl, timm:$row_mask, timm:$bank_mask, timm:$bound_ctrl)), @@ -1349,11 +1350,7 @@ class UpdateDPPPat : GCNPat < (as_i32timm $row_mask), (as_i32timm $bank_mask), (as_i1timm $bound_ctrl)) >; - -def : UpdateDPPPat; -def : UpdateDPPPat; -def : UpdateDPPPat; -def : UpdateDPPPat; +} } // End OtherPredicates = [isGFX8Plus] diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.update.dpp.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.update.dpp.ll index f7adfe47b64f..727184a36c00 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.update.dpp.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.update.dpp.ll @@ -43,8 +43,8 @@ define amdgpu_kernel void @dpp_test(ptr addrspace(1) %out, i32 %in1, i32 %in2) { store i32 %tmp0, ptr addrspace(1) %out ret void } -define amdgpu_kernel void @update_dpp64_test(ptr addrspace(1) %arg, i64 %in1, i64 %in2) { -; GFX8-LABEL: update_dpp64_test: +define amdgpu_kernel void @update_dppi64_test(ptr addrspace(1) %arg, i64 %in1, i64 %in2) { +; GFX8-LABEL: update_dppi64_test: ; GFX8: ; %bb.0: ; GFX8-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 ; GFX8-NEXT: v_lshlrev_b32_e32 v2, 3, v0 @@ -62,7 +62,7 @@ define amdgpu_kernel void @update_dpp64_test(ptr addrspace(1) %arg, i64 %in1, i6 ; GFX8-NEXT: flat_store_dwordx2 v[0:1], v[4:5] ; GFX8-NEXT: s_endpgm ; -; GFX10-LABEL: update_dpp64_test: +; GFX10-LABEL: update_dppi64_test: ; GFX10: ; %bb.0: ; GFX10-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 ; GFX10-NEXT: v_lshlrev_b32_e32 v4, 3, v0 @@ -76,7 +76,7 @@ define amdgpu_kernel void @update_dpp64_test(ptr addrspace(1) %arg, i64 %in1, i6 ; GFX10-NEXT: global_store_dwordx2 v4, v[2:3], s[0:1] ; GFX10-NEXT: s_endpgm ; -; GFX11-LABEL: update_dpp64_test: +; GFX11-LABEL: update_dppi64_test: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 ; GFX11-NEXT: v_lshlrev_b32_e32 v4, 3, v0 @@ -98,6 +98,335 @@ define amdgpu_kernel void @update_dpp64_test(ptr addrspace(1) %arg, i64 %in1, i6 ret void } +define amdgpu_kernel void @update_dppf64_test(ptr addrspace(1) %arg, double %in1, double %in2) { +; GFX8-LABEL: update_dppf64_test: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX8-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_mov_b32_e32 v0, s0 +; GFX8-NEXT: v_mov_b32_e32 v1, s1 +; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 +; GFX8-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GFX8-NEXT: flat_load_dwordx2 v[2:3], v[0:1] +; GFX8-NEXT: v_mov_b32_e32 v5, s3 +; GFX8-NEXT: v_mov_b32_e32 v4, s2 +; GFX8-NEXT: s_waitcnt vmcnt(0) +; GFX8-NEXT: v_mov_b32_dpp v5, v3 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX8-NEXT: v_mov_b32_dpp v4, v2 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX8-NEXT: flat_store_dwordx2 v[0:1], v[4:5] +; GFX8-NEXT: s_endpgm +; +; GFX10-LABEL: update_dppf64_test: +; GFX10: ; %bb.0: +; GFX10-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX10-NEXT: v_lshlrev_b32_e32 v4, 3, v0 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: global_load_dwordx2 v[0:1], v4, s[0:1] +; GFX10-NEXT: v_mov_b32_e32 v2, s2 +; GFX10-NEXT: v_mov_b32_e32 v3, s3 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_dpp v2, v0 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX10-NEXT: v_mov_b32_dpp v3, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX10-NEXT: global_store_dwordx2 v4, v[2:3], s[0:1] +; GFX10-NEXT: s_endpgm +; +; GFX11-LABEL: update_dppf64_test: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 +; GFX11-NEXT: v_lshlrev_b32_e32 v4, 3, v0 +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: v_dual_mov_b32 v2, s2 :: v_dual_mov_b32 v3, s3 +; GFX11-NEXT: global_load_b64 v[0:1], v4, s[0:1] +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_dpp v2, v0 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX11-NEXT: v_mov_b32_dpp v3, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX11-NEXT: global_store_b64 v4, v[2:3], s[0:1] +; GFX11-NEXT: s_nop 0 +; GFX11-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) +; GFX11-NEXT: s_endpgm + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds double, ptr addrspace(1) %arg, i32 %id + %load = load double, ptr addrspace(1) %gep + %tmp0 = call double @llvm.amdgcn.update.dpp.f64(double %in1, double %load, i32 1, i32 1, i32 1, i1 false) #1 + store double %tmp0, ptr addrspace(1) %gep + ret void +} + +define amdgpu_kernel void @update_dppv2i32_test(ptr addrspace(1) %arg, <2 x i32> %in1, <2 x i32> %in2) { +; GFX8-LABEL: update_dppv2i32_test: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX8-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_mov_b32_e32 v0, s0 +; GFX8-NEXT: v_mov_b32_e32 v1, s1 +; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 +; GFX8-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GFX8-NEXT: flat_load_dwordx2 v[2:3], v[0:1] +; GFX8-NEXT: v_mov_b32_e32 v5, s3 +; GFX8-NEXT: v_mov_b32_e32 v4, s2 +; GFX8-NEXT: s_waitcnt vmcnt(0) +; GFX8-NEXT: v_mov_b32_dpp v5, v3 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX8-NEXT: v_mov_b32_dpp v4, v2 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX8-NEXT: flat_store_dwordx2 v[0:1], v[4:5] +; GFX8-NEXT: s_endpgm +; +; GFX10-LABEL: update_dppv2i32_test: +; GFX10: ; %bb.0: +; GFX10-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX10-NEXT: v_lshlrev_b32_e32 v4, 3, v0 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: global_load_dwordx2 v[0:1], v4, s[0:1] +; GFX10-NEXT: v_mov_b32_e32 v2, s2 +; GFX10-NEXT: v_mov_b32_e32 v3, s3 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_dpp v2, v0 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX10-NEXT: v_mov_b32_dpp v3, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX10-NEXT: global_store_dwordx2 v4, v[2:3], s[0:1] +; GFX10-NEXT: s_endpgm +; +; GFX11-LABEL: update_dppv2i32_test: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 +; GFX11-NEXT: v_lshlrev_b32_e32 v4, 3, v0 +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: v_dual_mov_b32 v2, s2 :: v_dual_mov_b32 v3, s3 +; GFX11-NEXT: global_load_b64 v[0:1], v4, s[0:1] +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_dpp v2, v0 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX11-NEXT: v_mov_b32_dpp v3, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX11-NEXT: global_store_b64 v4, v[2:3], s[0:1] +; GFX11-NEXT: s_nop 0 +; GFX11-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) +; GFX11-NEXT: s_endpgm + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds <2 x i32>, ptr addrspace(1) %arg, i32 %id + %load = load <2 x i32>, ptr addrspace(1) %gep + %tmp0 = call <2 x i32> @llvm.amdgcn.update.dpp.v2i32(<2 x i32> %in1, <2 x i32> %load, i32 1, i32 1, i32 1, i1 false) #1 + store <2 x i32> %tmp0, ptr addrspace(1) %gep + ret void +} + +define amdgpu_kernel void @update_dppv2f32_test(ptr addrspace(1) %arg, <2 x float> %in1, <2 x float> %in2) { +; GFX8-LABEL: update_dppv2f32_test: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX8-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_mov_b32_e32 v0, s0 +; GFX8-NEXT: v_mov_b32_e32 v1, s1 +; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 +; GFX8-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GFX8-NEXT: flat_load_dwordx2 v[2:3], v[0:1] +; GFX8-NEXT: v_mov_b32_e32 v5, s3 +; GFX8-NEXT: v_mov_b32_e32 v4, s2 +; GFX8-NEXT: s_waitcnt vmcnt(0) +; GFX8-NEXT: v_mov_b32_dpp v5, v3 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX8-NEXT: v_mov_b32_dpp v4, v2 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX8-NEXT: flat_store_dwordx2 v[0:1], v[4:5] +; GFX8-NEXT: s_endpgm +; +; GFX10-LABEL: update_dppv2f32_test: +; GFX10: ; %bb.0: +; GFX10-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX10-NEXT: v_lshlrev_b32_e32 v4, 3, v0 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: global_load_dwordx2 v[0:1], v4, s[0:1] +; GFX10-NEXT: v_mov_b32_e32 v2, s2 +; GFX10-NEXT: v_mov_b32_e32 v3, s3 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_dpp v2, v0 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX10-NEXT: v_mov_b32_dpp v3, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX10-NEXT: global_store_dwordx2 v4, v[2:3], s[0:1] +; GFX10-NEXT: s_endpgm +; +; GFX11-LABEL: update_dppv2f32_test: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 +; GFX11-NEXT: v_lshlrev_b32_e32 v4, 3, v0 +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: v_dual_mov_b32 v2, s2 :: v_dual_mov_b32 v3, s3 +; GFX11-NEXT: global_load_b64 v[0:1], v4, s[0:1] +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_dpp v2, v0 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX11-NEXT: v_mov_b32_dpp v3, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX11-NEXT: global_store_b64 v4, v[2:3], s[0:1] +; GFX11-NEXT: s_nop 0 +; GFX11-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) +; GFX11-NEXT: s_endpgm + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds <2 x float>, ptr addrspace(1) %arg, i32 %id + %load = load <2 x float>, ptr addrspace(1) %gep + %tmp0 = call <2 x float> @llvm.amdgcn.update.dpp.v2f32(<2 x float> %in1, <2 x float> %load, i32 1, i32 1, i32 1, i1 false) #1 + store <2 x float> %tmp0, ptr addrspace(1) %gep + ret void +} + +define amdgpu_kernel void @update_dpp_p0_test(ptr addrspace(1) %arg, ptr %in1, ptr %in2) { +; GFX8-LABEL: update_dpp_p0_test: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX8-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_mov_b32_e32 v0, s0 +; GFX8-NEXT: v_mov_b32_e32 v1, s1 +; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 +; GFX8-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GFX8-NEXT: flat_load_dwordx2 v[2:3], v[0:1] +; GFX8-NEXT: v_mov_b32_e32 v5, s3 +; GFX8-NEXT: v_mov_b32_e32 v4, s2 +; GFX8-NEXT: s_waitcnt vmcnt(0) +; GFX8-NEXT: v_mov_b32_dpp v5, v3 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX8-NEXT: v_mov_b32_dpp v4, v2 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX8-NEXT: flat_store_dwordx2 v[0:1], v[4:5] +; GFX8-NEXT: s_endpgm +; +; GFX10-LABEL: update_dpp_p0_test: +; GFX10: ; %bb.0: +; GFX10-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX10-NEXT: v_lshlrev_b32_e32 v4, 3, v0 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: global_load_dwordx2 v[0:1], v4, s[0:1] +; GFX10-NEXT: v_mov_b32_e32 v2, s2 +; GFX10-NEXT: v_mov_b32_e32 v3, s3 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_dpp v2, v0 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX10-NEXT: v_mov_b32_dpp v3, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX10-NEXT: global_store_dwordx2 v4, v[2:3], s[0:1] +; GFX10-NEXT: s_endpgm +; +; GFX11-LABEL: update_dpp_p0_test: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 +; GFX11-NEXT: v_lshlrev_b32_e32 v4, 3, v0 +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: v_dual_mov_b32 v2, s2 :: v_dual_mov_b32 v3, s3 +; GFX11-NEXT: global_load_b64 v[0:1], v4, s[0:1] +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_dpp v2, v0 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX11-NEXT: v_mov_b32_dpp v3, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX11-NEXT: global_store_b64 v4, v[2:3], s[0:1] +; GFX11-NEXT: s_nop 0 +; GFX11-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) +; GFX11-NEXT: s_endpgm + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds ptr, ptr addrspace(1) %arg, i32 %id + %load = load ptr, ptr addrspace(1) %gep + %tmp0 = call ptr @llvm.amdgcn.update.dpp.v2f32(ptr %in1, ptr %load, i32 1, i32 1, i32 1, i1 false) #1 + store ptr %tmp0, ptr addrspace(1) %gep + ret void +} + +define amdgpu_kernel void @update_dpp_p3_test(ptr addrspace(3) %arg, ptr addrspace(3) %in1, ptr %in2) { +; GFX8-LABEL: update_dpp_p3_test: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX8-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX8-NEXT: s_mov_b32 m0, -1 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_add_u32_e32 v0, vcc, s0, v0 +; GFX8-NEXT: ds_read_b32 v1, v0 +; GFX8-NEXT: v_mov_b32_e32 v2, s1 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: s_nop 0 +; GFX8-NEXT: v_mov_b32_dpp v2, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX8-NEXT: ds_write_b32 v0, v2 +; GFX8-NEXT: s_endpgm +; +; GFX10-LABEL: update_dpp_p3_test: +; GFX10: ; %bb.0: +; GFX10-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX10-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: v_add_nc_u32_e32 v0, s0, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, s1 +; GFX10-NEXT: ds_read_b32 v1, v0 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: v_mov_b32_dpp v2, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX10-NEXT: ds_write_b32 v0, v2 +; GFX10-NEXT: s_endpgm +; +; GFX11-LABEL: update_dpp_p3_test: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX11-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: v_add_nc_u32_e32 v0, s0, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, s1 +; GFX11-NEXT: ds_load_b32 v1, v0 +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: v_mov_b32_dpp v2, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX11-NEXT: ds_store_b32 v0, v2 +; GFX11-NEXT: s_endpgm + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds ptr addrspace(3), ptr addrspace(3) %arg, i32 %id + %load = load ptr addrspace(3), ptr addrspace(3) %gep + %tmp0 = call ptr addrspace(3) @llvm.amdgcn.update.dpp.p3(ptr addrspace(3) %in1, ptr addrspace(3) %load, i32 1, i32 1, i32 1, i1 false) #1 + store ptr addrspace(3) %tmp0, ptr addrspace(3) %gep + ret void +} + +define amdgpu_kernel void @update_dpp_p5_test(ptr addrspace(5) %arg, ptr addrspace(5) %in1, ptr %in2) { +; GFX8-LABEL: update_dpp_p5_test: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_mov_b32 s88, SCRATCH_RSRC_DWORD0 +; GFX8-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX8-NEXT: s_mov_b32 s89, SCRATCH_RSRC_DWORD1 +; GFX8-NEXT: s_mov_b32 s90, -1 +; GFX8-NEXT: s_mov_b32 s91, 0xe80000 +; GFX8-NEXT: s_add_u32 s88, s88, s3 +; GFX8-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX8-NEXT: s_addc_u32 s89, s89, 0 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_add_u32_e32 v0, vcc, s0, v0 +; GFX8-NEXT: buffer_load_dword v1, v0, s[88:91], 0 offen +; GFX8-NEXT: v_mov_b32_e32 v2, s1 +; GFX8-NEXT: s_waitcnt vmcnt(0) +; GFX8-NEXT: s_nop 0 +; GFX8-NEXT: v_mov_b32_dpp v2, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX8-NEXT: buffer_store_dword v2, v0, s[88:91], 0 offen +; GFX8-NEXT: s_endpgm +; +; GFX10-LABEL: update_dpp_p5_test: +; GFX10: ; %bb.0: +; GFX10-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX10-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX10-NEXT: s_mov_b32 s4, SCRATCH_RSRC_DWORD0 +; GFX10-NEXT: s_mov_b32 s5, SCRATCH_RSRC_DWORD1 +; GFX10-NEXT: s_mov_b32 s6, -1 +; GFX10-NEXT: s_mov_b32 s7, 0x31c16000 +; GFX10-NEXT: s_add_u32 s4, s4, s3 +; GFX10-NEXT: s_addc_u32 s5, s5, 0 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: v_add_nc_u32_e32 v0, s0, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, s1 +; GFX10-NEXT: buffer_load_dword v1, v0, s[4:7], 0 offen +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_dpp v2, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX10-NEXT: buffer_store_dword v2, v0, s[4:7], 0 offen +; GFX10-NEXT: s_endpgm +; +; GFX11-LABEL: update_dpp_p5_test: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX11-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: v_add_nc_u32_e32 v0, s0, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, s1 +; GFX11-NEXT: scratch_load_b32 v1, v0, off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_dpp v2, v1 quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1 +; GFX11-NEXT: scratch_store_b32 v0, v2, off +; GFX11-NEXT: s_endpgm + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds ptr addrspace(5), ptr addrspace(5) %arg, i32 %id + %load = load ptr addrspace(5), ptr addrspace(5) %gep + %tmp0 = call ptr addrspace(5) @llvm.amdgcn.update.dpp.p5(ptr addrspace(5) %in1, ptr addrspace(5) %load, i32 1, i32 1, i32 1, i1 false) #1 + store ptr addrspace(5) %tmp0, ptr addrspace(5) %gep + ret void +} + declare i32 @llvm.amdgcn.workitem.id.x() #0 declare i32 @llvm.amdgcn.update.dpp.i32(i32, i32, i32 immarg, i32 immarg, i32 immarg, i1 immarg) #1 declare i64 @llvm.amdgcn.update.dpp.i64(i64, i64, i32 immarg, i32 immarg, i32 immarg, i1 immarg) #1 diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.update.dpp.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.update.dpp.ll index e43daf46e1e0..b678378e5554 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.update.dpp.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.update.dpp.ll @@ -55,11 +55,11 @@ bb: ret void } -; GCN-LABEL: {{^}}update_dpp64_test: +; GCN-LABEL: {{^}}update_dppi64_test: ; GCN: load_{{dwordx2|b64}} v[[[SRC_LO:[0-9]+]]:[[SRC_HI:[0-9]+]]] ; GCN-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_LO]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} ; GCN-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} -define amdgpu_kernel void @update_dpp64_test(ptr addrspace(1) %arg, i64 %in1, i64 %in2) { +define amdgpu_kernel void @update_dppi64_test(ptr addrspace(1) %arg, i64 %in1, i64 %in2) { %id = tail call i32 @llvm.amdgcn.workitem.id.x() %gep = getelementptr inbounds i64, ptr addrspace(1) %arg, i32 %id %load = load i64, ptr addrspace(1) %gep @@ -68,7 +68,83 @@ define amdgpu_kernel void @update_dpp64_test(ptr addrspace(1) %arg, i64 %in1, i6 ret void } -; GCN-LABEL: {{^}}update_dpp64_imm_old_test: +; GCN-LABEL: {{^}}update_dppf64_test: +; GCN: load_{{dwordx2|b64}} v[[[SRC_LO:[0-9]+]]:[[SRC_HI:[0-9]+]]] +; GCN-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_LO]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +; GCN-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +define amdgpu_kernel void @update_dppf64_test(ptr addrspace(1) %arg, double %in1, double %in2) { + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds double, ptr addrspace(1) %arg, i32 %id + %load = load double, ptr addrspace(1) %gep + %tmp0 = call double @llvm.amdgcn.update.dpp.f64(double %in1, double %load, i32 1, i32 1, i32 1, i1 false) #0 + store double %tmp0, ptr addrspace(1) %gep + ret void +} + +; GCN-LABEL: {{^}}update_dppv2i32_test: +; GCN: load_{{dwordx2|b64}} v[[[SRC_LO:[0-9]+]]:[[SRC_HI:[0-9]+]]] +; GCN-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_LO]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +; GCN-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +define amdgpu_kernel void @update_dppv2i32_test(ptr addrspace(1) %arg, <2 x i32> %in1, <2 x i32> %in2) { + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds <2 x i32>, ptr addrspace(1) %arg, i32 %id + %load = load <2 x i32>, ptr addrspace(1) %gep + %tmp0 = call <2 x i32> @llvm.amdgcn.update.dpp.v2i32(<2 x i32> %in1, <2 x i32> %load, i32 1, i32 1, i32 1, i1 false) #0 + store <2 x i32> %tmp0, ptr addrspace(1) %gep + ret void +} + +; GCN-LABEL: {{^}}update_dppv2f32_test: +; GCN: load_{{dwordx2|b64}} v[[[SRC_LO:[0-9]+]]:[[SRC_HI:[0-9]+]]] +; GCN-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_LO]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +; GCN-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +define amdgpu_kernel void @update_dppv2f32_test(ptr addrspace(1) %arg, <2 x float> %in1, <2 x float> %in2) { + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds <2 x float>, ptr addrspace(1) %arg, i32 %id + %load = load <2 x float>, ptr addrspace(1) %gep + %tmp0 = call <2 x float> @llvm.amdgcn.update.dpp.v2f32(<2 x float> %in1, <2 x float> %load, i32 1, i32 1, i32 1, i1 false) #0 + store <2 x float> %tmp0, ptr addrspace(1) %gep + ret void +} + +; GCN-LABEL: {{^}}update_dpp_p0_test: +; GCN: load_{{dwordx2|b64}} v[[[SRC_LO:[0-9]+]]:[[SRC_HI:[0-9]+]]] +; GCN-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_LO]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +; GCN-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +define amdgpu_kernel void @update_dpp_p0_test(ptr addrspace(1) %arg, ptr %in1, ptr %in2) { + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds ptr, ptr addrspace(1) %arg, i32 %id + %load = load ptr, ptr addrspace(1) %gep + %tmp0 = call ptr @llvm.amdgcn.update.dpp.p0(ptr %in1, ptr %load, i32 1, i32 1, i32 1, i1 false) #0 + store ptr %tmp0, ptr addrspace(1) %gep + ret void +} + +; GCN-LABEL: {{^}}update_dpp_p3_test: +; GCN: {{load|read}}_{{dword|b32}} v[[SRC:[0-9]+]] +; GCN: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +define amdgpu_kernel void @update_dpp_p3_test(ptr addrspace(3) %arg, ptr addrspace(3) %in1, ptr %in2) { + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds ptr addrspace(3), ptr addrspace(3) %arg, i32 %id + %load = load ptr addrspace(3), ptr addrspace(3) %gep + %tmp0 = call ptr addrspace(3) @llvm.amdgcn.update.dpp.p3(ptr addrspace(3) %in1, ptr addrspace(3) %load, i32 1, i32 1, i32 1, i1 false) #0 + store ptr addrspace(3) %tmp0, ptr addrspace(3) %gep + ret void +} + +; GCN-LABEL: {{^}}update_dpp_p5_test: +; GCN: {{load|read}}_{{dword|b32}} v[[SRC:[0-9]+]] +; GCN: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +define amdgpu_kernel void @update_dpp_p5_test(ptr addrspace(5) %arg, ptr addrspace(5) %in1, ptr %in2) { + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds ptr addrspace(5), ptr addrspace(5) %arg, i32 %id + %load = load ptr addrspace(5), ptr addrspace(5) %gep + %tmp0 = call ptr addrspace(5) @llvm.amdgcn.update.dpp.p5(ptr addrspace(5) %in1, ptr addrspace(5) %load, i32 1, i32 1, i32 1, i1 false) #0 + store ptr addrspace(5) %tmp0, ptr addrspace(5) %gep + ret void +} + +; GCN-LABEL: {{^}}update_dppi64_imm_old_test: ; GCN-OPT-DAG: v_mov_b32_e32 v[[OLD_LO:[0-9]+]], 0x3afaedd9 ; GFX8-OPT-DAG,GFX10-DAG: v_mov_b32_e32 v[[OLD_HI:[0-9]+]], 0x7047 ; GFX11-DAG: v_mov_b32_e32 v[[OLD_HI:[0-9]+]], 0x7047 @@ -79,7 +155,7 @@ define amdgpu_kernel void @update_dpp64_test(ptr addrspace(1) %arg, i64 %in1, i6 ; GFX8-OPT-DAG,GFX10-DAG,GFX11-DAG: v_mov_b32_dpp v[[OLD_HI]], v[[SRC_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} ; GCN-NOOPT-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_LO]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} ; GCN-NOOPT-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} -define amdgpu_kernel void @update_dpp64_imm_old_test(ptr addrspace(1) %arg, i64 %in2) { +define amdgpu_kernel void @update_dppi64_imm_old_test(ptr addrspace(1) %arg, i64 %in2) { %id = tail call i32 @llvm.amdgcn.workitem.id.x() %gep = getelementptr inbounds i64, ptr addrspace(1) %arg, i32 %id %load = load i64, ptr addrspace(1) %gep @@ -88,7 +164,27 @@ define amdgpu_kernel void @update_dpp64_imm_old_test(ptr addrspace(1) %arg, i64 ret void } -; GCN-LABEL: {{^}}update_dpp64_imm_src_test: +; GCN-LABEL: {{^}}update_dppf64_imm_old_test: +; GCN-OPT-DAG: v_mov_b32_e32 v[[OLD_LO:[0-9]+]], 0x6b8564a +; GFX8-OPT-DAG,GFX10-DAG: v_mov_b32_e32 v[[OLD_HI:[0-9]+]], 0x405edce1 +; GFX11-DAG: v_mov_b32_e32 v[[OLD_HI:[0-9]+]], 0x405edce1 +; GFX8-NOOPT-DAG: s_mov_b32 s[[SOLD_LO:[0-9]+]], 0x6b8564a +; GFX8-NOOPT-DAG: s_mov_b32 s[[SOLD_HI:[0-9]+]], 0x405edce1 +; GCN-DAG: load_{{dwordx2|b64}} v[[[SRC_LO:[0-9]+]]:[[SRC_HI:[0-9]+]]] +; GCN-OPT-DAG: v_mov_b32_dpp v[[OLD_LO]], v[[SRC_LO]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +; GFX8-OPT-DAG,GFX10-DAG,GFX11-DAG: v_mov_b32_dpp v[[OLD_HI]], v[[SRC_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +; GCN-NOOPT-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_LO]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +; GCN-NOOPT-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +define amdgpu_kernel void @update_dppf64_imm_old_test(ptr addrspace(1) %arg, double %in2) { + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds i64, ptr addrspace(1) %arg, i32 %id + %load = load double, ptr addrspace(1) %gep + %tmp0 = call double @llvm.amdgcn.update.dpp.f64(double 123.4512345123450, double %load, i32 1, i32 1, i32 1, i1 false) #0 + store double %tmp0, ptr addrspace(1) %gep + ret void +} + +; GCN-LABEL: {{^}}update_dppi64_imm_src_test: ; GCN-OPT-DAG: v_mov_b32_e32 v[[OLD_LO:[0-9]+]], 0x3afaedd9 ; GCN-OPT-DAG: v_mov_b32_e32 v[[OLD_HI:[0-9]+]], 0x7047 ; GFX8-NOOPT-DAG: s_mov_b32 s[[SOLD_LO:[0-9]+]], 0x3afaedd9 @@ -97,12 +193,27 @@ define amdgpu_kernel void @update_dpp64_imm_old_test(ptr addrspace(1) %arg, i64 ; GCN-OPT-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[OLD_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} ; GCN-NOOPT-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_LO]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} ; GCN-NOOPT-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} -define amdgpu_kernel void @update_dpp64_imm_src_test(ptr addrspace(1) %out, i64 %in1) { +define amdgpu_kernel void @update_dppi64_imm_src_test(ptr addrspace(1) %out, i64 %in1) { %tmp0 = call i64 @llvm.amdgcn.update.dpp.i64(i64 %in1, i64 123451234512345, i32 1, i32 1, i32 1, i1 false) #0 store i64 %tmp0, ptr addrspace(1) %out ret void } +; GCN-LABEL: {{^}}update_dppf64_imm_src_test: +; GCN-OPT-DAG: v_mov_b32_e32 v[[OLD_LO:[0-9]+]], 0x6b8564a +; GCN-OPT-DAG: v_mov_b32_e32 v[[OLD_HI:[0-9]+]], 0x405edce1 +; GFX8-NOOPT-DAG: s_mov_b32 s[[SOLD_LO:[0-9]+]], 0x6b8564a +; GFX8-NOOPT-DAG: s_mov_b32 s[[SOLD_HI:[0-9]+]], 0x405edce1 +; GCN-OPT-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[OLD_LO]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +; GCN-OPT-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[OLD_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +; GCN-NOOPT-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_LO]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +; GCN-NOOPT-DAG: v_mov_b32_dpp v{{[0-9]+}}, v[[SRC_HI]] quad_perm:[1,0,0,0] row_mask:0x1 bank_mask:0x1{{$}} +define amdgpu_kernel void @update_dppf64_imm_src_test(ptr addrspace(1) %out, double %in1) { + %tmp0 = call double @llvm.amdgcn.update.dpp.f64(double %in1, double 123.451234512345, i32 1, i32 1, i32 1, i1 false) #0 + store double %tmp0, ptr addrspace(1) %out + ret void +} + ; GCN-LABEL: {{^}}dpp_test_f32: ; GCN: v_mov_b32_e32 [[DST:v[0-9]+]], s{{[0-9]+}} ; GCN: v_mov_b32_e32 [[SRC:v[0-9]+]], s{{[0-9]+}} -- GitLab From 2163ae761808ca0e5478357384f6ddbacce279eb Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 13 May 2024 13:51:22 +0900 Subject: [PATCH 011/578] [LVStringPool] Remove incorrect std::move (NFCI) "Value" is still used afterwards in the return value. In this case, this doesn't actually make a difference because a move for a primitive type is the same as a copy, so there is no actual misbehavior. Still drop the std::move to make the code less confusing. --- llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h index 4c596b5b1dde..8ce751a56c59 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h @@ -60,7 +60,7 @@ public: if (isValidIndex(Index)) return Index; size_t Value = Entries.size(); - ValueType *Entry = ValueType::create(Key, Allocator, std::move(Value)); + ValueType *Entry = ValueType::create(Key, Allocator, Value); StringTable.insert(Entry); Entries.push_back(Entry); return Value; -- GitLab From eeafc9daa15d2d022bcdd456d4b8bafd23f5f121 Mon Sep 17 00:00:00 2001 From: Christian Ulmann Date: Mon, 13 May 2024 07:37:41 +0200 Subject: [PATCH 012/578] [MLIR][Mem2Reg] Fix multi slot handling & move retry handling (#91464) This commit fixes Mem2Regs mutli-slot allocator handling and extends the test dialect to test this. Additionally, this modifies Mem2Reg's API to always attempt a full promotion on all the passed in "allocators". This ensures that the pass does not require unnecessary walks over the regions and improves caching benefits. --- .../mlir/Interfaces/MemorySlotInterfaces.td | 6 +- mlir/include/mlir/Transforms/Mem2Reg.h | 6 +- mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp | 8 +- .../Dialect/MemRef/IR/MemRefMemorySlot.cpp | 8 +- mlir/lib/Transforms/Mem2Reg.cpp | 85 ++++++++++++------- mlir/test/Transforms/mem2reg.mlir | 28 ++++++ mlir/test/lib/Dialect/Test/TestOpDefs.cpp | 59 +++++++++++++ mlir/test/lib/Dialect/Test/TestOps.h | 1 + mlir/test/lib/Dialect/Test/TestOps.td | 11 +++ 9 files changed, 173 insertions(+), 39 deletions(-) create mode 100644 mlir/test/Transforms/mem2reg.mlir diff --git a/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td b/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td index adf182ac7069..e2409cbec5fd 100644 --- a/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td +++ b/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td @@ -68,8 +68,12 @@ def PromotableAllocationOpInterface Hook triggered once the promotion of a slot is complete. This can also clean up the created default value if necessary. This will only be called for slots declared by this operation. + + Must return a new promotable allocation op if this operation produced + multiple promotable slots, nullopt otherwise. }], - "void", "handlePromotionComplete", + "::std::optional<::mlir::PromotableAllocationOpInterface>", + "handlePromotionComplete", (ins "const ::mlir::MemorySlot &":$slot, "::mlir::Value":$defaultValue, diff --git a/mlir/include/mlir/Transforms/Mem2Reg.h b/mlir/include/mlir/Transforms/Mem2Reg.h index fee7fb312750..6986cad9ae12 100644 --- a/mlir/include/mlir/Transforms/Mem2Reg.h +++ b/mlir/include/mlir/Transforms/Mem2Reg.h @@ -9,7 +9,6 @@ #ifndef MLIR_TRANSFORMS_MEM2REG_H #define MLIR_TRANSFORMS_MEM2REG_H -#include "mlir/IR/PatternMatch.h" #include "mlir/Interfaces/MemorySlotInterfaces.h" #include "llvm/ADT/Statistic.h" @@ -23,8 +22,9 @@ struct Mem2RegStatistics { llvm::Statistic *newBlockArgumentAmount = nullptr; }; -/// Attempts to promote the memory slots of the provided allocators. Succeeds if -/// at least one memory slot was promoted. +/// Attempts to promote the memory slots of the provided allocators. Iteratively +/// retries the promotion of all slots as promoting one slot might enable +/// subsequent promotions. Succeeds if at least one memory slot was promoted. LogicalResult tryToPromoteMemorySlots(ArrayRef allocators, OpBuilder &builder, const DataLayout &dataLayout, diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp index 70102e1c8192..4fdf847a559c 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp @@ -50,12 +50,14 @@ void LLVM::AllocaOp::handleBlockArgument(const MemorySlot &slot, declareOp.getLocationExpr()); } -void LLVM::AllocaOp::handlePromotionComplete(const MemorySlot &slot, - Value defaultValue, - OpBuilder &builder) { +std::optional +LLVM::AllocaOp::handlePromotionComplete(const MemorySlot &slot, + Value defaultValue, + OpBuilder &builder) { if (defaultValue && defaultValue.use_empty()) defaultValue.getDefiningOp()->erase(); this->erase(); + return std::nullopt; } SmallVector LLVM::AllocaOp::getDestructurableSlots() { diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp index dca07e84ea73..e30598e6878f 100644 --- a/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp @@ -96,12 +96,14 @@ Value memref::AllocaOp::getDefaultValue(const MemorySlot &slot, }); } -void memref::AllocaOp::handlePromotionComplete(const MemorySlot &slot, - Value defaultValue, - OpBuilder &builder) { +std::optional +memref::AllocaOp::handlePromotionComplete(const MemorySlot &slot, + Value defaultValue, + OpBuilder &builder) { if (defaultValue.use_empty()) defaultValue.getDefiningOp()->erase(); this->erase(); + return std::nullopt; } void memref::AllocaOp::handleBlockArgument(const MemorySlot &slot, diff --git a/mlir/lib/Transforms/Mem2Reg.cpp b/mlir/lib/Transforms/Mem2Reg.cpp index 8adbbcd01cb4..e096747741c0 100644 --- a/mlir/lib/Transforms/Mem2Reg.cpp +++ b/mlir/lib/Transforms/Mem2Reg.cpp @@ -173,7 +173,9 @@ public: /// Actually promotes the slot by mutating IR. Promoting a slot DOES /// invalidate the MemorySlotPromotionInfo of other slots. Preparation of /// promotion info should NOT be performed in batches. - void promoteSlot(); + /// Returns a promotable allocation op if a new allocator was created, nullopt + /// otherwise. + std::optional promoteSlot(); private: /// Computes the reaching definition for all the operations that require @@ -595,7 +597,8 @@ void MemorySlotPromoter::removeBlockingUses() { "after promotion, the slot pointer should not be used anymore"); } -void MemorySlotPromoter::promoteSlot() { +std::optional +MemorySlotPromoter::promoteSlot() { computeReachingDefInRegion(slot.ptr.getParentRegion(), getOrCreateDefaultValue()); @@ -622,7 +625,7 @@ void MemorySlotPromoter::promoteSlot() { if (statistics.promotedAmount) (*statistics.promotedAmount)++; - allocator.handlePromotionComplete(slot, defaultValue, builder); + return allocator.handlePromotionComplete(slot, defaultValue, builder); } LogicalResult mlir::tryToPromoteMemorySlots( @@ -636,20 +639,50 @@ LogicalResult mlir::tryToPromoteMemorySlots( // lazily and cached to avoid expensive recomputation. BlockIndexCache blockIndexCache; - for (PromotableAllocationOpInterface allocator : allocators) { - for (MemorySlot slot : allocator.getPromotableSlots()) { - if (slot.ptr.use_empty()) - continue; - - MemorySlotPromotionAnalyzer analyzer(slot, dominance, dataLayout); - std::optional info = analyzer.computeInfo(); - if (info) { - MemorySlotPromoter(slot, allocator, builder, dominance, dataLayout, - std::move(*info), statistics, blockIndexCache) - .promoteSlot(); - promotedAny = true; + SmallVector workList(allocators.begin(), + allocators.end()); + + SmallVector newWorkList; + newWorkList.reserve(workList.size()); + while (true) { + bool changesInThisRound = false; + for (PromotableAllocationOpInterface allocator : workList) { + bool changedAllocator = false; + for (MemorySlot slot : allocator.getPromotableSlots()) { + if (slot.ptr.use_empty()) + continue; + + MemorySlotPromotionAnalyzer analyzer(slot, dominance, dataLayout); + std::optional info = analyzer.computeInfo(); + if (info) { + std::optional newAllocator = + MemorySlotPromoter(slot, allocator, builder, dominance, + dataLayout, std::move(*info), statistics, + blockIndexCache) + .promoteSlot(); + changedAllocator = true; + // Add newly created allocators to the worklist for further + // processing. + if (newAllocator) + newWorkList.push_back(*newAllocator); + + // A break is required, since promoting a slot may invalidate the + // remaining slots of an allocator. + break; + } } + if (!changedAllocator) + newWorkList.push_back(allocator); + changesInThisRound |= changedAllocator; } + if (!changesInThisRound) + break; + promotedAny = true; + + // Swap the vector's backing memory and clear the entries in newWorkList + // afterwards. This ensures that additional heap allocations can be avoided. + workList.swap(newWorkList); + newWorkList.clear(); } return success(promotedAny); @@ -677,22 +710,16 @@ struct Mem2Reg : impl::Mem2RegBase { OpBuilder builder(®ion.front(), region.front().begin()); - // Promoting a slot can allow for further promotion of other slots, - // promotion is tried until no promotion succeeds. - while (true) { - SmallVector allocators; - // Build a list of allocators to attempt to promote the slots of. - region.walk([&](PromotableAllocationOpInterface allocator) { - allocators.emplace_back(allocator); - }); - - // Attempt promoting until no promotion succeeds. - if (failed(tryToPromoteMemorySlots(allocators, builder, dataLayout, - dominance, statistics))) - break; + SmallVector allocators; + // Build a list of allocators to attempt to promote the slots of. + region.walk([&](PromotableAllocationOpInterface allocator) { + allocators.emplace_back(allocator); + }); + // Attempt promoting as many of the slots as possible. + if (succeeded(tryToPromoteMemorySlots(allocators, builder, dataLayout, + dominance, statistics))) changed = true; - } } if (!changed) markAllAnalysesPreserved(); diff --git a/mlir/test/Transforms/mem2reg.mlir b/mlir/test/Transforms/mem2reg.mlir new file mode 100644 index 000000000000..daeaa2da0763 --- /dev/null +++ b/mlir/test/Transforms/mem2reg.mlir @@ -0,0 +1,28 @@ +// RUN: mlir-opt %s --pass-pipeline='builtin.module(func.func(mem2reg))' --split-input-file | FileCheck %s + +// Verifies that allocators with mutliple slots are handled properly. + +// CHECK-LABEL: func.func @multi_slot_alloca +func.func @multi_slot_alloca() -> (i32, i32) { + // CHECK-NOT: test.multi_slot_alloca + %1, %2 = test.multi_slot_alloca : () -> (memref, memref) + %3 = memref.load %1[] : memref + %4 = memref.load %2[] : memref + return %3, %4 : i32, i32 +} + +// ----- + +// Verifies that a multi slot allocator can be partially promoted. + +func.func private @consumer(memref) + +// CHECK-LABEL: func.func @multi_slot_alloca_only_second +func.func @multi_slot_alloca_only_second() -> (i32, i32) { + // CHECK: %{{[[:alnum:]]+}} = test.multi_slot_alloca + %1, %2 = test.multi_slot_alloca : () -> (memref, memref) + func.call @consumer(%1) : (memref) -> () + %3 = memref.load %1[] : memref + %4 = memref.load %2[] : memref + return %3, %4 : i32, i32 +} diff --git a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp index 08df2e5e1228..d22d48b139a0 100644 --- a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp +++ b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp @@ -11,6 +11,7 @@ #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/IR/Verifier.h" #include "mlir/Interfaces/FunctionImplementation.h" +#include "mlir/Interfaces/MemorySlotInterfaces.h" using namespace mlir; using namespace test; @@ -1172,3 +1173,61 @@ void TestOpWithVersionedProperties::writeToMlirBytecode( writer.writeVarInt(prop.value1); writer.writeVarInt(prop.value2); } + +//===----------------------------------------------------------------------===// +// TestMultiSlotAlloca +//===----------------------------------------------------------------------===// + +llvm::SmallVector TestMultiSlotAlloca::getPromotableSlots() { + SmallVector slots; + for (Value result : getResults()) { + slots.push_back(MemorySlot{ + result, cast(result.getType()).getElementType()}); + } + return slots; +} + +Value TestMultiSlotAlloca::getDefaultValue(const MemorySlot &slot, + OpBuilder &builder) { + return builder.create(getLoc(), slot.elemType, + builder.getI32IntegerAttr(42)); +} + +void TestMultiSlotAlloca::handleBlockArgument(const MemorySlot &slot, + BlockArgument argument, + OpBuilder &builder) { + // Not relevant for testing. +} + +std::optional +TestMultiSlotAlloca::handlePromotionComplete(const MemorySlot &slot, + Value defaultValue, + OpBuilder &builder) { + if (defaultValue && defaultValue.use_empty()) + defaultValue.getDefiningOp()->erase(); + + if (getNumResults() == 1) { + erase(); + return std::nullopt; + } + + SmallVector newTypes; + SmallVector remainingValues; + + for (Value oldResult : getResults()) { + if (oldResult == slot.ptr) + continue; + remainingValues.push_back(oldResult); + newTypes.push_back(oldResult.getType()); + } + + OpBuilder::InsertionGuard guard(builder); + builder.setInsertionPoint(*this); + auto replacement = builder.create(getLoc(), newTypes); + for (auto [oldResult, newResult] : + llvm::zip_equal(remainingValues, replacement.getResults())) + oldResult.replaceAllUsesWith(newResult); + + erase(); + return replacement; +} diff --git a/mlir/test/lib/Dialect/Test/TestOps.h b/mlir/test/lib/Dialect/Test/TestOps.h index f9925855bb9d..837ccca56592 100644 --- a/mlir/test/lib/Dialect/Test/TestOps.h +++ b/mlir/test/lib/Dialect/Test/TestOps.h @@ -36,6 +36,7 @@ #include "mlir/Interfaces/InferIntRangeInterface.h" #include "mlir/Interfaces/InferTypeOpInterface.h" #include "mlir/Interfaces/LoopLikeInterface.h" +#include "mlir/Interfaces/MemorySlotInterfaces.h" #include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Interfaces/ValueBoundsOpInterface.h" #include "mlir/Interfaces/ViewLikeInterface.h" diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td index 5352d574ac39..e16ea2407314 100644 --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -28,6 +28,7 @@ include "mlir/Interfaces/DestinationStyleOpInterface.td" include "mlir/Interfaces/InferIntRangeInterface.td" include "mlir/Interfaces/InferTypeOpInterface.td" include "mlir/Interfaces/LoopLikeInterface.td" +include "mlir/Interfaces/MemorySlotInterfaces.td" include "mlir/Interfaces/SideEffectInterfaces.td" @@ -3167,4 +3168,14 @@ def TestOpOptionallyImplementingInterface let arguments = (ins BoolAttr:$implementsInterface); } +//===----------------------------------------------------------------------===// +// Test Mem2Reg +//===----------------------------------------------------------------------===// + +def TestMultiSlotAlloca : TEST_Op<"multi_slot_alloca", + [DeclareOpInterfaceMethods]> { + let results = (outs Variadic>:$results); + let assemblyFormat = "attr-dict `:` functional-type(operands, results)"; +} + #endif // TEST_OPS -- GitLab From 662267daea7e76ee3cee90c63ab2bc2964b77b76 Mon Sep 17 00:00:00 2001 From: Chen Zheng Date: Mon, 13 May 2024 01:32:25 -0400 Subject: [PATCH 013/578] [PPC] add testcase, nfc --- .../CodeGen/PowerPC/aix-tocdata-fastisel.ll | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 llvm/test/CodeGen/PowerPC/aix-tocdata-fastisel.ll diff --git a/llvm/test/CodeGen/PowerPC/aix-tocdata-fastisel.ll b/llvm/test/CodeGen/PowerPC/aix-tocdata-fastisel.ll new file mode 100644 index 000000000000..5a7fcd1d0ddd --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-tocdata-fastisel.ll @@ -0,0 +1,23 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=powerpc64-ibm-aix-xcoff -fast-isel -verify-machineinstrs \ +; RUN: -code-model=small | FileCheck %s --check-prefix=SMALL + +;; FIXME: when toc data for 64 big large code model is supported, +;; add a run line for large code model too. + +@a = global i32 0, align 4 #0 + +define signext i32 @foo() #1 { +; SMALL-LABEL: foo: +; SMALL: # %bb.0: # %entry +; SMALL-NEXT: la 3, a[TD](2) +; SMALL-NEXT: lwz 3, 0(3) +; SMALL-NEXT: extsw 3, 3 +; SMALL-NEXT: blr +entry: + %0 = load i32, ptr @a, align 4 + ret i32 %0 +} + +attributes #0 = { "toc-data" } +attributes #1 = { noinline optnone } -- GitLab From e6785fd75284f53b9e23db6f249598e09f3fc39f Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sun, 12 May 2024 23:02:37 -0700 Subject: [PATCH 014/578] [Scalar] Fix a warning This patch fixes: llvm/lib/Transforms/Scalar/GVNSink.cpp:270:33: error: lambda capture 'this' is not used [-Werror,-Wunused-lambda-capture] While I am at it, this patch replaces llvm::for_each with a range-based for loop. --- llvm/lib/Transforms/Scalar/GVNSink.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/GVNSink.cpp b/llvm/lib/Transforms/Scalar/GVNSink.cpp index ddf01dc612bb..95a4c644a91a 100644 --- a/llvm/lib/Transforms/Scalar/GVNSink.cpp +++ b/llvm/lib/Transforms/Scalar/GVNSink.cpp @@ -267,13 +267,13 @@ public: }; assert(llvm::is_sorted(Blocks, ComesBefore)); int C = 0; - llvm::for_each(Values, [&C, this](const Value *V) { + for (const Value *V : Values) { if (!isa(V)) { - const Instruction *I = cast(V); - assert(I->getParent() == this->Blocks[C]); + assert(cast(V)->getParent() == Blocks[C]); + (void)C; } C++; - }); + } } /// Create a PHI from an array of incoming values and incoming blocks. ModelledPHI(SmallVectorImpl &V, -- GitLab From e74a34b6932965dfdc182b69f779e5bee551585a Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Mon, 13 May 2024 13:56:25 +0800 Subject: [PATCH 015/578] [NFC] [Serialization] Merge IdentID with IdentifierID In ASTBitCodes.h, there are two type alias for the ID type of Identifiers with the same underlying type. It is confusing. This patch tries to merge the `IdentID` to `IdentifierID` to erase such confusion. --- .../include/clang/Frontend/MultiplexConsumer.h | 2 +- .../include/clang/Serialization/ASTBitCodes.h | 9 +++------ .../Serialization/ASTDeserializationListener.h | 2 +- clang/include/clang/Serialization/ASTReader.h | 2 +- clang/include/clang/Serialization/ASTWriter.h | 10 +++++----- clang/include/clang/Serialization/ModuleFile.h | 2 +- clang/lib/Frontend/FrontendAction.cpp | 2 +- clang/lib/Frontend/MultiplexConsumer.cpp | 2 +- clang/lib/Serialization/ASTReader.cpp | 4 ++-- clang/lib/Serialization/ASTReaderInternals.h | 2 +- clang/lib/Serialization/ASTWriter.cpp | 18 +++++++++--------- 11 files changed, 26 insertions(+), 29 deletions(-) diff --git a/clang/include/clang/Frontend/MultiplexConsumer.h b/clang/include/clang/Frontend/MultiplexConsumer.h index f29c8e92fded..4ed0d86d3cdf 100644 --- a/clang/include/clang/Frontend/MultiplexConsumer.h +++ b/clang/include/clang/Frontend/MultiplexConsumer.h @@ -32,7 +32,7 @@ public: MultiplexASTDeserializationListener( const std::vector &L); void ReaderInitialized(ASTReader *Reader) override; - void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) override; + void IdentifierRead(serialization::IdentifierID ID, IdentifierInfo *II) override; void MacroRead(serialization::MacroID ID, MacroInfo *MI) override; void TypeRead(serialization::TypeIdx Idx, QualType T) override; void DeclRead(GlobalDeclID ID, const Decl *D) override; diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index ae9521e42709..d3538e43d3d7 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -61,6 +61,9 @@ const unsigned VERSION_MINOR = 1; /// and start at 1. 0 is reserved for NULL. using IdentifierID = uint32_t; +/// The number of predefined identifier IDs. +const unsigned int NUM_PREDEF_IDENT_IDS = 1; + /// An ID number that refers to a declaration in an AST file. See the comments /// in DeclIDBase for details. using DeclID = DeclIDBase::DeclID; @@ -123,12 +126,6 @@ struct UnsafeQualTypeDenseMapInfo { } }; -/// An ID number that refers to an identifier in an AST file. -using IdentID = uint32_t; - -/// The number of predefined identifier IDs. -const unsigned int NUM_PREDEF_IDENT_IDS = 1; - /// An ID number that refers to a macro in an AST file. using MacroID = uint32_t; diff --git a/clang/include/clang/Serialization/ASTDeserializationListener.h b/clang/include/clang/Serialization/ASTDeserializationListener.h index 3ab7f1a91843..1d81a9ae3fe2 100644 --- a/clang/include/clang/Serialization/ASTDeserializationListener.h +++ b/clang/include/clang/Serialization/ASTDeserializationListener.h @@ -35,7 +35,7 @@ public: virtual void ReaderInitialized(ASTReader *Reader) { } /// An identifier was deserialized from the AST file. - virtual void IdentifierRead(serialization::IdentID ID, + virtual void IdentifierRead(serialization::IdentifierID ID, IdentifierInfo *II) { } /// A macro was read from the AST file. virtual void MacroRead(serialization::MacroID ID, MacroInfo *MI) { } diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index e24fa121528f..1bb5fa27a241 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -667,7 +667,7 @@ private: std::vector IdentifiersLoaded; using GlobalIdentifierMapType = - ContinuousRangeMap; + ContinuousRangeMap; /// Mapping from global identifier IDs to the module in which the /// identifier resides along with the offset that should be added to the diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 482e9dd168cc..7bb0e81545bd 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -277,10 +277,10 @@ private: std::vector TypeOffsets; /// The first ID number we can use for our own identifiers. - serialization::IdentID FirstIdentID = serialization::NUM_PREDEF_IDENT_IDS; + serialization::IdentifierID FirstIdentID = serialization::NUM_PREDEF_IDENT_IDS; /// The identifier ID that will be assigned to the next new identifier. - serialization::IdentID NextIdentID = FirstIdentID; + serialization::IdentifierID NextIdentID = FirstIdentID; /// Map that provides the ID numbers of each identifier in /// the output stream. @@ -288,7 +288,7 @@ private: /// The ID numbers for identifiers are consecutive (in order of /// discovery), starting at 1. An ID of zero refers to a NULL /// IdentifierInfo. - llvm::MapVector IdentifierIDs; + llvm::MapVector IdentifierIDs; /// The first ID number we can use for our own macros. serialization::MacroID FirstMacroID = serialization::NUM_PREDEF_MACRO_IDS; @@ -698,7 +698,7 @@ public: serialization::SelectorID getSelectorRef(Selector Sel); /// Get the unique number used to refer to the given identifier. - serialization::IdentID getIdentifierRef(const IdentifierInfo *II); + serialization::IdentifierID getIdentifierRef(const IdentifierInfo *II); /// Get the unique number used to refer to the given macro. serialization::MacroID getMacroRef(MacroInfo *MI, const IdentifierInfo *Name); @@ -855,7 +855,7 @@ public: private: // ASTDeserializationListener implementation void ReaderInitialized(ASTReader *Reader) override; - void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) override; + void IdentifierRead(serialization::IdentifierID ID, IdentifierInfo *II) override; void MacroRead(serialization::MacroID ID, MacroInfo *MI) override; void TypeRead(serialization::TypeIdx Idx, QualType T) override; void SelectorRead(serialization::SelectorID ID, Selector Sel) override; diff --git a/clang/include/clang/Serialization/ModuleFile.h b/clang/include/clang/Serialization/ModuleFile.h index 8e0fce1fd48c..7d8cbe3d40f5 100644 --- a/clang/include/clang/Serialization/ModuleFile.h +++ b/clang/include/clang/Serialization/ModuleFile.h @@ -308,7 +308,7 @@ public: const uint32_t *IdentifierOffsets = nullptr; /// Base identifier ID for identifiers local to this module. - serialization::IdentID BaseIdentifierID = 0; + serialization::IdentifierID BaseIdentifierID = 0; /// Remapping table for identifier IDs in this module. ContinuousRangeMap IdentifierRemap; diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 9ae7664b4b49..a9c45e525c69 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -71,7 +71,7 @@ public: if (Previous) Previous->ReaderInitialized(Reader); } - void IdentifierRead(serialization::IdentID ID, + void IdentifierRead(serialization::IdentifierID ID, IdentifierInfo *II) override { if (Previous) Previous->IdentifierRead(ID, II); diff --git a/clang/lib/Frontend/MultiplexConsumer.cpp b/clang/lib/Frontend/MultiplexConsumer.cpp index c74bfd86195f..8fdc7f55a500 100644 --- a/clang/lib/Frontend/MultiplexConsumer.cpp +++ b/clang/lib/Frontend/MultiplexConsumer.cpp @@ -35,7 +35,7 @@ void MultiplexASTDeserializationListener::ReaderInitialized( } void MultiplexASTDeserializationListener::IdentifierRead( - serialization::IdentID ID, IdentifierInfo *II) { + serialization::IdentifierID ID, IdentifierInfo *II) { for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->IdentifierRead(ID, II); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 78e4df440641..7627996d2c32 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1005,7 +1005,7 @@ static bool readBit(unsigned &Bits) { return Value; } -IdentID ASTIdentifierLookupTrait::ReadIdentifierID(const unsigned char *d) { +IdentifierID ASTIdentifierLookupTrait::ReadIdentifierID(const unsigned char *d) { using namespace llvm::support; unsigned RawID = endian::readNext(d); @@ -1041,7 +1041,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, markIdentifierFromAST(Reader, *II); Reader.markIdentifierUpToDate(II); - IdentID ID = Reader.getGlobalIdentifierID(F, RawID); + IdentifierID ID = Reader.getGlobalIdentifierID(F, RawID); if (!IsInteresting) { // For uninteresting identifiers, there's nothing else to do. Just notify // the reader that we've finished loading this identifier. diff --git a/clang/lib/Serialization/ASTReaderInternals.h b/clang/lib/Serialization/ASTReaderInternals.h index 49268ad5251d..536b19f91691 100644 --- a/clang/lib/Serialization/ASTReaderInternals.h +++ b/clang/lib/Serialization/ASTReaderInternals.h @@ -175,7 +175,7 @@ public: const unsigned char* d, unsigned DataLen); - IdentID ReadIdentifierID(const unsigned char *d); + IdentifierID ReadIdentifierID(const unsigned char *d); ASTReader &getReader() const { return Reader; } }; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ab07cf3efa45..6154ead589d3 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -3746,7 +3746,7 @@ public: using key_type = const IdentifierInfo *; using key_type_ref = key_type; - using data_type = IdentID; + using data_type = IdentifierID; using data_type_ref = data_type; using hash_value_type = unsigned; @@ -3775,7 +3775,7 @@ public: } std::pair - EmitKeyDataLength(raw_ostream &Out, const IdentifierInfo *II, IdentID ID) { + EmitKeyDataLength(raw_ostream &Out, const IdentifierInfo *II, IdentifierID ID) { // Record the location of the identifier data. This is used when generating // the mapping from persistent IDs to strings. Writer.SetIdentifierOffset(II, Out.tell()); @@ -3807,7 +3807,7 @@ public: Out.write(II->getNameStart(), KeyLen); } - void EmitData(raw_ostream &Out, const IdentifierInfo *II, IdentID ID, + void EmitData(raw_ostream &Out, const IdentifierInfo *II, IdentifierID ID, unsigned) { using namespace llvm::support; @@ -3891,7 +3891,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, IdentifierOffsets.resize(NextIdentID - FirstIdentID); for (auto IdentIDPair : IdentifierIDs) { const IdentifierInfo *II = IdentIDPair.first; - IdentID ID = IdentIDPair.second; + IdentifierID ID = IdentIDPair.second; assert(II && "NULL identifier in identifier table"); // Write out identifiers if either the ID is local or the identifier has @@ -4779,7 +4779,7 @@ void ASTWriter::AddVersionTuple(const VersionTuple &Version, /// Note that the identifier II occurs at the given offset /// within the identifier table. void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { - IdentID ID = IdentifierIDs[II]; + IdentifierID ID = IdentifierIDs[II]; // Only store offsets new to this AST file. Other identifier names are looked // up earlier in the chain and thus don't need an offset. if (ID >= FirstIdentID) @@ -5945,11 +5945,11 @@ void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Recor Record.push_back(getIdentifierRef(II)); } -IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { +IdentifierID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { if (!II) return 0; - IdentID &ID = IdentifierIDs[II]; + IdentifierID &ID = IdentifierIDs[II]; if (ID == 0) ID = NextIdentID++; return ID; @@ -6610,9 +6610,9 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { NextSubmoduleID = FirstSubmoduleID; } -void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { +void ASTWriter::IdentifierRead(IdentifierID ID, IdentifierInfo *II) { // Always keep the highest ID. See \p TypeRead() for more information. - IdentID &StoredID = IdentifierIDs[II]; + IdentifierID &StoredID = IdentifierIDs[II]; if (ID > StoredID) StoredID = ID; } -- GitLab From f841ca0c355ae53c96f615996d0aff4648da8618 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sun, 12 May 2024 23:08:40 -0700 Subject: [PATCH 016/578] Use StringRef::operator== instead of StringRef::equals (NFC) (#91864) I'm planning to remove StringRef::equals in favor of StringRef::operator==. - StringRef::operator==/!= outnumber StringRef::equals by a factor of 276 under llvm-project/ in terms of their usage. - The elimination of StringRef::equals brings StringRef closer to std::string_view, which has operator== but not equals. - S == "foo" is more readable than S.equals("foo"), especially for !Long.Expression.equals("str") vs Long.Expression != "str". --- bolt/lib/Profile/DataAggregator.cpp | 2 +- bolt/lib/Profile/DataReader.cpp | 3 +-- bolt/lib/Rewrite/DWARFRewriter.cpp | 10 +++++----- bolt/lib/Rewrite/SDTRewriter.cpp | 2 +- clang-tools-extra/clang-tidy/ClangTidyCheck.cpp | 2 +- .../bugprone/ForwardingReferenceOverloadCheck.cpp | 4 ++-- .../clang-tidy/modernize/LoopConvertCheck.cpp | 2 +- .../clang-tidy/readability/IdentifierNamingCheck.cpp | 2 +- .../readability/SuspiciousCallArgumentCheck.cpp | 4 ++-- clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp | 3 +-- .../clang-tidy/utils/RenamerClangTidyCheck.cpp | 2 +- flang/lib/Frontend/CompilerInvocation.cpp | 4 ++-- flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 2 +- flang/lib/Optimizer/CodeGen/CodeGen.cpp | 8 ++++---- lld/COFF/DebugTypes.cpp | 2 +- lld/ELF/InputSection.cpp | 2 +- lld/ELF/Writer.cpp | 2 +- lld/MachO/Driver.cpp | 2 +- lld/wasm/InputChunks.cpp | 4 ++-- 19 files changed, 30 insertions(+), 32 deletions(-) diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index 9a71e227f233..302bcf1f2d87 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -2000,7 +2000,7 @@ std::error_code DataAggregator::parseMMapEvents() { std::pair FileMMapInfo = FileMMapInfoRes.get(); if (FileMMapInfo.second.PID == -1) continue; - if (FileMMapInfo.first.equals("(deleted)")) + if (FileMMapInfo.first == "(deleted)") continue; // Consider only the first mapping of the file for any given PID diff --git a/bolt/lib/Profile/DataReader.cpp b/bolt/lib/Profile/DataReader.cpp index 67f357fe4d3f..b2511ba10399 100644 --- a/bolt/lib/Profile/DataReader.cpp +++ b/bolt/lib/Profile/DataReader.cpp @@ -1205,8 +1205,7 @@ std::error_code DataReader::parse() { // Add entry data for branches to another function or branches // to entry points (including recursive calls) - if (BI.To.IsSymbol && - (!BI.From.Name.equals(BI.To.Name) || BI.To.Offset == 0)) { + if (BI.To.IsSymbol && (BI.From.Name != BI.To.Name || BI.To.Offset == 0)) { I = GetOrCreateFuncEntry(BI.To.Name); I->second.EntryData.emplace_back(std::move(BI)); } diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index 26e4889faada..9d4297f913f3 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -1550,7 +1550,7 @@ CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder, for (const SectionRef &Section : Obj->sections()) { StringRef Contents = cantFail(Section.getContents()); StringRef Name = cantFail(Section.getName()); - if (Name.equals(".debug_types")) + if (Name == ".debug_types") BC.registerOrUpdateNoteSection(".debug_types", copyByteArray(Contents), Contents.size()); } @@ -1633,10 +1633,10 @@ void DWARFRewriter::finalizeDebugSections( for (const SectionRef &Secs : Obj->sections()) { StringRef Contents = cantFail(Secs.getContents()); StringRef Name = cantFail(Secs.getName()); - if (Name.equals(".debug_abbrev")) { + if (Name == ".debug_abbrev") { BC.registerOrUpdateNoteSection(".debug_abbrev", copyByteArray(Contents), Contents.size()); - } else if (Name.equals(".debug_info")) { + } else if (Name == ".debug_info") { BC.registerOrUpdateNoteSection(".debug_info", copyByteArray(Contents), Contents.size()); } @@ -1771,7 +1771,7 @@ std::optional updateDebugData( }; switch (SectionIter->second.second) { default: { - if (!SectionName.equals("debug_str.dwo")) + if (SectionName != "debug_str.dwo") errs() << "BOLT-WARNING: unsupported debug section: " << SectionName << "\n"; return SectionContents; @@ -1959,7 +1959,7 @@ void DWARFRewriter::updateDWP(DWARFUnit &CU, continue; } - if (SectionName.equals("debug_str.dwo")) { + if (SectionName == "debug_str.dwo") { CurStrSection = OutData; } else { // Since handleDebugDataPatching returned true, we already know this is diff --git a/bolt/lib/Rewrite/SDTRewriter.cpp b/bolt/lib/Rewrite/SDTRewriter.cpp index cc663b28990f..a3928c554ad6 100644 --- a/bolt/lib/Rewrite/SDTRewriter.cpp +++ b/bolt/lib/Rewrite/SDTRewriter.cpp @@ -87,7 +87,7 @@ void SDTRewriter::readSection() { StringRef Name = DE.getCStr(&Offset); - if (!Name.equals("stapsdt")) + if (Name != "stapsdt") errs() << "BOLT-WARNING: SDT note name \"" << Name << "\" is not expected\n"; diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp index 710b361e16c0..6028bb225813 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp @@ -171,7 +171,7 @@ std::optional ClangTidyCheck::OptionsView::getEnumInt( if (IgnoreCase) { if (Value.equals_insensitive(NameAndEnum.second)) return NameAndEnum.first; - } else if (Value.equals(NameAndEnum.second)) { + } else if (Value == NameAndEnum.second) { return NameAndEnum.first; } else if (Value.equals_insensitive(NameAndEnum.second)) { Closest = NameAndEnum.second; diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp index e7be8134781e..36687a8e761e 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp @@ -25,8 +25,8 @@ AST_MATCHER(QualType, isEnableIf) { const NamedDecl *TypeDecl = Spec->getTemplateName().getAsTemplateDecl()->getTemplatedDecl(); return TypeDecl->isInStdNamespace() && - (TypeDecl->getName().equals("enable_if") || - TypeDecl->getName().equals("enable_if_t")); + (TypeDecl->getName() == "enable_if" || + TypeDecl->getName() == "enable_if_t"); }; const Type *BaseType = Node.getTypePtr(); // Case: pointer or reference to enable_if. diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp index 3229e302eb43..a1786ba5acfd 100644 --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp @@ -421,7 +421,7 @@ getContainerFromBeginEndCall(const Expr *Init, bool IsBegin, bool *IsArrow, return {}; if (IsReverse && !Call->Name.consume_back("r")) return {}; - if (!Call->Name.empty() && !Call->Name.equals("c")) + if (!Call->Name.empty() && Call->Name != "c") return {}; return std::make_pair(Call->Container, Call->CallKind); } diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index 27a12bfc5806..c3208392df15 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -1358,7 +1358,7 @@ IdentifierNamingCheck::getFailureInfo( std::replace(KindName.begin(), KindName.end(), '_', ' '); std::string Fixup = fixupWithStyle(Type, Name, Style, HNOption, ND); - if (StringRef(Fixup).equals(Name)) { + if (StringRef(Fixup) == Name) { if (!IgnoreFailedSplit) { LLVM_DEBUG(Location.print(llvm::dbgs(), SM); llvm::dbgs() diff --git a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp index 3eb80019ae75..18420d0c8488 100644 --- a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp @@ -138,11 +138,11 @@ static bool applyAbbreviationHeuristic( const llvm::StringMap &AbbreviationDictionary, StringRef Arg, StringRef Param) { if (AbbreviationDictionary.contains(Arg) && - Param.equals(AbbreviationDictionary.lookup(Arg))) + Param == AbbreviationDictionary.lookup(Arg)) return true; if (AbbreviationDictionary.contains(Param) && - Arg.equals(AbbreviationDictionary.lookup(Param))) + Arg == AbbreviationDictionary.lookup(Param)) return true; return false; diff --git a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp index a44720c47eca..0fa54b3847eb 100644 --- a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp +++ b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp @@ -88,8 +88,7 @@ determineIncludeKind(StringRef CanonicalFile, StringRef IncludeFile, if (FileCopy.consume_front(Parts.first) && FileCopy.consume_back(Parts.second)) { // Determine the kind of this inclusion. - if (FileCopy.equals("/internal/") || - FileCopy.equals("/proto/")) { + if (FileCopy == "/internal/" || FileCopy == "/proto/") { return IncludeSorter::IK_MainTUInclude; } } diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp index f5ed61736540..e811f5519de2 100644 --- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp @@ -86,7 +86,7 @@ static const NamedDecl *findDecl(const RecordDecl &RecDecl, StringRef DeclName) { for (const Decl *D : RecDecl.decls()) { if (const auto *ND = dyn_cast(D)) { - if (ND->getDeclName().isIdentifier() && ND->getName().equals(DeclName)) + if (ND->getDeclName().isIdentifier() && ND->getName() == DeclName) return ND; } } diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 4318286e7415..db7fd3cccc7a 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -883,7 +883,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, // -x cuda auto language = args.getLastArgValue(clang::driver::options::OPT_x); - if (language.equals("cuda")) { + if (language == "cuda") { res.getFrontendOpts().features.Enable( Fortran::common::LanguageFeature::CUDA); } @@ -986,7 +986,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, if (args.hasArg(clang::driver::options::OPT_std_EQ)) { auto standard = args.getLastArgValue(clang::driver::options::OPT_std_EQ); // We only allow f2018 as the given standard - if (standard.equals("f2018")) { + if (standard == "f2018") { res.setEnableConformanceChecks(); } else { const unsigned diagID = diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index dcbbc39b84ea..58064d23eb08 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -1607,7 +1607,7 @@ static bool isIntrinsicModuleProcedure(llvm::StringRef name) { static bool isCoarrayIntrinsic(llvm::StringRef name) { return name.starts_with("atomic_") || name.starts_with("co_") || name.contains("image") || name.ends_with("cobound") || - name.equals("team_number"); + name == "team_number"; } /// Return the generic name of an intrinsic module procedure specific name. diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index b4705aa47992..21154902d23f 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -3497,7 +3497,7 @@ public: rewriter.startOpModification(op); auto callee = op.getCallee(); if (callee) - if (callee->equals("hypotf")) + if (*callee == "hypotf") op.setCalleeAttr(mlir::SymbolRefAttr::get(op.getContext(), "_hypotf")); rewriter.finalizeOpModification(op); @@ -3514,7 +3514,7 @@ public: matchAndRewrite(mlir::LLVM::LLVMFuncOp op, mlir::PatternRewriter &rewriter) const override { rewriter.startOpModification(op); - if (op.getSymName().equals("hypotf")) + if (op.getSymName() == "hypotf") op.setSymNameAttr(rewriter.getStringAttr("_hypotf")); rewriter.finalizeOpModification(op); return mlir::success(); @@ -3629,11 +3629,11 @@ public: auto callee = op.getCallee(); if (!callee) return true; - return !callee->equals("hypotf"); + return *callee != "hypotf"; }); target.addDynamicallyLegalOp( [](mlir::LLVM::LLVMFuncOp op) { - return !op.getSymName().equals("hypotf"); + return op.getSymName() != "hypotf"; }); } diff --git a/lld/COFF/DebugTypes.cpp b/lld/COFF/DebugTypes.cpp index a4c808e4c9a0..7689ad163a65 100644 --- a/lld/COFF/DebugTypes.cpp +++ b/lld/COFF/DebugTypes.cpp @@ -465,7 +465,7 @@ static bool equalsPath(StringRef path1, StringRef path2) { #if defined(_WIN32) return path1.equals_insensitive(path2); #else - return path1.equals(path2); + return path1 == path2; #endif } diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index fa48552b8f7a..fa81611e7c9e 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -1128,7 +1128,7 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *buf, for (Relocation &rel : relocs()) { // Ignore calls into the split-stack api. if (rel.sym->getName().starts_with("__morestack")) { - if (rel.sym->getName().equals("__morestack")) + if (rel.sym->getName() == "__morestack") morestackCalls.push_back(&rel); continue; } diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 240c16a4d8f6..e400ed2ae945 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -577,7 +577,7 @@ static bool isRelroSection(const OutputSection *sec) { // for accessing .got as well, .got and .toc need to be close enough in the // virtual address space. Usually, .toc comes just after .got. Since we place // .got into RELRO, .toc needs to be placed into RELRO too. - if (sec->name.equals(".toc")) + if (sec->name == ".toc") return true; // .got.plt contains pointers to external function symbols. They are diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index 65de531db04b..d4d8d53d69ee 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1507,7 +1507,7 @@ bool link(ArrayRef argsArr, llvm::raw_ostream &stdoutOS, StringRef sep = sys::path::get_separator(); // real_path removes trailing slashes as part of the normalization, but // these are meaningful for our text based stripping - if (config->osoPrefix.equals(".") || config->osoPrefix.ends_with(sep)) + if (config->osoPrefix == "." || config->osoPrefix.ends_with(sep)) expanded += sep; config->osoPrefix = saver().save(expanded.str()); } diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp index 2074dd59c1dd..975225974aff 100644 --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -519,8 +519,8 @@ uint64_t InputSection::getTombstoneForSection(StringRef name) { // If they occur in DWARF debug symbols, we want to change the pc of the // function to -1 to avoid overlapping with a valid range. However for the // debug_ranges and debug_loc sections that would conflict with the existing - // meaning of -1 so we use -2. - if (name.equals(".debug_ranges") || name.equals(".debug_loc")) + // meaning of -1 so we use -2. + if (name == ".debug_ranges" || name == ".debug_loc") return UINT64_C(-2); if (name.starts_with(".debug_")) return UINT64_C(-1); -- GitLab From 1fadb2b0c881ced247931f442fdee6c4ed96dccb Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 12 May 2024 23:06:06 -0700 Subject: [PATCH 017/578] Revert "[clang-format] Fix FormatToken::isSimpleTypeSpecifier() (#91712)" This reverts commits e62ce1f8842c, 5cd280433e8e, and de641e289269 due to buildbot failures. --- clang/lib/Format/Format.cpp | 3 +- clang/lib/Format/FormatToken.cpp | 46 +++++++++- clang/lib/Format/FormatToken.h | 8 +- clang/lib/Format/FormatTokenLexer.cpp | 1 + clang/lib/Format/QualifierAlignmentFixer.cpp | 24 ++--- clang/lib/Format/QualifierAlignmentFixer.h | 5 +- clang/lib/Format/TokenAnalyzer.cpp | 4 +- clang/lib/Format/TokenAnalyzer.h | 1 - clang/lib/Format/TokenAnnotator.cpp | 43 ++++----- clang/lib/Format/TokenAnnotator.h | 6 +- clang/lib/Format/UnwrappedLineParser.cpp | 19 ++-- clang/lib/Format/UnwrappedLineParser.h | 1 - clang/unittests/Format/QualifierFixerTest.cpp | 92 ++++++++----------- 13 files changed, 134 insertions(+), 119 deletions(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 52005a6c881f..8f027ffa20cc 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -3858,7 +3858,8 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) { LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11; LangOpts.LineComment = 1; - LangOpts.CXXOperatorNames = Style.isCpp(); + bool AlternativeOperators = Style.isCpp(); + LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; LangOpts.Bool = 1; LangOpts.ObjC = 1; LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp index 85bec71ffbbc..4fb70ffac706 100644 --- a/clang/lib/Format/FormatToken.cpp +++ b/clang/lib/Format/FormatToken.cpp @@ -34,6 +34,43 @@ const char *getTokenTypeName(TokenType Type) { return nullptr; } +// FIXME: This is copy&pasted from Sema. Put it in a common place and remove +// duplication. +bool FormatToken::isSimpleTypeSpecifier() const { + switch (Tok.getKind()) { + case tok::kw_short: + case tok::kw_long: + case tok::kw___int64: + case tok::kw___int128: + case tok::kw_signed: + case tok::kw_unsigned: + case tok::kw_void: + case tok::kw_char: + case tok::kw_int: + case tok::kw_half: + case tok::kw_float: + case tok::kw_double: + case tok::kw___bf16: + case tok::kw__Float16: + case tok::kw___float128: + case tok::kw___ibm128: + case tok::kw_wchar_t: + case tok::kw_bool: +#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: +#include "clang/Basic/TransformTypeTraits.def" + case tok::annot_typename: + case tok::kw_char8_t: + case tok::kw_char16_t: + case tok::kw_char32_t: + case tok::kw_typeof: + case tok::kw_decltype: + case tok::kw__Atomic: + return true; + default: + return false; + } +} + // Sorted common C++ non-keyword types. static SmallVector CppNonKeywordTypes = { "clock_t", "int16_t", "int32_t", "int64_t", "int8_t", @@ -41,16 +78,15 @@ static SmallVector CppNonKeywordTypes = { "uint32_t", "uint64_t", "uint8_t", "uintptr_t", }; -bool FormatToken::isTypeName(const LangOptions &LangOpts) const { - const bool IsCpp = LangOpts.CXXOperatorNames; - return is(TT_TypeName) || Tok.isSimpleTypeSpecifier(LangOpts) || +bool FormatToken::isTypeName(bool IsCpp) const { + return is(TT_TypeName) || isSimpleTypeSpecifier() || (IsCpp && is(tok::identifier) && std::binary_search(CppNonKeywordTypes.begin(), CppNonKeywordTypes.end(), TokenText)); } -bool FormatToken::isTypeOrIdentifier(const LangOptions &LangOpts) const { - return isTypeName(LangOpts) || isOneOf(tok::kw_auto, tok::identifier); +bool FormatToken::isTypeOrIdentifier(bool IsCpp) const { + return isTypeName(IsCpp) || isOneOf(tok::kw_auto, tok::identifier); } bool FormatToken::isBlockIndentedInitRBrace(const FormatStyle &Style) const { diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 8792f4c75074..95f16fde5005 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -684,8 +684,12 @@ public: isAttribute(); } - [[nodiscard]] bool isTypeName(const LangOptions &LangOpts) const; - [[nodiscard]] bool isTypeOrIdentifier(const LangOptions &LangOpts) const; + /// Determine whether the token is a simple-type-specifier. + [[nodiscard]] bool isSimpleTypeSpecifier() const; + + [[nodiscard]] bool isTypeName(bool IsCpp) const; + + [[nodiscard]] bool isTypeOrIdentifier(bool IsCpp) const; bool isObjCAccessSpecifier() const { return is(tok::at) && Next && diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index e21b5a882b77..f430d3764bab 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -1442,6 +1442,7 @@ void FormatTokenLexer::readRawToken(FormatToken &Tok) { void FormatTokenLexer::resetLexer(unsigned Offset) { StringRef Buffer = SourceMgr.getBufferData(ID); + LangOpts = getFormattingLangOpts(Style); Lex.reset(new Lexer(SourceMgr.getLocForStartOfFile(ID), LangOpts, Buffer.begin(), Buffer.begin() + Offset, Buffer.end())); Lex->SetKeepWhitespaceMode(true); diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp index a904f0b773c6..c26353045672 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.cpp +++ b/clang/lib/Format/QualifierAlignmentFixer.cpp @@ -268,11 +268,13 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( if (isPossibleMacro(TypeToken)) return Tok; + const bool IsCpp = Style.isCpp(); + // The case `const long long int volatile` -> `long long int const volatile` // The case `long const long int volatile` -> `long long int const volatile` // The case `long long volatile int const` -> `long long int const volatile` // The case `const long long volatile int` -> `long long int const volatile` - if (TypeToken->isTypeName(LangOpts)) { + if (TypeToken->isTypeName(IsCpp)) { // The case `const decltype(foo)` -> `const decltype(foo)` // The case `const typeof(foo)` -> `const typeof(foo)` // The case `const _Atomic(foo)` -> `const _Atomic(foo)` @@ -281,7 +283,7 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( const FormatToken *LastSimpleTypeSpecifier = TypeToken; while (isQualifierOrType(LastSimpleTypeSpecifier->getNextNonComment(), - LangOpts)) { + IsCpp)) { LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment(); } @@ -293,7 +295,7 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( // The case `unsigned short const` -> `unsigned short const` // The case: // `unsigned short volatile const` -> `unsigned short const volatile` - if (PreviousCheck && PreviousCheck->isTypeName(LangOpts)) { + if (PreviousCheck && PreviousCheck->isTypeName(IsCpp)) { if (LastQual != Tok) rotateTokens(SourceMgr, Fixes, Tok, LastQual, /*Left=*/false); return Tok; @@ -410,11 +412,11 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft( // The case `volatile long long const int` -> `const volatile long long int` // The case `const long long volatile int` -> `const volatile long long int` // The case `long volatile long int const` -> `const volatile long long int` - if (TypeToken->isTypeName(LangOpts)) { + if (const bool IsCpp = Style.isCpp(); TypeToken->isTypeName(IsCpp)) { const FormatToken *LastSimpleTypeSpecifier = TypeToken; while (isConfiguredQualifierOrType( LastSimpleTypeSpecifier->getPreviousNonComment(), - ConfiguredQualifierTokens, LangOpts)) { + ConfiguredQualifierTokens, IsCpp)) { LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getPreviousNonComment(); } @@ -612,16 +614,16 @@ void prepareLeftRightOrderingForQualifierAlignmentFixer( } } -bool LeftRightQualifierAlignmentFixer::isQualifierOrType( - const FormatToken *Tok, const LangOptions &LangOpts) { - return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) || - isQualifier(Tok)); +bool LeftRightQualifierAlignmentFixer::isQualifierOrType(const FormatToken *Tok, + bool IsCpp) { + return Tok && + (Tok->isTypeName(IsCpp) || Tok->is(tok::kw_auto) || isQualifier(Tok)); } bool LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( const FormatToken *Tok, const std::vector &Qualifiers, - const LangOptions &LangOpts) { - return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) || + bool IsCpp) { + return Tok && (Tok->isTypeName(IsCpp) || Tok->is(tok::kw_auto) || isConfiguredQualifier(Tok, Qualifiers)); } diff --git a/clang/lib/Format/QualifierAlignmentFixer.h b/clang/lib/Format/QualifierAlignmentFixer.h index 710fa2dc0030..e1cc27e62b13 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.h +++ b/clang/lib/Format/QualifierAlignmentFixer.h @@ -71,12 +71,11 @@ public: tok::TokenKind QualifierType); // Is the Token a simple or qualifier type - static bool isQualifierOrType(const FormatToken *Tok, - const LangOptions &LangOpts); + static bool isQualifierOrType(const FormatToken *Tok, bool IsCpp = true); static bool isConfiguredQualifierOrType(const FormatToken *Tok, const std::vector &Qualifiers, - const LangOptions &LangOpts); + bool IsCpp = true); // Is the Token likely a Macro static bool isPossibleMacro(const FormatToken *Tok); diff --git a/clang/lib/Format/TokenAnalyzer.cpp b/clang/lib/Format/TokenAnalyzer.cpp index 804a2b0f5e8c..bd648c430f9b 100644 --- a/clang/lib/Format/TokenAnalyzer.cpp +++ b/clang/lib/Format/TokenAnalyzer.cpp @@ -84,7 +84,7 @@ Environment::Environment(StringRef Code, StringRef FileName, NextStartColumn(NextStartColumn), LastStartColumn(LastStartColumn) {} TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style) - : Style(Style), LangOpts(getFormattingLangOpts(Style)), Env(Env), + : Style(Style), Env(Env), AffectedRangeMgr(Env.getSourceManager(), Env.getCharRanges()), UnwrappedLines(1), Encoding(encoding::detectEncoding( @@ -101,7 +101,7 @@ std::pair TokenAnalyzer::process(bool SkipAnnotation) { tooling::Replacements Result; llvm::SpecificBumpPtrAllocator Allocator; - IdentifierTable IdentTable(LangOpts); + IdentifierTable IdentTable(getFormattingLangOpts(Style)); FormatTokenLexer Lex(Env.getSourceManager(), Env.getFileID(), Env.getFirstStartColumn(), Style, Encoding, Allocator, IdentTable); diff --git a/clang/lib/Format/TokenAnalyzer.h b/clang/lib/Format/TokenAnalyzer.h index ef559099d325..b7494c395c8a 100644 --- a/clang/lib/Format/TokenAnalyzer.h +++ b/clang/lib/Format/TokenAnalyzer.h @@ -92,7 +92,6 @@ protected: void finishRun() override; FormatStyle Style; - LangOptions LangOpts; // Stores Style, FileID and SourceManager etc. const Environment &Env; // AffectedRangeMgr stores ranges to be fixed. diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 478cae23d3c8..e935d3e2709c 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -126,9 +126,7 @@ public: const AdditionalKeywords &Keywords, SmallVector &Scopes) : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false), - IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)), - Keywords(Keywords), Scopes(Scopes) { - assert(IsCpp == LangOpts.CXXOperatorNames); + IsCpp(Style.isCpp()), Keywords(Keywords), Scopes(Scopes) { Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false)); resetTokenMetadata(); } @@ -564,7 +562,7 @@ private: (CurrentToken->is(tok::l_paren) && CurrentToken->Next && CurrentToken->Next->isOneOf(tok::star, tok::amp, tok::caret)); if ((CurrentToken->Previous->isOneOf(tok::kw_const, tok::kw_auto) || - CurrentToken->Previous->isTypeName(LangOpts)) && + CurrentToken->Previous->isTypeName(IsCpp)) && !(CurrentToken->is(tok::l_brace) || (CurrentToken->is(tok::l_paren) && !ProbablyFunctionTypeLParen))) { Contexts.back().IsExpression = false; @@ -2626,7 +2624,7 @@ private: return true; // MyClass a; - if (PreviousNotConst->isTypeName(LangOpts)) + if (PreviousNotConst->isTypeName(IsCpp)) return true; // type[] a in Java @@ -2730,7 +2728,7 @@ private: } if (Tok.Next->is(tok::question) || - (Tok.Next->is(tok::ampamp) && !Tok.Previous->isTypeName(LangOpts))) { + (Tok.Next->is(tok::ampamp) && !Tok.Previous->isTypeName(IsCpp))) { return false; } @@ -2759,10 +2757,9 @@ private: } // Heuristically try to determine whether the parentheses contain a type. - auto IsQualifiedPointerOrReference = [](FormatToken *T, - const LangOptions &LangOpts) { + auto IsQualifiedPointerOrReference = [](FormatToken *T, bool IsCpp) { // This is used to handle cases such as x = (foo *const)&y; - assert(!T->isTypeName(LangOpts) && "Should have already been checked"); + assert(!T->isTypeName(IsCpp) && "Should have already been checked"); // Strip trailing qualifiers such as const or volatile when checking // whether the parens could be a cast to a pointer/reference type. while (T) { @@ -2794,8 +2791,8 @@ private: bool ParensAreType = !Tok.Previous || Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || - Tok.Previous->isTypeName(LangOpts) || - IsQualifiedPointerOrReference(Tok.Previous, LangOpts); + Tok.Previous->isTypeName(IsCpp) || + IsQualifiedPointerOrReference(Tok.Previous, IsCpp); bool ParensCouldEndDecl = Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater); if (ParensAreType && !ParensCouldEndDecl) @@ -3068,7 +3065,6 @@ private: FormatToken *CurrentToken; bool AutoFound; bool IsCpp; - LangOptions LangOpts; const AdditionalKeywords &Keywords; SmallVector &Scopes; @@ -3643,8 +3639,7 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) { // This function heuristically determines whether 'Current' starts the name of a // function declaration. -static bool isFunctionDeclarationName(const LangOptions &LangOpts, - const FormatToken &Current, +static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, const AnnotatedLine &Line, FormatToken *&ClosingParen) { assert(Current.Previous); @@ -3663,7 +3658,7 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts, } auto skipOperatorName = - [&LangOpts](const FormatToken *Next) -> const FormatToken * { + [IsCpp](const FormatToken *Next) -> const FormatToken * { for (; Next; Next = Next->Next) { if (Next->is(TT_OverloadedOperatorLParen)) return Next; @@ -3682,7 +3677,7 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts, Next = Next->Next; continue; } - if ((Next->isTypeName(LangOpts) || Next->is(tok::identifier)) && + if ((Next->isTypeName(IsCpp) || Next->is(tok::identifier)) && Next->Next && Next->Next->isPointerOrReference()) { // For operator void*(), operator char*(), operator Foo*(). Next = Next->Next; @@ -3698,10 +3693,8 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts, return nullptr; }; - const auto *Next = Current.Next; - const bool IsCpp = LangOpts.CXXOperatorNames; - // Find parentheses of parameter list. + const FormatToken *Next = Current.Next; if (Current.is(tok::kw_operator)) { if (Previous.Tok.getIdentifierInfo() && !Previous.isOneOf(tok::kw_return, tok::kw_co_return)) { @@ -3781,7 +3774,7 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts, Tok = Tok->MatchingParen; continue; } - if (Tok->is(tok::kw_const) || Tok->isTypeName(LangOpts) || + if (Tok->is(tok::kw_const) || Tok->isTypeName(IsCpp) || Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) { return true; } @@ -3844,7 +3837,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { AfterLastAttribute = Tok; if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName); IsCtorOrDtor || - isFunctionDeclarationName(LangOpts, *Tok, Line, ClosingParen)) { + isFunctionDeclarationName(IsCpp, *Tok, Line, ClosingParen)) { if (!IsCtorOrDtor) Tok->setFinalizedType(TT_FunctionDeclarationName); LineIsFunctionDeclaration = true; @@ -4454,7 +4447,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Left.Tok.isLiteral()) return true; // for (auto a = 0, b = 0; const auto & c : {1, 2, 3}) - if (Left.isTypeOrIdentifier(LangOpts) && Right.Next && Right.Next->Next && + if (Left.isTypeOrIdentifier(IsCpp) && Right.Next && Right.Next->Next && Right.Next->Next->is(TT_RangeBasedForLoopColon)) { return getTokenPointerOrReferenceAlignment(Right) != FormatStyle::PAS_Left; @@ -4497,7 +4490,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Right.is(tok::l_brace) && Right.is(BK_Block)) return true; // for (auto a = 0, b = 0; const auto& c : {1, 2, 3}) - if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(LangOpts) && Right.Next && + if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(IsCpp) && Right.Next && Right.Next->is(TT_RangeBasedForLoopColon)) { return getTokenPointerOrReferenceAlignment(Left) != FormatStyle::PAS_Right; @@ -4541,7 +4534,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Right.isPointerOrReference()) { const FormatToken *Previous = &Left; while (Previous && Previous->isNot(tok::kw_operator)) { - if (Previous->is(tok::identifier) || Previous->isTypeName(LangOpts)) { + if (Previous->is(tok::identifier) || Previous->isTypeName(IsCpp)) { Previous = Previous->getPreviousNonComment(); continue; } @@ -4730,7 +4723,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (!Style.isVerilog() && (Left.isOneOf(tok::identifier, tok::greater, tok::r_square, tok::r_paren) || - Left.isTypeName(LangOpts)) && + Left.isTypeName(IsCpp)) && Right.is(tok::l_brace) && Right.getNextNonComment() && Right.isNot(BK_Block)) { return false; diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index d19d3d061e40..25a24dccb1b8 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -211,10 +211,7 @@ private: class TokenAnnotator { public: TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords) - : Style(Style), IsCpp(Style.isCpp()), - LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords) { - assert(IsCpp == LangOpts.CXXOperatorNames); - } + : Style(Style), IsCpp(Style.isCpp()), Keywords(Keywords) {} /// Adapts the indent levels of comment lines to the indent of the /// subsequent line. @@ -263,7 +260,6 @@ private: const FormatStyle &Style; bool IsCpp; - LangOptions LangOpts; const AdditionalKeywords &Keywords; diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 4f1c2c5114e9..310b75485e08 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -160,16 +160,13 @@ UnwrappedLineParser::UnwrappedLineParser( IdentifierTable &IdentTable) : Line(new UnwrappedLine), MustBreakBeforeNextToken(false), CurrentLines(&Lines), Style(Style), IsCpp(Style.isCpp()), - LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords), - CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr), - Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1), + Keywords(Keywords), CommentPragmasRegex(Style.CommentPragmas), + Tokens(nullptr), Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1), IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None ? IG_Rejected : IG_Inited), IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn), - Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) { - assert(IsCpp == LangOpts.CXXOperatorNames); -} + Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {} void UnwrappedLineParser::reset() { PPBranchLevel = -1; @@ -1873,7 +1870,7 @@ void UnwrappedLineParser::parseStructuralElement( case tok::caret: nextToken(); // Block return type. - if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) { + if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(IsCpp)) { nextToken(); // Return types: pointers are ok too. while (FormatTok->is(tok::star)) @@ -2234,7 +2231,7 @@ bool UnwrappedLineParser::tryToParseLambda() { bool InTemplateParameterList = false; while (FormatTok->isNot(tok::l_brace)) { - if (FormatTok->isTypeName(LangOpts)) { + if (FormatTok->isTypeName(IsCpp)) { nextToken(); continue; } @@ -3451,7 +3448,7 @@ bool UnwrappedLineParser::parseRequires() { break; } default: - if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) { + if (PreviousNonComment->isTypeOrIdentifier(IsCpp)) { // This is a requires clause. parseRequiresClause(RequiresToken); return true; @@ -3514,7 +3511,7 @@ bool UnwrappedLineParser::parseRequires() { --OpenAngles; break; default: - if (NextToken->isTypeName(LangOpts)) { + if (NextToken->isTypeName(IsCpp)) { FormatTok = Tokens->setPosition(StoredPosition); parseRequiresExpression(RequiresToken); return false; @@ -4030,7 +4027,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { if (FormatTok->is(tok::l_square)) { FormatToken *Previous = FormatTok->Previous; if (!Previous || (Previous->isNot(tok::r_paren) && - !Previous->isTypeOrIdentifier(LangOpts))) { + !Previous->isTypeOrIdentifier(IsCpp))) { // Don't try parsing a lambda if we had a closing parenthesis before, // it was probably a pointer to an array: int (*)[]. if (!tryToParseLambda()) diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index d7963a4211bb..2a0fe19d0957 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -316,7 +316,6 @@ private: const FormatStyle &Style; bool IsCpp; - LangOptions LangOpts; const AdditionalKeywords &Keywords; llvm::Regex CommentPragmasRegex; diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index fdc392e5d948..792d8f3c3a98 100644 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -1055,82 +1055,70 @@ TEST_F(QualifierFixerTest, IsQualifierType) { ConfiguredTokens.push_back(tok::kw_constexpr); ConfiguredTokens.push_back(tok::kw_friend); - static const LangOptions LangOpts{getFormattingLangOpts()}; - auto Tokens = annotate( "const static inline auto restrict int double long constexpr friend"); ASSERT_EQ(Tokens.size(), 11u) << Tokens; EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[0], ConfiguredTokens, LangOpts)); + Tokens[0], ConfiguredTokens)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[1], ConfiguredTokens, LangOpts)); + Tokens[1], ConfiguredTokens)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[2], ConfiguredTokens, LangOpts)); + Tokens[2], ConfiguredTokens)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[3], ConfiguredTokens, LangOpts)); + Tokens[3], ConfiguredTokens)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[4], ConfiguredTokens, LangOpts)); + Tokens[4], ConfiguredTokens)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[5], ConfiguredTokens, LangOpts)); + Tokens[5], ConfiguredTokens)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[6], ConfiguredTokens, LangOpts)); + Tokens[6], ConfiguredTokens)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[7], ConfiguredTokens, LangOpts)); + Tokens[7], ConfiguredTokens)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[8], ConfiguredTokens, LangOpts)); + Tokens[8], ConfiguredTokens)); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[9], ConfiguredTokens, LangOpts)); - - EXPECT_TRUE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[0], LangOpts)); - EXPECT_TRUE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[1], LangOpts)); - EXPECT_TRUE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[2], LangOpts)); - EXPECT_TRUE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[3], LangOpts)); - EXPECT_TRUE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[4], LangOpts)); - EXPECT_TRUE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[5], LangOpts)); - EXPECT_TRUE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[6], LangOpts)); - EXPECT_TRUE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[7], LangOpts)); - EXPECT_TRUE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[8], LangOpts)); - EXPECT_TRUE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[9], LangOpts)); + Tokens[9], ConfiguredTokens)); + + EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[0])); + EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[1])); + EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[2])); + EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[3])); + EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[4])); + EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[5])); + EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[6])); + EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[7])); + EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[8])); + EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[9])); auto NotTokens = annotate("for while do Foo Bar "); ASSERT_EQ(NotTokens.size(), 6u) << Tokens; EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[0], ConfiguredTokens, LangOpts)); + NotTokens[0], ConfiguredTokens)); EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[1], ConfiguredTokens, LangOpts)); + NotTokens[1], ConfiguredTokens)); EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[2], ConfiguredTokens, LangOpts)); + NotTokens[2], ConfiguredTokens)); EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[3], ConfiguredTokens, LangOpts)); + NotTokens[3], ConfiguredTokens)); EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[4], ConfiguredTokens, LangOpts)); + NotTokens[4], ConfiguredTokens)); EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[5], ConfiguredTokens, LangOpts)); - - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[0], - LangOpts)); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[1], - LangOpts)); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[2], - LangOpts)); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[3], - LangOpts)); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[4], - LangOpts)); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[5], - LangOpts)); + NotTokens[5], ConfiguredTokens)); + + EXPECT_FALSE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[0])); + EXPECT_FALSE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[1])); + EXPECT_FALSE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[2])); + EXPECT_FALSE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[3])); + EXPECT_FALSE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[4])); + EXPECT_FALSE( + LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[5])); } TEST_F(QualifierFixerTest, IsMacro) { -- GitLab From b5f4210e9f51f938ae517f219f04f9ab431a2684 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 13 May 2024 14:27:59 +0800 Subject: [PATCH 018/578] [InstCombine] Drop nuw flag when CtlzOp is a sub nuw (#91776) See the following case: ``` define i32 @src1(i32 %x) { %dec = sub nuw i32 -2, %x %ctlz = tail call i32 @llvm.ctlz.i32(i32 %dec, i1 false) %sub = sub nsw i32 32, %ctlz %shl = shl i32 1, %sub %ugt = icmp ult i32 %x, -2 %sel = select i1 %ugt, i32 %shl, i32 1 ret i32 %sel } define i32 @tgt1(i32 %x) { %dec = sub nuw i32 -2, %x %ctlz = tail call i32 @llvm.ctlz.i32(i32 %dec, i1 false) %sub = sub nsw i32 32, %ctlz %and = and i32 %sub, 31 %shl = shl nuw i32 1, %and ret i32 %shl } ``` `nuw` in `%dec` should be dropped after the select instruction is eliminated. Alive2: https://alive2.llvm.org/ce/z/7S9529 Fixes https://github.com/llvm/llvm-project/issues/91691. --- .../InstCombine/InstCombineSelect.cpp | 14 ++++++-- llvm/test/Transforms/InstCombine/bit_ceil.ll | 36 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index ee090e012508..a3ddb402bf66 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3343,7 +3343,8 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) { // pattern. static bool isSafeToRemoveBitCeilSelect(ICmpInst::Predicate Pred, Value *Cond0, const APInt *Cond1, Value *CtlzOp, - unsigned BitWidth) { + unsigned BitWidth, + bool &ShouldDropNUW) { // The challenge in recognizing std::bit_ceil(X) is that the operand is used // for the CTLZ proper and select condition, each possibly with some // operation like add and sub. @@ -3366,6 +3367,8 @@ static bool isSafeToRemoveBitCeilSelect(ICmpInst::Predicate Pred, Value *Cond0, ConstantRange CR = ConstantRange::makeExactICmpRegion( CmpInst::getInversePredicate(Pred), *Cond1); + ShouldDropNUW = false; + // Match the operation that's used to compute CtlzOp from CommonAncestor. If // CtlzOp == CommonAncestor, return true as no operation is needed. If a // match is found, execute the operation on CR, update CR, and return true. @@ -3379,6 +3382,7 @@ static bool isSafeToRemoveBitCeilSelect(ICmpInst::Predicate Pred, Value *Cond0, return true; } if (match(CtlzOp, m_Sub(m_APInt(C), m_Specific(CommonAncestor)))) { + ShouldDropNUW = true; CR = ConstantRange(*C).sub(CR); return true; } @@ -3448,14 +3452,20 @@ static Instruction *foldBitCeil(SelectInst &SI, IRBuilderBase &Builder) { Pred = CmpInst::getInversePredicate(Pred); } + bool ShouldDropNUW; + if (!match(FalseVal, m_One()) || !match(TrueVal, m_OneUse(m_Shl(m_One(), m_OneUse(m_Sub(m_SpecificInt(BitWidth), m_Value(Ctlz)))))) || !match(Ctlz, m_Intrinsic(m_Value(CtlzOp), m_Zero())) || - !isSafeToRemoveBitCeilSelect(Pred, Cond0, Cond1, CtlzOp, BitWidth)) + !isSafeToRemoveBitCeilSelect(Pred, Cond0, Cond1, CtlzOp, BitWidth, + ShouldDropNUW)) return nullptr; + if (ShouldDropNUW) + cast(CtlzOp)->setHasNoUnsignedWrap(false); + // Build 1 << (-CTLZ & (BitWidth-1)). The negation likely corresponds to a // single hardware instruction as opposed to BitWidth - CTLZ, where BitWidth // is an integer constant. Masking with BitWidth-1 comes free on some diff --git a/llvm/test/Transforms/InstCombine/bit_ceil.ll b/llvm/test/Transforms/InstCombine/bit_ceil.ll index 16631afa4878..79665be01576 100644 --- a/llvm/test/Transforms/InstCombine/bit_ceil.ll +++ b/llvm/test/Transforms/InstCombine/bit_ceil.ll @@ -284,6 +284,42 @@ define <4 x i32> @bit_ceil_v4i32(<4 x i32> %x) { ret <4 x i32> %sel } +define i32 @pr91691(i32 %0) { +; CHECK-LABEL: @pr91691( +; CHECK-NEXT: [[TMP2:%.*]] = sub i32 -2, [[TMP0:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[TMP2]], i1 false) +; CHECK-NEXT: [[TMP4:%.*]] = sub nsw i32 0, [[TMP3]] +; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 31 +; CHECK-NEXT: [[TMP6:%.*]] = shl nuw i32 1, [[TMP5]] +; CHECK-NEXT: ret i32 [[TMP6]] +; + %2 = sub nuw i32 -2, %0 + %3 = tail call i32 @llvm.ctlz.i32(i32 %2, i1 false) + %4 = sub i32 32, %3 + %5 = shl i32 1, %4 + %6 = icmp ult i32 %0, -2 + %7 = select i1 %6, i32 %5, i32 1 + ret i32 %7 +} + +define i32 @pr91691_keep_nsw(i32 %0) { +; CHECK-LABEL: @pr91691_keep_nsw( +; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 -2, [[TMP0:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[TMP2]], i1 false) +; CHECK-NEXT: [[TMP4:%.*]] = sub nsw i32 0, [[TMP3]] +; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 31 +; CHECK-NEXT: [[TMP6:%.*]] = shl nuw i32 1, [[TMP5]] +; CHECK-NEXT: ret i32 [[TMP6]] +; + %2 = sub nsw i32 -2, %0 + %3 = tail call i32 @llvm.ctlz.i32(i32 %2, i1 false) + %4 = sub i32 32, %3 + %5 = shl i32 1, %4 + %6 = icmp ult i32 %0, -2 + %7 = select i1 %6, i32 %5, i32 1 + ret i32 %7 +} + declare i32 @llvm.ctlz.i32(i32, i1 immarg) declare i64 @llvm.ctlz.i64(i64, i1 immarg) declare <4 x i32> @llvm.ctlz.v4i32(<4 x i32>, i1) -- GitLab From fd4efecac21d92428d2f804f43e85bdfa460bdd5 Mon Sep 17 00:00:00 2001 From: Kai Sasaki Date: Mon, 13 May 2024 15:31:41 +0900 Subject: [PATCH 019/578] [mlir] Fix warning due to non ISO standard __FUNCTION__ usage (#91851) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR fixes the warning message due to the non ISO standard usage of `__FUNCTION__` ``` /home/lewuathe/llvm-project/mlir/test/CAPI/transform_interpreter.c: In function ‘testApplyNamedSequence’: /home/lewuathe/llvm-project/mlir/test/CAPI/transform_interpreter.c:21:27: warning: ISO C does not support ‘__FUNCTION__’ predefined identifier [-Wpedantic] 21 | fprintf(stderr, "%s\n", __FUNCTION__); | ``` As `__FUNCTION__` is another name of `__func__` and it conforms to the specification. We should be able to use `__func__` here. Ref: https://stackoverflow.com/questions/52962812/how-to-silence-gcc-pedantic-wpedantic-warning-regarding-function Compiler ``` Ubuntu clang version 18.1.3 (1) Target: x86_64-pc-linux-gnu ``` --- mlir/test/CAPI/transform_interpreter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/test/CAPI/transform_interpreter.c b/mlir/test/CAPI/transform_interpreter.c index f1ab185e0e21..a849b2f24526 100644 --- a/mlir/test/CAPI/transform_interpreter.c +++ b/mlir/test/CAPI/transform_interpreter.c @@ -18,7 +18,7 @@ #include int testApplyNamedSequence(MlirContext ctx) { - fprintf(stderr, "%s\n", __FUNCTION__); + fprintf(stderr, "%s\n", __func__); const char module[] = "module attributes {transform.with_named_sequence} {" -- GitLab From 5082feabd155a59d7ae0249713def100516b839d Mon Sep 17 00:00:00 2001 From: Alcaro Date: Mon, 13 May 2024 08:33:39 +0200 Subject: [PATCH 020/578] [Documentation][Blocks ABI] Fix typoed integer (#65688) Fix an integer value in the prose to match the rest of the content. --- clang/docs/Block-ABI-Apple.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/Block-ABI-Apple.rst b/clang/docs/Block-ABI-Apple.rst index 68f7a3819ca2..f46f2f991ad7 100644 --- a/clang/docs/Block-ABI-Apple.rst +++ b/clang/docs/Block-ABI-Apple.rst @@ -80,7 +80,7 @@ The following flags bits are in use thusly for a possible ABI.2010.3.16: In 10.6.ABI the (1<<29) was usually set and was always ignored by the runtime - it had been a transitional marker that did not get deleted after the transition. This bit is now paired with (1<<30), and represented as the pair -(3<<30), for the following combinations of valid bit settings, and their +(3<<29), for the following combinations of valid bit settings, and their meanings: .. code-block:: c -- GitLab From 5ca368501ae81ca364f66ee6053aa4f8104fdbdd Mon Sep 17 00:00:00 2001 From: Adrian Kuegel Date: Mon, 13 May 2024 06:44:37 +0000 Subject: [PATCH 021/578] [mlir][Bazel] Update BUILD file for 1337622a492f4e77604b09ac8ff97042e46d8d42 --- 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 6a7bc5c9fea0..6304b7b548d8 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -397,6 +397,7 @@ mlir_c_api_cc_library( name = "CAPIIR", srcs = [ "lib/CAPI/Dialect/Func.cpp", + "lib/CAPI/Dialect/IRDL.cpp", "lib/CAPI/IR/AffineExpr.cpp", "lib/CAPI/IR/AffineMap.cpp", "lib/CAPI/IR/BuiltinAttributes.cpp", @@ -415,6 +416,7 @@ mlir_c_api_cc_library( "include/mlir-c/BuiltinTypes.h", "include/mlir-c/Diagnostics.h", "include/mlir-c/Dialect/Func.h", + "include/mlir-c/Dialect/IRDL.h", "include/mlir-c/ExecutionEngine.h", "include/mlir-c/IR.h", "include/mlir-c/IntegerSet.h", @@ -446,6 +448,7 @@ mlir_c_api_cc_library( ":AsmParser", ":ConversionPassIncGen", ":FuncDialect", + ":IRDLDialect", ":InferTypeOpInterface", ":Parser", ], -- GitLab From baa5beecc04aef9da258e31e4a9de1a27051ee5a Mon Sep 17 00:00:00 2001 From: tyb0807 Date: Mon, 13 May 2024 09:08:04 +0200 Subject: [PATCH 022/578] [NFC] Make NVGPU casing consistent (#91903) --- mlir/lib/Bindings/Python/DialectNVGPU.cpp | 8 ++++---- mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp | 2 +- mlir/lib/Dialect/MemRef/Transforms/FoldMemRefAliasOps.cpp | 6 +++--- mlir/python/CMakeLists.txt | 2 +- mlir/python/mlir/dialects/nvgpu.py | 2 +- mlir/test/lib/Dialect/NVGPU/TestNVGPUTransforms.cpp | 4 ++-- mlir/tools/mlir-opt/mlir-opt.cpp | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/mlir/lib/Bindings/Python/DialectNVGPU.cpp b/mlir/lib/Bindings/Python/DialectNVGPU.cpp index 341e4d55bcf2..754e0a75b0ab 100644 --- a/mlir/lib/Bindings/Python/DialectNVGPU.cpp +++ b/mlir/lib/Bindings/Python/DialectNVGPU.cpp @@ -1,4 +1,4 @@ -//===--- DialectNvgpu.cpp - Pybind module for Nvgpu dialect API support ---===// +//===--- DialectNVGPU.cpp - Pybind module for NVGPU dialect API support ---===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -17,7 +17,7 @@ using namespace mlir; using namespace mlir::python; using namespace mlir::python::adaptors; -static void populateDialectNvgpuSubmodule(const pybind11::module &m) { +static void populateDialectNVGPUSubmodule(const pybind11::module &m) { auto nvgpuTensorMapDescriptorType = mlir_type_subclass( m, "TensorMapDescriptorType", mlirTypeIsANVGPUTensorMapDescriptorType); @@ -34,8 +34,8 @@ static void populateDialectNvgpuSubmodule(const pybind11::module &m) { py::arg("ctx") = py::none()); } -PYBIND11_MODULE(_mlirDialectsNvgpu, m) { +PYBIND11_MODULE(_mlirDialectsNVGPU, m) { m.doc() = "MLIR NVGPU dialect."; - populateDialectNvgpuSubmodule(m); + populateDialectNVGPUSubmodule(m); } diff --git a/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp b/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp index 3f92372d7cea..782cc92f83fe 100644 --- a/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp +++ b/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp @@ -441,7 +441,7 @@ struct PrepareContractToGPUMMA } }; -// Fold transpose op into the transfer read op. Nvgpu mma.sync op only supports +// Fold transpose op into the transfer read op. NVGPU mma.sync op only supports // row-, column-, and row-major layout for matrixA, matrixB, and matrixC, // respectively. We can fold the transpose operation when loading the data from // Shared Memory to registers. diff --git a/mlir/lib/Dialect/MemRef/Transforms/FoldMemRefAliasOps.cpp b/mlir/lib/Dialect/MemRef/Transforms/FoldMemRefAliasOps.cpp index 29a5bc9a7ae5..db085b386483 100644 --- a/mlir/lib/Dialect/MemRef/Transforms/FoldMemRefAliasOps.cpp +++ b/mlir/lib/Dialect/MemRef/Transforms/FoldMemRefAliasOps.cpp @@ -362,7 +362,7 @@ public: /// Folds nvgpu.device_async_copy subviews into the copy itself. This pattern /// is folds subview on src and dst memref of the copy. -class NvgpuAsyncCopyOpSubViewOpFolder final +class NVGPUAsyncCopyOpSubViewOpFolder final : public OpRewritePattern { public: using OpRewritePattern::OpRewritePattern; @@ -694,7 +694,7 @@ LogicalResult StoreOpOfCollapseShapeOpFolder::matchAndRewrite( return success(); } -LogicalResult NvgpuAsyncCopyOpSubViewOpFolder::matchAndRewrite( +LogicalResult NVGPUAsyncCopyOpSubViewOpFolder::matchAndRewrite( nvgpu::DeviceAsyncCopyOp copyOp, PatternRewriter &rewriter) const { LLVM_DEBUG(DBGS() << "copyOp : " << copyOp << "\n"); @@ -769,7 +769,7 @@ void memref::populateFoldMemRefAliasOpPatterns(RewritePatternSet &patterns) { LoadOpOfCollapseShapeOpFolder, StoreOpOfCollapseShapeOpFolder, StoreOpOfCollapseShapeOpFolder, - SubViewOfSubViewFolder, NvgpuAsyncCopyOpSubViewOpFolder>( + SubViewOfSubViewFolder, NVGPUAsyncCopyOpSubViewOpFolder>( patterns.getContext()); } diff --git a/mlir/python/CMakeLists.txt b/mlir/python/CMakeLists.txt index a6c78880c8e7..d8f2d1989fde 100644 --- a/mlir/python/CMakeLists.txt +++ b/mlir/python/CMakeLists.txt @@ -538,7 +538,7 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.Quant.Pybind ) declare_mlir_python_extension(MLIRPythonExtension.Dialects.NVGPU.Pybind - MODULE_NAME _mlirDialectsNvgpu + MODULE_NAME _mlirDialectsNVGPU ADD_TO_PARENT MLIRPythonSources.Dialects.nvgpu ROOT_DIR "${PYTHON_SOURCE_DIR}" SOURCES diff --git a/mlir/python/mlir/dialects/nvgpu.py b/mlir/python/mlir/dialects/nvgpu.py index e19bf610ea33..d6a54f2772f4 100644 --- a/mlir/python/mlir/dialects/nvgpu.py +++ b/mlir/python/mlir/dialects/nvgpu.py @@ -4,4 +4,4 @@ from ._nvgpu_ops_gen import * from ._nvgpu_enum_gen import * -from .._mlir_libs._mlirDialectsNvgpu import * +from .._mlir_libs._mlirDialectsNVGPU import * diff --git a/mlir/test/lib/Dialect/NVGPU/TestNVGPUTransforms.cpp b/mlir/test/lib/Dialect/NVGPU/TestNVGPUTransforms.cpp index 74a15ba273d8..8ca29257b812 100644 --- a/mlir/test/lib/Dialect/NVGPU/TestNVGPUTransforms.cpp +++ b/mlir/test/lib/Dialect/NVGPU/TestNVGPUTransforms.cpp @@ -68,9 +68,9 @@ struct TestMmaSyncF32ToTF32Patterns namespace mlir { namespace test { -void registerTestNvgpuLowerings() { +void registerTestNVGPULowerings() { PassRegistration(); } } // namespace test -} // namespace mlir \ No newline at end of file +} // namespace mlir diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp index 7e39cb62965e..1dfc5d178b61 100644 --- a/mlir/tools/mlir-opt/mlir-opt.cpp +++ b/mlir/tools/mlir-opt/mlir-opt.cpp @@ -143,7 +143,7 @@ void registerTestTransformDialectEraseSchedulePass(); void registerTestWrittenToPass(); void registerTestVectorLowerings(); void registerTestVectorReductionToSPIRVDotProd(); -void registerTestNvgpuLowerings(); +void registerTestNVGPULowerings(); #if MLIR_ENABLE_PDL_IN_PATTERNMATCH void registerTestDialectConversionPasses(); void registerTestPDLByteCodePass(); @@ -270,7 +270,7 @@ void registerTestPasses() { mlir::test::registerTestTransformDialectEraseSchedulePass(); mlir::test::registerTestVectorLowerings(); mlir::test::registerTestVectorReductionToSPIRVDotProd(); - mlir::test::registerTestNvgpuLowerings(); + mlir::test::registerTestNVGPULowerings(); mlir::test::registerTestWrittenToPass(); #if MLIR_ENABLE_PDL_IN_PATTERNMATCH mlir::test::registerTestDialectConversionPasses(); -- GitLab From 0bacffbbfc081b4147ac935512e2c5da9e3c06f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Warzy=C5=84ski?= Date: Mon, 13 May 2024 08:13:51 +0100 Subject: [PATCH 023/578] [mlir][vector] Update tests/patterns for vector.transpose (#91359) Pretty much all logic that we have today for lowering vector.transpose assumes fixed length vectors (it's done via vector.shuffle that don't support scalable vectors). This patch updates related tests and patterns to capture and document this limitation more explicitly. Note that `vector.transpose` is a valid operation in the context of scalable vectors, but we are yet to implement the missing lowerings. Summary of changes: * `@transpose_nx8x2xf32` is renamed as `@transpose_scalabl`e and moved near other tests using `lowering_strategy = "shuffle_1d" (to avoid duplicating TD sequences) * tests specific to X86 (`avx2_lowering_strategy = true`) are moved to a dedicated file (to separate generic tests from target-specific tests) * `@transpose10_nx4xnx1xf32` duplicated `@transpose10_4xnx1xf32` and was deleted (the latter is renamed as `@transpose10_4x1xf32_scalable` to match its fixed-width counterpart: `@transpose10_4x1xf32`) --- .../Transforms/LowerVectorTranspose.cpp | 1 + .../CPU/X86/vector-transpose-lowering.mlir | 493 +++++++++++++++ .../Vector/vector-transpose-lowering.mlir | 561 ++---------------- 3 files changed, 533 insertions(+), 522 deletions(-) create mode 100644 mlir/test/Dialect/Vector/CPU/X86/vector-transpose-lowering.mlir diff --git a/mlir/lib/Dialect/Vector/Transforms/LowerVectorTranspose.cpp b/mlir/lib/Dialect/Vector/Transforms/LowerVectorTranspose.cpp index 792550dcfaf2..7011c478fefb 100644 --- a/mlir/lib/Dialect/Vector/Transforms/LowerVectorTranspose.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/LowerVectorTranspose.cpp @@ -352,6 +352,7 @@ public: return success(); } + // TODO: Add support for scalable vectors if (inputType.isScalable()) return failure(); diff --git a/mlir/test/Dialect/Vector/CPU/X86/vector-transpose-lowering.mlir b/mlir/test/Dialect/Vector/CPU/X86/vector-transpose-lowering.mlir new file mode 100644 index 000000000000..ae2b5393ca44 --- /dev/null +++ b/mlir/test/Dialect/Vector/CPU/X86/vector-transpose-lowering.mlir @@ -0,0 +1,493 @@ +// RUN: mlir-opt %s --transform-interpreter --split-input-file | FileCheck %s + +// NOTE: This file tests lowerings that are implemented in the X86Vector +// dialect. Since X86 does not support scalable vectors, all examples in this +// file use fixed-width vectors. + +// CHECK-LABEL: func @transpose4x8 +func.func @transpose4x8xf32(%arg0: vector<4x8xf32>) -> vector<8x4xf32> { + // CHECK: vector.extract {{.*}}[0] + // CHECK-NEXT: vector.extract {{.*}}[1] + // CHECK-NEXT: vector.extract {{.*}}[2] + // CHECK-NEXT: vector.extract {{.*}}[3] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 8, 9, 4, 5, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 3, 10, 11, 6, 7, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 8, 9, 4, 5, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 3, 10, 11, 6, 7, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.shape_cast {{.*}} vector<4x8xf32> to vector<32xf32> + // CHECK-NEXT: vector.shape_cast {{.*}} vector<32xf32> to vector<8x4xf32> + %0 = vector.transpose %arg0, [1, 0] : vector<4x8xf32> to vector<8x4xf32> + return %0 : vector<8x4xf32> +} + +// CHECK-LABEL: func @transpose021_1x4x8 +func.func @transpose021_1x4x8xf32(%arg0: vector<1x4x8xf32>) -> vector<1x8x4xf32> { + // CHECK: vector.extract {{.*}}[0, 0] + // CHECK-NEXT: vector.extract {{.*}}[0, 1] + // CHECK-NEXT: vector.extract {{.*}}[0, 2] + // CHECK-NEXT: vector.extract {{.*}}[0, 3] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 8, 9, 4, 5, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 3, 10, 11, 6, 7, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 8, 9, 4, 5, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 3, 10, 11, 6, 7, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.shape_cast {{.*}} vector<4x8xf32> to vector<32xf32> + // CHECK-NEXT: vector.shape_cast {{.*}} vector<32xf32> to vector<1x8x4xf32> + %0 = vector.transpose %arg0, [0, 2, 1] : vector<1x4x8xf32> to vector<1x8x4xf32> + return %0 : vector<1x8x4xf32> +} + +// CHECK-LABEL: func @transpose8x8 +func.func @transpose8x8xf32(%arg0: vector<8x8xf32>) -> vector<8x8xf32> { + // CHECK: vector.extract {{.*}}[0] + // CHECK-NEXT: vector.extract {{.*}}[1] + // CHECK-NEXT: vector.extract {{.*}}[2] + // CHECK-NEXT: vector.extract {{.*}}[3] + // CHECK-NEXT: vector.extract {{.*}}[4] + // CHECK-NEXT: vector.extract {{.*}}[5] + // CHECK-NEXT: vector.extract {{.*}}[6] + // CHECK-NEXT: vector.extract {{.*}}[7] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.insert {{.*}}[4] + // CHECK-NEXT: vector.insert {{.*}}[5] + // CHECK-NEXT: vector.insert {{.*}}[6] + // CHECK-NEXT: vector.insert {{.*}}[7] + %0 = vector.transpose %arg0, [1, 0] : vector<8x8xf32> to vector<8x8xf32> + return %0 : vector<8x8xf32> +} + +// CHECK-LABEL: func @transpose021_1x8x8 +func.func @transpose021_1x8x8xf32(%arg0: vector<1x8x8xf32>) -> vector<1x8x8xf32> { + // CHECK: vector.extract {{.*}}[0, 0] + // CHECK-NEXT: vector.extract {{.*}}[0, 1] + // CHECK-NEXT: vector.extract {{.*}}[0, 2] + // CHECK-NEXT: vector.extract {{.*}}[0, 3] + // CHECK-NEXT: vector.extract {{.*}}[0, 4] + // CHECK-NEXT: vector.extract {{.*}}[0, 5] + // CHECK-NEXT: vector.extract {{.*}}[0, 6] + // CHECK-NEXT: vector.extract {{.*}}[0, 7] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.insert {{.*}}[4] + // CHECK-NEXT: vector.insert {{.*}}[5] + // CHECK-NEXT: vector.insert {{.*}}[6] + // CHECK-NEXT: vector.insert {{.*}}[7] + // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<1x8x8xf32> + %0 = vector.transpose %arg0, [0, 2, 1] : vector<1x8x8xf32> to vector<1x8x8xf32> + return %0 : vector<1x8x8xf32> +} + +// CHECK-LABEL: func @transpose120_8x1x8 +func.func @transpose120_8x1x8xf32(%arg0: vector<8x1x8xf32>) -> vector<1x8x8xf32> { + // CHECK: vector.extract {{.*}}[0, 0] + // CHECK-NEXT: vector.extract {{.*}}[1, 0] + // CHECK-NEXT: vector.extract {{.*}}[2, 0] + // CHECK-NEXT: vector.extract {{.*}}[3, 0] + // CHECK-NEXT: vector.extract {{.*}}[4, 0] + // CHECK-NEXT: vector.extract {{.*}}[5, 0] + // CHECK-NEXT: vector.extract {{.*}}[6, 0] + // CHECK-NEXT: vector.extract {{.*}}[7, 0] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.insert {{.*}}[4] + // CHECK-NEXT: vector.insert {{.*}}[5] + // CHECK-NEXT: vector.insert {{.*}}[6] + // CHECK-NEXT: vector.insert {{.*}}[7] + // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<1x8x8xf32> + %0 = vector.transpose %arg0, [1, 2, 0] : vector<8x1x8xf32> to vector<1x8x8xf32> + return %0 : vector<1x8x8xf32> +} + +// CHECK-LABEL: func @transpose120_8x8x1 +func.func @transpose120_8x8x1xf32(%arg0: vector<8x8x1xf32>) -> vector<8x1x8xf32> { + // CHECK: vector.shape_cast %{{.*}} : vector<8x8x1xf32> to vector<8x8xf32> + // CHECK-NEXT: vector.extract {{.*}}[0] + // CHECK-NEXT: vector.extract {{.*}}[1] + // CHECK-NEXT: vector.extract {{.*}}[2] + // CHECK-NEXT: vector.extract {{.*}}[3] + // CHECK-NEXT: vector.extract {{.*}}[4] + // CHECK-NEXT: vector.extract {{.*}}[5] + // CHECK-NEXT: vector.extract {{.*}}[6] + // CHECK-NEXT: vector.extract {{.*}}[7] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.insert {{.*}}[4] + // CHECK-NEXT: vector.insert {{.*}}[5] + // CHECK-NEXT: vector.insert {{.*}}[6] + // CHECK-NEXT: vector.insert {{.*}}[7] + // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x1x8xf32> + %0 = vector.transpose %arg0, [1, 2, 0] : vector<8x8x1xf32> to vector<8x1x8xf32> + return %0 : vector<8x1x8xf32> +} + +// CHECK-LABEL: func @transpose102_8x8x1 +func.func @transpose102_8x8x1xf32(%arg0: vector<8x8x1xf32>) -> vector<8x8x1xf32> { + // CHECK: vector.shape_cast %{{.*}} : vector<8x8x1xf32> to vector<8x8xf32> + // CHECK-NEXT: vector.extract {{.*}}[0] + // CHECK-NEXT: vector.extract {{.*}}[1] + // CHECK-NEXT: vector.extract {{.*}}[2] + // CHECK-NEXT: vector.extract {{.*}}[3] + // CHECK-NEXT: vector.extract {{.*}}[4] + // CHECK-NEXT: vector.extract {{.*}}[5] + // CHECK-NEXT: vector.extract {{.*}}[6] + // CHECK-NEXT: vector.extract {{.*}}[7] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.insert {{.*}}[4] + // CHECK-NEXT: vector.insert {{.*}}[5] + // CHECK-NEXT: vector.insert {{.*}}[6] + // CHECK-NEXT: vector.insert {{.*}}[7] + // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x8x1xf32> + %0 = vector.transpose %arg0, [1, 0, 2] : vector<8x8x1xf32> to vector<8x8x1xf32> + return %0 : vector<8x8x1xf32> +} + +// CHECK-LABEL: func @transpose201_8x1x8 +func.func @transpose201_8x1x8xf32(%arg0: vector<8x1x8xf32>) -> vector<8x8x1xf32> { + // CHECK: vector.extract {{.*}}[0, 0] + // CHECK-NEXT: vector.extract {{.*}}[1, 0] + // CHECK-NEXT: vector.extract {{.*}}[2, 0] + // CHECK-NEXT: vector.extract {{.*}}[3, 0] + // CHECK-NEXT: vector.extract {{.*}}[4, 0] + // CHECK-NEXT: vector.extract {{.*}}[5, 0] + // CHECK-NEXT: vector.extract {{.*}}[6, 0] + // CHECK-NEXT: vector.extract {{.*}}[7, 0] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.insert {{.*}}[4] + // CHECK-NEXT: vector.insert {{.*}}[5] + // CHECK-NEXT: vector.insert {{.*}}[6] + // CHECK-NEXT: vector.insert {{.*}}[7] + // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x8x1xf32> + %0 = vector.transpose %arg0, [2, 0, 1] : vector<8x1x8xf32> to vector<8x8x1xf32> + return %0 : vector<8x8x1xf32> +} + +// CHECK-LABEL: func @transpose201_1x8x8 +func.func @transpose201_1x8x8xf32(%arg0: vector<1x8x8xf32>) -> vector<8x1x8xf32> { + // CHECK: vector.extract {{.*}}[0, 0] + // CHECK-NEXT: vector.extract {{.*}}[0, 1] + // CHECK-NEXT: vector.extract {{.*}}[0, 2] + // CHECK-NEXT: vector.extract {{.*}}[0, 3] + // CHECK-NEXT: vector.extract {{.*}}[0, 4] + // CHECK-NEXT: vector.extract {{.*}}[0, 5] + // CHECK-NEXT: vector.extract {{.*}}[0, 6] + // CHECK-NEXT: vector.extract {{.*}}[0, 7] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.insert {{.*}}[4] + // CHECK-NEXT: vector.insert {{.*}}[5] + // CHECK-NEXT: vector.insert {{.*}}[6] + // CHECK-NEXT: vector.insert {{.*}}[7] + // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x1x8xf32> + %0 = vector.transpose %arg0, [2, 0, 1] : vector<1x8x8xf32> to vector<8x1x8xf32> + return %0 : vector<8x1x8xf32> +} + +// CHECK-LABEL: func @transpose210_8x1x8 +func.func @transpose210_8x1x8xf32(%arg0: vector<8x1x8xf32>) -> vector<8x1x8xf32> { + // CHECK: vector.extract {{.*}}[0, 0] + // CHECK-NEXT: vector.extract {{.*}}[1, 0] + // CHECK-NEXT: vector.extract {{.*}}[2, 0] + // CHECK-NEXT: vector.extract {{.*}}[3, 0] + // CHECK-NEXT: vector.extract {{.*}}[4, 0] + // CHECK-NEXT: vector.extract {{.*}}[5, 0] + // CHECK-NEXT: vector.extract {{.*}}[6, 0] + // CHECK-NEXT: vector.extract {{.*}}[7, 0] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.insert {{.*}}[4] + // CHECK-NEXT: vector.insert {{.*}}[5] + // CHECK-NEXT: vector.insert {{.*}}[6] + // CHECK-NEXT: vector.insert {{.*}}[7] + // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x1x8xf32> + %0 = vector.transpose %arg0, [2, 1, 0] : vector<8x1x8xf32> to vector<8x1x8xf32> + return %0 : vector<8x1x8xf32> +} + +// CHECK-LABEL: func @transpose210_8x8x1 +func.func @transpose210_8x8x1xf32(%arg0: vector<8x8x1xf32>) -> vector<1x8x8xf32> { + // CHECK: vector.shape_cast %{{.*}} : vector<8x8x1xf32> to vector<8x8xf32> + // CHECK-NEXT: vector.extract {{.*}}[0] + // CHECK-NEXT: vector.extract {{.*}}[1] + // CHECK-NEXT: vector.extract {{.*}}[2] + // CHECK-NEXT: vector.extract {{.*}}[3] + // CHECK-NEXT: vector.extract {{.*}}[4] + // CHECK-NEXT: vector.extract {{.*}}[5] + // CHECK-NEXT: vector.extract {{.*}}[6] + // CHECK-NEXT: vector.extract {{.*}}[7] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.insert {{.*}}[4] + // CHECK-NEXT: vector.insert {{.*}}[5] + // CHECK-NEXT: vector.insert {{.*}}[6] + // CHECK-NEXT: vector.insert {{.*}}[7] + // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<1x8x8xf32> + %0 = vector.transpose %arg0, [2, 1, 0] : vector<8x8x1xf32> to vector<1x8x8xf32> + return %0 : vector<1x8x8xf32> +} + +// CHECK-LABEL: func @transpose210_1x8x8 +func.func @transpose210_1x8x8xf32(%arg0: vector<1x8x8xf32>) -> vector<8x8x1xf32> { + // CHECK: vector.extract {{.*}}[0, 0] + // CHECK-NEXT: vector.extract {{.*}}[0, 1] + // CHECK-NEXT: vector.extract {{.*}}[0, 2] + // CHECK-NEXT: vector.extract {{.*}}[0, 3] + // CHECK-NEXT: vector.extract {{.*}}[0, 4] + // CHECK-NEXT: vector.extract {{.*}}[0, 5] + // CHECK-NEXT: vector.extract {{.*}}[0, 6] + // CHECK-NEXT: vector.extract {{.*}}[0, 7] + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> + // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> + // CHECK-NEXT: vector.insert {{.*}}[0] + // CHECK-NEXT: vector.insert {{.*}}[1] + // CHECK-NEXT: vector.insert {{.*}}[2] + // CHECK-NEXT: vector.insert {{.*}}[3] + // CHECK-NEXT: vector.insert {{.*}}[4] + // CHECK-NEXT: vector.insert {{.*}}[5] + // CHECK-NEXT: vector.insert {{.*}}[6] + // CHECK-NEXT: vector.insert {{.*}}[7] + // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x8x1xf32> + %0 = vector.transpose %arg0, [2, 1, 0] : vector<1x8x8xf32> to vector<8x8x1xf32> + return %0 : vector<8x8x1xf32> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> + transform.apply_patterns to %func_op { + transform.apply_patterns.vector.lower_transpose avx2_lowering_strategy = true + } : !transform.op<"func.func"> + transform.yield + } +} diff --git a/mlir/test/Dialect/Vector/vector-transpose-lowering.mlir b/mlir/test/Dialect/Vector/vector-transpose-lowering.mlir index 628a8ce50959..219a72df52a1 100644 --- a/mlir/test/Dialect/Vector/vector-transpose-lowering.mlir +++ b/mlir/test/Dialect/Vector/vector-transpose-lowering.mlir @@ -110,6 +110,17 @@ func.func @transpose(%arg0: vector<2x4xf32>) -> vector<4x2xf32> { return %0 : vector<4x2xf32> } +/// Scalable vectors are not supported + +// CHECK-LABEL: func @transpose_scalable +// CHECK-NOT: vector.shuffle +// CHECK-NOT: vector.shape_cast +// CHECK: vector.transpose +func.func @transpose_scalable(%arg0: vector<2x[4]xf32>) -> vector<[4]x2xf32> { + %0 = vector.transpose %arg0, [1, 0] : vector<2x[4]xf32> to vector<[4]x2xf32> + return %0 : vector<[4]x2xf32> +} + module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { @@ -132,502 +143,22 @@ func.func @transpose(%arg0: vector<2x4xf32>) -> vector<4x2xf32> { return %0 : vector<4x2xf32> } +/// Scalable vectors are not supported -module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { - %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> - transform.apply_patterns to %func_op { - transform.apply_patterns.vector.lower_transpose lowering_strategy = "flat_transpose" - } : !transform.op<"func.func"> - transform.yield - } -} - -// ----- - -// CHECK-LABEL: func @transpose4x8 -func.func @transpose4x8xf32(%arg0: vector<4x8xf32>) -> vector<8x4xf32> { - // CHECK: vector.extract {{.*}}[0] - // CHECK-NEXT: vector.extract {{.*}}[1] - // CHECK-NEXT: vector.extract {{.*}}[2] - // CHECK-NEXT: vector.extract {{.*}}[3] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 8, 9, 4, 5, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 3, 10, 11, 6, 7, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 8, 9, 4, 5, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 3, 10, 11, 6, 7, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.shape_cast {{.*}} vector<4x8xf32> to vector<32xf32> - // CHECK-NEXT: vector.shape_cast {{.*}} vector<32xf32> to vector<8x4xf32> - %0 = vector.transpose %arg0, [1, 0] : vector<4x8xf32> to vector<8x4xf32> - return %0 : vector<8x4xf32> -} - -// CHECK-LABEL: func @transpose021_1x4x8 -func.func @transpose021_1x4x8xf32(%arg0: vector<1x4x8xf32>) -> vector<1x8x4xf32> { - // CHECK: vector.extract {{.*}}[0, 0] - // CHECK-NEXT: vector.extract {{.*}}[0, 1] - // CHECK-NEXT: vector.extract {{.*}}[0, 2] - // CHECK-NEXT: vector.extract {{.*}}[0, 3] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 8, 9, 4, 5, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 3, 10, 11, 6, 7, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 8, 9, 4, 5, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 3, 10, 11, 6, 7, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.shape_cast {{.*}} vector<4x8xf32> to vector<32xf32> - // CHECK-NEXT: vector.shape_cast {{.*}} vector<32xf32> to vector<1x8x4xf32> - %0 = vector.transpose %arg0, [0, 2, 1] : vector<1x4x8xf32> to vector<1x8x4xf32> - return %0 : vector<1x8x4xf32> -} - -// CHECK-LABEL: func @transpose8x8 -func.func @transpose8x8xf32(%arg0: vector<8x8xf32>) -> vector<8x8xf32> { - // CHECK: vector.extract {{.*}}[0] - // CHECK-NEXT: vector.extract {{.*}}[1] - // CHECK-NEXT: vector.extract {{.*}}[2] - // CHECK-NEXT: vector.extract {{.*}}[3] - // CHECK-NEXT: vector.extract {{.*}}[4] - // CHECK-NEXT: vector.extract {{.*}}[5] - // CHECK-NEXT: vector.extract {{.*}}[6] - // CHECK-NEXT: vector.extract {{.*}}[7] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.insert {{.*}}[4] - // CHECK-NEXT: vector.insert {{.*}}[5] - // CHECK-NEXT: vector.insert {{.*}}[6] - // CHECK-NEXT: vector.insert {{.*}}[7] - %0 = vector.transpose %arg0, [1, 0] : vector<8x8xf32> to vector<8x8xf32> - return %0 : vector<8x8xf32> -} - -// CHECK-LABEL: func @transpose021_1x8x8 -func.func @transpose021_1x8x8xf32(%arg0: vector<1x8x8xf32>) -> vector<1x8x8xf32> { - // CHECK: vector.extract {{.*}}[0, 0] - // CHECK-NEXT: vector.extract {{.*}}[0, 1] - // CHECK-NEXT: vector.extract {{.*}}[0, 2] - // CHECK-NEXT: vector.extract {{.*}}[0, 3] - // CHECK-NEXT: vector.extract {{.*}}[0, 4] - // CHECK-NEXT: vector.extract {{.*}}[0, 5] - // CHECK-NEXT: vector.extract {{.*}}[0, 6] - // CHECK-NEXT: vector.extract {{.*}}[0, 7] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.insert {{.*}}[4] - // CHECK-NEXT: vector.insert {{.*}}[5] - // CHECK-NEXT: vector.insert {{.*}}[6] - // CHECK-NEXT: vector.insert {{.*}}[7] - // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<1x8x8xf32> - %0 = vector.transpose %arg0, [0, 2, 1] : vector<1x8x8xf32> to vector<1x8x8xf32> - return %0 : vector<1x8x8xf32> -} - -// CHECK-LABEL: func @transpose120_8x1x8 -func.func @transpose120_8x1x8xf32(%arg0: vector<8x1x8xf32>) -> vector<1x8x8xf32> { - // CHECK: vector.extract {{.*}}[0, 0] - // CHECK-NEXT: vector.extract {{.*}}[1, 0] - // CHECK-NEXT: vector.extract {{.*}}[2, 0] - // CHECK-NEXT: vector.extract {{.*}}[3, 0] - // CHECK-NEXT: vector.extract {{.*}}[4, 0] - // CHECK-NEXT: vector.extract {{.*}}[5, 0] - // CHECK-NEXT: vector.extract {{.*}}[6, 0] - // CHECK-NEXT: vector.extract {{.*}}[7, 0] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.insert {{.*}}[4] - // CHECK-NEXT: vector.insert {{.*}}[5] - // CHECK-NEXT: vector.insert {{.*}}[6] - // CHECK-NEXT: vector.insert {{.*}}[7] - // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<1x8x8xf32> - %0 = vector.transpose %arg0, [1, 2, 0] : vector<8x1x8xf32> to vector<1x8x8xf32> - return %0 : vector<1x8x8xf32> -} - -// CHECK-LABEL: func @transpose120_8x8x1 -func.func @transpose120_8x8x1xf32(%arg0: vector<8x8x1xf32>) -> vector<8x1x8xf32> { - // CHECK: vector.shape_cast %{{.*}} : vector<8x8x1xf32> to vector<8x8xf32> - // CHECK-NEXT: vector.extract {{.*}}[0] - // CHECK-NEXT: vector.extract {{.*}}[1] - // CHECK-NEXT: vector.extract {{.*}}[2] - // CHECK-NEXT: vector.extract {{.*}}[3] - // CHECK-NEXT: vector.extract {{.*}}[4] - // CHECK-NEXT: vector.extract {{.*}}[5] - // CHECK-NEXT: vector.extract {{.*}}[6] - // CHECK-NEXT: vector.extract {{.*}}[7] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.insert {{.*}}[4] - // CHECK-NEXT: vector.insert {{.*}}[5] - // CHECK-NEXT: vector.insert {{.*}}[6] - // CHECK-NEXT: vector.insert {{.*}}[7] - // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x1x8xf32> - %0 = vector.transpose %arg0, [1, 2, 0] : vector<8x8x1xf32> to vector<8x1x8xf32> - return %0 : vector<8x1x8xf32> -} - -// CHECK-LABEL: func @transpose102_8x8x1 -func.func @transpose102_8x8x1xf32(%arg0: vector<8x8x1xf32>) -> vector<8x8x1xf32> { - // CHECK: vector.shape_cast %{{.*}} : vector<8x8x1xf32> to vector<8x8xf32> - // CHECK-NEXT: vector.extract {{.*}}[0] - // CHECK-NEXT: vector.extract {{.*}}[1] - // CHECK-NEXT: vector.extract {{.*}}[2] - // CHECK-NEXT: vector.extract {{.*}}[3] - // CHECK-NEXT: vector.extract {{.*}}[4] - // CHECK-NEXT: vector.extract {{.*}}[5] - // CHECK-NEXT: vector.extract {{.*}}[6] - // CHECK-NEXT: vector.extract {{.*}}[7] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.insert {{.*}}[4] - // CHECK-NEXT: vector.insert {{.*}}[5] - // CHECK-NEXT: vector.insert {{.*}}[6] - // CHECK-NEXT: vector.insert {{.*}}[7] - // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x8x1xf32> - %0 = vector.transpose %arg0, [1, 0, 2] : vector<8x8x1xf32> to vector<8x8x1xf32> - return %0 : vector<8x8x1xf32> -} - -// CHECK-LABEL: func @transpose201_8x1x8 -func.func @transpose201_8x1x8xf32(%arg0: vector<8x1x8xf32>) -> vector<8x8x1xf32> { - // CHECK: vector.extract {{.*}}[0, 0] - // CHECK-NEXT: vector.extract {{.*}}[1, 0] - // CHECK-NEXT: vector.extract {{.*}}[2, 0] - // CHECK-NEXT: vector.extract {{.*}}[3, 0] - // CHECK-NEXT: vector.extract {{.*}}[4, 0] - // CHECK-NEXT: vector.extract {{.*}}[5, 0] - // CHECK-NEXT: vector.extract {{.*}}[6, 0] - // CHECK-NEXT: vector.extract {{.*}}[7, 0] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.insert {{.*}}[4] - // CHECK-NEXT: vector.insert {{.*}}[5] - // CHECK-NEXT: vector.insert {{.*}}[6] - // CHECK-NEXT: vector.insert {{.*}}[7] - // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x8x1xf32> - %0 = vector.transpose %arg0, [2, 0, 1] : vector<8x1x8xf32> to vector<8x8x1xf32> - return %0 : vector<8x8x1xf32> -} - -// CHECK-LABEL: func @transpose201_1x8x8 -func.func @transpose201_1x8x8xf32(%arg0: vector<1x8x8xf32>) -> vector<8x1x8xf32> { - // CHECK: vector.extract {{.*}}[0, 0] - // CHECK-NEXT: vector.extract {{.*}}[0, 1] - // CHECK-NEXT: vector.extract {{.*}}[0, 2] - // CHECK-NEXT: vector.extract {{.*}}[0, 3] - // CHECK-NEXT: vector.extract {{.*}}[0, 4] - // CHECK-NEXT: vector.extract {{.*}}[0, 5] - // CHECK-NEXT: vector.extract {{.*}}[0, 6] - // CHECK-NEXT: vector.extract {{.*}}[0, 7] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.insert {{.*}}[4] - // CHECK-NEXT: vector.insert {{.*}}[5] - // CHECK-NEXT: vector.insert {{.*}}[6] - // CHECK-NEXT: vector.insert {{.*}}[7] - // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x1x8xf32> - %0 = vector.transpose %arg0, [2, 0, 1] : vector<1x8x8xf32> to vector<8x1x8xf32> - return %0 : vector<8x1x8xf32> -} - -// CHECK-LABEL: func @transpose210_8x1x8 -func.func @transpose210_8x1x8xf32(%arg0: vector<8x1x8xf32>) -> vector<8x1x8xf32> { - // CHECK: vector.extract {{.*}}[0, 0] - // CHECK-NEXT: vector.extract {{.*}}[1, 0] - // CHECK-NEXT: vector.extract {{.*}}[2, 0] - // CHECK-NEXT: vector.extract {{.*}}[3, 0] - // CHECK-NEXT: vector.extract {{.*}}[4, 0] - // CHECK-NEXT: vector.extract {{.*}}[5, 0] - // CHECK-NEXT: vector.extract {{.*}}[6, 0] - // CHECK-NEXT: vector.extract {{.*}}[7, 0] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.insert {{.*}}[4] - // CHECK-NEXT: vector.insert {{.*}}[5] - // CHECK-NEXT: vector.insert {{.*}}[6] - // CHECK-NEXT: vector.insert {{.*}}[7] - // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x1x8xf32> - %0 = vector.transpose %arg0, [2, 1, 0] : vector<8x1x8xf32> to vector<8x1x8xf32> - return %0 : vector<8x1x8xf32> -} - -// CHECK-LABEL: func @transpose210_8x8x1 -func.func @transpose210_8x8x1xf32(%arg0: vector<8x8x1xf32>) -> vector<1x8x8xf32> { - // CHECK: vector.shape_cast %{{.*}} : vector<8x8x1xf32> to vector<8x8xf32> - // CHECK-NEXT: vector.extract {{.*}}[0] - // CHECK-NEXT: vector.extract {{.*}}[1] - // CHECK-NEXT: vector.extract {{.*}}[2] - // CHECK-NEXT: vector.extract {{.*}}[3] - // CHECK-NEXT: vector.extract {{.*}}[4] - // CHECK-NEXT: vector.extract {{.*}}[5] - // CHECK-NEXT: vector.extract {{.*}}[6] - // CHECK-NEXT: vector.extract {{.*}}[7] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.insert {{.*}}[4] - // CHECK-NEXT: vector.insert {{.*}}[5] - // CHECK-NEXT: vector.insert {{.*}}[6] - // CHECK-NEXT: vector.insert {{.*}}[7] - // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<1x8x8xf32> - %0 = vector.transpose %arg0, [2, 1, 0] : vector<8x8x1xf32> to vector<1x8x8xf32> - return %0 : vector<1x8x8xf32> -} - -// CHECK-LABEL: func @transpose210_1x8x8 -func.func @transpose210_1x8x8xf32(%arg0: vector<1x8x8xf32>) -> vector<8x8x1xf32> { - // CHECK: vector.extract {{.*}}[0, 0] - // CHECK-NEXT: vector.extract {{.*}}[0, 1] - // CHECK-NEXT: vector.extract {{.*}}[0, 2] - // CHECK-NEXT: vector.extract {{.*}}[0, 3] - // CHECK-NEXT: vector.extract {{.*}}[0, 4] - // CHECK-NEXT: vector.extract {{.*}}[0, 5] - // CHECK-NEXT: vector.extract {{.*}}[0, 6] - // CHECK-NEXT: vector.extract {{.*}}[0, 7] - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [0, 8, 1, 9, 4, 12, 5, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.shuffle {{.*}} [2, 10, 3, 11, 6, 14, 7, 15] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [2, 3, 8, 9, 6, 7, 12, 13] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0xcc", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-NEXT: llvm.inline_asm asm_dialect = intel "vblendps $0, $1, $2, 0x33", "=x,x,x" {{.*}} : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [0, 1, 2, 3, 8, 9, 10, 11] : vector<8xf32>, vector<8xf32> - // CHECK-COUNT-4: vector.shuffle {{.*}} [4, 5, 6, 7, 12, 13, 14, 15] : vector<8xf32>, vector<8xf32> - // CHECK-NEXT: vector.insert {{.*}}[0] - // CHECK-NEXT: vector.insert {{.*}}[1] - // CHECK-NEXT: vector.insert {{.*}}[2] - // CHECK-NEXT: vector.insert {{.*}}[3] - // CHECK-NEXT: vector.insert {{.*}}[4] - // CHECK-NEXT: vector.insert {{.*}}[5] - // CHECK-NEXT: vector.insert {{.*}}[6] - // CHECK-NEXT: vector.insert {{.*}}[7] - // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x8xf32> to vector<8x8x1xf32> - %0 = vector.transpose %arg0, [2, 1, 0] : vector<1x8x8xf32> to vector<8x8x1xf32> - return %0 : vector<8x8x1xf32> +// CHECK-LABEL: func @transpose_scalable( +func.func @transpose_scalable(%arg0: vector<2x[4]xf32>) -> vector<[4]x2xf32> { + // CHECK-NOT: vector.shape_cast + // CHECK-NOT: vector.flat_transpose + // CHECK: vector.transpose + %0 = vector.transpose %arg0, [1, 0] : vector<2x[4]xf32> to vector<[4]x2xf32> + return %0 : vector<[4]x2xf32> } module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { - transform.apply_patterns.vector.lower_transpose avx2_lowering_strategy = true + transform.apply_patterns.vector.lower_transpose lowering_strategy = "flat_transpose" } : !transform.op<"func.func"> transform.yield } @@ -635,6 +166,7 @@ module attributes {transform.with_named_sequence} { // ----- +// CHECK-LABEL: @transpose_shuffle16x16xf32( func.func @transpose_shuffle16x16xf32(%arg0: vector<16x16xf32>) -> vector<16x16xf32> { // CHECK: vector.shuffle {{.*}} [0, 16, 1, 17, 4, 20, 5, 21, 8, 24, 9, 25, 12, 28, 13, 29] : vector<16xf32>, vector<16xf32> // CHECK: vector.shuffle {{.*}} [2, 18, 3, 19, 6, 22, 7, 23, 10, 26, 11, 27, 14, 30, 15, 31] : vector<16xf32>, vector<16xf32> @@ -704,6 +236,14 @@ func.func @transpose_shuffle16x16xf32(%arg0: vector<16x16xf32>) -> vector<16x16x return %0 : vector<16x16xf32> } +// CHECK-LABEL: @transpose_shuffle16x16xf32_scalable( +func.func @transpose_shuffle16x16xf32_scalable(%arg0: vector<16x[16]xf32>) -> vector<[16]x16xf32> { + // CHECK-NOT: vector.shuffle + // CHECK: vector.transpose + %0 = vector.transpose %arg0, [1, 0] : vector<16x[16]xf32> to vector<[16]x16xf32> + return %0 : vector<[16]x16xf32> +} + module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> @@ -786,6 +326,14 @@ func.func @transpose021_shuffle16x16xf32(%arg0: vector<1x16x16xf32>) -> vector<1 return %0 : vector<1x16x16xf32> } +// CHECK-LABEL: func @transpose021_shuffle16x16xf32_scalable +func.func @transpose021_shuffle16x16xf32_scalable(%arg0: vector<1x16x[16]xf32>) -> vector<1x[16]x16xf32> { + // CHECK-NOT: vector.shuffle + // CHECK: vector.transpose + %0 = vector.transpose %arg0, [0, 2, 1] : vector<1x16x[16]xf32> to vector<1x[16]x16xf32> + return %0 : vector<1x[16]x16xf32> +} + module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> @@ -830,23 +378,14 @@ func.func @transpose10_1xnx4xf32(%arg0: vector<1x[4]xf32>) -> vector<[4]x1xf32> /// Scalable unit dim should not be lowered to shape_cast. -// CHECK-LABEL: func @transpose10_4xnx1xf32 -func.func @transpose10_4xnx1xf32(%arg0: vector<4x[1]xf32>) -> vector<[1]x4xf32> { +// CHECK-LABEL: func @transpose10_4x1xf32_scalable +func.func @transpose10_4x1xf32_scalable(%arg0: vector<4x[1]xf32>) -> vector<[1]x4xf32> { // CHECK-NOT: vector.shape_cast // CHECK: vector.transpose %{{.*}} : vector<4x[1]xf32> to vector<[1]x4xf32> %0 = vector.transpose %arg0, [1, 0] : vector<4x[1]xf32> to vector<[1]x4xf32> return %0 : vector<[1]x4xf32> } -// CHECK-LABEL: func @transpose10_nx4xnx1xf32 -func.func @transpose10_nx4xnx1xf32(%arg0: vector<4x[1]xf32>) -> vector<[1]x4xf32> { - // CHECK-NOT: vector.shape_cast - // CHECK: vector.transpose %{{.*}} : vector<4x[1]xf32> to vector<[1]x4xf32> - %0 = vector.transpose %arg0, [1, 0] : vector<4x[1]xf32> to vector<[1]x4xf32> - - return %0 : vector<[1]x4xf32> -} - module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> @@ -856,25 +395,3 @@ module attributes {transform.with_named_sequence} { transform.yield } } - -// ----- - -// Scalable transposes should not be lowered to vector.shuffle. - -// CHECK-LABEL: func @transpose_nx8x2xf32 -func.func @transpose_nx8x2xf32(%arg0: vector<[8]x2xf32>) -> vector<2x[8]xf32> { - // CHECK-NOT: vector.shuffle - // CHECK: vector.transpose %{{.*}} : vector<[8]x2xf32> to vector<2x[8]xf32> - %0 = vector.transpose %arg0, [1, 0] : vector<[8]x2xf32> to vector<2x[8]xf32> - return %0 : vector<2x[8]xf32> -} - -module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { - %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> - transform.apply_patterns to %func_op { - transform.apply_patterns.vector.lower_transpose lowering_strategy = "shuffle_1d" - } : !transform.op<"func.func"> - transform.yield - } -} -- GitLab From d182877ba3f5ad93e061f68a9ecce38cb8cec418 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 13 May 2024 09:33:35 +0200 Subject: [PATCH 024/578] [clang] CTAD alias: fix the transformation for the require-clause expr (#90961) In the clang AST, constraint nodes are deliberately not instantiated unless they are actively being evaluated. Consequently, occurrences of template parameters in the require-clause expression have a subtle "depth" difference compared to normal occurrences in places, such as function parameters. When transforming the require-clause, we must take this distinction into account. The existing implementation overlooks this consideration. This patch is to rewrite the implementation of the require-clause transformation to address this issue. Fixes #90177 --- clang/lib/Sema/SemaTemplate.cpp | 148 +++++++++++++++++-- clang/test/AST/ast-dump-ctad-alias.cpp | 40 +++++ clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 68 +++++++++ 3 files changed, 242 insertions(+), 14 deletions(-) create mode 100644 clang/test/AST/ast-dump-ctad-alias.cpp diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0e7bd8dd8957..bae00c629270 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2758,31 +2758,149 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) { return false; } +unsigned getTemplateParameterDepth(NamedDecl *TemplateParam) { + if (auto *TTP = dyn_cast(TemplateParam)) + return TTP->getDepth(); + if (auto *TTP = dyn_cast(TemplateParam)) + return TTP->getDepth(); + if (auto *NTTP = dyn_cast(TemplateParam)) + return NTTP->getDepth(); + llvm_unreachable("Unhandled template parameter types"); +} + NamedDecl *transformTemplateParameter(Sema &SemaRef, DeclContext *DC, NamedDecl *TemplateParam, MultiLevelTemplateArgumentList &Args, - unsigned NewIndex) { + unsigned NewIndex, unsigned NewDepth) { if (auto *TTP = dyn_cast(TemplateParam)) - return transformTemplateTypeParam(SemaRef, DC, TTP, Args, TTP->getDepth(), + return transformTemplateTypeParam(SemaRef, DC, TTP, Args, NewDepth, NewIndex); if (auto *TTP = dyn_cast(TemplateParam)) - return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, - TTP->getDepth()); + return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, NewDepth); if (auto *NTTP = dyn_cast(TemplateParam)) - return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, - NTTP->getDepth()); + return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, NewDepth); llvm_unreachable("Unhandled template parameter types"); } -Expr *transformRequireClause(Sema &SemaRef, FunctionTemplateDecl *FTD, - llvm::ArrayRef TransformedArgs) { - Expr *RC = FTD->getTemplateParameters()->getRequiresClause(); +// Transform the require-clause of F if any. +// The return result is expected to be the require-clause for the synthesized +// alias deduction guide. +Expr *transformRequireClause(Sema &SemaRef, FunctionTemplateDecl *F, + TypeAliasTemplateDecl *AliasTemplate, + ArrayRef DeduceResults) { + Expr *RC = F->getTemplateParameters()->getRequiresClause(); if (!RC) return nullptr; + + auto &Context = SemaRef.Context; + LocalInstantiationScope Scope(SemaRef); + + // In the clang AST, constraint nodes are deliberately not instantiated unless + // they are actively being evaluated. Consequently, occurrences of template + // parameters in the require-clause expression have a subtle "depth" + // difference compared to normal occurrences in places, such as function + // parameters. When transforming the require-clause, we must take this + // distinction into account: + // + // 1) In the transformed require-clause, occurrences of template parameters + // must use the "uninstantiated" depth; + // 2) When substituting on the require-clause expr of the underlying + // deduction guide, we must use the entire set of template argument lists; + // + // It's important to note that we're performing this transformation on an + // *instantiated* AliasTemplate. + + // For 1), if the alias template is nested within a class template, we + // calcualte the 'uninstantiated' depth by adding the substitution level back. + unsigned AdjustDepth = 0; + if (auto *PrimaryTemplate = + AliasTemplate->getInstantiatedFromMemberTemplate()) + AdjustDepth = PrimaryTemplate->getTemplateDepth(); + + // We rebuild all template parameters with the uninstantiated depth, and + // build template arguments refer to them. + SmallVector AdjustedAliasTemplateArgs; + + for (auto *TP : *AliasTemplate->getTemplateParameters()) { + // Rebuild any internal references to earlier parameters and reindex + // as we go. + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(AdjustedAliasTemplateArgs); + NamedDecl *NewParam = transformTemplateParameter( + SemaRef, AliasTemplate->getDeclContext(), TP, Args, + /*NewIndex=*/AdjustedAliasTemplateArgs.size(), + getTemplateParameterDepth(TP) + AdjustDepth); + + auto NewTemplateArgument = Context.getCanonicalTemplateArgument( + Context.getInjectedTemplateArg(NewParam)); + AdjustedAliasTemplateArgs.push_back(NewTemplateArgument); + } + // Template arguments used to transform the template arguments in + // DeducedResults. + SmallVector TemplateArgsForBuildingRC( + F->getTemplateParameters()->size()); + // Transform the transformed template args MultiLevelTemplateArgumentList Args; Args.setKind(TemplateSubstitutionKind::Rewrite); - Args.addOuterTemplateArguments(TransformedArgs); - ExprResult E = SemaRef.SubstExpr(RC, Args); + Args.addOuterTemplateArguments(AdjustedAliasTemplateArgs); + + for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { + const auto &D = DeduceResults[Index]; + if (D.isNull()) + continue; + TemplateArgumentLoc Input = + SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{}); + TemplateArgumentLoc Output; + if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) { + assert(TemplateArgsForBuildingRC[Index].isNull() && + "InstantiatedArgs must be null before setting"); + TemplateArgsForBuildingRC[Index] = Output.getArgument(); + } + } + + // A list of template arguments for transforming the require-clause of F. + // It must contain the entire set of template argument lists. + MultiLevelTemplateArgumentList ArgsForBuildingRC; + ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite); + ArgsForBuildingRC.addOuterTemplateArguments(TemplateArgsForBuildingRC); + // For 2), if the underlying F is instantiated from a member template, we need + // the entire template argument list, as the constraint AST in the + // require-clause of F remains completely uninstantiated. + // + // For example: + // template // depth 0 + // struct Outer { + // template + // struct Foo { Foo(U); }; + // + // template // depth 1 + // requires C + // Foo(U) -> Foo; + // }; + // template + // using AFoo = Outer::Foo; + // + // In this scenario, the deduction guide for `Foo` inside `Outer`: + // - The occurrence of U in the require-expression is [depth:1, index:0] + // - The occurrence of U in the function parameter is [depth:0, index:0] + // - The template parameter of U is [depth:0, index:0] + // + // We add the outer template arguments which is [int] to the multi-level arg + // list to ensure that the occurrence U in `C` will be replaced with int + // during the substitution. + if (F->getInstantiatedFromMemberTemplate()) { + auto OuterLevelArgs = SemaRef.getTemplateInstantiationArgs( + F, F->getLexicalDeclContext(), + /*Final=*/false, /*Innermost=*/std::nullopt, + /*RelativeToPrimary=*/true, + /*Pattern=*/nullptr, + /*ForConstraintInstantiation=*/true); + for (auto It : OuterLevelArgs) + ArgsForBuildingRC.addOuterTemplateArguments(It.Args); + } + + ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC); if (E.isInvalid()) return nullptr; return E.getAs(); @@ -2920,7 +3038,8 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, Args.addOuterTemplateArguments(TransformedDeducedAliasArgs); NamedDecl *NewParam = transformTemplateParameter( SemaRef, AliasTemplate->getDeclContext(), TP, Args, - /*NewIndex=*/FPrimeTemplateParams.size()); + /*NewIndex=*/FPrimeTemplateParams.size(), + getTemplateParameterDepth(TP)); FPrimeTemplateParams.push_back(NewParam); auto NewTemplateArgument = Context.getCanonicalTemplateArgument( @@ -2937,7 +3056,8 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, // TemplateArgsForBuildingFPrime. Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime); NamedDecl *NewParam = transformTemplateParameter( - SemaRef, F->getDeclContext(), TP, Args, FPrimeTemplateParams.size()); + SemaRef, F->getDeclContext(), TP, Args, FPrimeTemplateParams.size(), + getTemplateParameterDepth(TP)); FPrimeTemplateParams.push_back(NewParam); assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() && @@ -2993,7 +3113,7 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, auto *GG = cast(FPrime); Expr *RequiresClause = - transformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime); + transformRequireClause(SemaRef, F, AliasTemplate, DeduceResults); // FIXME: implement the is_deducible constraint per C++ // [over.match.class.deduct]p3.3: diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp new file mode 100644 index 000000000000..423c3454ccb7 --- /dev/null +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++2a -ast-dump %s | FileCheck -strict-whitespace %s + +template +constexpr bool Concept = true; +template // depth 0 +struct Out { + template // depth 1 + struct Inner { + U t; + }; + + template // depth1 + requires Concept + Inner(V) -> Inner; +}; + +template +struct Out2 { + template // depth1 + using AInner = Out::Inner; +}; +Out2::AInner t(1.0); + +// Verify that the require-clause of alias deduction guide is transformed correctly: +// - Occurrence T should be replaced with `int`; +// - Occurrence V should be replaced with the Y with depth 1 +// +// CHECK: | `-FunctionTemplateDecl {{.*}} +// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 Y +// CHECK-NEXT: | |-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'Concept' +// CHECK-NEXT: | | |-TemplateArgument type 'int' +// CHECK-NEXT: | | | `-BuiltinType {{.*}} 'int' +// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0' +// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 +// CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} 'auto (type-parameter-0-0) -> Inner' +// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0' +// CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} used 'auto (double) -> Inner' implicit_instantiation +// CHECK-NEXT: | |-TemplateArgument type 'double' +// CHECK-NEXT: | | `-BuiltinType {{.*}} 'double' +// CHECK-NEXT: | `-ParmVarDecl {{.*}} 'double' diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index e8b4383f53c5..4c5595e409f2 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -321,3 +321,71 @@ AG ag(1.0); // choosen. static_assert(__is_same(decltype(ag.t1), int)); } // namespace test23 + +// GH90177 +// verify that the transformed require-clause of the alias deduction gudie has +// the right depth info. +namespace test24 { +class Forward; +class Key {}; + +template +constexpr bool C = sizeof(D); + +// Case1: the alias template and the underlying deduction guide are in the same +// scope. +template +struct Case1 { + template + struct Foo { + Foo(U); + }; + + template + requires (C) + Foo(V) -> Foo; + + template + using Alias = Foo; +}; +// The require-clause should be evaluated on the type Key. +Case1::Alias t2 = Key(); + + +// Case2: the alias template and underlying deduction guide are in different +// scope. +template +struct Foo { + Foo(T); +}; +template +requires (C) +Foo(U) -> Foo; + +template +struct Case2 { + template + using Alias = Foo; +}; +// The require-caluse should be evaluated on the type Key. +Case2::Alias t1 = Key(); + +// Case3: crashes on the constexpr evaluator due to the mixed-up depth in +// require-expr. +template +struct A1 { + template + struct A2 { + template + struct Foo { + Foo(T3); + }; + template + requires C + Foo(T3) -> Foo; + }; +}; +template +using AFoo = A1::A2::Foo; +AFoo case3(1); +} // namespace test24 -- GitLab From 109ede496ecf6de5dabace08d73ec7604b343a6b Mon Sep 17 00:00:00 2001 From: David Green Date: Mon, 13 May 2024 08:46:04 +0100 Subject: [PATCH 025/578] [AArch64] Extend v2i64 fptosi.sat to v2f64 (#91714) This helps it produce a single instruction for the saturate, as opposed to having to scalarize. --- .../Target/AArch64/AArch64ISelLowering.cpp | 9 + llvm/test/CodeGen/AArch64/fcvt_combine.ll | 7 +- llvm/test/CodeGen/AArch64/fpclamptosat_vec.ll | 16 +- .../test/CodeGen/AArch64/fptosi-sat-vector.ll | 23 +- .../test/CodeGen/AArch64/fptoui-sat-vector.ll | 23 +- .../AArch64/sve-fixed-vector-llrint.ll | 7 +- .../CodeGen/AArch64/sve-fixed-vector-lrint.ll | 7 +- llvm/test/CodeGen/AArch64/vector-llrint.ll | 283 ++++++------------ llvm/test/CodeGen/AArch64/vector-lrint.ll | 283 ++++++------------ 9 files changed, 221 insertions(+), 437 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index a6c020c6b823..1e0071fffe66 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -4286,6 +4286,15 @@ AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op, return SDValue(); SDLoc DL(Op); + // Expand to f64 if we are saturating to i64, to help produce keep the lanes + // the same width and produce a fcvtzu. + if (SatWidth == 64 && SrcElementWidth < 64) { + MVT F64VT = MVT::getVectorVT(MVT::f64, SrcVT.getVectorNumElements()); + SrcVal = DAG.getNode(ISD::FP_EXTEND, DL, F64VT, SrcVal); + SrcVT = F64VT; + SrcElementVT = MVT::f64; + SrcElementWidth = 64; + } // Cases that we can emit directly. if (SrcElementWidth == DstElementWidth && SrcElementWidth == SatWidth) return DAG.getNode(Op.getOpcode(), DL, DstVT, SrcVal, diff --git a/llvm/test/CodeGen/AArch64/fcvt_combine.ll b/llvm/test/CodeGen/AArch64/fcvt_combine.ll index 29170aab9656..62669a6d99ea 100644 --- a/llvm/test/CodeGen/AArch64/fcvt_combine.ll +++ b/llvm/test/CodeGen/AArch64/fcvt_combine.ll @@ -345,11 +345,8 @@ define <2 x i64> @test6_sat(<2 x float> %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: fmov v1.2s, #16.00000000 ; CHECK-NEXT: fmul v0.2s, v0.2s, v1.2s -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fcvtzs x8, s0 -; CHECK-NEXT: fcvtzs x9, s1 -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: mov v0.d[1], x9 +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtzs v0.2d, v0.2d ; CHECK-NEXT: ret %mul.i = fmul <2 x float> %f, %vcvt.i = call <2 x i64> @llvm.fptosi.sat.v2i64.v2f32(<2 x float> %mul.i) diff --git a/llvm/test/CodeGen/AArch64/fpclamptosat_vec.ll b/llvm/test/CodeGen/AArch64/fpclamptosat_vec.ll index 2ea581359af6..4e8bfcd9d751 100644 --- a/llvm/test/CodeGen/AArch64/fpclamptosat_vec.ll +++ b/llvm/test/CodeGen/AArch64/fpclamptosat_vec.ll @@ -436,12 +436,8 @@ entry: define <2 x i64> @stest_f32i64(<2 x float> %x) { ; CHECK-LABEL: stest_f32i64: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fcvtzs x8, s0 -; CHECK-NEXT: fcvtzs x9, s1 -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: mov v0.d[1], x9 +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtzs v0.2d, v0.2d ; CHECK-NEXT: ret entry: %conv = fptosi <2 x float> %x to <2 x i128> @@ -1056,12 +1052,8 @@ entry: define <2 x i64> @stest_f32i64_mm(<2 x float> %x) { ; CHECK-LABEL: stest_f32i64_mm: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fcvtzs x8, s0 -; CHECK-NEXT: fcvtzs x9, s1 -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: mov v0.d[1], x9 +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtzs v0.2d, v0.2d ; CHECK-NEXT: ret entry: %conv = fptosi <2 x float> %x to <2 x i128> diff --git a/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll b/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll index c45885a38f15..d620a8851ee4 100644 --- a/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll +++ b/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll @@ -793,12 +793,8 @@ define <2 x i50> @test_signed_v2f32_v2i50(<2 x float> %f) { define <2 x i64> @test_signed_v2f32_v2i64(<2 x float> %f) { ; CHECK-LABEL: test_signed_v2f32_v2i64: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fcvtzs x8, s0 -; CHECK-NEXT: fcvtzs x9, s1 -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: mov v0.d[1], x9 +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtzs v0.2d, v0.2d ; CHECK-NEXT: ret %x = call <2 x i64> @llvm.fptosi.sat.v2f32.v2i64(<2 x float> %f) ret <2 x i64> %x @@ -1060,17 +1056,10 @@ define <4 x i50> @test_signed_v4f32_v4i50(<4 x float> %f) { define <4 x i64> @test_signed_v4f32_v4i64(<4 x float> %f) { ; CHECK-LABEL: test_signed_v4f32_v4i64: ; CHECK: // %bb.0: -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: mov s3, v0.s[1] -; CHECK-NEXT: fcvtzs x9, s0 -; CHECK-NEXT: mov s2, v1.s[1] -; CHECK-NEXT: fcvtzs x8, s1 -; CHECK-NEXT: fcvtzs x11, s3 -; CHECK-NEXT: fmov d0, x9 -; CHECK-NEXT: fcvtzs x10, s2 -; CHECK-NEXT: fmov d1, x8 -; CHECK-NEXT: mov v0.d[1], x11 -; CHECK-NEXT: mov v1.d[1], x10 +; CHECK-NEXT: fcvtl2 v1.2d, v0.4s +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtzs v1.2d, v1.2d +; CHECK-NEXT: fcvtzs v0.2d, v0.2d ; CHECK-NEXT: ret %x = call <4 x i64> @llvm.fptosi.sat.v4f32.v4i64(<4 x float> %f) ret <4 x i64> %x diff --git a/llvm/test/CodeGen/AArch64/fptoui-sat-vector.ll b/llvm/test/CodeGen/AArch64/fptoui-sat-vector.ll index c94db3484994..16e04070b654 100644 --- a/llvm/test/CodeGen/AArch64/fptoui-sat-vector.ll +++ b/llvm/test/CodeGen/AArch64/fptoui-sat-vector.ll @@ -707,12 +707,8 @@ define <2 x i50> @test_unsigned_v2f32_v2i50(<2 x float> %f) { define <2 x i64> @test_unsigned_v2f32_v2i64(<2 x float> %f) { ; CHECK-LABEL: test_unsigned_v2f32_v2i64: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fcvtzu x8, s0 -; CHECK-NEXT: fcvtzu x9, s1 -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: mov v0.d[1], x9 +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtzu v0.2d, v0.2d ; CHECK-NEXT: ret %x = call <2 x i64> @llvm.fptoui.sat.v2f32.v2i64(<2 x float> %f) ret <2 x i64> %x @@ -927,17 +923,10 @@ define <4 x i50> @test_unsigned_v4f32_v4i50(<4 x float> %f) { define <4 x i64> @test_unsigned_v4f32_v4i64(<4 x float> %f) { ; CHECK-LABEL: test_unsigned_v4f32_v4i64: ; CHECK: // %bb.0: -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: mov s3, v0.s[1] -; CHECK-NEXT: fcvtzu x9, s0 -; CHECK-NEXT: mov s2, v1.s[1] -; CHECK-NEXT: fcvtzu x8, s1 -; CHECK-NEXT: fcvtzu x11, s3 -; CHECK-NEXT: fmov d0, x9 -; CHECK-NEXT: fcvtzu x10, s2 -; CHECK-NEXT: fmov d1, x8 -; CHECK-NEXT: mov v0.d[1], x11 -; CHECK-NEXT: mov v1.d[1], x10 +; CHECK-NEXT: fcvtl2 v1.2d, v0.4s +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtzu v1.2d, v1.2d +; CHECK-NEXT: fcvtzu v0.2d, v0.2d ; CHECK-NEXT: ret %x = call <4 x i64> @llvm.fptoui.sat.v4f32.v4i64(<4 x float> %f) ret <4 x i64> %x diff --git a/llvm/test/CodeGen/AArch64/sve-fixed-vector-llrint.ll b/llvm/test/CodeGen/AArch64/sve-fixed-vector-llrint.ll index 9137eae269d9..c77861509e4a 100644 --- a/llvm/test/CodeGen/AArch64/sve-fixed-vector-llrint.ll +++ b/llvm/test/CodeGen/AArch64/sve-fixed-vector-llrint.ll @@ -295,11 +295,8 @@ define <2 x i64> @llrint_v2i64_v2f32(<2 x float> %x) { ; CHECK-LABEL: llrint_v2i64_v2f32: ; CHECK: // %bb.0: ; CHECK-NEXT: frintx v0.2s, v0.2s -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fcvtzs x8, s0 -; CHECK-NEXT: fcvtzs x9, s1 -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: mov v0.d[1], x9 +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtzs v0.2d, v0.2d ; CHECK-NEXT: ret %a = call <2 x i64> @llvm.llrint.v2i64.v2f32(<2 x float> %x) ret <2 x i64> %a diff --git a/llvm/test/CodeGen/AArch64/sve-fixed-vector-lrint.ll b/llvm/test/CodeGen/AArch64/sve-fixed-vector-lrint.ll index 9bdbe9b8ac62..6a97e7ad64bf 100644 --- a/llvm/test/CodeGen/AArch64/sve-fixed-vector-lrint.ll +++ b/llvm/test/CodeGen/AArch64/sve-fixed-vector-lrint.ll @@ -534,11 +534,8 @@ define <2 x iXLen> @lrint_v2f32(<2 x float> %x) { ; CHECK-i64-LABEL: lrint_v2f32: ; CHECK-i64: // %bb.0: ; CHECK-i64-NEXT: frintx v0.2s, v0.2s -; CHECK-i64-NEXT: mov s1, v0.s[1] -; CHECK-i64-NEXT: fcvtzs x8, s0 -; CHECK-i64-NEXT: fcvtzs x9, s1 -; CHECK-i64-NEXT: fmov d0, x8 -; CHECK-i64-NEXT: mov v0.d[1], x9 +; CHECK-i64-NEXT: fcvtl v0.2d, v0.2s +; CHECK-i64-NEXT: fcvtzs v0.2d, v0.2d ; CHECK-i64-NEXT: ret %a = call <2 x iXLen> @llvm.lrint.v2iXLen.v2f32(<2 x float> %x) ret <2 x iXLen> %a diff --git a/llvm/test/CodeGen/AArch64/vector-llrint.ll b/llvm/test/CodeGen/AArch64/vector-llrint.ll index b7e743b5085f..5503de2b4c5d 100644 --- a/llvm/test/CodeGen/AArch64/vector-llrint.ll +++ b/llvm/test/CodeGen/AArch64/vector-llrint.ll @@ -387,11 +387,8 @@ define <2 x i64> @llrint_v2i64_v2f32(<2 x float> %x) { ; CHECK-LABEL: llrint_v2i64_v2f32: ; CHECK: // %bb.0: ; CHECK-NEXT: frintx v0.2s, v0.2s -; CHECK-NEXT: mov s1, v0.s[1] -; CHECK-NEXT: fcvtzs x8, s0 -; CHECK-NEXT: fcvtzs x9, s1 -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: mov v0.d[1], x9 +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtzs v0.2d, v0.2d ; CHECK-NEXT: ret %a = call <2 x i64> @llvm.llrint.v2i64.v2f32(<2 x float> %x) ret <2 x i64> %a @@ -404,16 +401,10 @@ define <4 x i64> @llrint_v4i64_v4f32(<4 x float> %x) { ; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 ; CHECK-NEXT: frintx v0.2s, v0.2s ; CHECK-NEXT: frintx v1.2s, v1.2s -; CHECK-NEXT: mov s2, v0.s[1] -; CHECK-NEXT: fcvtzs x8, s0 -; CHECK-NEXT: mov s3, v1.s[1] -; CHECK-NEXT: fcvtzs x9, s1 -; CHECK-NEXT: fcvtzs x10, s2 -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: fcvtzs x11, s3 -; CHECK-NEXT: fmov d1, x9 -; CHECK-NEXT: mov v0.d[1], x10 -; CHECK-NEXT: mov v1.d[1], x11 +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtl v1.2d, v1.2s +; CHECK-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: ret %a = call <4 x i64> @llvm.llrint.v4i64.v4f32(<4 x float> %x) ret <4 x i64> %a @@ -429,26 +420,14 @@ define <8 x i64> @llrint_v8i64_v8f32(<8 x float> %x) { ; CHECK-NEXT: frintx v1.2s, v1.2s ; CHECK-NEXT: frintx v2.2s, v2.2s ; CHECK-NEXT: frintx v3.2s, v3.2s -; CHECK-NEXT: mov s4, v0.s[1] -; CHECK-NEXT: mov s5, v1.s[1] -; CHECK-NEXT: fcvtzs x8, s0 -; CHECK-NEXT: fcvtzs x10, s1 -; CHECK-NEXT: mov s6, v2.s[1] -; CHECK-NEXT: mov s7, v3.s[1] -; CHECK-NEXT: fcvtzs x11, s2 -; CHECK-NEXT: fcvtzs x12, s3 -; CHECK-NEXT: fcvtzs x9, s4 -; CHECK-NEXT: fcvtzs x13, s5 -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: fmov d2, x10 -; CHECK-NEXT: fcvtzs x14, s6 -; CHECK-NEXT: fcvtzs x15, s7 -; CHECK-NEXT: fmov d1, x11 -; CHECK-NEXT: fmov d3, x12 -; CHECK-NEXT: mov v0.d[1], x9 -; CHECK-NEXT: mov v2.d[1], x13 -; CHECK-NEXT: mov v1.d[1], x14 -; CHECK-NEXT: mov v3.d[1], x15 +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtl v1.2d, v1.2s +; CHECK-NEXT: fcvtl v4.2d, v2.2s +; CHECK-NEXT: fcvtl v3.2d, v3.2s +; CHECK-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-NEXT: fcvtzs v2.2d, v1.2d +; CHECK-NEXT: fcvtzs v1.2d, v4.2d +; CHECK-NEXT: fcvtzs v3.2d, v3.2d ; CHECK-NEXT: ret %a = call <8 x i64> @llvm.llrint.v8i64.v8f32(<8 x float> %x) ret <8 x i64> %a @@ -458,58 +437,34 @@ declare <8 x i64> @llvm.llrint.v8i64.v8f32(<8 x float>) define <16 x i64> @llrint_v16i64_v16f32(<16 x float> %x) { ; CHECK-LABEL: llrint_v16i64_v16f32: ; CHECK: // %bb.0: -; CHECK-NEXT: frintx v4.2s, v0.2s -; CHECK-NEXT: frintx v5.2s, v1.2s -; CHECK-NEXT: ext v0.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: ext v1.16b, v1.16b, v1.16b, #8 +; CHECK-NEXT: ext v4.16b, v1.16b, v1.16b, #8 +; CHECK-NEXT: ext v5.16b, v0.16b, v0.16b, #8 ; CHECK-NEXT: ext v6.16b, v2.16b, v2.16b, #8 ; CHECK-NEXT: ext v7.16b, v3.16b, v3.16b, #8 -; CHECK-NEXT: frintx v2.2s, v2.2s -; CHECK-NEXT: frintx v3.2s, v3.2s -; CHECK-NEXT: mov s16, v4.s[1] -; CHECK-NEXT: mov s17, v5.s[1] -; CHECK-NEXT: fcvtzs x8, s4 ; CHECK-NEXT: frintx v0.2s, v0.2s ; CHECK-NEXT: frintx v1.2s, v1.2s -; CHECK-NEXT: fcvtzs x9, s5 -; CHECK-NEXT: frintx v4.2s, v6.2s -; CHECK-NEXT: frintx v5.2s, v7.2s -; CHECK-NEXT: fcvtzs x10, s2 -; CHECK-NEXT: mov s6, v2.s[1] -; CHECK-NEXT: fcvtzs x13, s3 -; CHECK-NEXT: mov s3, v3.s[1] -; CHECK-NEXT: fcvtzs x11, s16 -; CHECK-NEXT: fcvtzs x12, s17 -; CHECK-NEXT: mov s7, v0.s[1] -; CHECK-NEXT: mov s16, v1.s[1] -; CHECK-NEXT: fcvtzs x15, s1 -; CHECK-NEXT: mov s1, v4.s[1] -; CHECK-NEXT: mov s17, v5.s[1] -; CHECK-NEXT: fcvtzs x14, s0 -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: fcvtzs x8, s4 -; CHECK-NEXT: fmov d4, x10 -; CHECK-NEXT: fcvtzs x10, s5 -; CHECK-NEXT: fmov d2, x9 -; CHECK-NEXT: fcvtzs x9, s6 -; CHECK-NEXT: fmov d6, x13 -; CHECK-NEXT: fcvtzs x13, s7 -; CHECK-NEXT: fcvtzs x16, s16 -; CHECK-NEXT: fcvtzs x17, s3 -; CHECK-NEXT: fcvtzs x18, s1 -; CHECK-NEXT: fcvtzs x0, s17 -; CHECK-NEXT: fmov d1, x14 -; CHECK-NEXT: fmov d3, x15 -; CHECK-NEXT: fmov d5, x8 -; CHECK-NEXT: fmov d7, x10 -; CHECK-NEXT: mov v0.d[1], x11 -; CHECK-NEXT: mov v2.d[1], x12 -; CHECK-NEXT: mov v4.d[1], x9 -; CHECK-NEXT: mov v1.d[1], x13 -; CHECK-NEXT: mov v3.d[1], x16 -; CHECK-NEXT: mov v6.d[1], x17 -; CHECK-NEXT: mov v5.d[1], x18 -; CHECK-NEXT: mov v7.d[1], x0 +; CHECK-NEXT: frintx v2.2s, v2.2s +; CHECK-NEXT: frintx v3.2s, v3.2s +; CHECK-NEXT: frintx v5.2s, v5.2s +; CHECK-NEXT: frintx v4.2s, v4.2s +; CHECK-NEXT: frintx v6.2s, v6.2s +; CHECK-NEXT: frintx v7.2s, v7.2s +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtl v1.2d, v1.2s +; CHECK-NEXT: fcvtl v16.2d, v2.2s +; CHECK-NEXT: fcvtl v18.2d, v3.2s +; CHECK-NEXT: fcvtl v5.2d, v5.2s +; CHECK-NEXT: fcvtl v17.2d, v4.2s +; CHECK-NEXT: fcvtl v19.2d, v6.2s +; CHECK-NEXT: fcvtl v7.2d, v7.2s +; CHECK-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-NEXT: fcvtzs v2.2d, v1.2d +; CHECK-NEXT: fcvtzs v4.2d, v16.2d +; CHECK-NEXT: fcvtzs v6.2d, v18.2d +; CHECK-NEXT: fcvtzs v1.2d, v5.2d +; CHECK-NEXT: fcvtzs v3.2d, v17.2d +; CHECK-NEXT: fcvtzs v5.2d, v19.2d +; CHECK-NEXT: fcvtzs v7.2d, v7.2d ; CHECK-NEXT: ret %a = call <16 x i64> @llvm.llrint.v16i64.v16f32(<16 x float> %x) ret <16 x i64> %a @@ -519,118 +474,70 @@ declare <16 x i64> @llvm.llrint.v16i64.v16f32(<16 x float>) define <32 x i64> @llrint_v32i64_v32f32(<32 x float> %x) { ; CHECK-LABEL: llrint_v32i64_v32f32: ; CHECK: // %bb.0: -; CHECK-NEXT: ext v17.16b, v3.16b, v3.16b, #8 -; CHECK-NEXT: ext v18.16b, v4.16b, v4.16b, #8 -; CHECK-NEXT: ext v19.16b, v5.16b, v5.16b, #8 -; CHECK-NEXT: ext v21.16b, v7.16b, v7.16b, #8 -; CHECK-NEXT: ext v16.16b, v2.16b, v2.16b, #8 -; CHECK-NEXT: ext v20.16b, v6.16b, v6.16b, #8 +; CHECK-NEXT: ext v16.16b, v7.16b, v7.16b, #8 +; CHECK-NEXT: ext v17.16b, v6.16b, v6.16b, #8 ; CHECK-NEXT: frintx v7.2s, v7.2s -; CHECK-NEXT: frintx v24.2s, v6.2s -; CHECK-NEXT: frintx v23.2s, v5.2s +; CHECK-NEXT: frintx v6.2s, v6.2s +; CHECK-NEXT: ext v18.16b, v5.16b, v5.16b, #8 +; CHECK-NEXT: ext v21.16b, v4.16b, v4.16b, #8 +; CHECK-NEXT: ext v22.16b, v2.16b, v2.16b, #8 +; CHECK-NEXT: frintx v5.2s, v5.2s +; CHECK-NEXT: ext v23.16b, v3.16b, v3.16b, #8 ; CHECK-NEXT: frintx v4.2s, v4.2s -; CHECK-NEXT: frintx v3.2s, v3.2s +; CHECK-NEXT: ext v19.16b, v0.16b, v0.16b, #8 +; CHECK-NEXT: ext v20.16b, v1.16b, v1.16b, #8 +; CHECK-NEXT: frintx v16.2s, v16.2s ; CHECK-NEXT: frintx v17.2s, v17.2s +; CHECK-NEXT: fcvtl v7.2d, v7.2s +; CHECK-NEXT: fcvtl v6.2d, v6.2s ; CHECK-NEXT: frintx v18.2s, v18.2s -; CHECK-NEXT: frintx v22.2s, v19.2s ; CHECK-NEXT: frintx v21.2s, v21.2s -; CHECK-NEXT: frintx v16.2s, v16.2s -; CHECK-NEXT: frintx v20.2s, v20.2s -; CHECK-NEXT: mov s25, v7.s[1] -; CHECK-NEXT: fcvtzs x15, s7 -; CHECK-NEXT: frintx v19.2s, v1.2s -; CHECK-NEXT: fcvtzs x16, s24 -; CHECK-NEXT: ext v1.16b, v1.16b, v1.16b, #8 -; CHECK-NEXT: fcvtzs x10, s17 -; CHECK-NEXT: fcvtzs x11, s18 -; CHECK-NEXT: mov s26, v22.s[1] -; CHECK-NEXT: fcvtzs x12, s22 -; CHECK-NEXT: mov s22, v21.s[1] -; CHECK-NEXT: fcvtzs x14, s21 -; CHECK-NEXT: mov s21, v24.s[1] -; CHECK-NEXT: fcvtzs x9, s16 -; CHECK-NEXT: fcvtzs x13, s20 -; CHECK-NEXT: mov s20, v20.s[1] -; CHECK-NEXT: fmov d24, x15 -; CHECK-NEXT: mov s18, v18.s[1] -; CHECK-NEXT: fmov d6, x10 -; CHECK-NEXT: fmov d7, x11 -; CHECK-NEXT: fcvtzs x10, s25 -; CHECK-NEXT: fcvtzs x11, s22 -; CHECK-NEXT: fmov d25, x12 -; CHECK-NEXT: frintx v22.2s, v2.2s -; CHECK-NEXT: fcvtzs x15, s21 -; CHECK-NEXT: fmov d21, x14 -; CHECK-NEXT: fmov d5, x9 -; CHECK-NEXT: fcvtzs x9, s26 -; CHECK-NEXT: fmov d26, x13 -; CHECK-NEXT: fcvtzs x12, s20 -; CHECK-NEXT: fcvtzs x13, s19 -; CHECK-NEXT: mov s20, v23.s[1] -; CHECK-NEXT: mov v24.d[1], x10 -; CHECK-NEXT: mov v21.d[1], x11 -; CHECK-NEXT: fcvtzs x11, s23 -; CHECK-NEXT: fcvtzs x10, s22 -; CHECK-NEXT: mov s17, v17.s[1] +; CHECK-NEXT: frintx v2.2s, v2.2s +; CHECK-NEXT: frintx v3.2s, v3.2s +; CHECK-NEXT: fcvtl v5.2d, v5.2s +; CHECK-NEXT: frintx v23.2s, v23.2s +; CHECK-NEXT: fcvtl v4.2d, v4.2s ; CHECK-NEXT: frintx v1.2s, v1.2s -; CHECK-NEXT: mov s22, v22.s[1] -; CHECK-NEXT: mov v26.d[1], x12 -; CHECK-NEXT: fcvtzs x12, s18 -; CHECK-NEXT: mov v25.d[1], x9 -; CHECK-NEXT: fmov d2, x13 -; CHECK-NEXT: fcvtzs x13, s20 -; CHECK-NEXT: fmov d20, x16 -; CHECK-NEXT: stp q24, q21, [x8, #224] -; CHECK-NEXT: ext v21.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: fmov d18, x11 -; CHECK-NEXT: fcvtzs x11, s4 -; CHECK-NEXT: mov s4, v4.s[1] -; CHECK-NEXT: fmov d23, x10 -; CHECK-NEXT: mov v20.d[1], x15 -; CHECK-NEXT: fcvtzs x10, s3 -; CHECK-NEXT: mov s3, v3.s[1] -; CHECK-NEXT: mov v18.d[1], x13 +; CHECK-NEXT: fcvtl v16.2d, v16.2s +; CHECK-NEXT: fcvtl v17.2d, v17.2s +; CHECK-NEXT: fcvtzs v7.2d, v7.2d +; CHECK-NEXT: fcvtzs v6.2d, v6.2d +; CHECK-NEXT: fcvtl v18.2d, v18.2s +; CHECK-NEXT: fcvtl v21.2d, v21.2s +; CHECK-NEXT: frintx v20.2s, v20.2s +; CHECK-NEXT: fcvtl v3.2d, v3.2s +; CHECK-NEXT: fcvtzs v5.2d, v5.2d ; CHECK-NEXT: frintx v0.2s, v0.2s -; CHECK-NEXT: mov s16, v16.s[1] -; CHECK-NEXT: frintx v21.2s, v21.2s -; CHECK-NEXT: fcvtzs x13, s17 -; CHECK-NEXT: fcvtzs x14, s22 -; CHECK-NEXT: fcvtzs x9, s4 -; CHECK-NEXT: fmov d4, x11 -; CHECK-NEXT: mov v7.d[1], x12 -; CHECK-NEXT: stp q20, q26, [x8, #192] -; CHECK-NEXT: fmov d20, x10 -; CHECK-NEXT: fcvtzs x10, s3 -; CHECK-NEXT: stp q18, q25, [x8, #160] -; CHECK-NEXT: mov s18, v19.s[1] -; CHECK-NEXT: mov s3, v1.s[1] -; CHECK-NEXT: mov s17, v0.s[1] -; CHECK-NEXT: mov s19, v21.s[1] -; CHECK-NEXT: fcvtzs x11, s21 -; CHECK-NEXT: mov v4.d[1], x9 -; CHECK-NEXT: fcvtzs x9, s16 -; CHECK-NEXT: fcvtzs x12, s1 -; CHECK-NEXT: mov v6.d[1], x13 -; CHECK-NEXT: fcvtzs x13, s0 -; CHECK-NEXT: mov v20.d[1], x10 -; CHECK-NEXT: fcvtzs x15, s18 -; CHECK-NEXT: fcvtzs x10, s3 -; CHECK-NEXT: mov v23.d[1], x14 -; CHECK-NEXT: fcvtzs x14, s17 -; CHECK-NEXT: fmov d3, x11 -; CHECK-NEXT: stp q4, q7, [x8, #128] -; CHECK-NEXT: mov v5.d[1], x9 -; CHECK-NEXT: fcvtzs x9, s19 -; CHECK-NEXT: stp q20, q6, [x8, #96] -; CHECK-NEXT: fmov d0, x12 -; CHECK-NEXT: fmov d1, x13 -; CHECK-NEXT: mov v2.d[1], x15 -; CHECK-NEXT: stp q23, q5, [x8, #64] -; CHECK-NEXT: mov v0.d[1], x10 -; CHECK-NEXT: mov v1.d[1], x14 -; CHECK-NEXT: mov v3.d[1], x9 -; CHECK-NEXT: stp q2, q0, [x8, #32] -; CHECK-NEXT: stp q1, q3, [x8] +; CHECK-NEXT: fcvtl v2.2d, v2.2s +; CHECK-NEXT: fcvtzs v4.2d, v4.2d +; CHECK-NEXT: fcvtzs v16.2d, v16.2d +; CHECK-NEXT: fcvtzs v17.2d, v17.2d +; CHECK-NEXT: fcvtl v1.2d, v1.2s +; CHECK-NEXT: fcvtzs v3.2d, v3.2d +; CHECK-NEXT: fcvtl v0.2d, v0.2s +; CHECK-NEXT: fcvtzs v2.2d, v2.2d +; CHECK-NEXT: stp q6, q17, [x8, #192] +; CHECK-NEXT: fcvtl v6.2d, v23.2s +; CHECK-NEXT: frintx v17.2s, v19.2s +; CHECK-NEXT: stp q7, q16, [x8, #224] +; CHECK-NEXT: frintx v7.2s, v22.2s +; CHECK-NEXT: fcvtzs v16.2d, v18.2d +; CHECK-NEXT: fcvtzs v18.2d, v21.2d +; CHECK-NEXT: fcvtzs v1.2d, v1.2d +; CHECK-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-NEXT: fcvtzs v6.2d, v6.2d +; CHECK-NEXT: stp q5, q16, [x8, #160] +; CHECK-NEXT: fcvtl v7.2d, v7.2s +; CHECK-NEXT: fcvtl v5.2d, v20.2s +; CHECK-NEXT: stp q4, q18, [x8, #128] +; CHECK-NEXT: fcvtl v4.2d, v17.2s +; CHECK-NEXT: stp q3, q6, [x8, #96] +; CHECK-NEXT: fcvtzs v7.2d, v7.2d +; CHECK-NEXT: fcvtzs v3.2d, v5.2d +; CHECK-NEXT: stp q1, q3, [x8, #32] +; CHECK-NEXT: stp q2, q7, [x8, #64] +; CHECK-NEXT: fcvtzs v2.2d, v4.2d +; CHECK-NEXT: stp q0, q2, [x8] ; CHECK-NEXT: ret %a = call <32 x i64> @llvm.llrint.v32i64.v32f32(<32 x float> %x) ret <32 x i64> %a diff --git a/llvm/test/CodeGen/AArch64/vector-lrint.ll b/llvm/test/CodeGen/AArch64/vector-lrint.ll index 44f29f1420fe..602643264e7b 100644 --- a/llvm/test/CodeGen/AArch64/vector-lrint.ll +++ b/llvm/test/CodeGen/AArch64/vector-lrint.ll @@ -784,11 +784,8 @@ define <2 x iXLen> @lrint_v2f32(<2 x float> %x) { ; CHECK-i64-LABEL: lrint_v2f32: ; CHECK-i64: // %bb.0: ; CHECK-i64-NEXT: frintx v0.2s, v0.2s -; CHECK-i64-NEXT: mov s1, v0.s[1] -; CHECK-i64-NEXT: fcvtzs x8, s0 -; CHECK-i64-NEXT: fcvtzs x9, s1 -; CHECK-i64-NEXT: fmov d0, x8 -; CHECK-i64-NEXT: mov v0.d[1], x9 +; CHECK-i64-NEXT: fcvtl v0.2d, v0.2s +; CHECK-i64-NEXT: fcvtzs v0.2d, v0.2d ; CHECK-i64-NEXT: ret %a = call <2 x iXLen> @llvm.lrint.v2iXLen.v2f32(<2 x float> %x) ret <2 x iXLen> %a @@ -807,16 +804,10 @@ define <4 x iXLen> @lrint_v4f32(<4 x float> %x) { ; CHECK-i64-NEXT: ext v1.16b, v0.16b, v0.16b, #8 ; CHECK-i64-NEXT: frintx v0.2s, v0.2s ; CHECK-i64-NEXT: frintx v1.2s, v1.2s -; CHECK-i64-NEXT: mov s2, v0.s[1] -; CHECK-i64-NEXT: fcvtzs x8, s0 -; CHECK-i64-NEXT: mov s3, v1.s[1] -; CHECK-i64-NEXT: fcvtzs x9, s1 -; CHECK-i64-NEXT: fcvtzs x10, s2 -; CHECK-i64-NEXT: fmov d0, x8 -; CHECK-i64-NEXT: fcvtzs x11, s3 -; CHECK-i64-NEXT: fmov d1, x9 -; CHECK-i64-NEXT: mov v0.d[1], x10 -; CHECK-i64-NEXT: mov v1.d[1], x11 +; CHECK-i64-NEXT: fcvtl v0.2d, v0.2s +; CHECK-i64-NEXT: fcvtl v1.2d, v1.2s +; CHECK-i64-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-i64-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-i64-NEXT: ret %a = call <4 x iXLen> @llvm.lrint.v4iXLen.v4f32(<4 x float> %x) ret <4 x iXLen> %a @@ -840,26 +831,14 @@ define <8 x iXLen> @lrint_v8f32(<8 x float> %x) { ; CHECK-i64-NEXT: frintx v1.2s, v1.2s ; CHECK-i64-NEXT: frintx v2.2s, v2.2s ; CHECK-i64-NEXT: frintx v3.2s, v3.2s -; CHECK-i64-NEXT: mov s4, v0.s[1] -; CHECK-i64-NEXT: mov s5, v1.s[1] -; CHECK-i64-NEXT: fcvtzs x8, s0 -; CHECK-i64-NEXT: fcvtzs x10, s1 -; CHECK-i64-NEXT: mov s6, v2.s[1] -; CHECK-i64-NEXT: mov s7, v3.s[1] -; CHECK-i64-NEXT: fcvtzs x11, s2 -; CHECK-i64-NEXT: fcvtzs x12, s3 -; CHECK-i64-NEXT: fcvtzs x9, s4 -; CHECK-i64-NEXT: fcvtzs x13, s5 -; CHECK-i64-NEXT: fmov d0, x8 -; CHECK-i64-NEXT: fmov d2, x10 -; CHECK-i64-NEXT: fcvtzs x14, s6 -; CHECK-i64-NEXT: fcvtzs x15, s7 -; CHECK-i64-NEXT: fmov d1, x11 -; CHECK-i64-NEXT: fmov d3, x12 -; CHECK-i64-NEXT: mov v0.d[1], x9 -; CHECK-i64-NEXT: mov v2.d[1], x13 -; CHECK-i64-NEXT: mov v1.d[1], x14 -; CHECK-i64-NEXT: mov v3.d[1], x15 +; CHECK-i64-NEXT: fcvtl v0.2d, v0.2s +; CHECK-i64-NEXT: fcvtl v1.2d, v1.2s +; CHECK-i64-NEXT: fcvtl v4.2d, v2.2s +; CHECK-i64-NEXT: fcvtl v3.2d, v3.2s +; CHECK-i64-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-i64-NEXT: fcvtzs v2.2d, v1.2d +; CHECK-i64-NEXT: fcvtzs v1.2d, v4.2d +; CHECK-i64-NEXT: fcvtzs v3.2d, v3.2d ; CHECK-i64-NEXT: ret %a = call <8 x iXLen> @llvm.lrint.v8iXLen.v8f32(<8 x float> %x) ret <8 x iXLen> %a @@ -881,58 +860,34 @@ define <16 x iXLen> @lrint_v16f32(<16 x float> %x) { ; ; CHECK-i64-LABEL: lrint_v16f32: ; CHECK-i64: // %bb.0: -; CHECK-i64-NEXT: frintx v4.2s, v0.2s -; CHECK-i64-NEXT: frintx v5.2s, v1.2s -; CHECK-i64-NEXT: ext v0.16b, v0.16b, v0.16b, #8 -; CHECK-i64-NEXT: ext v1.16b, v1.16b, v1.16b, #8 +; CHECK-i64-NEXT: ext v4.16b, v1.16b, v1.16b, #8 +; CHECK-i64-NEXT: ext v5.16b, v0.16b, v0.16b, #8 ; CHECK-i64-NEXT: ext v6.16b, v2.16b, v2.16b, #8 ; CHECK-i64-NEXT: ext v7.16b, v3.16b, v3.16b, #8 -; CHECK-i64-NEXT: frintx v2.2s, v2.2s -; CHECK-i64-NEXT: frintx v3.2s, v3.2s -; CHECK-i64-NEXT: mov s16, v4.s[1] -; CHECK-i64-NEXT: mov s17, v5.s[1] -; CHECK-i64-NEXT: fcvtzs x8, s4 ; CHECK-i64-NEXT: frintx v0.2s, v0.2s ; CHECK-i64-NEXT: frintx v1.2s, v1.2s -; CHECK-i64-NEXT: fcvtzs x9, s5 -; CHECK-i64-NEXT: frintx v4.2s, v6.2s -; CHECK-i64-NEXT: frintx v5.2s, v7.2s -; CHECK-i64-NEXT: fcvtzs x10, s2 -; CHECK-i64-NEXT: mov s6, v2.s[1] -; CHECK-i64-NEXT: fcvtzs x13, s3 -; CHECK-i64-NEXT: mov s3, v3.s[1] -; CHECK-i64-NEXT: fcvtzs x11, s16 -; CHECK-i64-NEXT: fcvtzs x12, s17 -; CHECK-i64-NEXT: mov s7, v0.s[1] -; CHECK-i64-NEXT: mov s16, v1.s[1] -; CHECK-i64-NEXT: fcvtzs x15, s1 -; CHECK-i64-NEXT: mov s1, v4.s[1] -; CHECK-i64-NEXT: mov s17, v5.s[1] -; CHECK-i64-NEXT: fcvtzs x14, s0 -; CHECK-i64-NEXT: fmov d0, x8 -; CHECK-i64-NEXT: fcvtzs x8, s4 -; CHECK-i64-NEXT: fmov d4, x10 -; CHECK-i64-NEXT: fcvtzs x10, s5 -; CHECK-i64-NEXT: fmov d2, x9 -; CHECK-i64-NEXT: fcvtzs x9, s6 -; CHECK-i64-NEXT: fmov d6, x13 -; CHECK-i64-NEXT: fcvtzs x13, s7 -; CHECK-i64-NEXT: fcvtzs x16, s16 -; CHECK-i64-NEXT: fcvtzs x17, s3 -; CHECK-i64-NEXT: fcvtzs x18, s1 -; CHECK-i64-NEXT: fcvtzs x0, s17 -; CHECK-i64-NEXT: fmov d1, x14 -; CHECK-i64-NEXT: fmov d3, x15 -; CHECK-i64-NEXT: fmov d5, x8 -; CHECK-i64-NEXT: fmov d7, x10 -; CHECK-i64-NEXT: mov v0.d[1], x11 -; CHECK-i64-NEXT: mov v2.d[1], x12 -; CHECK-i64-NEXT: mov v4.d[1], x9 -; CHECK-i64-NEXT: mov v1.d[1], x13 -; CHECK-i64-NEXT: mov v3.d[1], x16 -; CHECK-i64-NEXT: mov v6.d[1], x17 -; CHECK-i64-NEXT: mov v5.d[1], x18 -; CHECK-i64-NEXT: mov v7.d[1], x0 +; CHECK-i64-NEXT: frintx v2.2s, v2.2s +; CHECK-i64-NEXT: frintx v3.2s, v3.2s +; CHECK-i64-NEXT: frintx v5.2s, v5.2s +; CHECK-i64-NEXT: frintx v4.2s, v4.2s +; CHECK-i64-NEXT: frintx v6.2s, v6.2s +; CHECK-i64-NEXT: frintx v7.2s, v7.2s +; CHECK-i64-NEXT: fcvtl v0.2d, v0.2s +; CHECK-i64-NEXT: fcvtl v1.2d, v1.2s +; CHECK-i64-NEXT: fcvtl v16.2d, v2.2s +; CHECK-i64-NEXT: fcvtl v18.2d, v3.2s +; CHECK-i64-NEXT: fcvtl v5.2d, v5.2s +; CHECK-i64-NEXT: fcvtl v17.2d, v4.2s +; CHECK-i64-NEXT: fcvtl v19.2d, v6.2s +; CHECK-i64-NEXT: fcvtl v7.2d, v7.2s +; CHECK-i64-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-i64-NEXT: fcvtzs v2.2d, v1.2d +; CHECK-i64-NEXT: fcvtzs v4.2d, v16.2d +; CHECK-i64-NEXT: fcvtzs v6.2d, v18.2d +; CHECK-i64-NEXT: fcvtzs v1.2d, v5.2d +; CHECK-i64-NEXT: fcvtzs v3.2d, v17.2d +; CHECK-i64-NEXT: fcvtzs v5.2d, v19.2d +; CHECK-i64-NEXT: fcvtzs v7.2d, v7.2d ; CHECK-i64-NEXT: ret %a = call <16 x iXLen> @llvm.lrint.v16iXLen.v16f32(<16 x float> %x) ret <16 x iXLen> %a @@ -962,118 +917,70 @@ define <32 x iXLen> @lrint_v32f32(<32 x float> %x) { ; ; CHECK-i64-LABEL: lrint_v32f32: ; CHECK-i64: // %bb.0: -; CHECK-i64-NEXT: ext v17.16b, v3.16b, v3.16b, #8 -; CHECK-i64-NEXT: ext v18.16b, v4.16b, v4.16b, #8 -; CHECK-i64-NEXT: ext v19.16b, v5.16b, v5.16b, #8 -; CHECK-i64-NEXT: ext v21.16b, v7.16b, v7.16b, #8 -; CHECK-i64-NEXT: ext v16.16b, v2.16b, v2.16b, #8 -; CHECK-i64-NEXT: ext v20.16b, v6.16b, v6.16b, #8 +; CHECK-i64-NEXT: ext v16.16b, v7.16b, v7.16b, #8 +; CHECK-i64-NEXT: ext v17.16b, v6.16b, v6.16b, #8 ; CHECK-i64-NEXT: frintx v7.2s, v7.2s -; CHECK-i64-NEXT: frintx v24.2s, v6.2s -; CHECK-i64-NEXT: frintx v23.2s, v5.2s +; CHECK-i64-NEXT: frintx v6.2s, v6.2s +; CHECK-i64-NEXT: ext v18.16b, v5.16b, v5.16b, #8 +; CHECK-i64-NEXT: ext v21.16b, v4.16b, v4.16b, #8 +; CHECK-i64-NEXT: ext v22.16b, v2.16b, v2.16b, #8 +; CHECK-i64-NEXT: frintx v5.2s, v5.2s +; CHECK-i64-NEXT: ext v23.16b, v3.16b, v3.16b, #8 ; CHECK-i64-NEXT: frintx v4.2s, v4.2s -; CHECK-i64-NEXT: frintx v3.2s, v3.2s +; CHECK-i64-NEXT: ext v19.16b, v0.16b, v0.16b, #8 +; CHECK-i64-NEXT: ext v20.16b, v1.16b, v1.16b, #8 +; CHECK-i64-NEXT: frintx v16.2s, v16.2s ; CHECK-i64-NEXT: frintx v17.2s, v17.2s +; CHECK-i64-NEXT: fcvtl v7.2d, v7.2s +; CHECK-i64-NEXT: fcvtl v6.2d, v6.2s ; CHECK-i64-NEXT: frintx v18.2s, v18.2s -; CHECK-i64-NEXT: frintx v22.2s, v19.2s ; CHECK-i64-NEXT: frintx v21.2s, v21.2s -; CHECK-i64-NEXT: frintx v16.2s, v16.2s -; CHECK-i64-NEXT: frintx v20.2s, v20.2s -; CHECK-i64-NEXT: mov s25, v7.s[1] -; CHECK-i64-NEXT: fcvtzs x15, s7 -; CHECK-i64-NEXT: frintx v19.2s, v1.2s -; CHECK-i64-NEXT: fcvtzs x16, s24 -; CHECK-i64-NEXT: ext v1.16b, v1.16b, v1.16b, #8 -; CHECK-i64-NEXT: fcvtzs x10, s17 -; CHECK-i64-NEXT: fcvtzs x11, s18 -; CHECK-i64-NEXT: mov s26, v22.s[1] -; CHECK-i64-NEXT: fcvtzs x12, s22 -; CHECK-i64-NEXT: mov s22, v21.s[1] -; CHECK-i64-NEXT: fcvtzs x14, s21 -; CHECK-i64-NEXT: mov s21, v24.s[1] -; CHECK-i64-NEXT: fcvtzs x9, s16 -; CHECK-i64-NEXT: fcvtzs x13, s20 -; CHECK-i64-NEXT: mov s20, v20.s[1] -; CHECK-i64-NEXT: fmov d24, x15 -; CHECK-i64-NEXT: mov s18, v18.s[1] -; CHECK-i64-NEXT: fmov d6, x10 -; CHECK-i64-NEXT: fmov d7, x11 -; CHECK-i64-NEXT: fcvtzs x10, s25 -; CHECK-i64-NEXT: fcvtzs x11, s22 -; CHECK-i64-NEXT: fmov d25, x12 -; CHECK-i64-NEXT: frintx v22.2s, v2.2s -; CHECK-i64-NEXT: fcvtzs x15, s21 -; CHECK-i64-NEXT: fmov d21, x14 -; CHECK-i64-NEXT: fmov d5, x9 -; CHECK-i64-NEXT: fcvtzs x9, s26 -; CHECK-i64-NEXT: fmov d26, x13 -; CHECK-i64-NEXT: fcvtzs x12, s20 -; CHECK-i64-NEXT: fcvtzs x13, s19 -; CHECK-i64-NEXT: mov s20, v23.s[1] -; CHECK-i64-NEXT: mov v24.d[1], x10 -; CHECK-i64-NEXT: mov v21.d[1], x11 -; CHECK-i64-NEXT: fcvtzs x11, s23 -; CHECK-i64-NEXT: fcvtzs x10, s22 -; CHECK-i64-NEXT: mov s17, v17.s[1] +; CHECK-i64-NEXT: frintx v2.2s, v2.2s +; CHECK-i64-NEXT: frintx v3.2s, v3.2s +; CHECK-i64-NEXT: fcvtl v5.2d, v5.2s +; CHECK-i64-NEXT: frintx v23.2s, v23.2s +; CHECK-i64-NEXT: fcvtl v4.2d, v4.2s ; CHECK-i64-NEXT: frintx v1.2s, v1.2s -; CHECK-i64-NEXT: mov s22, v22.s[1] -; CHECK-i64-NEXT: mov v26.d[1], x12 -; CHECK-i64-NEXT: fcvtzs x12, s18 -; CHECK-i64-NEXT: mov v25.d[1], x9 -; CHECK-i64-NEXT: fmov d2, x13 -; CHECK-i64-NEXT: fcvtzs x13, s20 -; CHECK-i64-NEXT: fmov d20, x16 -; CHECK-i64-NEXT: stp q24, q21, [x8, #224] -; CHECK-i64-NEXT: ext v21.16b, v0.16b, v0.16b, #8 -; CHECK-i64-NEXT: fmov d18, x11 -; CHECK-i64-NEXT: fcvtzs x11, s4 -; CHECK-i64-NEXT: mov s4, v4.s[1] -; CHECK-i64-NEXT: fmov d23, x10 -; CHECK-i64-NEXT: mov v20.d[1], x15 -; CHECK-i64-NEXT: fcvtzs x10, s3 -; CHECK-i64-NEXT: mov s3, v3.s[1] -; CHECK-i64-NEXT: mov v18.d[1], x13 +; CHECK-i64-NEXT: fcvtl v16.2d, v16.2s +; CHECK-i64-NEXT: fcvtl v17.2d, v17.2s +; CHECK-i64-NEXT: fcvtzs v7.2d, v7.2d +; CHECK-i64-NEXT: fcvtzs v6.2d, v6.2d +; CHECK-i64-NEXT: fcvtl v18.2d, v18.2s +; CHECK-i64-NEXT: fcvtl v21.2d, v21.2s +; CHECK-i64-NEXT: frintx v20.2s, v20.2s +; CHECK-i64-NEXT: fcvtl v3.2d, v3.2s +; CHECK-i64-NEXT: fcvtzs v5.2d, v5.2d ; CHECK-i64-NEXT: frintx v0.2s, v0.2s -; CHECK-i64-NEXT: mov s16, v16.s[1] -; CHECK-i64-NEXT: frintx v21.2s, v21.2s -; CHECK-i64-NEXT: fcvtzs x13, s17 -; CHECK-i64-NEXT: fcvtzs x14, s22 -; CHECK-i64-NEXT: fcvtzs x9, s4 -; CHECK-i64-NEXT: fmov d4, x11 -; CHECK-i64-NEXT: mov v7.d[1], x12 -; CHECK-i64-NEXT: stp q20, q26, [x8, #192] -; CHECK-i64-NEXT: fmov d20, x10 -; CHECK-i64-NEXT: fcvtzs x10, s3 -; CHECK-i64-NEXT: stp q18, q25, [x8, #160] -; CHECK-i64-NEXT: mov s18, v19.s[1] -; CHECK-i64-NEXT: mov s3, v1.s[1] -; CHECK-i64-NEXT: mov s17, v0.s[1] -; CHECK-i64-NEXT: mov s19, v21.s[1] -; CHECK-i64-NEXT: fcvtzs x11, s21 -; CHECK-i64-NEXT: mov v4.d[1], x9 -; CHECK-i64-NEXT: fcvtzs x9, s16 -; CHECK-i64-NEXT: fcvtzs x12, s1 -; CHECK-i64-NEXT: mov v6.d[1], x13 -; CHECK-i64-NEXT: fcvtzs x13, s0 -; CHECK-i64-NEXT: mov v20.d[1], x10 -; CHECK-i64-NEXT: fcvtzs x15, s18 -; CHECK-i64-NEXT: fcvtzs x10, s3 -; CHECK-i64-NEXT: mov v23.d[1], x14 -; CHECK-i64-NEXT: fcvtzs x14, s17 -; CHECK-i64-NEXT: fmov d3, x11 -; CHECK-i64-NEXT: stp q4, q7, [x8, #128] -; CHECK-i64-NEXT: mov v5.d[1], x9 -; CHECK-i64-NEXT: fcvtzs x9, s19 -; CHECK-i64-NEXT: stp q20, q6, [x8, #96] -; CHECK-i64-NEXT: fmov d0, x12 -; CHECK-i64-NEXT: fmov d1, x13 -; CHECK-i64-NEXT: mov v2.d[1], x15 -; CHECK-i64-NEXT: stp q23, q5, [x8, #64] -; CHECK-i64-NEXT: mov v0.d[1], x10 -; CHECK-i64-NEXT: mov v1.d[1], x14 -; CHECK-i64-NEXT: mov v3.d[1], x9 -; CHECK-i64-NEXT: stp q2, q0, [x8, #32] -; CHECK-i64-NEXT: stp q1, q3, [x8] +; CHECK-i64-NEXT: fcvtl v2.2d, v2.2s +; CHECK-i64-NEXT: fcvtzs v4.2d, v4.2d +; CHECK-i64-NEXT: fcvtzs v16.2d, v16.2d +; CHECK-i64-NEXT: fcvtzs v17.2d, v17.2d +; CHECK-i64-NEXT: fcvtl v1.2d, v1.2s +; CHECK-i64-NEXT: fcvtzs v3.2d, v3.2d +; CHECK-i64-NEXT: fcvtl v0.2d, v0.2s +; CHECK-i64-NEXT: fcvtzs v2.2d, v2.2d +; CHECK-i64-NEXT: stp q6, q17, [x8, #192] +; CHECK-i64-NEXT: fcvtl v6.2d, v23.2s +; CHECK-i64-NEXT: frintx v17.2s, v19.2s +; CHECK-i64-NEXT: stp q7, q16, [x8, #224] +; CHECK-i64-NEXT: frintx v7.2s, v22.2s +; CHECK-i64-NEXT: fcvtzs v16.2d, v18.2d +; CHECK-i64-NEXT: fcvtzs v18.2d, v21.2d +; CHECK-i64-NEXT: fcvtzs v1.2d, v1.2d +; CHECK-i64-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-i64-NEXT: fcvtzs v6.2d, v6.2d +; CHECK-i64-NEXT: stp q5, q16, [x8, #160] +; CHECK-i64-NEXT: fcvtl v7.2d, v7.2s +; CHECK-i64-NEXT: fcvtl v5.2d, v20.2s +; CHECK-i64-NEXT: stp q4, q18, [x8, #128] +; CHECK-i64-NEXT: fcvtl v4.2d, v17.2s +; CHECK-i64-NEXT: stp q3, q6, [x8, #96] +; CHECK-i64-NEXT: fcvtzs v7.2d, v7.2d +; CHECK-i64-NEXT: fcvtzs v3.2d, v5.2d +; CHECK-i64-NEXT: stp q1, q3, [x8, #32] +; CHECK-i64-NEXT: stp q2, q7, [x8, #64] +; CHECK-i64-NEXT: fcvtzs v2.2d, v4.2d +; CHECK-i64-NEXT: stp q0, q2, [x8] ; CHECK-i64-NEXT: ret %a = call <32 x iXLen> @llvm.lrint.v32iXLen.v32f32(<32 x float> %x) ret <32 x iXLen> %a -- GitLab From ae2a18d6cbc3328410bdb7e629fdc59766b73e4b Mon Sep 17 00:00:00 2001 From: Adrian Kuegel Date: Mon, 13 May 2024 07:47:33 +0000 Subject: [PATCH 026/578] [mlir][Bazel] Adjust BUILD.bazel for eeafc9daa15d2d022bcdd456d4b8bafd23f5f121 --- utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel index 0ebfcbe284bd..65b31dc97e2d 100644 --- a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel @@ -121,6 +121,7 @@ td_library( "//mlir:InferIntRangeInterfaceTdFiles", "//mlir:InferTypeOpInterfaceTdFiles", "//mlir:LinalgStructuredOpsTdFiles", + "//mlir:MemorySlotInterfacesTdFiles", "//mlir:OpBaseTdFiles", "//mlir:SideEffectInterfacesTdFiles", ], @@ -418,6 +419,7 @@ cc_library( "//mlir:LLVMIRToLLVMTranslation", "//mlir:LinalgDialect", "//mlir:LoopLikeInterface", + "//mlir:MemorySlotInterfaces", "//mlir:Pass", "//mlir:Reducer", "//mlir:SideEffectInterfaces", -- GitLab From 279a659e9772e48d95ad7d81f6deb00ee31e35e1 Mon Sep 17 00:00:00 2001 From: Corentin Ferry Date: Mon, 13 May 2024 10:15:39 +0200 Subject: [PATCH 027/578] [mlir][math] lower rsqrt to sqrt + fdiv (#91344) This commit creates an expansion pattern to lower math.rsqrt(x) into fdiv(1, sqrt(x)). --- .../mlir/Dialect/Math/Transforms/Passes.h | 1 + .../Math/Transforms/ExpandPatterns.cpp | 21 ++++++ mlir/test/Dialect/Math/expand-math.mlir | 70 +++++++++++++++++++ mlir/test/lib/Dialect/Math/TestExpandMath.cpp | 1 + .../test-expand-math-approx.mlir | 41 +++++++++++ 5 files changed, 134 insertions(+) diff --git a/mlir/include/mlir/Dialect/Math/Transforms/Passes.h b/mlir/include/mlir/Dialect/Math/Transforms/Passes.h index 24e6d9a8d98e..ba6977251564 100644 --- a/mlir/include/mlir/Dialect/Math/Transforms/Passes.h +++ b/mlir/include/mlir/Dialect/Math/Transforms/Passes.h @@ -42,6 +42,7 @@ void populateExpandPowFPattern(RewritePatternSet &patterns); void populateExpandFPowIPattern(RewritePatternSet &patterns); void populateExpandRoundFPattern(RewritePatternSet &patterns); void populateExpandRoundEvenPattern(RewritePatternSet &patterns); +void populateExpandRsqrtPattern(RewritePatternSet &patterns); void populateMathAlgebraicSimplificationPatterns(RewritePatternSet &patterns); struct MathPolynomialApproximationOptions { diff --git a/mlir/lib/Dialect/Math/Transforms/ExpandPatterns.cpp b/mlir/lib/Dialect/Math/Transforms/ExpandPatterns.cpp index 5ccf3b6d72a2..80569d95137c 100644 --- a/mlir/lib/Dialect/Math/Transforms/ExpandPatterns.cpp +++ b/mlir/lib/Dialect/Math/Transforms/ExpandPatterns.cpp @@ -615,6 +615,23 @@ static LogicalResult convertRoundEvenOp(math::RoundEvenOp op, return success(); } +// Convert `math.rsqrt` into `arith.divf` + `math.sqrt` +static LogicalResult convertRsqrtOp(math::RsqrtOp op, + PatternRewriter &rewriter) { + + auto operand = op.getOperand(); + auto operandTy = operand.getType(); + auto eTy = getElementTypeOrSelf(operandTy); + if (!isa(eTy)) + return failure(); + + Location loc = op->getLoc(); + auto constOneFloat = createFloatConst(loc, operandTy, 1.0, rewriter); + auto sqrtOp = rewriter.create(loc, operand); + rewriter.replaceOpWithNewOp(op, constOneFloat, sqrtOp); + return success(); +} + void mlir::populateExpandCtlzPattern(RewritePatternSet &patterns) { patterns.add(convertCtlzOp); } @@ -678,3 +695,7 @@ void mlir::populateExpandFloorFPattern(RewritePatternSet &patterns) { void mlir::populateExpandRoundEvenPattern(RewritePatternSet &patterns) { patterns.add(convertRoundEvenOp); } + +void mlir::populateExpandRsqrtPattern(RewritePatternSet &patterns) { + patterns.add(convertRsqrtOp); +} diff --git a/mlir/test/Dialect/Math/expand-math.mlir b/mlir/test/Dialect/Math/expand-math.mlir index 3d94b55126d0..016a7bbdeb56 100644 --- a/mlir/test/Dialect/Math/expand-math.mlir +++ b/mlir/test/Dialect/Math/expand-math.mlir @@ -658,3 +658,73 @@ func.func @math_fpowi_to_powf_scalar(%0 : f32, %1: i64) -> f32 { // CHECK: %[[AND:.*]] = arith.andi %[[CMPF1]], %[[CMPF]] : i1 // CHECK: %[[SEL:.*]] = arith.select %[[AND]], %[[MUL1]], %[[EXP]] : f32 // CHECK: return %[[SEL]] : f32 + +// ----- + +// CHECK-LABEL: func.func @rsqrt +// CHECK-SAME: (%[[ARG:.*]]: f16) +// CHECK-SAME: -> f16 +// CHECK-DAG: %[[CST:.*]] = arith.constant 1.000000e+00 : f16 +// CHECK-DAG: %[[SQRT:.*]] = math.sqrt %[[ARG]] : f16 +// CHECK-DAG: %[[DIV:.*]] = arith.divf %[[CST]], %[[SQRT]] : f16 +// CHECK: return %[[DIV]] : f16 +func.func @rsqrt16(%float: f16) -> (f16) { + %float_result = math.rsqrt %float : f16 + return %float_result : f16 +} + +// ----- + +// CHECK-LABEL: func.func @rsqrt +// CHECK-SAME: (%[[ARG:.*]]: f32) +// CHECK-SAME: -> f32 +// CHECK-DAG: %[[CST:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK-DAG: %[[SQRT:.*]] = math.sqrt %[[ARG]] : f32 +// CHECK-DAG: %[[DIV:.*]] = arith.divf %[[CST]], %[[SQRT]] : f32 +// CHECK: return %[[DIV]] : f32 +func.func @rsqrt32(%float: f32) -> (f32) { + %float_result = math.rsqrt %float : f32 + return %float_result : f32 +} + +// ----- + +// CHECK-LABEL: func.func @rsqrt +// CHECK-SAME: (%[[ARG:.*]]: f64) +// CHECK-SAME: -> f64 +// CHECK-DAG: %[[CST:.*]] = arith.constant 1.000000e+00 : f64 +// CHECK-DAG: %[[SQRT:.*]] = math.sqrt %[[ARG]] : f64 +// CHECK-DAG: %[[DIV:.*]] = arith.divf %[[CST]], %[[SQRT]] : f64 +// CHECK: return %[[DIV]] : f64 +func.func @rsqrt64(%float: f64) -> (f64) { + %float_result = math.rsqrt %float : f64 + return %float_result : f64 +} + +// ----- + +// CHECK-LABEL: func.func @rsqrt_vec +// CHECK-SAME: (%[[ARG:.*]]: vector<5xf32>) +// CHECK-SAME: -> vector<5xf32> +// CHECK-DAG: %[[CST:.*]] = arith.constant dense<1.000000e+00> : vector<5xf32> +// CHECK-DAG: %[[SQRT:.*]] = math.sqrt %[[ARG]] : vector<5xf32> +// CHECK-DAG: %[[DIV:.*]] = arith.divf %[[CST]], %[[SQRT]] : vector<5xf32> +// CHECK: return %[[DIV]] : vector<5xf32> +func.func @rsqrt_vec(%float: vector<5xf32>) -> (vector<5xf32>) { + %float_result = math.rsqrt %float : vector<5xf32> + return %float_result : vector<5xf32> +} + +// ----- + +// CHECK-LABEL: func.func @rsqrt_tns +// CHECK-SAME: (%[[ARG:.*]]: tensor<5x8xf32>) +// CHECK-SAME: -> tensor<5x8xf32> +// CHECK-DAG: %[[CST:.*]] = arith.constant dense<1.000000e+00> : tensor<5x8xf32> +// CHECK-DAG: %[[SQRT:.*]] = math.sqrt %[[ARG]] : tensor<5x8xf32> +// CHECK-DAG: %[[DIV:.*]] = arith.divf %[[CST]], %[[SQRT]] : tensor<5x8xf32> +// CHECK: return %[[DIV]] : tensor<5x8xf32> +func.func @rsqrt_tns(%float: tensor<5x8xf32>) -> (tensor<5x8xf32>) { + %float_result = math.rsqrt %float : tensor<5x8xf32> + return %float_result : tensor<5x8xf32> +} diff --git a/mlir/test/lib/Dialect/Math/TestExpandMath.cpp b/mlir/test/lib/Dialect/Math/TestExpandMath.cpp index da48ccb6e5e0..69af2a08b97b 100644 --- a/mlir/test/lib/Dialect/Math/TestExpandMath.cpp +++ b/mlir/test/lib/Dialect/Math/TestExpandMath.cpp @@ -52,6 +52,7 @@ void TestExpandMathPass::runOnOperation() { populateExpandFPowIPattern(patterns); populateExpandRoundFPattern(patterns); populateExpandRoundEvenPattern(patterns); + populateExpandRsqrtPattern(patterns); (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns)); } diff --git a/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir b/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir index 2b72acde6a3b..9b929b3c864d 100644 --- a/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir +++ b/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir @@ -833,6 +833,46 @@ func.func @atanh() { return } +// -------------------------------------------------------------------------- // +// Rsqrt. +// -------------------------------------------------------------------------- // + +func.func @rsqrt_f32(%a : f32) { + %r = math.rsqrt %a : f32 + vector.print %r : f32 + return +} + +func.func @rsqrt_3xf32(%a : vector<3xf32>) { + %r = math.rsqrt %a : vector<3xf32> + vector.print %r : vector<3xf32> + return +} + +func.func @rsqrt() { + // CHECK: 1 + %zero = arith.constant 1.0 : f32 + call @rsqrt_f32(%zero) : (f32) -> () + + // CHECK: 0.707107 + %cst1 = arith.constant 2.0 : f32 + call @rsqrt_f32(%cst1) : (f32) -> () + + // CHECK: inf + %cst2 = arith.constant 0.0 : f32 + call @rsqrt_f32(%cst2) : (f32) -> () + + // CHECK: -nan + %cst3 = arith.constant -1.0 : f32 + call @rsqrt_f32(%cst3) : (f32) -> () + + // CHECK: 0.5, 1.41421, 0.57735 + %vec_x = arith.constant dense<[4.0, 0.5, 3.0]> : vector<3xf32> + call @rsqrt_3xf32(%vec_x) : (vector<3xf32>) -> () + + return +} + func.func @main() { call @exp2f() : () -> () call @roundf() : () -> () @@ -844,5 +884,6 @@ func.func @main() { call @asinh() : () -> () call @acosh() : () -> () call @atanh() : () -> () + call @rsqrt() : () -> () return } -- GitLab From d4f5cf267936a082196b0c22fe45c730b24b9fe0 Mon Sep 17 00:00:00 2001 From: Azmat Yusuf Date: Mon, 13 May 2024 14:01:10 +0530 Subject: [PATCH 028/578] [Clang] Added check for unexpanded pack in attribute [[assume]] (#91893) Added a check for unexpanded parameter pack in attribute [[assume]]. Tested it with expected-error statements from clang fronted. This fixes #91232. --- clang/lib/Sema/SemaStmtAttr.cpp | 5 +++++ clang/test/SemaCXX/cxx23-assume.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 1c84830b6ddd..36f8ecadcfab 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -670,6 +670,11 @@ ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A, } auto *Assumption = A.getArgAsExpr(0); + + if (DiagnoseUnexpandedParameterPack(Assumption)) { + return ExprError(); + } + if (Assumption->getDependence() == ExprDependence::None) { ExprResult Res = BuildCXXAssumeExpr(Assumption, A.getAttrName(), Range); if (Res.isInvalid()) diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp index 8676970de14f..e67d72ae0a99 100644 --- a/clang/test/SemaCXX/cxx23-assume.cpp +++ b/clang/test/SemaCXX/cxx23-assume.cpp @@ -138,3 +138,8 @@ constexpr int foo() { } static_assert(foo() == 0); + +template +void f() { + [[assume(val)]]; // expected-error {{expression contains unexpanded parameter pack}} +} -- GitLab From 220756f1f92b335cbafdff67c570d096a6925d87 Mon Sep 17 00:00:00 2001 From: David Green Date: Mon, 13 May 2024 09:49:09 +0100 Subject: [PATCH 029/578] [AArch64][Inline] Regenerate Inline/AArch64/binop.ll test check lines. NFC Should hopefully help with #91854 --- llvm/test/Transforms/Inline/AArch64/binop.ll | 277 ++++++++++++++++--- 1 file changed, 233 insertions(+), 44 deletions(-) diff --git a/llvm/test/Transforms/Inline/AArch64/binop.ll b/llvm/test/Transforms/Inline/AArch64/binop.ll index eb882282820b..3dd66689a257 100644 --- a/llvm/test/Transforms/Inline/AArch64/binop.ll +++ b/llvm/test/Transforms/Inline/AArch64/binop.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=inline -mtriple=aarch64--linux-gnu -S -o - < %s -inline-threshold=0 | FileCheck %s target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" @@ -7,20 +8,35 @@ declare void @pad() @glbl = external global i32 define i32 @outer_add1(i32 %a) { -; CHECK-LABEL: @outer_add1( -; CHECK-NOT: call i32 @add +; CHECK-LABEL: define i32 @outer_add1( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[A]] +; %C = call i32 @add(i32 %a, i32 0) ret i32 %C } define i32 @outer_add2(i32 %a) { -; CHECK-LABEL: @outer_add2( -; CHECK-NOT: call i32 @add +; CHECK-LABEL: define i32 @outer_add2( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[A]] +; %C = call i32 @add(i32 0, i32 %a) ret i32 %C } define i32 @add(i32 %a, i32 %b) { +; CHECK-LABEL: define i32 @add( +; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], [[B]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[ADD]] +; %add = add i32 %a, %b call void @pad() store i32 0, ptr @glbl @@ -30,13 +46,24 @@ define i32 @add(i32 %a, i32 %b) { define i32 @outer_sub1(i32 %a) { -; CHECK-LABEL: @outer_sub1( -; CHECK-NOT: call i32 @sub1 +; CHECK-LABEL: define i32 @outer_sub1( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[A]] +; %C = call i32 @sub1(i32 %a, i32 0) ret i32 %C } define i32 @sub1(i32 %a, i32 %b) { +; CHECK-LABEL: define i32 @sub1( +; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { +; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A]], [[B]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[SUB]] +; %sub = sub i32 %a, %b call void @pad() store i32 0, ptr @glbl @@ -45,13 +72,22 @@ define i32 @sub1(i32 %a, i32 %b) { define i32 @outer_sub2(i32 %a) { -; CHECK-LABEL: @outer_sub2( -; CHECK-NOT: call i32 @sub2 +; CHECK-LABEL: define i32 @outer_sub2( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i32 0 +; %C = call i32 @sub2(i32 %a) ret i32 %C } define i32 @sub2(i32 %a) { +; CHECK-LABEL: define i32 @sub2( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A]], [[A]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i32 [[SUB]] +; %sub = sub i32 %a, %a call void @pad() ret i32 %sub @@ -60,20 +96,35 @@ define i32 @sub2(i32 %a) { define i32 @outer_mul1(i32 %a) { -; CHECK-LABEL: @outer_mul1( -; CHECK-NOT: call i32 @mul +; CHECK-LABEL: define i32 @outer_mul1( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 0 +; %C = call i32 @mul(i32 %a, i32 0) ret i32 %C } define i32 @outer_mul2(i32 %a) { -; CHECK-LABEL: @outer_mul2( -; CHECK-NOT: call i32 @mul +; CHECK-LABEL: define i32 @outer_mul2( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[A]] +; %C = call i32 @mul(i32 %a, i32 1) ret i32 %C } define i32 @mul(i32 %a, i32 %b) { +; CHECK-LABEL: define i32 @mul( +; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { +; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[A]], [[B]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[MUL]] +; %mul = mul i32 %a, %b call void @pad() store i32 0, ptr @glbl @@ -83,20 +134,35 @@ define i32 @mul(i32 %a, i32 %b) { define i32 @outer_div1(i32 %a) { -; CHECK-LABEL: @outer_div1( -; CHECK-NOT: call i32 @div1 +; CHECK-LABEL: define i32 @outer_div1( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 0 +; %C = call i32 @div1(i32 0, i32 %a) ret i32 %C } define i32 @outer_div2(i32 %a) { -; CHECK-LABEL: @outer_div2( -; CHECK-NOT: call i32 @div1 +; CHECK-LABEL: define i32 @outer_div2( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[A]] +; %C = call i32 @div1(i32 %a, i32 1) ret i32 %C } define i32 @div1(i32 %a, i32 %b) { +; CHECK-LABEL: define i32 @div1( +; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A]], [[B]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[DIV]] +; %div = sdiv i32 %a, %b call void @pad() store i32 0, ptr @glbl @@ -105,13 +171,22 @@ define i32 @div1(i32 %a, i32 %b) { define i32 @outer_div3(i32 %a) { -; CHECK-LABEL: @outer_div3( -; CHECK-NOT: call i32 @div +; CHECK-LABEL: define i32 @outer_div3( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i32 1 +; %C = call i32 @div2(i32 %a) ret i32 %C } define i32 @div2(i32 %a) { +; CHECK-LABEL: define i32 @div2( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A]], [[A]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i32 [[DIV]] +; %div = sdiv i32 %a, %a call void @pad() ret i32 %div @@ -120,20 +195,35 @@ define i32 @div2(i32 %a) { define i32 @outer_rem1(i32 %a) { -; CHECK-LABEL: @outer_rem1( -; CHECK-NOT: call i32 @rem +; CHECK-LABEL: define i32 @outer_rem1( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 0 +; %C = call i32 @rem1(i32 0, i32 %a) ret i32 %C } define i32 @outer_rem2(i32 %a) { -; CHECK-LABEL: @outer_rem2( -; CHECK-NOT: call i32 @rem +; CHECK-LABEL: define i32 @outer_rem2( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 0 +; %C = call i32 @rem1(i32 %a, i32 1) ret i32 %C } define i32 @rem1(i32 %a, i32 %b) { +; CHECK-LABEL: define i32 @rem1( +; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { +; CHECK-NEXT: [[REM:%.*]] = urem i32 [[A]], [[B]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[REM]] +; %rem = urem i32 %a, %b call void @pad() store i32 0, ptr @glbl @@ -142,13 +232,22 @@ define i32 @rem1(i32 %a, i32 %b) { define i32 @outer_rem3(i32 %a) { -; CHECK-LABEL: @outer_rem3( -; CHECK-NOT: call i32 @rem +; CHECK-LABEL: define i32 @outer_rem3( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i32 0 +; %C = call i32 @rem2(i32 %a) ret i32 %C } define i32 @rem2(i32 %a) { +; CHECK-LABEL: define i32 @rem2( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: [[REM:%.*]] = urem i32 [[A]], [[A]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i32 [[REM]] +; %rem = urem i32 %a, %a call void @pad() ret i32 %rem @@ -157,13 +256,24 @@ define i32 @rem2(i32 %a) { define i32 @outer_shl1(i32 %a) { -; CHECK-LABEL: @outer_shl1( -; CHECK-NOT: call i32 @shl +; CHECK-LABEL: define i32 @outer_shl1( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[A]] +; %C = call i32 @shl(i32 %a, i32 0) ret i32 %C } define i32 @shl(i32 %a, i32 %b) { +; CHECK-LABEL: define i32 @shl( +; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A]], [[B]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[SHL]] +; %shl = shl i32 %a, %b call void @pad() store i32 0, ptr @glbl @@ -173,13 +283,24 @@ define i32 @shl(i32 %a, i32 %b) { define i32 @outer_shr1(i32 %a) { -; CHECK-LABEL: @outer_shr1( -; CHECK-NOT: call i32 @shr +; CHECK-LABEL: define i32 @outer_shr1( +; CHECK-SAME: i32 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[A]] +; %C = call i32 @shr(i32 %a, i32 0) ret i32 %C } define i32 @shr(i32 %a, i32 %b) { +; CHECK-LABEL: define i32 @shr( +; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { +; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[A]], [[B]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i32 [[SHR]] +; %shr = ashr i32 %a, %b call void @pad() store i32 0, ptr @glbl @@ -189,20 +310,35 @@ define i32 @shr(i32 %a, i32 %b) { define i1 @outer_and1(i1 %a) { -; check-label: @outer_and1( -; check-not: call i1 @and1 +; CHECK-LABEL: define i1 @outer_and1( +; CHECK-SAME: i1 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i1 false +; %c = call i1 @and1(i1 %a, i1 false) ret i1 %c } define i1 @outer_and2(i1 %a) { -; check-label: @outer_and2( -; check-not: call i1 @and1 +; CHECK-LABEL: define i1 @outer_and2( +; CHECK-SAME: i1 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i1 [[A]] +; %c = call i1 @and1(i1 %a, i1 true) ret i1 %c } define i1 @and1(i1 %a, i1 %b) { +; CHECK-LABEL: define i1 @and1( +; CHECK-SAME: i1 [[A:%.*]], i1 [[B:%.*]]) { +; CHECK-NEXT: [[AND:%.*]] = and i1 [[A]], [[B]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i1 [[AND]] +; %and = and i1 %a, %b call void @pad() store i32 0, ptr @glbl @@ -211,13 +347,22 @@ define i1 @and1(i1 %a, i1 %b) { define i1 @outer_and3(i1 %a) { -; check-label: @outer_and3( -; check-not: call i1 @and2 +; CHECK-LABEL: define i1 @outer_and3( +; CHECK-SAME: i1 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i1 [[A]] +; %c = call i1 @and2(i1 %a) ret i1 %c } define i1 @and2(i1 %a) { +; CHECK-LABEL: define i1 @and2( +; CHECK-SAME: i1 [[A:%.*]]) { +; CHECK-NEXT: [[AND:%.*]] = and i1 [[A]], [[A]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i1 [[AND]] +; %and = and i1 %a, %a call void @pad() ret i1 %and @@ -226,20 +371,35 @@ define i1 @and2(i1 %a) { define i1 @outer_or1(i1 %a) { -; check-label: @outer_or1( -; check-not: call i1 @or1 +; CHECK-LABEL: define i1 @outer_or1( +; CHECK-SAME: i1 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i1 [[A]] +; %c = call i1 @or1(i1 %a, i1 false) ret i1 %c } define i1 @outer_or2(i1 %a) { -; check-label: @outer_or2( -; check-not: call i1 @or1 +; CHECK-LABEL: define i1 @outer_or2( +; CHECK-SAME: i1 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i1 true +; %c = call i1 @or1(i1 %a, i1 true) ret i1 %c } define i1 @or1(i1 %a, i1 %b) { +; CHECK-LABEL: define i1 @or1( +; CHECK-SAME: i1 [[A:%.*]], i1 [[B:%.*]]) { +; CHECK-NEXT: [[OR:%.*]] = or i1 [[A]], [[B]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i1 [[OR]] +; %or = or i1 %a, %b call void @pad() store i32 0, ptr @glbl @@ -248,13 +408,22 @@ define i1 @or1(i1 %a, i1 %b) { define i1 @outer_or3(i1 %a) { -; check-label: @outer_or3( -; check-not: call i1 @or2 +; CHECK-LABEL: define i1 @outer_or3( +; CHECK-SAME: i1 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i1 [[A]] +; %c = call i1 @or2(i1 %a) ret i1 %c } define i1 @or2(i1 %a) { +; CHECK-LABEL: define i1 @or2( +; CHECK-SAME: i1 [[A:%.*]]) { +; CHECK-NEXT: [[OR:%.*]] = or i1 [[A]], [[A]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i1 [[OR]] +; %or = or i1 %a, %a call void @pad() ret i1 %or @@ -263,13 +432,24 @@ define i1 @or2(i1 %a) { define i1 @outer_xor1(i1 %a) { -; check-label: @outer_xor1( -; check-not: call i1 @xor +; CHECK-LABEL: define i1 @outer_xor1( +; CHECK-SAME: i1 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i1 [[A]] +; %c = call i1 @xor1(i1 %a, i1 false) ret i1 %c } define i1 @xor1(i1 %a, i1 %b) { +; CHECK-LABEL: define i1 @xor1( +; CHECK-SAME: i1 [[A:%.*]], i1 [[B:%.*]]) { +; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[A]], [[B]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: store i32 0, ptr @glbl, align 4 +; CHECK-NEXT: ret i1 [[XOR]] +; %xor = xor i1 %a, %b call void @pad() store i32 0, ptr @glbl @@ -278,13 +458,22 @@ define i1 @xor1(i1 %a, i1 %b) { define i1 @outer_xor3(i1 %a) { -; check-label: @outer_xor3( -; check-not: call i1 @xor +; CHECK-LABEL: define i1 @outer_xor3( +; CHECK-SAME: i1 [[A:%.*]]) { +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i1 false +; %c = call i1 @xor2(i1 %a) ret i1 %c } define i1 @xor2(i1 %a) { +; CHECK-LABEL: define i1 @xor2( +; CHECK-SAME: i1 [[A:%.*]]) { +; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[A]], [[A]] +; CHECK-NEXT: call void @pad() +; CHECK-NEXT: ret i1 [[XOR]] +; %xor = xor i1 %a, %a call void @pad() ret i1 %xor -- GitLab From 0fb7546c587198df11714cfc433d4c5552af0888 Mon Sep 17 00:00:00 2001 From: Tuan Chuong Goh Date: Mon, 13 May 2024 08:21:36 +0000 Subject: [PATCH 030/578] [AArch64][NFC] Pre-commit Test for Select G_ICMP instruction through TableGen (#89932) --- llvm/test/CodeGen/AArch64/icmp.ll | 1056 +++++++++++++++++++++++++++++ 1 file changed, 1056 insertions(+) diff --git a/llvm/test/CodeGen/AArch64/icmp.ll b/llvm/test/CodeGen/AArch64/icmp.ll index 8e10847e7aae..2292bc6d2038 100644 --- a/llvm/test/CodeGen/AArch64/icmp.ll +++ b/llvm/test/CodeGen/AArch64/icmp.ll @@ -52,6 +52,1062 @@ entry: ret i8 %s } +define <2 x i1> @test_v2i64_eq(<2 x i64> %v1, <2 x i64> %v2) { +; CHECK-LABEL: test_v2i64_eq: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.2d, v0.2d, v1.2d +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret + %cmp = icmp eq <2 x i64> %v1, %v2 + ret <2 x i1> %cmp +} + +define <4 x i1> @test_v4i64_eq(<4 x i64> %v1, <4 x i64> %v2) { +; CHECK-SD-LABEL: test_v4i64_eq: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: cmeq v1.2d, v1.2d, v3.2d +; CHECK-SD-NEXT: cmeq v0.2d, v0.2d, v2.2d +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v4i64_eq: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: cmeq v0.2d, v0.2d, v2.2d +; CHECK-GI-NEXT: cmeq v1.2d, v1.2d, v3.2d +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret +entry: + %cmp = icmp eq <4 x i64> %v1, %v2 + ret <4 x i1> %cmp +} + +define <4 x i1> @test_v4i32_eq(<4 x i32> %v1, <4 x i32> %v2) { +; CHECK-LABEL: test_v4i32_eq: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret + %cmp = icmp eq <4 x i32> %v1, %v2 + ret <4 x i1> %cmp +} + +define <2 x i1> @test_v2i32_eq(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: test_v2i32_eq: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.2s, v0.2s, v1.2s +; CHECK-NEXT: ret + %cmp = icmp eq <2 x i32> %v1, %v2 + ret <2 x i1> %cmp +} + +define <2 x i1> @test_v2i16_eq(<2 x i16> %v1, <2 x i16> %v2) { +; CHECK-SD-LABEL: test_v2i16_eq: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-SD-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-SD-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-SD-NEXT: cmeq v0.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v2i16_eq: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-GI-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-GI-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-GI-NEXT: cmeq v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: ret + %cmp = icmp eq <2 x i16> %v1, %v2 + ret <2 x i1> %cmp +} + +define <8 x i1> @test_v8i16_eq(<8 x i16> %v1, <8 x i16> %v2) { +; CHECK-LABEL: test_v8i16_eq: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.8h, v0.8h, v1.8h +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret + %cmp = icmp eq <8 x i16> %v1, %v2 + ret <8 x i1> %cmp +} + +define <4 x i1> @test_v4i16_eq(<4 x i16> %v1, <4 x i16> %v2) { +; CHECK-LABEL: test_v4i16_eq: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.4h, v0.4h, v1.4h +; CHECK-NEXT: ret + %cmp = icmp eq <4 x i16> %v1, %v2 + ret <4 x i1> %cmp +} + +define <16 x i1> @test_v16i8_eq(<16 x i8> %v1, <16 x i8> %v2) { +; CHECK-LABEL: test_v16i8_eq: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.16b, v0.16b, v1.16b +; CHECK-NEXT: ret + %cmp = icmp eq <16 x i8> %v1, %v2 + ret <16 x i1> %cmp +} + +define <8 x i1> @test_v8i8_eq(<8 x i8> %v1, <8 x i8> %v2) { +; CHECK-LABEL: test_v8i8_eq: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.8b, v0.8b, v1.8b +; CHECK-NEXT: ret + %cmp = icmp eq <8 x i8> %v1, %v2 + ret <8 x i1> %cmp +} + +define <2 x i1> @test_v2i64_ne(<2 x i64> %v1, <2 x i64> %v2) { +; CHECK-LABEL: test_v2i64_ne: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.2d, v0.2d, v1.2d +; CHECK-NEXT: mvn v0.16b, v0.16b +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret + %cmp = icmp ne <2 x i64> %v1, %v2 + ret <2 x i1> %cmp +} + +define <4 x i1> @test_v4i64_ne(<4 x i64> %v1, <4 x i64> %v2) { +; CHECK-SD-LABEL: test_v4i64_ne: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: cmeq v1.2d, v1.2d, v3.2d +; CHECK-SD-NEXT: cmeq v0.2d, v0.2d, v2.2d +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: mvn v0.16b, v0.16b +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v4i64_ne: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: cmeq v0.2d, v0.2d, v2.2d +; CHECK-GI-NEXT: cmeq v1.2d, v1.2d, v3.2d +; CHECK-GI-NEXT: mvn v0.16b, v0.16b +; CHECK-GI-NEXT: mvn v1.16b, v1.16b +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret +entry: + %cmp = icmp ne <4 x i64> %v1, %v2 + ret <4 x i1> %cmp +} + +define <4 x i1> @test_v4i32_ne(<4 x i32> %v1, <4 x i32> %v2) { +; CHECK-LABEL: test_v4i32_ne: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.4s, v0.4s, v1.4s +; CHECK-NEXT: mvn v0.16b, v0.16b +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret + %cmp = icmp ne <4 x i32> %v1, %v2 + ret <4 x i1> %cmp +} + +define <2 x i1> @test_v2i32_ne(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: test_v2i32_ne: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.2s, v0.2s, v1.2s +; CHECK-NEXT: mvn v0.8b, v0.8b +; CHECK-NEXT: ret + %cmp = icmp ne <2 x i32> %v1, %v2 + ret <2 x i1> %cmp +} + +define <2 x i1> @test_v2i16_ne(<2 x i16> %v1, <2 x i16> %v2) { +; CHECK-SD-LABEL: test_v2i16_ne: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-SD-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-SD-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-SD-NEXT: cmeq v0.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: mvn v0.8b, v0.8b +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v2i16_ne: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-GI-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-GI-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-GI-NEXT: cmeq v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: mvn v0.8b, v0.8b +; CHECK-GI-NEXT: ret + %cmp = icmp ne <2 x i16> %v1, %v2 + ret <2 x i1> %cmp +} + +define <8 x i1> @test_v8i16_ne(<8 x i16> %v1, <8 x i16> %v2) { +; CHECK-LABEL: test_v8i16_ne: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.8h, v0.8h, v1.8h +; CHECK-NEXT: mvn v0.16b, v0.16b +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret + %cmp = icmp ne <8 x i16> %v1, %v2 + ret <8 x i1> %cmp +} + +define <4 x i1> @test_v4i16_ne(<4 x i16> %v1, <4 x i16> %v2) { +; CHECK-LABEL: test_v4i16_ne: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.4h, v0.4h, v1.4h +; CHECK-NEXT: mvn v0.8b, v0.8b +; CHECK-NEXT: ret + %cmp = icmp ne <4 x i16> %v1, %v2 + ret <4 x i1> %cmp +} + +define <16 x i1> @test_v16i8_ne(<16 x i8> %v1, <16 x i8> %v2) { +; CHECK-LABEL: test_v16i8_ne: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.16b, v0.16b, v1.16b +; CHECK-NEXT: mvn v0.16b, v0.16b +; CHECK-NEXT: ret + %cmp = icmp ne <16 x i8> %v1, %v2 + ret <16 x i1> %cmp +} + +define <8 x i1> @test_v8i8_ne(<8 x i8> %v1, <8 x i8> %v2) { +; CHECK-LABEL: test_v8i8_ne: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.8b, v0.8b, v1.8b +; CHECK-NEXT: mvn v0.8b, v0.8b +; CHECK-NEXT: ret + %cmp = icmp ne <8 x i8> %v1, %v2 + ret <8 x i1> %cmp +} + +define <2 x i1> @test_v2i64_ugt(<2 x i64> %v1, <2 x i64> %v2) { +; CHECK-LABEL: test_v2i64_ugt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.2d, v0.2d, v1.2d +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret + %cmp = icmp ugt <2 x i64> %v1, %v2 + ret <2 x i1> %cmp +} + +define <4 x i1> @test_v4i64_ugt(<4 x i64> %v1, <4 x i64> %v2) { +; CHECK-SD-LABEL: test_v4i64_ugt: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: cmhi v1.2d, v1.2d, v3.2d +; CHECK-SD-NEXT: cmhi v0.2d, v0.2d, v2.2d +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v4i64_ugt: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: cmhi v0.2d, v0.2d, v2.2d +; CHECK-GI-NEXT: cmhi v1.2d, v1.2d, v3.2d +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret +entry: + %cmp = icmp ugt <4 x i64> %v1, %v2 + ret <4 x i1> %cmp +} + +define <4 x i1> @test_v4i32_ugt(<4 x i32> %v1, <4 x i32> %v2) { +; CHECK-LABEL: test_v4i32_ugt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret + %cmp = icmp ugt <4 x i32> %v1, %v2 + ret <4 x i1> %cmp +} + +define <2 x i1> @test_v2i32_ugt(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: test_v2i32_ugt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.2s, v0.2s, v1.2s +; CHECK-NEXT: ret + %cmp = icmp ugt <2 x i32> %v1, %v2 + ret <2 x i1> %cmp +} + +define <2 x i1> @test_v2i16_ugt(<2 x i16> %v1, <2 x i16> %v2) { +; CHECK-SD-LABEL: test_v2i16_ugt: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-SD-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-SD-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-SD-NEXT: cmhi v0.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v2i16_ugt: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-GI-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-GI-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-GI-NEXT: cmhi v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: ret + %cmp = icmp ugt <2 x i16> %v1, %v2 + ret <2 x i1> %cmp +} + +define <8 x i1> @test_v8i16_ugt(<8 x i16> %v1, <8 x i16> %v2) { +; CHECK-LABEL: test_v8i16_ugt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.8h, v0.8h, v1.8h +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret + %cmp = icmp ugt <8 x i16> %v1, %v2 + ret <8 x i1> %cmp +} + +define <4 x i1> @test_v4i16_ugt(<4 x i16> %v1, <4 x i16> %v2) { +; CHECK-LABEL: test_v4i16_ugt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.4h, v0.4h, v1.4h +; CHECK-NEXT: ret + %cmp = icmp ugt <4 x i16> %v1, %v2 + ret <4 x i1> %cmp +} + +define <16 x i1> @test_v16i8_ugt(<16 x i8> %v1, <16 x i8> %v2) { +; CHECK-LABEL: test_v16i8_ugt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.16b, v0.16b, v1.16b +; CHECK-NEXT: ret + %cmp = icmp ugt <16 x i8> %v1, %v2 + ret <16 x i1> %cmp +} + +define <8 x i1> @test_v8i8_ugt(<8 x i8> %v1, <8 x i8> %v2) { +; CHECK-LABEL: test_v8i8_ugt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.8b, v0.8b, v1.8b +; CHECK-NEXT: ret + %cmp = icmp ugt <8 x i8> %v1, %v2 + ret <8 x i1> %cmp +} + +define <2 x i1> @test_v2i64_uge(<2 x i64> %v1, <2 x i64> %v2) { +; CHECK-LABEL: test_v2i64_uge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.2d, v0.2d, v1.2d +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret + %cmp = icmp uge <2 x i64> %v1, %v2 + ret <2 x i1> %cmp +} + +define <4 x i1> @test_v4i64_uge(<4 x i64> %v1, <4 x i64> %v2) { +; CHECK-SD-LABEL: test_v4i64_uge: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: cmhs v1.2d, v1.2d, v3.2d +; CHECK-SD-NEXT: cmhs v0.2d, v0.2d, v2.2d +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v4i64_uge: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: cmhs v0.2d, v0.2d, v2.2d +; CHECK-GI-NEXT: cmhs v1.2d, v1.2d, v3.2d +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret +entry: + %cmp = icmp uge <4 x i64> %v1, %v2 + ret <4 x i1> %cmp +} + +define <4 x i1> @test_v4i32_uge(<4 x i32> %v1, <4 x i32> %v2) { +; CHECK-LABEL: test_v4i32_uge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret + %cmp = icmp uge <4 x i32> %v1, %v2 + ret <4 x i1> %cmp +} + +define <2 x i1> @test_v2i32_uge(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: test_v2i32_uge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.2s, v0.2s, v1.2s +; CHECK-NEXT: ret + %cmp = icmp uge <2 x i32> %v1, %v2 + ret <2 x i1> %cmp +} + +define <2 x i1> @test_v2i16_uge(<2 x i16> %v1, <2 x i16> %v2) { +; CHECK-SD-LABEL: test_v2i16_uge: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-SD-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-SD-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-SD-NEXT: cmhs v0.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v2i16_uge: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-GI-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-GI-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-GI-NEXT: cmhs v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: ret + %cmp = icmp uge <2 x i16> %v1, %v2 + ret <2 x i1> %cmp +} + +define <8 x i1> @test_v8i16_uge(<8 x i16> %v1, <8 x i16> %v2) { +; CHECK-LABEL: test_v8i16_uge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.8h, v0.8h, v1.8h +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret + %cmp = icmp uge <8 x i16> %v1, %v2 + ret <8 x i1> %cmp +} + +define <4 x i1> @test_v4i16_uge(<4 x i16> %v1, <4 x i16> %v2) { +; CHECK-LABEL: test_v4i16_uge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.4h, v0.4h, v1.4h +; CHECK-NEXT: ret + %cmp = icmp uge <4 x i16> %v1, %v2 + ret <4 x i1> %cmp +} + +define <16 x i1> @test_v16i8_uge(<16 x i8> %v1, <16 x i8> %v2) { +; CHECK-LABEL: test_v16i8_uge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.16b, v0.16b, v1.16b +; CHECK-NEXT: ret + %cmp = icmp uge <16 x i8> %v1, %v2 + ret <16 x i1> %cmp +} + +define <8 x i1> @test_v8i8_uge(<8 x i8> %v1, <8 x i8> %v2) { +; CHECK-LABEL: test_v8i8_uge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.8b, v0.8b, v1.8b +; CHECK-NEXT: ret + %cmp = icmp uge <8 x i8> %v1, %v2 + ret <8 x i1> %cmp +} + +define <2 x i1> @test_v2i64_ult(<2 x i64> %v1, <2 x i64> %v2) { +; CHECK-LABEL: test_v2i64_ult: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.2d, v1.2d, v0.2d +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret + %cmp = icmp ult <2 x i64> %v1, %v2 + ret <2 x i1> %cmp +} + +define <4 x i1> @test_v4i64_ult(<4 x i64> %v1, <4 x i64> %v2) { +; CHECK-SD-LABEL: test_v4i64_ult: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: cmhi v1.2d, v3.2d, v1.2d +; CHECK-SD-NEXT: cmhi v0.2d, v2.2d, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v4i64_ult: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: cmhi v0.2d, v2.2d, v0.2d +; CHECK-GI-NEXT: cmhi v1.2d, v3.2d, v1.2d +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret +entry: + %cmp = icmp ult <4 x i64> %v1, %v2 + ret <4 x i1> %cmp +} + +define <4 x i1> @test_v4i32_ult(<4 x i32> %v1, <4 x i32> %v2) { +; CHECK-LABEL: test_v4i32_ult: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.4s, v1.4s, v0.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret + %cmp = icmp ult <4 x i32> %v1, %v2 + ret <4 x i1> %cmp +} + +define <2 x i1> @test_v2i32_ult(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: test_v2i32_ult: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.2s, v1.2s, v0.2s +; CHECK-NEXT: ret + %cmp = icmp ult <2 x i32> %v1, %v2 + ret <2 x i1> %cmp +} + +define <2 x i1> @test_v2i16_ult(<2 x i16> %v1, <2 x i16> %v2) { +; CHECK-LABEL: test_v2i16_ult: +; CHECK: // %bb.0: +; CHECK-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-NEXT: cmhi v0.2s, v1.2s, v0.2s +; CHECK-NEXT: ret + %cmp = icmp ult <2 x i16> %v1, %v2 + ret <2 x i1> %cmp +} + +define <8 x i1> @test_v8i16_ult(<8 x i16> %v1, <8 x i16> %v2) { +; CHECK-LABEL: test_v8i16_ult: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.8h, v1.8h, v0.8h +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret + %cmp = icmp ult <8 x i16> %v1, %v2 + ret <8 x i1> %cmp +} + +define <4 x i1> @test_v4i16_ult(<4 x i16> %v1, <4 x i16> %v2) { +; CHECK-LABEL: test_v4i16_ult: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.4h, v1.4h, v0.4h +; CHECK-NEXT: ret + %cmp = icmp ult <4 x i16> %v1, %v2 + ret <4 x i1> %cmp +} + +define <16 x i1> @test_v16i8_ult(<16 x i8> %v1, <16 x i8> %v2) { +; CHECK-LABEL: test_v16i8_ult: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.16b, v1.16b, v0.16b +; CHECK-NEXT: ret + %cmp = icmp ult <16 x i8> %v1, %v2 + ret <16 x i1> %cmp +} + +define <8 x i1> @test_v8i8_ult(<8 x i8> %v1, <8 x i8> %v2) { +; CHECK-LABEL: test_v8i8_ult: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhi v0.8b, v1.8b, v0.8b +; CHECK-NEXT: ret + %cmp = icmp ult <8 x i8> %v1, %v2 + ret <8 x i1> %cmp +} + +define <2 x i1> @test_v2i64_ule(<2 x i64> %v1, <2 x i64> %v2) { +; CHECK-LABEL: test_v2i64_ule: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.2d, v1.2d, v0.2d +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret + %cmp = icmp ule <2 x i64> %v1, %v2 + ret <2 x i1> %cmp +} + +define <4 x i1> @test_v4i64_ule(<4 x i64> %v1, <4 x i64> %v2) { +; CHECK-SD-LABEL: test_v4i64_ule: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: cmhs v1.2d, v3.2d, v1.2d +; CHECK-SD-NEXT: cmhs v0.2d, v2.2d, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v4i64_ule: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: cmhs v0.2d, v2.2d, v0.2d +; CHECK-GI-NEXT: cmhs v1.2d, v3.2d, v1.2d +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret +entry: + %cmp = icmp ule <4 x i64> %v1, %v2 + ret <4 x i1> %cmp +} + +define <4 x i1> @test_v4i32_ule(<4 x i32> %v1, <4 x i32> %v2) { +; CHECK-LABEL: test_v4i32_ule: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.4s, v1.4s, v0.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret + %cmp = icmp ule <4 x i32> %v1, %v2 + ret <4 x i1> %cmp +} + +define <2 x i1> @test_v2i32_ule(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: test_v2i32_ule: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.2s, v1.2s, v0.2s +; CHECK-NEXT: ret + %cmp = icmp ule <2 x i32> %v1, %v2 + ret <2 x i1> %cmp +} + +define <2 x i1> @test_v2i16_ule(<2 x i16> %v1, <2 x i16> %v2) { +; CHECK-LABEL: test_v2i16_ule: +; CHECK: // %bb.0: +; CHECK-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-NEXT: cmhs v0.2s, v1.2s, v0.2s +; CHECK-NEXT: ret + %cmp = icmp ule <2 x i16> %v1, %v2 + ret <2 x i1> %cmp +} + +define <8 x i1> @test_v8i16_ule(<8 x i16> %v1, <8 x i16> %v2) { +; CHECK-LABEL: test_v8i16_ule: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.8h, v1.8h, v0.8h +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret + %cmp = icmp ule <8 x i16> %v1, %v2 + ret <8 x i1> %cmp +} + +define <4 x i1> @test_v4i16_ule(<4 x i16> %v1, <4 x i16> %v2) { +; CHECK-LABEL: test_v4i16_ule: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.4h, v1.4h, v0.4h +; CHECK-NEXT: ret + %cmp = icmp ule <4 x i16> %v1, %v2 + ret <4 x i1> %cmp +} + +define <16 x i1> @test_v16i8_ule(<16 x i8> %v1, <16 x i8> %v2) { +; CHECK-LABEL: test_v16i8_ule: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.16b, v1.16b, v0.16b +; CHECK-NEXT: ret + %cmp = icmp ule <16 x i8> %v1, %v2 + ret <16 x i1> %cmp +} + +define <8 x i1> @test_v8i8_ule(<8 x i8> %v1, <8 x i8> %v2) { +; CHECK-LABEL: test_v8i8_ule: +; CHECK: // %bb.0: +; CHECK-NEXT: cmhs v0.8b, v1.8b, v0.8b +; CHECK-NEXT: ret + %cmp = icmp ule <8 x i8> %v1, %v2 + ret <8 x i1> %cmp +} + +define <2 x i1> @test_v2i64_sgt(<2 x i64> %v1, <2 x i64> %v2) { +; CHECK-LABEL: test_v2i64_sgt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.2d, v0.2d, v1.2d +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret + %cmp = icmp sgt <2 x i64> %v1, %v2 + ret <2 x i1> %cmp +} + +define <4 x i1> @test_v4i64_sgt(<4 x i64> %v1, <4 x i64> %v2) { +; CHECK-SD-LABEL: test_v4i64_sgt: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: cmgt v1.2d, v1.2d, v3.2d +; CHECK-SD-NEXT: cmgt v0.2d, v0.2d, v2.2d +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v4i64_sgt: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: cmgt v0.2d, v0.2d, v2.2d +; CHECK-GI-NEXT: cmgt v1.2d, v1.2d, v3.2d +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret +entry: + %cmp = icmp sgt <4 x i64> %v1, %v2 + ret <4 x i1> %cmp +} + +define <4 x i1> @test_v4i32_sgt(<4 x i32> %v1, <4 x i32> %v2) { +; CHECK-LABEL: test_v4i32_sgt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret + %cmp = icmp sgt <4 x i32> %v1, %v2 + ret <4 x i1> %cmp +} + +define <2 x i1> @test_v2i32_sgt(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: test_v2i32_sgt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.2s, v0.2s, v1.2s +; CHECK-NEXT: ret + %cmp = icmp sgt <2 x i32> %v1, %v2 + ret <2 x i1> %cmp +} + +define <2 x i1> @test_v2i16_sgt(<2 x i16> %v1, <2 x i16> %v2) { +; CHECK-SD-LABEL: test_v2i16_sgt: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: shl v1.2s, v1.2s, #16 +; CHECK-SD-NEXT: shl v0.2s, v0.2s, #16 +; CHECK-SD-NEXT: sshr v1.2s, v1.2s, #16 +; CHECK-SD-NEXT: sshr v0.2s, v0.2s, #16 +; CHECK-SD-NEXT: cmgt v0.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v2i16_sgt: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: shl v0.2s, v0.2s, #16 +; CHECK-GI-NEXT: shl v1.2s, v1.2s, #16 +; CHECK-GI-NEXT: sshr v0.2s, v0.2s, #16 +; CHECK-GI-NEXT: sshr v1.2s, v1.2s, #16 +; CHECK-GI-NEXT: cmgt v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: ret + %cmp = icmp sgt <2 x i16> %v1, %v2 + ret <2 x i1> %cmp +} + +define <8 x i1> @test_v8i16_sgt(<8 x i16> %v1, <8 x i16> %v2) { +; CHECK-LABEL: test_v8i16_sgt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.8h, v0.8h, v1.8h +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret + %cmp = icmp sgt <8 x i16> %v1, %v2 + ret <8 x i1> %cmp +} + +define <4 x i1> @test_v4i16_sgt(<4 x i16> %v1, <4 x i16> %v2) { +; CHECK-LABEL: test_v4i16_sgt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.4h, v0.4h, v1.4h +; CHECK-NEXT: ret + %cmp = icmp sgt <4 x i16> %v1, %v2 + ret <4 x i1> %cmp +} + +define <16 x i1> @test_v16i8_sgt(<16 x i8> %v1, <16 x i8> %v2) { +; CHECK-LABEL: test_v16i8_sgt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.16b, v0.16b, v1.16b +; CHECK-NEXT: ret + %cmp = icmp sgt <16 x i8> %v1, %v2 + ret <16 x i1> %cmp +} + +define <8 x i1> @test_v8i8_sgt(<8 x i8> %v1, <8 x i8> %v2) { +; CHECK-LABEL: test_v8i8_sgt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.8b, v0.8b, v1.8b +; CHECK-NEXT: ret + %cmp = icmp sgt <8 x i8> %v1, %v2 + ret <8 x i1> %cmp +} + +define <2 x i1> @test_v2i64_sge(<2 x i64> %v1, <2 x i64> %v2) { +; CHECK-LABEL: test_v2i64_sge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.2d, v0.2d, v1.2d +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret + %cmp = icmp sge <2 x i64> %v1, %v2 + ret <2 x i1> %cmp +} + +define <4 x i1> @test_v4i64_sge(<4 x i64> %v1, <4 x i64> %v2) { +; CHECK-SD-LABEL: test_v4i64_sge: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: cmge v1.2d, v1.2d, v3.2d +; CHECK-SD-NEXT: cmge v0.2d, v0.2d, v2.2d +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v4i64_sge: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: cmge v0.2d, v0.2d, v2.2d +; CHECK-GI-NEXT: cmge v1.2d, v1.2d, v3.2d +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret +entry: + %cmp = icmp sge <4 x i64> %v1, %v2 + ret <4 x i1> %cmp +} + +define <4 x i1> @test_v4i32_sge(<4 x i32> %v1, <4 x i32> %v2) { +; CHECK-LABEL: test_v4i32_sge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret + %cmp = icmp sge <4 x i32> %v1, %v2 + ret <4 x i1> %cmp +} + +define <2 x i1> @test_v2i32_sge(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: test_v2i32_sge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.2s, v0.2s, v1.2s +; CHECK-NEXT: ret + %cmp = icmp sge <2 x i32> %v1, %v2 + ret <2 x i1> %cmp +} + +define <2 x i1> @test_v2i16_sge(<2 x i16> %v1, <2 x i16> %v2) { +; CHECK-SD-LABEL: test_v2i16_sge: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: shl v1.2s, v1.2s, #16 +; CHECK-SD-NEXT: shl v0.2s, v0.2s, #16 +; CHECK-SD-NEXT: sshr v1.2s, v1.2s, #16 +; CHECK-SD-NEXT: sshr v0.2s, v0.2s, #16 +; CHECK-SD-NEXT: cmge v0.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v2i16_sge: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: shl v0.2s, v0.2s, #16 +; CHECK-GI-NEXT: shl v1.2s, v1.2s, #16 +; CHECK-GI-NEXT: sshr v0.2s, v0.2s, #16 +; CHECK-GI-NEXT: sshr v1.2s, v1.2s, #16 +; CHECK-GI-NEXT: cmge v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: ret + %cmp = icmp sge <2 x i16> %v1, %v2 + ret <2 x i1> %cmp +} + +define <8 x i1> @test_v8i16_sge(<8 x i16> %v1, <8 x i16> %v2) { +; CHECK-LABEL: test_v8i16_sge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.8h, v0.8h, v1.8h +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret + %cmp = icmp sge <8 x i16> %v1, %v2 + ret <8 x i1> %cmp +} + +define <4 x i1> @test_v4i16_sge(<4 x i16> %v1, <4 x i16> %v2) { +; CHECK-LABEL: test_v4i16_sge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.4h, v0.4h, v1.4h +; CHECK-NEXT: ret + %cmp = icmp sge <4 x i16> %v1, %v2 + ret <4 x i1> %cmp +} + +define <16 x i1> @test_v16i8_sge(<16 x i8> %v1, <16 x i8> %v2) { +; CHECK-LABEL: test_v16i8_sge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.16b, v0.16b, v1.16b +; CHECK-NEXT: ret + %cmp = icmp sge <16 x i8> %v1, %v2 + ret <16 x i1> %cmp +} + +define <8 x i1> @test_v8i8_sge(<8 x i8> %v1, <8 x i8> %v2) { +; CHECK-LABEL: test_v8i8_sge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.8b, v0.8b, v1.8b +; CHECK-NEXT: ret + %cmp = icmp sge <8 x i8> %v1, %v2 + ret <8 x i1> %cmp +} + +define <2 x i1> @test_v2i64_slt(<2 x i64> %v1, <2 x i64> %v2) { +; CHECK-LABEL: test_v2i64_slt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.2d, v1.2d, v0.2d +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret + %cmp = icmp slt <2 x i64> %v1, %v2 + ret <2 x i1> %cmp +} + +define <4 x i1> @test_v4i64_slt(<4 x i64> %v1, <4 x i64> %v2) { +; CHECK-SD-LABEL: test_v4i64_slt: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: cmgt v1.2d, v3.2d, v1.2d +; CHECK-SD-NEXT: cmgt v0.2d, v2.2d, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v4i64_slt: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: cmgt v0.2d, v2.2d, v0.2d +; CHECK-GI-NEXT: cmgt v1.2d, v3.2d, v1.2d +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret +entry: + %cmp = icmp slt <4 x i64> %v1, %v2 + ret <4 x i1> %cmp +} + +define <4 x i1> @test_v4i32_slt(<4 x i32> %v1, <4 x i32> %v2) { +; CHECK-LABEL: test_v4i32_slt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.4s, v1.4s, v0.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret + %cmp = icmp slt <4 x i32> %v1, %v2 + ret <4 x i1> %cmp +} + +define <2 x i1> @test_v2i32_slt(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: test_v2i32_slt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.2s, v1.2s, v0.2s +; CHECK-NEXT: ret + %cmp = icmp slt <2 x i32> %v1, %v2 + ret <2 x i1> %cmp +} + +define <2 x i1> @test_v2i16_slt(<2 x i16> %v1, <2 x i16> %v2) { +; CHECK-LABEL: test_v2i16_slt: +; CHECK: // %bb.0: +; CHECK-NEXT: shl v0.2s, v0.2s, #16 +; CHECK-NEXT: shl v1.2s, v1.2s, #16 +; CHECK-NEXT: sshr v0.2s, v0.2s, #16 +; CHECK-NEXT: sshr v1.2s, v1.2s, #16 +; CHECK-NEXT: cmgt v0.2s, v1.2s, v0.2s +; CHECK-NEXT: ret + %cmp = icmp slt <2 x i16> %v1, %v2 + ret <2 x i1> %cmp +} + +define <8 x i1> @test_v8i16_slt(<8 x i16> %v1, <8 x i16> %v2) { +; CHECK-LABEL: test_v8i16_slt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.8h, v1.8h, v0.8h +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret + %cmp = icmp slt <8 x i16> %v1, %v2 + ret <8 x i1> %cmp +} + +define <4 x i1> @test_v4i16_slt(<4 x i16> %v1, <4 x i16> %v2) { +; CHECK-LABEL: test_v4i16_slt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.4h, v1.4h, v0.4h +; CHECK-NEXT: ret + %cmp = icmp slt <4 x i16> %v1, %v2 + ret <4 x i1> %cmp +} + +define <16 x i1> @test_v16i8_slt(<16 x i8> %v1, <16 x i8> %v2) { +; CHECK-LABEL: test_v16i8_slt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.16b, v1.16b, v0.16b +; CHECK-NEXT: ret + %cmp = icmp slt <16 x i8> %v1, %v2 + ret <16 x i1> %cmp +} + +define <8 x i1> @test_v8i8_slt(<8 x i8> %v1, <8 x i8> %v2) { +; CHECK-LABEL: test_v8i8_slt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.8b, v1.8b, v0.8b +; CHECK-NEXT: ret + %cmp = icmp slt <8 x i8> %v1, %v2 + ret <8 x i1> %cmp +} + +define <2 x i1> @test_v2i64_sle(<2 x i64> %v1, <2 x i64> %v2) { +; CHECK-LABEL: test_v2i64_sle: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.2d, v1.2d, v0.2d +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret + %cmp = icmp sle <2 x i64> %v1, %v2 + ret <2 x i1> %cmp +} + +define <4 x i1> @test_v4i64_sle(<4 x i64> %v1, <4 x i64> %v2) { +; CHECK-SD-LABEL: test_v4i64_sle: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: cmge v1.2d, v3.2d, v1.2d +; CHECK-SD-NEXT: cmge v0.2d, v2.2d, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: test_v4i64_sle: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: cmge v0.2d, v2.2d, v0.2d +; CHECK-GI-NEXT: cmge v1.2d, v3.2d, v1.2d +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret +entry: + %cmp = icmp sle <4 x i64> %v1, %v2 + ret <4 x i1> %cmp +} + +define <4 x i1> @test_v4i32_sle(<4 x i32> %v1, <4 x i32> %v2) { +; CHECK-LABEL: test_v4i32_sle: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.4s, v1.4s, v0.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret + %cmp = icmp sle <4 x i32> %v1, %v2 + ret <4 x i1> %cmp +} + +define <2 x i1> @test_v2i32_sle(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: test_v2i32_sle: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.2s, v1.2s, v0.2s +; CHECK-NEXT: ret + %cmp = icmp sle <2 x i32> %v1, %v2 + ret <2 x i1> %cmp +} + +define <2 x i1> @test_v2i16_sle(<2 x i16> %v1, <2 x i16> %v2) { +; CHECK-LABEL: test_v2i16_sle: +; CHECK: // %bb.0: +; CHECK-NEXT: shl v0.2s, v0.2s, #16 +; CHECK-NEXT: shl v1.2s, v1.2s, #16 +; CHECK-NEXT: sshr v0.2s, v0.2s, #16 +; CHECK-NEXT: sshr v1.2s, v1.2s, #16 +; CHECK-NEXT: cmge v0.2s, v1.2s, v0.2s +; CHECK-NEXT: ret + %cmp = icmp sle <2 x i16> %v1, %v2 + ret <2 x i1> %cmp +} + +define <8 x i1> @test_v8i16_sle(<8 x i16> %v1, <8 x i16> %v2) { +; CHECK-LABEL: test_v8i16_sle: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.8h, v1.8h, v0.8h +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret + %cmp = icmp sle <8 x i16> %v1, %v2 + ret <8 x i1> %cmp +} + +define <4 x i1> @test_v4i16_sle(<4 x i16> %v1, <4 x i16> %v2) { +; CHECK-LABEL: test_v4i16_sle: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.4h, v1.4h, v0.4h +; CHECK-NEXT: ret + %cmp = icmp sle <4 x i16> %v1, %v2 + ret <4 x i1> %cmp +} + +define <16 x i1> @test_v16i8_sle(<16 x i8> %v1, <16 x i8> %v2) { +; CHECK-LABEL: test_v16i8_sle: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.16b, v1.16b, v0.16b +; CHECK-NEXT: ret + %cmp = icmp sle <16 x i8> %v1, %v2 + ret <16 x i1> %cmp +} + +define <8 x i1> @test_v8i8_sle(<8 x i8> %v1, <8 x i8> %v2) { +; CHECK-LABEL: test_v8i8_sle: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.8b, v1.8b, v0.8b +; CHECK-NEXT: ret + %cmp = icmp sle <8 x i8> %v1, %v2 + ret <8 x i1> %cmp +} + define <2 x i64> @v2i64_i64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %d, <2 x i64> %e) { ; CHECK-LABEL: v2i64_i64: ; CHECK: // %bb.0: // %entry -- GitLab From c6c7afd21edd0d16ebda916ea4939949e4e0fa8e Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Mon, 13 May 2024 11:02:09 +0200 Subject: [PATCH 031/578] [mlir][math] fix rsqrt test to not check sign of NaN Hotfix for "[mlir][math] lower rsqrt to sqrt + fdiv (#91344)" --- mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir b/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir index 9b929b3c864d..80d559cc6f73 100644 --- a/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir +++ b/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir @@ -862,7 +862,7 @@ func.func @rsqrt() { %cst2 = arith.constant 0.0 : f32 call @rsqrt_f32(%cst2) : (f32) -> () - // CHECK: -nan + // CHECK: nan %cst3 = arith.constant -1.0 : f32 call @rsqrt_f32(%cst3) : (f32) -> () -- GitLab From 61d4ca872215d3dfff0b3c92151dcbdc546a0aab Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 13 May 2024 10:37:09 +0100 Subject: [PATCH 032/578] [clang][ExtractAPI] Distinguish between record kind for display and for RTTI (#91466) rdar://127732562 --- clang/include/clang/ExtractAPI/API.h | 7 ++++-- .../clang/ExtractAPI/ExtractAPIVisitor.h | 25 +++++++++++-------- .../Serialization/SymbolGraphSerializer.cpp | 6 ++--- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index d323e1668a72..bf291074fd06 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -266,6 +266,8 @@ struct APIRecord { AccessControl Access; + RecordKind KindForDisplay; + private: const RecordKind Kind; friend class RecordContext; @@ -277,6 +279,7 @@ public: APIRecord *getNextInContext() const { return NextInContext; } RecordKind getKind() const { return Kind; } + RecordKind getKindForDisplay() const { return KindForDisplay; } static APIRecord *castFromRecordContext(const RecordContext *Ctx); static RecordContext *castToRecordContext(const APIRecord *Record); @@ -293,10 +296,10 @@ public: Availability(std::move(Availability)), Linkage(Linkage), Comment(Comment), Declaration(Declaration), SubHeading(SubHeading), IsFromSystemHeader(IsFromSystemHeader), Access(std::move(Access)), - Kind(Kind) {} + KindForDisplay(Kind), Kind(Kind) {} APIRecord(RecordKind Kind, StringRef USR, StringRef Name) - : USR(USR), Name(Name), Kind(Kind) {} + : USR(USR), Name(Name), KindForDisplay(Kind), Kind(Kind) {} // Pure virtual destructor to make APIRecord abstract virtual ~APIRecord() = 0; diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index 97cc457ea2a9..8ccebe457ed5 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -194,6 +194,15 @@ protected: return Bases; } + APIRecord::RecordKind getKindForDisplay(const CXXRecordDecl *Decl) { + if (Decl->isUnion()) + return APIRecord::RK_Union; + if (Decl->isStruct()) + return APIRecord::RK_Struct; + + return APIRecord::RK_CXXClass; + } + StringRef getOwningModuleName(const Decl &D) { if (auto *OwningModule = D.getImportedOwningModule()) return OwningModule->Name; @@ -599,13 +608,6 @@ bool ExtractAPIVisitorBase::VisitCXXRecordDecl( DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - APIRecord::RecordKind Kind; - if (Decl->isUnion()) - Kind = APIRecord::RecordKind::RK_Union; - else if (Decl->isStruct()) - Kind = APIRecord::RecordKind::RK_Struct; - else - Kind = APIRecord::RecordKind::RK_CXXClass; auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl); CXXClassRecord *Record; @@ -619,13 +621,15 @@ bool ExtractAPIVisitorBase::VisitCXXRecordDecl( AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, Template(Decl->getDescribedClassTemplate()), Access, isInSystemHeader(Decl)); - } else + } else { Record = API.createRecord( USR, Name, createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, - SubHeading, Kind, Access, isInSystemHeader(Decl), - isEmbeddedInVarDeclarator(*Decl)); + SubHeading, APIRecord::RecordKind::RK_CXXClass, Access, + isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl)); + } + Record->KindForDisplay = getKindForDisplay(Decl); Record->Bases = getBases(Decl); return true; @@ -849,6 +853,7 @@ bool ExtractAPIVisitorBase:: Template(Decl), DeclarationFragmentsBuilder::getAccessControl(Decl), isInSystemHeader(Decl)); + CTPSR->KindForDisplay = getKindForDisplay(Decl); CTPSR->Bases = getBases(Decl); return true; diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 34278b5d40c4..c16d4623f115 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -514,7 +514,7 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) { /// which is prefixed by the source language name, useful for tooling to parse /// the kind, and a \c displayName for rendering human-readable names. Object serializeSymbolKind(const APIRecord &Record, Language Lang) { - return serializeSymbolKind(Record.getKind(), Lang); + return serializeSymbolKind(Record.KindForDisplay, Lang); } /// Serialize the function signature field, as specified by the @@ -591,8 +591,8 @@ Array generateParentContexts(const SmallVectorImpl &Parents, Elem["usr"] = Parent.USR; Elem["name"] = Parent.Name; if (Parent.Record) - Elem["kind"] = - serializeSymbolKind(Parent.Record->getKind(), Lang)["identifier"]; + Elem["kind"] = serializeSymbolKind(Parent.Record->KindForDisplay, + Lang)["identifier"]; else Elem["kind"] = serializeSymbolKind(APIRecord::RK_Unknown, Lang)["identifier"]; -- GitLab From 119aecb955df91173d69c455bba0abd74271c215 Mon Sep 17 00:00:00 2001 From: Victor Campos Date: Mon, 13 May 2024 11:14:35 +0100 Subject: [PATCH 033/578] [DebugInfo] Emit negative DW_AT_bit_offset in explicit signed form (#87994) Before this patch, the value of DW_AT_bit_offset, used for bitfields before DWARF version 4, was always emitted as an unsigned integer using the form DW_FORM_data. If the value was originally a signed integer, for instance in the case of negative offsets, it was up to debug information consumers to re-cast it to a signed integer. This is problematic since the burden of deciding if the value should be read as signed or unsigned was put onto the debug info consumers: the DWARF specification doesn't define DW_AT_bit_offset's underlying type. If a debugger decided to interpret this attribute in the form data as unsigned, then negative offsets would be completely broken. The DWARF specification version 3 mentions in the Data Representation section, page 127: > If one of the DW_FORM_data forms is used to represent a signed or unsigned integer, it can be hard for a consumer to discover the context necessary to determine which interpretation is intended. Producers are therefore strongly encouraged to use DW_FORM_sdata or DW_FORM_udata for signed and unsigned integers respectively, rather than DW_FORM_data. Therefore, the proposal is to use DW_FORM_sdata, which is explicitly signed. This is an indication to consumers that the offset must be parsed unambiguously as a signed integer. Finally, gcc already uses DW_FORM_sdata for negative offsets, fixing the potential ambiguity altogether. This patch mimics gcc's behaviour by emitting negative values of DW_AT_bit_offset using the DW_FORM_sdata form. This eliminates any potential misinterpretation. One could argue that all values should use DW_FORM_sdata, but for the sake of parity with gcc, it is safe to restrict the change to negative values. --- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 11 +++++++++-- llvm/test/DebugInfo/ARM/bitfield.ll | 2 +- llvm/test/DebugInfo/NVPTX/packed_bitfields.ll | 2 +- llvm/test/DebugInfo/X86/packed_bitfields.ll | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 56c288ee95b4..6533e8281631 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -30,6 +30,7 @@ #include "llvm/Target/TargetLoweringObjectFile.h" #include #include +#include #include #include @@ -1649,7 +1650,8 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) { addUInt(MemberDie, dwarf::DW_AT_byte_size, std::nullopt, FieldSize / 8); addUInt(MemberDie, dwarf::DW_AT_bit_size, std::nullopt, Size); - uint64_t Offset = DT->getOffsetInBits(); + assert(DT->getOffsetInBits() <= std::numeric_limits::max()); + int64_t Offset = DT->getOffsetInBits(); // We can't use DT->getAlignInBits() here: AlignInBits for member type // is non-zero if and only if alignment was forced (e.g. _Alignas()), // which can't be done with bitfields. Thus we use FieldSize here. @@ -1669,7 +1671,12 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) { if (Asm->getDataLayout().isLittleEndian()) Offset = FieldSize - (Offset + Size); - addUInt(MemberDie, dwarf::DW_AT_bit_offset, std::nullopt, Offset); + if (Offset < 0) + addSInt(MemberDie, dwarf::DW_AT_bit_offset, dwarf::DW_FORM_sdata, + Offset); + else + addUInt(MemberDie, dwarf::DW_AT_bit_offset, std::nullopt, + (uint64_t)Offset); OffsetInBytes = FieldOffset >> 3; } else { addUInt(MemberDie, dwarf::DW_AT_data_bit_offset, std::nullopt, Offset); diff --git a/llvm/test/DebugInfo/ARM/bitfield.ll b/llvm/test/DebugInfo/ARM/bitfield.ll index 5bd06b785b15..672c61db6f49 100644 --- a/llvm/test/DebugInfo/ARM/bitfield.ll +++ b/llvm/test/DebugInfo/ARM/bitfield.ll @@ -12,7 +12,7 @@ ; CHECK: DW_AT_name {{.*}} "reserved" ; CHECK: DW_AT_byte_size {{.*}} (0x04) ; CHECK: DW_AT_bit_size {{.*}} (0x1c) -; CHECK: DW_AT_bit_offset {{.*}} (0xfffffffffffffff8) +; CHECK: DW_AT_bit_offset {{.*}} (-8) ; CHECK: DW_AT_data_member_location {{.*}} (DW_OP_plus_uconst 0x0) %struct.anon = type { i8, [5 x i8] } diff --git a/llvm/test/DebugInfo/NVPTX/packed_bitfields.ll b/llvm/test/DebugInfo/NVPTX/packed_bitfields.ll index e2097d7f49b4..62ffa0a4001f 100644 --- a/llvm/test/DebugInfo/NVPTX/packed_bitfields.ll +++ b/llvm/test/DebugInfo/NVPTX/packed_bitfields.ll @@ -16,7 +16,7 @@ ; CHECK-NEXT: .b8 1 // DW_AT_byte_size ; CHECK-NEXT: .b8 6 // DW_AT_bit_size ; Negative offset must be encoded as an unsigned integer. -; CHECK-NEXT: .b64 0xffffffffffffffff // DW_AT_bit_offset +; CHECK-NEXT: .b8 127 // DW_AT_bit_offset ; CHECK-NEXT: .b8 2 // DW_AT_data_member_location %struct.anon = type { i16 } diff --git a/llvm/test/DebugInfo/X86/packed_bitfields.ll b/llvm/test/DebugInfo/X86/packed_bitfields.ll index 0e541f09d227..614fa59c3678 100644 --- a/llvm/test/DebugInfo/X86/packed_bitfields.ll +++ b/llvm/test/DebugInfo/X86/packed_bitfields.ll @@ -15,7 +15,7 @@ ; CHECK-NOT: DW_TAG_member ; CHECK: DW_AT_byte_size {{.*}} (0x01) ; CHECK-NEXT: DW_AT_bit_size {{.*}} (0x06) -; CHECK-NEXT: DW_AT_bit_offset {{.*}} (0xffffffffffffffff) +; CHECK-NEXT: DW_AT_bit_offset {{.*}} (-1) ; CHECK-NEXT: DW_AT_data_member_location {{.*}} ({{.*}}0x0{{0*}}) ; ModuleID = 'repro.c' -- GitLab From 3438d8ac1ba58d098ff8d25a814b2c8c22d5844b Mon Sep 17 00:00:00 2001 From: Xing Xue Date: Mon, 13 May 2024 06:29:50 -0400 Subject: [PATCH 034/578] [libcxx] [test] Fix the locale ctype widen tests on AIX (#91744) The C locale on AIX uses `ISO-8859-1`, where `0xFB` is a valid character. Widening char(-5) succeeds and produces L'\u00fb' the same as on macOS, FreeBSD, and Windows. This patch removes `XFAIL: LIBCXX-AIX-FIXME` and uses the macOS, FreeBSD, and WIN32 code path for AIX. --- .../category.ctype/locale.ctype.byname/widen_1.pass.cpp | 3 +-- .../category.ctype/locale.ctype.byname/widen_many.pass.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_1.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_1.pass.cpp index bafdfcea0460..959a4be9e1de 100644 --- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_1.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_1.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // REQUIRES: locale.en_US.UTF-8 -// XFAIL: LIBCXX-AIX-FIXME // XFAIL: no-wide-characters // @@ -57,7 +56,7 @@ int main(int, char**) assert(f.widen('.') == L'.'); assert(f.widen('a') == L'a'); assert(f.widen('1') == L'1'); -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN32) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN32) || defined(_AIX) assert(f.widen(char(-5)) == L'\u00fb'); #else assert(f.widen(char(-5)) == wchar_t(-1)); diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_many.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_many.pass.cpp index 552eab1f2ab4..078b4a6fefb7 100644 --- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_many.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_many.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // REQUIRES: locale.en_US.UTF-8 -// XFAIL: LIBCXX-AIX-FIXME // XFAIL: no-wide-characters // @@ -63,7 +62,7 @@ int main(int, char**) assert(v[3] == L'.'); assert(v[4] == L'a'); assert(v[5] == L'1'); -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN32) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN32) || defined(_AIX) assert(v[6] == L'\xfb'); #else assert(v[6] == wchar_t(-1)); -- GitLab From 7eeccc1430eeaa434724522945245ba21c97ac57 Mon Sep 17 00:00:00 2001 From: Xing Xue Date: Mon, 13 May 2024 06:30:25 -0400 Subject: [PATCH 035/578] [libcxx][test] Fix numpunct grouping tests on AIX (#91781) The `grouping` string for locale `en_US.UTF-8` and `fr_FR.UTF-8` on AIX is `3`. This is different from Linux's `3;3` but is the same as Windows. This patch removes `XFAIL: LIBCXX-AIX-FIXME` and changes to use the `WIN32` code path. --- .../locale.numpunct.byname/grouping.pass.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/grouping.pass.cpp b/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/grouping.pass.cpp index 2f2bc2fd8832..86c447d400aa 100644 --- a/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/grouping.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/grouping.pass.cpp @@ -9,7 +9,6 @@ // NetBSD does not support LC_NUMERIC at the moment // XFAIL: netbsd -// XFAIL: LIBCXX-AIX-FIXME // XFAIL: LIBCXX-FREEBSD-FIXME // REQUIRES: locale.en_US.UTF-8 @@ -49,7 +48,7 @@ int main(int, char**) { typedef char C; const std::numpunct& np = std::use_facet >(l); -#ifdef _WIN32 +#if defined(_WIN32) || defined(_AIX) assert(np.grouping() == "\3"); #else assert(np.grouping() == "\3\3"); @@ -59,17 +58,17 @@ int main(int, char**) { typedef wchar_t C; const std::numpunct& np = std::use_facet >(l); -#ifdef _WIN32 +# if defined(_WIN32) || defined(_AIX) assert(np.grouping() == "\3"); -#else +# else assert(np.grouping() == "\3\3"); -#endif +# endif } #endif } { std::locale l(LOCALE_fr_FR_UTF_8); -#if defined(TEST_HAS_GLIBC) || defined(_WIN32) +#if defined(TEST_HAS_GLIBC) || defined(_WIN32) || defined(_AIX) const char* const group = "\3"; #else const char* const group = "\x7f"; -- GitLab From fbb37e960616efcf7cd5c1ebbe95f75c65d565dc Mon Sep 17 00:00:00 2001 From: Graham Hunter Date: Mon, 13 May 2024 11:35:28 +0100 Subject: [PATCH 036/578] [AArch64] Add an all-in-one histogram intrinsic Based on discussion from https://discourse.llvm.org/t/rfc-vectorization-support-for-histogram-count-operations/74788 Current interface is: llvm.experimental.histogram( ptrs, inc_amount, mask) The integer type used by 'inc_amount' needs to match the type of the buckets in memory. The intrinsic covers the following operations: * Gather load * histogram on the elements of 'ptrs' * multiply the histogram results by 'inc_amount' * add the result of the multiply to the values loaded by the gather * scatter store the results of the add Supports lowering to histcnt instructions for AArch64 targets, and scalarization for all others at present. --- llvm/docs/LangRef.rst | 54 +++++++++ .../llvm/Analysis/TargetTransformInfo.h | 7 ++ .../llvm/Analysis/TargetTransformInfoImpl.h | 4 + llvm/include/llvm/CodeGen/ISDOpcodes.h | 5 + llvm/include/llvm/CodeGen/SelectionDAG.h | 3 + llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 33 +++++ llvm/include/llvm/IR/Intrinsics.td | 7 ++ llvm/lib/Analysis/TargetTransformInfo.cpp | 5 + .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 38 ++++++ .../SelectionDAG/SelectionDAGBuilder.cpp | 63 ++++++++++ .../SelectionDAG/SelectionDAGBuilder.h | 1 + .../SelectionDAG/SelectionDAGDumper.cpp | 3 + .../Target/AArch64/AArch64ISelLowering.cpp | 63 ++++++++++ llvm/lib/Target/AArch64/AArch64ISelLowering.h | 1 + .../Scalar/ScalarizeMaskedMemIntrin.cpp | 69 +++++++++++ .../AArch64/neon-scalarize-histogram.ll | 114 ++++++++++++++++++ llvm/test/CodeGen/AArch64/sve2-histcnt.ll | 53 ++++++++ 17 files changed, 523 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/neon-scalarize-histogram.ll create mode 100644 llvm/test/CodeGen/AArch64/sve2-histcnt.ll diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index d0515876f9e4..06809f8bf445 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -19143,6 +19143,60 @@ will be on any later loop iteration. This intrinsic will only return 0 if the input count is also 0. A non-zero input count will produce a non-zero result. +'``llvm.experimental.vector.histogram.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These intrinsics are overloaded. + +These intrinsics represent histogram-like operations; that is, updating values +in memory that may not be contiguous, and where multiple elements within a +single vector may be updating the same value in memory. + +The update operation must be specified as part of the intrinsic name. For a +simple histogram like the following the ``add`` operation would be used. + +.. code-block:: c + + void simple_histogram(int *restrict buckets, unsigned *indices, int N, int inc) { + for (int i = 0; i < N; ++i) + buckets[indices[i]] += inc; + } + +More update operation types may be added in the future. + +:: + + declare <8 x i32> @llvm.experimental.vector.histogram.add.v8p0.i32(<8 x ptr> %ptrs, i32 %inc, <8 x i1> %mask) + declare @llvm.experimental.vector.histogram.add.nxv2p0.i64( %ptrs, i64 %inc, %mask) + +Arguments: +"""""""""" + +The first argument is a vector of pointers to the memory locations to be +updated. The second argument is a scalar used to update the value from +memory; it must match the type of value to be updated. The final argument +is a mask value to exclude locations from being modified. + +Semantics: +"""""""""" + +The '``llvm.experimental.vector.histogram.*``' intrinsics are used to perform +updates on potentially overlapping values in memory. The intrinsics represent +the follow sequence of operations: + +1. Gather load from the ``ptrs`` operand, with element type matching that of + the ``inc`` operand. +2. Update of the values loaded from memory. In the case of the ``add`` + update operation, this means: + + 1. Perform a cross-vector histogram operation on the ``ptrs`` operand. + 2. Multiply the result by the ``inc`` operand. + 3. Add the result to the values loaded from memory +3. Scatter the result of the update operation to the memory locations from + the ``ptrs`` operand. + +The ``mask`` operand will apply to at least the gather and scatter operations. + Matrix Intrinsics ----------------- diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h index f0eb83c143e2..0c3a6b3742c7 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -797,6 +797,9 @@ public: /// Return true if the target supports strided load. bool isLegalStridedLoadStore(Type *DataType, Align Alignment) const; + // Return true if the target supports masked vector histograms. + bool isLegalMaskedVectorHistogram(Type *AddrType, Type *DataType) const; + /// Return true if this is an alternating opcode pattern that can be lowered /// to a single instruction on the target. In X86 this is for the addsub /// instruction which corrsponds to a Shuffle + Fadd + FSub pattern in IR. @@ -1883,6 +1886,7 @@ public: virtual bool isLegalMaskedCompressStore(Type *DataType, Align Alignment) = 0; virtual bool isLegalMaskedExpandLoad(Type *DataType, Align Alignment) = 0; virtual bool isLegalStridedLoadStore(Type *DataType, Align Alignment) = 0; + virtual bool isLegalMaskedVectorHistogram(Type *AddrType, Type *DataType) = 0; virtual bool isLegalAltInstr(VectorType *VecTy, unsigned Opcode0, unsigned Opcode1, const SmallBitVector &OpcodeMask) const = 0; @@ -2386,6 +2390,9 @@ public: bool isLegalStridedLoadStore(Type *DataType, Align Alignment) override { return Impl.isLegalStridedLoadStore(DataType, Alignment); } + bool isLegalMaskedVectorHistogram(Type *AddrType, Type *DataType) override { + return Impl.isLegalMaskedVectorHistogram(AddrType, DataType); + } bool isLegalAltInstr(VectorType *VecTy, unsigned Opcode0, unsigned Opcode1, const SmallBitVector &OpcodeMask) const override { return Impl.isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask); diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h index 262ebdb3cbef..9a57331d281d 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -316,6 +316,10 @@ public: return false; } + bool isLegalMaskedVectorHistogram(Type *AddrType, Type *DataType) const { + return false; + } + bool enableOrderedReductions() const { return false; } bool hasDivRemOp(Type *DataType, bool IsSigned) const { return false; } diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h index 6429947958ee..d8af97957e48 100644 --- a/llvm/include/llvm/CodeGen/ISDOpcodes.h +++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -1402,6 +1402,11 @@ enum NodeType { // which is later translated to an implicit use in the MIR. CONVERGENCECTRL_GLUE, + // Experimental vector histogram intrinsic + // Operands: Input Chain, Inc, Mask, Base, Index, Scale, ID + // Output: Output Chain + EXPERIMENTAL_VECTOR_HISTOGRAM, + /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific pre-isel opcode values start here. BUILTIN_OP_END diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h index c08e57ba3f67..979ef8033eb5 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -1526,6 +1526,9 @@ public: ArrayRef Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating = false); + SDValue getMaskedHistogram(SDVTList VTs, EVT MemVT, const SDLoc &dl, + ArrayRef Ops, MachineMemOperand *MMO, + ISD::MemIndexType IndexType); SDValue getGetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO); diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index e7c710414545..ac94c6099d08 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -542,6 +542,7 @@ BEGIN_TWO_BYTE_PACK() friend class MaskedLoadStoreSDNode; friend class MaskedGatherScatterSDNode; friend class VPGatherScatterSDNode; + friend class MaskedHistogramSDNode; uint16_t : NumMemSDNodeBits; @@ -552,6 +553,7 @@ BEGIN_TWO_BYTE_PACK() // MaskedLoadStoreBaseSDNode => enum ISD::MemIndexedMode // VPGatherScatterSDNode => enum ISD::MemIndexType // MaskedGatherScatterSDNode => enum ISD::MemIndexType + // MaskedHistogramSDNode => enum ISD::MemIndexType uint16_t AddressingMode : 3; }; enum { NumLSBaseSDNodeBits = NumMemSDNodeBits + 3 }; @@ -564,6 +566,7 @@ BEGIN_TWO_BYTE_PACK() friend class MaskedLoadSDNode; friend class MaskedGatherSDNode; friend class VPGatherSDNode; + friend class MaskedHistogramSDNode; uint16_t : NumLSBaseSDNodeBits; @@ -1420,6 +1423,7 @@ public: return getOperand(2); case ISD::MGATHER: case ISD::MSCATTER: + case ISD::EXPERIMENTAL_VECTOR_HISTOGRAM: return getOperand(3); default: return getOperand(1); @@ -1468,6 +1472,7 @@ public: case ISD::EXPERIMENTAL_VP_STRIDED_STORE: case ISD::GET_FPENV_MEM: case ISD::SET_FPENV_MEM: + case ISD::EXPERIMENTAL_VECTOR_HISTOGRAM: return true; default: return N->isMemIntrinsic() || N->isTargetMemoryOpcode(); @@ -2953,6 +2958,34 @@ public: } }; +class MaskedHistogramSDNode : public MemSDNode { +public: + friend class SelectionDAG; + + MaskedHistogramSDNode(unsigned Order, const DebugLoc &DL, SDVTList VTs, + EVT MemVT, MachineMemOperand *MMO, + ISD::MemIndexType IndexType) + : MemSDNode(ISD::EXPERIMENTAL_VECTOR_HISTOGRAM, Order, DL, VTs, MemVT, + MMO) { + LSBaseSDNodeBits.AddressingMode = IndexType; + } + + ISD::MemIndexType getIndexType() const { + return static_cast(LSBaseSDNodeBits.AddressingMode); + } + + const SDValue &getBasePtr() const { return getOperand(3); } + const SDValue &getIndex() const { return getOperand(4); } + const SDValue &getMask() const { return getOperand(2); } + const SDValue &getScale() const { return getOperand(5); } + const SDValue &getInc() const { return getOperand(1); } + const SDValue &getIntID() const { return getOperand(6); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::EXPERIMENTAL_VECTOR_HISTOGRAM; + } +}; + class FPStateAccessSDNode : public MemSDNode { public: friend class SelectionDAG; diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 42192d472ba6..f1c7d950f927 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1856,6 +1856,13 @@ def int_experimental_vp_strided_load : DefaultAttrsIntrinsic<[llvm_anyvector_ty llvm_i32_ty], [ NoCapture>, IntrNoSync, IntrReadMem, IntrWillReturn, IntrArgMemOnly ]>; +// Experimental histogram +def int_experimental_vector_histogram_add : DefaultAttrsIntrinsic<[], + [ llvm_anyvector_ty, // Vector of pointers + llvm_anyint_ty, // Increment + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], // Mask + [ IntrArgMemOnly ]>; + // Operators let IntrProperties = [IntrNoMem, IntrNoSync, IntrWillReturn] in { // Integer arithmetic diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp index 00443ace46f7..f6a458f7ded4 100644 --- a/llvm/lib/Analysis/TargetTransformInfo.cpp +++ b/llvm/lib/Analysis/TargetTransformInfo.cpp @@ -513,6 +513,11 @@ bool TargetTransformInfo::isLegalStridedLoadStore(Type *DataType, return TTIImpl->isLegalStridedLoadStore(DataType, Alignment); } +bool TargetTransformInfo::isLegalMaskedVectorHistogram(Type *AddrType, + Type *DataType) const { + return TTIImpl->isLegalMaskedVectorHistogram(AddrType, DataType); +} + bool TargetTransformInfo::enableOrderedReductions() const { return TTIImpl->enableOrderedReductions(); } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 0a258350c68a..247f52370e4c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -9633,6 +9633,44 @@ SDValue SelectionDAG::getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, return V; } +SDValue SelectionDAG::getMaskedHistogram(SDVTList VTs, EVT MemVT, + const SDLoc &dl, ArrayRef Ops, + MachineMemOperand *MMO, + ISD::MemIndexType IndexType) { + assert(Ops.size() == 7 && "Incompatible number of operands"); + + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::EXPERIMENTAL_VECTOR_HISTOGRAM, VTs, Ops); + ID.AddInteger(MemVT.getRawBits()); + ID.AddInteger(getSyntheticNodeSubclassData( + dl.getIROrder(), VTs, MemVT, MMO, IndexType)); + ID.AddInteger(MMO->getPointerInfo().getAddrSpace()); + ID.AddInteger(MMO->getFlags()); + void *IP = nullptr; + if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + + auto *N = newSDNode(dl.getIROrder(), dl.getDebugLoc(), + VTs, MemVT, MMO, IndexType); + createOperands(N, Ops); + + assert(N->getMask().getValueType().getVectorElementCount() == + N->getIndex().getValueType().getVectorElementCount() && + "Vector width mismatch between mask and data"); + assert(isa(N->getScale()) && + N->getScale()->getAsAPIntVal().isPowerOf2() && + "Scale should be a constant power of 2"); + assert(N->getInc().getValueType().isInteger() && "Non integer update value"); + + CSEMap.InsertNode(N, IP); + InsertNode(N); + SDValue V(N, 0); + NewSDValueDbgMsg(V, "Creating new node: ", this); + return V; +} + SDValue SelectionDAG::getGetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO) { assert(Chain.getValueType() == MVT::Other && "Invalid chain type"); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index b76036a22992..ca352da5d36e 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6281,6 +6281,64 @@ void SelectionDAGBuilder::visitConvergenceControl(const CallInst &I, } } +void SelectionDAGBuilder::visitVectorHistogram(const CallInst &I, + unsigned IntrinsicID) { + // For now, we're only lowering an 'add' histogram. + // We can add others later, e.g. saturating adds, min/max. + assert(IntrinsicID == Intrinsic::experimental_vector_histogram_add && + "Tried to lower unsupported histogram type"); + SDLoc sdl = getCurSDLoc(); + Value *Ptr = I.getOperand(0); + SDValue Inc = getValue(I.getOperand(1)); + SDValue Mask = getValue(I.getOperand(2)); + + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + DataLayout TargetDL = DAG.getDataLayout(); + EVT VT = Inc.getValueType(); + Align Alignment = DAG.getEVTAlign(VT); + + const MDNode *Ranges = getRangeMetadata(I); + + SDValue Root = DAG.getRoot(); + SDValue Base; + SDValue Index; + ISD::MemIndexType IndexType; + SDValue Scale; + bool UniformBase = getUniformBase(Ptr, Base, Index, IndexType, Scale, this, + I.getParent(), VT.getScalarStoreSize()); + + unsigned AS = Ptr->getType()->getScalarType()->getPointerAddressSpace(); + + MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( + MachinePointerInfo(AS), + MachineMemOperand::MOLoad | MachineMemOperand::MOStore, + MemoryLocation::UnknownSize, Alignment, I.getAAMetadata(), Ranges); + + if (!UniformBase) { + Base = DAG.getConstant(0, sdl, TLI.getPointerTy(DAG.getDataLayout())); + Index = getValue(Ptr); + IndexType = ISD::SIGNED_SCALED; + Scale = + DAG.getTargetConstant(1, sdl, TLI.getPointerTy(DAG.getDataLayout())); + } + + EVT IdxVT = Index.getValueType(); + EVT EltTy = IdxVT.getVectorElementType(); + if (TLI.shouldExtendGSIndex(IdxVT, EltTy)) { + EVT NewIdxVT = IdxVT.changeVectorElementType(EltTy); + Index = DAG.getNode(ISD::SIGN_EXTEND, sdl, NewIdxVT, Index); + } + + SDValue ID = DAG.getTargetConstant(IntrinsicID, sdl, MVT::i32); + + SDValue Ops[] = {Root, Inc, Mask, Base, Index, Scale, ID}; + SDValue Histogram = DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), VT, sdl, + Ops, MMO, IndexType); + + setValue(&I, Histogram); + DAG.setRoot(Histogram); +} + /// Lower the call to the specified intrinsic function. void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { @@ -7948,6 +8006,11 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, case Intrinsic::experimental_convergence_entry: case Intrinsic::experimental_convergence_loop: visitConvergenceControl(I, Intrinsic); + return; + case Intrinsic::experimental_vector_histogram_add: { + visitVectorHistogram(I, Intrinsic); + return; + } } } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index 211e1653de56..ae361f8c500a 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -624,6 +624,7 @@ private: void visitTargetIntrinsic(const CallInst &I, unsigned Intrinsic); void visitConstrainedFPIntrinsic(const ConstrainedFPIntrinsic &FPI); void visitConvergenceControl(const CallInst &I, unsigned Intrinsic); + void visitVectorHistogram(const CallInst &I, unsigned IntrinsicID); void visitVPLoad(const VPIntrinsic &VPIntrin, EVT VT, const SmallVectorImpl &OpValues); void visitVPStore(const VPIntrinsic &VPIntrin, diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp index 4ad4a938ca97..59742e90c679 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp @@ -529,6 +529,9 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::PATCHPOINT: return "patchpoint"; + case ISD::EXPERIMENTAL_VECTOR_HISTOGRAM: + return "histogram"; + // Vector Predication #define BEGIN_REGISTER_VP_SDNODE(SDID, LEGALARG, NAME, ...) \ case ISD::SDID: \ diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 1e0071fffe66..0f1db3cb17aa 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -1618,6 +1618,11 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM, setOperationAction(ISD::VECREDUCE_SEQ_FADD, VT, Custom); } + // Histcnt is SVE2 only + if (Subtarget->hasSVE2() && Subtarget->isSVEAvailable()) + setOperationAction(ISD::EXPERIMENTAL_VECTOR_HISTOGRAM, MVT::Other, + Custom); + // NOTE: Currently this has to happen after computeRegisterProperties rather // than the preferred option of combining it with the addRegisterClass call. if (Subtarget->useSVEForFixedLengthVectors()) { @@ -6775,6 +6780,8 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op, return LowerFunnelShift(Op, DAG); case ISD::FLDEXP: return LowerFLDEXP(Op, DAG); + case ISD::EXPERIMENTAL_VECTOR_HISTOGRAM: + return LowerVECTOR_HISTOGRAM(Op, DAG); } } @@ -27355,6 +27362,62 @@ SDValue AArch64TargetLowering::LowerVECTOR_INTERLEAVE(SDValue Op, return DAG.getMergeValues({Lo, Hi}, DL); } +SDValue AArch64TargetLowering::LowerVECTOR_HISTOGRAM(SDValue Op, + SelectionDAG &DAG) const { + // FIXME: Maybe share some code with LowerMGather/Scatter? + MaskedHistogramSDNode *HG = cast(Op); + SDLoc DL(HG); + SDValue Chain = HG->getChain(); + SDValue Inc = HG->getInc(); + SDValue Mask = HG->getMask(); + SDValue Ptr = HG->getBasePtr(); + SDValue Index = HG->getIndex(); + SDValue Scale = HG->getScale(); + SDValue IntID = HG->getIntID(); + + // The Intrinsic ID determines the type of update operation. + ConstantSDNode *CID = cast(IntID.getNode()); + // Right now, we only support 'add' as an update. + assert(CID->getZExtValue() == Intrinsic::experimental_vector_histogram_add && + "Unexpected histogram update operation"); + + EVT IncVT = Inc.getValueType(); + EVT IndexVT = Index.getValueType(); + EVT MemVT = EVT::getVectorVT(*DAG.getContext(), IncVT, + IndexVT.getVectorElementCount()); + SDValue Zero = DAG.getConstant(0, DL, MVT::i64); + SDValue PassThru = DAG.getSplatVector(MemVT, DL, Zero); + SDValue IncSplat = DAG.getSplatVector(MemVT, DL, Inc); + SDValue Ops[] = {Chain, PassThru, Mask, Ptr, Index, Scale}; + + // Set the MMO to load only, rather than load|store. + MachineMemOperand *GMMO = HG->getMemOperand(); + GMMO->setFlags(MachineMemOperand::MOLoad); + ISD::MemIndexType IndexType = HG->getIndexType(); + SDValue Gather = + DAG.getMaskedGather(DAG.getVTList(MemVT, MVT::Other), MemVT, DL, Ops, + GMMO, IndexType, ISD::NON_EXTLOAD); + + SDValue GChain = Gather.getValue(1); + + // Perform the histcnt, multiply by inc, add to bucket data. + SDValue ID = DAG.getTargetConstant(Intrinsic::aarch64_sve_histcnt, DL, IncVT); + SDValue HistCnt = + DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, IndexVT, ID, Mask, Index, Index); + SDValue Mul = DAG.getNode(ISD::MUL, DL, MemVT, HistCnt, IncSplat); + SDValue Add = DAG.getNode(ISD::ADD, DL, MemVT, Gather, Mul); + + // Create a new MMO for the scatter. + MachineMemOperand *SMMO = DAG.getMachineFunction().getMachineMemOperand( + GMMO->getPointerInfo(), MachineMemOperand::MOStore, GMMO->getSize(), + GMMO->getAlign(), GMMO->getAAInfo()); + + SDValue ScatterOps[] = {GChain, Add, Mask, Ptr, Index, Scale}; + SDValue Scatter = DAG.getMaskedScatter(DAG.getVTList(MVT::Other), MemVT, DL, + ScatterOps, SMMO, IndexType, false); + return Scatter; +} + SDValue AArch64TargetLowering::LowerFixedLengthFPToIntToSVE(SDValue Op, SelectionDAG &DAG) const { diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index b3e282a04060..a44a3d35d2f9 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -1149,6 +1149,7 @@ private: SDValue LowerINSERT_SUBVECTOR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVECTOR_DEINTERLEAVE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVECTOR_INTERLEAVE(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerVECTOR_HISTOGRAM(SDValue Op, SelectionDAG &DAG) const; SDValue LowerDIV(SDValue Op, SelectionDAG &DAG) const; SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVectorSRA_SRL_SHL(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/lib/Transforms/Scalar/ScalarizeMaskedMemIntrin.cpp b/llvm/lib/Transforms/Scalar/ScalarizeMaskedMemIntrin.cpp index a4111fad5d9f..de80fa2c0502 100644 --- a/llvm/lib/Transforms/Scalar/ScalarizeMaskedMemIntrin.cpp +++ b/llvm/lib/Transforms/Scalar/ScalarizeMaskedMemIntrin.cpp @@ -862,6 +862,69 @@ static void scalarizeMaskedCompressStore(const DataLayout &DL, CallInst *CI, ModifiedDT = true; } +static void scalarizeMaskedVectorHistogram(const DataLayout &DL, CallInst *CI, + DomTreeUpdater *DTU, + bool &ModifiedDT) { + // If we extend histogram to return a result someday (like the updated vector) + // then we'll need to support it here. + assert(CI->getType()->isVoidTy() && "Histogram with non-void return."); + Value *Ptrs = CI->getArgOperand(0); + Value *Inc = CI->getArgOperand(1); + Value *Mask = CI->getArgOperand(2); + + auto *AddrType = cast(Ptrs->getType()); + Type *EltTy = Inc->getType(); + + IRBuilder<> Builder(CI->getContext()); + Instruction *InsertPt = CI; + Builder.SetInsertPoint(InsertPt); + + Builder.SetCurrentDebugLocation(CI->getDebugLoc()); + + // FIXME: Do we need to add an alignment parameter to the intrinsic? + unsigned VectorWidth = AddrType->getNumElements(); + + // Shorten the way if the mask is a vector of constants. + if (isConstantIntVector(Mask)) { + for (unsigned Idx = 0; Idx < VectorWidth; ++Idx) { + if (cast(Mask)->getAggregateElement(Idx)->isNullValue()) + continue; + Value *Ptr = Builder.CreateExtractElement(Ptrs, Idx, "Ptr" + Twine(Idx)); + LoadInst *Load = Builder.CreateLoad(EltTy, Ptr, "Load" + Twine(Idx)); + Value *Add = Builder.CreateAdd(Load, Inc); + Builder.CreateStore(Add, Ptr); + } + CI->eraseFromParent(); + return; + } + + for (unsigned Idx = 0; Idx < VectorWidth; ++Idx) { + Value *Predicate = + Builder.CreateExtractElement(Mask, Idx, "Mask" + Twine(Idx)); + + Instruction *ThenTerm = + SplitBlockAndInsertIfThen(Predicate, InsertPt, /*Unreachable=*/false, + /*BranchWeights=*/nullptr, DTU); + + BasicBlock *CondBlock = ThenTerm->getParent(); + CondBlock->setName("cond.histogram.update"); + + Builder.SetInsertPoint(CondBlock->getTerminator()); + Value *Ptr = Builder.CreateExtractElement(Ptrs, Idx, "Ptr" + Twine(Idx)); + LoadInst *Load = Builder.CreateLoad(EltTy, Ptr, "Load" + Twine(Idx)); + Value *Add = Builder.CreateAdd(Load, Inc); + Builder.CreateStore(Add, Ptr); + + // Create "else" block, fill it in the next iteration + BasicBlock *NewIfBlock = ThenTerm->getSuccessor(0); + NewIfBlock->setName("else"); + Builder.SetInsertPoint(NewIfBlock, NewIfBlock->begin()); + } + + CI->eraseFromParent(); + ModifiedDT = true; +} + static bool runImpl(Function &F, const TargetTransformInfo &TTI, DominatorTree *DT) { std::optional DTU; @@ -938,6 +1001,12 @@ static bool optimizeCallInst(CallInst *CI, bool &ModifiedDT, switch (II->getIntrinsicID()) { default: break; + case Intrinsic::experimental_vector_histogram_add: + if (TTI.isLegalMaskedVectorHistogram(CI->getArgOperand(0)->getType(), + CI->getArgOperand(1)->getType())) + return false; + scalarizeMaskedVectorHistogram(DL, CI, DTU, ModifiedDT); + break; case Intrinsic::masked_load: // Scalarize unsupported vector masked load if (TTI.isLegalMaskedLoad( diff --git a/llvm/test/CodeGen/AArch64/neon-scalarize-histogram.ll b/llvm/test/CodeGen/AArch64/neon-scalarize-histogram.ll new file mode 100644 index 000000000000..45f1429a810a --- /dev/null +++ b/llvm/test/CodeGen/AArch64/neon-scalarize-histogram.ll @@ -0,0 +1,114 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 +; RUN: llc -mtriple=aarch64 < %s -o - | FileCheck %s + +;; This test exercises the default lowering of the histogram to scalarized code. + +define void @histogram_i64(<2 x ptr> %buckets, i64 %inc, <2 x i1> %mask) { +; CHECK-LABEL: histogram_i64: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: fmov w8, s1 +; CHECK-NEXT: tbnz w8, #0, .LBB0_3 +; CHECK-NEXT: // %bb.1: // %else +; CHECK-NEXT: mov w8, v1.s[1] +; CHECK-NEXT: tbnz w8, #0, .LBB0_4 +; CHECK-NEXT: .LBB0_2: // %else2 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB0_3: // %cond.histogram.update +; CHECK-NEXT: fmov x8, d0 +; CHECK-NEXT: ldr x9, [x8] +; CHECK-NEXT: add x9, x9, x0 +; CHECK-NEXT: str x9, [x8] +; CHECK-NEXT: mov w8, v1.s[1] +; CHECK-NEXT: tbz w8, #0, .LBB0_2 +; CHECK-NEXT: .LBB0_4: // %cond.histogram.update1 +; CHECK-NEXT: mov x8, v0.d[1] +; CHECK-NEXT: ldr x9, [x8] +; CHECK-NEXT: add x9, x9, x0 +; CHECK-NEXT: str x9, [x8] +; CHECK-NEXT: ret + call void @llvm.experimental.vector.histogram.add.nxv2p0.i64(<2 x ptr> %buckets, i64 %inc, <2 x i1> %mask) + ret void +} + +define void @histogram_i32_literal(ptr %base, <4 x i32> %indices, <4 x i1> %mask) { +; CHECK-LABEL: histogram_i32_literal: +; CHECK: // %bb.0: +; CHECK-NEXT: dup v2.2d, x0 +; CHECK-NEXT: sshll v3.2d, v0.2s, #2 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: umov w8, v1.h[0] +; CHECK-NEXT: add v3.2d, v2.2d, v3.2d +; CHECK-NEXT: tbz w8, #0, .LBB1_2 +; CHECK-NEXT: // %bb.1: // %cond.histogram.update +; CHECK-NEXT: fmov x8, d3 +; CHECK-NEXT: ldr w9, [x8] +; CHECK-NEXT: add w9, w9, #1 +; CHECK-NEXT: str w9, [x8] +; CHECK-NEXT: .LBB1_2: // %else +; CHECK-NEXT: umov w8, v1.h[1] +; CHECK-NEXT: sshll2 v0.2d, v0.4s, #2 +; CHECK-NEXT: tbz w8, #0, .LBB1_4 +; CHECK-NEXT: // %bb.3: // %cond.histogram.update1 +; CHECK-NEXT: mov x8, v3.d[1] +; CHECK-NEXT: ldr w9, [x8] +; CHECK-NEXT: add w9, w9, #1 +; CHECK-NEXT: str w9, [x8] +; CHECK-NEXT: .LBB1_4: // %else2 +; CHECK-NEXT: umov w8, v1.h[2] +; CHECK-NEXT: add v0.2d, v2.2d, v0.2d +; CHECK-NEXT: tbnz w8, #0, .LBB1_7 +; CHECK-NEXT: // %bb.5: // %else4 +; CHECK-NEXT: umov w8, v1.h[3] +; CHECK-NEXT: tbnz w8, #0, .LBB1_8 +; CHECK-NEXT: .LBB1_6: // %else6 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB1_7: // %cond.histogram.update3 +; CHECK-NEXT: fmov x8, d0 +; CHECK-NEXT: ldr w9, [x8] +; CHECK-NEXT: add w9, w9, #1 +; CHECK-NEXT: str w9, [x8] +; CHECK-NEXT: umov w8, v1.h[3] +; CHECK-NEXT: tbz w8, #0, .LBB1_6 +; CHECK-NEXT: .LBB1_8: // %cond.histogram.update5 +; CHECK-NEXT: mov x8, v0.d[1] +; CHECK-NEXT: ldr w9, [x8] +; CHECK-NEXT: add w9, w9, #1 +; CHECK-NEXT: str w9, [x8] +; CHECK-NEXT: ret + + %buckets = getelementptr i32, ptr %base, <4 x i32> %indices + call void @llvm.experimental.vector.histogram.add.nxv4p0.i32(<4 x ptr> %buckets, i32 1, <4 x i1> %mask) + ret void +} + +define void @histogram_i32_literal_alltruemask(ptr %base, <4 x i32> %indices) { +; CHECK-LABEL: histogram_i32_literal_alltruemask: +; CHECK: // %bb.0: +; CHECK-NEXT: dup v1.2d, x0 +; CHECK-NEXT: sshll v2.2d, v0.2s, #2 +; CHECK-NEXT: sshll2 v0.2d, v0.4s, #2 +; CHECK-NEXT: add v2.2d, v1.2d, v2.2d +; CHECK-NEXT: add v0.2d, v1.2d, v0.2d +; CHECK-NEXT: fmov x8, d2 +; CHECK-NEXT: mov x9, v2.d[1] +; CHECK-NEXT: ldr w10, [x8] +; CHECK-NEXT: add w10, w10, #1 +; CHECK-NEXT: str w10, [x8] +; CHECK-NEXT: ldr w8, [x9] +; CHECK-NEXT: add w8, w8, #1 +; CHECK-NEXT: str w8, [x9] +; CHECK-NEXT: fmov x8, d0 +; CHECK-NEXT: mov x9, v0.d[1] +; CHECK-NEXT: ldr w10, [x8] +; CHECK-NEXT: add w10, w10, #1 +; CHECK-NEXT: str w10, [x8] +; CHECK-NEXT: ldr w8, [x9] +; CHECK-NEXT: add w8, w8, #1 +; CHECK-NEXT: str w8, [x9] +; CHECK-NEXT: ret + + %buckets = getelementptr i32, ptr %base, <4 x i32> %indices + call void @llvm.experimental.vector.histogram.add.nxv4p0.i32(<4 x ptr> %buckets, i32 1, <4 x i1> ) + ret void +} diff --git a/llvm/test/CodeGen/AArch64/sve2-histcnt.ll b/llvm/test/CodeGen/AArch64/sve2-histcnt.ll new file mode 100644 index 000000000000..557a42116cdb --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sve2-histcnt.ll @@ -0,0 +1,53 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 +; RUN: llc -mtriple=aarch64 < %s -o - | FileCheck %s + +define void @histogram_i64( %buckets, i64 %inc, %mask) #0 { +; CHECK-LABEL: histogram_i64: +; CHECK: // %bb.0: +; CHECK-NEXT: histcnt z1.d, p0/z, z0.d, z0.d +; CHECK-NEXT: mov z3.d, x0 +; CHECK-NEXT: ld1d { z2.d }, p0/z, [z0.d] +; CHECK-NEXT: ptrue p1.d +; CHECK-NEXT: mad z1.d, p1/m, z3.d, z2.d +; CHECK-NEXT: st1d { z1.d }, p0, [z0.d] +; CHECK-NEXT: ret + call void @llvm.experimental.vector.histogram.add.nxv2p0.i64( %buckets, i64 %inc, %mask) + ret void +} + +;; FIXME: We maybe need some dagcombines here? We're multiplying the output of the histcnt +;; by 1, so we should be able to remove that and directly add the histcnt to the +;; current bucket data. +define void @histogram_i32_literal(ptr %base, %indices, %mask) #0 { +; CHECK-LABEL: histogram_i32_literal: +; CHECK: // %bb.0: +; CHECK-NEXT: histcnt z1.s, p0/z, z0.s, z0.s +; CHECK-NEXT: mov z3.s, #1 // =0x1 +; CHECK-NEXT: ld1w { z2.s }, p0/z, [x0, z0.s, sxtw #2] +; CHECK-NEXT: ptrue p1.s +; CHECK-NEXT: mad z1.s, p1/m, z3.s, z2.s +; CHECK-NEXT: st1w { z1.s }, p0, [x0, z0.s, sxtw #2] +; CHECK-NEXT: ret + + %buckets = getelementptr i32, ptr %base, %indices + call void @llvm.experimental.vector.histogram.add.nxv4p0.i32( %buckets, i32 1, %mask) + ret void +} + +define void @histogram_i32_literal_noscale(ptr %base, %indices, %mask) #0 { +; CHECK-LABEL: histogram_i32_literal_noscale: +; CHECK: // %bb.0: +; CHECK-NEXT: histcnt z1.s, p0/z, z0.s, z0.s +; CHECK-NEXT: mov z3.s, #1 // =0x1 +; CHECK-NEXT: ld1w { z2.s }, p0/z, [x0, z0.s, sxtw] +; CHECK-NEXT: ptrue p1.s +; CHECK-NEXT: mad z1.s, p1/m, z3.s, z2.s +; CHECK-NEXT: st1w { z1.s }, p0, [x0, z0.s, sxtw] +; CHECK-NEXT: ret + + %buckets = getelementptr i8, ptr %base, %indices + call void @llvm.experimental.vector.histogram.add.nxv4p0.i32( %buckets, i32 1, %mask) + ret void +} + +attributes #0 = { "target-features"="+sve2" vscale_range(1, 16) } -- GitLab From fcc1baaa99fda4f5633e82f47e8de33c99bbcdd2 Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Mon, 13 May 2024 18:48:27 +0800 Subject: [PATCH 037/578] [AArch64] Fix -Wunused-variable in AArch64ISelLowering.cpp (NFC) llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp:27379:19: error: unused variable 'CID' [-Werror,-Wunused-variable] ConstantSDNode *CID = cast(IntID.getNode()); ^ 1 error generated. --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 0f1db3cb17aa..2aa328e0a127 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -27376,7 +27376,7 @@ SDValue AArch64TargetLowering::LowerVECTOR_HISTOGRAM(SDValue Op, SDValue IntID = HG->getIntID(); // The Intrinsic ID determines the type of update operation. - ConstantSDNode *CID = cast(IntID.getNode()); + [[maybe_unused]] ConstantSDNode *CID = cast(IntID.getNode()); // Right now, we only support 'add' as an update. assert(CID->getZExtValue() == Intrinsic::experimental_vector_histogram_add && "Unexpected histogram update operation"); -- GitLab From 0a6103eaeb7f22c009f9add87c84780b6f7f293a Mon Sep 17 00:00:00 2001 From: Muhammad Omair Javaid Date: Mon, 13 May 2024 16:01:17 +0500 Subject: [PATCH 038/578] Revert "[lldb] Attempt to fix signal-in-leaf-function-aarch64 on darwin" This reverts commit b903badd73a2467fdd4e363231f2bf9b0704b546. TestInterruptBacktrace was broken on AArch64/Windows as a result of this change. see lldb-aarch64-windows buildbot here: https://lab.llvm.org/buildbot/#/builders/219/builds/11261 --- .../test/Shell/Unwind/Inputs/signal-in-leaf-function-aarch64.c | 2 +- lldb/test/Shell/Unwind/signal-in-leaf-function-aarch64.test | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lldb/test/Shell/Unwind/Inputs/signal-in-leaf-function-aarch64.c b/lldb/test/Shell/Unwind/Inputs/signal-in-leaf-function-aarch64.c index fe020affcad0..9a751330623f 100644 --- a/lldb/test/Shell/Unwind/Inputs/signal-in-leaf-function-aarch64.c +++ b/lldb/test/Shell/Unwind/Inputs/signal-in-leaf-function-aarch64.c @@ -7,7 +7,7 @@ int __attribute__((naked)) signal_generating_add(int a, int b) { "ret"); } -void sigill_handler(int signo) { _exit(0); } +void sigill_handler(int) { _exit(0); } int main() { signal(SIGILL, sigill_handler); diff --git a/lldb/test/Shell/Unwind/signal-in-leaf-function-aarch64.test b/lldb/test/Shell/Unwind/signal-in-leaf-function-aarch64.test index 09f17c174bbf..0580d0cf734a 100644 --- a/lldb/test/Shell/Unwind/signal-in-leaf-function-aarch64.test +++ b/lldb/test/Shell/Unwind/signal-in-leaf-function-aarch64.test @@ -4,9 +4,6 @@ # RUN: %clang_host %S/Inputs/signal-in-leaf-function-aarch64.c -o %t # RUN: %lldb -s %s -o exit %t | FileCheck %s -# Convert EXC_BAD_INSTRUCTION to SIGILL on darwin -settings set platform.plugin.darwin.ignored-exceptions EXC_BAD_INSTRUCTION - breakpoint set -n sigill_handler # CHECK: Breakpoint 1: where = {{.*}}`sigill_handler -- GitLab From 4b44502ac81259630b422e791a82e0252e6478c3 Mon Sep 17 00:00:00 2001 From: Muhammad Omair Javaid Date: Mon, 13 May 2024 16:03:33 +0500 Subject: [PATCH 039/578] Revert "[lldb/aarch64] Fix unwinding when signal interrupts a leaf function (#91321)" This reverts commit fd1bd53ba5a06f344698a55578f6a5d79c457e30. TestInterruptBacktrace was broken on AArch64/Windows as a result of this change. See lldb-aarch64-windows buildbot here: https://lab.llvm.org/buildbot/#/builders/219/builds/11261 --- .../ARM64/EmulateInstructionARM64.cpp | 2 -- .../UnwindAssemblyInstEmulation.cpp | 4 +++- lldb/source/Target/RegisterContextUnwind.cpp | 6 ++--- .../Inputs/signal-in-leaf-function-aarch64.c | 15 ------------ .../signal-in-leaf-function-aarch64.test | 24 ------------------- .../ARM64/TestArm64InstEmulation.cpp | 24 ++++--------------- 6 files changed, 10 insertions(+), 65 deletions(-) delete mode 100644 lldb/test/Shell/Unwind/Inputs/signal-in-leaf-function-aarch64.c delete mode 100644 lldb/test/Shell/Unwind/signal-in-leaf-function-aarch64.test diff --git a/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index 62ecac3e0831..6ca4fb052457 100644 --- a/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -444,8 +444,6 @@ bool EmulateInstructionARM64::CreateFunctionEntryUnwind( // Our previous Call Frame Address is the stack pointer row->GetCFAValue().SetIsRegisterPlusOffset(gpr_sp_arm64, 0); - row->SetRegisterLocationToSame(gpr_lr_arm64, /*must_replace=*/false); - row->SetRegisterLocationToSame(gpr_fp_arm64, /*must_replace=*/false); unwind_plan.AppendRow(row); unwind_plan.SetSourceName("EmulateInstructionARM64"); diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 49edd40544e3..c4a171ec7d01 100644 --- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -424,6 +424,8 @@ size_t UnwindAssemblyInstEmulation::WriteMemory( log->PutString(strm.GetString()); } + const bool cant_replace = false; + switch (context.type) { default: case EmulateInstruction::eContextInvalid: @@ -465,7 +467,7 @@ size_t UnwindAssemblyInstEmulation::WriteMemory( m_pushed_regs[reg_num] = addr; const int32_t offset = addr - m_initial_sp; m_curr_row->SetRegisterLocationToAtCFAPlusOffset(reg_num, offset, - /*can_replace=*/true); + cant_replace); m_curr_row_modified = true; } } diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp index e2d712cb72ea..13e101413a47 100644 --- a/lldb/source/Target/RegisterContextUnwind.cpp +++ b/lldb/source/Target/RegisterContextUnwind.cpp @@ -1555,12 +1555,12 @@ RegisterContextUnwind::SavedLocationForRegister( } if (unwindplan_regloc.IsSame()) { - if (!m_all_registers_available && + if (!IsFrameZero() && (regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_PC || regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_RA)) { UnwindLogMsg("register %s (%d) is marked as 'IsSame' - it is a pc or " - "return address reg on a frame which does not have all " - "registers available -- treat as if we have no information", + "return address reg on a non-zero frame -- treat as if we " + "have no information", regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } else { diff --git a/lldb/test/Shell/Unwind/Inputs/signal-in-leaf-function-aarch64.c b/lldb/test/Shell/Unwind/Inputs/signal-in-leaf-function-aarch64.c deleted file mode 100644 index 9a751330623f..000000000000 --- a/lldb/test/Shell/Unwind/Inputs/signal-in-leaf-function-aarch64.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -int __attribute__((naked)) signal_generating_add(int a, int b) { - asm("add w0, w1, w0\n\t" - "udf #0xdead\n\t" - "ret"); -} - -void sigill_handler(int) { _exit(0); } - -int main() { - signal(SIGILL, sigill_handler); - return signal_generating_add(42, 47); -} diff --git a/lldb/test/Shell/Unwind/signal-in-leaf-function-aarch64.test b/lldb/test/Shell/Unwind/signal-in-leaf-function-aarch64.test deleted file mode 100644 index 0580d0cf734a..000000000000 --- a/lldb/test/Shell/Unwind/signal-in-leaf-function-aarch64.test +++ /dev/null @@ -1,24 +0,0 @@ -# REQUIRES: target-aarch64 && native -# UNSUPPORTED: system-windows - -# RUN: %clang_host %S/Inputs/signal-in-leaf-function-aarch64.c -o %t -# RUN: %lldb -s %s -o exit %t | FileCheck %s - -breakpoint set -n sigill_handler -# CHECK: Breakpoint 1: where = {{.*}}`sigill_handler - -run -# CHECK: thread #1, {{.*}} stop reason = signal SIGILL - -thread backtrace -# CHECK: frame #0: [[ADD:0x[0-9a-fA-F]*]] {{.*}}`signal_generating_add -# CHECK: frame #1: [[MAIN:0x[0-9a-fA-F]*]] {{.*}}`main - -continue -# CHECK: thread #1, {{.*}} stop reason = breakpoint 1 - -thread backtrace -# CHECK: frame #0: {{.*}}`sigill_handler -# Unknown number of signal trampoline frames -# CHECK: frame #{{[0-9]+}}: [[ADD]] {{.*}}`signal_generating_add -# CHECK: frame #{{[0-9]+}}: [[MAIN]] {{.*}}`main diff --git a/lldb/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp b/lldb/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp index 9303d6f5f3c6..80abeb8fae9e 100644 --- a/lldb/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp +++ b/lldb/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp @@ -77,7 +77,7 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) { // UnwindPlan we expect: - // row[0]: 0: CFA=sp +0 => fp= lr= + // row[0]: 0: CFA=sp +0 => // row[1]: 4: CFA=sp+16 => fp=[CFA-16] lr=[CFA-8] // row[2]: 8: CFA=fp+16 => fp=[CFA-16] lr=[CFA-8] // row[2]: 16: CFA=sp+16 => fp=[CFA-16] lr=[CFA-8] @@ -88,19 +88,13 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) { EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( sample_range, data, sizeof(data), unwind_plan)); - // CFA=sp +0 => fp= lr= + // CFA=sp +0 row_sp = unwind_plan.GetRowForFunctionOffset(0); EXPECT_EQ(0ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); - EXPECT_TRUE(regloc.IsSame()); - - EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); - EXPECT_TRUE(regloc.IsSame()); - // CFA=sp+16 => fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); @@ -152,12 +146,6 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) { EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); - - EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); - EXPECT_TRUE(regloc.IsSame()); - - EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); - EXPECT_TRUE(regloc.IsSame()); } TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) { @@ -393,12 +381,8 @@ TEST_F(TestArm64InstEmulation, TestFramelessThreeEpilogueFunction) { EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x26_arm64, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x27_arm64, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x28_arm64, regloc)); - - EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); - EXPECT_TRUE(regloc.IsSame()); - - EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); - EXPECT_TRUE(regloc.IsSame()); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); row_sp = unwind_plan.GetRowForFunctionOffset(36); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); -- GitLab From 99934daa9b795278b8cc168fad430e09473b4992 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 13 May 2024 19:12:05 +0800 Subject: [PATCH 040/578] [ADT] Introduce `APInt::clearHighBits` (#91938) This patch addresses https://github.com/llvm/llvm-project/pull/90034#discussion_r1579235844. --- llvm/include/llvm/ADT/APInt.h | 7 ++++ llvm/unittests/ADT/APIntTest.cpp | 65 ++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index 8d3c029b2e7e..2fd8b7ea636c 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -1398,6 +1398,13 @@ public: *this &= Keep; } + /// Set top hiBits bits to 0. + void clearHighBits(unsigned hiBits) { + assert(hiBits <= BitWidth && "More bits than bitwidth"); + APInt Keep = getLowBitsSet(BitWidth, BitWidth - hiBits); + *this &= Keep; + } + /// Set the sign bit to 0. void clearSignBit() { clearBit(BitWidth - 1); } diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp index 46aaa47ee645..eb4b847185f5 100644 --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -2534,6 +2534,71 @@ TEST(APIntTest, clearLowBits) { EXPECT_EQ(16u, i32hi16.popcount()); } +TEST(APIntTest, clearHighBits) { + APInt i64hi32 = APInt::getAllOnes(64); + i64hi32.clearHighBits(32); + EXPECT_EQ(32u, i64hi32.countr_one()); + EXPECT_EQ(0u, i64hi32.countr_zero()); + EXPECT_EQ(32u, i64hi32.getActiveBits()); + EXPECT_EQ(32u, i64hi32.countl_zero()); + EXPECT_EQ(0u, i64hi32.countl_one()); + EXPECT_EQ(32u, i64hi32.popcount()); + + APInt i128hi64 = APInt::getAllOnes(128); + i128hi64.clearHighBits(64); + EXPECT_EQ(64u, i128hi64.countr_one()); + EXPECT_EQ(0u, i128hi64.countr_zero()); + EXPECT_EQ(64u, i128hi64.getActiveBits()); + EXPECT_EQ(64u, i128hi64.countl_zero()); + EXPECT_EQ(0u, i128hi64.countl_one()); + EXPECT_EQ(64u, i128hi64.popcount()); + + APInt i128hi24 = APInt::getAllOnes(128); + i128hi24.clearHighBits(104); + EXPECT_EQ(24u, i128hi24.countr_one()); + EXPECT_EQ(0u, i128hi24.countr_zero()); + EXPECT_EQ(24u, i128hi24.getActiveBits()); + EXPECT_EQ(104u, i128hi24.countl_zero()); + EXPECT_EQ(0u, i128hi24.countl_one()); + EXPECT_EQ(24u, i128hi24.popcount()); + + APInt i128hi104 = APInt::getAllOnes(128); + i128hi104.clearHighBits(24); + EXPECT_EQ(104u, i128hi104.countr_one()); + EXPECT_EQ(0u, i128hi104.countr_zero()); + EXPECT_EQ(104u, i128hi104.getActiveBits()); + EXPECT_EQ(24u, i128hi104.countl_zero()); + EXPECT_EQ(0u, i128hi104.countl_one()); + EXPECT_EQ(104u, i128hi104.popcount()); + + APInt i128hi0 = APInt::getAllOnes(128); + i128hi0.clearHighBits(128); + EXPECT_EQ(0u, i128hi0.countr_one()); + EXPECT_EQ(128u, i128hi0.countr_zero()); + EXPECT_EQ(0u, i128hi0.getActiveBits()); + EXPECT_EQ(128u, i128hi0.countl_zero()); + EXPECT_EQ(0u, i128hi0.countl_one()); + EXPECT_EQ(0u, i128hi0.popcount()); + + APInt i80hi1 = APInt::getAllOnes(80); + i80hi1.clearHighBits(79); + EXPECT_EQ(1u, i80hi1.countr_one()); + EXPECT_EQ(0u, i80hi1.countr_zero()); + EXPECT_EQ(1u, i80hi1.getActiveBits()); + EXPECT_EQ(79u, i80hi1.countl_zero()); + EXPECT_EQ(0u, i80hi1.countl_one()); + EXPECT_EQ(1u, i80hi1.popcount()); + + APInt i32hi16 = APInt::getAllOnes(32); + i32hi16.clearHighBits(16); + EXPECT_EQ(16u, i32hi16.countr_one()); + EXPECT_EQ(0u, i32hi16.countr_zero()); + EXPECT_EQ(16u, i32hi16.getActiveBits()); + EXPECT_EQ(16u, i32hi16.countl_zero()); + EXPECT_EQ(0u, i32hi16.countl_one()); + EXPECT_EQ(16u, i32hi16.popcount()); +} + TEST(APIntTest, abds) { using APIntOps::abds; -- GitLab From efe91cf78bccda90637c817e3e592b5f34e891d0 Mon Sep 17 00:00:00 2001 From: Rajveer Singh Bharadwaj Date: Mon, 13 May 2024 17:13:35 +0530 Subject: [PATCH 041/578] [clang][analyzer] Check for label location bindings in `DereferenceChecker` (#91119) Resolves #89264 Values should not be stored in addresses of labels, this throws a fatal error when this happens. --------- Co-authored-by: Balazs Benics --- .../Checkers/DereferenceChecker.cpp | 15 ++++++++++++++- .../StaticAnalyzer/Core/BugReporterVisitors.cpp | 3 +++ clang/test/Analysis/gh-issue-89185.c | 15 +++++++-------- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp index 1cebfbbee77d..0355eede75ea 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -31,11 +31,13 @@ class DereferenceChecker : public Checker< check::Location, check::Bind, EventDispatcher > { - enum DerefKind { NullPointer, UndefinedPointerValue }; + enum DerefKind { NullPointer, UndefinedPointerValue, AddressOfLabel }; BugType BT_Null{this, "Dereference of null pointer", categories::LogicError}; BugType BT_Undef{this, "Dereference of undefined pointer value", categories::LogicError}; + BugType BT_Label{this, "Dereference of the address of a label", + categories::LogicError}; void reportBug(DerefKind K, ProgramStateRef State, const Stmt *S, CheckerContext &C) const; @@ -167,6 +169,11 @@ void DereferenceChecker::reportBug(DerefKind K, ProgramStateRef State, DerefStr1 = " results in an undefined pointer dereference"; DerefStr2 = " results in a dereference of an undefined pointer value"; break; + case DerefKind::AddressOfLabel: + BT = &BT_Label; + DerefStr1 = " results in an undefined pointer dereference"; + DerefStr2 = " results in a dereference of an address of a label"; + break; }; // Generate an error node. @@ -287,6 +294,12 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S, if (V.isUndef()) return; + // One should never write to label addresses. + if (auto Label = L.getAs()) { + reportBug(DerefKind::AddressOfLabel, C.getState(), S, C); + return; + } + const MemRegion *MR = L.getAsRegion(); const TypedValueRegion *TVR = dyn_cast_or_null(MR); if (!TVR) diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 984755fa7e50..487a3bd16b67 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -113,6 +113,9 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) { // Pointer arithmetic: '*(x + 2)' -> 'x') etc. if (const Expr *Inner = peelOffPointerArithmetic(B)) { E = Inner; + } else if (B->isAssignmentOp()) { + // Follow LHS of assignments: '*p = 404' -> 'p'. + E = B->getLHS(); } else { // Probably more arithmetic can be pattern-matched here, // but for now give up. diff --git a/clang/test/Analysis/gh-issue-89185.c b/clang/test/Analysis/gh-issue-89185.c index 8a907f198a5f..49526d2daa86 100644 --- a/clang/test/Analysis/gh-issue-89185.c +++ b/clang/test/Analysis/gh-issue-89185.c @@ -1,14 +1,13 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-output text -verify %s -void clang_analyzer_dump(char); -void clang_analyzer_dump_ptr(char*); +void clang_analyzer_warnIfReached(void); // https://github.com/llvm/llvm-project/issues/89185 void binding_to_label_loc() { - char *b = &&MyLabel; + char *b = &&MyLabel; // expected-note {{'b' initialized here}} MyLabel: - *b = 0; // no-crash - clang_analyzer_dump_ptr(b); // expected-warning {{&&MyLabel}} - clang_analyzer_dump(*b); // expected-warning {{Unknown}} - // FIXME: We should never reach here, as storing to a label is invalid. + *b = 0; + // expected-warning@-1 {{Dereference of the address of a label}} + // expected-note@-2 {{Dereference of the address of a label}} + clang_analyzer_warnIfReached(); // no-warning: Unreachable due to fatal error. } -- GitLab From 345f57df16af7e4fac3a321035e504b5d49206f4 Mon Sep 17 00:00:00 2001 From: Ivan Butygin Date: Mon, 13 May 2024 14:47:37 +0300 Subject: [PATCH 042/578] [mlir][arith] Overflow flags propagation in arith canonicalizations. (#91646) --- .../Dialect/Arith/IR/ArithCanonicalization.td | 35 +++--- mlir/lib/Dialect/Arith/IR/ArithOps.cpp | 8 ++ mlir/test/Dialect/Arith/canonicalize.mlir | 119 ++++++++++++++++++ 3 files changed, 145 insertions(+), 17 deletions(-) diff --git a/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td b/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td index 02d05780a7ac..6d7ac2be951d 100644 --- a/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td +++ b/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td @@ -24,10 +24,10 @@ def SubIntAttrs : NativeCodeCall<"subIntegerAttrs($_builder, $0, $1, $2)">; // Multiply two integer attributes and create a new one with the result. def MulIntAttrs : NativeCodeCall<"mulIntegerAttrs($_builder, $0, $1, $2)">; -// TODO: Canonicalizations currently doesn't take into account integer overflow -// flags and always reset them to default (wraparound) which is safe but can -// inhibit later optimizations. Individual patterns must be reviewed for -// better handling of overflow flags. +// Merge overflow flags from 2 ops, selecting the most conservative combination. +def MergeOverflow : NativeCodeCall<"mergeOverflowFlags($0, $1)">; + +// Default overflow flag (all wraparounds allowed). defvar DefOverflow = ConstantEnumCase; class cast : NativeCodeCall<"::mlir::cast<" # type # ">($0)">; @@ -45,7 +45,7 @@ def AddIAddConstant : (Arith_AddIOp $x, (ConstantLikeMatcher APIntAttr:$c0), $ovf1), (ConstantLikeMatcher APIntAttr:$c1), $ovf2), (Arith_AddIOp $x, (Arith_ConstantOp (AddIntAttrs $res, $c0, $c1)), - DefOverflow)>; + (MergeOverflow $ovf1, $ovf2))>; // addi(subi(x, c0), c1) -> addi(x, c1 - c0) def AddISubConstantRHS : @@ -53,7 +53,7 @@ def AddISubConstantRHS : (Arith_SubIOp $x, (ConstantLikeMatcher APIntAttr:$c0), $ovf1), (ConstantLikeMatcher APIntAttr:$c1), $ovf2), (Arith_AddIOp $x, (Arith_ConstantOp (SubIntAttrs $res, $c1, $c0)), - DefOverflow)>; + (MergeOverflow $ovf1, $ovf2))>; // addi(subi(c0, x), c1) -> subi(c0 + c1, x) def AddISubConstantLHS : @@ -61,7 +61,7 @@ def AddISubConstantLHS : (Arith_SubIOp (ConstantLikeMatcher APIntAttr:$c0), $x, $ovf1), (ConstantLikeMatcher APIntAttr:$c1), $ovf2), (Arith_SubIOp (Arith_ConstantOp (AddIntAttrs $res, $c0, $c1)), $x, - DefOverflow)>; + (MergeOverflow $ovf1, $ovf2))>; def IsScalarOrSplatNegativeOne : Constraint; // addi(muli(x, -1), y) -> subi(y, x) @@ -81,7 +81,7 @@ def AddIMulNegativeOneLhs : Pat<(Arith_AddIOp (Arith_MulIOp $x, (ConstantLikeMatcher AnyAttr:$c0), $ovf1), $y, $ovf2), - (Arith_SubIOp $y, $x, DefOverflow), + (Arith_SubIOp $y, $x, DefOverflow), // TODO: overflow flags [(IsScalarOrSplatNegativeOne $c0)]>; // muli(muli(x, c0), c1) -> muli(x, c0 * c1) @@ -90,7 +90,7 @@ def MulIMulIConstant : (Arith_MulIOp $x, (ConstantLikeMatcher APIntAttr:$c0), $ovf1), (ConstantLikeMatcher APIntAttr:$c1), $ovf2), (Arith_MulIOp $x, (Arith_ConstantOp (MulIntAttrs $res, $c0, $c1)), - DefOverflow)>; + (MergeOverflow $ovf1, $ovf2))>; //===----------------------------------------------------------------------===// // AddUIExtendedOp @@ -113,7 +113,7 @@ def SubIRHSAddConstant : (Arith_AddIOp $x, (ConstantLikeMatcher APIntAttr:$c0), $ovf1), (ConstantLikeMatcher APIntAttr:$c1), $ovf2), (Arith_AddIOp $x, (Arith_ConstantOp (SubIntAttrs $res, $c0, $c1)), - DefOverflow)>; + DefOverflow)>; // TODO: overflow flags // subi(c1, addi(x, c0)) -> subi(c1 - c0, x) def SubILHSAddConstant : @@ -121,7 +121,7 @@ def SubILHSAddConstant : (ConstantLikeMatcher APIntAttr:$c1), (Arith_AddIOp $x, (ConstantLikeMatcher APIntAttr:$c0), $ovf1), $ovf2), (Arith_SubIOp (Arith_ConstantOp (SubIntAttrs $res, $c1, $c0)), $x, - DefOverflow)>; + (MergeOverflow $ovf1, $ovf2))>; // subi(subi(x, c0), c1) -> subi(x, c0 + c1) def SubIRHSSubConstantRHS : @@ -129,7 +129,7 @@ def SubIRHSSubConstantRHS : (Arith_SubIOp $x, (ConstantLikeMatcher APIntAttr:$c0), $ovf1), (ConstantLikeMatcher APIntAttr:$c1), $ovf2), (Arith_SubIOp $x, (Arith_ConstantOp (AddIntAttrs $res, $c0, $c1)), - DefOverflow)>; + (MergeOverflow $ovf1, $ovf2))>; // subi(subi(c0, x), c1) -> subi(c0 - c1, x) def SubIRHSSubConstantLHS : @@ -137,7 +137,7 @@ def SubIRHSSubConstantLHS : (Arith_SubIOp (ConstantLikeMatcher APIntAttr:$c0), $x, $ovf1), (ConstantLikeMatcher APIntAttr:$c1), $ovf2), (Arith_SubIOp (Arith_ConstantOp (SubIntAttrs $res, $c0, $c1)), $x, - DefOverflow)>; + (MergeOverflow $ovf1, $ovf2))>; // subi(c1, subi(x, c0)) -> subi(c0 + c1, x) def SubILHSSubConstantRHS : @@ -145,7 +145,7 @@ def SubILHSSubConstantRHS : (ConstantLikeMatcher APIntAttr:$c1), (Arith_SubIOp $x, (ConstantLikeMatcher APIntAttr:$c0), $ovf1), $ovf2), (Arith_SubIOp (Arith_ConstantOp (AddIntAttrs $res, $c0, $c1)), $x, - DefOverflow)>; + (MergeOverflow $ovf1, $ovf2))>; // subi(c1, subi(c0, x)) -> addi(x, c1 - c0) def SubILHSSubConstantLHS : @@ -153,12 +153,13 @@ def SubILHSSubConstantLHS : (ConstantLikeMatcher APIntAttr:$c1), (Arith_SubIOp (ConstantLikeMatcher APIntAttr:$c0), $x, $ovf1), $ovf2), (Arith_AddIOp $x, (Arith_ConstantOp (SubIntAttrs $res, $c1, $c0)), - DefOverflow)>; + (MergeOverflow $ovf1, $ovf2))>; // subi(subi(a, b), a) -> subi(0, b) def SubISubILHSRHSLHS : Pat<(Arith_SubIOp:$res (Arith_SubIOp $x, $y, $ovf1), $x, $ovf2), - (Arith_SubIOp (Arith_ConstantOp (GetZeroAttr $y)), $y, DefOverflow)>; + (Arith_SubIOp (Arith_ConstantOp (GetZeroAttr $y)), $y, + (MergeOverflow $ovf1, $ovf2))>; //===----------------------------------------------------------------------===// // MulSIExtendedOp diff --git a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp index a1568d0ebba3..a0b50251c6b6 100644 --- a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp +++ b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp @@ -64,6 +64,14 @@ static IntegerAttr mulIntegerAttrs(PatternRewriter &builder, Value res, return applyToIntegerAttrs(builder, res, lhs, rhs, std::multiplies()); } +// Merge overflow flags from 2 ops, selecting the most conservative combination. +static IntegerOverflowFlagsAttr +mergeOverflowFlags(IntegerOverflowFlagsAttr val1, + IntegerOverflowFlagsAttr val2) { + return IntegerOverflowFlagsAttr::get(val1.getContext(), + val1.getValue() & val2.getValue()); +} + /// Invert an integer comparison predicate. arith::CmpIPredicate arith::invertPredicate(arith::CmpIPredicate pred) { switch (pred) { diff --git a/mlir/test/Dialect/Arith/canonicalize.mlir b/mlir/test/Dialect/Arith/canonicalize.mlir index f7ce2123a93c..e4f95bb0545a 100644 --- a/mlir/test/Dialect/Arith/canonicalize.mlir +++ b/mlir/test/Dialect/Arith/canonicalize.mlir @@ -833,6 +833,30 @@ func.func @tripleAddAdd(%arg0: index) -> index { return %add2 : index } +// CHECK-LABEL: @tripleAddAddOvf1 +// CHECK: %[[cres:.+]] = arith.constant 59 : index +// CHECK: %[[add:.+]] = arith.addi %arg0, %[[cres]] overflow : index +// CHECK: return %[[add]] +func.func @tripleAddAddOvf1(%arg0: index) -> index { + %c17 = arith.constant 17 : index + %c42 = arith.constant 42 : index + %add1 = arith.addi %c17, %arg0 overflow : index + %add2 = arith.addi %c42, %add1 overflow : index + return %add2 : index +} + +// CHECK-LABEL: @tripleAddAddOvf2 +// CHECK: %[[cres:.+]] = arith.constant 59 : index +// CHECK: %[[add:.+]] = arith.addi %arg0, %[[cres]] : index +// CHECK: return %[[add]] +func.func @tripleAddAddOvf2(%arg0: index) -> index { + %c17 = arith.constant 17 : index + %c42 = arith.constant 42 : index + %add1 = arith.addi %c17, %arg0 overflow : index + %add2 = arith.addi %c42, %add1 overflow : index + return %add2 : index +} + // CHECK-LABEL: @tripleAddSub0 // CHECK: %[[cres:.+]] = arith.constant 59 : index // CHECK: %[[add:.+]] = arith.subi %[[cres]], %arg0 : index @@ -845,6 +869,18 @@ func.func @tripleAddSub0(%arg0: index) -> index { return %add2 : index } +// CHECK-LABEL: @tripleAddSub0Ovf +// CHECK: %[[cres:.+]] = arith.constant 59 : index +// CHECK: %[[add:.+]] = arith.subi %[[cres]], %arg0 overflow : index +// CHECK: return %[[add]] +func.func @tripleAddSub0Ovf(%arg0: index) -> index { + %c17 = arith.constant 17 : index + %c42 = arith.constant 42 : index + %add1 = arith.subi %c17, %arg0 overflow : index + %add2 = arith.addi %c42, %add1 overflow : index + return %add2 : index +} + // CHECK-LABEL: @tripleAddSub1 // CHECK: %[[cres:.+]] = arith.constant 25 : index // CHECK: %[[add:.+]] = arith.addi %arg0, %[[cres]] : index @@ -857,6 +893,18 @@ func.func @tripleAddSub1(%arg0: index) -> index { return %add2 : index } +// CHECK-LABEL: @tripleAddSub1Ovf +// CHECK: %[[cres:.+]] = arith.constant 25 : index +// CHECK: %[[add:.+]] = arith.addi %arg0, %[[cres]] overflow : index +// CHECK: return %[[add]] +func.func @tripleAddSub1Ovf(%arg0: index) -> index { + %c17 = arith.constant 17 : index + %c42 = arith.constant 42 : index + %add1 = arith.subi %arg0, %c17 overflow : index + %add2 = arith.addi %c42, %add1 overflow : index + return %add2 : index +} + // CHECK-LABEL: @tripleSubAdd0 // CHECK: %[[cres:.+]] = arith.constant 25 : index // CHECK: %[[add:.+]] = arith.subi %[[cres]], %arg0 : index @@ -869,6 +917,18 @@ func.func @tripleSubAdd0(%arg0: index) -> index { return %add2 : index } +// CHECK-LABEL: @tripleSubAdd0Ovf +// CHECK: %[[cres:.+]] = arith.constant 25 : index +// CHECK: %[[add:.+]] = arith.subi %[[cres]], %arg0 overflow : index +// CHECK: return %[[add]] +func.func @tripleSubAdd0Ovf(%arg0: index) -> index { + %c17 = arith.constant 17 : index + %c42 = arith.constant 42 : index + %add1 = arith.addi %c17, %arg0 overflow : index + %add2 = arith.subi %c42, %add1 overflow : index + return %add2 : index +} + // CHECK-LABEL: @tripleSubAdd1 // CHECK: %[[cres:.+]] = arith.constant -25 : index // CHECK: %[[add:.+]] = arith.addi %arg0, %[[cres]] : index @@ -891,6 +951,16 @@ func.func @subSub0(%arg0: index, %arg1: index) -> index { return %sub2 : index } +// CHECK-LABEL: @subSub0Ovf +// CHECK: %[[c0:.+]] = arith.constant 0 : index +// CHECK: %[[add:.+]] = arith.subi %[[c0]], %arg1 overflow : index +// CHECK: return %[[add]] +func.func @subSub0Ovf(%arg0: index, %arg1: index) -> index { + %sub1 = arith.subi %arg0, %arg1 overflow : index + %sub2 = arith.subi %sub1, %arg0 overflow : index + return %sub2 : index +} + // CHECK-LABEL: @tripleSubSub0 // CHECK: %[[cres:.+]] = arith.constant 25 : index // CHECK: %[[add:.+]] = arith.addi %arg0, %[[cres]] : index @@ -903,6 +973,19 @@ func.func @tripleSubSub0(%arg0: index) -> index { return %add2 : index } +// CHECK-LABEL: @tripleSubSub0Ovf +// CHECK: %[[cres:.+]] = arith.constant 25 : index +// CHECK: %[[add:.+]] = arith.addi %arg0, %[[cres]] overflow : index +// CHECK: return %[[add]] +func.func @tripleSubSub0Ovf(%arg0: index) -> index { + %c17 = arith.constant 17 : index + %c42 = arith.constant 42 : index + %add1 = arith.subi %c17, %arg0 overflow : index + %add2 = arith.subi %c42, %add1 overflow : index + return %add2 : index +} + + // CHECK-LABEL: @tripleSubSub1 // CHECK: %[[cres:.+]] = arith.constant -25 : index // CHECK: %[[add:.+]] = arith.subi %[[cres]], %arg0 : index @@ -915,6 +998,18 @@ func.func @tripleSubSub1(%arg0: index) -> index { return %add2 : index } +// CHECK-LABEL: @tripleSubSub1Ovf +// CHECK: %[[cres:.+]] = arith.constant -25 : index +// CHECK: %[[add:.+]] = arith.subi %[[cres]], %arg0 overflow : index +// CHECK: return %[[add]] +func.func @tripleSubSub1Ovf(%arg0: index) -> index { + %c17 = arith.constant 17 : index + %c42 = arith.constant 42 : index + %add1 = arith.subi %c17, %arg0 overflow : index + %add2 = arith.subi %add1, %c42 overflow : index + return %add2 : index +} + // CHECK-LABEL: @tripleSubSub2 // CHECK: %[[cres:.+]] = arith.constant 59 : index // CHECK: %[[add:.+]] = arith.subi %[[cres]], %arg0 : index @@ -927,6 +1022,18 @@ func.func @tripleSubSub2(%arg0: index) -> index { return %add2 : index } +// CHECK-LABEL: @tripleSubSub2Ovf +// CHECK: %[[cres:.+]] = arith.constant 59 : index +// CHECK: %[[add:.+]] = arith.subi %[[cres]], %arg0 overflow : index +// CHECK: return %[[add]] +func.func @tripleSubSub2Ovf(%arg0: index) -> index { + %c17 = arith.constant 17 : index + %c42 = arith.constant 42 : index + %add1 = arith.subi %arg0, %c17 overflow : index + %add2 = arith.subi %c42, %add1 overflow : index + return %add2 : index +} + // CHECK-LABEL: @tripleSubSub3 // CHECK: %[[cres:.+]] = arith.constant 59 : index // CHECK: %[[add:.+]] = arith.subi %arg0, %[[cres]] : index @@ -939,6 +1046,18 @@ func.func @tripleSubSub3(%arg0: index) -> index { return %add2 : index } +// CHECK-LABEL: @tripleSubSub3Ovf +// CHECK: %[[cres:.+]] = arith.constant 59 : index +// CHECK: %[[add:.+]] = arith.subi %arg0, %[[cres]] overflow : index +// CHECK: return %[[add]] +func.func @tripleSubSub3Ovf(%arg0: index) -> index { + %c17 = arith.constant 17 : index + %c42 = arith.constant 42 : index + %add1 = arith.subi %arg0, %c17 overflow : index + %add2 = arith.subi %add1, %c42 overflow : index + return %add2 : index +} + // CHECK-LABEL: @subAdd1 // CHECK-NEXT: return %arg0 func.func @subAdd1(%arg0: index, %arg1 : index) -> index { -- GitLab From c5b0da9d83971d94d3b26105b1e42d3a3826ef1e Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 13 May 2024 13:49:09 +0200 Subject: [PATCH 043/578] InstCombine: Preserve inbounds in PointerReplacer (#91735) This avoids spurious test changes in a future commit. --- .../InstCombine/InstCombineLoadStoreAlloca.cpp | 1 + .../InstCombine/AMDGPU/memcpy-from-constant.ll | 12 ++++++------ llvm/test/Transforms/InstCombine/memcpy-addrspace.ll | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index c70872c12917..344f3ec74522 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -388,6 +388,7 @@ void PointerReplacer::replace(Instruction *I) { GetElementPtrInst::Create(GEP->getSourceElementType(), V, Indices); IC.InsertNewInstWith(NewI, GEP->getIterator()); NewI->takeName(GEP); + NewI->setIsInBounds(GEP->isInBounds()); WorkMap[GEP] = NewI; } else if (auto *BC = dyn_cast(I)) { auto *V = getReplacement(BC->getOperand(0)); diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/memcpy-from-constant.ll b/llvm/test/Transforms/InstCombine/AMDGPU/memcpy-from-constant.ll index 2d0e3d2edd90..c14d61b51ad7 100644 --- a/llvm/test/Transforms/InstCombine/AMDGPU/memcpy-from-constant.ll +++ b/llvm/test/Transforms/InstCombine/AMDGPU/memcpy-from-constant.ll @@ -10,7 +10,7 @@ target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:3 define i8 @memcpy_constant_arg_ptr_to_alloca(ptr addrspace(4) noalias readonly align 4 dereferenceable(32) %arg, i32 %idx) { ; CHECK-LABEL: @memcpy_constant_arg_ptr_to_alloca( ; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64 -; CHECK-NEXT: [[GEP:%.*]] = getelementptr [32 x i8], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] ; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(4) [[GEP]], align 1 ; CHECK-NEXT: ret i8 [[LOAD]] ; @@ -24,7 +24,7 @@ define i8 @memcpy_constant_arg_ptr_to_alloca(ptr addrspace(4) noalias readonly a define i8 @memcpy_constant_arg_ptr_to_alloca_load_metadata(ptr addrspace(4) noalias readonly align 4 dereferenceable(32) %arg, i32 %idx) { ; CHECK-LABEL: @memcpy_constant_arg_ptr_to_alloca_load_metadata( ; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64 -; CHECK-NEXT: [[GEP:%.*]] = getelementptr [32 x i8], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] ; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(4) [[GEP]], align 1, !noalias [[META0:![0-9]+]] ; CHECK-NEXT: ret i8 [[LOAD]] ; @@ -38,7 +38,7 @@ define i8 @memcpy_constant_arg_ptr_to_alloca_load_metadata(ptr addrspace(4) noal define i64 @memcpy_constant_arg_ptr_to_alloca_load_alignment(ptr addrspace(4) noalias readonly align 4 dereferenceable(256) %arg, i32 %idx) { ; CHECK-LABEL: @memcpy_constant_arg_ptr_to_alloca_load_alignment( ; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64 -; CHECK-NEXT: [[GEP:%.*]] = getelementptr [32 x i64], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [32 x i64], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] ; CHECK-NEXT: [[LOAD:%.*]] = load i64, ptr addrspace(4) [[GEP]], align 16 ; CHECK-NEXT: ret i64 [[LOAD]] ; @@ -68,7 +68,7 @@ define i64 @memcpy_constant_arg_ptr_to_alloca_load_atomic(ptr addrspace(4) noali define i8 @memmove_constant_arg_ptr_to_alloca(ptr addrspace(4) noalias readonly align 4 dereferenceable(32) %arg, i32 %idx) { ; CHECK-LABEL: @memmove_constant_arg_ptr_to_alloca( ; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64 -; CHECK-NEXT: [[GEP:%.*]] = getelementptr [32 x i8], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] ; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(4) [[GEP]], align 1 ; CHECK-NEXT: ret i8 [[LOAD]] ; @@ -83,7 +83,7 @@ define i8 @memmove_constant_arg_ptr_to_alloca(ptr addrspace(4) noalias readonly define amdgpu_kernel void @memcpy_constant_byref_arg_ptr_to_alloca(ptr addrspace(4) noalias readonly align 4 byref([32 x i8]) %arg, ptr addrspace(1) %out, i32 %idx) { ; CHECK-LABEL: @memcpy_constant_byref_arg_ptr_to_alloca( ; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64 -; CHECK-NEXT: [[GEP:%.*]] = getelementptr [32 x i8], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] ; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(4) [[GEP]], align 1 ; CHECK-NEXT: store i8 [[LOAD]], ptr addrspace(1) [[OUT:%.*]], align 1 ; CHECK-NEXT: ret void @@ -138,7 +138,7 @@ define amdgpu_kernel void @memcpy_constant_intrinsic_ptr_to_alloca(ptr addrspace define i8 @memcpy_constant_arg_ptr_to_alloca_addrspacecast_to_flat(ptr addrspace(4) noalias readonly align 4 dereferenceable(32) %arg, i32 %idx) { ; CHECK-LABEL: @memcpy_constant_arg_ptr_to_alloca_addrspacecast_to_flat( ; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64 -; CHECK-NEXT: [[GEP:%.*]] = getelementptr [32 x i8], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(4) [[ARG:%.*]], i64 0, i64 [[TMP1]] ; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(4) [[GEP]], align 1 ; CHECK-NEXT: ret i8 [[LOAD]] ; diff --git a/llvm/test/Transforms/InstCombine/memcpy-addrspace.ll b/llvm/test/Transforms/InstCombine/memcpy-addrspace.ll index d1543696bfc0..2ec3994f30fc 100644 --- a/llvm/test/Transforms/InstCombine/memcpy-addrspace.ll +++ b/llvm/test/Transforms/InstCombine/memcpy-addrspace.ll @@ -6,7 +6,7 @@ define void @test_load(ptr addrspace(1) %out, i64 %x) { ; CHECK-LABEL: @test_load( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr [8 x i32], ptr addrspace(2) @test.data, i64 0, i64 [[X:%.*]] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i32], ptr addrspace(2) @test.data, i64 0, i64 [[X:%.*]] ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(2) [[ARRAYIDX]], align 4 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]] ; CHECK-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4 @@ -25,7 +25,7 @@ entry: define void @test_load_bitcast_chain(ptr addrspace(1) %out, i64 %x) { ; CHECK-LABEL: @test_load_bitcast_chain( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr addrspace(2) @test.data, i64 [[X:%.*]] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr addrspace(2) @test.data, i64 [[X:%.*]] ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(2) [[ARRAYIDX]], align 4 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]] ; CHECK-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4 -- GitLab From 91d7ca904c601d181c431bffbf2773165de2fabd Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Mon, 13 May 2024 12:49:42 +0100 Subject: [PATCH 044/578] [DebugInfo] Remap extracted DIAssignIDs in hotcoldsplit (#91940) Fix #91814 When instructions are extracted into a new function the `DIAssignID` metadata uses and attachments need to be remapped so that the stores and assignment markers don't link to stores and assignment markers in the original function. This matches existing inlining behaviour for DIAssignIDs. --- llvm/include/llvm/IR/DebugInfo.h | 4 ++ llvm/lib/IR/DebugInfo.cpp | 24 +++++++++ llvm/lib/Transforms/Utils/CodeExtractor.cpp | 6 ++- llvm/lib/Transforms/Utils/InlineFunction.cpp | 21 +------- .../assignment-tracking/X86/hotcoldsplit.ll | 50 +++++++++++++++++++ 5 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 llvm/test/DebugInfo/assignment-tracking/X86/hotcoldsplit.ll diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h index 53cede5409e2..5b80218d6c5c 100644 --- a/llvm/include/llvm/IR/DebugInfo.h +++ b/llvm/include/llvm/IR/DebugInfo.h @@ -268,6 +268,10 @@ bool calculateFragmentIntersect( uint64_t SliceSizeInBits, const DbgVariableRecord *DVRAssign, std::optional &Result); +/// Replace DIAssignID uses and attachments with IDs from \p Map. +/// If an ID is unmapped a new ID is generated and added to \p Map. +void remapAssignID(DenseMap &Map, Instruction &I); + /// Helper struct for trackAssignments, below. We don't use the similar /// DebugVariable class because trackAssignments doesn't (yet?) understand /// partial variables (fragment info) as input and want to make that clear and diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 7976904b1fe9..4c3f37ceaaa4 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -2130,6 +2130,30 @@ bool at::calculateFragmentIntersect( SliceSizeInBits, DVRAssign, Result); } +/// Update inlined instructions' DIAssignID metadata. We need to do this +/// otherwise a function inlined more than once into the same function +/// will cause DIAssignID to be shared by many instructions. +void at::remapAssignID(DenseMap &Map, + Instruction &I) { + auto GetNewID = [&Map](Metadata *Old) { + DIAssignID *OldID = cast(Old); + if (DIAssignID *NewID = Map.lookup(OldID)) + return NewID; + DIAssignID *NewID = DIAssignID::getDistinct(OldID->getContext()); + Map[OldID] = NewID; + return NewID; + }; + // If we find a DIAssignID attachment or use, replace it with a new version. + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + if (DVR.isDbgAssign()) + DVR.setAssignId(GetNewID(DVR.getAssignID())); + } + if (auto *ID = I.getMetadata(LLVMContext::MD_DIAssignID)) + I.setMetadata(LLVMContext::MD_DIAssignID, GetNewID(ID)); + else if (auto *DAI = dyn_cast(&I)) + DAI->setAssignId(GetNewID(DAI->getAssignID())); +} + /// Collect constant properies (base, size, offset) of \p StoreDest. /// Return std::nullopt if any properties are not constants or the /// offset from the base pointer is negative. diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 6988292ac715..f2672b8e9118 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -1678,8 +1678,9 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc, DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR); DIB.finalizeSubprogram(NewSP); - // Fix up the scope information attached to the line locations in the new - // function. + // Fix up the scope information attached to the line locations and the + // debug assignment metadata in the new function. + DenseMap AssignmentIDMap; for (Instruction &I : instructions(NewFunc)) { if (const DebugLoc &DL = I.getDebugLoc()) I.setDebugLoc( @@ -1695,6 +1696,7 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc, return MD; }; updateLoopMetadataDebugLocations(I, updateLoopInfoLoc); + at::remapAssignID(AssignmentIDMap, I); } if (!TheCall.getDebugLoc()) TheCall.setDebugLoc(DILocation::get(Ctx, 0, 0, OldSP)); diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index 48bb76eb85e3..82daaedaa0e8 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1888,29 +1888,12 @@ static void trackInlinedStores(Function::iterator Start, Function::iterator End, /// otherwise a function inlined more than once into the same function /// will cause DIAssignID to be shared by many instructions. static void fixupAssignments(Function::iterator Start, Function::iterator End) { - // Map {Old, New} metadata. Not used directly - use GetNewID. DenseMap Map; - auto GetNewID = [&Map](Metadata *Old) { - DIAssignID *OldID = cast(Old); - if (DIAssignID *NewID = Map.lookup(OldID)) - return NewID; - DIAssignID *NewID = DIAssignID::getDistinct(OldID->getContext()); - Map[OldID] = NewID; - return NewID; - }; // Loop over all the inlined instructions. If we find a DIAssignID // attachment or use, replace it with a new version. for (auto BBI = Start; BBI != End; ++BBI) { - for (Instruction &I : *BBI) { - for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { - if (DVR.isDbgAssign()) - DVR.setAssignId(GetNewID(DVR.getAssignID())); - } - if (auto *ID = I.getMetadata(LLVMContext::MD_DIAssignID)) - I.setMetadata(LLVMContext::MD_DIAssignID, GetNewID(ID)); - else if (auto *DAI = dyn_cast(&I)) - DAI->setAssignId(GetNewID(DAI->getAssignID())); - } + for (Instruction &I : *BBI) + at::remapAssignID(Map, I); } } #undef DEBUG_TYPE diff --git a/llvm/test/DebugInfo/assignment-tracking/X86/hotcoldsplit.ll b/llvm/test/DebugInfo/assignment-tracking/X86/hotcoldsplit.ll new file mode 100644 index 000000000000..f3faba7122af --- /dev/null +++ b/llvm/test/DebugInfo/assignment-tracking/X86/hotcoldsplit.ll @@ -0,0 +1,50 @@ +; RUN: opt %s -passes=hotcoldsplit -S | FileCheck %s + +;; Check the extracted DIAssignID gets remapped. + +; CHECK-LABEL: define void @_foo() +; CHECK: common.ret: +; CHECK-NEXT: dbg.assign(metadata i64 0, metadata ![[#]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64), metadata ![[ID1:[0-9]+]], {{.*}}, metadata !DIExpression()) + +; CHECK-LABEL: define internal void @_foo.cold.1() +; CHECK: store i64 0, ptr null, align 8, !DIAssignID ![[ID2:[0-9]+]] + +; CHECK-DAG: ![[ID1]] = distinct !DIAssignID() +; CHECK-DAG: ![[ID2]] = distinct !DIAssignID() + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @_foo() !dbg !4 { +entry: + br i1 false, label %if.then7, label %common.ret + +common.ret: ; preds = %entry + call void @llvm.dbg.assign(metadata i64 0, metadata !7, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64), metadata !12, metadata ptr null, metadata !DIExpression()), !dbg !13 + ret void + +if.then7: ; preds = %entry + %call21 = load i1, ptr null, align 4294967296 + store i64 0, ptr null, align 8, !DIAssignID !12 + unreachable +} + +declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "file.cpp", directory: "foo") +!2 = !{} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = distinct !DISubprogram(name: "foo", linkageName: "_foo", scope: !5, file: !1, line: 425, type: !6, scopeLine: 425, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!5 = !DINamespace(name: "llvm", scope: null) +!6 = distinct !DISubroutineType(types: !2) +!7 = !DILocalVariable(name: "Path", scope: !4, file: !1, line: 436, type: !8) +!8 = !DIDerivedType(tag: DW_TAG_typedef, name: "string", scope: !9, file: !1, line: 79, baseType: !10) +!9 = !DINamespace(name: "std", scope: null) +!10 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "basic_string, std::allocator >", scope: !11, file: !1, line: 85, size: 256, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !2, templateParams: !2, identifier: "_ZTSNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE") +!11 = !DINamespace(name: "__cxx11", scope: !9, exportSymbols: true) +!12 = distinct !DIAssignID() +!13 = !DILocation(line: 0, scope: !4) -- GitLab From 32939a16bcb084c2572f201ee42613413784cf7e Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Mon, 13 May 2024 06:51:12 -0500 Subject: [PATCH 045/578] [Offload][NFC] Remove unused compiler definition from CMake --- offload/src/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/offload/src/CMakeLists.txt b/offload/src/CMakeLists.txt index 8fe6d19d83eb..b474f29ea0be 100644 --- a/offload/src/CMakeLists.txt +++ b/offload/src/CMakeLists.txt @@ -72,11 +72,6 @@ endforeach() target_compile_options(omptarget PUBLIC ${offload_compile_flags}) target_link_options(omptarget PUBLIC ${offload_link_flags}) -list(TRANSFORM LIBOMPTARGET_PLUGINS_TO_LOAD PREPEND "\"libomptarget.rtl.") -list(TRANSFORM LIBOMPTARGET_PLUGINS_TO_LOAD APPEND "\"") -list(JOIN LIBOMPTARGET_PLUGINS_TO_LOAD "," ENABLED_OFFLOAD_PLUGINS) -target_compile_definitions(omptarget PRIVATE ENABLED_OFFLOAD_PLUGINS=${ENABLED_OFFLOAD_PLUGINS}) - # libomptarget.so needs to be aware of where the plugins live as they # are now separated in the build directory. set_target_properties(omptarget PROPERTIES -- GitLab From bc17361c2baa0351f7f19b716fbe76bc9f99e903 Mon Sep 17 00:00:00 2001 From: Muhammad Omair Javaid Date: Mon, 13 May 2024 16:50:19 +0500 Subject: [PATCH 046/578] [lldb][DWARF] Fix delayed-definition-die-searching.test for Windows This is follow up fix on top of 9a7262c2601874e5aa64c5db19746770212d4b44 This fixes delayed-definition-die-searching.test to use -gdwarf. This is required to explicitly select DWARF instead of PDB on windows. Fixe LLDB build lldb-aarch64-windows: https://lab.llvm.org/buildbot/#/builders/219/builds/11303 --- .../SymbolFile/DWARF/delayed-definition-die-searching.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test index a2b36dadedd2..836fcd7b587b 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test +++ b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test @@ -1,7 +1,7 @@ # Test definition DIE searching is delayed until complete type is required. # RUN: split-file %s %t -# RUN: %clangxx_host %t/main.cpp %t/t1_def.cpp -g -o %t.out +# RUN: %clangxx_host %t/main.cpp %t/t1_def.cpp -gdwarf -o %t.out # RUN: %lldb -b %t.out -s %t/lldb.cmd | FileCheck %s # CHECK: (lldb) p v1 @@ -31,4 +31,4 @@ int main() { struct t1 { // this CU contains definition DIE for t1. int x; }; -t1 v2; \ No newline at end of file +t1 v2; -- GitLab From 710d95d1ecb4b6d69507cb910274ef3077ddc9c9 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Mon, 13 May 2024 15:55:20 +0400 Subject: [PATCH 047/578] [lldb] Fixed the test TestSettings when run with a remote target (#91915) The setting `platform.module-cache-directory` is a local path on the host. It cannot be set to a working directory from the remote target. This test failed in case of Windows host and Linux target because of the incompatible path. Use the local build dir instead. --- lldb/test/API/commands/settings/TestSettings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/test/API/commands/settings/TestSettings.py b/lldb/test/API/commands/settings/TestSettings.py index 104a9f09788c..385acceb7a8b 100644 --- a/lldb/test/API/commands/settings/TestSettings.py +++ b/lldb/test/API/commands/settings/TestSettings.py @@ -953,7 +953,7 @@ class SettingsCommandTestCase(TestBase): # Test OptionValueFileSpec self.verify_setting_value_json( - "platform.module-cache-directory", self.get_process_working_directory() + "platform.module-cache-directory", self.getBuildDir() ) # Test OptionValueArray -- GitLab From 7ce3dd49eb80816e3af52022ba2521b28a068c7b Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Mon, 13 May 2024 15:58:39 +0400 Subject: [PATCH 048/578] [lldb] Fixed the test TestQuoting (#91886) os.path.join() uses the path separator of the host OS by default. outfile_arg will be incorrect in case of Windows host and Linux target. Use lldbutil.append_to_process_working_directory() instead. --- lldb/test/API/commands/settings/quoting/TestQuoting.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lldb/test/API/commands/settings/quoting/TestQuoting.py b/lldb/test/API/commands/settings/quoting/TestQuoting.py index 393f4be3c824..60eeeead4e0a 100644 --- a/lldb/test/API/commands/settings/quoting/TestQuoting.py +++ b/lldb/test/API/commands/settings/quoting/TestQuoting.py @@ -51,9 +51,7 @@ class SettingsCommandTestCase(TestBase): outfile = self.getBuildArtifact(filename) if lldb.remote_platform: - outfile_arg = os.path.join( - lldb.remote_platform.GetWorkingDirectory(), filename - ) + outfile_arg = lldbutil.append_to_process_working_directory(self, filename) else: outfile_arg = outfile -- GitLab From 4ff45eee36f003cda18a3654df4086e69dc245b5 Mon Sep 17 00:00:00 2001 From: Pierre van Houtryve Date: Mon, 13 May 2024 13:59:24 +0200 Subject: [PATCH 049/578] [GlobalISel][KnownBits] Simplify G_CONSTANT handling (#91946) We called getIConstantVRegVal which again queried MRI to get the VReg def. We already have the def, so just get the CImm directly. It can't fail. --- llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp index c8199a42d15c..32d607cfd71a 100644 --- a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp @@ -256,10 +256,7 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known, break; } case TargetOpcode::G_CONSTANT: { - auto CstVal = getIConstantVRegVal(R, MRI); - if (!CstVal) - break; - Known = KnownBits::makeConstant(*CstVal); + Known = KnownBits::makeConstant(MI.getOperand(1).getCImm()->getValue()); break; } case TargetOpcode::G_FRAME_INDEX: { -- GitLab From 8823abea6fb029bf24abd501e43844e3f5b9c444 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Fri, 10 May 2024 14:45:32 +0200 Subject: [PATCH 050/578] InstCombine: Simplify vector initialization --- llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 344f3ec74522..537890d9025f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -382,8 +382,7 @@ void PointerReplacer::replace(Instruction *I) { } else if (auto *GEP = dyn_cast(I)) { auto *V = getReplacement(GEP->getPointerOperand()); assert(V && "Operand not replaced"); - SmallVector Indices; - Indices.append(GEP->idx_begin(), GEP->idx_end()); + SmallVector Indices(GEP->indices()); auto *NewI = GetElementPtrInst::Create(GEP->getSourceElementType(), V, Indices); IC.InsertNewInstWith(NewI, GEP->getIterator()); -- GitLab From 3f0e1d4cf09b0c90abfb1d06a26cc4c85c1f9568 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 13 May 2024 13:04:22 +0100 Subject: [PATCH 051/578] [SCEV] Swap order of arguments to MatchBinaryAddToConst (NFCI). (#91945) The argument order to MatchBinaryAddToConst doesn't match the comment and also is counter-intuitive (passing RHS before LHS, C2 before C1). This patch adjusts the order to be inline with the calls above, which should be equivalent, but more natural: https://alive2.llvm.org/ce/z/ZWGp-Z PR: https://github.com/llvm/llvm-project/pull/91945 --- llvm/lib/Analysis/ScalarEvolution.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 7dc5aa084f3c..254d79183a1e 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -11274,7 +11274,7 @@ bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred, [[fallthrough]]; case ICmpInst::ICMP_ULE: // (X + C1) u<= (X + C2) for C1 u<= C2. - if (MatchBinaryAddToConst(RHS, LHS, C2, C1, SCEV::FlagNUW) && C1.ule(C2)) + if (MatchBinaryAddToConst(LHS, RHS, C1, C2, SCEV::FlagNUW) && C1.ule(C2)) return true; break; @@ -11284,7 +11284,7 @@ bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred, [[fallthrough]]; case ICmpInst::ICMP_ULT: // (X + C1) u< (X + C2) if C1 u< C2. - if (MatchBinaryAddToConst(RHS, LHS, C2, C1, SCEV::FlagNUW) && C1.ult(C2)) + if (MatchBinaryAddToConst(LHS, RHS, C1, C2, SCEV::FlagNUW) && C1.ult(C2)) return true; break; } -- GitLab From 19a62fbe00930d7eaa9f948c8dd26d58f5422c00 Mon Sep 17 00:00:00 2001 From: Oleg Shyshkov Date: Mon, 13 May 2024 14:08:25 +0200 Subject: [PATCH 052/578] [OpenMP][MLIR] Fix llvm::sort comparator. (#91947) llvm::sort requires the comparator to return `false` for equal elements, otherwise it triggers `Your comparator is not a valid strict-weak ordering` assert. --- .../LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 0c3412666732..282e640d3aaa 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -2175,10 +2175,10 @@ getFirstOrLastMappedMemberPtr(mlir::omp::MapInfoOp mapInfo, bool first) { return !first; } - // iterated the entire list and couldn't make a decision, all elements - // were likely the same, return true for now similar to reaching the end - // of both and finding invalid indices. - return true; + // Iterated the entire list and couldn't make a decision, all elements + // were likely the same. Return false, since the sort comparator should + // return false for equal elements. + return false; }); return llvm::cast( -- GitLab From 5e9401c2c21efcd55aae42d0b3d68034d344b08d Mon Sep 17 00:00:00 2001 From: Chris Warner <73851242+cwarner-8702@users.noreply.github.com> Date: Mon, 13 May 2024 05:11:39 -0700 Subject: [PATCH 053/578] [clang-query] Load queries and matchers from file during REPL cycle (#90603) The clang-query tool has the ability to execute or pre-load queries from a file when the tool is launched, but doesn't have the ability to do the same from the interactive REPL prompt. Because the prompt also doesn't seem to allow multi-line matchers, this can make prototyping and iterating on more complicated matchers difficult. Supporting a dynamic load at REPL time allows the cost of reading the compilation database and building the AST to be imposed just once, and allows faster prototyping. --- clang-tools-extra/clang-query/Query.cpp | 22 +++++++++++++++++++ clang-tools-extra/clang-query/Query.h | 18 ++++++++++++++- clang-tools-extra/clang-query/QueryParser.cpp | 10 +++++++-- .../clang-query/tool/ClangQuery.cpp | 18 ++------------- clang-tools-extra/docs/ReleaseNotes.rst | 4 +++- .../test/clang-query/Inputs/empty.script | 1 + .../test/clang-query/Inputs/file.script | 1 + .../clang-query/Inputs/runtime_file.script | 5 +++++ clang-tools-extra/test/clang-query/errors.c | 2 ++ .../test/clang-query/file-empty.c | 2 ++ .../test/clang-query/file-query.c | 14 ++++++++++++ .../unittests/clang-query/QueryParserTest.cpp | 4 +++- 12 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 clang-tools-extra/test/clang-query/Inputs/empty.script create mode 100644 clang-tools-extra/test/clang-query/Inputs/file.script create mode 100644 clang-tools-extra/test/clang-query/Inputs/runtime_file.script create mode 100644 clang-tools-extra/test/clang-query/file-empty.c create mode 100644 clang-tools-extra/test/clang-query/file-query.c diff --git a/clang-tools-extra/clang-query/Query.cpp b/clang-tools-extra/clang-query/Query.cpp index c436d6fa9498..9d5807a52fa8 100644 --- a/clang-tools-extra/clang-query/Query.cpp +++ b/clang-tools-extra/clang-query/Query.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "Query.h" +#include "QueryParser.h" #include "QuerySession.h" #include "clang/AST/ASTDumper.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -281,5 +282,26 @@ const QueryKind SetQueryKind::value; const QueryKind SetQueryKind::value; #endif +bool FileQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { + auto Buffer = llvm::MemoryBuffer::getFile(StringRef{File}.trim()); + if (!Buffer) { + if (Prefix.has_value()) + llvm::errs() << *Prefix << ": "; + llvm::errs() << "cannot open " << File << ": " + << Buffer.getError().message() << "\n"; + return false; + } + + StringRef FileContentRef(Buffer.get()->getBuffer()); + + while (!FileContentRef.empty()) { + QueryRef Q = QueryParser::parse(FileContentRef, QS); + if (!Q->run(llvm::outs(), QS)) + return false; + FileContentRef = Q->RemainingContent; + } + return true; +} + } // namespace query } // namespace clang diff --git a/clang-tools-extra/clang-query/Query.h b/clang-tools-extra/clang-query/Query.h index 7aefa6bb5ee0..7242479633c2 100644 --- a/clang-tools-extra/clang-query/Query.h +++ b/clang-tools-extra/clang-query/Query.h @@ -30,7 +30,8 @@ enum QueryKind { QK_SetTraversalKind, QK_EnableOutputKind, QK_DisableOutputKind, - QK_Quit + QK_Quit, + QK_File }; class QuerySession; @@ -188,6 +189,21 @@ struct DisableOutputQuery : SetNonExclusiveOutputQuery { } }; +struct FileQuery : Query { + FileQuery(StringRef File, StringRef Prefix = StringRef()) + : Query(QK_File), File(File), + Prefix(!Prefix.empty() ? std::optional(Prefix) + : std::nullopt) {} + + bool run(llvm::raw_ostream &OS, QuerySession &QS) const override; + + static bool classof(const Query *Q) { return Q->Kind == QK_File; } + +private: + std::string File; + std::optional Prefix; +}; + } // namespace query } // namespace clang diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp index 162acc1a598d..85a442bdd7de 100644 --- a/clang-tools-extra/clang-query/QueryParser.cpp +++ b/clang-tools-extra/clang-query/QueryParser.cpp @@ -183,7 +183,8 @@ enum ParsedQueryKind { PQK_Unlet, PQK_Quit, PQK_Enable, - PQK_Disable + PQK_Disable, + PQK_File }; enum ParsedQueryVariable { @@ -222,12 +223,14 @@ QueryRef QueryParser::doParse() { .Case("let", PQK_Let) .Case("m", PQK_Match, /*IsCompletion=*/false) .Case("match", PQK_Match) - .Case("q", PQK_Quit, /*IsCompletion=*/false) + .Case("q", PQK_Quit, /*IsCompletion=*/false) .Case("quit", PQK_Quit) .Case("set", PQK_Set) .Case("enable", PQK_Enable) .Case("disable", PQK_Disable) .Case("unlet", PQK_Unlet) + .Case("f", PQK_File, /*IsCompletion=*/false) + .Case("file", PQK_File) .Default(PQK_Invalid); switch (QKind) { @@ -351,6 +354,9 @@ QueryRef QueryParser::doParse() { return endQuery(new LetQuery(Name, VariantValue())); } + case PQK_File: + return new FileQuery(Line); + case PQK_Invalid: return new InvalidQuery("unknown command: " + CommandStr); } diff --git a/clang-tools-extra/clang-query/tool/ClangQuery.cpp b/clang-tools-extra/clang-query/tool/ClangQuery.cpp index da7ac2701448..a2de7a2dced8 100644 --- a/clang-tools-extra/clang-query/tool/ClangQuery.cpp +++ b/clang-tools-extra/clang-query/tool/ClangQuery.cpp @@ -74,22 +74,8 @@ static cl::opt PreloadFile( bool runCommandsInFile(const char *ExeName, std::string const &FileName, QuerySession &QS) { - auto Buffer = llvm::MemoryBuffer::getFile(FileName); - if (!Buffer) { - llvm::errs() << ExeName << ": cannot open " << FileName << ": " - << Buffer.getError().message() << "\n"; - return true; - } - - StringRef FileContentRef(Buffer.get()->getBuffer()); - - while (!FileContentRef.empty()) { - QueryRef Q = QueryParser::parse(FileContentRef, QS); - if (!Q->run(llvm::outs(), QS)) - return true; - FileContentRef = Q->RemainingContent; - } - return false; + FileQuery Query(FileName, ExeName); + return !Query.run(llvm::errs(), QS); } int main(int argc, const char **argv) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 6a2b8d3b6ded..fc976ce3a33d 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -90,7 +90,9 @@ Improvements to clang-doc Improvements to clang-query --------------------------- -The improvements are... +- Added the `file` command to dynamically load a list of commands and matchers + from an external file, allowing the cost of reading the compilation database + and building the AST to be imposed just once for faster prototyping. Improvements to clang-rename ---------------------------- diff --git a/clang-tools-extra/test/clang-query/Inputs/empty.script b/clang-tools-extra/test/clang-query/Inputs/empty.script new file mode 100644 index 000000000000..3c30abd1ae5d --- /dev/null +++ b/clang-tools-extra/test/clang-query/Inputs/empty.script @@ -0,0 +1 @@ +# This file intentionally has no queries diff --git a/clang-tools-extra/test/clang-query/Inputs/file.script b/clang-tools-extra/test/clang-query/Inputs/file.script new file mode 100644 index 000000000000..b58e7bbc24bf --- /dev/null +++ b/clang-tools-extra/test/clang-query/Inputs/file.script @@ -0,0 +1 @@ +f DIRECTORY/runtime_file.script diff --git a/clang-tools-extra/test/clang-query/Inputs/runtime_file.script b/clang-tools-extra/test/clang-query/Inputs/runtime_file.script new file mode 100644 index 000000000000..714d7f03b1bf --- /dev/null +++ b/clang-tools-extra/test/clang-query/Inputs/runtime_file.script @@ -0,0 +1,5 @@ +set bind-root false + +l func functionDecl(hasName("bar")) +m func.bind("f") +m varDecl().bind("v") \ No newline at end of file diff --git a/clang-tools-extra/test/clang-query/errors.c b/clang-tools-extra/test/clang-query/errors.c index bbb742125744..3b9059ab0257 100644 --- a/clang-tools-extra/test/clang-query/errors.c +++ b/clang-tools-extra/test/clang-query/errors.c @@ -1,10 +1,12 @@ // RUN: not clang-query -c foo -c bar %s -- | FileCheck %s // RUN: not clang-query -f %S/Inputs/foo.script %s -- | FileCheck %s // RUN: not clang-query -f %S/Inputs/nonexistent.script %s -- 2>&1 | FileCheck --check-prefix=CHECK-NONEXISTENT %s +// RUN: not clang-query -c 'file %S/Inputs/nonexistent.script' %s -- 2>&1 | FileCheck --check-prefix=CHECK-NONEXISTENT-FILEQUERY %s // RUN: not clang-query -c foo -f foo %s -- 2>&1 | FileCheck --check-prefix=CHECK-BOTH %s // CHECK: unknown command: foo // CHECK-NOT: unknown command: bar // CHECK-NONEXISTENT: cannot open {{.*}}nonexistent.script +// CHECK-NONEXISTENT-FILEQUERY: cannot open {{.*}}nonexistent.script // CHECK-BOTH: cannot specify both -c and -f diff --git a/clang-tools-extra/test/clang-query/file-empty.c b/clang-tools-extra/test/clang-query/file-empty.c new file mode 100644 index 000000000000..15137c57e915 --- /dev/null +++ b/clang-tools-extra/test/clang-query/file-empty.c @@ -0,0 +1,2 @@ +// RUN: clang-query -c 'file %S/Inputs/empty.script' %s -- +// COM: no output expected; nothing to CHECK diff --git a/clang-tools-extra/test/clang-query/file-query.c b/clang-tools-extra/test/clang-query/file-query.c new file mode 100644 index 000000000000..10a44e7aaccf --- /dev/null +++ b/clang-tools-extra/test/clang-query/file-query.c @@ -0,0 +1,14 @@ +// RUN: rm -rf %/t +// RUN: mkdir %/t +// RUN: cp %/S/Inputs/file.script %/t/file.script +// RUN: cp %/S/Inputs/runtime_file.script %/t/runtime_file.script +// Need to embed the correct temp path in the actual JSON-RPC requests. +// RUN: sed -e "s|DIRECTORY|%/t|" %/t/file.script > %/t/file.script.temp + +// RUN: clang-query -c 'file %/t/file.script.temp' %s -- | FileCheck %s + +// CHECK: file-query.c:11:1: note: "f" binds here +void bar(void) {} + +// CHECK: file-query.c:14:1: note: "v" binds here +int baz{1}; diff --git a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp index 06b0d7b36590..b561e2bb9833 100644 --- a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp +++ b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp @@ -197,7 +197,7 @@ TEST_F(QueryParserTest, Comment) { TEST_F(QueryParserTest, Complete) { std::vector Comps = QueryParser::complete("", 0, QS); - ASSERT_EQ(8u, Comps.size()); + ASSERT_EQ(9u, Comps.size()); EXPECT_EQ("help ", Comps[0].TypedText); EXPECT_EQ("help", Comps[0].DisplayText); EXPECT_EQ("let ", Comps[1].TypedText); @@ -214,6 +214,8 @@ TEST_F(QueryParserTest, Complete) { EXPECT_EQ("disable", Comps[6].DisplayText); EXPECT_EQ("unlet ", Comps[7].TypedText); EXPECT_EQ("unlet", Comps[7].DisplayText); + EXPECT_EQ("file ", Comps[8].TypedText); + EXPECT_EQ("file", Comps[8].DisplayText); Comps = QueryParser::complete("set o", 5, QS); ASSERT_EQ(1u, Comps.size()); -- GitLab From e76b257483e6c6743de0fa6eca4d0cc60e08385d Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Mon, 13 May 2024 14:31:39 +0200 Subject: [PATCH 054/578] [Clang][OpenMP][Tile] Ensure AST node uniqueness. (#91325) 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. --- clang/lib/Sema/SemaOpenMP.cpp | 75 +++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index cf5447f223d4..fff4c7350f0f 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -15109,6 +15109,8 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, SourceLocation StartLoc, SourceLocation EndLoc) { ASTContext &Context = getASTContext(); + Scope *CurScope = SemaRef.getCurScope(); + auto SizesClauses = OMPExecutableDirective::getClausesOfKind(Clauses); if (SizesClauses.empty()) { @@ -15137,6 +15139,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, NumLoops, AStmt, nullptr, nullptr); SmallVector PreInits; + CaptureVars CopyTransformer(SemaRef); // Create iteration variables for the generated loops. SmallVector FloorIndVars; @@ -15200,19 +15203,30 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, Expr *NumIterations = LoopHelper.NumIterations; auto *OrigCntVar = cast(LoopHelper.Counters[0]); QualType CntTy = OrigCntVar->getType(); - Expr *DimTileSize = SizesClause->getSizesRefs()[I]; - Scope *CurScope = SemaRef.getCurScope(); - // Commonly used variables. - DeclRefExpr *TileIV = buildDeclRefExpr(SemaRef, TileIndVars[I], CntTy, - OrigCntVar->getExprLoc()); - DeclRefExpr *FloorIV = buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy, - OrigCntVar->getExprLoc()); + // 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 MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, I, + SizesClause]() -> Expr * { + Expr *DimTileSize = SizesClause->getSizesRefs()[I]; + return AssertSuccess(CopyTransformer.TransformExpr(DimTileSize)); + }; + auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, CntTy, + OrigCntVar]() { + return buildDeclRefExpr(SemaRef, TileIndVars[I], CntTy, + OrigCntVar->getExprLoc()); + }; + auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, CntTy, + OrigCntVar]() { + return buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy, + OrigCntVar->getExprLoc()); + }; // For init-statement: auto .tile.iv = .floor.iv - SemaRef.AddInitializerToDecl(TileIndVars[I], - SemaRef.DefaultLvalueConversion(FloorIV).get(), - /*DirectInit=*/false); + SemaRef.AddInitializerToDecl( + TileIndVars[I], SemaRef.DefaultLvalueConversion(MakeFloorIVRef()).get(), + /*DirectInit=*/false); Decl *CounterDecl = TileIndVars[I]; StmtResult InitStmt = new (Context) DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1), @@ -15220,10 +15234,11 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, if (!InitStmt.isUsable()) return StmtError(); - // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize, - // NumIterations) - ExprResult EndOfTile = SemaRef.BuildBinOp( - CurScope, LoopHelper.Cond->getExprLoc(), BO_Add, FloorIV, DimTileSize); + // For cond-expression: + // .tile.iv < min(.floor.iv + DimTileSize, NumIterations) + ExprResult EndOfTile = + SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add, + MakeFloorIVRef(), MakeDimTileSize()); if (!EndOfTile.isUsable()) return StmtError(); ExprResult IsPartialTile = @@ -15238,25 +15253,28 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, return StmtError(); ExprResult CondExpr = SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, - TileIV, MinTileAndIterSpace.get()); + MakeTileIVRef(), MinTileAndIterSpace.get()); if (!CondExpr.isUsable()) return StmtError(); // For incr-statement: ++.tile.iv ExprResult IncrStmt = SemaRef.BuildUnaryOp( - CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV); + CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef()); if (!IncrStmt.isUsable()) return StmtError(); // Statements to set the original iteration variable's value from the // logical iteration number. // Generated for loop is: + // \code // Original_for_init; - // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize, - // NumIterations); ++.tile.iv) { + // for (auto .tile.iv = .floor.iv; + // .tile.iv < min(.floor.iv + DimTileSize, NumIterations); + // ++.tile.iv) { // Original_Body; // Original_counter_update; // } + // \endcode // FIXME: If the innermost body is an loop itself, inserting these // statements stops it being recognized as a perfectly nested loop (e.g. // for applying tiling again). If this is the case, sink the expressions @@ -15278,12 +15296,18 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, Expr *NumIterations = LoopHelper.NumIterations; DeclRefExpr *OrigCntVar = cast(LoopHelper.Counters[0]); QualType CntTy = OrigCntVar->getType(); - Expr *DimTileSize = SizesClause->getSizesRefs()[I]; - Scope *CurScope = SemaRef.getCurScope(); // Commonly used variables. - DeclRefExpr *FloorIV = buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy, - OrigCntVar->getExprLoc()); + auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, I, + SizesClause]() -> Expr * { + Expr *DimTileSize = SizesClause->getSizesRefs()[I]; + return AssertSuccess(CopyTransformer.TransformExpr(DimTileSize)); + }; + auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, CntTy, + OrigCntVar]() { + return buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy, + OrigCntVar->getExprLoc()); + }; // For init-statement: auto .floor.iv = 0 SemaRef.AddInitializerToDecl( @@ -15298,15 +15322,16 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, return StmtError(); // For cond-expression: .floor.iv < NumIterations - ExprResult CondExpr = SemaRef.BuildBinOp( - CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, FloorIV, NumIterations); + ExprResult CondExpr = + SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, + MakeFloorIVRef(), NumIterations); if (!CondExpr.isUsable()) return StmtError(); // For incr-statement: .floor.iv += DimTileSize ExprResult IncrStmt = SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign, - FloorIV, DimTileSize); + MakeFloorIVRef(), MakeDimTileSize()); if (!IncrStmt.isUsable()) return StmtError(); -- GitLab From 061db17a3075e34c55ebd463d06e16771e398e04 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 13 May 2024 13:40:27 +0100 Subject: [PATCH 055/578] Fix MSVC "signed/unsigned mismatch" warning. NFC. --- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 6533e8281631..1e33c2729e5d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1650,7 +1650,8 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) { addUInt(MemberDie, dwarf::DW_AT_byte_size, std::nullopt, FieldSize / 8); addUInt(MemberDie, dwarf::DW_AT_bit_size, std::nullopt, Size); - assert(DT->getOffsetInBits() <= std::numeric_limits::max()); + assert(DT->getOffsetInBits() <= + (uint64_t)std::numeric_limits::max()); int64_t Offset = DT->getOffsetInBits(); // We can't use DT->getAlignInBits() here: AlignInBits for member type // is non-zero if and only if alignment was forced (e.g. _Alignas()), -- GitLab From 1a4b113a41266b94fe217e5fe90d91db15d2356b Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 13 May 2024 13:44:32 +0100 Subject: [PATCH 056/578] [CostModel][X86] getCastInstrCost - update cost tables to support CostKinds Add TypeConversionCostKindTblEntry to hold the costs kinds and update the cast tables to take the existing default codesize/latency/sizelatency values (I'll update these values in future commits). I've moved AdjustCost to the end of the function to ensure we don't accidentally use it, apart from when we fallback to default cost calculations. --- .../lib/Target/X86/X86TargetTransformInfo.cpp | 1554 +++++++++-------- 1 file changed, 787 insertions(+), 767 deletions(-) diff --git a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp index 0a0bc7b32e87..ac66144aeaae 100644 --- a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp +++ b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp @@ -99,6 +99,7 @@ struct CostKindCosts { } }; using CostKindTblEntry = CostTblEntryT; +using TypeConversionCostKindTblEntry = TypeConversionCostTblEntryT; TargetTransformInfo::PopcntSupportKind X86TTIImpl::getPopcntSupport(unsigned TyWidth) { @@ -2138,811 +2139,803 @@ InstructionCost X86TTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); - // TODO: Allow non-throughput costs that aren't binary. - auto AdjustCost = [&CostKind](InstructionCost Cost, - InstructionCost N = 1) -> InstructionCost { - if (CostKind != TTI::TCK_RecipThroughput) - return Cost == 0 ? 0 : N; - return Cost * N; - }; - // The cost tables include both specific, custom (non-legal) src/dst type // conversions and generic, legalized types. We test for customs first, before // falling back to legalization. // FIXME: Need a better design of the cost table to handle non-simple types of // potential massive combinations (elem_num x src_type x dst_type). - static const TypeConversionCostTblEntry AVX512BWConversionTbl[] { - { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i8, 1 }, - { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i8, 1 }, + static const TypeConversionCostKindTblEntry AVX512BWConversionTbl[]{ + { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i8, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i8, { 1, 1, 1, 1 } }, // Mask sign extend has an instruction. - { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v8i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v32i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v64i8, MVT::v64i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v64i1, 1 }, + { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v8i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v32i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v64i8, MVT::v64i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v64i1, { 1, 1, 1, 1 } }, // Mask zero extend is a sext + shift. - { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v8i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v32i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v64i8, MVT::v64i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v64i1, 2 }, - - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 2 }, - { ISD::TRUNCATE, MVT::v2i1, MVT::v16i8, 2 }, - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 2 }, - { ISD::TRUNCATE, MVT::v2i1, MVT::v8i16, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v16i8, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v8i16, 2 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, 2 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v16i8, 2 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, 2 }, - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, 2 }, - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, 2 }, - { ISD::TRUNCATE, MVT::v32i1, MVT::v32i8, 2 }, - { ISD::TRUNCATE, MVT::v32i1, MVT::v32i16, 2 }, - { ISD::TRUNCATE, MVT::v64i1, MVT::v64i8, 2 }, - { ISD::TRUNCATE, MVT::v64i1, MVT::v32i16, 2 }, - - { ISD::TRUNCATE, MVT::v32i8, MVT::v32i16, 2 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 2 }, // widen to zmm - { ISD::TRUNCATE, MVT::v2i8, MVT::v2i16, 2 }, // vpmovwb - { ISD::TRUNCATE, MVT::v4i8, MVT::v4i16, 2 }, // vpmovwb - { ISD::TRUNCATE, MVT::v8i8, MVT::v8i16, 2 }, // vpmovwb + { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v2i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v2i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v4i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v4i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v8i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v32i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v64i8, MVT::v64i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v64i1, { 2, 1, 1, 1 } }, + + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v2i1, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v2i1, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v32i1, MVT::v32i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v32i1, MVT::v32i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v64i1, MVT::v64i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v64i1, MVT::v32i16, { 2, 1, 1, 1 } }, + + { ISD::TRUNCATE, MVT::v32i8, MVT::v32i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 2, 1, 1, 1 } }, // widen to zmm + { ISD::TRUNCATE, MVT::v2i8, MVT::v2i16, { 2, 1, 1, 1 } }, // vpmovwb + { ISD::TRUNCATE, MVT::v4i8, MVT::v4i16, { 2, 1, 1, 1 } }, // vpmovwb + { ISD::TRUNCATE, MVT::v8i8, MVT::v8i16, { 2, 1, 1, 1 } }, // vpmovwb }; - static const TypeConversionCostTblEntry AVX512DQConversionTbl[] = { + static const TypeConversionCostKindTblEntry AVX512DQConversionTbl[] = { // Mask sign extend has an instruction. - { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v16i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i1, 1 }, + { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v16i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i1, { 1, 1, 1, 1 } }, // Mask zero extend is a sext + shift. - { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v16i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i1, 2 }, - - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, 2 }, - { ISD::TRUNCATE, MVT::v2i1, MVT::v4i32, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, 2 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 2 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, 2 }, - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i32, 2 }, - { ISD::TRUNCATE, MVT::v16i1, MVT::v8i64, 2 }, - - { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i64, 1 }, - { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i64, 1 }, - - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i64, 1 }, - { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i64, 1 }, - - { ISD::FP_TO_SINT, MVT::v8i64, MVT::v8f32, 1 }, - { ISD::FP_TO_SINT, MVT::v8i64, MVT::v8f64, 1 }, - - { ISD::FP_TO_UINT, MVT::v8i64, MVT::v8f32, 1 }, - { ISD::FP_TO_UINT, MVT::v8i64, MVT::v8f64, 1 }, + { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1, } }, + { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v2i1, { 2, 1, 1, 1, } }, + { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1, } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1, } }, + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1, } }, + { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v16i1, { 2, 1, 1, 1, } }, + { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i1, { 2, 1, 1, 1, } }, + { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i1, { 2, 1, 1, 1, } }, + + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v2i1, MVT::v4i32, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i32, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i1, MVT::v8i64, { 2, 1, 1, 1 } }, + + { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i64, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i64, { 1, 1, 1, 1 } }, + + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i64, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i64, { 1, 1, 1, 1 } }, + + { ISD::FP_TO_SINT, MVT::v8i64, MVT::v8f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i64, MVT::v8f64, { 1, 1, 1, 1 } }, + + { ISD::FP_TO_UINT, MVT::v8i64, MVT::v8f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i64, MVT::v8f64, { 1, 1, 1, 1 } }, }; // TODO: For AVX512DQ + AVX512VL, we also have cheap casts for 128-bit and // 256-bit wide vectors. - static const TypeConversionCostTblEntry AVX512FConversionTbl[] = { - { ISD::FP_EXTEND, MVT::v8f64, MVT::v8f32, 1 }, - { ISD::FP_EXTEND, MVT::v8f64, MVT::v16f32, 3 }, - { ISD::FP_EXTEND, MVT::v16f64, MVT::v16f32, 4 }, // 2*vcvtps2pd+vextractf64x4 - { ISD::FP_ROUND, MVT::v8f32, MVT::v8f64, 1 }, - - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 3 }, // sext+vpslld+vptestmd - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 3 }, // sext+vpslld+vptestmd - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, 3 }, // sext+vpslld+vptestmd - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, 3 }, // sext+vpslld+vptestmd - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 3 }, // sext+vpsllq+vptestmq - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, 3 }, // sext+vpsllq+vptestmq - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, 3 }, // sext+vpsllq+vptestmq - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, 3 }, // sext+vpslld+vptestmd - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, 2 }, // zmm vpslld+vptestmd - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, 2 }, // zmm vpslld+vptestmd - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 2 }, // zmm vpslld+vptestmd - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i32, 2 }, // vpslld+vptestmd - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, 2 }, // zmm vpsllq+vptestmq - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, 2 }, // zmm vpsllq+vptestmq - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, 2 }, // vpsllq+vptestmq - { ISD::TRUNCATE, MVT::v2i8, MVT::v2i32, 2 }, // vpmovdb - { ISD::TRUNCATE, MVT::v4i8, MVT::v4i32, 2 }, // vpmovdb - { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 2 }, // vpmovdb - { ISD::TRUNCATE, MVT::v32i8, MVT::v16i32, 2 }, // vpmovdb - { ISD::TRUNCATE, MVT::v64i8, MVT::v16i32, 2 }, // vpmovdb - { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, 2 }, // vpmovdw - { ISD::TRUNCATE, MVT::v32i16, MVT::v16i32, 2 }, // vpmovdw - { ISD::TRUNCATE, MVT::v2i8, MVT::v2i64, 2 }, // vpmovqb - { ISD::TRUNCATE, MVT::v2i16, MVT::v2i64, 1 }, // vpshufb - { ISD::TRUNCATE, MVT::v8i8, MVT::v8i64, 2 }, // vpmovqb - { ISD::TRUNCATE, MVT::v16i8, MVT::v8i64, 2 }, // vpmovqb - { ISD::TRUNCATE, MVT::v32i8, MVT::v8i64, 2 }, // vpmovqb - { ISD::TRUNCATE, MVT::v64i8, MVT::v8i64, 2 }, // vpmovqb - { ISD::TRUNCATE, MVT::v8i16, MVT::v8i64, 2 }, // vpmovqw - { ISD::TRUNCATE, MVT::v16i16, MVT::v8i64, 2 }, // vpmovqw - { ISD::TRUNCATE, MVT::v32i16, MVT::v8i64, 2 }, // vpmovqw - { ISD::TRUNCATE, MVT::v8i32, MVT::v8i64, 1 }, // vpmovqd - { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 1 }, // zmm vpmovqd - { ISD::TRUNCATE, MVT::v16i8, MVT::v16i64, 5 },// 2*vpmovqd+concat+vpmovdb - - { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 3 }, // extend to v16i32 - { ISD::TRUNCATE, MVT::v32i8, MVT::v32i16, 8 }, - { ISD::TRUNCATE, MVT::v64i8, MVT::v32i16, 8 }, + static const TypeConversionCostKindTblEntry AVX512FConversionTbl[] = { + { ISD::FP_EXTEND, MVT::v8f64, MVT::v8f32, { 1, 1, 1, 1 } }, + { ISD::FP_EXTEND, MVT::v8f64, MVT::v16f32, { 3, 1, 1, 1 } }, + { ISD::FP_EXTEND, MVT::v16f64, MVT::v16f32, { 4, 1, 1, 1 } }, // 2*vcvtps2pd+vextractf64x4 + { ISD::FP_ROUND, MVT::v8f32, MVT::v8f64, { 1, 1, 1, 1 } }, + + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, { 2, 1, 1, 1 } }, // zmm vpslld+vptestmd + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } }, // zmm vpslld+vptestmd + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } }, // zmm vpslld+vptestmd + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } }, // zmm vpsllq+vptestmq + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } }, // zmm vpsllq+vptestmq + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, { 2, 1, 1, 1 } }, // vpsllq+vptestmq + { ISD::TRUNCATE, MVT::v2i8, MVT::v2i32, { 2, 1, 1, 1 } }, // vpmovdb + { ISD::TRUNCATE, MVT::v4i8, MVT::v4i32, { 2, 1, 1, 1 } }, // vpmovdb + { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdb + { ISD::TRUNCATE, MVT::v32i8, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdb + { ISD::TRUNCATE, MVT::v64i8, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdb + { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdw + { ISD::TRUNCATE, MVT::v32i16, MVT::v16i32, { 2, 1, 1, 1 } }, // vpmovdw + { ISD::TRUNCATE, MVT::v2i8, MVT::v2i64, { 2, 1, 1, 1 } }, // vpmovqb + { ISD::TRUNCATE, MVT::v2i16, MVT::v2i64, { 1, 1, 1, 1 } }, // vpshufb + { ISD::TRUNCATE, MVT::v8i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb + { ISD::TRUNCATE, MVT::v16i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb + { ISD::TRUNCATE, MVT::v32i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb + { ISD::TRUNCATE, MVT::v64i8, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqb + { ISD::TRUNCATE, MVT::v8i16, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqw + { ISD::TRUNCATE, MVT::v16i16, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqw + { ISD::TRUNCATE, MVT::v32i16, MVT::v8i64, { 2, 1, 1, 1 } }, // vpmovqw + { ISD::TRUNCATE, MVT::v8i32, MVT::v8i64, { 1, 1, 1, 1 } }, // vpmovqd + { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 1, 1, 1, 1 } }, // zmm vpmovqd + { ISD::TRUNCATE, MVT::v16i8, MVT::v16i64, { 5, 1, 1, 1 } },// 2*vpmovqd+concat+vpmovdb + + { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 3, 1, 1, 1 } }, // extend to v16i32 + { ISD::TRUNCATE, MVT::v32i8, MVT::v32i16, { 8, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v64i8, MVT::v32i16, { 8, 1, 1, 1 } }, // Sign extend is zmm vpternlogd+vptruncdb. // Zero extend is zmm broadcast load+vptruncdw. - { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, 3 }, - { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, 4 }, - { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, 3 }, - { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, 4 }, - { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, 3 }, - { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, 4 }, - { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, 3 }, - { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, 4 }, + { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 4, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 4, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 4, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, { 4, 1, 1, 1 } }, // Sign extend is zmm vpternlogd+vptruncdw. // Zero extend is zmm vpternlogd+vptruncdw+vpsrlw. - { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, 3 }, - { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, 4 }, - { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, 3 }, - { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, 4 }, - { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, 3 }, - { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, 4 }, - { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 3 }, - { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 4 }, - - { ISD::SIGN_EXTEND, MVT::v2i32, MVT::v2i1, 1 }, // zmm vpternlogd - { ISD::ZERO_EXTEND, MVT::v2i32, MVT::v2i1, 2 }, // zmm vpternlogd+psrld - { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, 1 }, // zmm vpternlogd - { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, 2 }, // zmm vpternlogd+psrld - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 1 }, // zmm vpternlogd - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 2 }, // zmm vpternlogd+psrld - { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, 1 }, // zmm vpternlogq - { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, 2 }, // zmm vpternlogq+psrlq - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 1 }, // zmm vpternlogq - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 2 }, // zmm vpternlogq+psrlq - - { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i1, 1 }, // vpternlogd - { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i1, 2 }, // vpternlogd+psrld - { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i1, 1 }, // vpternlogq - { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i1, 2 }, // vpternlogq+psrlq - - { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i8, 1 }, - { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i8, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i16, 1 }, - { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i16, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i8, 1 }, - { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i8, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i16, 1 }, - { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i16, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i32, 1 }, - { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i32, 1 }, - - { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i8, 3 }, // FIXME: May not be right - { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i8, 3 }, // FIXME: May not be right - - { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i1, 4 }, - { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i1, 3 }, - { ISD::SINT_TO_FP, MVT::v8f64, MVT::v16i8, 2 }, - { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i8, 1 }, - { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i16, 2 }, - { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i16, 1 }, - { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, 1 }, - { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i32, 1 }, - - { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i1, 4 }, - { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i1, 3 }, - { ISD::UINT_TO_FP, MVT::v8f64, MVT::v16i8, 2 }, - { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i8, 1 }, - { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i16, 2 }, - { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i16, 1 }, - { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, 1 }, - { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i32, 1 }, - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i64, 26 }, - { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i64, 5 }, - - { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f32, 2 }, - { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f64, 7 }, - { ISD::FP_TO_SINT, MVT::v32i8, MVT::v32f64,15 }, - { ISD::FP_TO_SINT, MVT::v64i8, MVT::v64f32,11 }, - { ISD::FP_TO_SINT, MVT::v64i8, MVT::v64f64,31 }, - { ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f64, 3 }, - { ISD::FP_TO_SINT, MVT::v16i16, MVT::v16f64, 7 }, - { ISD::FP_TO_SINT, MVT::v32i16, MVT::v32f32, 5 }, - { ISD::FP_TO_SINT, MVT::v32i16, MVT::v32f64,15 }, - { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, 1 }, - { ISD::FP_TO_SINT, MVT::v16i32, MVT::v16f64, 3 }, - - { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f64, 1 }, - { ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f64, 3 }, - { ISD::FP_TO_UINT, MVT::v8i8, MVT::v8f64, 3 }, - { ISD::FP_TO_UINT, MVT::v16i32, MVT::v16f32, 1 }, - { ISD::FP_TO_UINT, MVT::v16i16, MVT::v16f32, 3 }, - { ISD::FP_TO_UINT, MVT::v16i8, MVT::v16f32, 3 }, + { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 4, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 4, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 4, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 4, 1, 1, 1 } }, + + { ISD::SIGN_EXTEND, MVT::v2i32, MVT::v2i1, { 1, 1, 1, 1 } }, // zmm vpternlogd + { ISD::ZERO_EXTEND, MVT::v2i32, MVT::v2i1, { 2, 1, 1, 1 } }, // zmm vpternlogd+psrld + { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } }, // zmm vpternlogd + { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1 } }, // zmm vpternlogd+psrld + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } }, // zmm vpternlogd + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1 } }, // zmm vpternlogd+psrld + { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } }, // zmm vpternlogq + { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1 } }, // zmm vpternlogq+psrlq + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } }, // zmm vpternlogq + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1 } }, // zmm vpternlogq+psrlq + + { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i1, { 1, 1, 1, 1 } }, // vpternlogd + { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld + { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i1, { 1, 1, 1, 1 } }, // vpternlogq + { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i1, { 2, 1, 1, 1 } }, // vpternlogq+psrlq + + { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i16, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i16, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i8, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i8, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i32, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i32, { 1, 1, 1, 1 } }, + + { ISD::SIGN_EXTEND, MVT::v32i16, MVT::v32i8, { 3, 1, 1, 1 } }, // FIXME: May not be right + { ISD::ZERO_EXTEND, MVT::v32i16, MVT::v32i8, { 3, 1, 1, 1 } }, // FIXME: May not be right + + { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i1, { 4, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i1, { 3, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f64, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i16, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i32, { 1, 1, 1, 1 } }, + + { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i1, { 4, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i1, { 3, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f64, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i16, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i32, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i64, {26, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i64, { 5, 1, 1, 1 } }, + + { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f64, { 7, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v32i8, MVT::v32f64, {15, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v64i8, MVT::v64f32, {11, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v64i8, MVT::v64f64, {31, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f64, { 3, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v16i16, MVT::v16f64, { 7, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v32i16, MVT::v32f32, { 5, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v32i16, MVT::v32f64, {15, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v16i32, MVT::v16f64, { 3, 1, 1, 1 } }, + + { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f64, { 3, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i8, MVT::v8f64, { 3, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v16i32, MVT::v16f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v16i16, MVT::v16f32, { 3, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v16i8, MVT::v16f32, { 3, 1, 1, 1 } }, }; - static const TypeConversionCostTblEntry AVX512BWVLConversionTbl[] { + static const TypeConversionCostKindTblEntry AVX512BWVLConversionTbl[] { // Mask sign extend has an instruction. - { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v8i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v32i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v32i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v64i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v64i1, 1 }, + { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v8i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v32i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v32i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v32i8, MVT::v64i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v64i1, { 1, 1, 1, 1 } }, // Mask zero extend is a sext + shift. - { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v8i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v32i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v32i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v64i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v64i1, 2 }, - - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 2 }, - { ISD::TRUNCATE, MVT::v2i1, MVT::v16i8, 2 }, - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 2 }, - { ISD::TRUNCATE, MVT::v2i1, MVT::v8i16, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v16i8, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v8i16, 2 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, 2 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v16i8, 2 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, 2 }, - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, 2 }, - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, 2 }, - { ISD::TRUNCATE, MVT::v32i1, MVT::v32i8, 2 }, - { ISD::TRUNCATE, MVT::v32i1, MVT::v16i16, 2 }, - { ISD::TRUNCATE, MVT::v64i1, MVT::v32i8, 2 }, - { ISD::TRUNCATE, MVT::v64i1, MVT::v16i16, 2 }, - - { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 2 }, + { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v2i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v2i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v4i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v4i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v8i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v32i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v32i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v32i8, MVT::v64i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v64i1, { 2, 1, 1, 1 } }, + + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v2i1, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v2i1, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v32i1, MVT::v32i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v32i1, MVT::v16i16, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v64i1, MVT::v32i8, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v64i1, MVT::v16i16, { 2, 1, 1, 1 } }, + + { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 2, 1, 1, 1 } }, }; - static const TypeConversionCostTblEntry AVX512DQVLConversionTbl[] = { + static const TypeConversionCostKindTblEntry AVX512DQVLConversionTbl[] = { // Mask sign extend has an instruction. - { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v2i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i1, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 1 }, + { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v2i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i1, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } }, // Mask zero extend is a sext + shift. - { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v2i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i1, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 2 }, - - { ISD::TRUNCATE, MVT::v16i1, MVT::v4i64, 2 }, - { ISD::TRUNCATE, MVT::v16i1, MVT::v8i32, 2 }, - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, 2 }, - { ISD::TRUNCATE, MVT::v2i1, MVT::v4i32, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, 2 }, - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, 2 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v4i64, 2 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 2 }, - - { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i64, 1 }, - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, 1 }, - { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i64, 1 }, - { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i64, 1 }, - - { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, 1 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 1 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, 1 }, - { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, 1 }, - - { ISD::FP_TO_SINT, MVT::v2i64, MVT::v4f32, 1 }, - { ISD::FP_TO_SINT, MVT::v4i64, MVT::v4f32, 1 }, - { ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, 1 }, - { ISD::FP_TO_SINT, MVT::v4i64, MVT::v4f64, 1 }, - - { ISD::FP_TO_UINT, MVT::v2i64, MVT::v4f32, 1 }, - { ISD::FP_TO_UINT, MVT::v4i64, MVT::v4f32, 1 }, - { ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, 1 }, - { ISD::FP_TO_UINT, MVT::v4i64, MVT::v4f64, 1 }, + { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v2i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i1, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1 } }, + + { ISD::TRUNCATE, MVT::v16i1, MVT::v4i64, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i1, MVT::v8i32, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v2i1, MVT::v4i32, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v4i64, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } }, + + { ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i64, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i64, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i64, { 1, 1, 1, 1 } }, + + { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, { 1, 1, 1, 1 } }, + + { ISD::FP_TO_SINT, MVT::v2i64, MVT::v4f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v4i64, MVT::v4f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v4i64, MVT::v4f64, { 1, 1, 1, 1 } }, + + { ISD::FP_TO_UINT, MVT::v2i64, MVT::v4f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i64, MVT::v4f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i64, MVT::v4f64, { 1, 1, 1, 1 } }, }; - static const TypeConversionCostTblEntry AVX512VLConversionTbl[] = { - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 3 }, // sext+vpslld+vptestmd - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 3 }, // sext+vpslld+vptestmd - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, 3 }, // sext+vpslld+vptestmd - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, 8 }, // split+2*v8i8 - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 3 }, // sext+vpsllq+vptestmq - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, 3 }, // sext+vpsllq+vptestmq - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, 3 }, // sext+vpsllq+vptestmq - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, 8 }, // split+2*v8i16 - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, 2 }, // vpslld+vptestmd - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, 2 }, // vpslld+vptestmd - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 2 }, // vpslld+vptestmd - { ISD::TRUNCATE, MVT::v16i1, MVT::v8i32, 2 }, // vpslld+vptestmd - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, 2 }, // vpsllq+vptestmq - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, 2 }, // vpsllq+vptestmq - { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 1 }, // vpmovqd - { ISD::TRUNCATE, MVT::v4i8, MVT::v4i64, 2 }, // vpmovqb - { ISD::TRUNCATE, MVT::v4i16, MVT::v4i64, 2 }, // vpmovqw - { ISD::TRUNCATE, MVT::v8i8, MVT::v8i32, 2 }, // vpmovwb + static const TypeConversionCostKindTblEntry AVX512VLConversionTbl[] = { + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 3, 1, 1, 1 } }, // sext+vpslld+vptestmd + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i8, { 8, 1, 1, 1 } }, // split+2*v8i8 + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i16, { 3, 1, 1, 1 } }, // sext+vpsllq+vptestmq + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 8, 1, 1, 1 } }, // split+2*v8i16 + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd + { ISD::TRUNCATE, MVT::v16i1, MVT::v8i32, { 2, 1, 1, 1 } }, // vpslld+vptestmd + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i64, { 2, 1, 1, 1 } }, // vpsllq+vptestmq + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 2, 1, 1, 1 } }, // vpsllq+vptestmq + { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 1, 1, 1, 1 } }, // vpmovqd + { ISD::TRUNCATE, MVT::v4i8, MVT::v4i64, { 2, 1, 1, 1 } }, // vpmovqb + { ISD::TRUNCATE, MVT::v4i16, MVT::v4i64, { 2, 1, 1, 1 } }, // vpmovqw + { ISD::TRUNCATE, MVT::v8i8, MVT::v8i32, { 2, 1, 1, 1 } }, // vpmovwb // sign extend is vpcmpeq+maskedmove+vpmovdw+vpacksswb // zero extend is vpcmpeq+maskedmove+vpmovdw+vpsrlw+vpackuswb - { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, 5 }, - { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, 6 }, - { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, 5 }, - { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, 6 }, - { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, 5 }, - { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, 6 }, - { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, 10 }, - { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, 12 }, + { ISD::SIGN_EXTEND, MVT::v2i8, MVT::v2i1, { 5, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v2i8, MVT::v2i1, { 6, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i8, MVT::v4i1, { 5, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i8, MVT::v4i1, { 6, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i8, MVT::v8i1, { 5, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i8, MVT::v8i1, { 6, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i8, MVT::v16i1, {10, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i8, MVT::v16i1, {12, 1, 1, 1 } }, // sign extend is vpcmpeq+maskedmove+vpmovdw // zero extend is vpcmpeq+maskedmove+vpmovdw+vpsrlw - { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, 4 }, - { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, 5 }, - { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, 4 }, - { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, 5 }, - { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, 4 }, - { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, 5 }, - { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 10 }, - { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 12 }, - - { ISD::SIGN_EXTEND, MVT::v2i32, MVT::v2i1, 1 }, // vpternlogd - { ISD::ZERO_EXTEND, MVT::v2i32, MVT::v2i1, 2 }, // vpternlogd+psrld - { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, 1 }, // vpternlogd - { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, 2 }, // vpternlogd+psrld - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 1 }, // vpternlogd - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 2 }, // vpternlogd+psrld - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i1, 1 }, // vpternlogd - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i1, 2 }, // vpternlogd+psrld - - { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, 1 }, // vpternlogq - { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, 2 }, // vpternlogq+psrlq - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 1 }, // vpternlogq - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 2 }, // vpternlogq+psrlq - - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, 1 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, 1 }, - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, 1 }, - { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 1 }, - { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, 1 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 1 }, - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 1 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 1 }, - - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, 1 }, - { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, 1 }, - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, 1 }, - { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, 1 }, - - { ISD::UINT_TO_FP, MVT::f32, MVT::i64, 1 }, - { ISD::UINT_TO_FP, MVT::f64, MVT::i64, 1 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, 1 }, - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, 1 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, 1 }, - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, 1 }, - { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 1 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 1 }, - { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, 1 }, - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, 1 }, - { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, 5 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 5 }, - { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, 5 }, - - { ISD::FP_TO_SINT, MVT::v16i8, MVT::v8f32, 2 }, - { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f32, 2 }, - { ISD::FP_TO_SINT, MVT::v32i8, MVT::v32f32, 5 }, - - { ISD::FP_TO_UINT, MVT::i64, MVT::f32, 1 }, - { ISD::FP_TO_UINT, MVT::i64, MVT::f64, 1 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 1 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, 1 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, 1 }, - { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, 1 }, - { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f64, 1 }, + { ISD::SIGN_EXTEND, MVT::v2i16, MVT::v2i1, { 4, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v2i16, MVT::v2i1, { 5, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i16, MVT::v4i1, { 4, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i16, MVT::v4i1, { 5, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v8i1, { 4, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v8i1, { 5, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, {10, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, {12, 1, 1, 1 } }, + + { ISD::SIGN_EXTEND, MVT::v2i32, MVT::v2i1, { 1, 1, 1, 1 } }, // vpternlogd + { ISD::ZERO_EXTEND, MVT::v2i32, MVT::v2i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld + { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v4i1, { 1, 1, 1, 1 } }, // vpternlogd + { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v4i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 1, 1, 1, 1 } }, // vpternlogd + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i1, { 1, 1, 1, 1 } }, // vpternlogd + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i1, { 2, 1, 1, 1 } }, // vpternlogd+psrld + + { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v2i1, { 1, 1, 1, 1 } }, // vpternlogq + { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v2i1, { 2, 1, 1, 1 } }, // vpternlogq+psrlq + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 1, 1, 1, 1 } }, // vpternlogq + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 2, 1, 1, 1 } }, // vpternlogq+psrlq + + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, { 1, 1, 1, 1 } }, + + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, { 1, 1, 1, 1 } }, + + { ISD::UINT_TO_FP, MVT::f32, MVT::i64, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::f64, MVT::i64, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, { 5, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 5, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, { 5, 1, 1, 1 } }, + + { ISD::FP_TO_SINT, MVT::v16i8, MVT::v8f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v32i8, MVT::v32f32, { 5, 1, 1, 1 } }, + + { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::i64, MVT::f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f64, { 1, 1, 1, 1 } }, }; - static const TypeConversionCostTblEntry AVX2ConversionTbl[] = { - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 3 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 3 }, - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 3 }, - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 3 }, - { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 1 }, - { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 1 }, - - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, 2 }, - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, 2 }, - { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 2 }, - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, 2 }, - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 2 }, - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 2 }, - { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i16, 3 }, - { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i16, 3 }, - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 2 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 2 }, - - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 2 }, - - { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, 4 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 4 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v8i16, 1 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, 1 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, 1 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v8i32, 4 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v4i64, 4 }, - { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, 1 }, - { ISD::TRUNCATE, MVT::v8i16, MVT::v2i64, 1 }, - { ISD::TRUNCATE, MVT::v8i16, MVT::v4i64, 5 }, - { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 1 }, - { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, 2 }, - - { ISD::FP_EXTEND, MVT::v8f64, MVT::v8f32, 3 }, - { ISD::FP_ROUND, MVT::v8f32, MVT::v8f64, 3 }, - - { ISD::FP_TO_SINT, MVT::v16i16, MVT::v8f32, 1 }, - { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f64, 1 }, - { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f32, 1 }, - { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, 3 }, - - { ISD::FP_TO_UINT, MVT::i64, MVT::f32, 3 }, - { ISD::FP_TO_UINT, MVT::i64, MVT::f64, 3 }, - { ISD::FP_TO_UINT, MVT::v16i16, MVT::v8f32, 1 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 3 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, 4 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, 4 }, - { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, 3 }, - { ISD::FP_TO_UINT, MVT::v8i32, MVT::v4f64, 4 }, - - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, 2 }, - { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, 2 }, - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, 2 }, - { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, 2 }, - { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, 1 }, - { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i32, 1 }, - { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, 3 }, - - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, 2 }, - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, 2 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, 2 }, - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, 2 }, - { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 2 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, 1 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 2 }, - { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, 2 }, - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, 2 }, - { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, 4 }, + static const TypeConversionCostKindTblEntry AVX2ConversionTbl[] = { + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 3, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 3, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 1, 1, 1, 1 } }, + + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i16, { 3, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i16, { 3, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, { 2, 1, 1, 1 } }, + + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 2, 1, 1, 1 } }, + + { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, { 4, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 4, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, { 1, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, { 1, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v8i32, { 4, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v4i64, { 4, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, { 1, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i16, MVT::v2i64, { 1, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i16, MVT::v4i64, { 5, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 1, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, { 2, 1, 1, 1 } }, + + { ISD::FP_EXTEND, MVT::v8f64, MVT::v8f32, { 3, 1, 1, 1 } }, + { ISD::FP_ROUND, MVT::v8f32, MVT::v8f64, { 3, 1, 1, 1 } }, + + { ISD::FP_TO_SINT, MVT::v16i16, MVT::v8f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, { 3, 1, 1, 1 } }, + + { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 3, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::i64, MVT::f64, { 3, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v16i16, MVT::v8f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 3, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, { 4, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, { 3, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i32, MVT::v4f64, { 4, 1, 1, 1 } }, + + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i32, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, { 3, 1, 1, 1 } }, + + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, { 4, 1, 1, 1 } }, }; - static const TypeConversionCostTblEntry AVXConversionTbl[] = { - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, 4 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, 4 }, - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, 4 }, - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, 4 }, - { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, 4 }, - { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, 4 }, - - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, 3 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, 3 }, - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, 3 }, - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, 3 }, - { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 3 }, - { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 3 }, - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, 3 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, 3 }, - { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 3 }, - { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 3 }, - { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 3 }, - { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 3 }, - - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, 4 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, 5 }, - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, 4 }, - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, 9 }, - { ISD::TRUNCATE, MVT::v16i1, MVT::v16i64, 11 }, - - { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, 6 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 6 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 2 }, // and+extract+packuswb - { ISD::TRUNCATE, MVT::v16i8, MVT::v8i32, 5 }, - { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, 5 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v4i64, 5 }, - { ISD::TRUNCATE, MVT::v8i16, MVT::v4i64, 3 }, // and+extract+2*packusdw - { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 2 }, - - { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i1, 3 }, - { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i1, 3 }, - { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i1, 8 }, - { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, 4 }, - { ISD::SINT_TO_FP, MVT::v4f64, MVT::v16i8, 2 }, - { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, 4 }, - { ISD::SINT_TO_FP, MVT::v4f64, MVT::v8i16, 2 }, - { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, 2 }, - { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i32, 2 }, - { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, 4 }, - { ISD::SINT_TO_FP, MVT::v4f32, MVT::v2i64, 5 }, - { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i64, 8 }, - - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i1, 7 }, - { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i1, 7 }, - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i1, 6 }, - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, 4 }, - { ISD::UINT_TO_FP, MVT::v4f64, MVT::v16i8, 2 }, - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, 4 }, - { ISD::UINT_TO_FP, MVT::v4f64, MVT::v8i16, 2 }, - { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 4 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, 4 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 5 }, - { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, 6 }, - { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, 8 }, - { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, 10 }, - { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, 10 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, 18 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 5 }, - { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, 10 }, - - { ISD::FP_TO_SINT, MVT::v16i8, MVT::v8f32, 2 }, - { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f64, 2 }, - { ISD::FP_TO_SINT, MVT::v32i8, MVT::v8f32, 2 }, - { ISD::FP_TO_SINT, MVT::v32i8, MVT::v4f64, 2 }, - { ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f32, 2 }, - { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f64, 2 }, - { ISD::FP_TO_SINT, MVT::v16i16, MVT::v8f32, 2 }, - { ISD::FP_TO_SINT, MVT::v16i16, MVT::v4f64, 2 }, - { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f64, 2 }, - { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f32, 2 }, - { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, 5 }, - - { ISD::FP_TO_UINT, MVT::v16i8, MVT::v8f32, 2 }, - { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f64, 2 }, - { ISD::FP_TO_UINT, MVT::v32i8, MVT::v8f32, 2 }, - { ISD::FP_TO_UINT, MVT::v32i8, MVT::v4f64, 2 }, - { ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f32, 2 }, - { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f64, 2 }, - { ISD::FP_TO_UINT, MVT::v16i16, MVT::v8f32, 2 }, - { ISD::FP_TO_UINT, MVT::v16i16, MVT::v4f64, 2 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 3 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, 4 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, 6 }, - { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, 7 }, - { ISD::FP_TO_UINT, MVT::v8i32, MVT::v4f64, 7 }, - - { ISD::FP_EXTEND, MVT::v4f64, MVT::v4f32, 1 }, - { ISD::FP_ROUND, MVT::v4f32, MVT::v4f64, 1 }, + static const TypeConversionCostKindTblEntry AVXConversionTbl[] = { + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i1, { 4, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i1, { 4, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i1, { 4, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i1, { 4, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i1, { 4, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i1, { 4, 1, 1, 1 } }, + + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v16i8, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v16i8, { 3, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v16i8, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v16i8, { 3, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, { 3, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v8i16, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v8i16, { 3, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, { 3, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, { 3, 1, 1, 1 } }, + + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i64, { 4, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i32, { 5, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i16, { 4, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i64, { 9, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i1, MVT::v16i64, {11, 1, 1, 1 } }, + + { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, { 6, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 6, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 2, 1, 1, 1 } }, // and+extract+packuswb + { ISD::TRUNCATE, MVT::v16i8, MVT::v8i32, { 5, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, { 5, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v4i64, { 5, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i16, MVT::v4i64, { 3, 1, 1, 1 } }, // and+extract+2*packusdw + { ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, { 2, 1, 1, 1 } }, + + { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i1, { 3, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i1, { 3, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i1, { 8, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f32, MVT::v16i8, { 4, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f64, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, { 4, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f64, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, { 2, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i32, { 2, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v8f64, MVT::v8i32, { 4, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f32, MVT::v2i64, { 5, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i64, { 8, 1, 1, 1 } }, + + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i1, { 7, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i1, { 7, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i1, { 6, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v16i8, { 4, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f64, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, { 4, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f64, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 4, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, { 4, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 5, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, { 6, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i32, { 8, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v8f64, MVT::v8i32, {10, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i64, {10, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, {18, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 5, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i64, {10, 1, 1, 1 } }, + + { ISD::FP_TO_SINT, MVT::v16i8, MVT::v8f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f64, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v32i8, MVT::v8f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v32i8, MVT::v4f64, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f64, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v16i16, MVT::v8f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v16i16, MVT::v4f64, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f64, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f64, { 5, 1, 1, 1 } }, + + { ISD::FP_TO_UINT, MVT::v16i8, MVT::v8f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f64, { 2, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v32i8, MVT::v8f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v32i8, MVT::v4f64, { 2, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f64, { 2, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v16i16, MVT::v8f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v16i16, MVT::v4f64, { 2, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 3, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f64, { 6, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f32, { 7, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i32, MVT::v4f64, { 7, 1, 1, 1 } }, + + { ISD::FP_EXTEND, MVT::v4f64, MVT::v4f32, { 1, 1, 1, 1 } }, + { ISD::FP_ROUND, MVT::v4f32, MVT::v4f64, { 1, 1, 1, 1 } }, }; - static const TypeConversionCostTblEntry SSE41ConversionTbl[] = { - { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v16i8, 1 }, - { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v16i8, 1 }, - { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v16i8, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v16i8, 1 }, - { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v16i8, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v16i8, 1 }, - { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v8i16, 1 }, - { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v8i16, 1 }, - { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v8i16, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v8i16, 1 }, - { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v4i32, 1 }, - { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v4i32, 1 }, + static const TypeConversionCostKindTblEntry SSE41ConversionTbl[] = { + { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v4i32, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v4i32, { 1, 1, 1, 1 } }, // These truncates end up widening elements. - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 1 }, // PMOVXZBQ - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 1 }, // PMOVXZWQ - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 1 }, // PMOVXZBD - - { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, 2 }, - { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, 2 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, 2 }, - - { ISD::SINT_TO_FP, MVT::f32, MVT::i32, 1 }, - { ISD::SINT_TO_FP, MVT::f64, MVT::i32, 1 }, - { ISD::SINT_TO_FP, MVT::f32, MVT::i64, 1 }, - { ISD::SINT_TO_FP, MVT::f64, MVT::i64, 1 }, - { ISD::SINT_TO_FP, MVT::v4f32, MVT::v16i8, 1 }, - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, 1 }, - { ISD::SINT_TO_FP, MVT::v4f32, MVT::v8i16, 1 }, - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, 1 }, - { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, 1 }, - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v4i32, 1 }, - { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, 2 }, - - { ISD::UINT_TO_FP, MVT::f32, MVT::i32, 1 }, - { ISD::UINT_TO_FP, MVT::f64, MVT::i32, 1 }, - { ISD::UINT_TO_FP, MVT::f32, MVT::i64, 4 }, - { ISD::UINT_TO_FP, MVT::f64, MVT::i64, 4 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v16i8, 1 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, 1 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v8i16, 1 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, 1 }, - { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 3 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 3 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v4i32, 2 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v2i64, 12 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, 22 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 4 }, - - { ISD::FP_TO_SINT, MVT::i32, MVT::f32, 1 }, - { ISD::FP_TO_SINT, MVT::i64, MVT::f32, 1 }, - { ISD::FP_TO_SINT, MVT::i32, MVT::f64, 1 }, - { ISD::FP_TO_SINT, MVT::i64, MVT::f64, 1 }, - { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f32, 2 }, - { ISD::FP_TO_SINT, MVT::v16i8, MVT::v2f64, 2 }, - { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f32, 1 }, - { ISD::FP_TO_SINT, MVT::v8i16, MVT::v2f64, 1 }, - { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, 1 }, - { ISD::FP_TO_SINT, MVT::v4i32, MVT::v2f64, 1 }, - - { ISD::FP_TO_UINT, MVT::i32, MVT::f32, 1 }, - { ISD::FP_TO_UINT, MVT::i64, MVT::f32, 4 }, - { ISD::FP_TO_UINT, MVT::i32, MVT::f64, 1 }, - { ISD::FP_TO_UINT, MVT::i64, MVT::f64, 4 }, - { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f32, 2 }, - { ISD::FP_TO_UINT, MVT::v16i8, MVT::v2f64, 2 }, - { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f32, 1 }, - { ISD::FP_TO_UINT, MVT::v8i16, MVT::v2f64, 1 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 4 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, 4 }, + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 1, 1, 1, 1 } }, // PMOVXZBQ + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 1, 1, 1, 1 } }, // PMOVXZWQ + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 1, 1, 1, 1 } }, // PMOVXZBD + + { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, { 2, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, { 2, 1, 1, 1 } }, + + { ISD::SINT_TO_FP, MVT::f32, MVT::i32, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::f64, MVT::i32, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::f32, MVT::i64, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::f64, MVT::i64, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f32, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v4i32, { 1, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, { 2, 1, 1, 1 } }, + + { ISD::UINT_TO_FP, MVT::f32, MVT::i32, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::f64, MVT::i32, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::f32, MVT::i64, { 4, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::f64, MVT::i64, { 4, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 3, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 3, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v4i32, { 2, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v2i64, {12, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i64, {22, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, { 4, 1, 1, 1 } }, + + { ISD::FP_TO_SINT, MVT::i32, MVT::f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::i64, MVT::f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::i32, MVT::f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::i64, MVT::f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v16i8, MVT::v2f64, { 2, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i16, MVT::v2f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v4i32, MVT::v2f64, { 1, 1, 1, 1 } }, + + { ISD::FP_TO_UINT, MVT::i32, MVT::f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 4, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::i32, MVT::f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::i64, MVT::f64, { 4, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f32, { 2, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v16i8, MVT::v2f64, { 2, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f32, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i16, MVT::v2f64, { 1, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 4, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } }, }; - static const TypeConversionCostTblEntry SSE2ConversionTbl[] = { + static const TypeConversionCostKindTblEntry SSE2ConversionTbl[] = { // These are somewhat magic numbers justified by comparing the // output of llvm-mca for our various supported scheduler models // and basing it off the worst case scenario. - { ISD::SINT_TO_FP, MVT::f32, MVT::i32, 3 }, - { ISD::SINT_TO_FP, MVT::f64, MVT::i32, 3 }, - { ISD::SINT_TO_FP, MVT::f32, MVT::i64, 3 }, - { ISD::SINT_TO_FP, MVT::f64, MVT::i64, 3 }, - { ISD::SINT_TO_FP, MVT::v4f32, MVT::v16i8, 3 }, - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, 4 }, - { ISD::SINT_TO_FP, MVT::v4f32, MVT::v8i16, 3 }, - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, 4 }, - { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, 3 }, - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v4i32, 4 }, - { ISD::SINT_TO_FP, MVT::v4f32, MVT::v2i64, 8 }, - { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, 8 }, - - { ISD::UINT_TO_FP, MVT::f32, MVT::i32, 3 }, - { ISD::UINT_TO_FP, MVT::f64, MVT::i32, 3 }, - { ISD::UINT_TO_FP, MVT::f32, MVT::i64, 8 }, - { ISD::UINT_TO_FP, MVT::f64, MVT::i64, 9 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, 4 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v16i8, 4 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v8i16, 4 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, 4 }, - { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 7 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v4i32, 7 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 5 }, - { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 15 }, - { ISD::UINT_TO_FP, MVT::v4f32, MVT::v2i64, 18 }, - - { ISD::FP_TO_SINT, MVT::i32, MVT::f32, 4 }, - { ISD::FP_TO_SINT, MVT::i64, MVT::f32, 4 }, - { ISD::FP_TO_SINT, MVT::i32, MVT::f64, 4 }, - { ISD::FP_TO_SINT, MVT::i64, MVT::f64, 4 }, - { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f32, 6 }, - { ISD::FP_TO_SINT, MVT::v16i8, MVT::v2f64, 6 }, - { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f32, 5 }, - { ISD::FP_TO_SINT, MVT::v8i16, MVT::v2f64, 5 }, - { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, 4 }, - { ISD::FP_TO_SINT, MVT::v4i32, MVT::v2f64, 4 }, - - { ISD::FP_TO_UINT, MVT::i32, MVT::f32, 4 }, - { ISD::FP_TO_UINT, MVT::i64, MVT::f32, 4 }, - { ISD::FP_TO_UINT, MVT::i32, MVT::f64, 4 }, - { ISD::FP_TO_UINT, MVT::i64, MVT::f64, 15 }, - { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f32, 6 }, - { ISD::FP_TO_UINT, MVT::v16i8, MVT::v2f64, 6 }, - { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f32, 5 }, - { ISD::FP_TO_UINT, MVT::v8i16, MVT::v2f64, 5 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 8 }, - { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, 8 }, - - { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v16i8, 4 }, - { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v16i8, 4 }, - { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v16i8, 2 }, - { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v16i8, 3 }, - { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v16i8, 1 }, - { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v16i8, 2 }, - { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v8i16, 2 }, - { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v8i16, 3 }, - { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v8i16, 1 }, - { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v8i16, 2 }, - { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v4i32, 1 }, - { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v4i32, 2 }, + { ISD::SINT_TO_FP, MVT::f32, MVT::i32, { 3, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::f64, MVT::i32, { 3, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::f32, MVT::i64, { 3, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::f64, MVT::i64, { 3, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f32, MVT::v16i8, { 3, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v16i8, { 4, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f32, MVT::v8i16, { 3, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v8i16, { 4, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, { 3, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v4i32, { 4, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v4f32, MVT::v2i64, { 8, 1, 1, 1 } }, + { ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, { 8, 1, 1, 1 } }, + + { ISD::UINT_TO_FP, MVT::f32, MVT::i32, { 3, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::f64, MVT::i32, { 3, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::f32, MVT::i64, { 8, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::f64, MVT::i64, { 9, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v16i8, { 4, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v16i8, { 4, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v8i16, { 4, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v8i16, { 4, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, { 7, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v4i32, { 7, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, { 5, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, {15, 1, 1, 1 } }, + { ISD::UINT_TO_FP, MVT::v4f32, MVT::v2i64, {18, 1, 1, 1 } }, + + { ISD::FP_TO_SINT, MVT::i32, MVT::f32, { 4, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::i64, MVT::f32, { 4, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::i32, MVT::f64, { 4, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::i64, MVT::f64, { 4, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v16i8, MVT::v4f32, { 6, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v16i8, MVT::v2f64, { 6, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i16, MVT::v4f32, { 5, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v8i16, MVT::v2f64, { 5, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, { 4, 1, 1, 1 } }, + { ISD::FP_TO_SINT, MVT::v4i32, MVT::v2f64, { 4, 1, 1, 1 } }, + + { ISD::FP_TO_UINT, MVT::i32, MVT::f32, { 4, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::i64, MVT::f32, { 4, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::i32, MVT::f64, { 4, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::i64, MVT::f64, {15, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v16i8, MVT::v4f32, { 6, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v16i8, MVT::v2f64, { 6, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i16, MVT::v4f32, { 5, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v8i16, MVT::v2f64, { 5, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, { 8, 1, 1, 1 } }, + { ISD::FP_TO_UINT, MVT::v4i32, MVT::v2f64, { 8, 1, 1, 1 } }, + + { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v16i8, { 4, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v16i8, { 4, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v16i8, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v8i16, MVT::v16i8, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v8i16, MVT::v16i8, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v8i16, { 3, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v4i32, MVT::v8i16, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v4i32, MVT::v8i16, { 2, 1, 1, 1 } }, + { ISD::ZERO_EXTEND, MVT::v2i64, MVT::v4i32, { 1, 1, 1, 1 } }, + { ISD::SIGN_EXTEND, MVT::v2i64, MVT::v4i32, { 2, 1, 1, 1 } }, // These truncates are really widening elements. - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, 1 }, // PSHUFD - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, 2 }, // PUNPCKLWD+DQ - { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, 3 }, // PUNPCKLBW+WD+PSHUFD - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, 1 }, // PUNPCKLWD - { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, 2 }, // PUNPCKLBW+WD - { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, 1 }, // PUNPCKLBW - - { ISD::TRUNCATE, MVT::v16i8, MVT::v8i16, 2 }, // PAND+PACKUSWB - { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 3 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, 3 }, // PAND+2*PACKUSWB - { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 7 }, - { ISD::TRUNCATE, MVT::v2i16, MVT::v2i32, 1 }, - { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, 3 }, - { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, 5 }, - { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32,10 }, - { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, 4 }, // PAND+3*PACKUSWB - { ISD::TRUNCATE, MVT::v8i16, MVT::v2i64, 2 }, // PSHUFD+PSHUFLW - { ISD::TRUNCATE, MVT::v4i32, MVT::v2i64, 1 }, // PSHUFD + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i32, { 1, 1, 1, 1 } }, // PSHUFD + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i16, { 2, 1, 1, 1 } }, // PUNPCKLWD+DQ + { ISD::TRUNCATE, MVT::v2i1, MVT::v2i8, { 3, 1, 1, 1 } }, // PUNPCKLBW+WD+PSHUFD + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i16, { 1, 1, 1, 1 } }, // PUNPCKLWD + { ISD::TRUNCATE, MVT::v4i1, MVT::v4i8, { 2, 1, 1, 1 } }, // PUNPCKLBW+WD + { ISD::TRUNCATE, MVT::v8i1, MVT::v8i8, { 1, 1, 1, 1 } }, // PUNPCKLBW + + { ISD::TRUNCATE, MVT::v16i8, MVT::v8i16, { 2, 1, 1, 1 } }, // PAND+PACKUSWB + { ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, { 3, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v4i32, { 3, 1, 1, 1 } }, // PAND+2*PACKUSWB + { ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, { 7, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v2i16, MVT::v2i32, { 1, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i16, MVT::v4i32, { 3, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, { 5, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, {10, 1, 1, 1 } }, + { ISD::TRUNCATE, MVT::v16i8, MVT::v2i64, { 4, 1, 1, 1 } }, // PAND+3*PACKUSWB + { ISD::TRUNCATE, MVT::v8i16, MVT::v2i64, { 2, 1, 1, 1 } }, // PSHUFD+PSHUFLW + { ISD::TRUNCATE, MVT::v4i32, MVT::v2i64, { 1, 1, 1, 1 } }, // PSHUFD }; // Attempt to map directly to (simple) MVT types to let us match custom entries. @@ -2958,56 +2951,66 @@ InstructionCost X86TTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, if (ST->hasBWI()) if (const auto *Entry = ConvertCostTableLookup( AVX512BWConversionTbl, ISD, SimpleDstTy, SimpleSrcTy)) - return AdjustCost(Entry->Cost); + if (auto KindCost = Entry->Cost[CostKind]) + return *KindCost; if (ST->hasDQI()) if (const auto *Entry = ConvertCostTableLookup( AVX512DQConversionTbl, ISD, SimpleDstTy, SimpleSrcTy)) - return AdjustCost(Entry->Cost); + if (auto KindCost = Entry->Cost[CostKind]) + return *KindCost; if (ST->hasAVX512()) if (const auto *Entry = ConvertCostTableLookup( AVX512FConversionTbl, ISD, SimpleDstTy, SimpleSrcTy)) - return AdjustCost(Entry->Cost); + if (auto KindCost = Entry->Cost[CostKind]) + return *KindCost; } if (ST->hasBWI()) if (const auto *Entry = ConvertCostTableLookup( AVX512BWVLConversionTbl, ISD, SimpleDstTy, SimpleSrcTy)) - return AdjustCost(Entry->Cost); + if (auto KindCost = Entry->Cost[CostKind]) + return *KindCost; if (ST->hasDQI()) if (const auto *Entry = ConvertCostTableLookup( AVX512DQVLConversionTbl, ISD, SimpleDstTy, SimpleSrcTy)) - return AdjustCost(Entry->Cost); + if (auto KindCost = Entry->Cost[CostKind]) + return *KindCost; if (ST->hasAVX512()) if (const auto *Entry = ConvertCostTableLookup(AVX512VLConversionTbl, ISD, SimpleDstTy, SimpleSrcTy)) - return AdjustCost(Entry->Cost); + if (auto KindCost = Entry->Cost[CostKind]) + return *KindCost; if (ST->hasAVX2()) { if (const auto *Entry = ConvertCostTableLookup(AVX2ConversionTbl, ISD, SimpleDstTy, SimpleSrcTy)) - return AdjustCost(Entry->Cost); + if (auto KindCost = Entry->Cost[CostKind]) + return *KindCost; } if (ST->hasAVX()) { if (const auto *Entry = ConvertCostTableLookup(AVXConversionTbl, ISD, SimpleDstTy, SimpleSrcTy)) - return AdjustCost(Entry->Cost); + if (auto KindCost = Entry->Cost[CostKind]) + return *KindCost; } if (ST->hasSSE41()) { if (const auto *Entry = ConvertCostTableLookup(SSE41ConversionTbl, ISD, SimpleDstTy, SimpleSrcTy)) - return AdjustCost(Entry->Cost); + if (auto KindCost = Entry->Cost[CostKind]) + return *KindCost; } if (ST->hasSSE2()) { if (const auto *Entry = ConvertCostTableLookup(SSE2ConversionTbl, ISD, SimpleDstTy, SimpleSrcTy)) - return AdjustCost(Entry->Cost); + if (auto KindCost = Entry->Cost[CostKind]) + return *KindCost; } } @@ -3023,53 +3026,63 @@ InstructionCost X86TTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, if (ST->hasBWI()) if (const auto *Entry = ConvertCostTableLookup( AVX512BWConversionTbl, ISD, LTDest.second, LTSrc.second)) - return AdjustCost(Entry->Cost, std::max(LTSrc.first, LTDest.first)); + if (auto KindCost = Entry->Cost[CostKind]) + return std::max(LTSrc.first, LTDest.first) * *KindCost; if (ST->hasDQI()) if (const auto *Entry = ConvertCostTableLookup( AVX512DQConversionTbl, ISD, LTDest.second, LTSrc.second)) - return AdjustCost(Entry->Cost, std::max(LTSrc.first, LTDest.first)); + if (auto KindCost = Entry->Cost[CostKind]) + return std::max(LTSrc.first, LTDest.first) * *KindCost; if (ST->hasAVX512()) if (const auto *Entry = ConvertCostTableLookup( AVX512FConversionTbl, ISD, LTDest.second, LTSrc.second)) - return AdjustCost(Entry->Cost, std::max(LTSrc.first, LTDest.first)); + if (auto KindCost = Entry->Cost[CostKind]) + return std::max(LTSrc.first, LTDest.first) * *KindCost; } if (ST->hasBWI()) if (const auto *Entry = ConvertCostTableLookup(AVX512BWVLConversionTbl, ISD, LTDest.second, LTSrc.second)) - return AdjustCost(Entry->Cost, std::max(LTSrc.first, LTDest.first)); + if (auto KindCost = Entry->Cost[CostKind]) + return std::max(LTSrc.first, LTDest.first) * *KindCost; if (ST->hasDQI()) if (const auto *Entry = ConvertCostTableLookup(AVX512DQVLConversionTbl, ISD, LTDest.second, LTSrc.second)) - return AdjustCost(Entry->Cost, std::max(LTSrc.first, LTDest.first)); + if (auto KindCost = Entry->Cost[CostKind]) + return std::max(LTSrc.first, LTDest.first) * *KindCost; if (ST->hasAVX512()) if (const auto *Entry = ConvertCostTableLookup(AVX512VLConversionTbl, ISD, LTDest.second, LTSrc.second)) - return AdjustCost(Entry->Cost, std::max(LTSrc.first, LTDest.first)); + if (auto KindCost = Entry->Cost[CostKind]) + return std::max(LTSrc.first, LTDest.first) * *KindCost; if (ST->hasAVX2()) if (const auto *Entry = ConvertCostTableLookup(AVX2ConversionTbl, ISD, LTDest.second, LTSrc.second)) - return AdjustCost(Entry->Cost, std::max(LTSrc.first, LTDest.first)); + if (auto KindCost = Entry->Cost[CostKind]) + return std::max(LTSrc.first, LTDest.first) * *KindCost; if (ST->hasAVX()) if (const auto *Entry = ConvertCostTableLookup(AVXConversionTbl, ISD, LTDest.second, LTSrc.second)) - return AdjustCost(Entry->Cost, std::max(LTSrc.first, LTDest.first)); + if (auto KindCost = Entry->Cost[CostKind]) + return std::max(LTSrc.first, LTDest.first) * *KindCost; if (ST->hasSSE41()) if (const auto *Entry = ConvertCostTableLookup(SSE41ConversionTbl, ISD, LTDest.second, LTSrc.second)) - return AdjustCost(Entry->Cost, std::max(LTSrc.first, LTDest.first)); + if (auto KindCost = Entry->Cost[CostKind]) + return std::max(LTSrc.first, LTDest.first) * *KindCost; if (ST->hasSSE2()) if (const auto *Entry = ConvertCostTableLookup(SSE2ConversionTbl, ISD, LTDest.second, LTSrc.second)) - return AdjustCost(Entry->Cost, std::max(LTSrc.first, LTDest.first)); + if (auto KindCost = Entry->Cost[CostKind]) + return std::max(LTSrc.first, LTDest.first) * *KindCost; // Fallback, for i8/i16 sitofp/uitofp cases we need to extend to i32 for // sitofp. @@ -3098,6 +3111,13 @@ InstructionCost X86TTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, TTI::CastContextHint::None, CostKind); } + // TODO: Allow non-throughput costs that aren't binary. + auto AdjustCost = [&CostKind](InstructionCost Cost, + InstructionCost N = 1) -> InstructionCost { + if (CostKind != TTI::TCK_RecipThroughput) + return Cost == 0 ? 0 : N; + return Cost * N; + }; return AdjustCost( BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I)); } -- GitLab From f0590581aa01944a3bb502a622a412617d1efcbb Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Mon, 13 May 2024 14:55:34 +0200 Subject: [PATCH 057/578] [Clang][OpenMP] Fix unused lambda capture warning. --- clang/lib/Sema/SemaOpenMP.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index fff4c7350f0f..2475f962fd0d 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -15207,8 +15207,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, // 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 MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, I, - SizesClause]() -> Expr * { + auto MakeDimTileSize = [&CopyTransformer, I, SizesClause]() -> Expr * { Expr *DimTileSize = SizesClause->getSizesRefs()[I]; return AssertSuccess(CopyTransformer.TransformExpr(DimTileSize)); }; @@ -15298,8 +15297,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, QualType CntTy = OrigCntVar->getType(); // Commonly used variables. - auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, I, - SizesClause]() -> Expr * { + auto MakeDimTileSize = [&CopyTransformer, I, SizesClause]() -> Expr * { Expr *DimTileSize = SizesClause->getSizesRefs()[I]; return AssertSuccess(CopyTransformer.TransformExpr(DimTileSize)); }; -- GitLab From ca1bd5995f6ed934f9187305190a5abfac049173 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 13 May 2024 08:09:24 -0500 Subject: [PATCH 058/578] [flang][OpenMP] Decompose compound constructs, do recursive lowering (#90098) A compound construct with a list of clauses is broken up into individual leaf/composite constructs. Each such construct has the list of clauses that apply to it based on the OpenMP spec. Each lowering function (i.e. a function that generates MLIR ops) is now responsible for generating its body as described below. Functions that receive AST nodes extract the construct, and the clauses from the node. They then create a work queue consisting of individual constructs, and invoke a common dispatch function to process (lower) the queue. The dispatch function examines the current position in the queue, and invokes the appropriate lowering function. Each lowering function receives the queue as well, and once it needs to generate its body, it either invokes the dispatch function on the rest of the queue (if any), or processes nested evaluations if the work queue is at the end. --- flang/lib/Lower/CMakeLists.txt | 1 + flang/lib/Lower/OpenMP/Clauses.cpp | 23 + flang/lib/Lower/OpenMP/Clauses.h | 13 +- flang/lib/Lower/OpenMP/Decomposer.cpp | 126 ++ flang/lib/Lower/OpenMP/Decomposer.h | 51 + flang/lib/Lower/OpenMP/OpenMP.cpp | 828 ++++++------ flang/lib/Lower/OpenMP/Utils.cpp | 6 - flang/lib/Lower/OpenMP/Utils.h | 1 - .../Lower/OpenMP/default-clause-byref.f90 | 5 +- flang/test/Lower/OpenMP/default-clause.f90 | 4 +- .../parallel-lastprivate-clause-scalar.f90 | 4 +- llvm/include/llvm/Frontend/OpenMP/ClauseT.h | 52 +- .../Frontend/OpenMP/ConstructCompositionT.h | 403 ++++++ .../Frontend/OpenMP/ConstructDecompositionT.h | 1161 +++++++++++++++++ llvm/unittests/Frontend/CMakeLists.txt | 1 + .../Frontend/OpenMPDecompositionTest.cpp | 999 ++++++++++++++ 16 files changed, 3226 insertions(+), 452 deletions(-) create mode 100644 flang/lib/Lower/OpenMP/Decomposer.cpp create mode 100644 flang/lib/Lower/OpenMP/Decomposer.h create mode 100644 llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h create mode 100644 llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h create mode 100644 llvm/unittests/Frontend/OpenMPDecompositionTest.cpp diff --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt index f92d1a2bc7de..1546409752e7 100644 --- a/flang/lib/Lower/CMakeLists.txt +++ b/flang/lib/Lower/CMakeLists.txt @@ -27,6 +27,7 @@ add_flang_library(FortranLower OpenMP/ClauseProcessor.cpp OpenMP/Clauses.cpp OpenMP/DataSharingProcessor.cpp + OpenMP/Decomposer.cpp OpenMP/OpenMP.cpp OpenMP/ReductionProcessor.cpp OpenMP/Utils.cpp diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 97337cfc08c7..87370c92964a 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -1227,4 +1227,27 @@ List makeClauses(const parser::OmpClauseList &clauses, return makeClause(s, semaCtx); }); } + +bool transferLocations(const List &from, List &to) { + bool allDone = true; + + for (Clause &clause : to) { + if (!clause.source.empty()) + continue; + auto found = + llvm::find_if(from, [&](const Clause &c) { return c.id == clause.id; }); + // This is not completely accurate, but should be good enough for now. + // It can be improved in the future if necessary, but in cases of + // synthesized clauses getting accurate location may be impossible. + if (found != from.end()) { + clause.source = found->source; + } else { + // Found a clause that won't have "source". + allDone = false; + } + } + + return allDone; +} + } // namespace Fortran::lower::omp diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h index 3e776425c733..407579319279 100644 --- a/flang/lib/Lower/OpenMP/Clauses.h +++ b/flang/lib/Lower/OpenMP/Clauses.h @@ -23,11 +23,15 @@ namespace Fortran::lower::omp { using namespace Fortran; -using SomeType = evaluate::SomeType; using SomeExpr = semantics::SomeExpr; using MaybeExpr = semantics::MaybeExpr; -using TypeTy = SomeType; +// evaluate::SomeType doesn't provide == operation. It's not really used in +// flang's clauses so far, so a trivial implementation is sufficient. +struct TypeTy : public evaluate::SomeType { + bool operator==(const TypeTy &t) const { return true; } +}; + using IdTy = semantics::Symbol *; using ExprTy = SomeExpr; @@ -222,6 +226,8 @@ using When = tomp::clause::WhenT; using Write = tomp::clause::WriteT; } // namespace clause +using tomp::type::operator==; + struct CancellationConstructType { using EmptyTrait = std::true_type; }; @@ -244,6 +250,7 @@ using ClauseBase = tomp::ClauseT; struct Clause : public ClauseBase { + // "source" will be ignored by tomp::type::operator==. parser::CharBlock source; }; @@ -258,6 +265,8 @@ Clause makeClause(const Fortran::parser::OmpClause &cls, List makeClauses(const parser::OmpClauseList &clauses, semantics::SemanticsContext &semaCtx); + +bool transferLocations(const List &from, List &to); } // namespace Fortran::lower::omp #endif // FORTRAN_LOWER_OPENMP_CLAUSES_H diff --git a/flang/lib/Lower/OpenMP/Decomposer.cpp b/flang/lib/Lower/OpenMP/Decomposer.cpp new file mode 100644 index 000000000000..e6897cb81e94 --- /dev/null +++ b/flang/lib/Lower/OpenMP/Decomposer.cpp @@ -0,0 +1,126 @@ +//===-- Decomposer.cpp -- Compound directive decomposition ----------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ +// +//===----------------------------------------------------------------------===// + +#include "Decomposer.h" + +#include "Clauses.h" +#include "Utils.h" +#include "flang/Lower/PFTBuilder.h" +#include "flang/Semantics/semantics.h" +#include "flang/Tools/CrossToolHelpers.h" +#include "mlir/IR/BuiltinOps.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Frontend/OpenMP/ClauseT.h" +#include "llvm/Frontend/OpenMP/ConstructCompositionT.h" +#include "llvm/Frontend/OpenMP/ConstructDecompositionT.h" +#include "llvm/Frontend/OpenMP/OMP.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include + +using namespace Fortran; + +namespace { +using namespace Fortran::lower::omp; + +struct ConstructDecomposition { + ConstructDecomposition(mlir::ModuleOp modOp, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &ev, + llvm::omp::Directive compound, + const List &clauses) + : semaCtx(semaCtx), mod(modOp), eval(ev) { + tomp::ConstructDecompositionT decompose(getOpenMPVersionAttribute(modOp), + *this, compound, + llvm::ArrayRef(clauses)); + output = std::move(decompose.output); + } + + // Given an object, return its base object if one exists. + std::optional getBaseObject(const Object &object) { + return lower::omp::getBaseObject(object, semaCtx); + } + + // Return the iteration variable of the associated loop if any. + std::optional getLoopIterVar() { + if (semantics::Symbol *symbol = getIterationVariableSymbol(eval)) + return Object{symbol, /*designator=*/{}}; + return std::nullopt; + } + + semantics::SemanticsContext &semaCtx; + mlir::ModuleOp mod; + lower::pft::Evaluation &eval; + List output; +}; +} // namespace + +static UnitConstruct mergeConstructs(uint32_t version, + llvm::ArrayRef units) { + tomp::ConstructCompositionT compose(version, units); + return compose.merged; +} + +namespace Fortran::lower::omp { +LLVM_DUMP_METHOD llvm::raw_ostream &operator<<(llvm::raw_ostream &os, + const UnitConstruct &uc) { + os << llvm::omp::getOpenMPDirectiveName(uc.id); + for (auto [index, clause] : llvm::enumerate(uc.clauses)) { + os << (index == 0 ? '\t' : ' '); + os << llvm::omp::getOpenMPClauseName(clause.id); + } + return os; +} + +ConstructQueue buildConstructQueue( + mlir::ModuleOp modOp, Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, const parser::CharBlock &source, + llvm::omp::Directive compound, const List &clauses) { + + List constructs; + + ConstructDecomposition decompose(modOp, semaCtx, eval, compound, clauses); + assert(!decompose.output.empty() && "Construct decomposition failed"); + + llvm::SmallVector loweringUnits; + std::ignore = + llvm::omp::getLeafOrCompositeConstructs(compound, loweringUnits); + uint32_t version = getOpenMPVersionAttribute(modOp); + + int leafIndex = 0; + for (llvm::omp::Directive dir_id : loweringUnits) { + llvm::ArrayRef leafsOrSelf = + llvm::omp::getLeafConstructsOrSelf(dir_id); + size_t numLeafs = leafsOrSelf.size(); + + llvm::ArrayRef toMerge{&decompose.output[leafIndex], + numLeafs}; + auto &uc = constructs.emplace_back(mergeConstructs(version, toMerge)); + + if (!transferLocations(clauses, uc.clauses)) { + // If some clauses are left without source information, use the + // directive's source. + for (auto &clause : uc.clauses) { + if (clause.source.empty()) + clause.source = source; + } + } + leafIndex += numLeafs; + } + + return constructs; +} +} // namespace Fortran::lower::omp diff --git a/flang/lib/Lower/OpenMP/Decomposer.h b/flang/lib/Lower/OpenMP/Decomposer.h new file mode 100644 index 000000000000..f42d8f5c1740 --- /dev/null +++ b/flang/lib/Lower/OpenMP/Decomposer.h @@ -0,0 +1,51 @@ +//===-- Decomposer.h -- Compound directive decomposition ------------------===// +// +// 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 FORTRAN_LOWER_OPENMP_DECOMPOSER_H +#define FORTRAN_LOWER_OPENMP_DECOMPOSER_H + +#include "Clauses.h" +#include "mlir/IR/BuiltinOps.h" +#include "llvm/Frontend/OpenMP/ConstructCompositionT.h" +#include "llvm/Frontend/OpenMP/ConstructDecompositionT.h" +#include "llvm/Frontend/OpenMP/OMP.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { +class raw_ostream; +} + +namespace Fortran { +namespace semantics { +class SemanticsContext; +} +namespace lower::pft { +struct Evaluation; +} +} // namespace Fortran + +namespace Fortran::lower::omp { +using UnitConstruct = tomp::DirectiveWithClauses; +using ConstructQueue = List; + +LLVM_DUMP_METHOD llvm::raw_ostream &operator<<(llvm::raw_ostream &os, + const UnitConstruct &uc); + +// Given a potentially compound construct with a list of clauses that +// apply to it, break it up into individual sub-constructs each with +// the subset of applicable clauses (plus implicit clauses, if any). +// From that create a work queue where each work item corresponds to +// the sub-construct with its clauses. +ConstructQueue buildConstructQueue(mlir::ModuleOp modOp, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::CharBlock &source, + llvm::omp::Directive compound, + const List &clauses); +} // namespace Fortran::lower::omp + +#endif // FORTRAN_LOWER_OPENMP_DECOMPOSER_H diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index f23902d6a823..eaf4b5f997ff 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -15,6 +15,7 @@ #include "ClauseProcessor.h" #include "Clauses.h" #include "DataSharingProcessor.h" +#include "Decomposer.h" #include "DirectivesCommon.h" #include "ReductionProcessor.h" #include "Utils.h" @@ -44,6 +45,13 @@ using namespace Fortran::lower::omp; // Code generation helper functions //===----------------------------------------------------------------------===// +static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item); + static Fortran::lower::pft::Evaluation * getCollapsedLoopEval(Fortran::lower::pft::Evaluation &eval, int collapseValue) { // Return the Evaluation of the innermost collapsed loop, or the current one @@ -460,81 +468,6 @@ markDeclareTarget(mlir::Operation *op, declareTargetOp.setDeclareTarget(deviceType, captureClause); } -/// Split a combined directive into an outer leaf directive and the (possibly -/// combined) rest of the combined directive. Composite directives and -/// non-compound directives are not split, in which case it will return the -/// input directive as its first output and an empty value as its second output. -static std::pair> -splitCombinedDirective(llvm::omp::Directive dir) { - using D = llvm::omp::Directive; - switch (dir) { - case D::OMPD_masked_taskloop: - return {D::OMPD_masked, D::OMPD_taskloop}; - case D::OMPD_masked_taskloop_simd: - return {D::OMPD_masked, D::OMPD_taskloop_simd}; - case D::OMPD_master_taskloop: - return {D::OMPD_master, D::OMPD_taskloop}; - case D::OMPD_master_taskloop_simd: - return {D::OMPD_master, D::OMPD_taskloop_simd}; - case D::OMPD_parallel_do: - return {D::OMPD_parallel, D::OMPD_do}; - case D::OMPD_parallel_do_simd: - return {D::OMPD_parallel, D::OMPD_do_simd}; - case D::OMPD_parallel_masked: - return {D::OMPD_parallel, D::OMPD_masked}; - case D::OMPD_parallel_masked_taskloop: - return {D::OMPD_parallel, D::OMPD_masked_taskloop}; - case D::OMPD_parallel_masked_taskloop_simd: - return {D::OMPD_parallel, D::OMPD_masked_taskloop_simd}; - case D::OMPD_parallel_master: - return {D::OMPD_parallel, D::OMPD_master}; - case D::OMPD_parallel_master_taskloop: - return {D::OMPD_parallel, D::OMPD_master_taskloop}; - case D::OMPD_parallel_master_taskloop_simd: - return {D::OMPD_parallel, D::OMPD_master_taskloop_simd}; - case D::OMPD_parallel_sections: - return {D::OMPD_parallel, D::OMPD_sections}; - case D::OMPD_parallel_workshare: - return {D::OMPD_parallel, D::OMPD_workshare}; - case D::OMPD_target_parallel: - return {D::OMPD_target, D::OMPD_parallel}; - case D::OMPD_target_parallel_do: - return {D::OMPD_target, D::OMPD_parallel_do}; - case D::OMPD_target_parallel_do_simd: - return {D::OMPD_target, D::OMPD_parallel_do_simd}; - case D::OMPD_target_simd: - return {D::OMPD_target, D::OMPD_simd}; - case D::OMPD_target_teams: - return {D::OMPD_target, D::OMPD_teams}; - case D::OMPD_target_teams_distribute: - return {D::OMPD_target, D::OMPD_teams_distribute}; - case D::OMPD_target_teams_distribute_parallel_do: - return {D::OMPD_target, D::OMPD_teams_distribute_parallel_do}; - case D::OMPD_target_teams_distribute_parallel_do_simd: - return {D::OMPD_target, D::OMPD_teams_distribute_parallel_do_simd}; - case D::OMPD_target_teams_distribute_simd: - return {D::OMPD_target, D::OMPD_teams_distribute_simd}; - case D::OMPD_teams_distribute: - return {D::OMPD_teams, D::OMPD_distribute}; - case D::OMPD_teams_distribute_parallel_do: - return {D::OMPD_teams, D::OMPD_distribute_parallel_do}; - case D::OMPD_teams_distribute_parallel_do_simd: - return {D::OMPD_teams, D::OMPD_distribute_parallel_do_simd}; - case D::OMPD_teams_distribute_simd: - return {D::OMPD_teams, D::OMPD_distribute_simd}; - case D::OMPD_parallel_loop: - return {D::OMPD_parallel, D::OMPD_loop}; - case D::OMPD_target_parallel_loop: - return {D::OMPD_target, D::OMPD_parallel_loop}; - case D::OMPD_target_teams_loop: - return {D::OMPD_target, D::OMPD_teams_loop}; - case D::OMPD_teams_loop: - return {D::OMPD_teams, D::OMPD_loop}; - default: - return {dir, std::nullopt}; - } -} - //===----------------------------------------------------------------------===// // Op body generation helper structures and functions //===----------------------------------------------------------------------===// @@ -555,11 +488,6 @@ struct OpWithBodyGenInfo { : converter(converter), symTable(symTable), semaCtx(semaCtx), loc(loc), eval(eval), dir(dir) {} - OpWithBodyGenInfo &setGenNested(bool value) { - genNested = value; - return *this; - } - OpWithBodyGenInfo &setOuterCombined(bool value) { outerCombined = value; return *this; @@ -600,8 +528,6 @@ struct OpWithBodyGenInfo { Fortran::lower::pft::Evaluation &eval; /// [in] leaf directive for which to generate the op body. llvm::omp::Directive dir; - /// [in] whether to generate FIR for nested evaluations - bool genNested = true; /// [in] is this an outer operation - prevents privatization. bool outerCombined = false; /// [in] list of clauses to process. @@ -620,9 +546,13 @@ struct OpWithBodyGenInfo { /// Create the body (block) for an OpenMP Operation. /// -/// \param [in] op - the operation the body belongs to. -/// \param [in] info - options controlling code-gen for the construction. -static void createBodyOfOp(mlir::Operation &op, OpWithBodyGenInfo &info) { +/// \param [in] op - the operation the body belongs to. +/// \param [in] info - options controlling code-gen for the construction. +/// \param [in] queue - work queue with nested constructs. +/// \param [in] item - item in the queue to generate body for. +static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, + const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = info.converter.getFirOpBuilder(); auto insertMarker = [](fir::FirOpBuilder &builder) { @@ -678,7 +608,10 @@ static void createBodyOfOp(mlir::Operation &op, OpWithBodyGenInfo &info) { } } - if (info.genNested) { + if (ConstructQueue::iterator next = std::next(item); next != queue.end()) { + genOMPDispatch(info.converter, info.symTable, info.semaCtx, info.eval, + info.loc, queue, next); + } else { // genFIR(Evaluation&) tries to patch up unterminated blocks, causing // a lot of complications for our approach if the terminator generation // is delayed past this point. Insert a temporary terminator here, then @@ -769,11 +702,12 @@ static void genBodyOfTargetDataOp( Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::omp::TargetDataOp &dataOp, llvm::ArrayRef useDeviceTypes, + Fortran::lower::pft::Evaluation &eval, mlir::omp::TargetDataOp &dataOp, + llvm::ArrayRef useDeviceTypes, llvm::ArrayRef useDeviceLocs, llvm::ArrayRef useDeviceSymbols, - const mlir::Location ¤tLocation) { + const mlir::Location ¤tLocation, const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Region ®ion = dataOp.getRegion(); @@ -826,8 +760,13 @@ static void genBodyOfTargetDataOp( // Set the insertion point after the marker. firOpBuilder.setInsertionPointAfter(undefMarker.getDefiningOp()); - if (genNested) + + if (ConstructQueue::iterator next = std::next(item); next != queue.end()) { + genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, + next); + } else { genNestedEvaluations(converter, eval); + } } // This functions creates a block for the body of the targetOp's region. It adds @@ -836,12 +775,13 @@ static void genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, + Fortran::lower::pft::Evaluation &eval, mlir::omp::TargetOp &targetOp, llvm::ArrayRef mapSyms, llvm::ArrayRef mapSymLocs, llvm::ArrayRef mapSymTypes, - const mlir::Location ¤tLocation) { + const mlir::Location ¤tLocation, + const ConstructQueue &queue, ConstructQueue::iterator item) { assert(mapSymTypes.size() == mapSymLocs.size()); fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); @@ -983,15 +923,22 @@ genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, // Create the insertion point after the marker. firOpBuilder.setInsertionPointAfter(undefMarker.getDefiningOp()); - if (genNested) + + if (ConstructQueue::iterator next = std::next(item); next != queue.end()) { + genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, + next); + } else { genNestedEvaluations(converter, eval); + } } template -static OpTy genOpWithBody(OpWithBodyGenInfo &info, Args &&...args) { +static OpTy genOpWithBody(const OpWithBodyGenInfo &info, + const ConstructQueue &queue, + ConstructQueue::iterator item, Args &&...args) { auto op = info.converter.getFirOpBuilder().create( info.loc, std::forward(args)...); - createBodyOfOp(*op, info); + createBodyOfOp(*op, info, queue, item); return op; } @@ -1276,7 +1223,8 @@ static mlir::omp::BarrierOp genBarrierOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const ConstructQueue &queue, ConstructQueue::iterator item) { return converter.getFirOpBuilder().create(loc); } @@ -1284,8 +1232,9 @@ static mlir::omp::CriticalOp genCriticalOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses, + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item, const std::optional &name) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::FlatSymbolRefAttr nameAttr; @@ -1308,17 +1257,17 @@ genCriticalOp(Fortran::lower::AbstractConverter &converter, return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, - llvm::omp::Directive::OMPD_critical) - .setGenNested(genNested), - nameAttr); + llvm::omp::Directive::OMPD_critical), + queue, item, nameAttr); } static mlir::omp::DistributeOp genDistributeOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Distribute construct"); return nullptr; } @@ -1328,7 +1277,8 @@ genFlushOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ObjectList &objects, const List &clauses) { + const ObjectList &objects, const List &clauses, + const ConstructQueue &queue, ConstructQueue::iterator item) { llvm::SmallVector operandRange; genFlushClauses(converter, semaCtx, objects, clauses, loc, operandRange); @@ -1340,12 +1290,13 @@ static mlir::omp::MasterOp genMasterOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, - llvm::omp::Directive::OMPD_master) - .setGenNested(genNested)); + llvm::omp::Directive::OMPD_master), + queue, item); } static mlir::omp::OrderedOp @@ -1353,7 +1304,8 @@ genOrderedOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses) { + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "OMPD_ordered"); return nullptr; } @@ -1362,25 +1314,25 @@ static mlir::omp::OrderedRegionOp genOrderedRegionOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { mlir::omp::OrderedRegionClauseOps clauseOps; genOrderedRegionClauses(converter, semaCtx, clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, - llvm::omp::Directive::OMPD_ordered) - .setGenNested(genNested), - clauseOps); + llvm::omp::Directive::OMPD_ordered), + queue, item, clauseOps); } static mlir::omp::ParallelOp genParallelOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses, - bool outerCombined = false) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item, bool outerCombined = false) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; mlir::omp::ParallelClauseOps clauseOps; @@ -1399,14 +1351,14 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, OpWithBodyGenInfo genInfo = OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_parallel) - .setGenNested(genNested) .setOuterCombined(outerCombined) .setClauses(&clauses) .setReductions(&reductionSyms, &reductionTypes) .setGenRegionEntryCb(reductionCallback); if (!enableDelayedPrivatization) - return genOpWithBody(genInfo, clauseOps); + return genOpWithBody(genInfo, queue, item, + clauseOps); bool privatize = !outerCombined; DataSharingProcessor dsp(converter, semaCtx, clauses, eval, @@ -1454,19 +1406,23 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, }; genInfo.setGenRegionEntryCb(genRegionEntryCB).setDataSharingProcessor(&dsp); - return genOpWithBody(genInfo, clauseOps); + return genOpWithBody(genInfo, queue, item, clauseOps); } static mlir::omp::SectionOp genSectionOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { + // Currently only private/firstprivate clause is handled, and + // all privatization is done within `omp.section` operations. return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_section) - .setGenNested(genNested)); + .setClauses(&clauses), + queue, item); } static mlir::omp::SectionsOp @@ -1474,12 +1430,77 @@ genSectionsOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const mlir::omp::SectionsClauseOps &clauseOps) { - return genOpWithBody( + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { + mlir::omp::SectionsClauseOps clauseOps; + genSectionsClauses(converter, semaCtx, clauses, loc, clauseOps); + + auto &builder = converter.getFirOpBuilder(); + + // Insert privatizations before SECTIONS + symTable.pushScope(); + DataSharingProcessor dsp(converter, semaCtx, clauses, eval); + dsp.processStep1(); + + List nonDsaClauses; + List lastprivates; + + for (const Clause &clause : clauses) { + if (clause.id == llvm::omp::Clause::OMPC_lastprivate) { + lastprivates.push_back(&std::get(clause.u)); + } else { + switch (clause.id) { + case llvm::omp::Clause::OMPC_firstprivate: + case llvm::omp::Clause::OMPC_private: + case llvm::omp::Clause::OMPC_shared: + break; + default: + nonDsaClauses.push_back(clause); + } + } + } + + // SECTIONS construct. + mlir::omp::SectionsOp sectionsOp = genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_sections) - .setGenNested(false), - clauseOps); + .setClauses(&nonDsaClauses), + queue, item, clauseOps); + + if (!lastprivates.empty()) { + mlir::Region §ionsBody = sectionsOp.getRegion(); + assert(sectionsBody.hasOneBlock()); + mlir::Block &body = sectionsBody.front(); + + auto lastSectionOp = llvm::find_if( + llvm::reverse(body.getOperations()), [](const mlir::Operation &op) { + return llvm::isa(op); + }); + assert(lastSectionOp != body.rend()); + + for (const clause::Lastprivate *lastp : lastprivates) { + builder.setInsertionPoint( + lastSectionOp->getRegion(0).back().getTerminator()); + mlir::OpBuilder::InsertPoint insp = builder.saveInsertionPoint(); + const auto &objList = std::get(lastp->t); + for (const Object &object : objList) { + Fortran::semantics::Symbol *sym = object.id(); + converter.copyHostAssociateVar(*sym, &insp); + } + } + } + + // Perform DataSharingProcessor's step2 out of SECTIONS + builder.setInsertionPointAfter(sectionsOp.getOperation()); + dsp.processStep2(sectionsOp, false); + // Emit implicit barrier to synchronize threads and avoid data + // races on post-update of lastprivate variables when `nowait` + // clause is present. + if (clauseOps.nowaitAttr && !lastprivates.empty()) + builder.create(loc); + + symTable.popScope(); + return sectionsOp; } static mlir::omp::SimdOp @@ -1487,7 +1508,8 @@ genSimdOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses) { + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); DataSharingProcessor dsp(converter, semaCtx, clauses, eval); dsp.processStep1(); @@ -1522,7 +1544,8 @@ genSimdOp(Fortran::lower::AbstractConverter &converter, *nestedEval, llvm::omp::Directive::OMPD_simd) .setClauses(&clauses) .setDataSharingProcessor(&dsp) - .setGenRegionEntryCb(ivCallback)); + .setGenRegionEntryCb(ivCallback), + queue, item); return simdOp; } @@ -1531,26 +1554,26 @@ static mlir::omp::SingleOp genSingleOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { mlir::omp::SingleClauseOps clauseOps; genSingleClauses(converter, semaCtx, clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_single) - .setGenNested(genNested) .setClauses(&clauses), - clauseOps); + queue, item, clauseOps); } static mlir::omp::TargetOp genTargetOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses, - bool outerCombined = false) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item, bool outerCombined = false) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; @@ -1657,8 +1680,8 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::visitAllSymbols(eval, captureImplicitMap); auto targetOp = firOpBuilder.create(loc, clauseOps); - genBodyOfTargetOp(converter, symTable, semaCtx, eval, genNested, targetOp, - mapSyms, mapLocs, mapTypes, loc); + genBodyOfTargetOp(converter, symTable, semaCtx, eval, targetOp, mapSyms, + mapLocs, mapTypes, loc, queue, item); return targetOp; } @@ -1666,8 +1689,9 @@ static mlir::omp::TargetDataOp genTargetDataOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TargetDataClauseOps clauseOps; llvm::SmallVector useDeviceTypes; @@ -1679,9 +1703,9 @@ genTargetDataOp(Fortran::lower::AbstractConverter &converter, auto targetDataOp = converter.getFirOpBuilder().create(loc, clauseOps); - genBodyOfTargetDataOp(converter, symTable, semaCtx, eval, genNested, - targetDataOp, useDeviceTypes, useDeviceLocs, - useDeviceSyms, loc); + genBodyOfTargetDataOp(converter, symTable, semaCtx, eval, targetDataOp, + useDeviceTypes, useDeviceLocs, useDeviceSyms, loc, + queue, item); return targetDataOp; } @@ -1690,8 +1714,9 @@ static OpTy genTargetEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - mlir::Location loc, - const List &clauses) { + mlir::Location loc, const List &clauses, + const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; @@ -1718,8 +1743,9 @@ static mlir::omp::TaskOp genTaskOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TaskClauseOps clauseOps; genTaskClauses(converter, semaCtx, stmtCtx, clauses, loc, clauseOps); @@ -1727,26 +1753,25 @@ genTaskOp(Fortran::lower::AbstractConverter &converter, return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_task) - .setGenNested(genNested) .setClauses(&clauses), - clauseOps); + queue, item, clauseOps); } static mlir::omp::TaskgroupOp genTaskgroupOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { mlir::omp::TaskgroupClauseOps clauseOps; genTaskgroupClauses(converter, semaCtx, clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_taskgroup) - .setGenNested(genNested) .setClauses(&clauses), - clauseOps); + queue, item, clauseOps); } static mlir::omp::TaskloopOp @@ -1754,7 +1779,8 @@ genTaskloopOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses) { + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Taskloop construct"); } @@ -1763,7 +1789,8 @@ genTaskwaitOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses) { + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { mlir::omp::TaskwaitClauseOps clauseOps; genTaskwaitClauses(converter, semaCtx, clauses, loc, clauseOps); return converter.getFirOpBuilder().create(loc, @@ -1774,7 +1801,8 @@ static mlir::omp::TaskyieldOp genTaskyieldOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const ConstructQueue &queue, ConstructQueue::iterator item) { return converter.getFirOpBuilder().create(loc); } @@ -1782,9 +1810,9 @@ static mlir::omp::TeamsOp genTeamsOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses, - bool outerCombined = false) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item, bool outerCombined = false) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TeamsClauseOps clauseOps; genTeamsClauses(converter, semaCtx, stmtCtx, clauses, loc, clauseOps); @@ -1792,10 +1820,9 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter, return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_teams) - .setGenNested(genNested) .setOuterCombined(outerCombined) .setClauses(&clauses), - clauseOps); + queue, item, clauseOps); } static mlir::omp::WsloopOp @@ -1803,7 +1830,8 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses) { + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); DataSharingProcessor dsp(converter, semaCtx, clauses, eval); dsp.processStep1(); @@ -1844,7 +1872,8 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, .setClauses(&clauses) .setDataSharingProcessor(&dsp) .setReductions(&reductionSyms, &reductionTypes) - .setGenRegionEntryCb(ivCallback)); + .setGenRegionEntryCb(ivCallback), + queue, item); return wsloopOp; } @@ -1852,13 +1881,13 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, // Code generation functions for composite constructs //===----------------------------------------------------------------------===// -static void -genCompositeDistributeParallelDo(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const List &clauses, - mlir::Location loc) { +static void genCompositeDistributeParallelDo( + Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO"); } @@ -1866,8 +1895,9 @@ static void genCompositeDistributeParallelDoSimd( Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, const List &clauses, - mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO SIMD"); } @@ -1876,7 +1906,9 @@ genCompositeDistributeSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &clauses, mlir::Location loc) { + mlir::Location loc, const List &clauses, + const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE SIMD"); } @@ -1884,8 +1916,9 @@ static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &clauses, - mlir::Location loc) { + mlir::Location loc, const List &clauses, + const ConstructQueue &queue, + ConstructQueue::iterator item) { ClauseProcessor cp(converter, semaCtx, clauses); cp.processTODO( @@ -1898,7 +1931,7 @@ static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, // When support for vectorization is enabled, then we need to add handling of // if clause. Currently if clause can be skipped because we always assume // SIMD length = 1. - genWsloopOp(converter, symTable, semaCtx, eval, loc, clauses); + genWsloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); } static void @@ -1906,10 +1939,128 @@ genCompositeTaskloopSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &clauses, mlir::Location loc) { + mlir::Location loc, const List &clauses, + const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Composite TASKLOOP SIMD"); } +//===----------------------------------------------------------------------===// +// Dispatch +//===----------------------------------------------------------------------===// + +static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { + assert(item != queue.end()); + const List &clauses = item->clauses; + + switch (llvm::omp::Directive dir = item->id) { + case llvm::omp::Directive::OMPD_distribute: + genDistributeOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_do: + genWsloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_loop: + case llvm::omp::Directive::OMPD_masked: + case llvm::omp::Directive::OMPD_tile: + case llvm::omp::Directive::OMPD_unroll: + TODO(loc, "Unhandled loop directive (" + + llvm::omp::getOpenMPDirectiveName(dir) + ")"); + break; + case llvm::omp::Directive::OMPD_master: + genMasterOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_ordered: + genOrderedRegionOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_parallel: + genParallelOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item, + /*outerCombined=*/false); + break; + case llvm::omp::Directive::OMPD_sections: + genSectionsOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_simd: + genSimdOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_single: + genSingleOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_target: + genTargetOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item, + /*outerCombined=*/false); + break; + case llvm::omp::Directive::OMPD_target_data: + genTargetDataOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_target_enter_data: + genTargetEnterExitUpdateDataOp( + converter, symTable, semaCtx, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_target_exit_data: + genTargetEnterExitUpdateDataOp( + converter, symTable, semaCtx, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_target_update: + genTargetEnterExitUpdateDataOp( + converter, symTable, semaCtx, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_task: + genTaskOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_taskgroup: + genTaskgroupOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_taskloop: + genTaskloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_teams: + genTeamsOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + // case llvm::omp::Directive::OMPD_workdistribute: + case llvm::omp::Directive::OMPD_workshare: + // FIXME: Workshare is not a commonly used OpenMP construct, an + // implementation for this feature will come later. For the codes + // that use this construct, add a single construct for now. + genSingleOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + // Composite constructs + case llvm::omp::Directive::OMPD_distribute_parallel_do: + genCompositeDistributeParallelDo(converter, symTable, semaCtx, eval, loc, + clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: + genCompositeDistributeParallelDoSimd(converter, symTable, semaCtx, eval, + loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_distribute_simd: + genCompositeDistributeSimd(converter, symTable, semaCtx, eval, loc, clauses, + queue, item); + break; + case llvm::omp::Directive::OMPD_do_simd: + genCompositeDoSimd(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_taskloop_simd: + genCompositeTaskloopSimd(converter, symTable, semaCtx, eval, loc, clauses, + queue, item); + break; + default: + break; + } +} + //===----------------------------------------------------------------------===// // OpenMPDeclarativeConstruct visitors //===----------------------------------------------------------------------===// @@ -2020,36 +2171,47 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, semaCtx); mlir::Location currentLocation = converter.genLocation(directive.source); + ConstructQueue queue{ + buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, + eval, directive.source, directive.v, clauses)}; + switch (directive.v) { default: break; case llvm::omp::Directive::OMPD_barrier: - genBarrierOp(converter, symTable, semaCtx, eval, currentLocation); + genBarrierOp(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); break; case llvm::omp::Directive::OMPD_taskwait: - genTaskwaitOp(converter, symTable, semaCtx, eval, currentLocation, clauses); + genTaskwaitOp(converter, symTable, semaCtx, eval, currentLocation, clauses, + queue, queue.begin()); break; case llvm::omp::Directive::OMPD_taskyield: - genTaskyieldOp(converter, symTable, semaCtx, eval, currentLocation); + genTaskyieldOp(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); break; case llvm::omp::Directive::OMPD_target_data: - genTargetDataOp(converter, symTable, semaCtx, eval, /*genNested=*/true, - currentLocation, clauses); + genTargetDataOp(converter, symTable, semaCtx, eval, currentLocation, + clauses, queue, queue.begin()); break; case llvm::omp::Directive::OMPD_target_enter_data: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses); + converter, symTable, semaCtx, currentLocation, clauses, queue, + queue.begin()); break; case llvm::omp::Directive::OMPD_target_exit_data: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses); + converter, symTable, semaCtx, currentLocation, clauses, queue, + queue.begin()); break; case llvm::omp::Directive::OMPD_target_update: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses); + converter, symTable, semaCtx, currentLocation, clauses, queue, + queue.begin()); break; case llvm::omp::Directive::OMPD_ordered: - genOrderedOp(converter, symTable, semaCtx, eval, currentLocation, clauses); + genOrderedOp(converter, symTable, semaCtx, eval, currentLocation, clauses, + queue, queue.begin()); break; } } @@ -2073,8 +2235,12 @@ genOMP(Fortran::lower::AbstractConverter &converter, [&](auto &&s) { return makeClause(s.v, semaCtx); }) : List{}; mlir::Location currentLocation = converter.genLocation(verbatim.source); + + ConstructQueue queue{buildConstructQueue( + converter.getFirOpBuilder().getModule(), semaCtx, eval, verbatim.source, + llvm::omp::Directive::OMPD_flush, clauses)}; genFlushOp(converter, symTable, semaCtx, eval, currentLocation, objects, - clauses); + clauses, queue, queue.begin()); } static void @@ -2217,75 +2383,15 @@ genOMP(Fortran::lower::AbstractConverter &converter, } } - std::optional nextDir = origDirective; - bool outermostLeafConstruct = true; - while (nextDir) { - llvm::omp::Directive leafDir; - std::tie(leafDir, nextDir) = splitCombinedDirective(*nextDir); - const bool genNested = !nextDir; - const bool outerCombined = outermostLeafConstruct && nextDir.has_value(); - switch (leafDir) { - case llvm::omp::Directive::OMPD_master: - // 2.16 MASTER construct. - genMasterOp(converter, symTable, semaCtx, eval, genNested, - currentLocation); - break; - case llvm::omp::Directive::OMPD_ordered: - // 2.17.9 ORDERED construct. - genOrderedRegionOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_parallel: - // 2.6 PARALLEL construct. - genParallelOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses, outerCombined); - break; - case llvm::omp::Directive::OMPD_single: - // 2.8.2 SINGLE construct. - genSingleOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_target: - // 2.12.5 TARGET construct. - genTargetOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses, outerCombined); - break; - case llvm::omp::Directive::OMPD_target_data: - // 2.12.2 TARGET DATA construct. - genTargetDataOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_task: - // 2.10.1 TASK construct. - genTaskOp(converter, symTable, semaCtx, eval, genNested, currentLocation, - clauses); - break; - case llvm::omp::Directive::OMPD_taskgroup: - // 2.17.6 TASKGROUP construct. - genTaskgroupOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_teams: - // 2.7 TEAMS construct. - // FIXME Pass the outerCombined argument or rename it to better describe - // what it represents if it must always be `false` in this context. - genTeamsOp(converter, symTable, semaCtx, eval, genNested, currentLocation, - clauses); - break; - case llvm::omp::Directive::OMPD_workshare: - // 2.8.3 WORKSHARE construct. - // FIXME: Workshare is not a commonly used OpenMP construct, an - // implementation for this feature will come later. For the codes - // that use this construct, add a single construct for now. - genSingleOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - default: - llvm_unreachable("Unexpected block construct"); - break; - } - outermostLeafConstruct = false; - } + llvm::omp::Directive directive = + std::get(beginBlockDirective.t).v; + const parser::CharBlock &source = + std::get(beginBlockDirective.t).source; + ConstructQueue queue{ + buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, + eval, source, directive, clauses)}; + genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); } static void @@ -2298,10 +2404,15 @@ genOMP(Fortran::lower::AbstractConverter &converter, std::get(criticalConstruct.t); List clauses = makeClauses(std::get(cd.t), semaCtx); + + ConstructQueue queue{buildConstructQueue( + converter.getFirOpBuilder().getModule(), semaCtx, eval, cd.source, + llvm::omp::Directive::OMPD_critical, clauses)}; + const auto &name = std::get>(cd.t); mlir::Location currentLocation = converter.getCurrentLocation(); - genCriticalOp(converter, symTable, semaCtx, eval, /*genNested=*/true, - currentLocation, clauses, name); + genCriticalOp(converter, symTable, semaCtx, eval, currentLocation, clauses, + queue, queue.begin(), name); } static void @@ -2322,14 +2433,6 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, std::get(loopConstruct.t); List clauses = makeClauses( std::get(beginLoopDirective.t), semaCtx); - mlir::Location currentLocation = - converter.genLocation(beginLoopDirective.source); - const auto origDirective = - std::get(beginLoopDirective.t).v; - - assert(llvm::omp::loopConstructSet.test(origDirective) && - "Expected loop construct"); - if (auto &endLoopDirective = std::get>( loopConstruct.t)) { @@ -2338,101 +2441,18 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, semaCtx)); } - std::optional nextDir = origDirective; - while (nextDir) { - llvm::omp::Directive leafDir; - std::tie(leafDir, nextDir) = splitCombinedDirective(*nextDir); - if (llvm::omp::compositeConstructSet.test(leafDir)) { - assert(!nextDir && "Composite construct cannot be split"); - switch (leafDir) { - case llvm::omp::Directive::OMPD_distribute_parallel_do: - // 2.9.4.3 DISTRIBUTE PARALLEL Worksharing-Loop construct. - genCompositeDistributeParallelDo(converter, symTable, semaCtx, eval, - clauses, currentLocation); - break; - case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: - // 2.9.4.4 DISTRIBUTE PARALLEL Worksharing-Loop SIMD construct. - genCompositeDistributeParallelDoSimd(converter, symTable, semaCtx, eval, - clauses, currentLocation); - break; - case llvm::omp::Directive::OMPD_distribute_simd: - // 2.9.4.2 DISTRIBUTE SIMD construct. - genCompositeDistributeSimd(converter, symTable, semaCtx, eval, clauses, - currentLocation); - break; - case llvm::omp::Directive::OMPD_do_simd: - // 2.9.3.2 Worksharing-Loop SIMD construct. - genCompositeDoSimd(converter, symTable, semaCtx, eval, clauses, - currentLocation); - break; - case llvm::omp::Directive::OMPD_taskloop_simd: - // 2.10.3 TASKLOOP SIMD construct. - genCompositeTaskloopSimd(converter, symTable, semaCtx, eval, clauses, - currentLocation); - break; - default: - llvm_unreachable("Unexpected composite construct"); - } - } else { - const bool genNested = !nextDir; - switch (leafDir) { - case llvm::omp::Directive::OMPD_distribute: - // 2.9.4.1 DISTRIBUTE construct. - genDistributeOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_do: - // 2.9.2 Worksharing-Loop construct. - genWsloopOp(converter, symTable, semaCtx, eval, currentLocation, - clauses); - break; - case llvm::omp::Directive::OMPD_parallel: - // 2.6 PARALLEL construct. - // FIXME This is not necessarily always the outer leaf construct of a - // combined construct in this constext (e.g. distribute parallel do). - // Maybe rename the argument if it represents something else or - // initialize it properly. - genParallelOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses, - /*outerCombined=*/true); - break; - case llvm::omp::Directive::OMPD_simd: - // 2.9.3.1 SIMD construct. - genSimdOp(converter, symTable, semaCtx, eval, currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_target: - // 2.12.5 TARGET construct. - genTargetOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses, /*outerCombined=*/true); - break; - case llvm::omp::Directive::OMPD_taskloop: - // 2.10.2 TASKLOOP construct. - genTaskloopOp(converter, symTable, semaCtx, eval, currentLocation, - clauses); - break; - case llvm::omp::Directive::OMPD_teams: - // 2.7 TEAMS construct. - // FIXME This is not necessarily always the outer leaf construct of a - // combined construct in this constext (e.g. target teams distribute). - // Maybe rename the argument if it represents something else or - // initialize it properly. - genTeamsOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses, /*outerCombined=*/true); - break; - case llvm::omp::Directive::OMPD_loop: - case llvm::omp::Directive::OMPD_masked: - case llvm::omp::Directive::OMPD_master: - case llvm::omp::Directive::OMPD_tile: - case llvm::omp::Directive::OMPD_unroll: - TODO(currentLocation, "Unhandled loop directive (" + - llvm::omp::getOpenMPDirectiveName(leafDir) + - ")"); - break; - default: - llvm_unreachable("Unexpected loop construct"); - } - } - } + mlir::Location currentLocation = + converter.genLocation(beginLoopDirective.source); + + llvm::omp::Directive directive = + std::get(beginLoopDirective.t).v; + const parser::CharBlock &source = + std::get(beginLoopDirective.t).source; + ConstructQueue queue{ + buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, + eval, source, directive, clauses)}; + genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); } static void @@ -2441,8 +2461,12 @@ genOMP(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPSectionConstruct §ionConstruct) { - // SECTION constructs are handled as a part of SECTIONS. - llvm_unreachable("Unexpected standalone OMP SECTION"); + mlir::Location loc = converter.getCurrentLocation(); + ConstructQueue queue{buildConstructQueue( + converter.getFirOpBuilder().getModule(), semaCtx, eval, + sectionConstruct.source, llvm::omp::Directive::OMPD_section, {})}; + genSectionOp(converter, symTable, semaCtx, eval, loc, + /*clauses=*/{}, queue, queue.begin()); } static void @@ -2461,77 +2485,17 @@ genOMP(Fortran::lower::AbstractConverter &converter, clauses.append(makeClauses( std::get(endSectionsDirective.t), semaCtx)); - - // Process clauses before optional omp.parallel, so that new variables are - // allocated outside of the parallel region mlir::Location currentLocation = converter.getCurrentLocation(); - mlir::omp::SectionsClauseOps clauseOps; - genSectionsClauses(converter, semaCtx, clauses, currentLocation, clauseOps); - - // Parallel wrapper of PARALLEL SECTIONS construct - llvm::omp::Directive dir = - std::get(beginSectionsDirective.t) - .v; - if (dir == llvm::omp::Directive::OMPD_parallel_sections) { - genParallelOp(converter, symTable, semaCtx, eval, - /*genNested=*/false, currentLocation, clauses, - /*outerCombined=*/true); - } - - // Insert privatizations before SECTIONS - symTable.pushScope(); - DataSharingProcessor dsp(converter, semaCtx, clauses, eval); - dsp.processStep1(); - - // SECTIONS construct. - mlir::omp::SectionsOp sectionsOp = genSectionsOp( - converter, symTable, semaCtx, eval, currentLocation, clauseOps); - - // Generate nested SECTION operations recursively. - const auto §ionBlocks = - std::get(sectionsConstruct.t); - auto &firOpBuilder = converter.getFirOpBuilder(); - auto ip = firOpBuilder.saveInsertionPoint(); - mlir::omp::SectionOp lastSectionOp; - for (const auto &[nblock, neval] : - llvm::zip(sectionBlocks.v, eval.getNestedEvaluations())) { - symTable.pushScope(); - lastSectionOp = genSectionOp(converter, symTable, semaCtx, neval, - /*genNested=*/true, currentLocation); - symTable.popScope(); - firOpBuilder.restoreInsertionPoint(ip); - } - - // For `omp.sections`, lastprivatized variables occur in - // lexically final `omp.section` operation. - bool hasLastPrivate = false; - if (lastSectionOp) { - for (const Clause &clause : clauses) { - if (const auto *lastPrivate = - std::get_if(&clause.u)) { - hasLastPrivate = true; - firOpBuilder.setInsertionPoint( - lastSectionOp.getRegion().back().getTerminator()); - mlir::OpBuilder::InsertPoint lastPrivIP = - converter.getFirOpBuilder().saveInsertionPoint(); - const auto &objList = std::get<1>(lastPrivate->t); - for (const Object &obj : objList) { - Fortran::semantics::Symbol *sym = obj.id(); - converter.copyHostAssociateVar(*sym, &lastPrivIP); - } - } - } - } - // Perform DataSharingProcessor's step2 out of SECTIONS - firOpBuilder.setInsertionPointAfter(sectionsOp.getOperation()); - dsp.processStep2(sectionsOp, false); - // Emit implicit barrier to synchronize threads and avoid data - // races on post-update of lastprivate variables when `nowait` - // clause is present. - if (clauseOps.nowaitAttr && hasLastPrivate) - firOpBuilder.create(converter.getCurrentLocation()); - symTable.popScope(); + llvm::omp::Directive directive = + std::get(beginSectionsDirective.t).v; + const parser::CharBlock &source = + std::get(beginSectionsDirective.t).source; + ConstructQueue queue{ + buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, + eval, source, directive, clauses)}; + genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); } static void genOMP(Fortran::lower::AbstractConverter &converter, diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp index eed63b226133..cb1d1a5a7f3d 100644 --- a/flang/lib/Lower/OpenMP/Utils.cpp +++ b/flang/lib/Lower/OpenMP/Utils.cpp @@ -51,12 +51,6 @@ int64_t getCollapseValue(const List &clauses) { return 1; } -uint32_t getOpenMPVersion(mlir::ModuleOp mod) { - if (mlir::Attribute verAttr = mod->getAttr("omp.version")) - return llvm::cast(verAttr).getVersion(); - llvm_unreachable("Expecting OpenMP version attribute in module"); -} - void genObjectList(const ObjectList &objects, Fortran::lower::AbstractConverter &converter, llvm::SmallVectorImpl &operands) { diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h index 8fbb18fa8656..345ce55620ee 100644 --- a/flang/lib/Lower/OpenMP/Utils.h +++ b/flang/lib/Lower/OpenMP/Utils.h @@ -93,7 +93,6 @@ void gatherFuncAndVarSyms( llvm::SmallVectorImpl &symbolAndClause); int64_t getCollapseValue(const List &clauses); -uint32_t getOpenMPVersion(mlir::ModuleOp mod); Fortran::semantics::Symbol * getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject); diff --git a/flang/test/Lower/OpenMP/default-clause-byref.f90 b/flang/test/Lower/OpenMP/default-clause-byref.f90 index 62ba67e5962f..7cc2bc2e0c71 100644 --- a/flang/test/Lower/OpenMP/default-clause-byref.f90 +++ b/flang/test/Lower/OpenMP/default-clause-byref.f90 @@ -161,12 +161,12 @@ subroutine nested_default_clause_tests !CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFnested_default_clause_testsEz"} !CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: omp.parallel { +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} !CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref !CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref -!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} -!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_testsEz"} !CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFnested_default_clause_testsEk"} @@ -221,6 +221,7 @@ subroutine nested_default_clause_tests !CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} !CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} !CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) diff --git a/flang/test/Lower/OpenMP/default-clause.f90 b/flang/test/Lower/OpenMP/default-clause.f90 index a90f0f4ef5f8..843ee6bb7910 100644 --- a/flang/test/Lower/OpenMP/default-clause.f90 +++ b/flang/test/Lower/OpenMP/default-clause.f90 @@ -160,12 +160,12 @@ end program default_clause_lowering !CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFnested_default_clause_test1Ez"} !CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFnested_default_clause_test1Ez"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: omp.parallel { +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_test1Ey"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_test1Ey"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_test1Ex"} !CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_test1Ex"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref !CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref -!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_test1Ey"} -!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_test1Ey"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_test1Ez"} !CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_test1Ez"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFnested_default_clause_test1Ek"} diff --git a/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 b/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 index b7f11c8c722f..e6ee75c8a5be 100644 --- a/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 +++ b/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 @@ -145,10 +145,10 @@ end subroutine !CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) !CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg2"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) !CHECK: omp.parallel { -!CHECK-DAG: %[[CLONE1:.*]] = fir.alloca i32 {bindc_name = "arg1" -!CHECK-DAG: %[[CLONE1_DECL:.*]]:2 = hlfir.declare %[[CLONE1]] {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK-DAG: %[[CLONE2:.*]] = fir.alloca i32 {bindc_name = "arg2" !CHECK-DAG: %[[CLONE2_DECL:.*]]:2 = hlfir.declare %[[CLONE2]] {uniq_name = "_QFmult_lastprivate_int2Earg2"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK-DAG: %[[CLONE1:.*]] = fir.alloca i32 {bindc_name = "arg1" +!CHECK-DAG: %[[CLONE1_DECL:.*]]:2 = hlfir.declare %[[CLONE1]] {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: omp.wsloop { !CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} { diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h index daef02bcfc9a..07c95497b7a4 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h @@ -178,6 +178,12 @@ template using ListT = llvm::SmallVector; // provide their own specialization that conforms to the above requirements. template struct ObjectT; +// By default, object equality is only determined by its identity. +template +bool operator==(const ObjectT &o1, const ObjectT &o2) { + return o1.id() == o2.id(); +} + template using ObjectListT = ListT>; using DirectiveName = llvm::omp::Directive; @@ -264,6 +270,32 @@ struct ReductionIdentifierT { template // using IteratorT = ListT>; + +template +std::enable_if_t operator==(const T &a, + const T &b) { + return true; +} +template +std::enable_if_t operator==(const T &a, + const T &b) { + return true; +} +template +std::enable_if_t operator==(const T &a, + const T &b) { + return a.v == b.v; +} +template +std::enable_if_t operator==(const T &a, + const T &b) { + return a.t == b.t; +} +template +std::enable_if_t operator==(const T &a, + const T &b) { + return a.u == b.u; +} } // namespace type template using ListT = type::ListT; @@ -285,6 +317,8 @@ ListT makeList(ContainerTy &&container, FunctionTy &&func) { } namespace clause { +using type::operator==; + // V5.2: [8.3.1] `assumption` clauses template // struct AbsentT { @@ -726,7 +760,7 @@ struct LinearT { ENUM(LinearModifier, Ref, Val, Uval); using TupleTrait = std::true_type; - // Step == nullptr means 1. + // Step == nullopt means 1. std::tuple t; @@ -1142,9 +1176,11 @@ struct UsesAllocatorsT { using MemSpace = E; using TraitsArray = ObjectT; using Allocator = E; - using AllocatorSpec = - std::tuple; // Not a spec name - using Allocators = ListT; // Not a spec name + struct AllocatorSpec { // Not a spec name + using TupleTrait = std::true_type; + std::tuple t; + }; + using Allocators = ListT; // Not a spec name using WrapperTrait = std::true_type; Allocators v; }; @@ -1232,9 +1268,10 @@ using UnionOfAllClausesT = typename type::Union< // UnionClausesT, // WrapperClausesT // >::type; - } // namespace clause +using type::operator==; + // The variant wrapper that encapsulates all possible specific clauses. // The `Extras` arguments are additional types representing local extensions // to the clause set, e.g. @@ -1260,6 +1297,11 @@ struct ClauseT { VariantTy u; }; +template struct DirectiveWithClauses { + llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown; + tomp::type::ListT clauses; +}; + } // namespace tomp #undef OPT diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h new file mode 100644 index 000000000000..7a4ed92a1070 --- /dev/null +++ b/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h @@ -0,0 +1,403 @@ +//===- ConstructCompositionT.h -- Composing compound constructs -----------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// Given a list of leaf construct, each with a set of clauses, generate the +// compound construct whose leaf constructs are the given list, and whose clause +// list is the merged lists of individual leaf clauses. +// +// *** At the moment it assumes that the individual constructs and their clauses +// *** are a subset of those created by splitting a valid compound construct. +//===----------------------------------------------------------------------===// +#ifndef LLVM_FRONTEND_OPENMP_CONSTRUCTCOMPOSITIONT_H +#define LLVM_FRONTEND_OPENMP_CONSTRUCTCOMPOSITIONT_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Frontend/OpenMP/ClauseT.h" +#include "llvm/Frontend/OpenMP/OMP.h" + +#include +#include +#include +#include +#include +#include + +namespace tomp { +template struct ConstructCompositionT { + using ClauseTy = ClauseType; + + using TypeTy = typename ClauseTy::TypeTy; + using IdTy = typename ClauseTy::IdTy; + using ExprTy = typename ClauseTy::ExprTy; + + ConstructCompositionT(uint32_t version, + llvm::ArrayRef> leafs); + + DirectiveWithClauses merged; + +private: + // Use an ordered container, since we beed to maintain the order in which + // clauses are added to it. This is to avoid non-deterministic output. + using ClauseSet = ListT; + + enum class Presence { + All, // Clause is preesnt on all leaf constructs that allow it. + Some, // Clause is present on some, but not on all constructs. + None, // Clause is absent on all constructs. + }; + + template + ClauseTy makeClause(llvm::omp::Clause clauseId, S &&specific) { + return ClauseTy{clauseId, std::move(specific)}; + } + + llvm::omp::Directive + makeCompound(llvm::ArrayRef> parts); + + Presence checkPresence(llvm::omp::Clause clauseId); + + // There are clauses that need special handling: + // 1. "if": the "directive-name-modifier" on the merged clause may need + // to be set appropriately. + // 2. "reduction": implies "privateness" of all objects (incompatible + // with "shared"); there are rules for merging modifiers + void mergeIf(); + void mergeReduction(); + void mergeDSA(); + + uint32_t version; + llvm::ArrayRef> leafs; + + // clause id -> set of leaf constructs that contain it + std::unordered_map clausePresence; + // clause id -> set of instances of that clause + std::unordered_map clauseSets; +}; + +template +ConstructCompositionT::ConstructCompositionT( + uint32_t version, llvm::ArrayRef> leafs) + : version(version), leafs(leafs) { + // Merge the list of constructs with clauses into a compound construct + // with a single list of clauses. + // The intended use of this function is in splitting compound constructs, + // while preserving composite constituent constructs: + // Step 1: split compound construct into leaf constructs. + // Step 2: identify composite sub-construct, and merge the constituent leafs. + // + // *** At the moment it assumes that the individual constructs and their + // *** clauses are a subset of those created by splitting a valid compound + // *** construct. + // + // 1. Deduplicate clauses + // - exact duplicates: e.g. shared(x) shared(x) -> shared(x) + // - special cases of clauses differing in modifier: + // (a) reduction: inscan + (none|default) = inscan + // (b) reduction: task + (none|default) = task + // (c) combine repeated "if" clauses if possible + // 2. Merge DSA clauses: e.g. private(x) private(y) -> private(x, y). + // 3. Resolve potential DSA conflicts (typically due to implied clauses). + + if (leafs.empty()) + return; + + merged.id = makeCompound(leafs); + + // Populate the two maps: + for (const auto &[index, leaf] : llvm::enumerate(leafs)) { + for (const auto &clause : leaf.clauses) { + // Update clausePresence. + auto &pset = clausePresence[clause.id]; + if (pset.size() < leafs.size()) + pset.resize(leafs.size()); + pset.set(index); + // Update clauseSets. + ClauseSet &cset = clauseSets[clause.id]; + if (!llvm::is_contained(cset, clause)) + cset.push_back(clause); + } + } + + mergeIf(); + mergeReduction(); + mergeDSA(); + + // Fir the rest of the clauses, just copy them. + for (auto &[id, clauses] : clauseSets) { + // Skip clauses we've already dealt with. + switch (id) { + case llvm::omp::Clause::OMPC_if: + case llvm::omp::Clause::OMPC_reduction: + case llvm::omp::Clause::OMPC_shared: + case llvm::omp::Clause::OMPC_private: + case llvm::omp::Clause::OMPC_firstprivate: + case llvm::omp::Clause::OMPC_lastprivate: + continue; + default: + break; + } + llvm::append_range(merged.clauses, clauses); + } +} + +template +llvm::omp::Directive ConstructCompositionT::makeCompound( + llvm::ArrayRef> parts) { + llvm::SmallVector dirIds; + llvm::transform(parts, std::back_inserter(dirIds), + [](auto &&dwc) { return dwc.id; }); + + return llvm::omp::getCompoundConstruct(dirIds); +} + +template +auto ConstructCompositionT::checkPresence(llvm::omp::Clause clauseId) + -> Presence { + auto found = clausePresence.find(clauseId); + if (found == clausePresence.end()) + return Presence::None; + + bool OnAll = true, OnNone = true; + for (const auto &[index, leaf] : llvm::enumerate(leafs)) { + if (!llvm::omp::isAllowedClauseForDirective(leaf.id, clauseId, version)) + continue; + + if (found->second.test(index)) + OnNone = false; + else + OnAll = false; + } + + if (OnNone) + return Presence::None; + if (OnAll) + return Presence::All; + return Presence::Some; +} + +template void ConstructCompositionT::mergeIf() { + using IfTy = tomp::clause::IfT; + // Deal with the "if" clauses. If it's on all leafs that allow it, then it + // will apply to the compound construct. Otherwise it will apply to the + // single (assumed) leaf construct. + // This assumes that the "if" clauses have the same expression. + Presence presence = checkPresence(llvm::omp::Clause::OMPC_if); + if (presence == Presence::None) + return; + + const ClauseTy &some = *clauseSets[llvm::omp::Clause::OMPC_if].begin(); + const auto &someIf = std::get(some.u); + + if (presence == Presence::All) { + // Create "if" without "directive-name-modifier". + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_if, + IfTy{{/*DirectiveNameModifier=*/std::nullopt, + /*IfExpression=*/std::get( + someIf.t)}})); + } else { + // Find out where it's present and create "if" with the corresponding + // "directive-name-modifier". + int Idx = clausePresence[llvm::omp::Clause::OMPC_if].find_first(); + assert(Idx >= 0); + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_if, + IfTy{{/*DirectiveNameModifier=*/leafs[Idx].id, + /*IfExpression=*/std::get( + someIf.t)}})); + } +} + +template void ConstructCompositionT::mergeReduction() { + Presence presence = checkPresence(llvm::omp::Clause::OMPC_reduction); + if (presence == Presence::None) + return; + + using ReductionTy = tomp::clause::ReductionT; + using ModifierTy = typename ReductionTy::ReductionModifier; + using IdentifiersTy = typename ReductionTy::ReductionIdentifiers; + using ListTy = typename ReductionTy::List; + // There are exceptions on which constructs "reduction" may appear + // (specifically "parallel", and "teams"). Assume that if "reduction" + // is present, it can be applied to the compound construct. + + // What's left is to see if there are any modifiers present. Again, + // assume that there are no conflicting modifiers. + // There can be, however, multiple reductions on different objects. + auto equal = [](const ClauseTy &red1, const ClauseTy &red2) { + // Extract actual reductions. + const auto r1 = std::get(red1.u); + const auto r2 = std::get(red2.u); + // Compare everything except modifiers. + if (std::get(r1.t) != std::get(r2.t)) + return false; + if (std::get(r1.t) != std::get(r2.t)) + return false; + return true; + }; + + auto getModifier = [](const ClauseTy &clause) { + const ReductionTy &red = std::get(clause.u); + return std::get>(red.t); + }; + + const ClauseSet &reductions = clauseSets[llvm::omp::Clause::OMPC_reduction]; + std::unordered_set visited; + while (reductions.size() != visited.size()) { + typename ClauseSet::const_iterator first; + + // Find first non-visited reduction. + for (first = reductions.begin(); first != reductions.end(); ++first) { + if (visited.count(&*first)) + continue; + visited.insert(&*first); + break; + } + + std::optional modifier = getModifier(*first); + + // Visit all other reductions that are "equal" (with respect to the + // definition above) to "first". Collect modifiers. + for (auto iter = std::next(first); iter != reductions.end(); ++iter) { + if (!equal(*first, *iter)) + continue; + visited.insert(&*iter); + if (!modifier || *modifier == ModifierTy::Default) + modifier = getModifier(*iter); + } + + const auto &firstRed = std::get(first->u); + merged.clauses.emplace_back(makeClause( + llvm::omp::Clause::OMPC_reduction, + ReductionTy{ + {/*ReductionModifier=*/modifier, + /*ReductionIdentifiers=*/std::get(firstRed.t), + /*List=*/std::get(firstRed.t)}})); + } +} + +template void ConstructCompositionT::mergeDSA() { + using ObjectTy = tomp::type::ObjectT; + + // Resolve data-sharing attributes. + enum DSA : int { + None = 0, + Shared = 1 << 0, + Private = 1 << 1, + FirstPrivate = 1 << 2, + LastPrivate = 1 << 3, + LastPrivateConditional = 1 << 4, + }; + + // Use ordered containers to avoid non-deterministic output. + llvm::SmallVector> objectDsa; + + auto getDsa = [&](const ObjectTy &object) -> std::pair & { + auto found = llvm::find_if(objectDsa, [&](std::pair &p) { + return p.first.id() == object.id(); + }); + if (found != objectDsa.end()) + return *found; + return objectDsa.emplace_back(object, DSA::None); + }; + + using SharedTy = tomp::clause::SharedT; + using PrivateTy = tomp::clause::PrivateT; + using FirstprivateTy = tomp::clause::FirstprivateT; + using LastprivateTy = tomp::clause::LastprivateT; + + // Visit clauses that affect DSA. + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_shared]) { + for (auto &object : std::get(clause.u).v) + getDsa(object).second |= DSA::Shared; + } + + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_private]) { + for (auto &object : std::get(clause.u).v) + getDsa(object).second |= DSA::Private; + } + + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_firstprivate]) { + for (auto &object : std::get(clause.u).v) + getDsa(object).second |= DSA::FirstPrivate; + } + + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_lastprivate]) { + using ModifierTy = typename LastprivateTy::LastprivateModifier; + using ListTy = typename LastprivateTy::List; + const auto &lastp = std::get(clause.u); + for (auto &object : std::get(lastp.t)) { + auto &mod = std::get>(lastp.t); + if (mod && *mod == ModifierTy::Conditional) { + getDsa(object).second |= DSA::LastPrivateConditional; + } else { + getDsa(object).second |= DSA::LastPrivate; + } + } + } + + // Check reductions as well, clear "shared" if set. + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_reduction]) { + using ReductionTy = tomp::clause::ReductionT; + using ListTy = typename ReductionTy::List; + for (auto &object : std::get(std::get(clause.u).t)) + getDsa(object).second &= ~DSA::Shared; + } + + tomp::ListT privateObj, sharedObj, firstpObj, lastpObj, lastpcObj; + for (auto &[object, dsa] : objectDsa) { + if (dsa & + (DSA::FirstPrivate | DSA::LastPrivate | DSA::LastPrivateConditional)) { + if (dsa & DSA::FirstPrivate) + firstpObj.push_back(object); // no else + if (dsa & DSA::LastPrivateConditional) + lastpcObj.push_back(object); + else if (dsa & DSA::LastPrivate) + lastpObj.push_back(object); + } else if (dsa & DSA::Private) { + privateObj.push_back(object); + } else if (dsa & DSA::Shared) { + sharedObj.push_back(object); + } + } + + // Materialize each clause. + if (!privateObj.empty()) { + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_private, + PrivateTy{/*List=*/std::move(privateObj)})); + } + if (!sharedObj.empty()) { + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_shared, + SharedTy{/*List=*/std::move(sharedObj)})); + } + if (!firstpObj.empty()) { + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_firstprivate, + FirstprivateTy{/*List=*/std::move(firstpObj)})); + } + if (!lastpObj.empty()) { + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_lastprivate, + LastprivateTy{{/*LastprivateModifier=*/std::nullopt, + /*List=*/std::move(lastpObj)}})); + } + if (!lastpcObj.empty()) { + auto conditional = LastprivateTy::LastprivateModifier::Conditional; + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_lastprivate, + LastprivateTy{{/*LastprivateModifier=*/conditional, + /*List=*/std::move(lastpcObj)}})); + } +} +} // namespace tomp + +#endif // LLVM_FRONTEND_OPENMP_CONSTRUCTCOMPOSITIONT_H diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h new file mode 100644 index 000000000000..37c88f0fa07b --- /dev/null +++ b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h @@ -0,0 +1,1161 @@ +//===- ConstructDecompositionT.h -- Decomposing compound constructs -------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// Given a compound construct with a set of clauses, generate the list of +// constituent leaf constructs, each with a list of clauses that apply to it. +// +// Note: Clauses that are not originally present, but that are implied by the +// OpenMP spec are materialized, and are present in the output. +// +// Note: Composite constructs will also be broken up into leaf constructs. +// If composite constructs require processing as a whole, the lists of clauses +// for each leaf constituent should be merged. +//===----------------------------------------------------------------------===// +#ifndef LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H +#define LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Frontend/OpenMP/ClauseT.h" +#include "llvm/Frontend/OpenMP/OMP.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline llvm::ArrayRef getWorksharing() { + static llvm::omp::Directive worksharing[] = { + llvm::omp::Directive::OMPD_do, llvm::omp::Directive::OMPD_for, + llvm::omp::Directive::OMPD_scope, llvm::omp::Directive::OMPD_sections, + llvm::omp::Directive::OMPD_single, llvm::omp::Directive::OMPD_workshare, + }; + return worksharing; +} + +static inline llvm::ArrayRef getWorksharingLoop() { + static llvm::omp::Directive worksharingLoop[] = { + llvm::omp::Directive::OMPD_do, + llvm::omp::Directive::OMPD_for, + }; + return worksharingLoop; +} + +namespace detail { +template +typename std::remove_reference_t::iterator +find_unique(Container &&container, Predicate &&pred) { + auto first = std::find_if(container.begin(), container.end(), pred); + if (first == container.end()) + return first; + auto second = std::find_if(std::next(first), container.end(), pred); + if (second == container.end()) + return first; + return container.end(); +} + +} // namespace detail + +namespace tomp { + +// ClauseType - Either instance of ClauseT, or a type derived from ClauseT. +// +// This is the clause representation in the code using this infrastructure. +// +// HelperType - A class that implements two member functions: +// +// // Return the base object of the given object, if any. +// std::optional getBaseObject(const Object &object) const +// // Return the iteration variable of the outermost loop associated +// // with the construct being worked on, if any. +// std::optional getLoopIterVar() const +template +struct ConstructDecompositionT { + using ClauseTy = ClauseType; + + using TypeTy = typename ClauseTy::TypeTy; + using IdTy = typename ClauseTy::IdTy; + using ExprTy = typename ClauseTy::ExprTy; + using HelperTy = HelperType; + using ObjectTy = tomp::ObjectT; + + using ClauseSet = std::unordered_set; + + ConstructDecompositionT(uint32_t ver, HelperType &helper, + llvm::omp::Directive dir, + llvm::ArrayRef clauses) + : version(ver), construct(dir), helper(helper) { + for (const ClauseTy &clause : clauses) + nodes.push_back(&clause); + + bool success = split(); + if (!success) + return; + + // Copy the individual leaf directives with their clauses to the + // output list. Copy by value, since we don't own the storage + // with the input clauses, and the internal representation uses + // clause addresses. + for (auto &leaf : leafs) { + output.push_back({leaf.id}); + auto &out = output.back(); + for (const ClauseTy *c : leaf.clauses) + out.clauses.push_back(*c); + } + } + + tomp::ListT> output; + +private: + bool split(); + + struct LeafReprInternal { + llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown; + tomp::type::ListT clauses; + }; + + LeafReprInternal *findDirective(llvm::omp::Directive dirId) { + auto found = llvm::find_if( + leafs, [&](const LeafReprInternal &leaf) { return leaf.id == dirId; }); + return found != leafs.end() ? &*found : nullptr; + } + + ClauseSet *findClausesWith(const ObjectTy &object) { + if (auto found = syms.find(object.id()); found != syms.end()) + return &found->second; + return nullptr; + } + + template + ClauseTy *makeClause(llvm::omp::Clause clauseId, S &&specific) { + implicit.push_back(ClauseTy{clauseId, std::move(specific)}); + return &implicit.back(); + } + + void addClauseSymsToMap(const ObjectTy &object, const ClauseTy *); + void addClauseSymsToMap(const tomp::ObjectListT &objects, + const ClauseTy *); + void addClauseSymsToMap(const TypeTy &item, const ClauseTy *); + void addClauseSymsToMap(const ExprTy &item, const ClauseTy *); + void addClauseSymsToMap(const tomp::clause::MapT &item, + const ClauseTy *); + + template + void addClauseSymsToMap(const std::optional &item, const ClauseTy *); + template + void addClauseSymsToMap(const tomp::ListT &item, const ClauseTy *); + template + void addClauseSymsToMap(const std::tuple &item, const ClauseTy *, + std::index_sequence = {}); + template + std::enable_if_t>, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + template + std::enable_if_t::EmptyTrait::value, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + template + std::enable_if_t::IncompleteTrait::value, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + template + std::enable_if_t::WrapperTrait::value, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + template + std::enable_if_t::TupleTrait::value, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + template + std::enable_if_t::UnionTrait::value, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + // Apply a clause to the only directive that allows it. If there are no + // directives that allow it, or if there is more that one, do not apply + // anything and return false, otherwise return true. + bool applyToUnique(const ClauseTy *node); + + // Apply a clause to the first directive in given range that allows it. + // If such a directive does not exist, return false, otherwise return true. + template + bool applyToFirst(const ClauseTy *node, llvm::iterator_range range); + + // Apply a clause to the innermost directive that allows it. If such a + // directive does not exist, return false, otherwise return true. + bool applyToInnermost(const ClauseTy *node); + + // Apply a clause to the outermost directive that allows it. If such a + // directive does not exist, return false, otherwise return true. + bool applyToOutermost(const ClauseTy *node); + + template + bool applyIf(const ClauseTy *node, Predicate shouldApply); + + bool applyToAll(const ClauseTy *node); + + template + bool applyClause(Clause &&clause, const ClauseTy *node); + + bool applyClause(const tomp::clause::CollapseT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::PrivateT &clause, + const ClauseTy *); + bool + applyClause(const tomp::clause::FirstprivateT &clause, + const ClauseTy *); + bool + applyClause(const tomp::clause::LastprivateT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::SharedT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::DefaultT &clause, + const ClauseTy *); + bool + applyClause(const tomp::clause::ThreadLimitT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::OrderT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::AllocateT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::ReductionT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::IfT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::LinearT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::NowaitT &clause, + const ClauseTy *); + + uint32_t version; + llvm::omp::Directive construct; + HelperType &helper; + ListT leafs; + tomp::ListT nodes; + std::list implicit; // Container for materialized implicit clauses. + // Inserting must preserve element addresses. + std::unordered_map syms; + std::unordered_set mapBases; +}; + +// Deduction guide +template +ConstructDecompositionT(uint32_t, HelperType &, llvm::omp::Directive, + llvm::ArrayRef) + -> ConstructDecompositionT; + +template +void ConstructDecompositionT::addClauseSymsToMap(const ObjectTy &object, + const ClauseTy *node) { + syms[object.id()].insert(node); +} + +template +void ConstructDecompositionT::addClauseSymsToMap( + const tomp::ObjectListT &objects, const ClauseTy *node) { + for (auto &object : objects) + syms[object.id()].insert(node); +} + +template +void ConstructDecompositionT::addClauseSymsToMap(const TypeTy &item, + const ClauseTy *node) { + // Nothing to do for types. +} + +template +void ConstructDecompositionT::addClauseSymsToMap(const ExprTy &item, + const ClauseTy *node) { + // Nothing to do for expressions. +} + +template +void ConstructDecompositionT::addClauseSymsToMap( + const tomp::clause::MapT &item, + const ClauseTy *node) { + auto &objects = std::get>(item.t); + addClauseSymsToMap(objects, node); + for (auto &object : objects) { + if (auto base = helper.getBaseObject(object)) + mapBases.insert(base->id()); + } +} + +template +template +void ConstructDecompositionT::addClauseSymsToMap( + const std::optional &item, const ClauseTy *node) { + if (item) + addClauseSymsToMap(*item, node); +} + +template +template +void ConstructDecompositionT::addClauseSymsToMap( + const tomp::ListT &item, const ClauseTy *node) { + for (auto &s : item) + addClauseSymsToMap(s, node); +} + +template +template +void ConstructDecompositionT::addClauseSymsToMap( + const std::tuple &item, const ClauseTy *node, + std::index_sequence) { + (void)node; // Silence strange warning from GCC. + (addClauseSymsToMap(std::get(item), node), ...); +} + +template +template +std::enable_if_t>, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + // Nothing to do for enums. +} + +template +template +std::enable_if_t::EmptyTrait::value, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + // Nothing to do for an empty class. +} + +template +template +std::enable_if_t::IncompleteTrait::value, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + // Nothing to do for an incomplete class (they're empty). +} + +template +template +std::enable_if_t::WrapperTrait::value, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + addClauseSymsToMap(item.v, node); +} + +template +template +std::enable_if_t::TupleTrait::value, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + constexpr size_t tuple_size = + std::tuple_size_v>; + addClauseSymsToMap(item.t, node, std::make_index_sequence{}); +} + +template +template +std::enable_if_t::UnionTrait::value, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + std::visit([&](auto &&s) { addClauseSymsToMap(s, node); }, item.u); +} + +// Apply a clause to the only directive that allows it. If there are no +// directives that allow it, or if there is more that one, do not apply +// anything and return false, otherwise return true. +template +bool ConstructDecompositionT::applyToUnique(const ClauseTy *node) { + auto unique = detail::find_unique(leafs, [=](const auto &dirInfo) { + return llvm::omp::isAllowedClauseForDirective(dirInfo.id, node->id, + version); + }); + + if (unique != leafs.end()) { + unique->clauses.push_back(node); + return true; + } + return false; +} + +// Apply a clause to the first directive in given range that allows it. +// If such a directive does not exist, return false, otherwise return true. +template +template +bool ConstructDecompositionT::applyToFirst( + const ClauseTy *node, llvm::iterator_range range) { + if (range.empty()) + return false; + + for (auto &leaf : range) { + if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version)) + continue; + leaf.clauses.push_back(node); + return true; + } + return false; +} + +// Apply a clause to the innermost directive that allows it. If such a +// directive does not exist, return false, otherwise return true. +template +bool ConstructDecompositionT::applyToInnermost(const ClauseTy *node) { + return applyToFirst(node, llvm::reverse(leafs)); +} + +// Apply a clause to the outermost directive that allows it. If such a +// directive does not exist, return false, otherwise return true. +template +bool ConstructDecompositionT::applyToOutermost(const ClauseTy *node) { + return applyToFirst(node, llvm::iterator_range(leafs)); +} + +template +template +bool ConstructDecompositionT::applyIf(const ClauseTy *node, + Predicate shouldApply) { + bool applied = false; + for (auto &leaf : leafs) { + if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version)) + continue; + if (!shouldApply(leaf)) + continue; + leaf.clauses.push_back(node); + applied = true; + } + + return applied; +} + +template +bool ConstructDecompositionT::applyToAll(const ClauseTy *node) { + return applyIf(node, [](auto) { return true; }); +} + +template +template +bool ConstructDecompositionT::applyClause(Clause &&clause, + const ClauseTy *node) { + // The default behavior is to find the unique directive to which the + // given clause may be applied. If there are no such directives, or + // if there are multiple ones, flag an error. + // From "OpenMP Application Programming Interface", Version 5.2: + // S Some clauses are permitted only on a single leaf construct of the + // S combined or composite construct, in which case the effect is as if + // S the clause is applied to that specific construct. (p339, 31-33) + if (applyToUnique(node)) + return true; + + return false; +} + +// COLLAPSE +// [5.2:93:20-21] +// Directives: distribute, do, for, loop, simd, taskloop +// +// [5.2:339:35] +// (35) The collapse clause is applied once to the combined or composite +// construct. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::CollapseT &clause, + const ClauseTy *node) { + // Apply "collapse" to the innermost directive. If it's not one that + // allows it flag an error. + if (!leafs.empty()) { + auto &last = leafs.back(); + + if (llvm::omp::isAllowedClauseForDirective(last.id, node->id, version)) { + last.clauses.push_back(node); + return true; + } + } + + return false; +} + +// PRIVATE +// [5.2:111:5-7] +// Directives: distribute, do, for, loop, parallel, scope, sections, simd, +// single, target, task, taskloop, teams +// +// [5.2:340:1-2] +// (1) The effect of the 1 private clause is as if it is applied only to the +// innermost leaf construct that permits it. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::PrivateT &clause, + const ClauseTy *node) { + return applyToInnermost(node); +} + +// FIRSTPRIVATE +// [5.2:112:5-7] +// Directives: distribute, do, for, parallel, scope, sections, single, target, +// task, taskloop, teams +// +// [5.2:340:3-20] +// (3) The effect of the firstprivate clause is as if it is applied to one or +// more leaf constructs as follows: +// (5) To the distribute construct if it is among the constituent constructs; +// (6) To the teams construct if it is among the constituent constructs and the +// distribute construct is not; +// (8) To a worksharing construct that accepts the clause if one is among the +// constituent constructs; +// (9) To the taskloop construct if it is among the constituent constructs; +// (10) To the parallel construct if it is among the constituent constructs and +// neither a taskloop construct nor a worksharing construct that accepts +// the clause is among them; +// (12) To the target construct if it is among the constituent constructs and +// the same list item neither appears in a lastprivate clause nor is the +// base variable or base pointer of a list item that appears in a map +// clause. +// +// (15) If the parallel construct is among the constituent constructs and the +// effect is not as if the firstprivate clause is applied to it by the above +// rules, then the effect is as if the shared clause with the same list item is +// applied to the parallel construct. +// (17) If the teams construct is among the constituent constructs and the +// effect is not as if the firstprivate clause is applied to it by the above +// rules, then the effect is as if the shared clause with the same list item is +// applied to the teams construct. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::FirstprivateT &clause, + const ClauseTy *node) { + bool applied = false; + + // [5.2:340:3-6] + auto dirDistribute = findDirective(llvm::omp::OMPD_distribute); + auto dirTeams = findDirective(llvm::omp::OMPD_teams); + if (dirDistribute != nullptr) { + dirDistribute->clauses.push_back(node); + applied = true; + // [5.2:340:17] + if (dirTeams != nullptr) { + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/clause.v}); + dirTeams->clauses.push_back(shared); + } + } else if (dirTeams != nullptr) { + dirTeams->clauses.push_back(node); + applied = true; + } + + // [5.2:340:8] + auto findWorksharing = [&]() { + auto worksharing = getWorksharing(); + for (auto &leaf : leafs) { + auto found = llvm::find(worksharing, leaf.id); + if (found != std::end(worksharing)) + return &leaf; + } + return static_cast(nullptr); + }; + + auto dirWorksharing = findWorksharing(); + if (dirWorksharing != nullptr) { + dirWorksharing->clauses.push_back(node); + applied = true; + } + + // [5.2:340:9] + auto dirTaskloop = findDirective(llvm::omp::OMPD_taskloop); + if (dirTaskloop != nullptr) { + dirTaskloop->clauses.push_back(node); + applied = true; + } + + // [5.2:340:10] + auto dirParallel = findDirective(llvm::omp::OMPD_parallel); + if (dirParallel != nullptr) { + if (dirTaskloop == nullptr && dirWorksharing == nullptr) { + dirParallel->clauses.push_back(node); + applied = true; + } else { + // [5.2:340:15] + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/clause.v}); + dirParallel->clauses.push_back(shared); + } + } + + // [5.2:340:12] + auto inLastprivate = [&](const ObjectTy &object) { + if (ClauseSet *set = findClausesWith(object)) { + return llvm::find_if(*set, [](const ClauseTy *c) { + return c->id == llvm::omp::Clause::OMPC_lastprivate; + }) != set->end(); + } + return false; + }; + + auto dirTarget = findDirective(llvm::omp::OMPD_target); + if (dirTarget != nullptr) { + tomp::ObjectListT objects; + llvm::copy_if( + clause.v, std::back_inserter(objects), [&](const ObjectTy &object) { + return !inLastprivate(object) && !mapBases.count(object.id()); + }); + if (!objects.empty()) { + auto *firstp = makeClause( + llvm::omp::Clause::OMPC_firstprivate, + tomp::clause::FirstprivateT{/*List=*/objects}); + dirTarget->clauses.push_back(firstp); + applied = true; + } + } + + // "task" is not handled by any of the cases above. + if (auto dirTask = findDirective(llvm::omp::OMPD_task)) { + dirTask->clauses.push_back(node); + applied = true; + } + + return applied; +} + +// LASTPRIVATE +// [5.2:115:7-8] +// Directives: distribute, do, for, loop, sections, simd, taskloop +// +// [5.2:340:21-30] +// (21) The effect of the lastprivate clause is as if it is applied to all leaf +// constructs that permit the clause. +// (22) If the parallel construct is among the constituent constructs and the +// list item is not also specified in the firstprivate clause, then the effect +// of the lastprivate clause is as if the shared clause with the same list item +// is applied to the parallel construct. +// (24) If the teams construct is among the constituent constructs and the list +// item is not also specified in the firstprivate clause, then the effect of the +// lastprivate clause is as if the shared clause with the same list item is +// applied to the teams construct. +// (27) If the target construct is among the constituent constructs and the list +// item is not the base variable or base pointer of a list item that appears in +// a map clause, the effect of the lastprivate clause is as if the same list +// item appears in a map clause with a map-type of tofrom. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::LastprivateT &clause, + const ClauseTy *node) { + bool applied = false; + + // [5.2:340:21] + applied = applyToAll(node); + if (!applied) + return false; + + auto inFirstprivate = [&](const ObjectTy &object) { + if (ClauseSet *set = findClausesWith(object)) { + return llvm::find_if(*set, [](const ClauseTy *c) { + return c->id == llvm::omp::Clause::OMPC_firstprivate; + }) != set->end(); + } + return false; + }; + + auto &objects = std::get>(clause.t); + + // Prepare list of objects that could end up in a "shared" clause. + tomp::ObjectListT sharedObjects; + llvm::copy_if( + objects, std::back_inserter(sharedObjects), + [&](const ObjectTy &object) { return !inFirstprivate(object); }); + + if (!sharedObjects.empty()) { + // [5.2:340:22] + if (auto dirParallel = findDirective(llvm::omp::OMPD_parallel)) { + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/sharedObjects}); + dirParallel->clauses.push_back(shared); + applied = true; + } + + // [5.2:340:24] + if (auto dirTeams = findDirective(llvm::omp::OMPD_teams)) { + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/sharedObjects}); + dirTeams->clauses.push_back(shared); + applied = true; + } + } + + // [5.2:340:27] + if (auto dirTarget = findDirective(llvm::omp::OMPD_target)) { + tomp::ObjectListT tofrom; + llvm::copy_if( + objects, std::back_inserter(tofrom), + [&](const ObjectTy &object) { return !mapBases.count(object.id()); }); + + if (!tofrom.empty()) { + using MapType = + typename tomp::clause::MapT::MapType; + auto *map = + makeClause(llvm::omp::Clause::OMPC_map, + tomp::clause::MapT{ + {/*MapType=*/MapType::Tofrom, + /*MapTypeModifier=*/std::nullopt, + /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, + /*LocatorList=*/std::move(tofrom)}}); + dirTarget->clauses.push_back(map); + applied = true; + } + } + + return applied; +} + +// SHARED +// [5.2:110:5-6] +// Directives: parallel, task, taskloop, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::SharedT &clause, + const ClauseTy *node) { + // [5.2:340:31] + return applyToAll(node); +} + +// DEFAULT +// [5.2:109:5-6] +// Directives: parallel, task, taskloop, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::DefaultT &clause, + const ClauseTy *node) { + // [5.2:340:31] + return applyToAll(node); +} + +// THREAD_LIMIT +// [5.2:277:14-15] +// Directives: target, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::ThreadLimitT &clause, + const ClauseTy *node) { + // [5.2:340:31] + return applyToAll(node); +} + +// ORDER +// [5.2:234:3-4] +// Directives: distribute, do, for, loop, simd +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::OrderT &clause, + const ClauseTy *node) { + // [5.2:340:31] + return applyToAll(node); +} + +// ALLOCATE +// [5.2:178:7-9] +// Directives: allocators, distribute, do, for, parallel, scope, sections, +// single, target, task, taskgroup, taskloop, teams +// +// [5.2:340:33-35] +// (33) The effect of the allocate clause is as if it is applied to all leaf +// constructs that permit the clause and to which a data-sharing attribute +// clause that may create a private copy of the same list item is applied. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::AllocateT &clause, + const ClauseTy *node) { + // This one needs to be applied at the end, once we know which clauses are + // assigned to which leaf constructs. + + // [5.2:340:33] + auto canMakePrivateCopy = [](llvm::omp::Clause id) { + switch (id) { + case llvm::omp::Clause::OMPC_firstprivate: + case llvm::omp::Clause::OMPC_lastprivate: + case llvm::omp::Clause::OMPC_private: + return true; + default: + return false; + } + }; + + bool applied = applyIf(node, [&](const auto &leaf) { + return llvm::any_of(leaf.clauses, [&](const ClauseTy *n) { + return canMakePrivateCopy(n->id); + }); + }); + + return applied; +} + +// REDUCTION +// [5.2:134:17-18] +// Directives: do, for, loop, parallel, scope, sections, simd, taskloop, teams +// +// [5.2:340:36-37], [5.2:341:1-13] +// (36) The effect of the reduction clause is as if it is applied to all leaf +// constructs that permit the clause, except for the following constructs: +// (1) The parallel construct, when combined with the sections, +// worksharing-loop, loop, or taskloop construct; and +// (3) The teams construct, when combined with the loop construct. +// (4) For the parallel and teams constructs above, the effect of the reduction +// clause instead is as if each list item or, for any list item that is an array +// item, its corresponding base array or base pointer appears in a shared clause +// for the construct. +// (6) If the task reduction-modifier is specified, the effect is as if it only +// modifies the behavior of the reduction clause on the innermost leaf construct +// that accepts the modifier (see Section 5.5.8). +// (8) If the inscan reduction-modifier is specified, the effect is as if it +// modifies the behavior of the reduction clause on all constructs of the +// combined construct to which the clause is applied and that accept the +// modifier. +// (10) If a list item in a reduction clause on a combined target construct does +// not have the same base variable or base pointer as a list item in a map +// clause on the construct, then the effect is as if the list item in the +// reduction clause appears as a list item in a map clause with a map-type of +// tofrom. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::ReductionT &clause, + const ClauseTy *node) { + using ReductionTy = tomp::clause::ReductionT; + + // [5.2:340:36], [5.2:341:1], [5.2:341:3] + bool applyToParallel = true, applyToTeams = true; + + auto dirParallel = findDirective(llvm::omp::Directive::OMPD_parallel); + if (dirParallel) { + auto exclusions = llvm::concat( + getWorksharingLoop(), tomp::ListT{ + llvm::omp::Directive::OMPD_loop, + llvm::omp::Directive::OMPD_sections, + llvm::omp::Directive::OMPD_taskloop, + }); + auto present = [&](llvm::omp::Directive id) { + return findDirective(id) != nullptr; + }; + + if (llvm::any_of(exclusions, present)) + applyToParallel = false; + } + + auto dirTeams = findDirective(llvm::omp::Directive::OMPD_teams); + if (dirTeams) { + // The only exclusion is OMPD_loop. + if (findDirective(llvm::omp::Directive::OMPD_loop)) + applyToTeams = false; + } + + using ReductionModifier = typename ReductionTy::ReductionModifier; + using ReductionIdentifiers = typename ReductionTy::ReductionIdentifiers; + + auto &objects = std::get>(clause.t); + auto &modifier = std::get>(clause.t); + + // Apply the reduction clause first to all directives according to the spec. + // If the reduction was applied at least once, proceed with the data sharing + // side-effects. + bool applied = false; + + // [5.2:341:6], [5.2:341:8] + auto isValidModifier = [](llvm::omp::Directive dir, ReductionModifier mod, + bool alreadyApplied) { + switch (mod) { + case ReductionModifier::Inscan: + // According to [5.2:135:11-13], "inscan" only applies to + // worksharing-loop, worksharing-loop-simd, or "simd" constructs. + return dir == llvm::omp::Directive::OMPD_simd || + llvm::is_contained(getWorksharingLoop(), dir); + case ReductionModifier::Task: + if (alreadyApplied) + return false; + // According to [5.2:135:16-18], "task" only applies to "parallel" and + // worksharing constructs. + return dir == llvm::omp::Directive::OMPD_parallel || + llvm::is_contained(getWorksharing(), dir); + case ReductionModifier::Default: + return true; + } + llvm_unreachable("Unexpected modifier"); + }; + + auto *unmodified = makeClause( + llvm::omp::Clause::OMPC_reduction, + ReductionTy{ + {/*ReductionModifier=*/std::nullopt, + /*ReductionIdentifiers=*/std::get(clause.t), + /*List=*/objects}}); + + ReductionModifier effective = + modifier.has_value() ? *modifier : ReductionModifier::Default; + bool effectiveApplied = false; + // Walk over the leaf constructs starting from the innermost, and apply + // the clause as required by the spec. + for (auto &leaf : llvm::reverse(leafs)) { + if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version)) + continue; + if (!applyToParallel && &leaf == dirParallel) + continue; + if (!applyToTeams && &leaf == dirTeams) + continue; + // Some form of the clause will be applied past this point. + if (isValidModifier(leaf.id, effective, effectiveApplied)) { + // Apply clause with modifier. + leaf.clauses.push_back(node); + effectiveApplied = true; + } else { + // Apply clause without modifier. + leaf.clauses.push_back(unmodified); + } + applied = true; + } + + if (!applied) + return false; + + tomp::ObjectListT sharedObjects; + llvm::transform(objects, std::back_inserter(sharedObjects), + [&](const ObjectTy &object) { + auto maybeBase = helper.getBaseObject(object); + return maybeBase ? *maybeBase : object; + }); + + // [5.2:341:4] + if (!sharedObjects.empty()) { + if (dirParallel && !applyToParallel) { + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/sharedObjects}); + dirParallel->clauses.push_back(shared); + } + if (dirTeams && !applyToTeams) { + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/sharedObjects}); + dirTeams->clauses.push_back(shared); + } + } + + // [5.2:341:10] + auto dirTarget = findDirective(llvm::omp::Directive::OMPD_target); + if (dirTarget && leafs.size() > 1) { + tomp::ObjectListT tofrom; + llvm::copy_if(objects, std::back_inserter(tofrom), + [&](const ObjectTy &object) { + if (auto maybeBase = helper.getBaseObject(object)) + return !mapBases.count(maybeBase->id()); + return !mapBases.count(object.id()); // XXX is this ok? + }); + if (!tofrom.empty()) { + using MapType = + typename tomp::clause::MapT::MapType; + auto *map = makeClause( + llvm::omp::Clause::OMPC_map, + tomp::clause::MapT{ + {/*MapType=*/MapType::Tofrom, /*MapTypeModifier=*/std::nullopt, + /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, + /*LocatorList=*/std::move(tofrom)}}); + + dirTarget->clauses.push_back(map); + applied = true; + } + } + + return applied; +} + +// IF +// [5.2:72:7-9] +// Directives: cancel, parallel, simd, target, target data, target enter data, +// target exit data, target update, task, taskloop +// +// [5.2:72:15-18] +// (15) For combined or composite constructs, the if clause only applies to the +// semantics of the construct named in the directive-name-modifier. +// (16) For a combined or composite construct, if no directive-name-modifier is +// specified then the if clause applies to all constituent constructs to which +// an if clause can apply. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::IfT &clause, + const ClauseTy *node) { + using DirectiveNameModifier = + typename clause::IfT::DirectiveNameModifier; + using IfExpression = typename clause::IfT::IfExpression; + auto &modifier = std::get>(clause.t); + + if (modifier) { + llvm::omp::Directive dirId = *modifier; + auto *unmodified = + makeClause(llvm::omp::Clause::OMPC_if, + tomp::clause::IfT{ + {/*DirectiveNameModifier=*/std::nullopt, + /*IfExpression=*/std::get(clause.t)}}); + + if (auto *hasDir = findDirective(dirId)) { + hasDir->clauses.push_back(unmodified); + return true; + } + return false; + } + + return applyToAll(node); +} + +// LINEAR +// [5.2:118:1-2] +// Directives: declare simd, do, for, simd +// +// [5.2:341:15-22] +// (15.1) The effect of the linear clause is as if it is applied to the +// innermost leaf construct. +// (15.2) Additionally, if the list item is not the iteration variable of a simd +// or worksharing-loop SIMD construct, the effect on the outer leaf constructs +// is as if the list item was specified in firstprivate and lastprivate clauses +// on the combined or composite construct, with the rules specified above +// applied. +// (19) If a list item of the linear clause is the iteration variable of a simd +// or worksharing-loop SIMD construct and it is not declared in the construct, +// the effect on the outer leaf constructs is as if the list item was specified +// in a lastprivate clause on the combined or composite construct with the rules +// specified above applied. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::LinearT &clause, + const ClauseTy *node) { + // [5.2:341:15.1] + if (!applyToInnermost(node)) + return false; + + // [5.2:341:15.2], [5.2:341:19] + auto dirSimd = findDirective(llvm::omp::Directive::OMPD_simd); + std::optional iterVar = helper.getLoopIterVar(); + const auto &objects = std::get>(clause.t); + + // Lists of objects that will be used to construct "firstprivate" and + // "lastprivate" clauses. + tomp::ObjectListT first, last; + + for (const ObjectTy &object : objects) { + last.push_back(object); + if (!dirSimd || !iterVar || object.id() != iterVar->id()) + first.push_back(object); + } + + if (!first.empty()) { + auto *firstp = makeClause( + llvm::omp::Clause::OMPC_firstprivate, + tomp::clause::FirstprivateT{/*List=*/first}); + nodes.push_back(firstp); // Appending to the main clause list. + } + if (!last.empty()) { + auto *lastp = + makeClause(llvm::omp::Clause::OMPC_lastprivate, + tomp::clause::LastprivateT{ + {/*LastprivateModifier=*/std::nullopt, /*List=*/last}}); + nodes.push_back(lastp); // Appending to the main clause list. + } + return true; +} + +// NOWAIT +// [5.2:308:11-13] +// Directives: dispatch, do, for, interop, scope, sections, single, target, +// target enter data, target exit data, target update, taskwait, workshare +// +// [5.2:341:23] +// (23) The effect of the nowait clause is as if it is applied to the outermost +// leaf construct that permits it. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::NowaitT &clause, + const ClauseTy *node) { + return applyToOutermost(node); +} + +template bool ConstructDecompositionT::split() { + bool success = true; + + for (llvm::omp::Directive leaf : + llvm::omp::getLeafConstructsOrSelf(construct)) + leafs.push_back(LeafReprInternal{leaf, /*clauses=*/{}}); + + for (const ClauseTy *node : nodes) + addClauseSymsToMap(*node, node); + + // First we need to apply LINEAR, because it can generate additional + // "firstprivate" and "lastprivate" clauses that apply to the combined/ + // composite construct. + // Collect them separately, because they may modify the clause list. + llvm::SmallVector linears; + for (const ClauseTy *node : nodes) { + if (node->id == llvm::omp::Clause::OMPC_linear) + linears.push_back(node); + } + for (const auto *node : linears) { + success = success && + applyClause(std::get>( + node->u), + node); + } + + // "allocate" clauses need to be applied last since they need to see + // which directives have data-privatizing clauses. + auto skip = [](const ClauseTy *node) { + switch (node->id) { + case llvm::omp::Clause::OMPC_allocate: + case llvm::omp::Clause::OMPC_linear: + return true; + default: + return false; + } + }; + + // Apply (almost) all clauses. + for (const ClauseTy *node : nodes) { + if (skip(node)) + continue; + success = + success && + std::visit([&](auto &&s) { return applyClause(s, node); }, node->u); + } + + // Apply "allocate". + for (const ClauseTy *node : nodes) { + if (node->id != llvm::omp::Clause::OMPC_allocate) + continue; + success = + success && + std::visit([&](auto &&s) { return applyClause(s, node); }, node->u); + } + + return success; +} + +} // namespace tomp + +#endif // LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H diff --git a/llvm/unittests/Frontend/CMakeLists.txt b/llvm/unittests/Frontend/CMakeLists.txt index 3f290b63ba64..85e113816e3b 100644 --- a/llvm/unittests/Frontend/CMakeLists.txt +++ b/llvm/unittests/Frontend/CMakeLists.txt @@ -15,6 +15,7 @@ add_llvm_unittest(LLVMFrontendTests OpenMPIRBuilderTest.cpp OpenMPParsingTest.cpp OpenMPCompositionTest.cpp + OpenMPDecompositionTest.cpp DEPENDS acc_gen diff --git a/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp b/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp new file mode 100644 index 000000000000..df48e9cc0ff4 --- /dev/null +++ b/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp @@ -0,0 +1,999 @@ +//===- llvm/unittests/Frontend/OpenMPDecompositionTest.cpp ----------------===// +// +// 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 "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Frontend/OpenMP/ClauseT.h" +#include "llvm/Frontend/OpenMP/ConstructDecompositionT.h" +#include "llvm/Frontend/OpenMP/OMP.h" +#include "gtest/gtest.h" + +#include +#include +#include +#include +#include +#include +#include + +// The actual tests start at comment "--- Test" below. + +// Create simple instantiations of all clauses to allow manual construction +// of clauses, and implement emitting of a directive with clauses to a string. +// +// The tests then follow the pattern +// 1. Create a list of clauses. +// 2. Pass them, together with a construct, to the decomposition class. +// 3. Extract individual resulting leaf constructs with clauses applied +// to them. +// 4. Convert them to strings and compare with expected outputs. + +namespace omp { +struct TypeTy {}; // placeholder +struct ExprTy {}; // placeholder +using IdTy = std::string; +} // namespace omp + +namespace tomp::type { +template <> struct ObjectT { + const omp::IdTy &id() const { return name; } + const std::optional ref() const { return omp::ExprTy{}; } + + omp::IdTy name; +}; +} // namespace tomp::type + +namespace omp { +template using List = tomp::type::ListT; + +using Object = tomp::ObjectT; + +namespace clause { +using DefinedOperator = tomp::type::DefinedOperatorT; +using ProcedureDesignator = tomp::type::ProcedureDesignatorT; +using ReductionOperator = tomp::type::ReductionIdentifierT; + +using AcqRel = tomp::clause::AcqRelT; +using Acquire = tomp::clause::AcquireT; +using AdjustArgs = tomp::clause::AdjustArgsT; +using Affinity = tomp::clause::AffinityT; +using Aligned = tomp::clause::AlignedT; +using Align = tomp::clause::AlignT; +using Allocate = tomp::clause::AllocateT; +using Allocator = tomp::clause::AllocatorT; +using AppendArgs = tomp::clause::AppendArgsT; +using AtomicDefaultMemOrder = + tomp::clause::AtomicDefaultMemOrderT; +using At = tomp::clause::AtT; +using Bind = tomp::clause::BindT; +using Capture = tomp::clause::CaptureT; +using Collapse = tomp::clause::CollapseT; +using Compare = tomp::clause::CompareT; +using Copyin = tomp::clause::CopyinT; +using Copyprivate = tomp::clause::CopyprivateT; +using Defaultmap = tomp::clause::DefaultmapT; +using Default = tomp::clause::DefaultT; +using Depend = tomp::clause::DependT; +using Destroy = tomp::clause::DestroyT; +using Detach = tomp::clause::DetachT; +using Device = tomp::clause::DeviceT; +using DeviceType = tomp::clause::DeviceTypeT; +using DistSchedule = tomp::clause::DistScheduleT; +using Doacross = tomp::clause::DoacrossT; +using DynamicAllocators = + tomp::clause::DynamicAllocatorsT; +using Enter = tomp::clause::EnterT; +using Exclusive = tomp::clause::ExclusiveT; +using Fail = tomp::clause::FailT; +using Filter = tomp::clause::FilterT; +using Final = tomp::clause::FinalT; +using Firstprivate = tomp::clause::FirstprivateT; +using From = tomp::clause::FromT; +using Full = tomp::clause::FullT; +using Grainsize = tomp::clause::GrainsizeT; +using HasDeviceAddr = tomp::clause::HasDeviceAddrT; +using Hint = tomp::clause::HintT; +using If = tomp::clause::IfT; +using Inbranch = tomp::clause::InbranchT; +using Inclusive = tomp::clause::InclusiveT; +using Indirect = tomp::clause::IndirectT; +using Init = tomp::clause::InitT; +using InReduction = tomp::clause::InReductionT; +using IsDevicePtr = tomp::clause::IsDevicePtrT; +using Lastprivate = tomp::clause::LastprivateT; +using Linear = tomp::clause::LinearT; +using Link = tomp::clause::LinkT; +using Map = tomp::clause::MapT; +using Match = tomp::clause::MatchT; +using Mergeable = tomp::clause::MergeableT; +using Message = tomp::clause::MessageT; +using Nocontext = tomp::clause::NocontextT; +using Nogroup = tomp::clause::NogroupT; +using Nontemporal = tomp::clause::NontemporalT; +using Notinbranch = tomp::clause::NotinbranchT; +using Novariants = tomp::clause::NovariantsT; +using Nowait = tomp::clause::NowaitT; +using NumTasks = tomp::clause::NumTasksT; +using NumTeams = tomp::clause::NumTeamsT; +using NumThreads = tomp::clause::NumThreadsT; +using OmpxAttribute = tomp::clause::OmpxAttributeT; +using OmpxBare = tomp::clause::OmpxBareT; +using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT; +using Ordered = tomp::clause::OrderedT; +using Order = tomp::clause::OrderT; +using Partial = tomp::clause::PartialT; +using Priority = tomp::clause::PriorityT; +using Private = tomp::clause::PrivateT; +using ProcBind = tomp::clause::ProcBindT; +using Read = tomp::clause::ReadT; +using Reduction = tomp::clause::ReductionT; +using Relaxed = tomp::clause::RelaxedT; +using Release = tomp::clause::ReleaseT; +using ReverseOffload = tomp::clause::ReverseOffloadT; +using Safelen = tomp::clause::SafelenT; +using Schedule = tomp::clause::ScheduleT; +using SeqCst = tomp::clause::SeqCstT; +using Severity = tomp::clause::SeverityT; +using Shared = tomp::clause::SharedT; +using Simdlen = tomp::clause::SimdlenT; +using Simd = tomp::clause::SimdT; +using Sizes = tomp::clause::SizesT; +using TaskReduction = tomp::clause::TaskReductionT; +using ThreadLimit = tomp::clause::ThreadLimitT; +using Threads = tomp::clause::ThreadsT; +using To = tomp::clause::ToT; +using UnifiedAddress = tomp::clause::UnifiedAddressT; +using UnifiedSharedMemory = + tomp::clause::UnifiedSharedMemoryT; +using Uniform = tomp::clause::UniformT; +using Unknown = tomp::clause::UnknownT; +using Untied = tomp::clause::UntiedT; +using Update = tomp::clause::UpdateT; +using UseDeviceAddr = tomp::clause::UseDeviceAddrT; +using UseDevicePtr = tomp::clause::UseDevicePtrT; +using UsesAllocators = tomp::clause::UsesAllocatorsT; +using Use = tomp::clause::UseT; +using Weak = tomp::clause::WeakT; +using When = tomp::clause::WhenT; +using Write = tomp::clause::WriteT; +} // namespace clause + +struct Helper { + std::optional getBaseObject(const Object &object) { + return std::nullopt; + } + std::optional getLoopIterVar() { return std::nullopt; } +}; + +using Clause = tomp::ClauseT; +using ConstructDecomposition = tomp::ConstructDecompositionT; +using DirectiveWithClauses = tomp::DirectiveWithClauses; +} // namespace omp + +struct StringifyClause { + static std::string join(const omp::List &Strings) { + std::stringstream Stream; + for (const auto &[Index, String] : llvm::enumerate(Strings)) { + if (Index != 0) + Stream << ", "; + Stream << String; + } + return Stream.str(); + } + + static std::string to_str(llvm::omp::Directive D) { + return getOpenMPDirectiveName(D).str(); + } + static std::string to_str(llvm::omp::Clause C) { + return getOpenMPClauseName(C).str(); + } + static std::string to_str(const omp::TypeTy &Type) { return "type"; } + static std::string to_str(const omp::ExprTy &Expr) { return "expr"; } + static std::string to_str(const omp::Object &Obj) { return Obj.id(); } + + template + static std::enable_if_t>, std::string> + to_str(U &&Item) { + return std::to_string(llvm::to_underlying(Item)); + } + + template static std::string to_str(const omp::List &Items) { + omp::List Names; + llvm::transform(Items, std::back_inserter(Names), + [](auto &&S) { return to_str(S); }); + return "(" + join(Names) + ")"; + } + + template + static std::string to_str(const std::optional &Item) { + if (Item) + return to_str(*Item); + return ""; + } + + template + static std::string to_str(const std::tuple &Tuple, + std::index_sequence) { + omp::List Strings; + (Strings.push_back(to_str(std::get(Tuple))), ...); + return "(" + join(Strings) + ")"; + } + + template + static std::enable_if_t::EmptyTrait::value, + std::string> + to_str(U &&Item) { + return ""; + } + + template + static std::enable_if_t::IncompleteTrait::value, + std::string> + to_str(U &&Item) { + return ""; + } + + template + static std::enable_if_t::WrapperTrait::value, + std::string> + to_str(U &&Item) { + // For a wrapper, stringify the wrappee, and only add parentheses if + // there aren't any already. + std::string Str = to_str(Item.v); + if (!Str.empty()) { + if (Str.front() == '(' && Str.back() == ')') + return Str; + } + return "(" + to_str(Item.v) + ")"; + } + + template + static std::enable_if_t::TupleTrait::value, + std::string> + to_str(U &&Item) { + constexpr size_t TupleSize = + std::tuple_size_v>; + return to_str(Item.t, std::make_index_sequence{}); + } + + template + static std::enable_if_t::UnionTrait::value, + std::string> + to_str(U &&Item) { + return std::visit([](auto &&S) { return to_str(S); }, Item.u); + } + + StringifyClause(const omp::Clause &C) + // Rely on content stringification to emit enclosing parentheses. + : Str(to_str(C.id) + to_str(C)) {} + + std::string Str; +}; + +std::string stringify(const omp::DirectiveWithClauses &DWC) { + std::stringstream Stream; + + Stream << getOpenMPDirectiveName(DWC.id).str(); + for (const omp::Clause &C : DWC.clauses) + Stream << ' ' << StringifyClause(C).Str; + + return Stream.str(); +} + +// --- Tests ---------------------------------------------------------- + +namespace { +using namespace llvm::omp; + +class OpenMPDecompositionTest : public testing::Test { +protected: + void SetUp() override {} + void TearDown() override {} + + omp::Helper Helper; + uint32_t AnyVersion = 999; +}; + +// PRIVATE +// [5.2:111:5-7] +// Directives: distribute, do, for, loop, parallel, scope, sections, simd, +// single, target, task, taskloop, teams +// +// [5.2:340:1-2] +// (1) The effect of the 1 private clause is as if it is applied only to the +// innermost leaf construct that permits it. +TEST_F(OpenMPDecompositionTest, Private1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_private, omp::clause::Private{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel"); // (1) + ASSERT_EQ(Dir1, "sections private(x)"); // (1) +} + +TEST_F(OpenMPDecompositionTest, Private2) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_private, omp::clause::Private{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel private(x)"); // (1) + ASSERT_EQ(Dir1, "masked"); // (1) +} + +// FIRSTPRIVATE +// [5.2:112:5-7] +// Directives: distribute, do, for, parallel, scope, sections, single, target, +// task, taskloop, teams +// +// [5.2:340:3-20] +// (3) The effect of the firstprivate clause is as if it is applied to one or +// more leaf constructs as follows: +// (5) To the distribute construct if it is among the constituent constructs; +// (6) To the teams construct if it is among the constituent constructs and the +// distribute construct is not; +// (8) To a worksharing construct that accepts the clause if one is among the +// constituent constructs; +// (9) To the taskloop construct if it is among the constituent constructs; +// (10) To the parallel construct if it is among the constituent constructs and +// neither a taskloop construct nor a worksharing construct that accepts +// the clause is among them; +// (12) To the target construct if it is among the constituent constructs and +// the same list item neither appears in a lastprivate clause nor is the +// base variable or base pointer of a list item that appears in a map +// clause. +// +// (15) If the parallel construct is among the constituent constructs and the +// effect is not as if the firstprivate clause is applied to it by the above +// rules, then the effect is as if the shared clause with the same list item is +// applied to the parallel construct. +// (17) If the teams construct is among the constituent constructs and the +// effect is not as if the firstprivate clause is applied to it by the above +// rules, then the effect is as if the shared clause with the same list item is +// applied to the teams construct. +TEST_F(OpenMPDecompositionTest, Firstprivate1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (10), (15) + ASSERT_EQ(Dir1, "sections firstprivate(x)"); // (8) +} + +TEST_F(OpenMPDecompositionTest, Firstprivate2) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_target_teams_distribute, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "target firstprivate(x)"); // (12) + ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17) + ASSERT_EQ(Dir2, "distribute firstprivate(x)"); // (5) +} + +TEST_F(OpenMPDecompositionTest, Firstprivate3) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_target_teams_distribute, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (12), (27) + ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17) + ASSERT_EQ(Dir2, "distribute firstprivate(x) lastprivate(, (x))"); // (5), (21) +} + +TEST_F(OpenMPDecompositionTest, Firstprivate4) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_teams, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "target firstprivate(x)"); // (12) + ASSERT_EQ(Dir1, "teams firstprivate(x)"); // (6) +} + +TEST_F(OpenMPDecompositionTest, Firstprivate5) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_parallel_masked_taskloop, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (10) + ASSERT_EQ(Dir1, "masked"); + ASSERT_EQ(Dir2, "taskloop firstprivate(x)"); // (9) +} + +TEST_F(OpenMPDecompositionTest, Firstprivate6) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel firstprivate(x)"); // (10) + ASSERT_EQ(Dir1, "masked"); +} + +TEST_F(OpenMPDecompositionTest, Firstprivate7) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + // Composite constructs are still decomposed. + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_distribute, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "teams shared(x)"); // (17) + ASSERT_EQ(Dir1, "distribute firstprivate(x)"); // (5) +} + +// LASTPRIVATE +// [5.2:115:7-8] +// Directives: distribute, do, for, loop, sections, simd, taskloop +// +// [5.2:340:21-30] +// (21) The effect of the lastprivate clause is as if it is applied to all leaf +// constructs that permit the clause. +// (22) If the parallel construct is among the constituent constructs and the +// list item is not also specified in the firstprivate clause, then the effect +// of the lastprivate clause is as if the shared clause with the same list item +// is applied to the parallel construct. +// (24) If the teams construct is among the constituent constructs and the list +// item is not also specified in the firstprivate clause, then the effect of the +// lastprivate clause is as if the shared clause with the same list item is +// applied to the teams construct. +// (27) If the target construct is among the constituent constructs and the list +// item is not the base variable or base pointer of a list item that appears in +// a map clause, the effect of the lastprivate clause is as if the same list +// item appears in a map clause with a map-type of tofrom. +TEST_F(OpenMPDecompositionTest, Lastprivate1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (21), (22) + ASSERT_EQ(Dir1, "sections lastprivate(, (x))"); // (21) +} + +TEST_F(OpenMPDecompositionTest, Lastprivate2) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_distribute, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "teams shared(x)"); // (21), (25) + ASSERT_EQ(Dir1, "distribute lastprivate(, (x))"); // (21) +} + +TEST_F(OpenMPDecompositionTest, Lastprivate3) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_do, + Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (21), (27) + ASSERT_EQ(Dir1, "parallel shared(x)"); // (22) + ASSERT_EQ(Dir2, "do lastprivate(, (x))"); // (21) +} + +// SHARED +// [5.2:110:5-6] +// Directives: parallel, task, taskloop, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +TEST_F(OpenMPDecompositionTest, Shared1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_shared, omp::clause::Shared{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_parallel_masked_taskloop, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (31) + ASSERT_EQ(Dir1, "masked"); // (31) + ASSERT_EQ(Dir2, "taskloop shared(x)"); // (31) +} + +// DEFAULT +// [5.2:109:5-6] +// Directives: parallel, task, taskloop, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +TEST_F(OpenMPDecompositionTest, Default1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_default, + omp::clause::Default{ + omp::clause::Default::DataSharingAttribute::Firstprivate}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_parallel_masked_taskloop, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "parallel default(0)"); // (31) + ASSERT_EQ(Dir1, "masked"); // (31) + ASSERT_EQ(Dir2, "taskloop default(0)"); // (31) +} + +// THREAD_LIMIT +// [5.2:277:14-15] +// Directives: target, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +TEST_F(OpenMPDecompositionTest, ThreadLimit1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_thread_limit, omp::clause::ThreadLimit{omp::ExprTy{}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_target_teams_distribute, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "target thread_limit(expr)"); // (31) + ASSERT_EQ(Dir1, "teams thread_limit(expr)"); // (31) + ASSERT_EQ(Dir2, "distribute"); // (31) +} + +// ORDER +// [5.2:234:3-4] +// Directives: distribute, do, for, loop, simd +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +TEST_F(OpenMPDecompositionTest, Order1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_order, + omp::clause::Order{{omp::clause::Order::OrderModifier::Unconstrained, + omp::clause::Order::Ordering::Concurrent}}}, + }; + + omp::ConstructDecomposition Dec( + AnyVersion, Helper, OMPD_target_teams_distribute_parallel_for_simd, + Clauses); + ASSERT_EQ(Dec.output.size(), 6u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + std::string Dir4 = stringify(Dec.output[4]); + std::string Dir5 = stringify(Dec.output[5]); + ASSERT_EQ(Dir0, "target"); // (31) + ASSERT_EQ(Dir1, "teams"); // (31) + // XXX OMP.td doesn't list "order" as allowed for "distribute" + ASSERT_EQ(Dir2, "distribute"); // (31) + ASSERT_EQ(Dir3, "parallel"); // (31) + ASSERT_EQ(Dir4, "for order(1, 0)"); // (31) + ASSERT_EQ(Dir5, "simd order(1, 0)"); // (31) +} + +// ALLOCATE +// [5.2:178:7-9] +// Directives: allocators, distribute, do, for, parallel, scope, sections, +// single, target, task, taskgroup, taskloop, teams +// +// [5.2:340:33-35] +// (33) The effect of the allocate clause is as if it is applied to all leaf +// constructs that permit the clause and to which a data-sharing attribute +// clause that may create a private copy of the same list item is applied. +TEST_F(OpenMPDecompositionTest, Allocate1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_allocate, + omp::clause::Allocate{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, + {OMPC_private, omp::clause::Private{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel"); // (33) + ASSERT_EQ(Dir1, "sections private(x) allocate(, , , (x))"); // (33) +} + +// REDUCTION +// [5.2:134:17-18] +// Directives: do, for, loop, parallel, scope, sections, simd, taskloop, teams +// +// [5.2:340-341:36-13] +// (36) The effect of the reduction clause is as if it is applied to all leaf +// constructs that permit the clause, except for the following constructs: +// (1) The parallel construct, when combined with the sections, +// worksharing-loop, loop, or taskloop construct; and +// (3) The teams construct, when combined with the loop construct. +// (4) For the parallel and teams constructs above, the effect of the reduction +// clause instead is as if each list item or, for any list item that is an array +// item, its corresponding base array or base pointer appears in a shared clause +// for the construct. +// (6) If the task reduction-modifier is specified, the effect is as if it only +// modifies the behavior of the reduction clause on the innermost leaf construct +// that accepts the modifier (see Section 5.5.8). +// (8) If the inscan reduction-modifier is specified, the effect is as if it +// modifies the behavior of the reduction clause on all constructs of the +// combined construct to which the clause is applied and that accept the +// modifier. +// (10) If a list item in a reduction clause on a combined target construct does +// not have the same base variable or base pointer as a list item in a map +// clause on the construct, then the effect is as if the list item in the +// reduction clause appears as a list item in a map clause with a map-type of +// tofrom. +namespace red { +// Make is easier to construct reduction operators from built-in intrinsics. +omp::clause::ReductionOperator +makeOp(omp::clause::DefinedOperator::IntrinsicOperator Op) { + return omp::clause::ReductionOperator{omp::clause::DefinedOperator{Op}}; +} +} // namespace red + +TEST_F(OpenMPDecompositionTest, Reduction1) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (36), (1), (4) + ASSERT_EQ(Dir1, "sections reduction(, (3), (x))"); // (36) +} + +TEST_F(OpenMPDecompositionTest, Reduction2) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel reduction(, (3), (x))"); // (36), (1), (4) + ASSERT_EQ(Dir1, "masked"); // (36) +} + +TEST_F(OpenMPDecompositionTest, Reduction3) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_loop, Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "teams shared(x)"); // (36), (3), (4) + ASSERT_EQ(Dir1, "loop reduction(, (3), (x))"); // (36) +} + +TEST_F(OpenMPDecompositionTest, Reduction4) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_teams_distribute_parallel_for, Clauses); + ASSERT_EQ(Dec.output.size(), 4u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3) + ASSERT_EQ(Dir1, "distribute"); // (36) + ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) + ASSERT_EQ(Dir3, "for reduction(, (3), (x))"); // (36) +} + +TEST_F(OpenMPDecompositionTest, Reduction5) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + auto TaskMod = omp::clause::Reduction::ReductionModifier::Task; + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{TaskMod, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_teams_distribute_parallel_for, Clauses); + ASSERT_EQ(Dec.output.size(), 4u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3), (6) + ASSERT_EQ(Dir1, "distribute"); // (36) + ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) + ASSERT_EQ(Dir3, "for reduction(2, (3), (x))"); // (36), (6) +} + +TEST_F(OpenMPDecompositionTest, Reduction6) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + auto InscanMod = omp::clause::Reduction::ReductionModifier::Inscan; + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{InscanMod, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_teams_distribute_parallel_for, Clauses); + ASSERT_EQ(Dec.output.size(), 4u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3), (8) + ASSERT_EQ(Dir1, "distribute"); // (36) + ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) + ASSERT_EQ(Dir3, "for reduction(1, (3), (x))"); // (36), (8) +} + +TEST_F(OpenMPDecompositionTest, Reduction7) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_do, + Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + // XXX Currently OMP.td allows "reduction" on "target". + ASSERT_EQ(Dir0, + "target reduction(, (3), (x)) map(2, , , , (x))"); // (36), (10) + ASSERT_EQ(Dir1, "parallel shared(x)"); // (36), (1), (4) + ASSERT_EQ(Dir2, "do reduction(, (3), (x))"); // (36) +} + +// IF +// [5.2:72:7-9] +// Directives: cancel, parallel, simd, target, target data, target enter data, +// target exit data, target update, task, taskloop +// +// [5.2:72:15-18] +// (15) For combined or composite constructs, the if clause only applies to the +// semantics of the construct named in the directive-name-modifier. +// (16) For a combined or composite construct, if no directive-name-modifier is +// specified then the if clause applies to all constituent constructs to which +// an if clause can apply. +TEST_F(OpenMPDecompositionTest, If1) { + omp::List Clauses{ + {OMPC_if, + omp::clause::If{{llvm::omp::Directive::OMPD_parallel, omp::ExprTy{}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_target_parallel_for_simd, Clauses); + ASSERT_EQ(Dec.output.size(), 4u); + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + ASSERT_EQ(Dir0, "target"); // (15) + ASSERT_EQ(Dir1, "parallel if(, expr)"); // (15) + ASSERT_EQ(Dir2, "for"); // (15) + ASSERT_EQ(Dir3, "simd"); // (15) +} + +TEST_F(OpenMPDecompositionTest, If2) { + omp::List Clauses{ + {OMPC_if, omp::clause::If{{std::nullopt, omp::ExprTy{}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_target_parallel_for_simd, Clauses); + ASSERT_EQ(Dec.output.size(), 4u); + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + ASSERT_EQ(Dir0, "target if(, expr)"); // (16) + ASSERT_EQ(Dir1, "parallel if(, expr)"); // (16) + ASSERT_EQ(Dir2, "for"); // (16) + ASSERT_EQ(Dir3, "simd if(, expr)"); // (16) +} + +// LINEAR +// [5.2:118:1-2] +// Directives: declare simd, do, for, simd +// +// [5.2:341:15-22] +// (15.1) The effect of the linear clause is as if it is applied to the +// innermost leaf construct. +// (15.2) Additionally, if the list item is not the iteration variable of a simd +// or worksharing-loop SIMD construct, the effect on the outer leaf constructs +// is as if the list item was specified in firstprivate and lastprivate clauses +// on the combined or composite construct, with the rules specified above +// applied. +// (19) If a list item of the linear clause is the iteration variable of a simd +// or worksharing-loop SIMD construct and it is not declared in the construct, +// the effect on the outer leaf constructs is as if the list item was specified +// in a lastprivate clause on the combined or composite construct with the rules +// specified above applied. +TEST_F(OpenMPDecompositionTest, Linear1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_linear, + omp::clause::Linear{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_for_simd, Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "for firstprivate(x) lastprivate(, (x))"); // (15.1), (15.2) + ASSERT_EQ(Dir1, "simd linear(, , , (x)) lastprivate(, (x))"); // (15.1) +} + +// NOWAIT +// [5.2:308:11-13] +// Directives: dispatch, do, for, interop, scope, sections, single, target, +// target enter data, target exit data, target update, taskwait, workshare +// +// [5.2:341:23] +// (23) The effect of the nowait clause is as if it is applied to the outermost +// leaf construct that permits it. +TEST_F(OpenMPDecompositionTest, Nowait1) { + omp::List Clauses{ + {OMPC_nowait, omp::clause::Nowait{}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_for, + Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "target nowait"); // (23) + ASSERT_EQ(Dir1, "parallel"); // (23) + ASSERT_EQ(Dir2, "for"); // (23) +} +} // namespace -- GitLab From d2676a73336b83607565fb2e4ce61bd67d732b09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hendrik=20H=C3=BCbner?= <117831077+HendrikHuebner@users.noreply.github.com> Date: Mon, 13 May 2024 15:35:17 +0200 Subject: [PATCH 059/578] [libc][POSIX][pthreads] implemented missing pthread_rwlockattr functions (#90249) Closes #89443 I added the two missing functions and respective test cases. Let me know if anything needs changing. --- libc/config/linux/x86_64/entrypoints.txt | 2 ++ libc/include/pthread.h.def | 5 ++++ libc/spec/posix.td | 10 +++++++ libc/src/pthread/CMakeLists.txt | 21 +++++++++++++ .../pthread/pthread_rwlockattr_getkind_np.cpp | 24 +++++++++++++++ .../pthread/pthread_rwlockattr_getkind_np.h | 21 +++++++++++++ libc/src/pthread/pthread_rwlockattr_init.cpp | 1 + .../pthread/pthread_rwlockattr_setkind_np.cpp | 30 +++++++++++++++++++ .../pthread/pthread_rwlockattr_setkind_np.h | 20 +++++++++++++ libc/test/src/pthread/CMakeLists.txt | 2 ++ .../src/pthread/pthread_rwlockattr_test.cpp | 29 ++++++++++++++++-- 11 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 libc/src/pthread/pthread_rwlockattr_getkind_np.cpp create mode 100644 libc/src/pthread/pthread_rwlockattr_getkind_np.h create mode 100644 libc/src/pthread/pthread_rwlockattr_setkind_np.cpp create mode 100644 libc/src/pthread/pthread_rwlockattr_setkind_np.h diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 5e3ddd34fb4d..155deddaaade 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -673,8 +673,10 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.pthread.pthread_mutexattr_settype libc.src.pthread.pthread_once libc.src.pthread.pthread_rwlockattr_destroy + libc.src.pthread.pthread_rwlockattr_getkind_np libc.src.pthread.pthread_rwlockattr_getpshared libc.src.pthread.pthread_rwlockattr_init + libc.src.pthread.pthread_rwlockattr_setkind_np libc.src.pthread.pthread_rwlockattr_setpshared libc.src.pthread.pthread_setspecific diff --git a/libc/include/pthread.h.def b/libc/include/pthread.h.def index a94d770657e1..d41273b5590e 100644 --- a/libc/include/pthread.h.def +++ b/libc/include/pthread.h.def @@ -38,6 +38,11 @@ enum { #define PTHREAD_PROCESS_PRIVATE 0 #define PTHREAD_PROCESS_SHARED 1 +#define PTHREAD_RWLOCK_PREFER_READER_NP 0 +#define PTHREAD_RWLOCK_PREFER_WRITER_NP 1 +#define PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP 2 + + %%public_api() #endif // LLVM_LIBC_PTHREAD_H diff --git a/libc/spec/posix.td b/libc/spec/posix.td index e7a0cf883c60..e16353b8142d 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -1234,6 +1234,11 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec, [ArgSpec] >, + FunctionSpec< + "pthread_rwlockattr_getkind_np", + RetValSpec, + [ArgSpec, ArgSpec] + >, FunctionSpec< "pthread_rwlockattr_getpshared", RetValSpec, @@ -1244,6 +1249,11 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec, [ArgSpec] >, + FunctionSpec< + "pthread_rwlockattr_setkind_np", + RetValSpec, + [ArgSpec, ArgSpec] + >, FunctionSpec< "pthread_rwlockattr_setpshared", RetValSpec, diff --git a/libc/src/pthread/CMakeLists.txt b/libc/src/pthread/CMakeLists.txt index c57475c9114f..e5bebb63c640 100644 --- a/libc/src/pthread/CMakeLists.txt +++ b/libc/src/pthread/CMakeLists.txt @@ -470,6 +470,16 @@ add_entrypoint_object( libc.include.pthread ) +add_entrypoint_object( + pthread_rwlockattr_getkind_np + SRCS + pthread_rwlockattr_getkind_np.cpp + HDRS + pthread_rwlockattr_getkind_np.h + DEPENDS + libc.include.pthread +) + add_entrypoint_object( pthread_rwlockattr_getpshared SRCS @@ -490,6 +500,17 @@ add_entrypoint_object( libc.include.pthread ) +add_entrypoint_object( + pthread_rwlockattr_setkind_np + SRCS + pthread_rwlockattr_setkind_np.cpp + HDRS + pthread_rwlockattr_setkind_np.h + DEPENDS + libc.include.pthread + libc.include.errno +) + add_entrypoint_object( pthread_rwlockattr_setpshared SRCS diff --git a/libc/src/pthread/pthread_rwlockattr_getkind_np.cpp b/libc/src/pthread/pthread_rwlockattr_getkind_np.cpp new file mode 100644 index 000000000000..0c821797b42c --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_getkind_np.cpp @@ -0,0 +1,24 @@ +//===-- Implementation of the pthread_rwlockattr_getkind_np ---------------===// +// +// 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 "pthread_rwlockattr_getkind_np.h" + +#include "src/__support/common.h" + +#include // pthread_rwlockattr_t + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_getkind_np, + (const pthread_rwlockattr_t *__restrict attr, + int *__restrict pref)) { + *pref = attr->pref; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_getkind_np.h b/libc/src/pthread/pthread_rwlockattr_getkind_np.h new file mode 100644 index 000000000000..51f633cd559d --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_getkind_np.h @@ -0,0 +1,21 @@ +//===-- Implementation header for pthread_rwlockattr_getkind_np -*- 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_PTHREAD_PTHREAD_RWLOCKATTR_GETKIND_NP_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_GETKIND_NP_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *__restrict attr, + int *__restrict pref); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_GETKIND_NP_H diff --git a/libc/src/pthread/pthread_rwlockattr_init.cpp b/libc/src/pthread/pthread_rwlockattr_init.cpp index 7971f1714db4..bbc89555c6c1 100644 --- a/libc/src/pthread/pthread_rwlockattr_init.cpp +++ b/libc/src/pthread/pthread_rwlockattr_init.cpp @@ -17,6 +17,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_init, (pthread_rwlockattr_t * attr)) { attr->pshared = PTHREAD_PROCESS_PRIVATE; + attr->pref = PTHREAD_RWLOCK_PREFER_READER_NP; return 0; } diff --git a/libc/src/pthread/pthread_rwlockattr_setkind_np.cpp b/libc/src/pthread/pthread_rwlockattr_setkind_np.cpp new file mode 100644 index 000000000000..47fbf2a851e5 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_setkind_np.cpp @@ -0,0 +1,30 @@ +//===-- Implementation of the pthread_rwlockattr_setkind_np ---------------===// +// +// 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 "pthread_rwlockattr_setkind_np.h" + +#include "src/__support/common.h" + +#include +#include // pthread_rwlockattr_t + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_setkind_np, + (pthread_rwlockattr_t * attr, int pref)) { + + if (pref != PTHREAD_RWLOCK_PREFER_READER_NP && + pref != PTHREAD_RWLOCK_PREFER_WRITER_NP && + pref != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP) + return EINVAL; + + attr->pref = pref; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_setkind_np.h b/libc/src/pthread/pthread_rwlockattr_setkind_np.h new file mode 100644 index 000000000000..00ef8e1bbe00 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_setkind_np.h @@ -0,0 +1,20 @@ +//===-- Implementation header for pthread_rwlockattr_setkind_np -*- 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_PTHREAD_PTHREAD_RWLOCKATTR_SETKIND_NP_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_SETKIND_NP_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_SETKIND_NP_H diff --git a/libc/test/src/pthread/CMakeLists.txt b/libc/test/src/pthread/CMakeLists.txt index ea75e65f57c9..0eeec445d5f4 100644 --- a/libc/test/src/pthread/CMakeLists.txt +++ b/libc/test/src/pthread/CMakeLists.txt @@ -68,7 +68,9 @@ add_libc_unittest( libc.include.errno libc.include.pthread libc.src.pthread.pthread_rwlockattr_destroy + libc.src.pthread.pthread_rwlockattr_getkind_np libc.src.pthread.pthread_rwlockattr_getpshared libc.src.pthread.pthread_rwlockattr_init + libc.src.pthread.pthread_rwlockattr_setkind_np libc.src.pthread.pthread_rwlockattr_setpshared ) diff --git a/libc/test/src/pthread/pthread_rwlockattr_test.cpp b/libc/test/src/pthread/pthread_rwlockattr_test.cpp index 6e5ae70df734..3791f568e222 100644 --- a/libc/test/src/pthread/pthread_rwlockattr_test.cpp +++ b/libc/test/src/pthread/pthread_rwlockattr_test.cpp @@ -8,8 +8,10 @@ #include "include/llvm-libc-macros/generic-error-number-macros.h" // EINVAL #include "src/pthread/pthread_rwlockattr_destroy.h" +#include "src/pthread/pthread_rwlockattr_getkind_np.h" #include "src/pthread/pthread_rwlockattr_getpshared.h" #include "src/pthread/pthread_rwlockattr_init.h" +#include "src/pthread/pthread_rwlockattr_setkind_np.h" #include "src/pthread/pthread_rwlockattr_setpshared.h" #include "test/UnitTest/Test.h" @@ -25,40 +27,61 @@ TEST(LlvmLibcPThreadRWLockAttrTest, InitAndDestroy) { TEST(LlvmLibcPThreadRWLockAttrTest, GetDefaultValues) { pthread_rwlockattr_t attr; - // Invalid value. + // Invalid values. int pshared = 42; + int pref = 1337; ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getkind_np(&attr, &pref), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); + ASSERT_EQ(pref, PTHREAD_RWLOCK_PREFER_READER_NP); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); } TEST(LlvmLibcPThreadRWLockAttrTest, SetGoodValues) { pthread_rwlockattr_t attr; - // Invalid value. + // Invalid values. int pshared = 42; + int pref = 1337; ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setpshared( &attr, PTHREAD_PROCESS_SHARED), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setkind_np( + &attr, PTHREAD_RWLOCK_PREFER_WRITER_NP), + 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getkind_np(&attr, &pref), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_SHARED); + ASSERT_EQ(pref, PTHREAD_RWLOCK_PREFER_WRITER_NP); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); } TEST(LlvmLibcPThreadRWLockAttrTest, SetBadValues) { pthread_rwlockattr_t attr; - // Invalid value. + // Invalid values. int pshared = 42; + int pref = 1337; ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setpshared(&attr, pshared), EINVAL); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setkind_np(&attr, pref), EINVAL); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getkind_np(&attr, &pref), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); + ASSERT_EQ(pref, PTHREAD_RWLOCK_PREFER_READER_NP); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); } -- GitLab From 29a986bc0972c7d2deb85f8789ea3183c8ca06ca Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Mon, 13 May 2024 15:36:46 +0200 Subject: [PATCH 060/578] new-prs-labeler.yml: Include conversion passes of TOSA/emitc (#91921) --- .github/new-prs-labeler.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml index d608ea449f1d..a57ba28faf16 100644 --- a/.github/new-prs-labeler.yml +++ b/.github/new-prs-labeler.yml @@ -239,7 +239,7 @@ mlir:dlti: - mlir/**/DLTI/** mlir:emitc: - - mlir/**/EmitC/** + - mlir/**/*EmitC*/** - mlir/lib/Target/Cpp/** mlir:func: @@ -306,7 +306,7 @@ mlir:tensor: - mlir/**/Tensor/** mlir:tosa: - - mlir/**/Tosa/** + - mlir/**/*Tosa*/** mlir:ub: - mlir/**/UB/** -- GitLab From 27595c4befbbf42891ef7e13fe28926eb7fc825d Mon Sep 17 00:00:00 2001 From: Schrodinger ZHU Yifan Date: Mon, 13 May 2024 09:43:14 -0400 Subject: [PATCH 061/578] Revert "[libc][POSIX][pthreads] implemented missing pthread_rwlockattr functions" (#91966) Reverts llvm/llvm-project#90249 Fullbuild is broken: https://lab.llvm.org/buildbot/#/builders/163/builds/56501 --- libc/config/linux/x86_64/entrypoints.txt | 2 -- libc/include/pthread.h.def | 5 ---- libc/spec/posix.td | 10 ------- libc/src/pthread/CMakeLists.txt | 21 ------------- .../pthread/pthread_rwlockattr_getkind_np.cpp | 24 --------------- .../pthread/pthread_rwlockattr_getkind_np.h | 21 ------------- libc/src/pthread/pthread_rwlockattr_init.cpp | 1 - .../pthread/pthread_rwlockattr_setkind_np.cpp | 30 ------------------- .../pthread/pthread_rwlockattr_setkind_np.h | 20 ------------- libc/test/src/pthread/CMakeLists.txt | 2 -- .../src/pthread/pthread_rwlockattr_test.cpp | 29 ++---------------- 11 files changed, 3 insertions(+), 162 deletions(-) delete mode 100644 libc/src/pthread/pthread_rwlockattr_getkind_np.cpp delete mode 100644 libc/src/pthread/pthread_rwlockattr_getkind_np.h delete mode 100644 libc/src/pthread/pthread_rwlockattr_setkind_np.cpp delete mode 100644 libc/src/pthread/pthread_rwlockattr_setkind_np.h diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 155deddaaade..5e3ddd34fb4d 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -673,10 +673,8 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.pthread.pthread_mutexattr_settype libc.src.pthread.pthread_once libc.src.pthread.pthread_rwlockattr_destroy - libc.src.pthread.pthread_rwlockattr_getkind_np libc.src.pthread.pthread_rwlockattr_getpshared libc.src.pthread.pthread_rwlockattr_init - libc.src.pthread.pthread_rwlockattr_setkind_np libc.src.pthread.pthread_rwlockattr_setpshared libc.src.pthread.pthread_setspecific diff --git a/libc/include/pthread.h.def b/libc/include/pthread.h.def index d41273b5590e..a94d770657e1 100644 --- a/libc/include/pthread.h.def +++ b/libc/include/pthread.h.def @@ -38,11 +38,6 @@ enum { #define PTHREAD_PROCESS_PRIVATE 0 #define PTHREAD_PROCESS_SHARED 1 -#define PTHREAD_RWLOCK_PREFER_READER_NP 0 -#define PTHREAD_RWLOCK_PREFER_WRITER_NP 1 -#define PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP 2 - - %%public_api() #endif // LLVM_LIBC_PTHREAD_H diff --git a/libc/spec/posix.td b/libc/spec/posix.td index e16353b8142d..e7a0cf883c60 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -1234,11 +1234,6 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec, [ArgSpec] >, - FunctionSpec< - "pthread_rwlockattr_getkind_np", - RetValSpec, - [ArgSpec, ArgSpec] - >, FunctionSpec< "pthread_rwlockattr_getpshared", RetValSpec, @@ -1249,11 +1244,6 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec, [ArgSpec] >, - FunctionSpec< - "pthread_rwlockattr_setkind_np", - RetValSpec, - [ArgSpec, ArgSpec] - >, FunctionSpec< "pthread_rwlockattr_setpshared", RetValSpec, diff --git a/libc/src/pthread/CMakeLists.txt b/libc/src/pthread/CMakeLists.txt index e5bebb63c640..c57475c9114f 100644 --- a/libc/src/pthread/CMakeLists.txt +++ b/libc/src/pthread/CMakeLists.txt @@ -470,16 +470,6 @@ add_entrypoint_object( libc.include.pthread ) -add_entrypoint_object( - pthread_rwlockattr_getkind_np - SRCS - pthread_rwlockattr_getkind_np.cpp - HDRS - pthread_rwlockattr_getkind_np.h - DEPENDS - libc.include.pthread -) - add_entrypoint_object( pthread_rwlockattr_getpshared SRCS @@ -500,17 +490,6 @@ add_entrypoint_object( libc.include.pthread ) -add_entrypoint_object( - pthread_rwlockattr_setkind_np - SRCS - pthread_rwlockattr_setkind_np.cpp - HDRS - pthread_rwlockattr_setkind_np.h - DEPENDS - libc.include.pthread - libc.include.errno -) - add_entrypoint_object( pthread_rwlockattr_setpshared SRCS diff --git a/libc/src/pthread/pthread_rwlockattr_getkind_np.cpp b/libc/src/pthread/pthread_rwlockattr_getkind_np.cpp deleted file mode 100644 index 0c821797b42c..000000000000 --- a/libc/src/pthread/pthread_rwlockattr_getkind_np.cpp +++ /dev/null @@ -1,24 +0,0 @@ -//===-- Implementation of the pthread_rwlockattr_getkind_np ---------------===// -// -// 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 "pthread_rwlockattr_getkind_np.h" - -#include "src/__support/common.h" - -#include // pthread_rwlockattr_t - -namespace LIBC_NAMESPACE { - -LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_getkind_np, - (const pthread_rwlockattr_t *__restrict attr, - int *__restrict pref)) { - *pref = attr->pref; - return 0; -} - -} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_getkind_np.h b/libc/src/pthread/pthread_rwlockattr_getkind_np.h deleted file mode 100644 index 51f633cd559d..000000000000 --- a/libc/src/pthread/pthread_rwlockattr_getkind_np.h +++ /dev/null @@ -1,21 +0,0 @@ -//===-- Implementation header for pthread_rwlockattr_getkind_np -*- 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_PTHREAD_PTHREAD_RWLOCKATTR_GETKIND_NP_H -#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_GETKIND_NP_H - -#include - -namespace LIBC_NAMESPACE { - -int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *__restrict attr, - int *__restrict pref); - -} // namespace LIBC_NAMESPACE - -#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_GETKIND_NP_H diff --git a/libc/src/pthread/pthread_rwlockattr_init.cpp b/libc/src/pthread/pthread_rwlockattr_init.cpp index bbc89555c6c1..7971f1714db4 100644 --- a/libc/src/pthread/pthread_rwlockattr_init.cpp +++ b/libc/src/pthread/pthread_rwlockattr_init.cpp @@ -17,7 +17,6 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_init, (pthread_rwlockattr_t * attr)) { attr->pshared = PTHREAD_PROCESS_PRIVATE; - attr->pref = PTHREAD_RWLOCK_PREFER_READER_NP; return 0; } diff --git a/libc/src/pthread/pthread_rwlockattr_setkind_np.cpp b/libc/src/pthread/pthread_rwlockattr_setkind_np.cpp deleted file mode 100644 index 47fbf2a851e5..000000000000 --- a/libc/src/pthread/pthread_rwlockattr_setkind_np.cpp +++ /dev/null @@ -1,30 +0,0 @@ -//===-- Implementation of the pthread_rwlockattr_setkind_np ---------------===// -// -// 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 "pthread_rwlockattr_setkind_np.h" - -#include "src/__support/common.h" - -#include -#include // pthread_rwlockattr_t - -namespace LIBC_NAMESPACE { - -LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_setkind_np, - (pthread_rwlockattr_t * attr, int pref)) { - - if (pref != PTHREAD_RWLOCK_PREFER_READER_NP && - pref != PTHREAD_RWLOCK_PREFER_WRITER_NP && - pref != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP) - return EINVAL; - - attr->pref = pref; - return 0; -} - -} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_setkind_np.h b/libc/src/pthread/pthread_rwlockattr_setkind_np.h deleted file mode 100644 index 00ef8e1bbe00..000000000000 --- a/libc/src/pthread/pthread_rwlockattr_setkind_np.h +++ /dev/null @@ -1,20 +0,0 @@ -//===-- Implementation header for pthread_rwlockattr_setkind_np -*- 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_PTHREAD_PTHREAD_RWLOCKATTR_SETKIND_NP_H -#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_SETKIND_NP_H - -#include - -namespace LIBC_NAMESPACE { - -int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref); - -} // namespace LIBC_NAMESPACE - -#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_SETKIND_NP_H diff --git a/libc/test/src/pthread/CMakeLists.txt b/libc/test/src/pthread/CMakeLists.txt index 0eeec445d5f4..ea75e65f57c9 100644 --- a/libc/test/src/pthread/CMakeLists.txt +++ b/libc/test/src/pthread/CMakeLists.txt @@ -68,9 +68,7 @@ add_libc_unittest( libc.include.errno libc.include.pthread libc.src.pthread.pthread_rwlockattr_destroy - libc.src.pthread.pthread_rwlockattr_getkind_np libc.src.pthread.pthread_rwlockattr_getpshared libc.src.pthread.pthread_rwlockattr_init - libc.src.pthread.pthread_rwlockattr_setkind_np libc.src.pthread.pthread_rwlockattr_setpshared ) diff --git a/libc/test/src/pthread/pthread_rwlockattr_test.cpp b/libc/test/src/pthread/pthread_rwlockattr_test.cpp index 3791f568e222..6e5ae70df734 100644 --- a/libc/test/src/pthread/pthread_rwlockattr_test.cpp +++ b/libc/test/src/pthread/pthread_rwlockattr_test.cpp @@ -8,10 +8,8 @@ #include "include/llvm-libc-macros/generic-error-number-macros.h" // EINVAL #include "src/pthread/pthread_rwlockattr_destroy.h" -#include "src/pthread/pthread_rwlockattr_getkind_np.h" #include "src/pthread/pthread_rwlockattr_getpshared.h" #include "src/pthread/pthread_rwlockattr_init.h" -#include "src/pthread/pthread_rwlockattr_setkind_np.h" #include "src/pthread/pthread_rwlockattr_setpshared.h" #include "test/UnitTest/Test.h" @@ -27,61 +25,40 @@ TEST(LlvmLibcPThreadRWLockAttrTest, InitAndDestroy) { TEST(LlvmLibcPThreadRWLockAttrTest, GetDefaultValues) { pthread_rwlockattr_t attr; - // Invalid values. + // Invalid value. int pshared = 42; - int pref = 1337; ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); - ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getkind_np(&attr, &pref), 0); - ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); - ASSERT_EQ(pref, PTHREAD_RWLOCK_PREFER_READER_NP); - ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); } TEST(LlvmLibcPThreadRWLockAttrTest, SetGoodValues) { pthread_rwlockattr_t attr; - // Invalid values. + // Invalid value. int pshared = 42; - int pref = 1337; ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setpshared( &attr, PTHREAD_PROCESS_SHARED), 0); - ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setkind_np( - &attr, PTHREAD_RWLOCK_PREFER_WRITER_NP), - 0); - ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); - ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getkind_np(&attr, &pref), 0); - ASSERT_EQ(pshared, PTHREAD_PROCESS_SHARED); - ASSERT_EQ(pref, PTHREAD_RWLOCK_PREFER_WRITER_NP); - ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); } TEST(LlvmLibcPThreadRWLockAttrTest, SetBadValues) { pthread_rwlockattr_t attr; - // Invalid values. + // Invalid value. int pshared = 42; - int pref = 1337; ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setpshared(&attr, pshared), EINVAL); - ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setkind_np(&attr, pref), EINVAL); - ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); - ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getkind_np(&attr, &pref), 0); - ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); - ASSERT_EQ(pref, PTHREAD_RWLOCK_PREFER_READER_NP); - ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); } -- GitLab From 25a3ba33153e99c4614d404ba18b761d652e24de Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 13 May 2024 08:42:06 -0500 Subject: [PATCH 062/578] Revert "[flang][OpenMP] Decompose compound constructs, do recursive lowering (#90098)" It breaks some builds, e.g. https://lab.llvm.org/buildbot/#/builders/268/builds/13909 This reverts commit ca1bd5995f6ed934f9187305190a5abfac049173. --- flang/lib/Lower/CMakeLists.txt | 1 - flang/lib/Lower/OpenMP/Clauses.cpp | 23 - flang/lib/Lower/OpenMP/Clauses.h | 13 +- flang/lib/Lower/OpenMP/Decomposer.cpp | 126 -- flang/lib/Lower/OpenMP/Decomposer.h | 51 - flang/lib/Lower/OpenMP/OpenMP.cpp | 828 ++++++------ flang/lib/Lower/OpenMP/Utils.cpp | 6 + flang/lib/Lower/OpenMP/Utils.h | 1 + .../Lower/OpenMP/default-clause-byref.f90 | 5 +- flang/test/Lower/OpenMP/default-clause.f90 | 4 +- .../parallel-lastprivate-clause-scalar.f90 | 4 +- llvm/include/llvm/Frontend/OpenMP/ClauseT.h | 52 +- .../Frontend/OpenMP/ConstructCompositionT.h | 403 ------ .../Frontend/OpenMP/ConstructDecompositionT.h | 1161 ----------------- llvm/unittests/Frontend/CMakeLists.txt | 1 - .../Frontend/OpenMPDecompositionTest.cpp | 999 -------------- 16 files changed, 452 insertions(+), 3226 deletions(-) delete mode 100644 flang/lib/Lower/OpenMP/Decomposer.cpp delete mode 100644 flang/lib/Lower/OpenMP/Decomposer.h delete mode 100644 llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h delete mode 100644 llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h delete mode 100644 llvm/unittests/Frontend/OpenMPDecompositionTest.cpp diff --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt index 1546409752e7..f92d1a2bc7de 100644 --- a/flang/lib/Lower/CMakeLists.txt +++ b/flang/lib/Lower/CMakeLists.txt @@ -27,7 +27,6 @@ add_flang_library(FortranLower OpenMP/ClauseProcessor.cpp OpenMP/Clauses.cpp OpenMP/DataSharingProcessor.cpp - OpenMP/Decomposer.cpp OpenMP/OpenMP.cpp OpenMP/ReductionProcessor.cpp OpenMP/Utils.cpp diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 87370c92964a..97337cfc08c7 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -1227,27 +1227,4 @@ List makeClauses(const parser::OmpClauseList &clauses, return makeClause(s, semaCtx); }); } - -bool transferLocations(const List &from, List &to) { - bool allDone = true; - - for (Clause &clause : to) { - if (!clause.source.empty()) - continue; - auto found = - llvm::find_if(from, [&](const Clause &c) { return c.id == clause.id; }); - // This is not completely accurate, but should be good enough for now. - // It can be improved in the future if necessary, but in cases of - // synthesized clauses getting accurate location may be impossible. - if (found != from.end()) { - clause.source = found->source; - } else { - // Found a clause that won't have "source". - allDone = false; - } - } - - return allDone; -} - } // namespace Fortran::lower::omp diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h index 407579319279..3e776425c733 100644 --- a/flang/lib/Lower/OpenMP/Clauses.h +++ b/flang/lib/Lower/OpenMP/Clauses.h @@ -23,15 +23,11 @@ namespace Fortran::lower::omp { using namespace Fortran; +using SomeType = evaluate::SomeType; using SomeExpr = semantics::SomeExpr; using MaybeExpr = semantics::MaybeExpr; -// evaluate::SomeType doesn't provide == operation. It's not really used in -// flang's clauses so far, so a trivial implementation is sufficient. -struct TypeTy : public evaluate::SomeType { - bool operator==(const TypeTy &t) const { return true; } -}; - +using TypeTy = SomeType; using IdTy = semantics::Symbol *; using ExprTy = SomeExpr; @@ -226,8 +222,6 @@ using When = tomp::clause::WhenT; using Write = tomp::clause::WriteT; } // namespace clause -using tomp::type::operator==; - struct CancellationConstructType { using EmptyTrait = std::true_type; }; @@ -250,7 +244,6 @@ using ClauseBase = tomp::ClauseT; struct Clause : public ClauseBase { - // "source" will be ignored by tomp::type::operator==. parser::CharBlock source; }; @@ -265,8 +258,6 @@ Clause makeClause(const Fortran::parser::OmpClause &cls, List makeClauses(const parser::OmpClauseList &clauses, semantics::SemanticsContext &semaCtx); - -bool transferLocations(const List &from, List &to); } // namespace Fortran::lower::omp #endif // FORTRAN_LOWER_OPENMP_CLAUSES_H diff --git a/flang/lib/Lower/OpenMP/Decomposer.cpp b/flang/lib/Lower/OpenMP/Decomposer.cpp deleted file mode 100644 index e6897cb81e94..000000000000 --- a/flang/lib/Lower/OpenMP/Decomposer.cpp +++ /dev/null @@ -1,126 +0,0 @@ -//===-- Decomposer.cpp -- Compound directive decomposition ----------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ -// -//===----------------------------------------------------------------------===// - -#include "Decomposer.h" - -#include "Clauses.h" -#include "Utils.h" -#include "flang/Lower/PFTBuilder.h" -#include "flang/Semantics/semantics.h" -#include "flang/Tools/CrossToolHelpers.h" -#include "mlir/IR/BuiltinOps.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Frontend/OpenMP/ClauseT.h" -#include "llvm/Frontend/OpenMP/ConstructCompositionT.h" -#include "llvm/Frontend/OpenMP/ConstructDecompositionT.h" -#include "llvm/Frontend/OpenMP/OMP.h" -#include "llvm/Support/raw_ostream.h" - -#include -#include -#include - -using namespace Fortran; - -namespace { -using namespace Fortran::lower::omp; - -struct ConstructDecomposition { - ConstructDecomposition(mlir::ModuleOp modOp, - semantics::SemanticsContext &semaCtx, - lower::pft::Evaluation &ev, - llvm::omp::Directive compound, - const List &clauses) - : semaCtx(semaCtx), mod(modOp), eval(ev) { - tomp::ConstructDecompositionT decompose(getOpenMPVersionAttribute(modOp), - *this, compound, - llvm::ArrayRef(clauses)); - output = std::move(decompose.output); - } - - // Given an object, return its base object if one exists. - std::optional getBaseObject(const Object &object) { - return lower::omp::getBaseObject(object, semaCtx); - } - - // Return the iteration variable of the associated loop if any. - std::optional getLoopIterVar() { - if (semantics::Symbol *symbol = getIterationVariableSymbol(eval)) - return Object{symbol, /*designator=*/{}}; - return std::nullopt; - } - - semantics::SemanticsContext &semaCtx; - mlir::ModuleOp mod; - lower::pft::Evaluation &eval; - List output; -}; -} // namespace - -static UnitConstruct mergeConstructs(uint32_t version, - llvm::ArrayRef units) { - tomp::ConstructCompositionT compose(version, units); - return compose.merged; -} - -namespace Fortran::lower::omp { -LLVM_DUMP_METHOD llvm::raw_ostream &operator<<(llvm::raw_ostream &os, - const UnitConstruct &uc) { - os << llvm::omp::getOpenMPDirectiveName(uc.id); - for (auto [index, clause] : llvm::enumerate(uc.clauses)) { - os << (index == 0 ? '\t' : ' '); - os << llvm::omp::getOpenMPClauseName(clause.id); - } - return os; -} - -ConstructQueue buildConstructQueue( - mlir::ModuleOp modOp, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, const parser::CharBlock &source, - llvm::omp::Directive compound, const List &clauses) { - - List constructs; - - ConstructDecomposition decompose(modOp, semaCtx, eval, compound, clauses); - assert(!decompose.output.empty() && "Construct decomposition failed"); - - llvm::SmallVector loweringUnits; - std::ignore = - llvm::omp::getLeafOrCompositeConstructs(compound, loweringUnits); - uint32_t version = getOpenMPVersionAttribute(modOp); - - int leafIndex = 0; - for (llvm::omp::Directive dir_id : loweringUnits) { - llvm::ArrayRef leafsOrSelf = - llvm::omp::getLeafConstructsOrSelf(dir_id); - size_t numLeafs = leafsOrSelf.size(); - - llvm::ArrayRef toMerge{&decompose.output[leafIndex], - numLeafs}; - auto &uc = constructs.emplace_back(mergeConstructs(version, toMerge)); - - if (!transferLocations(clauses, uc.clauses)) { - // If some clauses are left without source information, use the - // directive's source. - for (auto &clause : uc.clauses) { - if (clause.source.empty()) - clause.source = source; - } - } - leafIndex += numLeafs; - } - - return constructs; -} -} // namespace Fortran::lower::omp diff --git a/flang/lib/Lower/OpenMP/Decomposer.h b/flang/lib/Lower/OpenMP/Decomposer.h deleted file mode 100644 index f42d8f5c1740..000000000000 --- a/flang/lib/Lower/OpenMP/Decomposer.h +++ /dev/null @@ -1,51 +0,0 @@ -//===-- Decomposer.h -- Compound directive decomposition ------------------===// -// -// 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 FORTRAN_LOWER_OPENMP_DECOMPOSER_H -#define FORTRAN_LOWER_OPENMP_DECOMPOSER_H - -#include "Clauses.h" -#include "mlir/IR/BuiltinOps.h" -#include "llvm/Frontend/OpenMP/ConstructCompositionT.h" -#include "llvm/Frontend/OpenMP/ConstructDecompositionT.h" -#include "llvm/Frontend/OpenMP/OMP.h" -#include "llvm/Support/Compiler.h" - -namespace llvm { -class raw_ostream; -} - -namespace Fortran { -namespace semantics { -class SemanticsContext; -} -namespace lower::pft { -struct Evaluation; -} -} // namespace Fortran - -namespace Fortran::lower::omp { -using UnitConstruct = tomp::DirectiveWithClauses; -using ConstructQueue = List; - -LLVM_DUMP_METHOD llvm::raw_ostream &operator<<(llvm::raw_ostream &os, - const UnitConstruct &uc); - -// Given a potentially compound construct with a list of clauses that -// apply to it, break it up into individual sub-constructs each with -// the subset of applicable clauses (plus implicit clauses, if any). -// From that create a work queue where each work item corresponds to -// the sub-construct with its clauses. -ConstructQueue buildConstructQueue(mlir::ModuleOp modOp, - semantics::SemanticsContext &semaCtx, - lower::pft::Evaluation &eval, - const parser::CharBlock &source, - llvm::omp::Directive compound, - const List &clauses); -} // namespace Fortran::lower::omp - -#endif // FORTRAN_LOWER_OPENMP_DECOMPOSER_H diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index eaf4b5f997ff..f23902d6a823 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -15,7 +15,6 @@ #include "ClauseProcessor.h" #include "Clauses.h" #include "DataSharingProcessor.h" -#include "Decomposer.h" #include "DirectivesCommon.h" #include "ReductionProcessor.h" #include "Utils.h" @@ -45,13 +44,6 @@ using namespace Fortran::lower::omp; // Code generation helper functions //===----------------------------------------------------------------------===// -static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - mlir::Location loc, const ConstructQueue &queue, - ConstructQueue::iterator item); - static Fortran::lower::pft::Evaluation * getCollapsedLoopEval(Fortran::lower::pft::Evaluation &eval, int collapseValue) { // Return the Evaluation of the innermost collapsed loop, or the current one @@ -468,6 +460,81 @@ markDeclareTarget(mlir::Operation *op, declareTargetOp.setDeclareTarget(deviceType, captureClause); } +/// Split a combined directive into an outer leaf directive and the (possibly +/// combined) rest of the combined directive. Composite directives and +/// non-compound directives are not split, in which case it will return the +/// input directive as its first output and an empty value as its second output. +static std::pair> +splitCombinedDirective(llvm::omp::Directive dir) { + using D = llvm::omp::Directive; + switch (dir) { + case D::OMPD_masked_taskloop: + return {D::OMPD_masked, D::OMPD_taskloop}; + case D::OMPD_masked_taskloop_simd: + return {D::OMPD_masked, D::OMPD_taskloop_simd}; + case D::OMPD_master_taskloop: + return {D::OMPD_master, D::OMPD_taskloop}; + case D::OMPD_master_taskloop_simd: + return {D::OMPD_master, D::OMPD_taskloop_simd}; + case D::OMPD_parallel_do: + return {D::OMPD_parallel, D::OMPD_do}; + case D::OMPD_parallel_do_simd: + return {D::OMPD_parallel, D::OMPD_do_simd}; + case D::OMPD_parallel_masked: + return {D::OMPD_parallel, D::OMPD_masked}; + case D::OMPD_parallel_masked_taskloop: + return {D::OMPD_parallel, D::OMPD_masked_taskloop}; + case D::OMPD_parallel_masked_taskloop_simd: + return {D::OMPD_parallel, D::OMPD_masked_taskloop_simd}; + case D::OMPD_parallel_master: + return {D::OMPD_parallel, D::OMPD_master}; + case D::OMPD_parallel_master_taskloop: + return {D::OMPD_parallel, D::OMPD_master_taskloop}; + case D::OMPD_parallel_master_taskloop_simd: + return {D::OMPD_parallel, D::OMPD_master_taskloop_simd}; + case D::OMPD_parallel_sections: + return {D::OMPD_parallel, D::OMPD_sections}; + case D::OMPD_parallel_workshare: + return {D::OMPD_parallel, D::OMPD_workshare}; + case D::OMPD_target_parallel: + return {D::OMPD_target, D::OMPD_parallel}; + case D::OMPD_target_parallel_do: + return {D::OMPD_target, D::OMPD_parallel_do}; + case D::OMPD_target_parallel_do_simd: + return {D::OMPD_target, D::OMPD_parallel_do_simd}; + case D::OMPD_target_simd: + return {D::OMPD_target, D::OMPD_simd}; + case D::OMPD_target_teams: + return {D::OMPD_target, D::OMPD_teams}; + case D::OMPD_target_teams_distribute: + return {D::OMPD_target, D::OMPD_teams_distribute}; + case D::OMPD_target_teams_distribute_parallel_do: + return {D::OMPD_target, D::OMPD_teams_distribute_parallel_do}; + case D::OMPD_target_teams_distribute_parallel_do_simd: + return {D::OMPD_target, D::OMPD_teams_distribute_parallel_do_simd}; + case D::OMPD_target_teams_distribute_simd: + return {D::OMPD_target, D::OMPD_teams_distribute_simd}; + case D::OMPD_teams_distribute: + return {D::OMPD_teams, D::OMPD_distribute}; + case D::OMPD_teams_distribute_parallel_do: + return {D::OMPD_teams, D::OMPD_distribute_parallel_do}; + case D::OMPD_teams_distribute_parallel_do_simd: + return {D::OMPD_teams, D::OMPD_distribute_parallel_do_simd}; + case D::OMPD_teams_distribute_simd: + return {D::OMPD_teams, D::OMPD_distribute_simd}; + case D::OMPD_parallel_loop: + return {D::OMPD_parallel, D::OMPD_loop}; + case D::OMPD_target_parallel_loop: + return {D::OMPD_target, D::OMPD_parallel_loop}; + case D::OMPD_target_teams_loop: + return {D::OMPD_target, D::OMPD_teams_loop}; + case D::OMPD_teams_loop: + return {D::OMPD_teams, D::OMPD_loop}; + default: + return {dir, std::nullopt}; + } +} + //===----------------------------------------------------------------------===// // Op body generation helper structures and functions //===----------------------------------------------------------------------===// @@ -488,6 +555,11 @@ struct OpWithBodyGenInfo { : converter(converter), symTable(symTable), semaCtx(semaCtx), loc(loc), eval(eval), dir(dir) {} + OpWithBodyGenInfo &setGenNested(bool value) { + genNested = value; + return *this; + } + OpWithBodyGenInfo &setOuterCombined(bool value) { outerCombined = value; return *this; @@ -528,6 +600,8 @@ struct OpWithBodyGenInfo { Fortran::lower::pft::Evaluation &eval; /// [in] leaf directive for which to generate the op body. llvm::omp::Directive dir; + /// [in] whether to generate FIR for nested evaluations + bool genNested = true; /// [in] is this an outer operation - prevents privatization. bool outerCombined = false; /// [in] list of clauses to process. @@ -546,13 +620,9 @@ struct OpWithBodyGenInfo { /// Create the body (block) for an OpenMP Operation. /// -/// \param [in] op - the operation the body belongs to. -/// \param [in] info - options controlling code-gen for the construction. -/// \param [in] queue - work queue with nested constructs. -/// \param [in] item - item in the queue to generate body for. -static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, - const ConstructQueue &queue, - ConstructQueue::iterator item) { +/// \param [in] op - the operation the body belongs to. +/// \param [in] info - options controlling code-gen for the construction. +static void createBodyOfOp(mlir::Operation &op, OpWithBodyGenInfo &info) { fir::FirOpBuilder &firOpBuilder = info.converter.getFirOpBuilder(); auto insertMarker = [](fir::FirOpBuilder &builder) { @@ -608,10 +678,7 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, } } - if (ConstructQueue::iterator next = std::next(item); next != queue.end()) { - genOMPDispatch(info.converter, info.symTable, info.semaCtx, info.eval, - info.loc, queue, next); - } else { + if (info.genNested) { // genFIR(Evaluation&) tries to patch up unterminated blocks, causing // a lot of complications for our approach if the terminator generation // is delayed past this point. Insert a temporary terminator here, then @@ -702,12 +769,11 @@ static void genBodyOfTargetDataOp( Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::omp::TargetDataOp &dataOp, - llvm::ArrayRef useDeviceTypes, + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::omp::TargetDataOp &dataOp, llvm::ArrayRef useDeviceTypes, llvm::ArrayRef useDeviceLocs, llvm::ArrayRef useDeviceSymbols, - const mlir::Location ¤tLocation, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const mlir::Location ¤tLocation) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Region ®ion = dataOp.getRegion(); @@ -760,13 +826,8 @@ static void genBodyOfTargetDataOp( // Set the insertion point after the marker. firOpBuilder.setInsertionPointAfter(undefMarker.getDefiningOp()); - - if (ConstructQueue::iterator next = std::next(item); next != queue.end()) { - genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, - next); - } else { + if (genNested) genNestedEvaluations(converter, eval); - } } // This functions creates a block for the body of the targetOp's region. It adds @@ -775,13 +836,12 @@ static void genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, + Fortran::lower::pft::Evaluation &eval, bool genNested, mlir::omp::TargetOp &targetOp, llvm::ArrayRef mapSyms, llvm::ArrayRef mapSymLocs, llvm::ArrayRef mapSymTypes, - const mlir::Location ¤tLocation, - const ConstructQueue &queue, ConstructQueue::iterator item) { + const mlir::Location ¤tLocation) { assert(mapSymTypes.size() == mapSymLocs.size()); fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); @@ -923,22 +983,15 @@ genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, // Create the insertion point after the marker. firOpBuilder.setInsertionPointAfter(undefMarker.getDefiningOp()); - - if (ConstructQueue::iterator next = std::next(item); next != queue.end()) { - genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, - next); - } else { + if (genNested) genNestedEvaluations(converter, eval); - } } template -static OpTy genOpWithBody(const OpWithBodyGenInfo &info, - const ConstructQueue &queue, - ConstructQueue::iterator item, Args &&...args) { +static OpTy genOpWithBody(OpWithBodyGenInfo &info, Args &&...args) { auto op = info.converter.getFirOpBuilder().create( info.loc, std::forward(args)...); - createBodyOfOp(*op, info, queue, item); + createBodyOfOp(*op, info); return op; } @@ -1223,8 +1276,7 @@ static mlir::omp::BarrierOp genBarrierOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc) { return converter.getFirOpBuilder().create(loc); } @@ -1232,9 +1284,8 @@ static mlir::omp::CriticalOp genCriticalOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item, + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc, const List &clauses, const std::optional &name) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::FlatSymbolRefAttr nameAttr; @@ -1257,17 +1308,17 @@ genCriticalOp(Fortran::lower::AbstractConverter &converter, return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, - llvm::omp::Directive::OMPD_critical), - queue, item, nameAttr); + llvm::omp::Directive::OMPD_critical) + .setGenNested(genNested), + nameAttr); } static mlir::omp::DistributeOp genDistributeOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc, const List &clauses) { TODO(loc, "Distribute construct"); return nullptr; } @@ -1277,8 +1328,7 @@ genFlushOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ObjectList &objects, const List &clauses, - const ConstructQueue &queue, ConstructQueue::iterator item) { + const ObjectList &objects, const List &clauses) { llvm::SmallVector operandRange; genFlushClauses(converter, semaCtx, objects, clauses, loc, operandRange); @@ -1290,13 +1340,12 @@ static mlir::omp::MasterOp genMasterOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc) { return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, - llvm::omp::Directive::OMPD_master), - queue, item); + llvm::omp::Directive::OMPD_master) + .setGenNested(genNested)); } static mlir::omp::OrderedOp @@ -1304,8 +1353,7 @@ genOrderedOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const List &clauses) { TODO(loc, "OMPD_ordered"); return nullptr; } @@ -1314,25 +1362,25 @@ static mlir::omp::OrderedRegionOp genOrderedRegionOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc, const List &clauses) { mlir::omp::OrderedRegionClauseOps clauseOps; genOrderedRegionClauses(converter, semaCtx, clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, - llvm::omp::Directive::OMPD_ordered), - queue, item, clauseOps); + llvm::omp::Directive::OMPD_ordered) + .setGenNested(genNested), + clauseOps); } static mlir::omp::ParallelOp genParallelOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item, bool outerCombined = false) { + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc, const List &clauses, + bool outerCombined = false) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; mlir::omp::ParallelClauseOps clauseOps; @@ -1351,14 +1399,14 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, OpWithBodyGenInfo genInfo = OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_parallel) + .setGenNested(genNested) .setOuterCombined(outerCombined) .setClauses(&clauses) .setReductions(&reductionSyms, &reductionTypes) .setGenRegionEntryCb(reductionCallback); if (!enableDelayedPrivatization) - return genOpWithBody(genInfo, queue, item, - clauseOps); + return genOpWithBody(genInfo, clauseOps); bool privatize = !outerCombined; DataSharingProcessor dsp(converter, semaCtx, clauses, eval, @@ -1406,23 +1454,19 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, }; genInfo.setGenRegionEntryCb(genRegionEntryCB).setDataSharingProcessor(&dsp); - return genOpWithBody(genInfo, queue, item, clauseOps); + return genOpWithBody(genInfo, clauseOps); } static mlir::omp::SectionOp genSectionOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { - // Currently only private/firstprivate clause is handled, and - // all privatization is done within `omp.section` operations. + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc) { return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_section) - .setClauses(&clauses), - queue, item); + .setGenNested(genNested)); } static mlir::omp::SectionsOp @@ -1430,77 +1474,12 @@ genSectionsOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { - mlir::omp::SectionsClauseOps clauseOps; - genSectionsClauses(converter, semaCtx, clauses, loc, clauseOps); - - auto &builder = converter.getFirOpBuilder(); - - // Insert privatizations before SECTIONS - symTable.pushScope(); - DataSharingProcessor dsp(converter, semaCtx, clauses, eval); - dsp.processStep1(); - - List nonDsaClauses; - List lastprivates; - - for (const Clause &clause : clauses) { - if (clause.id == llvm::omp::Clause::OMPC_lastprivate) { - lastprivates.push_back(&std::get(clause.u)); - } else { - switch (clause.id) { - case llvm::omp::Clause::OMPC_firstprivate: - case llvm::omp::Clause::OMPC_private: - case llvm::omp::Clause::OMPC_shared: - break; - default: - nonDsaClauses.push_back(clause); - } - } - } - - // SECTIONS construct. - mlir::omp::SectionsOp sectionsOp = genOpWithBody( + const mlir::omp::SectionsClauseOps &clauseOps) { + return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_sections) - .setClauses(&nonDsaClauses), - queue, item, clauseOps); - - if (!lastprivates.empty()) { - mlir::Region §ionsBody = sectionsOp.getRegion(); - assert(sectionsBody.hasOneBlock()); - mlir::Block &body = sectionsBody.front(); - - auto lastSectionOp = llvm::find_if( - llvm::reverse(body.getOperations()), [](const mlir::Operation &op) { - return llvm::isa(op); - }); - assert(lastSectionOp != body.rend()); - - for (const clause::Lastprivate *lastp : lastprivates) { - builder.setInsertionPoint( - lastSectionOp->getRegion(0).back().getTerminator()); - mlir::OpBuilder::InsertPoint insp = builder.saveInsertionPoint(); - const auto &objList = std::get(lastp->t); - for (const Object &object : objList) { - Fortran::semantics::Symbol *sym = object.id(); - converter.copyHostAssociateVar(*sym, &insp); - } - } - } - - // Perform DataSharingProcessor's step2 out of SECTIONS - builder.setInsertionPointAfter(sectionsOp.getOperation()); - dsp.processStep2(sectionsOp, false); - // Emit implicit barrier to synchronize threads and avoid data - // races on post-update of lastprivate variables when `nowait` - // clause is present. - if (clauseOps.nowaitAttr && !lastprivates.empty()) - builder.create(loc); - - symTable.popScope(); - return sectionsOp; + .setGenNested(false), + clauseOps); } static mlir::omp::SimdOp @@ -1508,8 +1487,7 @@ genSimdOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const List &clauses) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); DataSharingProcessor dsp(converter, semaCtx, clauses, eval); dsp.processStep1(); @@ -1544,8 +1522,7 @@ genSimdOp(Fortran::lower::AbstractConverter &converter, *nestedEval, llvm::omp::Directive::OMPD_simd) .setClauses(&clauses) .setDataSharingProcessor(&dsp) - .setGenRegionEntryCb(ivCallback), - queue, item); + .setGenRegionEntryCb(ivCallback)); return simdOp; } @@ -1554,26 +1531,26 @@ static mlir::omp::SingleOp genSingleOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc, const List &clauses) { mlir::omp::SingleClauseOps clauseOps; genSingleClauses(converter, semaCtx, clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_single) + .setGenNested(genNested) .setClauses(&clauses), - queue, item, clauseOps); + clauseOps); } static mlir::omp::TargetOp genTargetOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item, bool outerCombined = false) { + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc, const List &clauses, + bool outerCombined = false) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; @@ -1680,8 +1657,8 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::visitAllSymbols(eval, captureImplicitMap); auto targetOp = firOpBuilder.create(loc, clauseOps); - genBodyOfTargetOp(converter, symTable, semaCtx, eval, targetOp, mapSyms, - mapLocs, mapTypes, loc, queue, item); + genBodyOfTargetOp(converter, symTable, semaCtx, eval, genNested, targetOp, + mapSyms, mapLocs, mapTypes, loc); return targetOp; } @@ -1689,9 +1666,8 @@ static mlir::omp::TargetDataOp genTargetDataOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc, const List &clauses) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TargetDataClauseOps clauseOps; llvm::SmallVector useDeviceTypes; @@ -1703,9 +1679,9 @@ genTargetDataOp(Fortran::lower::AbstractConverter &converter, auto targetDataOp = converter.getFirOpBuilder().create(loc, clauseOps); - genBodyOfTargetDataOp(converter, symTable, semaCtx, eval, targetDataOp, - useDeviceTypes, useDeviceLocs, useDeviceSyms, loc, - queue, item); + genBodyOfTargetDataOp(converter, symTable, semaCtx, eval, genNested, + targetDataOp, useDeviceTypes, useDeviceLocs, + useDeviceSyms, loc); return targetDataOp; } @@ -1714,9 +1690,8 @@ static OpTy genTargetEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - mlir::Location loc, const List &clauses, - const ConstructQueue &queue, - ConstructQueue::iterator item) { + mlir::Location loc, + const List &clauses) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; @@ -1743,9 +1718,8 @@ static mlir::omp::TaskOp genTaskOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc, const List &clauses) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TaskClauseOps clauseOps; genTaskClauses(converter, semaCtx, stmtCtx, clauses, loc, clauseOps); @@ -1753,25 +1727,26 @@ genTaskOp(Fortran::lower::AbstractConverter &converter, return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_task) + .setGenNested(genNested) .setClauses(&clauses), - queue, item, clauseOps); + clauseOps); } static mlir::omp::TaskgroupOp genTaskgroupOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc, const List &clauses) { mlir::omp::TaskgroupClauseOps clauseOps; genTaskgroupClauses(converter, semaCtx, clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_taskgroup) + .setGenNested(genNested) .setClauses(&clauses), - queue, item, clauseOps); + clauseOps); } static mlir::omp::TaskloopOp @@ -1779,8 +1754,7 @@ genTaskloopOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const List &clauses) { TODO(loc, "Taskloop construct"); } @@ -1789,8 +1763,7 @@ genTaskwaitOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const List &clauses) { mlir::omp::TaskwaitClauseOps clauseOps; genTaskwaitClauses(converter, semaCtx, clauses, loc, clauseOps); return converter.getFirOpBuilder().create(loc, @@ -1801,8 +1774,7 @@ static mlir::omp::TaskyieldOp genTaskyieldOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc) { return converter.getFirOpBuilder().create(loc); } @@ -1810,9 +1782,9 @@ static mlir::omp::TeamsOp genTeamsOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item, bool outerCombined = false) { + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location loc, const List &clauses, + bool outerCombined = false) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TeamsClauseOps clauseOps; genTeamsClauses(converter, semaCtx, stmtCtx, clauses, loc, clauseOps); @@ -1820,9 +1792,10 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter, return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_teams) + .setGenNested(genNested) .setOuterCombined(outerCombined) .setClauses(&clauses), - queue, item, clauseOps); + clauseOps); } static mlir::omp::WsloopOp @@ -1830,8 +1803,7 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const List &clauses) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); DataSharingProcessor dsp(converter, semaCtx, clauses, eval); dsp.processStep1(); @@ -1872,8 +1844,7 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, .setClauses(&clauses) .setDataSharingProcessor(&dsp) .setReductions(&reductionSyms, &reductionTypes) - .setGenRegionEntryCb(ivCallback), - queue, item); + .setGenRegionEntryCb(ivCallback)); return wsloopOp; } @@ -1881,13 +1852,13 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, // Code generation functions for composite constructs //===----------------------------------------------------------------------===// -static void genCompositeDistributeParallelDo( - Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { +static void +genCompositeDistributeParallelDo(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const List &clauses, + mlir::Location loc) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO"); } @@ -1895,9 +1866,8 @@ static void genCompositeDistributeParallelDoSimd( Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + Fortran::lower::pft::Evaluation &eval, const List &clauses, + mlir::Location loc) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO SIMD"); } @@ -1906,9 +1876,7 @@ genCompositeDistributeSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - mlir::Location loc, const List &clauses, - const ConstructQueue &queue, - ConstructQueue::iterator item) { + const List &clauses, mlir::Location loc) { TODO(loc, "Composite DISTRIBUTE SIMD"); } @@ -1916,9 +1884,8 @@ static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - mlir::Location loc, const List &clauses, - const ConstructQueue &queue, - ConstructQueue::iterator item) { + const List &clauses, + mlir::Location loc) { ClauseProcessor cp(converter, semaCtx, clauses); cp.processTODO( @@ -1931,7 +1898,7 @@ static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, // When support for vectorization is enabled, then we need to add handling of // if clause. Currently if clause can be skipped because we always assume // SIMD length = 1. - genWsloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + genWsloopOp(converter, symTable, semaCtx, eval, loc, clauses); } static void @@ -1939,128 +1906,10 @@ genCompositeTaskloopSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - mlir::Location loc, const List &clauses, - const ConstructQueue &queue, - ConstructQueue::iterator item) { + const List &clauses, mlir::Location loc) { TODO(loc, "Composite TASKLOOP SIMD"); } -//===----------------------------------------------------------------------===// -// Dispatch -//===----------------------------------------------------------------------===// - -static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - mlir::Location loc, const ConstructQueue &queue, - ConstructQueue::iterator item) { - assert(item != queue.end()); - const List &clauses = item->clauses; - - switch (llvm::omp::Directive dir = item->id) { - case llvm::omp::Directive::OMPD_distribute: - genDistributeOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); - break; - case llvm::omp::Directive::OMPD_do: - genWsloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); - break; - case llvm::omp::Directive::OMPD_loop: - case llvm::omp::Directive::OMPD_masked: - case llvm::omp::Directive::OMPD_tile: - case llvm::omp::Directive::OMPD_unroll: - TODO(loc, "Unhandled loop directive (" + - llvm::omp::getOpenMPDirectiveName(dir) + ")"); - break; - case llvm::omp::Directive::OMPD_master: - genMasterOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); - break; - case llvm::omp::Directive::OMPD_ordered: - genOrderedRegionOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); - break; - case llvm::omp::Directive::OMPD_parallel: - genParallelOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item, - /*outerCombined=*/false); - break; - case llvm::omp::Directive::OMPD_sections: - genSectionsOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); - break; - case llvm::omp::Directive::OMPD_simd: - genSimdOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); - break; - case llvm::omp::Directive::OMPD_single: - genSingleOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); - break; - case llvm::omp::Directive::OMPD_target: - genTargetOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item, - /*outerCombined=*/false); - break; - case llvm::omp::Directive::OMPD_target_data: - genTargetDataOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); - break; - case llvm::omp::Directive::OMPD_target_enter_data: - genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, loc, clauses, queue, item); - break; - case llvm::omp::Directive::OMPD_target_exit_data: - genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, loc, clauses, queue, item); - break; - case llvm::omp::Directive::OMPD_target_update: - genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, loc, clauses, queue, item); - break; - case llvm::omp::Directive::OMPD_task: - genTaskOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); - break; - case llvm::omp::Directive::OMPD_taskgroup: - genTaskgroupOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); - break; - case llvm::omp::Directive::OMPD_taskloop: - genTaskloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); - break; - case llvm::omp::Directive::OMPD_teams: - genTeamsOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); - break; - // case llvm::omp::Directive::OMPD_workdistribute: - case llvm::omp::Directive::OMPD_workshare: - // FIXME: Workshare is not a commonly used OpenMP construct, an - // implementation for this feature will come later. For the codes - // that use this construct, add a single construct for now. - genSingleOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); - break; - // Composite constructs - case llvm::omp::Directive::OMPD_distribute_parallel_do: - genCompositeDistributeParallelDo(converter, symTable, semaCtx, eval, loc, - clauses, queue, item); - break; - case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: - genCompositeDistributeParallelDoSimd(converter, symTable, semaCtx, eval, - loc, clauses, queue, item); - break; - case llvm::omp::Directive::OMPD_distribute_simd: - genCompositeDistributeSimd(converter, symTable, semaCtx, eval, loc, clauses, - queue, item); - break; - case llvm::omp::Directive::OMPD_do_simd: - genCompositeDoSimd(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); - break; - case llvm::omp::Directive::OMPD_taskloop_simd: - genCompositeTaskloopSimd(converter, symTable, semaCtx, eval, loc, clauses, - queue, item); - break; - default: - break; - } -} - //===----------------------------------------------------------------------===// // OpenMPDeclarativeConstruct visitors //===----------------------------------------------------------------------===// @@ -2171,47 +2020,36 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, semaCtx); mlir::Location currentLocation = converter.genLocation(directive.source); - ConstructQueue queue{ - buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, - eval, directive.source, directive.v, clauses)}; - switch (directive.v) { default: break; case llvm::omp::Directive::OMPD_barrier: - genBarrierOp(converter, symTable, semaCtx, eval, currentLocation, queue, - queue.begin()); + genBarrierOp(converter, symTable, semaCtx, eval, currentLocation); break; case llvm::omp::Directive::OMPD_taskwait: - genTaskwaitOp(converter, symTable, semaCtx, eval, currentLocation, clauses, - queue, queue.begin()); + genTaskwaitOp(converter, symTable, semaCtx, eval, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_taskyield: - genTaskyieldOp(converter, symTable, semaCtx, eval, currentLocation, queue, - queue.begin()); + genTaskyieldOp(converter, symTable, semaCtx, eval, currentLocation); break; case llvm::omp::Directive::OMPD_target_data: - genTargetDataOp(converter, symTable, semaCtx, eval, currentLocation, - clauses, queue, queue.begin()); + genTargetDataOp(converter, symTable, semaCtx, eval, /*genNested=*/true, + currentLocation, clauses); break; case llvm::omp::Directive::OMPD_target_enter_data: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses, queue, - queue.begin()); + converter, symTable, semaCtx, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_target_exit_data: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses, queue, - queue.begin()); + converter, symTable, semaCtx, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_target_update: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses, queue, - queue.begin()); + converter, symTable, semaCtx, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_ordered: - genOrderedOp(converter, symTable, semaCtx, eval, currentLocation, clauses, - queue, queue.begin()); + genOrderedOp(converter, symTable, semaCtx, eval, currentLocation, clauses); break; } } @@ -2235,12 +2073,8 @@ genOMP(Fortran::lower::AbstractConverter &converter, [&](auto &&s) { return makeClause(s.v, semaCtx); }) : List{}; mlir::Location currentLocation = converter.genLocation(verbatim.source); - - ConstructQueue queue{buildConstructQueue( - converter.getFirOpBuilder().getModule(), semaCtx, eval, verbatim.source, - llvm::omp::Directive::OMPD_flush, clauses)}; genFlushOp(converter, symTable, semaCtx, eval, currentLocation, objects, - clauses, queue, queue.begin()); + clauses); } static void @@ -2383,15 +2217,75 @@ genOMP(Fortran::lower::AbstractConverter &converter, } } - llvm::omp::Directive directive = - std::get(beginBlockDirective.t).v; - const parser::CharBlock &source = - std::get(beginBlockDirective.t).source; - ConstructQueue queue{ - buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, - eval, source, directive, clauses)}; - genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, - queue.begin()); + std::optional nextDir = origDirective; + bool outermostLeafConstruct = true; + while (nextDir) { + llvm::omp::Directive leafDir; + std::tie(leafDir, nextDir) = splitCombinedDirective(*nextDir); + const bool genNested = !nextDir; + const bool outerCombined = outermostLeafConstruct && nextDir.has_value(); + switch (leafDir) { + case llvm::omp::Directive::OMPD_master: + // 2.16 MASTER construct. + genMasterOp(converter, symTable, semaCtx, eval, genNested, + currentLocation); + break; + case llvm::omp::Directive::OMPD_ordered: + // 2.17.9 ORDERED construct. + genOrderedRegionOp(converter, symTable, semaCtx, eval, genNested, + currentLocation, clauses); + break; + case llvm::omp::Directive::OMPD_parallel: + // 2.6 PARALLEL construct. + genParallelOp(converter, symTable, semaCtx, eval, genNested, + currentLocation, clauses, outerCombined); + break; + case llvm::omp::Directive::OMPD_single: + // 2.8.2 SINGLE construct. + genSingleOp(converter, symTable, semaCtx, eval, genNested, + currentLocation, clauses); + break; + case llvm::omp::Directive::OMPD_target: + // 2.12.5 TARGET construct. + genTargetOp(converter, symTable, semaCtx, eval, genNested, + currentLocation, clauses, outerCombined); + break; + case llvm::omp::Directive::OMPD_target_data: + // 2.12.2 TARGET DATA construct. + genTargetDataOp(converter, symTable, semaCtx, eval, genNested, + currentLocation, clauses); + break; + case llvm::omp::Directive::OMPD_task: + // 2.10.1 TASK construct. + genTaskOp(converter, symTable, semaCtx, eval, genNested, currentLocation, + clauses); + break; + case llvm::omp::Directive::OMPD_taskgroup: + // 2.17.6 TASKGROUP construct. + genTaskgroupOp(converter, symTable, semaCtx, eval, genNested, + currentLocation, clauses); + break; + case llvm::omp::Directive::OMPD_teams: + // 2.7 TEAMS construct. + // FIXME Pass the outerCombined argument or rename it to better describe + // what it represents if it must always be `false` in this context. + genTeamsOp(converter, symTable, semaCtx, eval, genNested, currentLocation, + clauses); + break; + case llvm::omp::Directive::OMPD_workshare: + // 2.8.3 WORKSHARE construct. + // FIXME: Workshare is not a commonly used OpenMP construct, an + // implementation for this feature will come later. For the codes + // that use this construct, add a single construct for now. + genSingleOp(converter, symTable, semaCtx, eval, genNested, + currentLocation, clauses); + break; + default: + llvm_unreachable("Unexpected block construct"); + break; + } + outermostLeafConstruct = false; + } } static void @@ -2404,15 +2298,10 @@ genOMP(Fortran::lower::AbstractConverter &converter, std::get(criticalConstruct.t); List clauses = makeClauses(std::get(cd.t), semaCtx); - - ConstructQueue queue{buildConstructQueue( - converter.getFirOpBuilder().getModule(), semaCtx, eval, cd.source, - llvm::omp::Directive::OMPD_critical, clauses)}; - const auto &name = std::get>(cd.t); mlir::Location currentLocation = converter.getCurrentLocation(); - genCriticalOp(converter, symTable, semaCtx, eval, currentLocation, clauses, - queue, queue.begin(), name); + genCriticalOp(converter, symTable, semaCtx, eval, /*genNested=*/true, + currentLocation, clauses, name); } static void @@ -2433,6 +2322,14 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, std::get(loopConstruct.t); List clauses = makeClauses( std::get(beginLoopDirective.t), semaCtx); + mlir::Location currentLocation = + converter.genLocation(beginLoopDirective.source); + const auto origDirective = + std::get(beginLoopDirective.t).v; + + assert(llvm::omp::loopConstructSet.test(origDirective) && + "Expected loop construct"); + if (auto &endLoopDirective = std::get>( loopConstruct.t)) { @@ -2441,18 +2338,101 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, semaCtx)); } - mlir::Location currentLocation = - converter.genLocation(beginLoopDirective.source); - - llvm::omp::Directive directive = - std::get(beginLoopDirective.t).v; - const parser::CharBlock &source = - std::get(beginLoopDirective.t).source; - ConstructQueue queue{ - buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, - eval, source, directive, clauses)}; - genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, - queue.begin()); + std::optional nextDir = origDirective; + while (nextDir) { + llvm::omp::Directive leafDir; + std::tie(leafDir, nextDir) = splitCombinedDirective(*nextDir); + if (llvm::omp::compositeConstructSet.test(leafDir)) { + assert(!nextDir && "Composite construct cannot be split"); + switch (leafDir) { + case llvm::omp::Directive::OMPD_distribute_parallel_do: + // 2.9.4.3 DISTRIBUTE PARALLEL Worksharing-Loop construct. + genCompositeDistributeParallelDo(converter, symTable, semaCtx, eval, + clauses, currentLocation); + break; + case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: + // 2.9.4.4 DISTRIBUTE PARALLEL Worksharing-Loop SIMD construct. + genCompositeDistributeParallelDoSimd(converter, symTable, semaCtx, eval, + clauses, currentLocation); + break; + case llvm::omp::Directive::OMPD_distribute_simd: + // 2.9.4.2 DISTRIBUTE SIMD construct. + genCompositeDistributeSimd(converter, symTable, semaCtx, eval, clauses, + currentLocation); + break; + case llvm::omp::Directive::OMPD_do_simd: + // 2.9.3.2 Worksharing-Loop SIMD construct. + genCompositeDoSimd(converter, symTable, semaCtx, eval, clauses, + currentLocation); + break; + case llvm::omp::Directive::OMPD_taskloop_simd: + // 2.10.3 TASKLOOP SIMD construct. + genCompositeTaskloopSimd(converter, symTable, semaCtx, eval, clauses, + currentLocation); + break; + default: + llvm_unreachable("Unexpected composite construct"); + } + } else { + const bool genNested = !nextDir; + switch (leafDir) { + case llvm::omp::Directive::OMPD_distribute: + // 2.9.4.1 DISTRIBUTE construct. + genDistributeOp(converter, symTable, semaCtx, eval, genNested, + currentLocation, clauses); + break; + case llvm::omp::Directive::OMPD_do: + // 2.9.2 Worksharing-Loop construct. + genWsloopOp(converter, symTable, semaCtx, eval, currentLocation, + clauses); + break; + case llvm::omp::Directive::OMPD_parallel: + // 2.6 PARALLEL construct. + // FIXME This is not necessarily always the outer leaf construct of a + // combined construct in this constext (e.g. distribute parallel do). + // Maybe rename the argument if it represents something else or + // initialize it properly. + genParallelOp(converter, symTable, semaCtx, eval, genNested, + currentLocation, clauses, + /*outerCombined=*/true); + break; + case llvm::omp::Directive::OMPD_simd: + // 2.9.3.1 SIMD construct. + genSimdOp(converter, symTable, semaCtx, eval, currentLocation, clauses); + break; + case llvm::omp::Directive::OMPD_target: + // 2.12.5 TARGET construct. + genTargetOp(converter, symTable, semaCtx, eval, genNested, + currentLocation, clauses, /*outerCombined=*/true); + break; + case llvm::omp::Directive::OMPD_taskloop: + // 2.10.2 TASKLOOP construct. + genTaskloopOp(converter, symTable, semaCtx, eval, currentLocation, + clauses); + break; + case llvm::omp::Directive::OMPD_teams: + // 2.7 TEAMS construct. + // FIXME This is not necessarily always the outer leaf construct of a + // combined construct in this constext (e.g. target teams distribute). + // Maybe rename the argument if it represents something else or + // initialize it properly. + genTeamsOp(converter, symTable, semaCtx, eval, genNested, + currentLocation, clauses, /*outerCombined=*/true); + break; + case llvm::omp::Directive::OMPD_loop: + case llvm::omp::Directive::OMPD_masked: + case llvm::omp::Directive::OMPD_master: + case llvm::omp::Directive::OMPD_tile: + case llvm::omp::Directive::OMPD_unroll: + TODO(currentLocation, "Unhandled loop directive (" + + llvm::omp::getOpenMPDirectiveName(leafDir) + + ")"); + break; + default: + llvm_unreachable("Unexpected loop construct"); + } + } + } } static void @@ -2461,12 +2441,8 @@ genOMP(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPSectionConstruct §ionConstruct) { - mlir::Location loc = converter.getCurrentLocation(); - ConstructQueue queue{buildConstructQueue( - converter.getFirOpBuilder().getModule(), semaCtx, eval, - sectionConstruct.source, llvm::omp::Directive::OMPD_section, {})}; - genSectionOp(converter, symTable, semaCtx, eval, loc, - /*clauses=*/{}, queue, queue.begin()); + // SECTION constructs are handled as a part of SECTIONS. + llvm_unreachable("Unexpected standalone OMP SECTION"); } static void @@ -2485,17 +2461,77 @@ genOMP(Fortran::lower::AbstractConverter &converter, clauses.append(makeClauses( std::get(endSectionsDirective.t), semaCtx)); + + // Process clauses before optional omp.parallel, so that new variables are + // allocated outside of the parallel region mlir::Location currentLocation = converter.getCurrentLocation(); + mlir::omp::SectionsClauseOps clauseOps; + genSectionsClauses(converter, semaCtx, clauses, currentLocation, clauseOps); + + // Parallel wrapper of PARALLEL SECTIONS construct + llvm::omp::Directive dir = + std::get(beginSectionsDirective.t) + .v; + if (dir == llvm::omp::Directive::OMPD_parallel_sections) { + genParallelOp(converter, symTable, semaCtx, eval, + /*genNested=*/false, currentLocation, clauses, + /*outerCombined=*/true); + } + + // Insert privatizations before SECTIONS + symTable.pushScope(); + DataSharingProcessor dsp(converter, semaCtx, clauses, eval); + dsp.processStep1(); + + // SECTIONS construct. + mlir::omp::SectionsOp sectionsOp = genSectionsOp( + converter, symTable, semaCtx, eval, currentLocation, clauseOps); + + // Generate nested SECTION operations recursively. + const auto §ionBlocks = + std::get(sectionsConstruct.t); + auto &firOpBuilder = converter.getFirOpBuilder(); + auto ip = firOpBuilder.saveInsertionPoint(); + mlir::omp::SectionOp lastSectionOp; + for (const auto &[nblock, neval] : + llvm::zip(sectionBlocks.v, eval.getNestedEvaluations())) { + symTable.pushScope(); + lastSectionOp = genSectionOp(converter, symTable, semaCtx, neval, + /*genNested=*/true, currentLocation); + symTable.popScope(); + firOpBuilder.restoreInsertionPoint(ip); + } + + // For `omp.sections`, lastprivatized variables occur in + // lexically final `omp.section` operation. + bool hasLastPrivate = false; + if (lastSectionOp) { + for (const Clause &clause : clauses) { + if (const auto *lastPrivate = + std::get_if(&clause.u)) { + hasLastPrivate = true; + firOpBuilder.setInsertionPoint( + lastSectionOp.getRegion().back().getTerminator()); + mlir::OpBuilder::InsertPoint lastPrivIP = + converter.getFirOpBuilder().saveInsertionPoint(); + const auto &objList = std::get<1>(lastPrivate->t); + for (const Object &obj : objList) { + Fortran::semantics::Symbol *sym = obj.id(); + converter.copyHostAssociateVar(*sym, &lastPrivIP); + } + } + } + } - llvm::omp::Directive directive = - std::get(beginSectionsDirective.t).v; - const parser::CharBlock &source = - std::get(beginSectionsDirective.t).source; - ConstructQueue queue{ - buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, - eval, source, directive, clauses)}; - genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, - queue.begin()); + // Perform DataSharingProcessor's step2 out of SECTIONS + firOpBuilder.setInsertionPointAfter(sectionsOp.getOperation()); + dsp.processStep2(sectionsOp, false); + // Emit implicit barrier to synchronize threads and avoid data + // races on post-update of lastprivate variables when `nowait` + // clause is present. + if (clauseOps.nowaitAttr && hasLastPrivate) + firOpBuilder.create(converter.getCurrentLocation()); + symTable.popScope(); } static void genOMP(Fortran::lower::AbstractConverter &converter, diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp index cb1d1a5a7f3d..eed63b226133 100644 --- a/flang/lib/Lower/OpenMP/Utils.cpp +++ b/flang/lib/Lower/OpenMP/Utils.cpp @@ -51,6 +51,12 @@ int64_t getCollapseValue(const List &clauses) { return 1; } +uint32_t getOpenMPVersion(mlir::ModuleOp mod) { + if (mlir::Attribute verAttr = mod->getAttr("omp.version")) + return llvm::cast(verAttr).getVersion(); + llvm_unreachable("Expecting OpenMP version attribute in module"); +} + void genObjectList(const ObjectList &objects, Fortran::lower::AbstractConverter &converter, llvm::SmallVectorImpl &operands) { diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h index 345ce55620ee..8fbb18fa8656 100644 --- a/flang/lib/Lower/OpenMP/Utils.h +++ b/flang/lib/Lower/OpenMP/Utils.h @@ -93,6 +93,7 @@ void gatherFuncAndVarSyms( llvm::SmallVectorImpl &symbolAndClause); int64_t getCollapseValue(const List &clauses); +uint32_t getOpenMPVersion(mlir::ModuleOp mod); Fortran::semantics::Symbol * getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject); diff --git a/flang/test/Lower/OpenMP/default-clause-byref.f90 b/flang/test/Lower/OpenMP/default-clause-byref.f90 index 7cc2bc2e0c71..62ba67e5962f 100644 --- a/flang/test/Lower/OpenMP/default-clause-byref.f90 +++ b/flang/test/Lower/OpenMP/default-clause-byref.f90 @@ -161,12 +161,12 @@ subroutine nested_default_clause_tests !CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFnested_default_clause_testsEz"} !CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: omp.parallel { -!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} -!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} !CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref !CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_testsEz"} !CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFnested_default_clause_testsEk"} @@ -221,7 +221,6 @@ subroutine nested_default_clause_tests !CHECK: omp.parallel { -!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} !CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} !CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) diff --git a/flang/test/Lower/OpenMP/default-clause.f90 b/flang/test/Lower/OpenMP/default-clause.f90 index 843ee6bb7910..a90f0f4ef5f8 100644 --- a/flang/test/Lower/OpenMP/default-clause.f90 +++ b/flang/test/Lower/OpenMP/default-clause.f90 @@ -160,12 +160,12 @@ end program default_clause_lowering !CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFnested_default_clause_test1Ez"} !CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFnested_default_clause_test1Ez"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: omp.parallel { -!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_test1Ey"} -!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_test1Ey"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_test1Ex"} !CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_test1Ex"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref !CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_test1Ey"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_test1Ey"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_test1Ez"} !CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_test1Ez"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFnested_default_clause_test1Ek"} diff --git a/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 b/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 index e6ee75c8a5be..b7f11c8c722f 100644 --- a/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 +++ b/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 @@ -145,10 +145,10 @@ end subroutine !CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) !CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg2"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) !CHECK: omp.parallel { -!CHECK-DAG: %[[CLONE2:.*]] = fir.alloca i32 {bindc_name = "arg2" -!CHECK-DAG: %[[CLONE2_DECL:.*]]:2 = hlfir.declare %[[CLONE2]] {uniq_name = "_QFmult_lastprivate_int2Earg2"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK-DAG: %[[CLONE1:.*]] = fir.alloca i32 {bindc_name = "arg1" !CHECK-DAG: %[[CLONE1_DECL:.*]]:2 = hlfir.declare %[[CLONE1]] {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK-DAG: %[[CLONE2:.*]] = fir.alloca i32 {bindc_name = "arg2" +!CHECK-DAG: %[[CLONE2_DECL:.*]]:2 = hlfir.declare %[[CLONE2]] {uniq_name = "_QFmult_lastprivate_int2Earg2"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: omp.wsloop { !CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} { diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h index 07c95497b7a4..daef02bcfc9a 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h @@ -178,12 +178,6 @@ template using ListT = llvm::SmallVector; // provide their own specialization that conforms to the above requirements. template struct ObjectT; -// By default, object equality is only determined by its identity. -template -bool operator==(const ObjectT &o1, const ObjectT &o2) { - return o1.id() == o2.id(); -} - template using ObjectListT = ListT>; using DirectiveName = llvm::omp::Directive; @@ -270,32 +264,6 @@ struct ReductionIdentifierT { template // using IteratorT = ListT>; - -template -std::enable_if_t operator==(const T &a, - const T &b) { - return true; -} -template -std::enable_if_t operator==(const T &a, - const T &b) { - return true; -} -template -std::enable_if_t operator==(const T &a, - const T &b) { - return a.v == b.v; -} -template -std::enable_if_t operator==(const T &a, - const T &b) { - return a.t == b.t; -} -template -std::enable_if_t operator==(const T &a, - const T &b) { - return a.u == b.u; -} } // namespace type template using ListT = type::ListT; @@ -317,8 +285,6 @@ ListT makeList(ContainerTy &&container, FunctionTy &&func) { } namespace clause { -using type::operator==; - // V5.2: [8.3.1] `assumption` clauses template // struct AbsentT { @@ -760,7 +726,7 @@ struct LinearT { ENUM(LinearModifier, Ref, Val, Uval); using TupleTrait = std::true_type; - // Step == nullopt means 1. + // Step == nullptr means 1. std::tuple t; @@ -1176,11 +1142,9 @@ struct UsesAllocatorsT { using MemSpace = E; using TraitsArray = ObjectT; using Allocator = E; - struct AllocatorSpec { // Not a spec name - using TupleTrait = std::true_type; - std::tuple t; - }; - using Allocators = ListT; // Not a spec name + using AllocatorSpec = + std::tuple; // Not a spec name + using Allocators = ListT; // Not a spec name using WrapperTrait = std::true_type; Allocators v; }; @@ -1268,9 +1232,8 @@ using UnionOfAllClausesT = typename type::Union< // UnionClausesT, // WrapperClausesT // >::type; -} // namespace clause -using type::operator==; +} // namespace clause // The variant wrapper that encapsulates all possible specific clauses. // The `Extras` arguments are additional types representing local extensions @@ -1297,11 +1260,6 @@ struct ClauseT { VariantTy u; }; -template struct DirectiveWithClauses { - llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown; - tomp::type::ListT clauses; -}; - } // namespace tomp #undef OPT diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h deleted file mode 100644 index 7a4ed92a1070..000000000000 --- a/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h +++ /dev/null @@ -1,403 +0,0 @@ -//===- ConstructCompositionT.h -- Composing compound constructs -----------===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// Given a list of leaf construct, each with a set of clauses, generate the -// compound construct whose leaf constructs are the given list, and whose clause -// list is the merged lists of individual leaf clauses. -// -// *** At the moment it assumes that the individual constructs and their clauses -// *** are a subset of those created by splitting a valid compound construct. -//===----------------------------------------------------------------------===// -#ifndef LLVM_FRONTEND_OPENMP_CONSTRUCTCOMPOSITIONT_H -#define LLVM_FRONTEND_OPENMP_CONSTRUCTCOMPOSITIONT_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Frontend/OpenMP/ClauseT.h" -#include "llvm/Frontend/OpenMP/OMP.h" - -#include -#include -#include -#include -#include -#include - -namespace tomp { -template struct ConstructCompositionT { - using ClauseTy = ClauseType; - - using TypeTy = typename ClauseTy::TypeTy; - using IdTy = typename ClauseTy::IdTy; - using ExprTy = typename ClauseTy::ExprTy; - - ConstructCompositionT(uint32_t version, - llvm::ArrayRef> leafs); - - DirectiveWithClauses merged; - -private: - // Use an ordered container, since we beed to maintain the order in which - // clauses are added to it. This is to avoid non-deterministic output. - using ClauseSet = ListT; - - enum class Presence { - All, // Clause is preesnt on all leaf constructs that allow it. - Some, // Clause is present on some, but not on all constructs. - None, // Clause is absent on all constructs. - }; - - template - ClauseTy makeClause(llvm::omp::Clause clauseId, S &&specific) { - return ClauseTy{clauseId, std::move(specific)}; - } - - llvm::omp::Directive - makeCompound(llvm::ArrayRef> parts); - - Presence checkPresence(llvm::omp::Clause clauseId); - - // There are clauses that need special handling: - // 1. "if": the "directive-name-modifier" on the merged clause may need - // to be set appropriately. - // 2. "reduction": implies "privateness" of all objects (incompatible - // with "shared"); there are rules for merging modifiers - void mergeIf(); - void mergeReduction(); - void mergeDSA(); - - uint32_t version; - llvm::ArrayRef> leafs; - - // clause id -> set of leaf constructs that contain it - std::unordered_map clausePresence; - // clause id -> set of instances of that clause - std::unordered_map clauseSets; -}; - -template -ConstructCompositionT::ConstructCompositionT( - uint32_t version, llvm::ArrayRef> leafs) - : version(version), leafs(leafs) { - // Merge the list of constructs with clauses into a compound construct - // with a single list of clauses. - // The intended use of this function is in splitting compound constructs, - // while preserving composite constituent constructs: - // Step 1: split compound construct into leaf constructs. - // Step 2: identify composite sub-construct, and merge the constituent leafs. - // - // *** At the moment it assumes that the individual constructs and their - // *** clauses are a subset of those created by splitting a valid compound - // *** construct. - // - // 1. Deduplicate clauses - // - exact duplicates: e.g. shared(x) shared(x) -> shared(x) - // - special cases of clauses differing in modifier: - // (a) reduction: inscan + (none|default) = inscan - // (b) reduction: task + (none|default) = task - // (c) combine repeated "if" clauses if possible - // 2. Merge DSA clauses: e.g. private(x) private(y) -> private(x, y). - // 3. Resolve potential DSA conflicts (typically due to implied clauses). - - if (leafs.empty()) - return; - - merged.id = makeCompound(leafs); - - // Populate the two maps: - for (const auto &[index, leaf] : llvm::enumerate(leafs)) { - for (const auto &clause : leaf.clauses) { - // Update clausePresence. - auto &pset = clausePresence[clause.id]; - if (pset.size() < leafs.size()) - pset.resize(leafs.size()); - pset.set(index); - // Update clauseSets. - ClauseSet &cset = clauseSets[clause.id]; - if (!llvm::is_contained(cset, clause)) - cset.push_back(clause); - } - } - - mergeIf(); - mergeReduction(); - mergeDSA(); - - // Fir the rest of the clauses, just copy them. - for (auto &[id, clauses] : clauseSets) { - // Skip clauses we've already dealt with. - switch (id) { - case llvm::omp::Clause::OMPC_if: - case llvm::omp::Clause::OMPC_reduction: - case llvm::omp::Clause::OMPC_shared: - case llvm::omp::Clause::OMPC_private: - case llvm::omp::Clause::OMPC_firstprivate: - case llvm::omp::Clause::OMPC_lastprivate: - continue; - default: - break; - } - llvm::append_range(merged.clauses, clauses); - } -} - -template -llvm::omp::Directive ConstructCompositionT::makeCompound( - llvm::ArrayRef> parts) { - llvm::SmallVector dirIds; - llvm::transform(parts, std::back_inserter(dirIds), - [](auto &&dwc) { return dwc.id; }); - - return llvm::omp::getCompoundConstruct(dirIds); -} - -template -auto ConstructCompositionT::checkPresence(llvm::omp::Clause clauseId) - -> Presence { - auto found = clausePresence.find(clauseId); - if (found == clausePresence.end()) - return Presence::None; - - bool OnAll = true, OnNone = true; - for (const auto &[index, leaf] : llvm::enumerate(leafs)) { - if (!llvm::omp::isAllowedClauseForDirective(leaf.id, clauseId, version)) - continue; - - if (found->second.test(index)) - OnNone = false; - else - OnAll = false; - } - - if (OnNone) - return Presence::None; - if (OnAll) - return Presence::All; - return Presence::Some; -} - -template void ConstructCompositionT::mergeIf() { - using IfTy = tomp::clause::IfT; - // Deal with the "if" clauses. If it's on all leafs that allow it, then it - // will apply to the compound construct. Otherwise it will apply to the - // single (assumed) leaf construct. - // This assumes that the "if" clauses have the same expression. - Presence presence = checkPresence(llvm::omp::Clause::OMPC_if); - if (presence == Presence::None) - return; - - const ClauseTy &some = *clauseSets[llvm::omp::Clause::OMPC_if].begin(); - const auto &someIf = std::get(some.u); - - if (presence == Presence::All) { - // Create "if" without "directive-name-modifier". - merged.clauses.emplace_back( - makeClause(llvm::omp::Clause::OMPC_if, - IfTy{{/*DirectiveNameModifier=*/std::nullopt, - /*IfExpression=*/std::get( - someIf.t)}})); - } else { - // Find out where it's present and create "if" with the corresponding - // "directive-name-modifier". - int Idx = clausePresence[llvm::omp::Clause::OMPC_if].find_first(); - assert(Idx >= 0); - merged.clauses.emplace_back( - makeClause(llvm::omp::Clause::OMPC_if, - IfTy{{/*DirectiveNameModifier=*/leafs[Idx].id, - /*IfExpression=*/std::get( - someIf.t)}})); - } -} - -template void ConstructCompositionT::mergeReduction() { - Presence presence = checkPresence(llvm::omp::Clause::OMPC_reduction); - if (presence == Presence::None) - return; - - using ReductionTy = tomp::clause::ReductionT; - using ModifierTy = typename ReductionTy::ReductionModifier; - using IdentifiersTy = typename ReductionTy::ReductionIdentifiers; - using ListTy = typename ReductionTy::List; - // There are exceptions on which constructs "reduction" may appear - // (specifically "parallel", and "teams"). Assume that if "reduction" - // is present, it can be applied to the compound construct. - - // What's left is to see if there are any modifiers present. Again, - // assume that there are no conflicting modifiers. - // There can be, however, multiple reductions on different objects. - auto equal = [](const ClauseTy &red1, const ClauseTy &red2) { - // Extract actual reductions. - const auto r1 = std::get(red1.u); - const auto r2 = std::get(red2.u); - // Compare everything except modifiers. - if (std::get(r1.t) != std::get(r2.t)) - return false; - if (std::get(r1.t) != std::get(r2.t)) - return false; - return true; - }; - - auto getModifier = [](const ClauseTy &clause) { - const ReductionTy &red = std::get(clause.u); - return std::get>(red.t); - }; - - const ClauseSet &reductions = clauseSets[llvm::omp::Clause::OMPC_reduction]; - std::unordered_set visited; - while (reductions.size() != visited.size()) { - typename ClauseSet::const_iterator first; - - // Find first non-visited reduction. - for (first = reductions.begin(); first != reductions.end(); ++first) { - if (visited.count(&*first)) - continue; - visited.insert(&*first); - break; - } - - std::optional modifier = getModifier(*first); - - // Visit all other reductions that are "equal" (with respect to the - // definition above) to "first". Collect modifiers. - for (auto iter = std::next(first); iter != reductions.end(); ++iter) { - if (!equal(*first, *iter)) - continue; - visited.insert(&*iter); - if (!modifier || *modifier == ModifierTy::Default) - modifier = getModifier(*iter); - } - - const auto &firstRed = std::get(first->u); - merged.clauses.emplace_back(makeClause( - llvm::omp::Clause::OMPC_reduction, - ReductionTy{ - {/*ReductionModifier=*/modifier, - /*ReductionIdentifiers=*/std::get(firstRed.t), - /*List=*/std::get(firstRed.t)}})); - } -} - -template void ConstructCompositionT::mergeDSA() { - using ObjectTy = tomp::type::ObjectT; - - // Resolve data-sharing attributes. - enum DSA : int { - None = 0, - Shared = 1 << 0, - Private = 1 << 1, - FirstPrivate = 1 << 2, - LastPrivate = 1 << 3, - LastPrivateConditional = 1 << 4, - }; - - // Use ordered containers to avoid non-deterministic output. - llvm::SmallVector> objectDsa; - - auto getDsa = [&](const ObjectTy &object) -> std::pair & { - auto found = llvm::find_if(objectDsa, [&](std::pair &p) { - return p.first.id() == object.id(); - }); - if (found != objectDsa.end()) - return *found; - return objectDsa.emplace_back(object, DSA::None); - }; - - using SharedTy = tomp::clause::SharedT; - using PrivateTy = tomp::clause::PrivateT; - using FirstprivateTy = tomp::clause::FirstprivateT; - using LastprivateTy = tomp::clause::LastprivateT; - - // Visit clauses that affect DSA. - for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_shared]) { - for (auto &object : std::get(clause.u).v) - getDsa(object).second |= DSA::Shared; - } - - for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_private]) { - for (auto &object : std::get(clause.u).v) - getDsa(object).second |= DSA::Private; - } - - for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_firstprivate]) { - for (auto &object : std::get(clause.u).v) - getDsa(object).second |= DSA::FirstPrivate; - } - - for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_lastprivate]) { - using ModifierTy = typename LastprivateTy::LastprivateModifier; - using ListTy = typename LastprivateTy::List; - const auto &lastp = std::get(clause.u); - for (auto &object : std::get(lastp.t)) { - auto &mod = std::get>(lastp.t); - if (mod && *mod == ModifierTy::Conditional) { - getDsa(object).second |= DSA::LastPrivateConditional; - } else { - getDsa(object).second |= DSA::LastPrivate; - } - } - } - - // Check reductions as well, clear "shared" if set. - for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_reduction]) { - using ReductionTy = tomp::clause::ReductionT; - using ListTy = typename ReductionTy::List; - for (auto &object : std::get(std::get(clause.u).t)) - getDsa(object).second &= ~DSA::Shared; - } - - tomp::ListT privateObj, sharedObj, firstpObj, lastpObj, lastpcObj; - for (auto &[object, dsa] : objectDsa) { - if (dsa & - (DSA::FirstPrivate | DSA::LastPrivate | DSA::LastPrivateConditional)) { - if (dsa & DSA::FirstPrivate) - firstpObj.push_back(object); // no else - if (dsa & DSA::LastPrivateConditional) - lastpcObj.push_back(object); - else if (dsa & DSA::LastPrivate) - lastpObj.push_back(object); - } else if (dsa & DSA::Private) { - privateObj.push_back(object); - } else if (dsa & DSA::Shared) { - sharedObj.push_back(object); - } - } - - // Materialize each clause. - if (!privateObj.empty()) { - merged.clauses.emplace_back( - makeClause(llvm::omp::Clause::OMPC_private, - PrivateTy{/*List=*/std::move(privateObj)})); - } - if (!sharedObj.empty()) { - merged.clauses.emplace_back( - makeClause(llvm::omp::Clause::OMPC_shared, - SharedTy{/*List=*/std::move(sharedObj)})); - } - if (!firstpObj.empty()) { - merged.clauses.emplace_back( - makeClause(llvm::omp::Clause::OMPC_firstprivate, - FirstprivateTy{/*List=*/std::move(firstpObj)})); - } - if (!lastpObj.empty()) { - merged.clauses.emplace_back( - makeClause(llvm::omp::Clause::OMPC_lastprivate, - LastprivateTy{{/*LastprivateModifier=*/std::nullopt, - /*List=*/std::move(lastpObj)}})); - } - if (!lastpcObj.empty()) { - auto conditional = LastprivateTy::LastprivateModifier::Conditional; - merged.clauses.emplace_back( - makeClause(llvm::omp::Clause::OMPC_lastprivate, - LastprivateTy{{/*LastprivateModifier=*/conditional, - /*List=*/std::move(lastpcObj)}})); - } -} -} // namespace tomp - -#endif // LLVM_FRONTEND_OPENMP_CONSTRUCTCOMPOSITIONT_H diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h deleted file mode 100644 index 37c88f0fa07b..000000000000 --- a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h +++ /dev/null @@ -1,1161 +0,0 @@ -//===- ConstructDecompositionT.h -- Decomposing compound constructs -------===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// Given a compound construct with a set of clauses, generate the list of -// constituent leaf constructs, each with a list of clauses that apply to it. -// -// Note: Clauses that are not originally present, but that are implied by the -// OpenMP spec are materialized, and are present in the output. -// -// Note: Composite constructs will also be broken up into leaf constructs. -// If composite constructs require processing as a whole, the lists of clauses -// for each leaf constituent should be merged. -//===----------------------------------------------------------------------===// -#ifndef LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H -#define LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Frontend/OpenMP/ClauseT.h" -#include "llvm/Frontend/OpenMP/OMP.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static inline llvm::ArrayRef getWorksharing() { - static llvm::omp::Directive worksharing[] = { - llvm::omp::Directive::OMPD_do, llvm::omp::Directive::OMPD_for, - llvm::omp::Directive::OMPD_scope, llvm::omp::Directive::OMPD_sections, - llvm::omp::Directive::OMPD_single, llvm::omp::Directive::OMPD_workshare, - }; - return worksharing; -} - -static inline llvm::ArrayRef getWorksharingLoop() { - static llvm::omp::Directive worksharingLoop[] = { - llvm::omp::Directive::OMPD_do, - llvm::omp::Directive::OMPD_for, - }; - return worksharingLoop; -} - -namespace detail { -template -typename std::remove_reference_t::iterator -find_unique(Container &&container, Predicate &&pred) { - auto first = std::find_if(container.begin(), container.end(), pred); - if (first == container.end()) - return first; - auto second = std::find_if(std::next(first), container.end(), pred); - if (second == container.end()) - return first; - return container.end(); -} - -} // namespace detail - -namespace tomp { - -// ClauseType - Either instance of ClauseT, or a type derived from ClauseT. -// -// This is the clause representation in the code using this infrastructure. -// -// HelperType - A class that implements two member functions: -// -// // Return the base object of the given object, if any. -// std::optional getBaseObject(const Object &object) const -// // Return the iteration variable of the outermost loop associated -// // with the construct being worked on, if any. -// std::optional getLoopIterVar() const -template -struct ConstructDecompositionT { - using ClauseTy = ClauseType; - - using TypeTy = typename ClauseTy::TypeTy; - using IdTy = typename ClauseTy::IdTy; - using ExprTy = typename ClauseTy::ExprTy; - using HelperTy = HelperType; - using ObjectTy = tomp::ObjectT; - - using ClauseSet = std::unordered_set; - - ConstructDecompositionT(uint32_t ver, HelperType &helper, - llvm::omp::Directive dir, - llvm::ArrayRef clauses) - : version(ver), construct(dir), helper(helper) { - for (const ClauseTy &clause : clauses) - nodes.push_back(&clause); - - bool success = split(); - if (!success) - return; - - // Copy the individual leaf directives with their clauses to the - // output list. Copy by value, since we don't own the storage - // with the input clauses, and the internal representation uses - // clause addresses. - for (auto &leaf : leafs) { - output.push_back({leaf.id}); - auto &out = output.back(); - for (const ClauseTy *c : leaf.clauses) - out.clauses.push_back(*c); - } - } - - tomp::ListT> output; - -private: - bool split(); - - struct LeafReprInternal { - llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown; - tomp::type::ListT clauses; - }; - - LeafReprInternal *findDirective(llvm::omp::Directive dirId) { - auto found = llvm::find_if( - leafs, [&](const LeafReprInternal &leaf) { return leaf.id == dirId; }); - return found != leafs.end() ? &*found : nullptr; - } - - ClauseSet *findClausesWith(const ObjectTy &object) { - if (auto found = syms.find(object.id()); found != syms.end()) - return &found->second; - return nullptr; - } - - template - ClauseTy *makeClause(llvm::omp::Clause clauseId, S &&specific) { - implicit.push_back(ClauseTy{clauseId, std::move(specific)}); - return &implicit.back(); - } - - void addClauseSymsToMap(const ObjectTy &object, const ClauseTy *); - void addClauseSymsToMap(const tomp::ObjectListT &objects, - const ClauseTy *); - void addClauseSymsToMap(const TypeTy &item, const ClauseTy *); - void addClauseSymsToMap(const ExprTy &item, const ClauseTy *); - void addClauseSymsToMap(const tomp::clause::MapT &item, - const ClauseTy *); - - template - void addClauseSymsToMap(const std::optional &item, const ClauseTy *); - template - void addClauseSymsToMap(const tomp::ListT &item, const ClauseTy *); - template - void addClauseSymsToMap(const std::tuple &item, const ClauseTy *, - std::index_sequence = {}); - template - std::enable_if_t>, void> - addClauseSymsToMap(U &&item, const ClauseTy *); - - template - std::enable_if_t::EmptyTrait::value, void> - addClauseSymsToMap(U &&item, const ClauseTy *); - - template - std::enable_if_t::IncompleteTrait::value, void> - addClauseSymsToMap(U &&item, const ClauseTy *); - - template - std::enable_if_t::WrapperTrait::value, void> - addClauseSymsToMap(U &&item, const ClauseTy *); - - template - std::enable_if_t::TupleTrait::value, void> - addClauseSymsToMap(U &&item, const ClauseTy *); - - template - std::enable_if_t::UnionTrait::value, void> - addClauseSymsToMap(U &&item, const ClauseTy *); - - // Apply a clause to the only directive that allows it. If there are no - // directives that allow it, or if there is more that one, do not apply - // anything and return false, otherwise return true. - bool applyToUnique(const ClauseTy *node); - - // Apply a clause to the first directive in given range that allows it. - // If such a directive does not exist, return false, otherwise return true. - template - bool applyToFirst(const ClauseTy *node, llvm::iterator_range range); - - // Apply a clause to the innermost directive that allows it. If such a - // directive does not exist, return false, otherwise return true. - bool applyToInnermost(const ClauseTy *node); - - // Apply a clause to the outermost directive that allows it. If such a - // directive does not exist, return false, otherwise return true. - bool applyToOutermost(const ClauseTy *node); - - template - bool applyIf(const ClauseTy *node, Predicate shouldApply); - - bool applyToAll(const ClauseTy *node); - - template - bool applyClause(Clause &&clause, const ClauseTy *node); - - bool applyClause(const tomp::clause::CollapseT &clause, - const ClauseTy *); - bool applyClause(const tomp::clause::PrivateT &clause, - const ClauseTy *); - bool - applyClause(const tomp::clause::FirstprivateT &clause, - const ClauseTy *); - bool - applyClause(const tomp::clause::LastprivateT &clause, - const ClauseTy *); - bool applyClause(const tomp::clause::SharedT &clause, - const ClauseTy *); - bool applyClause(const tomp::clause::DefaultT &clause, - const ClauseTy *); - bool - applyClause(const tomp::clause::ThreadLimitT &clause, - const ClauseTy *); - bool applyClause(const tomp::clause::OrderT &clause, - const ClauseTy *); - bool applyClause(const tomp::clause::AllocateT &clause, - const ClauseTy *); - bool applyClause(const tomp::clause::ReductionT &clause, - const ClauseTy *); - bool applyClause(const tomp::clause::IfT &clause, - const ClauseTy *); - bool applyClause(const tomp::clause::LinearT &clause, - const ClauseTy *); - bool applyClause(const tomp::clause::NowaitT &clause, - const ClauseTy *); - - uint32_t version; - llvm::omp::Directive construct; - HelperType &helper; - ListT leafs; - tomp::ListT nodes; - std::list implicit; // Container for materialized implicit clauses. - // Inserting must preserve element addresses. - std::unordered_map syms; - std::unordered_set mapBases; -}; - -// Deduction guide -template -ConstructDecompositionT(uint32_t, HelperType &, llvm::omp::Directive, - llvm::ArrayRef) - -> ConstructDecompositionT; - -template -void ConstructDecompositionT::addClauseSymsToMap(const ObjectTy &object, - const ClauseTy *node) { - syms[object.id()].insert(node); -} - -template -void ConstructDecompositionT::addClauseSymsToMap( - const tomp::ObjectListT &objects, const ClauseTy *node) { - for (auto &object : objects) - syms[object.id()].insert(node); -} - -template -void ConstructDecompositionT::addClauseSymsToMap(const TypeTy &item, - const ClauseTy *node) { - // Nothing to do for types. -} - -template -void ConstructDecompositionT::addClauseSymsToMap(const ExprTy &item, - const ClauseTy *node) { - // Nothing to do for expressions. -} - -template -void ConstructDecompositionT::addClauseSymsToMap( - const tomp::clause::MapT &item, - const ClauseTy *node) { - auto &objects = std::get>(item.t); - addClauseSymsToMap(objects, node); - for (auto &object : objects) { - if (auto base = helper.getBaseObject(object)) - mapBases.insert(base->id()); - } -} - -template -template -void ConstructDecompositionT::addClauseSymsToMap( - const std::optional &item, const ClauseTy *node) { - if (item) - addClauseSymsToMap(*item, node); -} - -template -template -void ConstructDecompositionT::addClauseSymsToMap( - const tomp::ListT &item, const ClauseTy *node) { - for (auto &s : item) - addClauseSymsToMap(s, node); -} - -template -template -void ConstructDecompositionT::addClauseSymsToMap( - const std::tuple &item, const ClauseTy *node, - std::index_sequence) { - (void)node; // Silence strange warning from GCC. - (addClauseSymsToMap(std::get(item), node), ...); -} - -template -template -std::enable_if_t>, void> -ConstructDecompositionT::addClauseSymsToMap(U &&item, - const ClauseTy *node) { - // Nothing to do for enums. -} - -template -template -std::enable_if_t::EmptyTrait::value, void> -ConstructDecompositionT::addClauseSymsToMap(U &&item, - const ClauseTy *node) { - // Nothing to do for an empty class. -} - -template -template -std::enable_if_t::IncompleteTrait::value, void> -ConstructDecompositionT::addClauseSymsToMap(U &&item, - const ClauseTy *node) { - // Nothing to do for an incomplete class (they're empty). -} - -template -template -std::enable_if_t::WrapperTrait::value, void> -ConstructDecompositionT::addClauseSymsToMap(U &&item, - const ClauseTy *node) { - addClauseSymsToMap(item.v, node); -} - -template -template -std::enable_if_t::TupleTrait::value, void> -ConstructDecompositionT::addClauseSymsToMap(U &&item, - const ClauseTy *node) { - constexpr size_t tuple_size = - std::tuple_size_v>; - addClauseSymsToMap(item.t, node, std::make_index_sequence{}); -} - -template -template -std::enable_if_t::UnionTrait::value, void> -ConstructDecompositionT::addClauseSymsToMap(U &&item, - const ClauseTy *node) { - std::visit([&](auto &&s) { addClauseSymsToMap(s, node); }, item.u); -} - -// Apply a clause to the only directive that allows it. If there are no -// directives that allow it, or if there is more that one, do not apply -// anything and return false, otherwise return true. -template -bool ConstructDecompositionT::applyToUnique(const ClauseTy *node) { - auto unique = detail::find_unique(leafs, [=](const auto &dirInfo) { - return llvm::omp::isAllowedClauseForDirective(dirInfo.id, node->id, - version); - }); - - if (unique != leafs.end()) { - unique->clauses.push_back(node); - return true; - } - return false; -} - -// Apply a clause to the first directive in given range that allows it. -// If such a directive does not exist, return false, otherwise return true. -template -template -bool ConstructDecompositionT::applyToFirst( - const ClauseTy *node, llvm::iterator_range range) { - if (range.empty()) - return false; - - for (auto &leaf : range) { - if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version)) - continue; - leaf.clauses.push_back(node); - return true; - } - return false; -} - -// Apply a clause to the innermost directive that allows it. If such a -// directive does not exist, return false, otherwise return true. -template -bool ConstructDecompositionT::applyToInnermost(const ClauseTy *node) { - return applyToFirst(node, llvm::reverse(leafs)); -} - -// Apply a clause to the outermost directive that allows it. If such a -// directive does not exist, return false, otherwise return true. -template -bool ConstructDecompositionT::applyToOutermost(const ClauseTy *node) { - return applyToFirst(node, llvm::iterator_range(leafs)); -} - -template -template -bool ConstructDecompositionT::applyIf(const ClauseTy *node, - Predicate shouldApply) { - bool applied = false; - for (auto &leaf : leafs) { - if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version)) - continue; - if (!shouldApply(leaf)) - continue; - leaf.clauses.push_back(node); - applied = true; - } - - return applied; -} - -template -bool ConstructDecompositionT::applyToAll(const ClauseTy *node) { - return applyIf(node, [](auto) { return true; }); -} - -template -template -bool ConstructDecompositionT::applyClause(Clause &&clause, - const ClauseTy *node) { - // The default behavior is to find the unique directive to which the - // given clause may be applied. If there are no such directives, or - // if there are multiple ones, flag an error. - // From "OpenMP Application Programming Interface", Version 5.2: - // S Some clauses are permitted only on a single leaf construct of the - // S combined or composite construct, in which case the effect is as if - // S the clause is applied to that specific construct. (p339, 31-33) - if (applyToUnique(node)) - return true; - - return false; -} - -// COLLAPSE -// [5.2:93:20-21] -// Directives: distribute, do, for, loop, simd, taskloop -// -// [5.2:339:35] -// (35) The collapse clause is applied once to the combined or composite -// construct. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::CollapseT &clause, - const ClauseTy *node) { - // Apply "collapse" to the innermost directive. If it's not one that - // allows it flag an error. - if (!leafs.empty()) { - auto &last = leafs.back(); - - if (llvm::omp::isAllowedClauseForDirective(last.id, node->id, version)) { - last.clauses.push_back(node); - return true; - } - } - - return false; -} - -// PRIVATE -// [5.2:111:5-7] -// Directives: distribute, do, for, loop, parallel, scope, sections, simd, -// single, target, task, taskloop, teams -// -// [5.2:340:1-2] -// (1) The effect of the 1 private clause is as if it is applied only to the -// innermost leaf construct that permits it. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::PrivateT &clause, - const ClauseTy *node) { - return applyToInnermost(node); -} - -// FIRSTPRIVATE -// [5.2:112:5-7] -// Directives: distribute, do, for, parallel, scope, sections, single, target, -// task, taskloop, teams -// -// [5.2:340:3-20] -// (3) The effect of the firstprivate clause is as if it is applied to one or -// more leaf constructs as follows: -// (5) To the distribute construct if it is among the constituent constructs; -// (6) To the teams construct if it is among the constituent constructs and the -// distribute construct is not; -// (8) To a worksharing construct that accepts the clause if one is among the -// constituent constructs; -// (9) To the taskloop construct if it is among the constituent constructs; -// (10) To the parallel construct if it is among the constituent constructs and -// neither a taskloop construct nor a worksharing construct that accepts -// the clause is among them; -// (12) To the target construct if it is among the constituent constructs and -// the same list item neither appears in a lastprivate clause nor is the -// base variable or base pointer of a list item that appears in a map -// clause. -// -// (15) If the parallel construct is among the constituent constructs and the -// effect is not as if the firstprivate clause is applied to it by the above -// rules, then the effect is as if the shared clause with the same list item is -// applied to the parallel construct. -// (17) If the teams construct is among the constituent constructs and the -// effect is not as if the firstprivate clause is applied to it by the above -// rules, then the effect is as if the shared clause with the same list item is -// applied to the teams construct. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::FirstprivateT &clause, - const ClauseTy *node) { - bool applied = false; - - // [5.2:340:3-6] - auto dirDistribute = findDirective(llvm::omp::OMPD_distribute); - auto dirTeams = findDirective(llvm::omp::OMPD_teams); - if (dirDistribute != nullptr) { - dirDistribute->clauses.push_back(node); - applied = true; - // [5.2:340:17] - if (dirTeams != nullptr) { - auto *shared = makeClause( - llvm::omp::Clause::OMPC_shared, - tomp::clause::SharedT{/*List=*/clause.v}); - dirTeams->clauses.push_back(shared); - } - } else if (dirTeams != nullptr) { - dirTeams->clauses.push_back(node); - applied = true; - } - - // [5.2:340:8] - auto findWorksharing = [&]() { - auto worksharing = getWorksharing(); - for (auto &leaf : leafs) { - auto found = llvm::find(worksharing, leaf.id); - if (found != std::end(worksharing)) - return &leaf; - } - return static_cast(nullptr); - }; - - auto dirWorksharing = findWorksharing(); - if (dirWorksharing != nullptr) { - dirWorksharing->clauses.push_back(node); - applied = true; - } - - // [5.2:340:9] - auto dirTaskloop = findDirective(llvm::omp::OMPD_taskloop); - if (dirTaskloop != nullptr) { - dirTaskloop->clauses.push_back(node); - applied = true; - } - - // [5.2:340:10] - auto dirParallel = findDirective(llvm::omp::OMPD_parallel); - if (dirParallel != nullptr) { - if (dirTaskloop == nullptr && dirWorksharing == nullptr) { - dirParallel->clauses.push_back(node); - applied = true; - } else { - // [5.2:340:15] - auto *shared = makeClause( - llvm::omp::Clause::OMPC_shared, - tomp::clause::SharedT{/*List=*/clause.v}); - dirParallel->clauses.push_back(shared); - } - } - - // [5.2:340:12] - auto inLastprivate = [&](const ObjectTy &object) { - if (ClauseSet *set = findClausesWith(object)) { - return llvm::find_if(*set, [](const ClauseTy *c) { - return c->id == llvm::omp::Clause::OMPC_lastprivate; - }) != set->end(); - } - return false; - }; - - auto dirTarget = findDirective(llvm::omp::OMPD_target); - if (dirTarget != nullptr) { - tomp::ObjectListT objects; - llvm::copy_if( - clause.v, std::back_inserter(objects), [&](const ObjectTy &object) { - return !inLastprivate(object) && !mapBases.count(object.id()); - }); - if (!objects.empty()) { - auto *firstp = makeClause( - llvm::omp::Clause::OMPC_firstprivate, - tomp::clause::FirstprivateT{/*List=*/objects}); - dirTarget->clauses.push_back(firstp); - applied = true; - } - } - - // "task" is not handled by any of the cases above. - if (auto dirTask = findDirective(llvm::omp::OMPD_task)) { - dirTask->clauses.push_back(node); - applied = true; - } - - return applied; -} - -// LASTPRIVATE -// [5.2:115:7-8] -// Directives: distribute, do, for, loop, sections, simd, taskloop -// -// [5.2:340:21-30] -// (21) The effect of the lastprivate clause is as if it is applied to all leaf -// constructs that permit the clause. -// (22) If the parallel construct is among the constituent constructs and the -// list item is not also specified in the firstprivate clause, then the effect -// of the lastprivate clause is as if the shared clause with the same list item -// is applied to the parallel construct. -// (24) If the teams construct is among the constituent constructs and the list -// item is not also specified in the firstprivate clause, then the effect of the -// lastprivate clause is as if the shared clause with the same list item is -// applied to the teams construct. -// (27) If the target construct is among the constituent constructs and the list -// item is not the base variable or base pointer of a list item that appears in -// a map clause, the effect of the lastprivate clause is as if the same list -// item appears in a map clause with a map-type of tofrom. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::LastprivateT &clause, - const ClauseTy *node) { - bool applied = false; - - // [5.2:340:21] - applied = applyToAll(node); - if (!applied) - return false; - - auto inFirstprivate = [&](const ObjectTy &object) { - if (ClauseSet *set = findClausesWith(object)) { - return llvm::find_if(*set, [](const ClauseTy *c) { - return c->id == llvm::omp::Clause::OMPC_firstprivate; - }) != set->end(); - } - return false; - }; - - auto &objects = std::get>(clause.t); - - // Prepare list of objects that could end up in a "shared" clause. - tomp::ObjectListT sharedObjects; - llvm::copy_if( - objects, std::back_inserter(sharedObjects), - [&](const ObjectTy &object) { return !inFirstprivate(object); }); - - if (!sharedObjects.empty()) { - // [5.2:340:22] - if (auto dirParallel = findDirective(llvm::omp::OMPD_parallel)) { - auto *shared = makeClause( - llvm::omp::Clause::OMPC_shared, - tomp::clause::SharedT{/*List=*/sharedObjects}); - dirParallel->clauses.push_back(shared); - applied = true; - } - - // [5.2:340:24] - if (auto dirTeams = findDirective(llvm::omp::OMPD_teams)) { - auto *shared = makeClause( - llvm::omp::Clause::OMPC_shared, - tomp::clause::SharedT{/*List=*/sharedObjects}); - dirTeams->clauses.push_back(shared); - applied = true; - } - } - - // [5.2:340:27] - if (auto dirTarget = findDirective(llvm::omp::OMPD_target)) { - tomp::ObjectListT tofrom; - llvm::copy_if( - objects, std::back_inserter(tofrom), - [&](const ObjectTy &object) { return !mapBases.count(object.id()); }); - - if (!tofrom.empty()) { - using MapType = - typename tomp::clause::MapT::MapType; - auto *map = - makeClause(llvm::omp::Clause::OMPC_map, - tomp::clause::MapT{ - {/*MapType=*/MapType::Tofrom, - /*MapTypeModifier=*/std::nullopt, - /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, - /*LocatorList=*/std::move(tofrom)}}); - dirTarget->clauses.push_back(map); - applied = true; - } - } - - return applied; -} - -// SHARED -// [5.2:110:5-6] -// Directives: parallel, task, taskloop, teams -// -// [5.2:340:31-32] -// (31) The effect of the shared, default, thread_limit, or order clause is as -// if it is applied to all leaf constructs that permit the clause. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::SharedT &clause, - const ClauseTy *node) { - // [5.2:340:31] - return applyToAll(node); -} - -// DEFAULT -// [5.2:109:5-6] -// Directives: parallel, task, taskloop, teams -// -// [5.2:340:31-32] -// (31) The effect of the shared, default, thread_limit, or order clause is as -// if it is applied to all leaf constructs that permit the clause. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::DefaultT &clause, - const ClauseTy *node) { - // [5.2:340:31] - return applyToAll(node); -} - -// THREAD_LIMIT -// [5.2:277:14-15] -// Directives: target, teams -// -// [5.2:340:31-32] -// (31) The effect of the shared, default, thread_limit, or order clause is as -// if it is applied to all leaf constructs that permit the clause. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::ThreadLimitT &clause, - const ClauseTy *node) { - // [5.2:340:31] - return applyToAll(node); -} - -// ORDER -// [5.2:234:3-4] -// Directives: distribute, do, for, loop, simd -// -// [5.2:340:31-32] -// (31) The effect of the shared, default, thread_limit, or order clause is as -// if it is applied to all leaf constructs that permit the clause. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::OrderT &clause, - const ClauseTy *node) { - // [5.2:340:31] - return applyToAll(node); -} - -// ALLOCATE -// [5.2:178:7-9] -// Directives: allocators, distribute, do, for, parallel, scope, sections, -// single, target, task, taskgroup, taskloop, teams -// -// [5.2:340:33-35] -// (33) The effect of the allocate clause is as if it is applied to all leaf -// constructs that permit the clause and to which a data-sharing attribute -// clause that may create a private copy of the same list item is applied. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::AllocateT &clause, - const ClauseTy *node) { - // This one needs to be applied at the end, once we know which clauses are - // assigned to which leaf constructs. - - // [5.2:340:33] - auto canMakePrivateCopy = [](llvm::omp::Clause id) { - switch (id) { - case llvm::omp::Clause::OMPC_firstprivate: - case llvm::omp::Clause::OMPC_lastprivate: - case llvm::omp::Clause::OMPC_private: - return true; - default: - return false; - } - }; - - bool applied = applyIf(node, [&](const auto &leaf) { - return llvm::any_of(leaf.clauses, [&](const ClauseTy *n) { - return canMakePrivateCopy(n->id); - }); - }); - - return applied; -} - -// REDUCTION -// [5.2:134:17-18] -// Directives: do, for, loop, parallel, scope, sections, simd, taskloop, teams -// -// [5.2:340:36-37], [5.2:341:1-13] -// (36) The effect of the reduction clause is as if it is applied to all leaf -// constructs that permit the clause, except for the following constructs: -// (1) The parallel construct, when combined with the sections, -// worksharing-loop, loop, or taskloop construct; and -// (3) The teams construct, when combined with the loop construct. -// (4) For the parallel and teams constructs above, the effect of the reduction -// clause instead is as if each list item or, for any list item that is an array -// item, its corresponding base array or base pointer appears in a shared clause -// for the construct. -// (6) If the task reduction-modifier is specified, the effect is as if it only -// modifies the behavior of the reduction clause on the innermost leaf construct -// that accepts the modifier (see Section 5.5.8). -// (8) If the inscan reduction-modifier is specified, the effect is as if it -// modifies the behavior of the reduction clause on all constructs of the -// combined construct to which the clause is applied and that accept the -// modifier. -// (10) If a list item in a reduction clause on a combined target construct does -// not have the same base variable or base pointer as a list item in a map -// clause on the construct, then the effect is as if the list item in the -// reduction clause appears as a list item in a map clause with a map-type of -// tofrom. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::ReductionT &clause, - const ClauseTy *node) { - using ReductionTy = tomp::clause::ReductionT; - - // [5.2:340:36], [5.2:341:1], [5.2:341:3] - bool applyToParallel = true, applyToTeams = true; - - auto dirParallel = findDirective(llvm::omp::Directive::OMPD_parallel); - if (dirParallel) { - auto exclusions = llvm::concat( - getWorksharingLoop(), tomp::ListT{ - llvm::omp::Directive::OMPD_loop, - llvm::omp::Directive::OMPD_sections, - llvm::omp::Directive::OMPD_taskloop, - }); - auto present = [&](llvm::omp::Directive id) { - return findDirective(id) != nullptr; - }; - - if (llvm::any_of(exclusions, present)) - applyToParallel = false; - } - - auto dirTeams = findDirective(llvm::omp::Directive::OMPD_teams); - if (dirTeams) { - // The only exclusion is OMPD_loop. - if (findDirective(llvm::omp::Directive::OMPD_loop)) - applyToTeams = false; - } - - using ReductionModifier = typename ReductionTy::ReductionModifier; - using ReductionIdentifiers = typename ReductionTy::ReductionIdentifiers; - - auto &objects = std::get>(clause.t); - auto &modifier = std::get>(clause.t); - - // Apply the reduction clause first to all directives according to the spec. - // If the reduction was applied at least once, proceed with the data sharing - // side-effects. - bool applied = false; - - // [5.2:341:6], [5.2:341:8] - auto isValidModifier = [](llvm::omp::Directive dir, ReductionModifier mod, - bool alreadyApplied) { - switch (mod) { - case ReductionModifier::Inscan: - // According to [5.2:135:11-13], "inscan" only applies to - // worksharing-loop, worksharing-loop-simd, or "simd" constructs. - return dir == llvm::omp::Directive::OMPD_simd || - llvm::is_contained(getWorksharingLoop(), dir); - case ReductionModifier::Task: - if (alreadyApplied) - return false; - // According to [5.2:135:16-18], "task" only applies to "parallel" and - // worksharing constructs. - return dir == llvm::omp::Directive::OMPD_parallel || - llvm::is_contained(getWorksharing(), dir); - case ReductionModifier::Default: - return true; - } - llvm_unreachable("Unexpected modifier"); - }; - - auto *unmodified = makeClause( - llvm::omp::Clause::OMPC_reduction, - ReductionTy{ - {/*ReductionModifier=*/std::nullopt, - /*ReductionIdentifiers=*/std::get(clause.t), - /*List=*/objects}}); - - ReductionModifier effective = - modifier.has_value() ? *modifier : ReductionModifier::Default; - bool effectiveApplied = false; - // Walk over the leaf constructs starting from the innermost, and apply - // the clause as required by the spec. - for (auto &leaf : llvm::reverse(leafs)) { - if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version)) - continue; - if (!applyToParallel && &leaf == dirParallel) - continue; - if (!applyToTeams && &leaf == dirTeams) - continue; - // Some form of the clause will be applied past this point. - if (isValidModifier(leaf.id, effective, effectiveApplied)) { - // Apply clause with modifier. - leaf.clauses.push_back(node); - effectiveApplied = true; - } else { - // Apply clause without modifier. - leaf.clauses.push_back(unmodified); - } - applied = true; - } - - if (!applied) - return false; - - tomp::ObjectListT sharedObjects; - llvm::transform(objects, std::back_inserter(sharedObjects), - [&](const ObjectTy &object) { - auto maybeBase = helper.getBaseObject(object); - return maybeBase ? *maybeBase : object; - }); - - // [5.2:341:4] - if (!sharedObjects.empty()) { - if (dirParallel && !applyToParallel) { - auto *shared = makeClause( - llvm::omp::Clause::OMPC_shared, - tomp::clause::SharedT{/*List=*/sharedObjects}); - dirParallel->clauses.push_back(shared); - } - if (dirTeams && !applyToTeams) { - auto *shared = makeClause( - llvm::omp::Clause::OMPC_shared, - tomp::clause::SharedT{/*List=*/sharedObjects}); - dirTeams->clauses.push_back(shared); - } - } - - // [5.2:341:10] - auto dirTarget = findDirective(llvm::omp::Directive::OMPD_target); - if (dirTarget && leafs.size() > 1) { - tomp::ObjectListT tofrom; - llvm::copy_if(objects, std::back_inserter(tofrom), - [&](const ObjectTy &object) { - if (auto maybeBase = helper.getBaseObject(object)) - return !mapBases.count(maybeBase->id()); - return !mapBases.count(object.id()); // XXX is this ok? - }); - if (!tofrom.empty()) { - using MapType = - typename tomp::clause::MapT::MapType; - auto *map = makeClause( - llvm::omp::Clause::OMPC_map, - tomp::clause::MapT{ - {/*MapType=*/MapType::Tofrom, /*MapTypeModifier=*/std::nullopt, - /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, - /*LocatorList=*/std::move(tofrom)}}); - - dirTarget->clauses.push_back(map); - applied = true; - } - } - - return applied; -} - -// IF -// [5.2:72:7-9] -// Directives: cancel, parallel, simd, target, target data, target enter data, -// target exit data, target update, task, taskloop -// -// [5.2:72:15-18] -// (15) For combined or composite constructs, the if clause only applies to the -// semantics of the construct named in the directive-name-modifier. -// (16) For a combined or composite construct, if no directive-name-modifier is -// specified then the if clause applies to all constituent constructs to which -// an if clause can apply. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::IfT &clause, - const ClauseTy *node) { - using DirectiveNameModifier = - typename clause::IfT::DirectiveNameModifier; - using IfExpression = typename clause::IfT::IfExpression; - auto &modifier = std::get>(clause.t); - - if (modifier) { - llvm::omp::Directive dirId = *modifier; - auto *unmodified = - makeClause(llvm::omp::Clause::OMPC_if, - tomp::clause::IfT{ - {/*DirectiveNameModifier=*/std::nullopt, - /*IfExpression=*/std::get(clause.t)}}); - - if (auto *hasDir = findDirective(dirId)) { - hasDir->clauses.push_back(unmodified); - return true; - } - return false; - } - - return applyToAll(node); -} - -// LINEAR -// [5.2:118:1-2] -// Directives: declare simd, do, for, simd -// -// [5.2:341:15-22] -// (15.1) The effect of the linear clause is as if it is applied to the -// innermost leaf construct. -// (15.2) Additionally, if the list item is not the iteration variable of a simd -// or worksharing-loop SIMD construct, the effect on the outer leaf constructs -// is as if the list item was specified in firstprivate and lastprivate clauses -// on the combined or composite construct, with the rules specified above -// applied. -// (19) If a list item of the linear clause is the iteration variable of a simd -// or worksharing-loop SIMD construct and it is not declared in the construct, -// the effect on the outer leaf constructs is as if the list item was specified -// in a lastprivate clause on the combined or composite construct with the rules -// specified above applied. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::LinearT &clause, - const ClauseTy *node) { - // [5.2:341:15.1] - if (!applyToInnermost(node)) - return false; - - // [5.2:341:15.2], [5.2:341:19] - auto dirSimd = findDirective(llvm::omp::Directive::OMPD_simd); - std::optional iterVar = helper.getLoopIterVar(); - const auto &objects = std::get>(clause.t); - - // Lists of objects that will be used to construct "firstprivate" and - // "lastprivate" clauses. - tomp::ObjectListT first, last; - - for (const ObjectTy &object : objects) { - last.push_back(object); - if (!dirSimd || !iterVar || object.id() != iterVar->id()) - first.push_back(object); - } - - if (!first.empty()) { - auto *firstp = makeClause( - llvm::omp::Clause::OMPC_firstprivate, - tomp::clause::FirstprivateT{/*List=*/first}); - nodes.push_back(firstp); // Appending to the main clause list. - } - if (!last.empty()) { - auto *lastp = - makeClause(llvm::omp::Clause::OMPC_lastprivate, - tomp::clause::LastprivateT{ - {/*LastprivateModifier=*/std::nullopt, /*List=*/last}}); - nodes.push_back(lastp); // Appending to the main clause list. - } - return true; -} - -// NOWAIT -// [5.2:308:11-13] -// Directives: dispatch, do, for, interop, scope, sections, single, target, -// target enter data, target exit data, target update, taskwait, workshare -// -// [5.2:341:23] -// (23) The effect of the nowait clause is as if it is applied to the outermost -// leaf construct that permits it. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::NowaitT &clause, - const ClauseTy *node) { - return applyToOutermost(node); -} - -template bool ConstructDecompositionT::split() { - bool success = true; - - for (llvm::omp::Directive leaf : - llvm::omp::getLeafConstructsOrSelf(construct)) - leafs.push_back(LeafReprInternal{leaf, /*clauses=*/{}}); - - for (const ClauseTy *node : nodes) - addClauseSymsToMap(*node, node); - - // First we need to apply LINEAR, because it can generate additional - // "firstprivate" and "lastprivate" clauses that apply to the combined/ - // composite construct. - // Collect them separately, because they may modify the clause list. - llvm::SmallVector linears; - for (const ClauseTy *node : nodes) { - if (node->id == llvm::omp::Clause::OMPC_linear) - linears.push_back(node); - } - for (const auto *node : linears) { - success = success && - applyClause(std::get>( - node->u), - node); - } - - // "allocate" clauses need to be applied last since they need to see - // which directives have data-privatizing clauses. - auto skip = [](const ClauseTy *node) { - switch (node->id) { - case llvm::omp::Clause::OMPC_allocate: - case llvm::omp::Clause::OMPC_linear: - return true; - default: - return false; - } - }; - - // Apply (almost) all clauses. - for (const ClauseTy *node : nodes) { - if (skip(node)) - continue; - success = - success && - std::visit([&](auto &&s) { return applyClause(s, node); }, node->u); - } - - // Apply "allocate". - for (const ClauseTy *node : nodes) { - if (node->id != llvm::omp::Clause::OMPC_allocate) - continue; - success = - success && - std::visit([&](auto &&s) { return applyClause(s, node); }, node->u); - } - - return success; -} - -} // namespace tomp - -#endif // LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H diff --git a/llvm/unittests/Frontend/CMakeLists.txt b/llvm/unittests/Frontend/CMakeLists.txt index 85e113816e3b..3f290b63ba64 100644 --- a/llvm/unittests/Frontend/CMakeLists.txt +++ b/llvm/unittests/Frontend/CMakeLists.txt @@ -15,7 +15,6 @@ add_llvm_unittest(LLVMFrontendTests OpenMPIRBuilderTest.cpp OpenMPParsingTest.cpp OpenMPCompositionTest.cpp - OpenMPDecompositionTest.cpp DEPENDS acc_gen diff --git a/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp b/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp deleted file mode 100644 index df48e9cc0ff4..000000000000 --- a/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp +++ /dev/null @@ -1,999 +0,0 @@ -//===- llvm/unittests/Frontend/OpenMPDecompositionTest.cpp ----------------===// -// -// 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 "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Frontend/OpenMP/ClauseT.h" -#include "llvm/Frontend/OpenMP/ConstructDecompositionT.h" -#include "llvm/Frontend/OpenMP/OMP.h" -#include "gtest/gtest.h" - -#include -#include -#include -#include -#include -#include -#include - -// The actual tests start at comment "--- Test" below. - -// Create simple instantiations of all clauses to allow manual construction -// of clauses, and implement emitting of a directive with clauses to a string. -// -// The tests then follow the pattern -// 1. Create a list of clauses. -// 2. Pass them, together with a construct, to the decomposition class. -// 3. Extract individual resulting leaf constructs with clauses applied -// to them. -// 4. Convert them to strings and compare with expected outputs. - -namespace omp { -struct TypeTy {}; // placeholder -struct ExprTy {}; // placeholder -using IdTy = std::string; -} // namespace omp - -namespace tomp::type { -template <> struct ObjectT { - const omp::IdTy &id() const { return name; } - const std::optional ref() const { return omp::ExprTy{}; } - - omp::IdTy name; -}; -} // namespace tomp::type - -namespace omp { -template using List = tomp::type::ListT; - -using Object = tomp::ObjectT; - -namespace clause { -using DefinedOperator = tomp::type::DefinedOperatorT; -using ProcedureDesignator = tomp::type::ProcedureDesignatorT; -using ReductionOperator = tomp::type::ReductionIdentifierT; - -using AcqRel = tomp::clause::AcqRelT; -using Acquire = tomp::clause::AcquireT; -using AdjustArgs = tomp::clause::AdjustArgsT; -using Affinity = tomp::clause::AffinityT; -using Aligned = tomp::clause::AlignedT; -using Align = tomp::clause::AlignT; -using Allocate = tomp::clause::AllocateT; -using Allocator = tomp::clause::AllocatorT; -using AppendArgs = tomp::clause::AppendArgsT; -using AtomicDefaultMemOrder = - tomp::clause::AtomicDefaultMemOrderT; -using At = tomp::clause::AtT; -using Bind = tomp::clause::BindT; -using Capture = tomp::clause::CaptureT; -using Collapse = tomp::clause::CollapseT; -using Compare = tomp::clause::CompareT; -using Copyin = tomp::clause::CopyinT; -using Copyprivate = tomp::clause::CopyprivateT; -using Defaultmap = tomp::clause::DefaultmapT; -using Default = tomp::clause::DefaultT; -using Depend = tomp::clause::DependT; -using Destroy = tomp::clause::DestroyT; -using Detach = tomp::clause::DetachT; -using Device = tomp::clause::DeviceT; -using DeviceType = tomp::clause::DeviceTypeT; -using DistSchedule = tomp::clause::DistScheduleT; -using Doacross = tomp::clause::DoacrossT; -using DynamicAllocators = - tomp::clause::DynamicAllocatorsT; -using Enter = tomp::clause::EnterT; -using Exclusive = tomp::clause::ExclusiveT; -using Fail = tomp::clause::FailT; -using Filter = tomp::clause::FilterT; -using Final = tomp::clause::FinalT; -using Firstprivate = tomp::clause::FirstprivateT; -using From = tomp::clause::FromT; -using Full = tomp::clause::FullT; -using Grainsize = tomp::clause::GrainsizeT; -using HasDeviceAddr = tomp::clause::HasDeviceAddrT; -using Hint = tomp::clause::HintT; -using If = tomp::clause::IfT; -using Inbranch = tomp::clause::InbranchT; -using Inclusive = tomp::clause::InclusiveT; -using Indirect = tomp::clause::IndirectT; -using Init = tomp::clause::InitT; -using InReduction = tomp::clause::InReductionT; -using IsDevicePtr = tomp::clause::IsDevicePtrT; -using Lastprivate = tomp::clause::LastprivateT; -using Linear = tomp::clause::LinearT; -using Link = tomp::clause::LinkT; -using Map = tomp::clause::MapT; -using Match = tomp::clause::MatchT; -using Mergeable = tomp::clause::MergeableT; -using Message = tomp::clause::MessageT; -using Nocontext = tomp::clause::NocontextT; -using Nogroup = tomp::clause::NogroupT; -using Nontemporal = tomp::clause::NontemporalT; -using Notinbranch = tomp::clause::NotinbranchT; -using Novariants = tomp::clause::NovariantsT; -using Nowait = tomp::clause::NowaitT; -using NumTasks = tomp::clause::NumTasksT; -using NumTeams = tomp::clause::NumTeamsT; -using NumThreads = tomp::clause::NumThreadsT; -using OmpxAttribute = tomp::clause::OmpxAttributeT; -using OmpxBare = tomp::clause::OmpxBareT; -using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT; -using Ordered = tomp::clause::OrderedT; -using Order = tomp::clause::OrderT; -using Partial = tomp::clause::PartialT; -using Priority = tomp::clause::PriorityT; -using Private = tomp::clause::PrivateT; -using ProcBind = tomp::clause::ProcBindT; -using Read = tomp::clause::ReadT; -using Reduction = tomp::clause::ReductionT; -using Relaxed = tomp::clause::RelaxedT; -using Release = tomp::clause::ReleaseT; -using ReverseOffload = tomp::clause::ReverseOffloadT; -using Safelen = tomp::clause::SafelenT; -using Schedule = tomp::clause::ScheduleT; -using SeqCst = tomp::clause::SeqCstT; -using Severity = tomp::clause::SeverityT; -using Shared = tomp::clause::SharedT; -using Simdlen = tomp::clause::SimdlenT; -using Simd = tomp::clause::SimdT; -using Sizes = tomp::clause::SizesT; -using TaskReduction = tomp::clause::TaskReductionT; -using ThreadLimit = tomp::clause::ThreadLimitT; -using Threads = tomp::clause::ThreadsT; -using To = tomp::clause::ToT; -using UnifiedAddress = tomp::clause::UnifiedAddressT; -using UnifiedSharedMemory = - tomp::clause::UnifiedSharedMemoryT; -using Uniform = tomp::clause::UniformT; -using Unknown = tomp::clause::UnknownT; -using Untied = tomp::clause::UntiedT; -using Update = tomp::clause::UpdateT; -using UseDeviceAddr = tomp::clause::UseDeviceAddrT; -using UseDevicePtr = tomp::clause::UseDevicePtrT; -using UsesAllocators = tomp::clause::UsesAllocatorsT; -using Use = tomp::clause::UseT; -using Weak = tomp::clause::WeakT; -using When = tomp::clause::WhenT; -using Write = tomp::clause::WriteT; -} // namespace clause - -struct Helper { - std::optional getBaseObject(const Object &object) { - return std::nullopt; - } - std::optional getLoopIterVar() { return std::nullopt; } -}; - -using Clause = tomp::ClauseT; -using ConstructDecomposition = tomp::ConstructDecompositionT; -using DirectiveWithClauses = tomp::DirectiveWithClauses; -} // namespace omp - -struct StringifyClause { - static std::string join(const omp::List &Strings) { - std::stringstream Stream; - for (const auto &[Index, String] : llvm::enumerate(Strings)) { - if (Index != 0) - Stream << ", "; - Stream << String; - } - return Stream.str(); - } - - static std::string to_str(llvm::omp::Directive D) { - return getOpenMPDirectiveName(D).str(); - } - static std::string to_str(llvm::omp::Clause C) { - return getOpenMPClauseName(C).str(); - } - static std::string to_str(const omp::TypeTy &Type) { return "type"; } - static std::string to_str(const omp::ExprTy &Expr) { return "expr"; } - static std::string to_str(const omp::Object &Obj) { return Obj.id(); } - - template - static std::enable_if_t>, std::string> - to_str(U &&Item) { - return std::to_string(llvm::to_underlying(Item)); - } - - template static std::string to_str(const omp::List &Items) { - omp::List Names; - llvm::transform(Items, std::back_inserter(Names), - [](auto &&S) { return to_str(S); }); - return "(" + join(Names) + ")"; - } - - template - static std::string to_str(const std::optional &Item) { - if (Item) - return to_str(*Item); - return ""; - } - - template - static std::string to_str(const std::tuple &Tuple, - std::index_sequence) { - omp::List Strings; - (Strings.push_back(to_str(std::get(Tuple))), ...); - return "(" + join(Strings) + ")"; - } - - template - static std::enable_if_t::EmptyTrait::value, - std::string> - to_str(U &&Item) { - return ""; - } - - template - static std::enable_if_t::IncompleteTrait::value, - std::string> - to_str(U &&Item) { - return ""; - } - - template - static std::enable_if_t::WrapperTrait::value, - std::string> - to_str(U &&Item) { - // For a wrapper, stringify the wrappee, and only add parentheses if - // there aren't any already. - std::string Str = to_str(Item.v); - if (!Str.empty()) { - if (Str.front() == '(' && Str.back() == ')') - return Str; - } - return "(" + to_str(Item.v) + ")"; - } - - template - static std::enable_if_t::TupleTrait::value, - std::string> - to_str(U &&Item) { - constexpr size_t TupleSize = - std::tuple_size_v>; - return to_str(Item.t, std::make_index_sequence{}); - } - - template - static std::enable_if_t::UnionTrait::value, - std::string> - to_str(U &&Item) { - return std::visit([](auto &&S) { return to_str(S); }, Item.u); - } - - StringifyClause(const omp::Clause &C) - // Rely on content stringification to emit enclosing parentheses. - : Str(to_str(C.id) + to_str(C)) {} - - std::string Str; -}; - -std::string stringify(const omp::DirectiveWithClauses &DWC) { - std::stringstream Stream; - - Stream << getOpenMPDirectiveName(DWC.id).str(); - for (const omp::Clause &C : DWC.clauses) - Stream << ' ' << StringifyClause(C).Str; - - return Stream.str(); -} - -// --- Tests ---------------------------------------------------------- - -namespace { -using namespace llvm::omp; - -class OpenMPDecompositionTest : public testing::Test { -protected: - void SetUp() override {} - void TearDown() override {} - - omp::Helper Helper; - uint32_t AnyVersion = 999; -}; - -// PRIVATE -// [5.2:111:5-7] -// Directives: distribute, do, for, loop, parallel, scope, sections, simd, -// single, target, task, taskloop, teams -// -// [5.2:340:1-2] -// (1) The effect of the 1 private clause is as if it is applied only to the -// innermost leaf construct that permits it. -TEST_F(OpenMPDecompositionTest, Private1) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_private, omp::clause::Private{{x}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, - Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "parallel"); // (1) - ASSERT_EQ(Dir1, "sections private(x)"); // (1) -} - -TEST_F(OpenMPDecompositionTest, Private2) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_private, omp::clause::Private{{x}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, - Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "parallel private(x)"); // (1) - ASSERT_EQ(Dir1, "masked"); // (1) -} - -// FIRSTPRIVATE -// [5.2:112:5-7] -// Directives: distribute, do, for, parallel, scope, sections, single, target, -// task, taskloop, teams -// -// [5.2:340:3-20] -// (3) The effect of the firstprivate clause is as if it is applied to one or -// more leaf constructs as follows: -// (5) To the distribute construct if it is among the constituent constructs; -// (6) To the teams construct if it is among the constituent constructs and the -// distribute construct is not; -// (8) To a worksharing construct that accepts the clause if one is among the -// constituent constructs; -// (9) To the taskloop construct if it is among the constituent constructs; -// (10) To the parallel construct if it is among the constituent constructs and -// neither a taskloop construct nor a worksharing construct that accepts -// the clause is among them; -// (12) To the target construct if it is among the constituent constructs and -// the same list item neither appears in a lastprivate clause nor is the -// base variable or base pointer of a list item that appears in a map -// clause. -// -// (15) If the parallel construct is among the constituent constructs and the -// effect is not as if the firstprivate clause is applied to it by the above -// rules, then the effect is as if the shared clause with the same list item is -// applied to the parallel construct. -// (17) If the teams construct is among the constituent constructs and the -// effect is not as if the firstprivate clause is applied to it by the above -// rules, then the effect is as if the shared clause with the same list item is -// applied to the teams construct. -TEST_F(OpenMPDecompositionTest, Firstprivate1) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, - Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "parallel shared(x)"); // (10), (15) - ASSERT_EQ(Dir1, "sections firstprivate(x)"); // (8) -} - -TEST_F(OpenMPDecompositionTest, Firstprivate2) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, - OMPD_target_teams_distribute, Clauses); - ASSERT_EQ(Dec.output.size(), 3u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - ASSERT_EQ(Dir0, "target firstprivate(x)"); // (12) - ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17) - ASSERT_EQ(Dir2, "distribute firstprivate(x)"); // (5) -} - -TEST_F(OpenMPDecompositionTest, Firstprivate3) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, - {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, - OMPD_target_teams_distribute, Clauses); - ASSERT_EQ(Dec.output.size(), 3u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (12), (27) - ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17) - ASSERT_EQ(Dir2, "distribute firstprivate(x) lastprivate(, (x))"); // (5), (21) -} - -TEST_F(OpenMPDecompositionTest, Firstprivate4) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_teams, - Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "target firstprivate(x)"); // (12) - ASSERT_EQ(Dir1, "teams firstprivate(x)"); // (6) -} - -TEST_F(OpenMPDecompositionTest, Firstprivate5) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, - OMPD_parallel_masked_taskloop, Clauses); - ASSERT_EQ(Dec.output.size(), 3u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - ASSERT_EQ(Dir0, "parallel shared(x)"); // (10) - ASSERT_EQ(Dir1, "masked"); - ASSERT_EQ(Dir2, "taskloop firstprivate(x)"); // (9) -} - -TEST_F(OpenMPDecompositionTest, Firstprivate6) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, - Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "parallel firstprivate(x)"); // (10) - ASSERT_EQ(Dir1, "masked"); -} - -TEST_F(OpenMPDecompositionTest, Firstprivate7) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, - }; - - // Composite constructs are still decomposed. - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_distribute, - Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "teams shared(x)"); // (17) - ASSERT_EQ(Dir1, "distribute firstprivate(x)"); // (5) -} - -// LASTPRIVATE -// [5.2:115:7-8] -// Directives: distribute, do, for, loop, sections, simd, taskloop -// -// [5.2:340:21-30] -// (21) The effect of the lastprivate clause is as if it is applied to all leaf -// constructs that permit the clause. -// (22) If the parallel construct is among the constituent constructs and the -// list item is not also specified in the firstprivate clause, then the effect -// of the lastprivate clause is as if the shared clause with the same list item -// is applied to the parallel construct. -// (24) If the teams construct is among the constituent constructs and the list -// item is not also specified in the firstprivate clause, then the effect of the -// lastprivate clause is as if the shared clause with the same list item is -// applied to the teams construct. -// (27) If the target construct is among the constituent constructs and the list -// item is not the base variable or base pointer of a list item that appears in -// a map clause, the effect of the lastprivate clause is as if the same list -// item appears in a map clause with a map-type of tofrom. -TEST_F(OpenMPDecompositionTest, Lastprivate1) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, - Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "parallel shared(x)"); // (21), (22) - ASSERT_EQ(Dir1, "sections lastprivate(, (x))"); // (21) -} - -TEST_F(OpenMPDecompositionTest, Lastprivate2) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_distribute, - Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "teams shared(x)"); // (21), (25) - ASSERT_EQ(Dir1, "distribute lastprivate(, (x))"); // (21) -} - -TEST_F(OpenMPDecompositionTest, Lastprivate3) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_do, - Clauses); - ASSERT_EQ(Dec.output.size(), 3u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (21), (27) - ASSERT_EQ(Dir1, "parallel shared(x)"); // (22) - ASSERT_EQ(Dir2, "do lastprivate(, (x))"); // (21) -} - -// SHARED -// [5.2:110:5-6] -// Directives: parallel, task, taskloop, teams -// -// [5.2:340:31-32] -// (31) The effect of the shared, default, thread_limit, or order clause is as -// if it is applied to all leaf constructs that permit the clause. -TEST_F(OpenMPDecompositionTest, Shared1) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_shared, omp::clause::Shared{{x}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, - OMPD_parallel_masked_taskloop, Clauses); - ASSERT_EQ(Dec.output.size(), 3u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - ASSERT_EQ(Dir0, "parallel shared(x)"); // (31) - ASSERT_EQ(Dir1, "masked"); // (31) - ASSERT_EQ(Dir2, "taskloop shared(x)"); // (31) -} - -// DEFAULT -// [5.2:109:5-6] -// Directives: parallel, task, taskloop, teams -// -// [5.2:340:31-32] -// (31) The effect of the shared, default, thread_limit, or order clause is as -// if it is applied to all leaf constructs that permit the clause. -TEST_F(OpenMPDecompositionTest, Default1) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_default, - omp::clause::Default{ - omp::clause::Default::DataSharingAttribute::Firstprivate}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, - OMPD_parallel_masked_taskloop, Clauses); - ASSERT_EQ(Dec.output.size(), 3u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - ASSERT_EQ(Dir0, "parallel default(0)"); // (31) - ASSERT_EQ(Dir1, "masked"); // (31) - ASSERT_EQ(Dir2, "taskloop default(0)"); // (31) -} - -// THREAD_LIMIT -// [5.2:277:14-15] -// Directives: target, teams -// -// [5.2:340:31-32] -// (31) The effect of the shared, default, thread_limit, or order clause is as -// if it is applied to all leaf constructs that permit the clause. -TEST_F(OpenMPDecompositionTest, ThreadLimit1) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_thread_limit, omp::clause::ThreadLimit{omp::ExprTy{}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, - OMPD_target_teams_distribute, Clauses); - ASSERT_EQ(Dec.output.size(), 3u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - ASSERT_EQ(Dir0, "target thread_limit(expr)"); // (31) - ASSERT_EQ(Dir1, "teams thread_limit(expr)"); // (31) - ASSERT_EQ(Dir2, "distribute"); // (31) -} - -// ORDER -// [5.2:234:3-4] -// Directives: distribute, do, for, loop, simd -// -// [5.2:340:31-32] -// (31) The effect of the shared, default, thread_limit, or order clause is as -// if it is applied to all leaf constructs that permit the clause. -TEST_F(OpenMPDecompositionTest, Order1) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_order, - omp::clause::Order{{omp::clause::Order::OrderModifier::Unconstrained, - omp::clause::Order::Ordering::Concurrent}}}, - }; - - omp::ConstructDecomposition Dec( - AnyVersion, Helper, OMPD_target_teams_distribute_parallel_for_simd, - Clauses); - ASSERT_EQ(Dec.output.size(), 6u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - std::string Dir3 = stringify(Dec.output[3]); - std::string Dir4 = stringify(Dec.output[4]); - std::string Dir5 = stringify(Dec.output[5]); - ASSERT_EQ(Dir0, "target"); // (31) - ASSERT_EQ(Dir1, "teams"); // (31) - // XXX OMP.td doesn't list "order" as allowed for "distribute" - ASSERT_EQ(Dir2, "distribute"); // (31) - ASSERT_EQ(Dir3, "parallel"); // (31) - ASSERT_EQ(Dir4, "for order(1, 0)"); // (31) - ASSERT_EQ(Dir5, "simd order(1, 0)"); // (31) -} - -// ALLOCATE -// [5.2:178:7-9] -// Directives: allocators, distribute, do, for, parallel, scope, sections, -// single, target, task, taskgroup, taskloop, teams -// -// [5.2:340:33-35] -// (33) The effect of the allocate clause is as if it is applied to all leaf -// constructs that permit the clause and to which a data-sharing attribute -// clause that may create a private copy of the same list item is applied. -TEST_F(OpenMPDecompositionTest, Allocate1) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_allocate, - omp::clause::Allocate{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, - {OMPC_private, omp::clause::Private{{x}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, - Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "parallel"); // (33) - ASSERT_EQ(Dir1, "sections private(x) allocate(, , , (x))"); // (33) -} - -// REDUCTION -// [5.2:134:17-18] -// Directives: do, for, loop, parallel, scope, sections, simd, taskloop, teams -// -// [5.2:340-341:36-13] -// (36) The effect of the reduction clause is as if it is applied to all leaf -// constructs that permit the clause, except for the following constructs: -// (1) The parallel construct, when combined with the sections, -// worksharing-loop, loop, or taskloop construct; and -// (3) The teams construct, when combined with the loop construct. -// (4) For the parallel and teams constructs above, the effect of the reduction -// clause instead is as if each list item or, for any list item that is an array -// item, its corresponding base array or base pointer appears in a shared clause -// for the construct. -// (6) If the task reduction-modifier is specified, the effect is as if it only -// modifies the behavior of the reduction clause on the innermost leaf construct -// that accepts the modifier (see Section 5.5.8). -// (8) If the inscan reduction-modifier is specified, the effect is as if it -// modifies the behavior of the reduction clause on all constructs of the -// combined construct to which the clause is applied and that accept the -// modifier. -// (10) If a list item in a reduction clause on a combined target construct does -// not have the same base variable or base pointer as a list item in a map -// clause on the construct, then the effect is as if the list item in the -// reduction clause appears as a list item in a map clause with a map-type of -// tofrom. -namespace red { -// Make is easier to construct reduction operators from built-in intrinsics. -omp::clause::ReductionOperator -makeOp(omp::clause::DefinedOperator::IntrinsicOperator Op) { - return omp::clause::ReductionOperator{omp::clause::DefinedOperator{Op}}; -} -} // namespace red - -TEST_F(OpenMPDecompositionTest, Reduction1) { - omp::Object x{"x"}; - auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); - - omp::List Clauses{ - {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, - Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "parallel shared(x)"); // (36), (1), (4) - ASSERT_EQ(Dir1, "sections reduction(, (3), (x))"); // (36) -} - -TEST_F(OpenMPDecompositionTest, Reduction2) { - omp::Object x{"x"}; - auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); - - omp::List Clauses{ - {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, - Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "parallel reduction(, (3), (x))"); // (36), (1), (4) - ASSERT_EQ(Dir1, "masked"); // (36) -} - -TEST_F(OpenMPDecompositionTest, Reduction3) { - omp::Object x{"x"}; - auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); - - omp::List Clauses{ - {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_loop, Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "teams shared(x)"); // (36), (3), (4) - ASSERT_EQ(Dir1, "loop reduction(, (3), (x))"); // (36) -} - -TEST_F(OpenMPDecompositionTest, Reduction4) { - omp::Object x{"x"}; - auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); - - omp::List Clauses{ - {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, - OMPD_teams_distribute_parallel_for, Clauses); - ASSERT_EQ(Dec.output.size(), 4u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - std::string Dir3 = stringify(Dec.output[3]); - ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3) - ASSERT_EQ(Dir1, "distribute"); // (36) - ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) - ASSERT_EQ(Dir3, "for reduction(, (3), (x))"); // (36) -} - -TEST_F(OpenMPDecompositionTest, Reduction5) { - omp::Object x{"x"}; - auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); - auto TaskMod = omp::clause::Reduction::ReductionModifier::Task; - - omp::List Clauses{ - {OMPC_reduction, omp::clause::Reduction{{TaskMod, {Add}, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, - OMPD_teams_distribute_parallel_for, Clauses); - ASSERT_EQ(Dec.output.size(), 4u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - std::string Dir3 = stringify(Dec.output[3]); - ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3), (6) - ASSERT_EQ(Dir1, "distribute"); // (36) - ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) - ASSERT_EQ(Dir3, "for reduction(2, (3), (x))"); // (36), (6) -} - -TEST_F(OpenMPDecompositionTest, Reduction6) { - omp::Object x{"x"}; - auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); - auto InscanMod = omp::clause::Reduction::ReductionModifier::Inscan; - - omp::List Clauses{ - {OMPC_reduction, omp::clause::Reduction{{InscanMod, {Add}, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, - OMPD_teams_distribute_parallel_for, Clauses); - ASSERT_EQ(Dec.output.size(), 4u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - std::string Dir3 = stringify(Dec.output[3]); - ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3), (8) - ASSERT_EQ(Dir1, "distribute"); // (36) - ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) - ASSERT_EQ(Dir3, "for reduction(1, (3), (x))"); // (36), (8) -} - -TEST_F(OpenMPDecompositionTest, Reduction7) { - omp::Object x{"x"}; - auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); - - omp::List Clauses{ - {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_do, - Clauses); - ASSERT_EQ(Dec.output.size(), 3u); - - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - // XXX Currently OMP.td allows "reduction" on "target". - ASSERT_EQ(Dir0, - "target reduction(, (3), (x)) map(2, , , , (x))"); // (36), (10) - ASSERT_EQ(Dir1, "parallel shared(x)"); // (36), (1), (4) - ASSERT_EQ(Dir2, "do reduction(, (3), (x))"); // (36) -} - -// IF -// [5.2:72:7-9] -// Directives: cancel, parallel, simd, target, target data, target enter data, -// target exit data, target update, task, taskloop -// -// [5.2:72:15-18] -// (15) For combined or composite constructs, the if clause only applies to the -// semantics of the construct named in the directive-name-modifier. -// (16) For a combined or composite construct, if no directive-name-modifier is -// specified then the if clause applies to all constituent constructs to which -// an if clause can apply. -TEST_F(OpenMPDecompositionTest, If1) { - omp::List Clauses{ - {OMPC_if, - omp::clause::If{{llvm::omp::Directive::OMPD_parallel, omp::ExprTy{}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, - OMPD_target_parallel_for_simd, Clauses); - ASSERT_EQ(Dec.output.size(), 4u); - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - std::string Dir3 = stringify(Dec.output[3]); - ASSERT_EQ(Dir0, "target"); // (15) - ASSERT_EQ(Dir1, "parallel if(, expr)"); // (15) - ASSERT_EQ(Dir2, "for"); // (15) - ASSERT_EQ(Dir3, "simd"); // (15) -} - -TEST_F(OpenMPDecompositionTest, If2) { - omp::List Clauses{ - {OMPC_if, omp::clause::If{{std::nullopt, omp::ExprTy{}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, - OMPD_target_parallel_for_simd, Clauses); - ASSERT_EQ(Dec.output.size(), 4u); - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - std::string Dir3 = stringify(Dec.output[3]); - ASSERT_EQ(Dir0, "target if(, expr)"); // (16) - ASSERT_EQ(Dir1, "parallel if(, expr)"); // (16) - ASSERT_EQ(Dir2, "for"); // (16) - ASSERT_EQ(Dir3, "simd if(, expr)"); // (16) -} - -// LINEAR -// [5.2:118:1-2] -// Directives: declare simd, do, for, simd -// -// [5.2:341:15-22] -// (15.1) The effect of the linear clause is as if it is applied to the -// innermost leaf construct. -// (15.2) Additionally, if the list item is not the iteration variable of a simd -// or worksharing-loop SIMD construct, the effect on the outer leaf constructs -// is as if the list item was specified in firstprivate and lastprivate clauses -// on the combined or composite construct, with the rules specified above -// applied. -// (19) If a list item of the linear clause is the iteration variable of a simd -// or worksharing-loop SIMD construct and it is not declared in the construct, -// the effect on the outer leaf constructs is as if the list item was specified -// in a lastprivate clause on the combined or composite construct with the rules -// specified above applied. -TEST_F(OpenMPDecompositionTest, Linear1) { - omp::Object x{"x"}; - - omp::List Clauses{ - {OMPC_linear, - omp::clause::Linear{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_for_simd, Clauses); - ASSERT_EQ(Dec.output.size(), 2u); - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - ASSERT_EQ(Dir0, "for firstprivate(x) lastprivate(, (x))"); // (15.1), (15.2) - ASSERT_EQ(Dir1, "simd linear(, , , (x)) lastprivate(, (x))"); // (15.1) -} - -// NOWAIT -// [5.2:308:11-13] -// Directives: dispatch, do, for, interop, scope, sections, single, target, -// target enter data, target exit data, target update, taskwait, workshare -// -// [5.2:341:23] -// (23) The effect of the nowait clause is as if it is applied to the outermost -// leaf construct that permits it. -TEST_F(OpenMPDecompositionTest, Nowait1) { - omp::List Clauses{ - {OMPC_nowait, omp::clause::Nowait{}}, - }; - - omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_for, - Clauses); - ASSERT_EQ(Dec.output.size(), 3u); - std::string Dir0 = stringify(Dec.output[0]); - std::string Dir1 = stringify(Dec.output[1]); - std::string Dir2 = stringify(Dec.output[2]); - ASSERT_EQ(Dir0, "target nowait"); // (23) - ASSERT_EQ(Dir1, "parallel"); // (23) - ASSERT_EQ(Dir2, "for"); // (23) -} -} // namespace -- GitLab From 1a25b723628e439d62dfb28ca5fa52e4b2a78e5a Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Mon, 13 May 2024 17:47:03 +0400 Subject: [PATCH 063/578] [lldb] Fixed the test TestPlatformProcessLaunch running on a remote target (#91923) Transfer `stdio.log` from the remote target if necessary. --- .../launch/TestPlatformProcessLaunch.py | 90 ++++++++++--------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/lldb/test/API/commands/platform/process/launch/TestPlatformProcessLaunch.py b/lldb/test/API/commands/platform/process/launch/TestPlatformProcessLaunch.py index 3fb7d00c93d2..7cbad03eeeea 100644 --- a/lldb/test/API/commands/platform/process/launch/TestPlatformProcessLaunch.py +++ b/lldb/test/API/commands/platform/process/launch/TestPlatformProcessLaunch.py @@ -3,6 +3,7 @@ Test platform process launch. """ from textwrap import dedent +from lldbsuite.test import lldbutil from lldbsuite.test.lldbtest import TestBase @@ -11,9 +12,10 @@ class ProcessLaunchTestCase(TestBase): def setup(self): self.build() - exe = self.getBuildArtifact("a.out") - self.runCmd("file " + exe) - return (exe, self.getBuildArtifact("stdio.log")) + self.runCmd("file " + self.getBuildArtifact("a.out")) + exe = lldbutil.append_to_process_working_directory(self, "a.out") + outfile = lldbutil.append_to_process_working_directory(self, "stdio.log") + return (exe, outfile) def test_process_launch_no_args(self): # When there are no extra arguments we just have 0, the program name. @@ -21,18 +23,18 @@ class ProcessLaunchTestCase(TestBase): self.runCmd("platform process launch --stdout {} -s".format(outfile)) self.runCmd("continue") - with open(outfile) as f: - self.assertEqual( - dedent( - """\ - Got 1 argument(s). - [0]: {} - """.format( - exe - ) - ), - f.read(), - ) + stdio_log = lldbutil.read_file_on_target(self, outfile) + self.assertEqual( + dedent( + """\ + Got 1 argument(s). + [0]: {} + """.format( + exe + ) + ), + stdio_log, + ) def test_process_launch_command_args(self): exe, outfile = self.setup() @@ -41,21 +43,21 @@ class ProcessLaunchTestCase(TestBase): self.runCmd("platform process launch --stdout {} -s -- A B C".format(outfile)) self.runCmd("continue") - with open(outfile) as f: - self.assertEqual( - dedent( - """\ - Got 4 argument(s). - [0]: {} - [1]: A - [2]: B - [3]: C - """.format( - exe - ) - ), - f.read(), - ) + stdio_log = lldbutil.read_file_on_target(self, outfile) + self.assertEqual( + dedent( + """\ + Got 4 argument(s). + [0]: {} + [1]: A + [2]: B + [3]: C + """.format( + exe + ) + ), + stdio_log, + ) def test_process_launch_target_args(self): exe, outfile = self.setup() @@ -64,17 +66,17 @@ class ProcessLaunchTestCase(TestBase): self.runCmd("platform process launch --stdout {} -s".format(outfile)) self.runCmd("continue") - with open(outfile) as f: - self.assertEqual( - dedent( - """\ - Got 3 argument(s). - [0]: {} - [1]: D - [2]: E - """.format( - exe - ) - ), - f.read(), - ) + stdio_log = lldbutil.read_file_on_target(self, outfile) + self.assertEqual( + dedent( + """\ + Got 3 argument(s). + [0]: {} + [1]: D + [2]: E + """.format( + exe + ) + ), + stdio_log, + ) -- GitLab From 13cd88108f00fc97bcd1e4eb7cc9e4e388928677 Mon Sep 17 00:00:00 2001 From: Pranav Bhandarkar Date: Mon, 13 May 2024 08:54:23 -0500 Subject: [PATCH 064/578] [mlir][OpenMP] - Honor dependencies in code-generation of the if clause in `omp.task` correctly (#90891) This patch fixes the code generation of the if clause, specifically when the condition evaluates to false and when the task directive has the depend clause on it. When the if clause of a task construct evaluates to false, then the task is an undeferred task. This undeferred task still has to honor dependencies. Previously, the OpenMPIRbuilder didn't honor dependencies. This patch fixes that. Fixes https://github.com/llvm/llvm-project/issues/90869 --- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 13 +++++++++++++ mlir/test/Target/LLVMIR/omptask_if_false.mlir | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 mlir/test/Target/LLVMIR/omptask_if_false.mlir diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp index 42ea20919a5e..391a4947877a 100644 --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -1870,6 +1870,9 @@ OpenMPIRBuilder::createTask(const LocationDescription &Loc, // call @__kmpc_omp_task(...) // br label %exit // else: + // ;; Wait for resolution of dependencies, if any, before + // ;; beginning the task + // call @__kmpc_omp_wait_deps(...) // call @__kmpc_omp_task_begin_if0(...) // call @outlined_fn(...) // call @__kmpc_omp_task_complete_if0(...) @@ -1887,6 +1890,16 @@ OpenMPIRBuilder::createTask(const LocationDescription &Loc, SplitBlockAndInsertIfThenElse(IfCondition, IfTerminator, &ThenTI, &ElseTI); Builder.SetInsertPoint(ElseTI); + + if (Dependencies.size()) { + Function *TaskWaitFn = + getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_wait_deps); + Builder.CreateCall( + TaskWaitFn, + {Ident, ThreadID, Builder.getInt32(Dependencies.size()), DepArray, + ConstantInt::get(Builder.getInt32Ty(), 0), + ConstantPointerNull::get(PointerType::getUnqual(M.getContext()))}); + } Function *TaskBeginFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_task_begin_if0); Function *TaskCompleteFn = diff --git a/mlir/test/Target/LLVMIR/omptask_if_false.mlir b/mlir/test/Target/LLVMIR/omptask_if_false.mlir new file mode 100644 index 000000000000..c6014a76add6 --- /dev/null +++ b/mlir/test/Target/LLVMIR/omptask_if_false.mlir @@ -0,0 +1,17 @@ +// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s + +llvm.func @foo_(%arg0: !llvm.ptr {fir.bindc_name = "n"}, %arg1: !llvm.ptr {fir.bindc_name = "r"}) attributes {fir.internal_name = "_QPfoo"} { + %0 = llvm.mlir.constant(false) : i1 + omp.task if(%0) depend(taskdependin -> %arg0 : !llvm.ptr) { + %1 = llvm.load %arg0 : !llvm.ptr -> i32 + llvm.store %1, %arg1 : i32, !llvm.ptr + omp.terminator + } + llvm.return +} + +// CHECK: call void @__kmpc_omp_wait_deps +// CHECK-NEXT: call void @__kmpc_omp_task_begin_if0 +// CHECK-NEXT: call void @foo_..omp_par +// CHECK-NEXT: call void @__kmpc_omp_task_complete_if0 + -- GitLab From 4445ed4244cd00981a04b1f461128ed4c47c1dec Mon Sep 17 00:00:00 2001 From: Oleg Shyshkov Date: Mon, 13 May 2024 15:57:57 +0200 Subject: [PATCH 065/578] [OpenMP][MLIR] Fix llvm::sort comparator. (#91963) The current comparator doesn't work correctly when two identical entries with -1 are compared. The comparator returns `first` is case when `aIndex == -1 && bIndex == -1`, but it should `continue` as those indexes are the same. --- .../LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 282e640d3aaa..a7294632d666 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -2155,18 +2155,15 @@ getFirstOrLastMappedMemberPtr(mlir::omp::MapInfoOp mapInfo, bool first) { int aIndex = indexValues[a * shape[1] + i]; int bIndex = indexValues[b * shape[1] + i]; + if (aIndex == bIndex) + continue; + if (aIndex != -1 && bIndex == -1) return false; if (aIndex == -1 && bIndex != -1) return true; - if (aIndex == -1) - return first; - - if (bIndex == -1) - return !first; - // A is earlier in the record type layout than B if (aIndex < bIndex) return first; -- GitLab From c4e9e41199127bb288e84e9477da99f28941edb3 Mon Sep 17 00:00:00 2001 From: cor3ntin Date: Mon, 13 May 2024 16:04:20 +0200 Subject: [PATCH 066/578] [Clang] Ensure ``if consteval`` consititute an immediate function context (#91939) We did not set the correct evaluation context for the compound statement of an ``if consteval`` statement in a templated entity in TreeTransform. Fixes #91509 --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/TreeTransform.h | 10 +++++++ .../SemaCXX/cxx2b-consteval-propagate.cpp | 26 +++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7c5dcc59c701..4702b8c10cdb 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -707,6 +707,7 @@ Bug Fixes to C++ Support initialized, rather than evaluating them as a part of the larger manifestly constant evaluated expression. - Fix a bug in access control checking due to dealyed checking of friend declaration. Fixes (#GH12361). +- Correctly treat the compound statement of an ``if consteval`` as an immediate context. Fixes (#GH91509). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 0b3cf566e3a7..126965088831 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -7964,6 +7964,11 @@ TreeTransform::TransformIfStmt(IfStmt *S) { // Transform the "then" branch. StmtResult Then; if (!ConstexprConditionValue || *ConstexprConditionValue) { + EnterExpressionEvaluationContext Ctx( + getSema(), Sema::ExpressionEvaluationContext::ImmediateFunctionContext, + nullptr, Sema::ExpressionEvaluationContextRecord::EK_Other, + S->isNonNegatedConsteval()); + Then = getDerived().TransformStmt(S->getThen()); if (Then.isInvalid()) return StmtError(); @@ -7978,6 +7983,11 @@ TreeTransform::TransformIfStmt(IfStmt *S) { // Transform the "else" branch. StmtResult Else; if (!ConstexprConditionValue || !*ConstexprConditionValue) { + EnterExpressionEvaluationContext Ctx( + getSema(), Sema::ExpressionEvaluationContext::ImmediateFunctionContext, + nullptr, Sema::ExpressionEvaluationContextRecord::EK_Other, + S->isNegatedConsteval()); + Else = getDerived().TransformStmt(S->getElse()); if (Else.isInvalid()) return StmtError(); diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp index 37fa1f1bdf59..07937deb6673 100644 --- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp +++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp @@ -420,3 +420,29 @@ int f = *fn().value + fn2(); // expected-error {{call to consteval function 'lv // expected-note {{pointer to heap-allocated object}} } #endif + + +#if __cplusplus >= 202302L + +namespace GH91509 { + +consteval int f(int) { return 0; } + +template +constexpr int g(int x) { + if consteval { + return f(x); + } + if !consteval {} + else { + return f(x); + } + return 1; +} + +int h(int x) { + return g(x); +} +} + +#endif -- GitLab From b0b6c16b470a7d5d9c63765058cca0ebe07ad57d Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Mon, 13 May 2024 16:10:58 +0200 Subject: [PATCH 067/578] [Clang][OpenMP][Tile] Allow non-constant tile sizes. (#91345) Allow non-constants in the `sizes` clause such as ``` #pragma omp tile sizes(a) for (int i = 0; i < n; ++i) ``` This is permitted since tile was introduced in [OpenMP 5.1](https://www.openmp.org/spec-html/5.1/openmpsu53.html#x78-860002.11.9). It is possible to sneak-in negative numbers at runtime as in ``` int a = -1; #pragma omp tile sizes(a) ``` Even though it is not well-formed, it should still result in every loop iteration to be executed exactly once, an invariant of the tile construct that we should ensure. `ParseOpenMPExprListClause` is extracted-out to be reused by the `permutation` clause of the `interchange` construct. Some care was put into ensuring correct behavior in template contexts. --- clang/include/clang/Parse/Parser.h | 17 ++ clang/lib/Parse/ParseOpenMP.cpp | 65 ++++-- clang/lib/Sema/SemaOpenMP.cpp | 118 ++++++++-- clang/test/OpenMP/tile_ast_print.cpp | 17 ++ clang/test/OpenMP/tile_codegen.cpp | 216 ++++++++++++++++-- clang/test/OpenMP/tile_messages.cpp | 50 +++- openmp/runtime/test/transform/tile/intfor.c | 191 ++++++++++++++++ .../test/transform/tile/negtile_intfor.c | 44 ++++ .../tile/parallel-wsloop-collapse-intfor.cpp | 100 ++++++++ 9 files changed, 748 insertions(+), 70 deletions(-) create mode 100644 openmp/runtime/test/transform/tile/intfor.c create mode 100644 openmp/runtime/test/transform/tile/negtile_intfor.c create mode 100644 openmp/runtime/test/transform/tile/parallel-wsloop-collapse-intfor.cpp diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 60d59732269b..61589fb7766f 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3553,6 +3553,23 @@ private: OMPClause *ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, bool ParseOnly); + /// Parses a clause consisting of a list of expressions. + /// + /// \param Kind The clause to parse. + /// \param ClauseNameLoc [out] The location of the clause name. + /// \param OpenLoc [out] The location of '('. + /// \param CloseLoc [out] The location of ')'. + /// \param Exprs [out] The parsed expressions. + /// \param ReqIntConst If true, each expression must be an integer constant. + /// + /// \return Whether the clause was parsed successfully. + bool ParseOpenMPExprListClause(OpenMPClauseKind Kind, + SourceLocation &ClauseNameLoc, + SourceLocation &OpenLoc, + SourceLocation &CloseLoc, + SmallVectorImpl &Exprs, + bool ReqIntConst = false); + /// Parses and creates OpenMP 5.0 iterators expression: /// = 'iterator' '(' { [ ] identifier = /// }+ ')' diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 53eabe0c662e..03a64600bc2a 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -3107,34 +3107,14 @@ bool Parser::ParseOpenMPSimpleVarList( } OMPClause *Parser::ParseOpenMPSizesClause() { - SourceLocation ClauseNameLoc = ConsumeToken(); + SourceLocation ClauseNameLoc, OpenLoc, CloseLoc; SmallVector ValExprs; - - BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); - if (T.consumeOpen()) { - Diag(Tok, diag::err_expected) << tok::l_paren; + if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc, + ValExprs)) return nullptr; - } - - while (true) { - ExprResult Val = ParseConstantExpression(); - if (!Val.isUsable()) { - T.skipToEnd(); - return nullptr; - } - - ValExprs.push_back(Val.get()); - - if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end)) - break; - - ExpectAndConsume(tok::comma); - } - - T.consumeClose(); - return Actions.OpenMP().ActOnOpenMPSizesClause( - ValExprs, ClauseNameLoc, T.getOpenLocation(), T.getCloseLocation()); + return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc, + OpenLoc, CloseLoc); } OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) { @@ -4991,3 +4971,38 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data); } + +bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind, + SourceLocation &ClauseNameLoc, + SourceLocation &OpenLoc, + SourceLocation &CloseLoc, + SmallVectorImpl &Exprs, + bool ReqIntConst) { + assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) && + "Expected parsing to start at clause name"); + ClauseNameLoc = ConsumeToken(); + + // Parse inside of '(' and ')'. + BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); + if (T.consumeOpen()) { + Diag(Tok, diag::err_expected) << tok::l_paren; + return true; + } + + // Parse the list with interleaved commas. + do { + ExprResult Val = + ReqIntConst ? ParseConstantExpression() : ParseAssignmentExpression(); + if (!Val.isUsable()) { + // Encountered something other than an expression; abort to ')'. + T.skipToEnd(); + return true; + } + Exprs.push_back(Val.get()); + } while (TryConsumeToken(tok::comma)); + + bool Result = T.consumeClose(); + OpenLoc = T.getOpenLocation(); + CloseLoc = T.getCloseLocation(); + return Result; +} diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 2475f962fd0d..7d00cf6fb5b6 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -15111,13 +15111,11 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, ASTContext &Context = getASTContext(); Scope *CurScope = SemaRef.getCurScope(); - auto SizesClauses = - OMPExecutableDirective::getClausesOfKind(Clauses); - if (SizesClauses.empty()) { - // A missing 'sizes' clause is already reported by the parser. + const auto *SizesClause = + OMPExecutableDirective::getSingleClause(Clauses); + if (!SizesClause || + llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; })) return StmtError(); - } - const OMPSizesClause *SizesClause = *SizesClauses.begin(); unsigned NumLoops = SizesClause->getNumSizes(); // Empty statement should only be possible if there already was an error. @@ -15138,6 +15136,13 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops, AStmt, nullptr, nullptr); + assert(LoopHelpers.size() == NumLoops && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + assert(OriginalInits.size() == NumLoops && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + SmallVector PreInits; CaptureVars CopyTransformer(SemaRef); @@ -15197,6 +15202,44 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, // Once the original iteration values are set, append the innermost body. Stmt *Inner = Body; + auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context, + SizesClause, CurScope](int I) -> Expr * { + Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I]; + if (isa(DimTileSizeExpr)) + return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)); + + // When the tile size is not a constant but a variable, it is possible to + // pass non-positive numbers. For instance: + // \code{c} + // int a = 0; + // #pragma omp tile sizes(a) + // for (int i = 0; i < 42; ++i) + // body(i); + // \endcode + // Although there is no meaningful interpretation of the tile size, the body + // should still be executed 42 times to avoid surprises. To preserve the + // invariant that every loop iteration is executed exactly once and not + // cause an infinite loop, apply a minimum tile size of one. + // Build expr: + // \code{c} + // (TS <= 0) ? 1 : TS + // \endcode + QualType DimTy = DimTileSizeExpr->getType(); + uint64_t DimWidth = Context.getTypeSize(DimTy); + IntegerLiteral *Zero = IntegerLiteral::Create( + Context, llvm::APInt::getZero(DimWidth), DimTy, {}); + IntegerLiteral *One = + IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {}); + Expr *Cond = AssertSuccess(SemaRef.BuildBinOp( + CurScope, {}, BO_LE, + AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero)); + Expr *MinOne = new (Context) ConditionalOperator( + Cond, {}, One, {}, + AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy, + VK_PRValue, OK_Ordinary); + return MinOne; + }; + // Create tile loops from the inside to the outside. for (int I = NumLoops - 1; I >= 0; --I) { OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I]; @@ -15207,10 +15250,6 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, // 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 MakeDimTileSize = [&CopyTransformer, I, SizesClause]() -> Expr * { - Expr *DimTileSize = SizesClause->getSizesRefs()[I]; - return AssertSuccess(CopyTransformer.TransformExpr(DimTileSize)); - }; auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, CntTy, OrigCntVar]() { return buildDeclRefExpr(SemaRef, TileIndVars[I], CntTy, @@ -15237,7 +15276,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, // .tile.iv < min(.floor.iv + DimTileSize, NumIterations) ExprResult EndOfTile = SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add, - MakeFloorIVRef(), MakeDimTileSize()); + MakeFloorIVRef(), MakeDimTileSize(I)); if (!EndOfTile.isUsable()) return StmtError(); ExprResult IsPartialTile = @@ -15297,10 +15336,6 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, QualType CntTy = OrigCntVar->getType(); // Commonly used variables. - auto MakeDimTileSize = [&CopyTransformer, I, SizesClause]() -> Expr * { - Expr *DimTileSize = SizesClause->getSizesRefs()[I]; - return AssertSuccess(CopyTransformer.TransformExpr(DimTileSize)); - }; auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, CntTy, OrigCntVar]() { return buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy, @@ -15329,7 +15364,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, // For incr-statement: .floor.iv += DimTileSize ExprResult IncrStmt = SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign, - MakeFloorIVRef(), MakeDimTileSize()); + MakeFloorIVRef(), MakeDimTileSize(I)); if (!IncrStmt.isUsable()) return StmtError(); @@ -17430,16 +17465,53 @@ OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { - for (Expr *SizeExpr : SizeExprs) { - ExprResult NumForLoopsResult = VerifyPositiveIntegerConstantInClause( - SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true); - if (!NumForLoopsResult.isUsable()) - return nullptr; + SmallVector SanitizedSizeExprs(SizeExprs); + + for (Expr *&SizeExpr : SanitizedSizeExprs) { + // Skip if already sanitized, e.g. during a partial template instantiation. + if (!SizeExpr) + continue; + + bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes, + /*StrictlyPositive=*/true); + + // isNonNegativeIntegerValue returns true for non-integral types (but still + // emits error diagnostic), so check for the expected type explicitly. + QualType SizeTy = SizeExpr->getType(); + if (!SizeTy->isIntegerType()) + IsValid = false; + + // Handling in templates is tricky. There are four possibilities to + // consider: + // + // 1a. The expression is valid and we are in a instantiated template or not + // in a template: + // Pass valid expression to be further analysed later in Sema. + // 1b. The expression is valid and we are in a template (including partial + // instantiation): + // isNonNegativeIntegerValue skipped any checks so there is no + // guarantee it will be correct after instantiation. + // ActOnOpenMPSizesClause will be called again at instantiation when + // it is not in a dependent context anymore. This may cause warnings + // to be emitted multiple times. + // 2a. The expression is invalid and we are in an instantiated template or + // not in a template: + // Invalidate the expression with a clearly wrong value (nullptr) so + // later in Sema we do not have to do the same validity analysis again + // or crash from unexpected data. Error diagnostics have already been + // emitted. + // 2b. The expression is invalid and we are in a template (including partial + // instantiation): + // Pass the invalid expression as-is, template instantiation may + // replace unexpected types/values with valid ones. The directives + // with this clause must not try to use these expressions in dependent + // contexts, but delay analysis until full instantiation. + if (!SizeExpr->isInstantiationDependent() && !IsValid) + SizeExpr = nullptr; } - DSAStack->setAssociatedLoops(SizeExprs.size()); return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, - SizeExprs); + SanitizedSizeExprs); } OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc, diff --git a/clang/test/OpenMP/tile_ast_print.cpp b/clang/test/OpenMP/tile_ast_print.cpp index afc8b34911e3..c4dff2c4be44 100644 --- a/clang/test/OpenMP/tile_ast_print.cpp +++ b/clang/test/OpenMP/tile_ast_print.cpp @@ -183,4 +183,21 @@ void tfoo7() { } +// PRINT-LABEL: void foo8( +// DUMP-LABEL: FunctionDecl {{.*}} foo8 +void foo8(int a) { + // PRINT: #pragma omp tile sizes(a) + // DUMP: OMPTileDirective + // DUMP-NEXT: OMPSizesClause + // DUMP-NEXT: ImplicitCastExpr + // DUMP-NEXT: DeclRefExpr {{.*}} 'a' + #pragma omp tile sizes(a) + // PRINT-NEXT: for (int i = 7; i < 19; i += 3) + // DUMP-NEXT: ForStmt + for (int i = 7; i < 19; i += 3) + // PRINT: body(i); + // DUMP: CallExpr + body(i); +} + #endif diff --git a/clang/test/OpenMP/tile_codegen.cpp b/clang/test/OpenMP/tile_codegen.cpp index 76cf2d8f1992..93a3a14133ab 100644 --- a/clang/test/OpenMP/tile_codegen.cpp +++ b/clang/test/OpenMP/tile_codegen.cpp @@ -83,6 +83,14 @@ extern "C" void tfoo7() { foo7(0, 42); } + +extern "C" void foo8(int a) { +#pragma omp tile sizes(a) + for (int i = 7; i < 17; i += 3) + body(i); +} + + #endif /* HEADER */ // CHECK1-LABEL: define {{[^@]+}}@body // CHECK1-SAME: (...) #[[ATTR0:[0-9]+]] { @@ -98,7 +106,7 @@ extern "C" void tfoo7() { // // // CHECK1-LABEL: define {{[^@]+}}@_ZN1SC1Ev -// CHECK1-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR2:[0-9]+]] comdat align 2 { +// 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 @@ -108,7 +116,7 @@ extern "C" void tfoo7() { // // // CHECK1-LABEL: define {{[^@]+}}@_ZN1SC2Ev -// CHECK1-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 { +// 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 @@ -885,7 +893,7 @@ extern "C" void tfoo7() { // // // CHECK1-LABEL: define {{[^@]+}}@foo6.omp_outlined -// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR5:[0-9]+]] { +// 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 @@ -1071,6 +1079,95 @@ extern "C" void tfoo7() { // CHECK1-NEXT: ret void // // +// CHECK1-LABEL: define {{[^@]+}}@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 +// CHECK1-NEXT: [[DOTFLOOR_0_IV_I:%.*]] = alloca i32, align 4 +// CHECK1-NEXT: [[DOTTILE_0_IV_I:%.*]] = alloca i32, align 4 +// CHECK1-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK1-NEXT: store i32 7, ptr [[I]], 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: [[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_END24:%.*]] +// 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_COND1:%.*]] +// CHECK1: for.cond1: +// 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: [[TMP4:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK1-NEXT: [[CMP2:%.*]] = icmp sle i32 [[TMP4]], 0 +// CHECK1-NEXT: br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +// CHECK1: cond.true: +// CHECK1-NEXT: br label [[COND_END:%.*]] +// CHECK1: cond.false: +// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK1-NEXT: br label [[COND_END]] +// CHECK1: cond.end: +// CHECK1-NEXT: [[COND:%.*]] = phi i32 [ 1, [[COND_TRUE]] ], [ [[TMP5]], [[COND_FALSE]] ] +// CHECK1-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], [[COND]] +// CHECK1-NEXT: [[CMP3:%.*]] = icmp slt i32 4, [[ADD]] +// CHECK1-NEXT: br i1 [[CMP3]], label [[COND_TRUE4:%.*]], label [[COND_FALSE5:%.*]] +// CHECK1: cond.true4: +// CHECK1-NEXT: br label [[COND_END12:%.*]] +// CHECK1: cond.false5: +// CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK1-NEXT: [[CMP6:%.*]] = icmp sle i32 [[TMP7]], 0 +// CHECK1-NEXT: br i1 [[CMP6]], label [[COND_TRUE7:%.*]], label [[COND_FALSE8:%.*]] +// CHECK1: cond.true7: +// CHECK1-NEXT: br label [[COND_END9:%.*]] +// CHECK1: cond.false8: +// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK1-NEXT: br label [[COND_END9]] +// CHECK1: cond.end9: +// CHECK1-NEXT: [[COND10:%.*]] = phi i32 [ 1, [[COND_TRUE7]] ], [ [[TMP8]], [[COND_FALSE8]] ] +// CHECK1-NEXT: [[ADD11:%.*]] = add nsw i32 [[TMP6]], [[COND10]] +// CHECK1-NEXT: br label [[COND_END12]] +// CHECK1: cond.end12: +// CHECK1-NEXT: [[COND13:%.*]] = phi i32 [ 4, [[COND_TRUE4]] ], [ [[ADD11]], [[COND_END9]] ] +// CHECK1-NEXT: [[CMP14:%.*]] = icmp slt i32 [[TMP2]], [[COND13]] +// CHECK1-NEXT: br i1 [[CMP14]], label [[FOR_BODY15:%.*]], label [[FOR_END:%.*]] +// CHECK1: for.body15: +// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK1-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP9]], 3 +// CHECK1-NEXT: [[ADD16:%.*]] = add nsw i32 7, [[MUL]] +// CHECK1-NEXT: store i32 [[ADD16]], ptr [[I]], align 4 +// CHECK1-NEXT: [[TMP10:%.*]] = load i32, ptr [[I]], align 4 +// CHECK1-NEXT: call void (...) @body(i32 noundef [[TMP10]]) +// CHECK1-NEXT: br label [[FOR_INC:%.*]] +// CHECK1: for.inc: +// CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK1-NEXT: [[INC:%.*]] = add nsw i32 [[TMP11]], 1 +// CHECK1-NEXT: store i32 [[INC]], ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK1-NEXT: br label [[FOR_COND1]], !llvm.loop [[LOOP23:![0-9]+]] +// CHECK1: for.end: +// CHECK1-NEXT: br label [[FOR_INC17:%.*]] +// CHECK1: for.inc17: +// CHECK1-NEXT: [[TMP12:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK1-NEXT: [[CMP18:%.*]] = icmp sle i32 [[TMP12]], 0 +// CHECK1-NEXT: br i1 [[CMP18]], label [[COND_TRUE19:%.*]], label [[COND_FALSE20:%.*]] +// CHECK1: cond.true19: +// CHECK1-NEXT: br label [[COND_END21:%.*]] +// CHECK1: cond.false20: +// CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK1-NEXT: br label [[COND_END21]] +// CHECK1: cond.end21: +// CHECK1-NEXT: [[COND22:%.*]] = phi i32 [ 1, [[COND_TRUE19]] ], [ [[TMP13]], [[COND_FALSE20]] ] +// CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK1-NEXT: [[ADD23:%.*]] = add nsw i32 [[TMP14]], [[COND22]] +// CHECK1-NEXT: store i32 [[ADD23]], ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK1-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP24:![0-9]+]] +// CHECK1: for.end24: +// CHECK1-NEXT: ret void +// +// // CHECK1-LABEL: define {{[^@]+}}@_GLOBAL__sub_I_tile_codegen.cpp // CHECK1-SAME: () #[[ATTR1]] section ".text.startup" { // CHECK1-NEXT: entry: @@ -1159,13 +1256,13 @@ extern "C" void tfoo7() { // // // CHECK2-LABEL: define {{[^@]+}}@body -// CHECK2-SAME: (...) #[[ATTR2:[0-9]+]] { +// 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:%.*]]) #[[ATTR2]] { +// 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 @@ -1255,7 +1352,7 @@ extern "C" void tfoo7() { // // // CHECK2-LABEL: define {{[^@]+}}@foo2 -// CHECK2-SAME: (i32 noundef [[START:%.*]], i32 noundef [[END:%.*]], i32 noundef [[STEP:%.*]]) #[[ATTR2]] { +// 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 @@ -1368,7 +1465,7 @@ extern "C" void tfoo7() { // // // CHECK2-LABEL: define {{[^@]+}}@foo3 -// CHECK2-SAME: () #[[ATTR2]] { +// CHECK2-SAME: () #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 // CHECK2-NEXT: [[TMP:%.*]] = alloca i32, align 4 @@ -1510,7 +1607,7 @@ extern "C" void tfoo7() { // // // CHECK2-LABEL: define {{[^@]+}}@foo4 -// CHECK2-SAME: () #[[ATTR2]] { +// CHECK2-SAME: () #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 // CHECK2-NEXT: [[TMP:%.*]] = alloca i32, align 4 @@ -1663,7 +1760,7 @@ extern "C" void tfoo7() { // // // CHECK2-LABEL: define {{[^@]+}}@foo5 -// CHECK2-SAME: () #[[ATTR2]] { +// CHECK2-SAME: () #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[DOTOMP_IV:%.*]] = alloca i64, align 8 // CHECK2-NEXT: [[TMP:%.*]] = alloca i32, align 4 @@ -1872,14 +1969,14 @@ extern "C" void tfoo7() { // // // CHECK2-LABEL: define {{[^@]+}}@foo6 -// CHECK2-SAME: () #[[ATTR2]] { +// 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_:%.*]]) #[[ATTR5:[0-9]+]] { +// 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 @@ -1974,15 +2071,104 @@ extern "C" void tfoo7() { // CHECK2-NEXT: ret void // // +// CHECK2-LABEL: define {{[^@]+}}@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 +// CHECK2-NEXT: [[DOTFLOOR_0_IV_I:%.*]] = alloca i32, align 4 +// CHECK2-NEXT: [[DOTTILE_0_IV_I:%.*]] = alloca i32, align 4 +// CHECK2-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK2-NEXT: store i32 7, ptr [[I]], 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: [[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_END24:%.*]] +// 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_COND1:%.*]] +// CHECK2: for.cond1: +// 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: [[TMP4:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK2-NEXT: [[CMP2:%.*]] = icmp sle i32 [[TMP4]], 0 +// CHECK2-NEXT: br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +// CHECK2: cond.true: +// CHECK2-NEXT: br label [[COND_END:%.*]] +// CHECK2: cond.false: +// CHECK2-NEXT: [[TMP5:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK2-NEXT: br label [[COND_END]] +// CHECK2: cond.end: +// CHECK2-NEXT: [[COND:%.*]] = phi i32 [ 1, [[COND_TRUE]] ], [ [[TMP5]], [[COND_FALSE]] ] +// CHECK2-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], [[COND]] +// CHECK2-NEXT: [[CMP3:%.*]] = icmp slt i32 4, [[ADD]] +// CHECK2-NEXT: br i1 [[CMP3]], label [[COND_TRUE4:%.*]], label [[COND_FALSE5:%.*]] +// CHECK2: cond.true4: +// CHECK2-NEXT: br label [[COND_END12:%.*]] +// CHECK2: cond.false5: +// CHECK2-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK2-NEXT: [[TMP7:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK2-NEXT: [[CMP6:%.*]] = icmp sle i32 [[TMP7]], 0 +// CHECK2-NEXT: br i1 [[CMP6]], label [[COND_TRUE7:%.*]], label [[COND_FALSE8:%.*]] +// CHECK2: cond.true7: +// CHECK2-NEXT: br label [[COND_END9:%.*]] +// CHECK2: cond.false8: +// CHECK2-NEXT: [[TMP8:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK2-NEXT: br label [[COND_END9]] +// CHECK2: cond.end9: +// CHECK2-NEXT: [[COND10:%.*]] = phi i32 [ 1, [[COND_TRUE7]] ], [ [[TMP8]], [[COND_FALSE8]] ] +// CHECK2-NEXT: [[ADD11:%.*]] = add nsw i32 [[TMP6]], [[COND10]] +// CHECK2-NEXT: br label [[COND_END12]] +// CHECK2: cond.end12: +// CHECK2-NEXT: [[COND13:%.*]] = phi i32 [ 4, [[COND_TRUE4]] ], [ [[ADD11]], [[COND_END9]] ] +// CHECK2-NEXT: [[CMP14:%.*]] = icmp slt i32 [[TMP2]], [[COND13]] +// CHECK2-NEXT: br i1 [[CMP14]], label [[FOR_BODY15:%.*]], label [[FOR_END:%.*]] +// CHECK2: for.body15: +// CHECK2-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK2-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP9]], 3 +// CHECK2-NEXT: [[ADD16:%.*]] = add nsw i32 7, [[MUL]] +// CHECK2-NEXT: store i32 [[ADD16]], ptr [[I]], align 4 +// CHECK2-NEXT: [[TMP10:%.*]] = load i32, ptr [[I]], align 4 +// CHECK2-NEXT: call void (...) @body(i32 noundef [[TMP10]]) +// CHECK2-NEXT: br label [[FOR_INC:%.*]] +// CHECK2: for.inc: +// 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: for.end: +// CHECK2-NEXT: br label [[FOR_INC17:%.*]] +// CHECK2: for.inc17: +// CHECK2-NEXT: [[TMP12:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK2-NEXT: [[CMP18:%.*]] = icmp sle i32 [[TMP12]], 0 +// CHECK2-NEXT: br i1 [[CMP18]], label [[COND_TRUE19:%.*]], label [[COND_FALSE20:%.*]] +// CHECK2: cond.true19: +// CHECK2-NEXT: br label [[COND_END21:%.*]] +// CHECK2: cond.false20: +// CHECK2-NEXT: [[TMP13:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK2-NEXT: br label [[COND_END21]] +// CHECK2: cond.end21: +// CHECK2-NEXT: [[COND22:%.*]] = phi i32 [ 1, [[COND_TRUE19]] ], [ [[TMP13]], [[COND_FALSE20]] ] +// 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: for.end24: +// CHECK2-NEXT: ret void +// +// // CHECK2-LABEL: define {{[^@]+}}@tfoo7 -// CHECK2-SAME: () #[[ATTR2]] { +// 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:%.*]]) #[[ATTR2]] comdat { +// 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 @@ -2053,14 +2239,14 @@ extern "C" void tfoo7() { // CHECK2-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP16]], 1 // CHECK2-NEXT: store i32 [[INC]], ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND6]], !llvm.loop [[LOOP21:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND6]], !llvm.loop [[LOOP23:![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: store i32 [[ADD16]], 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.end17: // CHECK2-NEXT: ret void // diff --git a/clang/test/OpenMP/tile_messages.cpp b/clang/test/OpenMP/tile_messages.cpp index adeef617b75c..5268dfe97e0c 100644 --- a/clang/test/OpenMP/tile_messages.cpp +++ b/clang/test/OpenMP/tile_messages.cpp @@ -43,13 +43,7 @@ void func() { // expected-error@+1 {{argument to 'sizes' clause must be a strictly positive integer value}} #pragma omp tile sizes(0) - ; - - // expected-error@+4 {{expression is not an integral constant expression}} - // expected-note@+3 {{read of non-const variable 'a' is not allowed in a constant expression}} - // expected-note@+1 {{declared here}} - int a; - #pragma omp tile sizes(a) + for (int i = 0; i < 7; ++i) ; // expected-warning@+2 {{extra tokens at the end of '#pragma omp tile' are ignored}} @@ -124,4 +118,46 @@ void func() { #pragma omp tile sizes(5) for (int i = 0; i/3<7; ++i) ; + + // expected-error@+2 {{expression must have integral or unscoped enumeration type, not 'struct S'}} + struct S{} s; + #pragma omp tile sizes(s) + for (int i = 0; i < 7; ++i) + ; +} + + +template +static void templated_func() { + // In a template context, but expression itself not instantiation-dependent + + // expected-error@+1 {{argument to 'sizes' clause must be a strictly positive integer value}} + #pragma omp tile sizes(0) + for (int i = 0; i < 7; ++i) + ; +} + +template +static void templated_func_value_dependent() { + // expected-error@+1 {{argument to 'sizes' clause must be a strictly positive integer value}} + #pragma omp tile sizes(S) + for (int i = 0; i < 7; ++i) + ; +} + +template +static void templated_func_type_dependent() { + constexpr T s = 0; + // expected-error@+1 {{argument to 'sizes' clause must be a strictly positive integer value}} + #pragma omp tile sizes(s) + for (int i = 0; i < 7; ++i) + ; +} + +void template_inst() { + templated_func(); + // expected-note@+1 {{in instantiation of function template specialization 'templated_func_value_dependent<0>' requested here}} + templated_func_value_dependent<0>(); + // expected-note@+1 {{in instantiation of function template specialization 'templated_func_type_dependent' requested here}} + templated_func_type_dependent(); } diff --git a/openmp/runtime/test/transform/tile/intfor.c b/openmp/runtime/test/transform/tile/intfor.c new file mode 100644 index 000000000000..4a930eab6730 --- /dev/null +++ b/openmp/runtime/test/transform/tile/intfor.c @@ -0,0 +1,191 @@ +// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include + +// TODO: The OpenMP specification explicitly does not define when and how often +// expressions in the clause are evaluated. Currently Clang evaluates it again +// whenever needed, but function calls in clauses are not common. A better +// implementation would evaluate it just once and reuse the result. +static int tilesize(int i) { + printf("tilesize(%d)\n", i); + return 3; +} + +int main() { + printf("do\n"); +#pragma omp tile sizes(tilesize(1), tilesize(2)) + for (int i = 7; i < 19; i += 3) + for (int j = 7; j < 20; j += 3) + printf("i=%d j=%d\n", i, j); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=7 j=7 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=7 j=10 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=7 j=13 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=10 j=7 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=10 j=10 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=10 j=13 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=13 j=7 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=13 j=10 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=13 j=13 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=7 j=16 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=7 j=19 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=10 j=16 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=10 j=19 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=13 j=16 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=13 j=19 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=16 j=7 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=16 j=10 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=16 j=13 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=16 j=16 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: i=16 j=19 +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(2) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: tilesize(1) +// CHECK-NEXT: done \ No newline at end of file diff --git a/openmp/runtime/test/transform/tile/negtile_intfor.c b/openmp/runtime/test/transform/tile/negtile_intfor.c new file mode 100644 index 000000000000..8784d9e9fa61 --- /dev/null +++ b/openmp/runtime/test/transform/tile/negtile_intfor.c @@ -0,0 +1,44 @@ +// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include + +int tilesize = -2; + +int main() { + printf("do\n"); +#pragma omp tile sizes(tilesize, tilesize) + for (int i = 7; i < 19; i += 3) + for (int j = 7; j < 20; j += 3) + printf("i=%d j=%d\n", i, j); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: i=7 j=7 +// CHECK-NEXT: i=7 j=10 +// CHECK-NEXT: i=7 j=13 +// CHECK-NEXT: i=7 j=16 +// CHECK-NEXT: i=7 j=19 +// CHECK-NEXT: i=10 j=7 +// CHECK-NEXT: i=10 j=10 +// CHECK-NEXT: i=10 j=13 +// CHECK-NEXT: i=10 j=16 +// CHECK-NEXT: i=10 j=19 +// CHECK-NEXT: i=13 j=7 +// CHECK-NEXT: i=13 j=10 +// CHECK-NEXT: i=13 j=13 +// CHECK-NEXT: i=13 j=16 +// CHECK-NEXT: i=13 j=19 +// CHECK-NEXT: i=16 j=7 +// CHECK-NEXT: i=16 j=10 +// CHECK-NEXT: i=16 j=13 +// CHECK-NEXT: i=16 j=16 +// CHECK-NEXT: i=16 j=19 +// CHECK-NEXT: done diff --git a/openmp/runtime/test/transform/tile/parallel-wsloop-collapse-intfor.cpp b/openmp/runtime/test/transform/tile/parallel-wsloop-collapse-intfor.cpp new file mode 100644 index 000000000000..f4c2af610768 --- /dev/null +++ b/openmp/runtime/test/transform/tile/parallel-wsloop-collapse-intfor.cpp @@ -0,0 +1,100 @@ +// 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(3) num_threads(1) + for (int i = 0; i < 3; ++i) +#pragma omp tile sizes(3, 3) + for (int j = 0; j < 4; ++j) + for (int k = 0; k < 5; ++k) + printf("i=%d j=%d k=%d\n", i, j, k); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do + +// Full tile +// CHECK-NEXT: i=0 j=0 k=0 +// CHECK-NEXT: i=0 j=0 k=1 +// CHECK-NEXT: i=0 j=0 k=2 +// CHECK-NEXT: i=0 j=1 k=0 +// CHECK-NEXT: i=0 j=1 k=1 +// CHECK-NEXT: i=0 j=1 k=2 +// CHECK-NEXT: i=0 j=2 k=0 +// CHECK-NEXT: i=0 j=2 k=1 +// CHECK-NEXT: i=0 j=2 k=2 + +// Partial tile +// CHECK-NEXT: i=0 j=0 k=3 +// CHECK-NEXT: i=0 j=0 k=4 +// CHECK-NEXT: i=0 j=1 k=3 +// CHECK-NEXT: i=0 j=1 k=4 +// CHECK-NEXT: i=0 j=2 k=3 +// CHECK-NEXT: i=0 j=2 k=4 + +// Partial tile +// CHECK-NEXT: i=0 j=3 k=0 +// CHECK-NEXT: i=0 j=3 k=1 +// CHECK-NEXT: i=0 j=3 k=2 + +// Partial tile +// CHECK-NEXT: i=0 j=3 k=3 +// CHECK-NEXT: i=0 j=3 k=4 + +// Full tile +// CHECK-NEXT: i=1 j=0 k=0 +// CHECK-NEXT: i=1 j=0 k=1 +// CHECK-NEXT: i=1 j=0 k=2 +// CHECK-NEXT: i=1 j=1 k=0 +// CHECK-NEXT: i=1 j=1 k=1 +// CHECK-NEXT: i=1 j=1 k=2 +// CHECK-NEXT: i=1 j=2 k=0 +// CHECK-NEXT: i=1 j=2 k=1 +// CHECK-NEXT: i=1 j=2 k=2 + +// Partial tiles +// CHECK-NEXT: i=1 j=0 k=3 +// CHECK-NEXT: i=1 j=0 k=4 +// CHECK-NEXT: i=1 j=1 k=3 +// CHECK-NEXT: i=1 j=1 k=4 +// CHECK-NEXT: i=1 j=2 k=3 +// CHECK-NEXT: i=1 j=2 k=4 +// CHECK-NEXT: i=1 j=3 k=0 +// CHECK-NEXT: i=1 j=3 k=1 +// CHECK-NEXT: i=1 j=3 k=2 +// CHECK-NEXT: i=1 j=3 k=3 +// CHECK-NEXT: i=1 j=3 k=4 + +// Full tile +// CHECK-NEXT: i=2 j=0 k=0 +// CHECK-NEXT: i=2 j=0 k=1 +// CHECK-NEXT: i=2 j=0 k=2 +// CHECK-NEXT: i=2 j=1 k=0 +// CHECK-NEXT: i=2 j=1 k=1 +// CHECK-NEXT: i=2 j=1 k=2 +// CHECK-NEXT: i=2 j=2 k=0 +// CHECK-NEXT: i=2 j=2 k=1 +// CHECK-NEXT: i=2 j=2 k=2 + +// Partial tiles +// CHECK-NEXT: i=2 j=0 k=3 +// CHECK-NEXT: i=2 j=0 k=4 +// CHECK-NEXT: i=2 j=1 k=3 +// CHECK-NEXT: i=2 j=1 k=4 +// CHECK-NEXT: i=2 j=2 k=3 +// CHECK-NEXT: i=2 j=2 k=4 +// CHECK-NEXT: i=2 j=3 k=0 +// CHECK-NEXT: i=2 j=3 k=1 +// CHECK-NEXT: i=2 j=3 k=2 +// CHECK-NEXT: i=2 j=3 k=3 +// CHECK-NEXT: i=2 j=3 k=4 +// CHECK-NEXT: done -- GitLab From 69e13125af2511abd59499272c88fcb6f19b9300 Mon Sep 17 00:00:00 2001 From: chuongg3 Date: Mon, 13 May 2024 15:16:11 +0100 Subject: [PATCH 068/578] [AArch64][GlobalISel] Select G_ICMP instruction through TableGen (#89932) G_ICMP NE => XOR(G_ICMP EQ, -1) moved to Legalizer to allow for combines if they come up in following passes. --- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 46 +++ .../GISel/AArch64InstructionSelector.cpp | 174 +-------- .../AArch64/GISel/AArch64LegalizerInfo.cpp | 47 ++- .../AArch64/GISel/AArch64LegalizerInfo.h | 2 + .../CodeGen/AArch64/GlobalISel/select-cmp.mir | 4 +- .../AArch64/GlobalISel/select-vector-icmp.mir | 338 ------------------ 6 files changed, 86 insertions(+), 525 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 17d96370c04a..bb32280fe51f 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -5403,6 +5403,52 @@ def : Pat<(AArch64bsp (v4i32 V128:$Rd), V128:$Rn, V128:$Rm), def : Pat<(AArch64bsp (v2i64 V128:$Rd), V128:$Rn, V128:$Rm), (BSPv16i8 V128:$Rd, V128:$Rn, V128:$Rm)>; +// The following SetCC patterns are used for GlobalISel only +multiclass SelectSetCC { + def : Pat<(v8i8 (InFrag (v8i8 V64:$Rn), (v8i8 V64:$Rm))), + (v8i8 (!cast(INST # v8i8) (v8i8 V64:$Rn), (v8i8 V64:$Rm)))>; + def : Pat<(v16i8 (InFrag (v16i8 V128:$Rn), (v16i8 V128:$Rm))), + (v16i8 (!cast(INST # v16i8) (v16i8 V128:$Rn), (v16i8 V128:$Rm)))>; + def : Pat<(v4i16 (InFrag (v4i16 V64:$Rn), (v4i16 V64:$Rm))), + (v4i16 (!cast(INST # v4i16) (v4i16 V64:$Rn), (v4i16 V64:$Rm)))>; + def : Pat<(v8i16 (InFrag (v8i16 V128:$Rn), (v8i16 V128:$Rm))), + (v8i16 (!cast(INST # v8i16) (v8i16 V128:$Rn), (v8i16 V128:$Rm)))>; + def : Pat<(v2i32 (InFrag (v2i32 V64:$Rn), (v2i32 V64:$Rm))), + (v2i32 (!cast(INST # v2i32) (v2i32 V64:$Rn), (v2i32 V64:$Rm)))>; + def : Pat<(v4i32 (InFrag (v4i32 V128:$Rn), (v4i32 V128:$Rm))), + (v4i32 (!cast(INST # v4i32) (v4i32 V128:$Rn), (v4i32 V128:$Rm)))>; + def : Pat<(v2i64 (InFrag (v2i64 V128:$Rn), (v2i64 V128:$Rm))), + (v2i64 (!cast(INST # v2i64) (v2i64 V128:$Rn), (v2i64 V128:$Rm)))>; +} + +defm : SelectSetCC; +defm : SelectSetCC; +defm : SelectSetCC; +defm : SelectSetCC; +defm : SelectSetCC; + +multiclass SelectSetCCSwapOperands { + def : Pat<(v8i8 (InFrag (v8i8 V64:$Rn), (v8i8 V64:$Rm))), + (v8i8 (!cast(INST # v8i8) (v8i8 V64:$Rm), (v8i8 V64:$Rn)))>; + def : Pat<(v16i8 (InFrag (v16i8 V128:$Rn), (v16i8 V128:$Rm))), + (v16i8 (!cast(INST # v16i8) (v16i8 V128:$Rm), (v16i8 V128:$Rn)))>; + def : Pat<(v4i16 (InFrag (v4i16 V64:$Rn), (v4i16 V64:$Rm))), + (v4i16 (!cast(INST # v4i16) (v4i16 V64:$Rm), (v4i16 V64:$Rn)))>; + def : Pat<(v8i16 (InFrag (v8i16 V128:$Rn), (v8i16 V128:$Rm))), + (v8i16 (!cast(INST # v8i16) (v8i16 V128:$Rm), (v8i16 V128:$Rn)))>; + def : Pat<(v2i32 (InFrag (v2i32 V64:$Rn), (v2i32 V64:$Rm))), + (v2i32 (!cast(INST # v2i32) (v2i32 V64:$Rm), (v2i32 V64:$Rn)))>; + def : Pat<(v4i32 (InFrag (v4i32 V128:$Rn), (v4i32 V128:$Rm))), + (v4i32 (!cast(INST # v4i32) (v4i32 V128:$Rm), (v4i32 V128:$Rn)))>; + def : Pat<(v2i64 (InFrag (v2i64 V128:$Rn), (v2i64 V128:$Rm))), + (v2i64 (!cast(INST # v2i64) (v2i64 V128:$Rm), (v2i64 V128:$Rn)))>; +} + +defm : SelectSetCCSwapOperands; +defm : SelectSetCCSwapOperands; +defm : SelectSetCCSwapOperands; +defm : SelectSetCCSwapOperands; + let Predicates = [HasNEON] in { def : InstAlias<"mov{\t$dst.16b, $src.16b|.16b\t$dst, $src}", (ORRv16i8 V128:$dst, V128:$src, V128:$src), 1>; diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index 61f5bc2464ee..1b65ae7b4782 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -221,7 +221,6 @@ private: bool selectIntrinsicWithSideEffects(MachineInstr &I, MachineRegisterInfo &MRI); bool selectIntrinsic(MachineInstr &I, MachineRegisterInfo &MRI); - bool selectVectorICmp(MachineInstr &I, MachineRegisterInfo &MRI); bool selectJumpTable(MachineInstr &I, MachineRegisterInfo &MRI); bool selectBrJT(MachineInstr &I, MachineRegisterInfo &MRI); bool selectTLSGlobalValue(MachineInstr &I, MachineRegisterInfo &MRI); @@ -3403,7 +3402,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { } case TargetOpcode::G_ICMP: { if (Ty.isVector()) - return selectVectorICmp(I, MRI); + return false; if (Ty != LLT::scalar(32)) { LLVM_DEBUG(dbgs() << "G_ICMP result has type: " << Ty @@ -3652,177 +3651,6 @@ bool AArch64InstructionSelector::selectTLSGlobalValue( return true; } -bool AArch64InstructionSelector::selectVectorICmp( - MachineInstr &I, MachineRegisterInfo &MRI) { - Register DstReg = I.getOperand(0).getReg(); - LLT DstTy = MRI.getType(DstReg); - Register SrcReg = I.getOperand(2).getReg(); - Register Src2Reg = I.getOperand(3).getReg(); - LLT SrcTy = MRI.getType(SrcReg); - - unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits(); - unsigned NumElts = DstTy.getNumElements(); - - // First index is element size, 0 == 8b, 1 == 16b, 2 == 32b, 3 == 64b - // Second index is num elts, 0 == v2, 1 == v4, 2 == v8, 3 == v16 - // Third index is cc opcode: - // 0 == eq - // 1 == ugt - // 2 == uge - // 3 == ult - // 4 == ule - // 5 == sgt - // 6 == sge - // 7 == slt - // 8 == sle - // ne is done by negating 'eq' result. - - // This table below assumes that for some comparisons the operands will be - // commuted. - // ult op == commute + ugt op - // ule op == commute + uge op - // slt op == commute + sgt op - // sle op == commute + sge op - unsigned PredIdx = 0; - bool SwapOperands = false; - CmpInst::Predicate Pred = (CmpInst::Predicate)I.getOperand(1).getPredicate(); - switch (Pred) { - case CmpInst::ICMP_NE: - case CmpInst::ICMP_EQ: - PredIdx = 0; - break; - case CmpInst::ICMP_UGT: - PredIdx = 1; - break; - case CmpInst::ICMP_UGE: - PredIdx = 2; - break; - case CmpInst::ICMP_ULT: - PredIdx = 3; - SwapOperands = true; - break; - case CmpInst::ICMP_ULE: - PredIdx = 4; - SwapOperands = true; - break; - case CmpInst::ICMP_SGT: - PredIdx = 5; - break; - case CmpInst::ICMP_SGE: - PredIdx = 6; - break; - case CmpInst::ICMP_SLT: - PredIdx = 7; - SwapOperands = true; - break; - case CmpInst::ICMP_SLE: - PredIdx = 8; - SwapOperands = true; - break; - default: - llvm_unreachable("Unhandled icmp predicate"); - return false; - } - - // This table obviously should be tablegen'd when we have our GISel native - // tablegen selector. - - static const unsigned OpcTable[4][4][9] = { - { - {0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */}, - {0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */}, - {AArch64::CMEQv8i8, AArch64::CMHIv8i8, AArch64::CMHSv8i8, - AArch64::CMHIv8i8, AArch64::CMHSv8i8, AArch64::CMGTv8i8, - AArch64::CMGEv8i8, AArch64::CMGTv8i8, AArch64::CMGEv8i8}, - {AArch64::CMEQv16i8, AArch64::CMHIv16i8, AArch64::CMHSv16i8, - AArch64::CMHIv16i8, AArch64::CMHSv16i8, AArch64::CMGTv16i8, - AArch64::CMGEv16i8, AArch64::CMGTv16i8, AArch64::CMGEv16i8} - }, - { - {0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */}, - {AArch64::CMEQv4i16, AArch64::CMHIv4i16, AArch64::CMHSv4i16, - AArch64::CMHIv4i16, AArch64::CMHSv4i16, AArch64::CMGTv4i16, - AArch64::CMGEv4i16, AArch64::CMGTv4i16, AArch64::CMGEv4i16}, - {AArch64::CMEQv8i16, AArch64::CMHIv8i16, AArch64::CMHSv8i16, - AArch64::CMHIv8i16, AArch64::CMHSv8i16, AArch64::CMGTv8i16, - AArch64::CMGEv8i16, AArch64::CMGTv8i16, AArch64::CMGEv8i16}, - {0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */} - }, - { - {AArch64::CMEQv2i32, AArch64::CMHIv2i32, AArch64::CMHSv2i32, - AArch64::CMHIv2i32, AArch64::CMHSv2i32, AArch64::CMGTv2i32, - AArch64::CMGEv2i32, AArch64::CMGTv2i32, AArch64::CMGEv2i32}, - {AArch64::CMEQv4i32, AArch64::CMHIv4i32, AArch64::CMHSv4i32, - AArch64::CMHIv4i32, AArch64::CMHSv4i32, AArch64::CMGTv4i32, - AArch64::CMGEv4i32, AArch64::CMGTv4i32, AArch64::CMGEv4i32}, - {0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */}, - {0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */} - }, - { - {AArch64::CMEQv2i64, AArch64::CMHIv2i64, AArch64::CMHSv2i64, - AArch64::CMHIv2i64, AArch64::CMHSv2i64, AArch64::CMGTv2i64, - AArch64::CMGEv2i64, AArch64::CMGTv2i64, AArch64::CMGEv2i64}, - {0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */}, - {0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */}, - {0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, 0 /* invalid */, - 0 /* invalid */} - }, - }; - unsigned EltIdx = Log2_32(SrcEltSize / 8); - unsigned NumEltsIdx = Log2_32(NumElts / 2); - unsigned Opc = OpcTable[EltIdx][NumEltsIdx][PredIdx]; - if (!Opc) { - LLVM_DEBUG(dbgs() << "Could not map G_ICMP to cmp opcode"); - return false; - } - - const RegisterBank &VecRB = *RBI.getRegBank(SrcReg, MRI, TRI); - const TargetRegisterClass *SrcRC = - getRegClassForTypeOnBank(SrcTy, VecRB, true); - if (!SrcRC) { - LLVM_DEBUG(dbgs() << "Could not determine source register class.\n"); - return false; - } - - unsigned NotOpc = Pred == ICmpInst::ICMP_NE ? AArch64::NOTv8i8 : 0; - if (SrcTy.getSizeInBits() == 128) - NotOpc = NotOpc ? AArch64::NOTv16i8 : 0; - - if (SwapOperands) - std::swap(SrcReg, Src2Reg); - - auto Cmp = MIB.buildInstr(Opc, {SrcRC}, {SrcReg, Src2Reg}); - constrainSelectedInstRegOperands(*Cmp, TII, TRI, RBI); - - // Invert if we had a 'ne' cc. - if (NotOpc) { - Cmp = MIB.buildInstr(NotOpc, {DstReg}, {Cmp}); - constrainSelectedInstRegOperands(*Cmp, TII, TRI, RBI); - } else { - MIB.buildCopy(DstReg, Cmp.getReg(0)); - } - RBI.constrainGenericRegister(DstReg, *SrcRC, MRI); - I.eraseFromParent(); - return true; -} - MachineInstr *AArch64InstructionSelector::emitScalarToVector( unsigned EltSize, const TargetRegisterClass *DstRC, Register Scalar, MachineIRBuilder &MIRBuilder) const { diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp index d4aac94d24f1..b8274f0f872c 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -495,17 +495,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) // FIXME: fix moreElementsToNextPow2 getActionDefinitionsBuilder(G_ICMP) - .legalFor({{s32, s32}, - {s32, s64}, - {s32, p0}, - {v4s32, v4s32}, - {v2s32, v2s32}, - {v2s64, v2s64}, - {v2s64, v2p0}, - {v4s16, v4s16}, - {v8s16, v8s16}, - {v8s8, v8s8}, - {v16s8, v16s8}}) + .legalFor({{s32, s32}, {s32, s64}, {s32, p0}}) .widenScalarOrEltToNextPow2(1) .clampScalar(1, s32, s64) .clampScalar(0, s32, s32) @@ -527,7 +517,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) .clampNumElements(1, v8s8, v16s8) .clampNumElements(1, v4s16, v8s16) .clampNumElements(1, v2s32, v4s32) - .clampNumElements(1, v2s64, v2s64); + .clampNumElements(1, v2s64, v2s64) + .customIf(isVector(0)); getActionDefinitionsBuilder(G_FCMP) .legalFor({{s32, MinFPScalar}, @@ -1266,6 +1257,8 @@ bool AArch64LegalizerInfo::legalizeCustom( return legalizePrefetch(MI, Helper); case TargetOpcode::G_ABS: return Helper.lowerAbsToCNeg(MI); + case TargetOpcode::G_ICMP: + return legalizeICMP(MI, MRI, MIRBuilder); } llvm_unreachable("expected switch to return"); @@ -1324,6 +1317,36 @@ bool AArch64LegalizerInfo::legalizeFunnelShift(MachineInstr &MI, return true; } +bool AArch64LegalizerInfo::legalizeICMP(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const { + Register DstReg = MI.getOperand(0).getReg(); + Register SrcReg1 = MI.getOperand(2).getReg(); + Register SrcReg2 = MI.getOperand(3).getReg(); + LLT DstTy = MRI.getType(DstReg); + LLT SrcTy = MRI.getType(SrcReg1); + + // Check the vector types are legal + if (DstTy.getScalarSizeInBits() != SrcTy.getScalarSizeInBits() || + DstTy.getNumElements() != SrcTy.getNumElements() || + (DstTy.getSizeInBits() != 64 && DstTy.getSizeInBits() != 128)) + return false; + + // Lowers G_ICMP NE => G_ICMP EQ to allow better pattern matching for + // following passes + CmpInst::Predicate Pred = (CmpInst::Predicate)MI.getOperand(1).getPredicate(); + if (Pred != CmpInst::ICMP_NE) + return true; + Register CmpReg = + MIRBuilder + .buildICmp(CmpInst::ICMP_EQ, MRI.getType(DstReg), SrcReg1, SrcReg2) + .getReg(0); + MIRBuilder.buildNot(DstReg, CmpReg); + + MI.eraseFromParent(); + return true; +} + bool AArch64LegalizerInfo::legalizeRotate(MachineInstr &MI, MachineRegisterInfo &MRI, LegalizerHelper &Helper) const { diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h index b69d9b015bd2..00d85a36e4b2 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h +++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h @@ -50,6 +50,8 @@ private: LegalizerHelper &Helper) const; bool legalizeRotate(MachineInstr &MI, MachineRegisterInfo &MRI, LegalizerHelper &Helper) const; + bool legalizeICMP(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const; bool legalizeFunnelShift(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder, GISelChangeObserver &Observer, diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-cmp.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-cmp.mir index 4151f7ecb3ea..df4e7ddaac8b 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-cmp.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-cmp.mir @@ -361,8 +361,8 @@ body: | ; CHECK-NEXT: %cmp_lhs:fpr128 = COPY $q0 ; CHECK-NEXT: %cmp_rhs:fpr128 = COPY $q1 ; CHECK-NEXT: %add_lhs:fpr128 = COPY $q2 - ; CHECK-NEXT: [[CMEQv4i32_:%[0-9]+]]:fpr128 = CMEQv4i32 %cmp_lhs, %cmp_rhs - ; CHECK-NEXT: %add:fpr128 = ADDv4i32 %add_lhs, [[CMEQv4i32_]] + ; CHECK-NEXT: %cmp:fpr128 = CMEQv4i32 %cmp_lhs, %cmp_rhs + ; CHECK-NEXT: %add:fpr128 = ADDv4i32 %add_lhs, %cmp ; CHECK-NEXT: $q0 = COPY %add ; CHECK-NEXT: RET_ReallyLR implicit $q0 %cmp_lhs:fpr(<4 x s32>) = COPY $q0 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-vector-icmp.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-vector-icmp.mir index 21e84ecaed32..7884d9e1b1d7 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-vector-icmp.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-vector-icmp.mir @@ -46,46 +46,6 @@ ret <8 x i1> %cmp } - define <2 x i1> @test_v2i64_ne(<2 x i64> %v1, <2 x i64> %v2) { - %cmp = icmp ne <2 x i64> %v1, %v2 - ret <2 x i1> %cmp - } - - define <4 x i1> @test_v4i32_ne(<4 x i32> %v1, <4 x i32> %v2) { - %cmp = icmp ne <4 x i32> %v1, %v2 - ret <4 x i1> %cmp - } - - define <2 x i1> @test_v2i32_ne(<2 x i32> %v1, <2 x i32> %v2) { - %cmp = icmp ne <2 x i32> %v1, %v2 - ret <2 x i1> %cmp - } - - define <2 x i1> @test_v2i16_ne(<2 x i16> %v1, <2 x i16> %v2) { - %cmp = icmp ne <2 x i16> %v1, %v2 - ret <2 x i1> %cmp - } - - define <8 x i1> @test_v8i16_ne(<8 x i16> %v1, <8 x i16> %v2) { - %cmp = icmp ne <8 x i16> %v1, %v2 - ret <8 x i1> %cmp - } - - define <4 x i1> @test_v4i16_ne(<4 x i16> %v1, <4 x i16> %v2) { - %cmp = icmp ne <4 x i16> %v1, %v2 - ret <4 x i1> %cmp - } - - define <16 x i1> @test_v16i8_ne(<16 x i8> %v1, <16 x i8> %v2) { - %cmp = icmp ne <16 x i8> %v1, %v2 - ret <16 x i1> %cmp - } - - define <8 x i1> @test_v8i8_ne(<8 x i8> %v1, <8 x i8> %v2) { - %cmp = icmp ne <8 x i8> %v1, %v2 - ret <8 x i1> %cmp - } - define <2 x i1> @test_v2i64_ugt(<2 x i64> %v1, <2 x i64> %v2) { %cmp = icmp ugt <2 x i64> %v1, %v2 ret <2 x i1> %cmp @@ -696,304 +656,6 @@ body: | $d0 = COPY %3(<8 x s8>) RET_ReallyLR implicit $d0 -... ---- -name: test_v2i64_ne -alignment: 4 -legalized: true -regBankSelected: true -tracksRegLiveness: true -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: _ } - - { id: 3, class: fpr } - - { id: 4, class: fpr } -machineFunctionInfo: {} -body: | - bb.1 (%ir-block.0): - liveins: $q0, $q1 - - ; CHECK-LABEL: name: test_v2i64_ne - ; CHECK: liveins: $q0, $q1 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr128 = COPY $q0 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr128 = COPY $q1 - ; CHECK-NEXT: [[CMEQv2i64_:%[0-9]+]]:fpr128 = CMEQv2i64 [[COPY]], [[COPY1]] - ; CHECK-NEXT: [[NOTv16i8_:%[0-9]+]]:fpr128 = NOTv16i8 [[CMEQv2i64_]] - ; CHECK-NEXT: [[XTNv2i32_:%[0-9]+]]:fpr64 = XTNv2i32 [[NOTv16i8_]] - ; CHECK-NEXT: $d0 = COPY [[XTNv2i32_]] - ; CHECK-NEXT: RET_ReallyLR implicit $d0 - %0:fpr(<2 x s64>) = COPY $q0 - %1:fpr(<2 x s64>) = COPY $q1 - %4:fpr(<2 x s64>) = G_ICMP intpred(ne), %0(<2 x s64>), %1 - %3:fpr(<2 x s32>) = G_TRUNC %4(<2 x s64>) - $d0 = COPY %3(<2 x s32>) - RET_ReallyLR implicit $d0 - -... ---- -name: test_v4i32_ne -alignment: 4 -legalized: true -regBankSelected: true -tracksRegLiveness: true -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: _ } - - { id: 3, class: fpr } - - { id: 4, class: fpr } -machineFunctionInfo: {} -body: | - bb.1 (%ir-block.0): - liveins: $q0, $q1 - - ; CHECK-LABEL: name: test_v4i32_ne - ; CHECK: liveins: $q0, $q1 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr128 = COPY $q0 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr128 = COPY $q1 - ; CHECK-NEXT: [[CMEQv4i32_:%[0-9]+]]:fpr128 = CMEQv4i32 [[COPY]], [[COPY1]] - ; CHECK-NEXT: [[NOTv16i8_:%[0-9]+]]:fpr128 = NOTv16i8 [[CMEQv4i32_]] - ; CHECK-NEXT: [[XTNv4i16_:%[0-9]+]]:fpr64 = XTNv4i16 [[NOTv16i8_]] - ; CHECK-NEXT: $d0 = COPY [[XTNv4i16_]] - ; CHECK-NEXT: RET_ReallyLR implicit $d0 - %0:fpr(<4 x s32>) = COPY $q0 - %1:fpr(<4 x s32>) = COPY $q1 - %4:fpr(<4 x s32>) = G_ICMP intpred(ne), %0(<4 x s32>), %1 - %3:fpr(<4 x s16>) = G_TRUNC %4(<4 x s32>) - $d0 = COPY %3(<4 x s16>) - RET_ReallyLR implicit $d0 - -... ---- -name: test_v2i32_ne -alignment: 4 -legalized: true -regBankSelected: true -tracksRegLiveness: true -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: _ } - - { id: 3, class: fpr } - - { id: 4, class: fpr } -machineFunctionInfo: {} -body: | - bb.1 (%ir-block.0): - liveins: $d0, $d1 - - ; CHECK-LABEL: name: test_v2i32_ne - ; CHECK: liveins: $d0, $d1 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY $d1 - ; CHECK-NEXT: [[CMEQv2i32_:%[0-9]+]]:fpr64 = CMEQv2i32 [[COPY]], [[COPY1]] - ; CHECK-NEXT: [[NOTv8i8_:%[0-9]+]]:fpr64 = NOTv8i8 [[CMEQv2i32_]] - ; CHECK-NEXT: $d0 = COPY [[NOTv8i8_]] - ; CHECK-NEXT: RET_ReallyLR implicit $d0 - %0:fpr(<2 x s32>) = COPY $d0 - %1:fpr(<2 x s32>) = COPY $d1 - %4:fpr(<2 x s32>) = G_ICMP intpred(ne), %0(<2 x s32>), %1 - %3:fpr(<2 x s32>) = COPY %4(<2 x s32>) - $d0 = COPY %3(<2 x s32>) - RET_ReallyLR implicit $d0 - -... ---- -name: test_v2i16_ne -alignment: 4 -legalized: true -regBankSelected: true -tracksRegLiveness: true -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: fpr } - - { id: 3, class: fpr } - - { id: 4, class: _ } - - { id: 5, class: fpr } - - { id: 6, class: _ } - - { id: 7, class: fpr } - - { id: 8, class: fpr } - - { id: 9, class: fpr } - - { id: 10, class: gpr } - - { id: 11, class: fpr } - - { id: 12, class: fpr } - - { id: 13, class: gpr } - - { id: 14, class: fpr } - - { id: 15, class: fpr } -machineFunctionInfo: {} -body: | - bb.1 (%ir-block.0): - liveins: $d0, $d1 - - ; CHECK-LABEL: name: test_v2i16_ne - ; CHECK: liveins: $d0, $d1 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY $d1 - ; CHECK-NEXT: [[MOVID:%[0-9]+]]:fpr64 = MOVID 51 - ; CHECK-NEXT: [[ANDv8i8_:%[0-9]+]]:fpr64 = ANDv8i8 [[COPY]], [[MOVID]] - ; CHECK-NEXT: [[MOVID1:%[0-9]+]]:fpr64 = MOVID 51 - ; CHECK-NEXT: [[ANDv8i8_1:%[0-9]+]]:fpr64 = ANDv8i8 [[COPY1]], [[MOVID1]] - ; CHECK-NEXT: [[CMEQv2i32_:%[0-9]+]]:fpr64 = CMEQv2i32 [[ANDv8i8_]], [[ANDv8i8_1]] - ; CHECK-NEXT: [[NOTv8i8_:%[0-9]+]]:fpr64 = NOTv8i8 [[CMEQv2i32_]] - ; CHECK-NEXT: $d0 = COPY [[NOTv8i8_]] - ; CHECK-NEXT: RET_ReallyLR implicit $d0 - %2:fpr(<2 x s32>) = COPY $d0 - %3:fpr(<2 x s32>) = COPY $d1 - %13:gpr(s32) = G_CONSTANT i32 65535 - %14:fpr(<2 x s32>) = G_BUILD_VECTOR %13(s32), %13(s32) - %15:fpr(<2 x s32>) = COPY %2(<2 x s32>) - %7:fpr(<2 x s32>) = G_AND %15, %14 - %10:gpr(s32) = G_CONSTANT i32 65535 - %11:fpr(<2 x s32>) = G_BUILD_VECTOR %10(s32), %10(s32) - %12:fpr(<2 x s32>) = COPY %3(<2 x s32>) - %8:fpr(<2 x s32>) = G_AND %12, %11 - %9:fpr(<2 x s32>) = G_ICMP intpred(ne), %7(<2 x s32>), %8 - %5:fpr(<2 x s32>) = COPY %9(<2 x s32>) - $d0 = COPY %5(<2 x s32>) - RET_ReallyLR implicit $d0 - -... ---- -name: test_v8i16_ne -alignment: 4 -legalized: true -regBankSelected: true -tracksRegLiveness: true -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: _ } - - { id: 3, class: fpr } - - { id: 4, class: fpr } -machineFunctionInfo: {} -body: | - bb.1 (%ir-block.0): - liveins: $q0, $q1 - - ; CHECK-LABEL: name: test_v8i16_ne - ; CHECK: liveins: $q0, $q1 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr128 = COPY $q0 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr128 = COPY $q1 - ; CHECK-NEXT: [[CMEQv8i16_:%[0-9]+]]:fpr128 = CMEQv8i16 [[COPY]], [[COPY1]] - ; CHECK-NEXT: [[NOTv16i8_:%[0-9]+]]:fpr128 = NOTv16i8 [[CMEQv8i16_]] - ; CHECK-NEXT: [[XTNv8i8_:%[0-9]+]]:fpr64 = XTNv8i8 [[NOTv16i8_]] - ; CHECK-NEXT: $d0 = COPY [[XTNv8i8_]] - ; CHECK-NEXT: RET_ReallyLR implicit $d0 - %0:fpr(<8 x s16>) = COPY $q0 - %1:fpr(<8 x s16>) = COPY $q1 - %4:fpr(<8 x s16>) = G_ICMP intpred(ne), %0(<8 x s16>), %1 - %3:fpr(<8 x s8>) = G_TRUNC %4(<8 x s16>) - $d0 = COPY %3(<8 x s8>) - RET_ReallyLR implicit $d0 - -... ---- -name: test_v4i16_ne -alignment: 4 -legalized: true -regBankSelected: true -tracksRegLiveness: true -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: _ } - - { id: 3, class: fpr } - - { id: 4, class: fpr } -machineFunctionInfo: {} -body: | - bb.1 (%ir-block.0): - liveins: $d0, $d1 - - ; CHECK-LABEL: name: test_v4i16_ne - ; CHECK: liveins: $d0, $d1 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY $d1 - ; CHECK-NEXT: [[CMEQv4i16_:%[0-9]+]]:fpr64 = CMEQv4i16 [[COPY]], [[COPY1]] - ; CHECK-NEXT: [[NOTv8i8_:%[0-9]+]]:fpr64 = NOTv8i8 [[CMEQv4i16_]] - ; CHECK-NEXT: $d0 = COPY [[NOTv8i8_]] - ; CHECK-NEXT: RET_ReallyLR implicit $d0 - %0:fpr(<4 x s16>) = COPY $d0 - %1:fpr(<4 x s16>) = COPY $d1 - %4:fpr(<4 x s16>) = G_ICMP intpred(ne), %0(<4 x s16>), %1 - %3:fpr(<4 x s16>) = COPY %4(<4 x s16>) - $d0 = COPY %3(<4 x s16>) - RET_ReallyLR implicit $d0 - -... ---- -name: test_v16i8_ne -alignment: 4 -legalized: true -regBankSelected: true -tracksRegLiveness: true -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: _ } - - { id: 3, class: fpr } - - { id: 4, class: fpr } -machineFunctionInfo: {} -body: | - bb.1 (%ir-block.0): - liveins: $q0, $q1 - - ; CHECK-LABEL: name: test_v16i8_ne - ; CHECK: liveins: $q0, $q1 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr128 = COPY $q0 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr128 = COPY $q1 - ; CHECK-NEXT: [[CMEQv16i8_:%[0-9]+]]:fpr128 = CMEQv16i8 [[COPY]], [[COPY1]] - ; CHECK-NEXT: [[NOTv16i8_:%[0-9]+]]:fpr128 = NOTv16i8 [[CMEQv16i8_]] - ; CHECK-NEXT: $q0 = COPY [[NOTv16i8_]] - ; CHECK-NEXT: RET_ReallyLR implicit $q0 - %0:fpr(<16 x s8>) = COPY $q0 - %1:fpr(<16 x s8>) = COPY $q1 - %4:fpr(<16 x s8>) = G_ICMP intpred(ne), %0(<16 x s8>), %1 - %3:fpr(<16 x s8>) = COPY %4(<16 x s8>) - $q0 = COPY %3(<16 x s8>) - RET_ReallyLR implicit $q0 - -... ---- -name: test_v8i8_ne -alignment: 4 -legalized: true -regBankSelected: true -tracksRegLiveness: true -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: _ } - - { id: 3, class: fpr } - - { id: 4, class: fpr } -machineFunctionInfo: {} -body: | - bb.1 (%ir-block.0): - liveins: $d0, $d1 - - ; CHECK-LABEL: name: test_v8i8_ne - ; CHECK: liveins: $d0, $d1 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY $d1 - ; CHECK-NEXT: [[CMEQv8i8_:%[0-9]+]]:fpr64 = CMEQv8i8 [[COPY]], [[COPY1]] - ; CHECK-NEXT: [[NOTv8i8_:%[0-9]+]]:fpr64 = NOTv8i8 [[CMEQv8i8_]] - ; CHECK-NEXT: $d0 = COPY [[NOTv8i8_]] - ; CHECK-NEXT: RET_ReallyLR implicit $d0 - %0:fpr(<8 x s8>) = COPY $d0 - %1:fpr(<8 x s8>) = COPY $d1 - %4:fpr(<8 x s8>) = G_ICMP intpred(ne), %0(<8 x s8>), %1 - %3:fpr(<8 x s8>) = COPY %4(<8 x s8>) - $d0 = COPY %3(<8 x s8>) - RET_ReallyLR implicit $d0 - ... --- name: test_v2i64_ugt -- GitLab From ca051dfe9f0996e7fdad8fde5817e5b6ce758ab9 Mon Sep 17 00:00:00 2001 From: Ivan Butygin Date: Mon, 13 May 2024 17:24:22 +0300 Subject: [PATCH 069/578] [mlir][utils] Add script to verify canonicalizations against Alive2 (#91867) This script takes IR before and after canonicalization, translates it into llvm IR and converts it to format suitable for Alive2 https://alive2.llvm.org/ce/ This is primarily for arith canonicalizations verification, but technically it can be adapted for any dialect translatable to llvm. Usage `python verify_canon.py canonicalize.mlir -f func1 func2 ...` Example output: https://alive2.llvm.org/ce/z/KhQs4J Initial discussion: https://github.com/llvm/llvm-project/pull/91646#pullrequestreview-2049342826 --- mlir/utils/verify-canon/verify_canon.py | 77 +++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 mlir/utils/verify-canon/verify_canon.py diff --git a/mlir/utils/verify-canon/verify_canon.py b/mlir/utils/verify-canon/verify_canon.py new file mode 100644 index 000000000000..bfddba9577b9 --- /dev/null +++ b/mlir/utils/verify-canon/verify_canon.py @@ -0,0 +1,77 @@ +# 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 script is a helper to verify canonicalization patterns using Alive2 +# https://alive2.llvm.org/ce/. +# It performs the following steps: +# - Filters out the provided test functions. +# - Runs the canonicalization pass on the remaining functions. +# - Lowers both the original and the canonicalized functions to LLVM IR. +# - Prints the canonicalized and the original functions side-by-side in a format +# that can be copied into Alive2 for verification. +# Example: `python verify_canon.py canonicalize.mlir -f func1 func2 func3` + +import subprocess +import tempfile +import sys +from pathlib import Path +from argparse import ArgumentParser + + +def filter_funcs(ir, funcs): + if not funcs: + return ir + + funcs_str = ",".join(funcs) + return subprocess.check_output( + ["mlir-opt", f"--symbol-privatize=exclude={funcs_str}", "--symbol-dce"], + input=ir, + ) + + +def add_func_prefix(src, prefix): + return src.replace("@", "@" + prefix) + + +def merge_ir(chunks): + files = [] + for chunk in chunks: + tmp = tempfile.NamedTemporaryFile(suffix=".ll") + tmp.write(chunk) + tmp.flush() + files.append(tmp) + + return subprocess.check_output(["llvm-link", "-S"] + [f.name for f in files]) + + +if __name__ == "__main__": + parser = ArgumentParser() + parser.add_argument("file") + parser.add_argument("-f", "--func-names", nargs="+", default=[]) + args = parser.parse_args() + + file = args.file + funcs = args.func_names + + orig_ir = Path(file).read_bytes() + orig_ir = filter_funcs(orig_ir, funcs) + + to_llvm_args = ["--convert-to-llvm"] + orig_args = ["mlir-opt"] + to_llvm_args + canon_args = ["mlir-opt", "-canonicalize"] + to_llvm_args + translate_args = ["mlir-translate", "-mlir-to-llvmir"] + + orig = subprocess.check_output(orig_args, input=orig_ir) + canonicalized = subprocess.check_output(canon_args, input=orig_ir) + + orig = subprocess.check_output(translate_args, input=orig) + canonicalized = subprocess.check_output(translate_args, input=canonicalized) + + enc = "utf-8" + orig = bytes(add_func_prefix(orig.decode(enc), "src_"), enc) + canonicalized = bytes(add_func_prefix(canonicalized.decode(enc), "tgt_"), enc) + + res = merge_ir([orig, canonicalized]) + + print(res.decode(enc)) -- GitLab From 96ebed7c7481bb143c9d3db5f4c128bb32545229 Mon Sep 17 00:00:00 2001 From: JOSTAR <52376093+shenjunjiekoda@users.noreply.github.com> Date: Mon, 13 May 2024 22:32:46 +0800 Subject: [PATCH 070/578] [analyzer][NFC] Move `CTUPhase1InliningMode` option to String analyzer options category (#91932) The `CTUPhase1InliningMode`option was originally placed under Unsigned analyzer options, but its value is a string. This move aligns the option with its actual type. --- .../StaticAnalyzer/Core/AnalyzerOptions.def | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def index 2fc825c2af9c..f008c9c581d9 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def @@ -413,22 +413,6 @@ ANALYZER_OPTION( "analysis is too low, it is meaningful to provide a minimum value that " "serves as an upper bound instead.", 10000) -ANALYZER_OPTION( - StringRef, CTUPhase1InliningMode, "ctu-phase1-inlining", - "Controls which functions will be inlined during the first phase of the ctu " - "analysis. " - "If the value is set to 'all' then all foreign functions are inlinied " - "immediately during the first phase, thus rendering the second phase a noop. " - "The 'ctu-max-nodes-*' budge has no effect in this case. " - "If the value is 'small' then only functions with a linear CFG and with a " - "limited number of statements would be inlined during the first phase. The " - "long and/or nontrivial functions are handled in the second phase and are " - "controlled by the 'ctu-max-nodes-*' budge. " - "The value 'none' means that all foreign functions are inlined only in the " - "second phase, 'ctu-max-nodes-*' budge limits the second phase. " - "Value: \"none\", \"small\", \"all\".", - "small") - ANALYZER_OPTION( unsigned, RegionStoreSmallStructLimit, "region-store-small-struct-limit", "The largest number of fields a struct can have and still be considered " @@ -478,6 +462,22 @@ ANALYZER_OPTION( "where to look for those alternative implementations (called models).", "") +ANALYZER_OPTION( + StringRef, CTUPhase1InliningMode, "ctu-phase1-inlining", + "Controls which functions will be inlined during the first phase of the ctu " + "analysis. " + "If the value is set to 'all' then all foreign functions are inlinied " + "immediately during the first phase, thus rendering the second phase a noop. " + "The 'ctu-max-nodes-*' budge has no effect in this case. " + "If the value is 'small' then only functions with a linear CFG and with a " + "limited number of statements would be inlined during the first phase. The " + "long and/or nontrivial functions are handled in the second phase and are " + "controlled by the 'ctu-max-nodes-*' budge. " + "The value 'none' means that all foreign functions are inlined only in the " + "second phase, 'ctu-max-nodes-*' budge limits the second phase. " + "Value: \"none\", \"small\", \"all\".", + "small") + ANALYZER_OPTION( StringRef, CXXMemberInliningMode, "c++-inlining", "Controls which C++ member functions will be considered for inlining. " -- GitLab From 3acc6919109d91c1f047a02229a1785b461259d9 Mon Sep 17 00:00:00 2001 From: jyu2-git Date: Mon, 13 May 2024 07:39:23 -0700 Subject: [PATCH 071/578] =?UTF-8?q?Revert=20"Revert=20"[OpenMP][TR12]=20ch?= =?UTF-8?q?ange=20property=20of=20map-type=20modifier."=E2=80=A6=20(#91821?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … (#90885)" This reverts commit eea81aa29848361eb5b24f24d2af643fdeb9adfd. --- .../clang/Basic/DiagnosticParseKinds.td | 5 + clang/lib/Parse/ParseOpenMP.cpp | 51 +++++++-- clang/test/OpenMP/target_ast_print.cpp | 58 ++++++++++ clang/test/OpenMP/target_map_messages.cpp | 105 ++++++++++-------- 4 files changed, 165 insertions(+), 54 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index bc9d7cacc50b..8316845844cb 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1438,6 +1438,9 @@ def err_omp_decl_in_declare_simd_variant : Error< def err_omp_sink_and_source_iteration_not_allowd: Error<" '%0 %select{sink:|source:}1' must be with '%select{omp_cur_iteration - 1|omp_cur_iteration}1'">; def err_omp_unknown_map_type : Error< "incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">; +def err_omp_more_one_map_type : Error<"map type is already specified">; +def note_previous_map_type_specified_here + : Note<"map type '%0' is previous specified here">; def err_omp_unknown_map_type_modifier : Error< "incorrect map type modifier, expected one of: 'always', 'close', 'mapper'" "%select{|, 'present'|, 'present', 'iterator'}0%select{|, 'ompx_hold'}1">; @@ -1445,6 +1448,8 @@ def err_omp_map_type_missing : Error< "missing map type">; def err_omp_map_type_modifier_missing : Error< "missing map type modifier">; +def err_omp_map_modifier_specification_list : Error< + "empty modifier-specification-list is not allowed">; def err_omp_declare_simd_inbranch_notinbranch : Error< "unexpected '%0' clause, '%1' is specified already">; def err_omp_expected_clause_argument diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 03a64600bc2a..ca2c6d69eb98 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -4208,13 +4208,20 @@ bool Parser::parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data) { return T.consumeClose(); } +static OpenMPMapClauseKind isMapType(Parser &P); + /// Parse map-type-modifiers in map clause. -/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) +/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] [map-type] : ] list) /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) | /// present +/// where, map-type ::= alloc | delete | from | release | to | tofrom bool Parser::parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data) { + bool HasMapType = false; + SourceLocation PreMapLoc = Tok.getLocation(); + StringRef PreMapName = ""; while (getCurToken().isNot(tok::colon)) { OpenMPMapModifierKind TypeModifier = isMapModifier(*this); + OpenMPMapClauseKind MapKind = isMapType(*this); if (TypeModifier == OMPC_MAP_MODIFIER_always || TypeModifier == OMPC_MAP_MODIFIER_close || TypeModifier == OMPC_MAP_MODIFIER_present || @@ -4237,6 +4244,19 @@ bool Parser::parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data) { Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma) << "map type modifier"; + } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) { + if (!HasMapType) { + HasMapType = true; + Data.ExtraModifier = MapKind; + MapKind = OMPC_MAP_unknown; + PreMapLoc = Tok.getLocation(); + PreMapName = Tok.getIdentifierInfo()->getName(); + } else { + Diag(Tok, diag::err_omp_more_one_map_type); + Diag(PreMapLoc, diag::note_previous_map_type_specified_here) + << PreMapName; + } + ConsumeToken(); } else { // For the case of unknown map-type-modifier or a map-type. // Map-type is followed by a colon; the function returns when it @@ -4247,8 +4267,14 @@ bool Parser::parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data) { continue; } // Potential map-type token as it is followed by a colon. - if (PP.LookAhead(0).is(tok::colon)) - return false; + if (PP.LookAhead(0).is(tok::colon)) { + if (getLangOpts().OpenMP >= 60) { + break; + } else { + return false; + } + } + Diag(Tok, diag::err_omp_unknown_map_type_modifier) << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1) : 0) @@ -4258,6 +4284,14 @@ bool Parser::parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data) { if (getCurToken().is(tok::comma)) ConsumeToken(); } + if (getLangOpts().OpenMP >= 60 && !HasMapType) { + if (!Tok.is(tok::colon)) { + Diag(Tok, diag::err_omp_unknown_map_type); + ConsumeToken(); + } else { + Data.ExtraModifier = OMPC_MAP_unknown; + } + } return false; } @@ -4269,13 +4303,12 @@ static OpenMPMapClauseKind isMapType(Parser &P) { if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) return OMPC_MAP_unknown; Preprocessor &PP = P.getPreprocessor(); - OpenMPMapClauseKind MapType = - static_cast(getOpenMPSimpleClauseType( - OMPC_map, PP.getSpelling(Tok), P.getLangOpts())); + unsigned MapType = + getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok), P.getLangOpts()); if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from || MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc || MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release) - return MapType; + return static_cast(MapType); return OMPC_MAP_unknown; } @@ -4659,8 +4692,10 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, // Only parse map-type-modifier[s] and map-type if a colon is present in // the map clause. if (ColonPresent) { + if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon)) + Diag(Tok, diag::err_omp_map_modifier_specification_list); IsInvalidMapperModifier = parseMapTypeModifiers(Data); - if (!IsInvalidMapperModifier) + if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier) parseMapType(*this, Data); else SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); diff --git a/clang/test/OpenMP/target_ast_print.cpp b/clang/test/OpenMP/target_ast_print.cpp index f4c10fe3a181..ec6cf2130d7a 100644 --- a/clang/test/OpenMP/target_ast_print.cpp +++ b/clang/test/OpenMP/target_ast_print.cpp @@ -1201,6 +1201,64 @@ foo(); } #endif // OMP52 +#ifdef OMP60 + +///==========================================================================/// +// RUN: %clang_cc1 -DOMP60 -verify -Wno-vla -fopenmp -fopenmp-version=60 -ast-print %s | FileCheck %s --check-prefix OMP60 +// RUN: %clang_cc1 -DOMP60 -fopenmp -fopenmp-version=60 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -DOMP60 -fopenmp -fopenmp-version=60 -std=c++11 -include-pch %t -verify -Wno-vla %s -ast-print | FileCheck %s --check-prefix OMP60 + +// RUN: %clang_cc1 -DOMP60 -verify -Wno-vla -fopenmp-simd -fopenmp-version=60 -ast-print %s | FileCheck %s --check-prefix OMP60 +// RUN: %clang_cc1 -DOMP60 -fopenmp-simd -fopenmp-version=60 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -DOMP60 -fopenmp-simd -fopenmp-version=60 -std=c++11 -include-pch %t -verify -Wno-vla %s -ast-print | FileCheck %s --check-prefix OMP60 + +void foo() {} +template +T tmain(T argc, T *argv) { + T i; +#pragma omp target map(from always: i) + foo(); +#pragma omp target map(from, close: i) + foo(); +#pragma omp target map(always,close: i) + foo(); + return 0; +} +//OMP60: template T tmain(T argc, T *argv) { +//OMP60-NEXT: T i; +//OMP60-NEXT: #pragma omp target map(always,from: i) +//OMP60-NEXT: foo(); +//OMP60-NEXT: #pragma omp target map(close,from: i) +//OMP60-NEXT: foo(); +//OMP60-NEXT: #pragma omp target map(always,close,tofrom: i) +//OMP60-NEXT: foo(); +//OMP60-NEXT: return 0; +//OMP60-NEXT:} +//OMP60: template<> int tmain(int argc, int *argv) { +//OMP60-NEXT: int i; +//OMP60-NEXT: #pragma omp target map(always,from: i) +//OMP60-NEXT: foo(); +//OMP60-NEXT: #pragma omp target map(close,from: i) +//OMP60-NEXT: foo(); +//OMP60-NEXT: #pragma omp target map(always,close,tofrom: i) +//OMP60-NEXT: foo(); +//OMP60-NEXT: return 0; +//OMP60-NEXT:} +//OMP60: template<> char tmain(char argc, char *argv) { +//OMP60-NEXT: char i; +//OMP60-NEXT: #pragma omp target map(always,from: i) +//OMP60-NEXT: foo(); +//OMP60-NEXT: #pragma omp target map(close,from: i) +//OMP60-NEXT: foo(); +//OMP60-NEXT: #pragma omp target map(always,close,tofrom: i) +//OMP60-NEXT: foo(); +//OMP60-NEXT: return 0; +//OMP60-NEXT:} +int main (int argc, char **argv) { + return tmain(argc, &argc) + tmain(argv[0][0], argv[0]); +} +#endif // OMP60 + #ifdef OMPX // RUN: %clang_cc1 -DOMPX -verify -Wno-vla -fopenmp -fopenmp-extensions -ast-print %s | FileCheck %s --check-prefix=OMPX diff --git a/clang/test/OpenMP/target_map_messages.cpp b/clang/test/OpenMP/target_map_messages.cpp index a6776ee12c0e..3bd432b47e63 100644 --- a/clang/test/OpenMP/target_map_messages.cpp +++ b/clang/test/OpenMP/target_map_messages.cpp @@ -1,34 +1,35 @@ // -fopenmp, -fno-openmp-extensions -// RUN: %clang_cc1 -verify=expected,ge50,lt51,omp,lt51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,lt50,lt51,omp,lt51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=40 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,lt50,lt51,omp,lt51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=45 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,ge50,lt51,omp,lt51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,ge50,ge51,omp,ge51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=51 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,ge50,ge51,ge52,omp,ge52-omp,omp52 -fopenmp -fno-openmp-extensions -fopenmp-version=52 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,lt51,lt60,omp,lt51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,lt50,lt51,lt60,omp,lt51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=40 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,lt50,lt51,lt60,omp,lt51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=45 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,lt51,lt60,omp,lt51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,ge51,lt60,omp,ge51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=51 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,ge51,ge52,lt60,omp,ge52-omp,omp52 -fopenmp -fno-openmp-extensions -fopenmp-version=52 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,ge52,ge60,omp,ge60-omp,omp60 -fopenmp -fno-openmp-extensions -fopenmp-version=60 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla // RUN: %clang_cc1 -DCCODE -verify -fopenmp -fno-openmp-extensions -ferror-limit 300 -x c %s -Wno-openmp -Wuninitialized -Wno-vla // -fopenmp-simd, -fno-openmp-extensions -// RUN: %clang_cc1 -verify=expected,ge50,lt51,omp,lt51-omp -fopenmp-simd -fno-openmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,lt50,lt51,omp,lt51-omp -fopenmp-simd -fno-openmp-extensions -fopenmp-version=40 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,lt50,lt51,omp,lt51-omp -fopenmp-simd -fno-openmp-extensions -fopenmp-version=45 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,ge50,lt51,omp,lt51-omp -fopenmp-simd -fno-openmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,ge50,ge51,omp,ge51-omp -fopenmp-simd -fno-openmp-extensions -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,lt51,lt60,omp,lt51-omp -fopenmp-simd -fno-openmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,lt50,lt51,lt60,omp,lt51-omp -fopenmp-simd -fno-openmp-extensions -fopenmp-version=40 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,lt50,lt51,lt60,omp,lt51-omp -fopenmp-simd -fno-openmp-extensions -fopenmp-version=45 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,lt51,lt60,omp,lt51-omp -fopenmp-simd -fno-openmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,ge51,lt60,omp,ge51-omp -fopenmp-simd -fno-openmp-extensions -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla // RUN: %clang_cc1 -DCCODE -verify -fopenmp-simd -fno-openmp-extensions -ferror-limit 300 -x c %s -Wno-openmp-mapping -Wuninitialized -Wno-vla // -fopenmp -fopenmp-extensions -// RUN: %clang_cc1 -verify=expected,ge50,lt51,ompx,lt51-ompx -fopenmp -fopenmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,lt50,lt51,ompx,lt51-ompx -fopenmp -fopenmp-extensions -fopenmp-version=40 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,lt50,lt51,ompx,lt51-ompx -fopenmp -fopenmp-extensions -fopenmp-version=45 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,ge50,lt51,ompx,lt51-ompx -fopenmp -fopenmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,ge50,ge51,ompx,ge51-ompx -fopenmp -fopenmp-extensions -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,lt51,lt60,ompx,lt51-ompx -fopenmp -fopenmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,lt50,lt51,lt60,ompx,lt51-ompx -fopenmp -fopenmp-extensions -fopenmp-version=40 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,lt50,lt51,lt60,ompx,lt51-ompx -fopenmp -fopenmp-extensions -fopenmp-version=45 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,lt51,lt60,ompx,lt51-ompx -fopenmp -fopenmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,ge51,lt60,ompx,ge51-ompx -fopenmp -fopenmp-extensions -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla // RUN: %clang_cc1 -DCCODE -verify -fopenmp -fopenmp-extensions -ferror-limit 300 -x c %s -Wno-openmp -Wuninitialized -Wno-vla // -fopenmp-simd -fopenmp-extensions -// RUN: %clang_cc1 -verify=expected,ge50,lt51,ompx,lt51-ompx -fopenmp-simd -fopenmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,lt50,lt51,ompx,lt51-ompx -fopenmp-simd -fopenmp-extensions -fopenmp-version=40 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,lt50,lt51,ompx,lt51-ompx -fopenmp-simd -fopenmp-extensions -fopenmp-version=45 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,ge50,lt51,ompx,lt51-ompx -fopenmp-simd -fopenmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla -// RUN: %clang_cc1 -verify=expected,ge50,ge51,ompx,ge51-ompx -fopenmp-simd -fopenmp-extensions -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,lt51,lt60,ompx,lt51-ompx -fopenmp-simd -fopenmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,lt50,lt51,lt60,ompx,lt51-ompx -fopenmp-simd -fopenmp-extensions -fopenmp-version=40 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,lt50,lt51,lt60,ompx,lt51-ompx -fopenmp-simd -fopenmp-extensions -fopenmp-version=45 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,lt51,lt60,ompx,lt51-ompx -fopenmp-simd -fopenmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla +// RUN: %clang_cc1 -verify=expected,ge50,ge51,lt60,ompx,ge51-ompx -fopenmp-simd -fopenmp-extensions -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized -Wno-vla // RUN: %clang_cc1 -DCCODE -verify -fopenmp-simd -fopenmp-extensions -ferror-limit 300 -x c %s -Wno-openmp-mapping -Wuninitialized -Wno-vla // Check @@ -113,7 +114,7 @@ struct SA { #pragma omp target map(b[true:true]) {} - #pragma omp target map(: c,f) // expected-error {{missing map type}} + #pragma omp target map(: c,f) // lt60-error {{missing map type}} // ge60-error {{empty modifier-specification-list is not allowed}} {} #pragma omp target map(always, tofrom: c,f) {} @@ -159,28 +160,28 @@ struct SA { // expected-error@+1 {{use of undeclared identifier 'present'}} #pragma omp target map(present) {} - // ge52-omp-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} + // ge52-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(ompx_hold, tofrom: c,f) {} - // ge52-omp-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} + // ge52-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(ompx_hold, tofrom: c[1:2],f) {} - // ge52-omp-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} + // ge52-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(ompx_hold, tofrom: c,f[1:2]) {} - // ge52-omp-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} + // ge52-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // expected-error@+3 {{section length is unspecified and cannot be inferred because subscripted value is not an array}} // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(ompx_hold, tofrom: c[:],f) {} - // ge52-omp-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} + // ge52-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // expected-error@+3 {{section length is unspecified and cannot be inferred because subscripted value is not an array}} // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} @@ -193,19 +194,19 @@ struct SA { {} #pragma omp target map(always, close, always, close, tofrom: a) // expected-error 2 {{same map type modifier has been specified more than once}} {} + // ge60-error@+3 {{same map type modifier has been specified more than once}} // ge51-error@+2 {{same map type modifier has been specified more than once}} // lt51-error@+1 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(present, present, tofrom: a) {} - // ge52-omp-error@+5 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} - // ge52-omp-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} + // ge52-error@+4 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // ompx-error@+3 {{same map type modifier has been specified more than once}} // ge51-omp-error@+2 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(ompx_hold, ompx_hold, tofrom: a) {} - // ge52-omp-error@+9 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} - // ge52-omp-error@+8 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} + // ge60-error@+9 {{same map type modifier has been specified more than once}} + // ge52-error@+8 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // expected-error@+7 2 {{same map type modifier has been specified more than once}} // ge51-error@+6 {{same map type modifier has been specified more than once}} // lt51-ompx-error@+5 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'ompx_hold'}} @@ -219,34 +220,45 @@ struct SA { {} #pragma omp target map( , , tofrom: a) // expected-error {{missing map type modifier}} expected-error {{missing map type modifier}} {} - #pragma omp target map( , , : a) // expected-error {{missing map type modifier}} expected-error {{missing map type modifier}} expected-error {{missing map type}} + #pragma omp target map( , , : a) // expected-error {{missing map type modifier}} expected-error {{missing map type modifier}} lt60-error {{missing map type}} {} + // ge60-error@+4 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // ge51-error@+3 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-error@+2 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} // expected-error@+1 {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} #pragma omp target map( d, f, bf: a) {} + // ge60-error@+5 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator}} // expected-error@+4 {{missing map type modifier}} // ge51-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} - // expected-error@+1 {{missing map type}} + // lt60-error@+1 {{missing map type}} #pragma omp target map( , f, : a) {} - #pragma omp target map(always close: a) // expected-error {{missing map type}} omp52-error{{missing ',' after map type modifier}} + #pragma omp target map(always close: a) // lt60-error {{missing map type}} ge52-error{{missing ',' after map type modifier}} {} - #pragma omp target map(always close bf: a) // omp52-error 2 {{missing ',' after map type modifier}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} + #pragma omp target map(always close bf: a) // ge52-error 2 {{missing ',' after map type modifier}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} {} - // omp52-error@+4 {{missing ',' after map type modifier}} + // ge52-error@+4 {{missing ',' after map type modifier}} // ge51-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} - // expected-error@+1 {{missing map type}} + // lt60-error@+1 {{missing map type}} #pragma omp target map(always tofrom close: a) {} + // ge60-note@+4 {{map type 'tofrom' is previous specified here}} + // ge60-error@+3 {{map type is already specified}} // ge51-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(tofrom from: a) {} - #pragma omp target map(close bf: a) // omp52-error {{missing ',' after map type modifier}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} + // ge60-note@+5 {{map type 'to' is previous specified here}} + // ge60-error@+4 {{map type is already specified}} + // ge52-error@+3 {{missing ',' after map type modifier}} + // ge51-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} + // lt51-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} + #pragma omp target map(to always from: a) + {} + #pragma omp target map(close bf: a) // ge52-error {{missing ',' after map type modifier}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} {} #pragma omp target map(([b[I]][bf])f) // lt50-error {{expected ',' or ']' in lambda capture list}} lt50-error {{expected ')'}} lt50-note {{to match this '('}} {} @@ -266,6 +278,7 @@ struct SA { // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(iterator(it=0:10, it=0:20), tofrom:a) {} + // ge60-error@+7 {{expected '(' after 'iterator'}} // ge51-ompx-error@+6 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'ompx_hold'}} // lt51-ompx-error@+5 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'ompx_hold'}} // lt51-error@+4 {{expected '(' after 'iterator'}} @@ -694,20 +707,20 @@ T tmain(T argc) { foo(); #pragma omp target data map(always, tofrom: x) -#pragma omp target data map(always: x) // expected-error {{missing map type}} +#pragma omp target data map(always: x) // lt60-error {{missing map type}} // ge51-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} -// expected-error@+1 {{missing map type}} +// lt60-error@+1 {{missing map type}} #pragma omp target data map(tofrom, always: x) #pragma omp target data map(always, tofrom: always, tofrom, x) #pragma omp target map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}} foo(); #pragma omp target data map(close, tofrom: x) -#pragma omp target data map(close: x) // expected-error {{missing map type}} +#pragma omp target data map(close: x) // lt60-error {{missing map type}} // ge51-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} -// expected-error@+1 {{missing map type}} +// lt60-error@+1 {{missing map type}} #pragma omp target data map(tofrom, close: x) #pragma omp target data map(close, tofrom: close, tofrom, x) foo(); @@ -829,19 +842,19 @@ int main(int argc, char **argv) { foo(); #pragma omp target data map(always, tofrom: x) -#pragma omp target data map(always: x) // expected-error {{missing map type}} +#pragma omp target data map(always: x) // lt60-error {{missing map type}} // ge51-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} -// expected-error@+1 {{missing map type}} +// lt60-error@+1 {{missing map type}} #pragma omp target data map(tofrom, always: x) #pragma omp target data map(always, tofrom: always, tofrom, x) #pragma omp target map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}} foo(); #pragma omp target data map(close, tofrom: x) -#pragma omp target data map(close: x) // expected-error {{missing map type}} +#pragma omp target data map(close: x) // lt60-error {{missing map type}} // ge51-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} -// expected-error@+1 {{missing map type}} +// lt60-error@+1 {{missing map type}} #pragma omp target data map(tofrom, close: x) foo(); // lt51-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} -- GitLab From 8b7f178091b70d264c13b1f83b58e6c9dfe81c1b Mon Sep 17 00:00:00 2001 From: madanial0 <118996571+madanial0@users.noreply.github.com> Date: Mon, 13 May 2024 10:40:14 -0400 Subject: [PATCH 072/578] [flang] Fix Failing rewrite-out_of_range testcase to only check for real 10 on supported platforms (#91629) The real 10 tests fail on `AIX` on `PPC`, only check them on `x86_64` Co-authored-by: Mark Danial --- flang/test/Evaluate/rewrite-out_of_range.F90 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/flang/test/Evaluate/rewrite-out_of_range.F90 b/flang/test/Evaluate/rewrite-out_of_range.F90 index a5cd09cb2853..b5df610ff2fb 100644 --- a/flang/test/Evaluate/rewrite-out_of_range.F90 +++ b/flang/test/Evaluate/rewrite-out_of_range.F90 @@ -1,5 +1,5 @@ ! Tests rewriting of OUT_OF_RANGE() -! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse -cpp %s 2>&1 | FileCheck %s --check-prefixes=CHECK%if target=x86_64{{.*}} %{,CHECK-X86-64%} logical round @@ -194,12 +194,12 @@ end !CHECK: PRINT *, " real", 8_4, "real", 8_4, .false._4 !CHECK: PRINT *, " real", 8_4, "real", 10_4, .false._4 !CHECK: PRINT *, " real", 8_4, "real", 16_4, .false._4 -!CHECK: PRINT *, " real", 10_4, "real", 2_4, blt(transfer(abs(x)-6.5504e4_10,0_16)-1_16,604444463063240877801471_16) -!CHECK: PRINT *, " real", 10_4, "real", 3_4, blt(transfer(abs(x)-3.3895313892515354759047080037148786688e38_10,0_16)-1_16,604444463063240877801471_16) -!CHECK: PRINT *, " real", 10_4, "real", 4_4, blt(transfer(abs(x)-3.4028234663852885981170418348451692544e38_10,0_16)-1_16,604444463063240877801471_16) -!CHECK: PRINT *, " real", 10_4, "real", 8_4, blt(transfer(abs(x)-1.79769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368e308_10,0_16)-1_16,604444463063240877801471_16) -!CHECK: PRINT *, " real", 10_4, "real", 10_4, .false._4 -!CHECK: PRINT *, " real", 10_4, "real", 16_4, .false._4 +!CHECK-X86-64: PRINT *, " real", 10_4, "real", 2_4, blt(transfer(abs(x)-6.5504e4_10,0_16)-1_16,604444463063240877801471_16) +!CHECK-X86-64: PRINT *, " real", 10_4, "real", 3_4, blt(transfer(abs(x)-3.3895313892515354759047080037148786688e38_10,0_16)-1_16,604444463063240877801471_16) +!CHECK-X86-64: PRINT *, " real", 10_4, "real", 4_4, blt(transfer(abs(x)-3.4028234663852885981170418348451692544e38_10,0_16)-1_16,604444463063240877801471_16) +!CHECK-X86-64: PRINT *, " real", 10_4, "real", 8_4, blt(transfer(abs(x)-1.79769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368e308_10,0_16)-1_16,604444463063240877801471_16) +!CHECK-X86-64: PRINT *, " real", 10_4, "real", 10_4, .false._4 +!CHECK-X86-64: PRINT *, " real", 10_4, "real", 16_4, .false._4 !CHECK: PRINT *, " real", 16_4, "real", 2_4, blt(transfer(abs(x)-6.5504e4_16,0_16)-1_16,170135991163610696904058773219554885631_16) !CHECK: PRINT *, " real", 16_4, "real", 3_4, blt(transfer(abs(x)-3.3895313892515354759047080037148786688e38_16,0_16)-1_16,170135991163610696904058773219554885631_16) !CHECK: PRINT *, " real", 16_4, "real", 4_4, blt(transfer(abs(x)-3.4028234663852885981170418348451692544e38_16,0_16)-1_16,170135991163610696904058773219554885631_16) -- GitLab From d8197728145137e2aa00f3b2ed69914f48851d09 Mon Sep 17 00:00:00 2001 From: Tuan Chuong Goh Date: Mon, 13 May 2024 14:27:09 +0000 Subject: [PATCH 073/578] [AArch64][NFC] Pre-commit tests for Select G_ICMP Zero Instruction (#90054) --- llvm/test/CodeGen/AArch64/icmp.ll | 1114 +++++++++++++++++++++++++++++ 1 file changed, 1114 insertions(+) diff --git a/llvm/test/CodeGen/AArch64/icmp.ll b/llvm/test/CodeGen/AArch64/icmp.ll index 2292bc6d2038..88b2f279ec3e 100644 --- a/llvm/test/CodeGen/AArch64/icmp.ll +++ b/llvm/test/CodeGen/AArch64/icmp.ll @@ -1375,3 +1375,1117 @@ entry: %s = select <32 x i1> %c, <32 x i8> %d, <32 x i8> %e ret <32 x i8> %s } + +; ===== ICMP Zero RHS ===== + +define <8 x i1> @icmp_eq_v8i8_Zero_RHS(<8 x i8> %a) { +; CHECK-SD-LABEL: icmp_eq_v8i8_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.8b, v0.8b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v8i8_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, v1.8b +; CHECK-GI-NEXT: ret + %c = icmp eq <8 x i8> %a, + ret <8 x i1> %c +} + +define <16 x i1> @icmp_eq_v16i8_Zero_RHS(<16 x i8> %a) { +; CHECK-SD-LABEL: icmp_eq_v16i8_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.16b, v0.16b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v16i8_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.16b, v0.16b, v1.16b +; CHECK-GI-NEXT: ret + %c = icmp eq <16 x i8> %a, + ret <16 x i1> %c +} + +define <4 x i1> @icmp_eq_v4i16_Zero_RHS(<4 x i16> %a) { +; CHECK-SD-LABEL: icmp_eq_v4i16_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.4h, v0.4h, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v4i16_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.4h, v0.4h, v1.4h +; CHECK-GI-NEXT: ret + %c = icmp eq <4 x i16> %a, + ret <4 x i1> %c +} + +define <8 x i1> @icmp_eq_v8i16_Zero_RHS(<8 x i16> %a) { +; CHECK-SD-LABEL: icmp_eq_v8i16_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.8h, v0.8h, #0 +; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v8i16_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.8h, v0.8h, v1.8h +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: ret + %c = icmp eq <8 x i16> %a, + ret <8 x i1> %c +} + +define <2 x i1> @icmp_eq_v2i32_Zero_RHS(<2 x i32> %a) { +; CHECK-SD-LABEL: icmp_eq_v2i32_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.2s, v0.2s, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v2i32_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: ret + %c = icmp eq <2 x i32> %a, + ret <2 x i1> %c +} + +define <4 x i1> @icmp_eq_v4i32_Zero_RHS(<4 x i32> %a) { +; CHECK-SD-LABEL: icmp_eq_v4i32_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0 +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v4i32_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret + %c = icmp eq <4 x i32> %a, + ret <4 x i1> %c +} + +define <2 x i1> @icmp_eq_v2i64_Zero_RHS(<2 x i64> %a) { +; CHECK-SD-LABEL: icmp_eq_v2i64_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.2d, v0.2d, #0 +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v2i64_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.2d, v0.2d, v1.2d +; CHECK-GI-NEXT: xtn v0.2s, v0.2d +; CHECK-GI-NEXT: ret + %c = icmp eq <2 x i64> %a, + ret <2 x i1> %c +} + +define <8 x i1> @icmp_sge_v8i8_Zero_RHS(<8 x i8> %a) { +; CHECK-SD-LABEL: icmp_sge_v8i8_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.8b, v0.8b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v8i8_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.8b, v0.8b, v1.8b +; CHECK-GI-NEXT: ret + %c = icmp sge <8 x i8> %a, + ret <8 x i1> %c +} + +define <16 x i1> @icmp_sge_v16i8_Zero_RHS(<16 x i8> %a) { +; CHECK-SD-LABEL: icmp_sge_v16i8_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.16b, v0.16b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v16i8_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.16b, v0.16b, v1.16b +; CHECK-GI-NEXT: ret + %c = icmp sge <16 x i8> %a, + ret <16 x i1> %c +} + +define <4 x i1> @icmp_sge_v4i16_Zero_RHS(<4 x i16> %a) { +; CHECK-SD-LABEL: icmp_sge_v4i16_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.4h, v0.4h, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v4i16_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.4h, v0.4h, v1.4h +; CHECK-GI-NEXT: ret + %c = icmp sge <4 x i16> %a, + ret <4 x i1> %c +} + +define <8 x i1> @icmp_sge_v8i16_Zero_RHS(<8 x i16> %a) { +; CHECK-SD-LABEL: icmp_sge_v8i16_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.8h, v0.8h, #0 +; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v8i16_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.8h, v0.8h, v1.8h +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: ret + %c = icmp sge <8 x i16> %a, + ret <8 x i1> %c +} + +define <2 x i1> @icmp_sge_v2i32_Zero_RHS(<2 x i32> %a) { +; CHECK-SD-LABEL: icmp_sge_v2i32_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.2s, v0.2s, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v2i32_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: ret + %c = icmp sge <2 x i32> %a, + ret <2 x i1> %c +} + +define <4 x i1> @icmp_sge_v4i32_Zero_RHS(<4 x i32> %a) { +; CHECK-SD-LABEL: icmp_sge_v4i32_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.4s, v0.4s, #0 +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v4i32_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret + %c = icmp sge <4 x i32> %a, + ret <4 x i1> %c +} + +define <2 x i1> @icmp_sge_v2i64_Zero_RHS(<2 x i64> %a) { +; CHECK-SD-LABEL: icmp_sge_v2i64_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.2d, v0.2d, #0 +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v2i64_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.2d, v0.2d, v1.2d +; CHECK-GI-NEXT: xtn v0.2s, v0.2d +; CHECK-GI-NEXT: ret + %c = icmp sge <2 x i64> %a, + ret <2 x i1> %c +} + +define <8 x i1> @icmp_sgt_v8i8_Zero_RHS(<8 x i8> %a) { +; CHECK-SD-LABEL: icmp_sgt_v8i8_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.8b, v0.8b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v8i8_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.8b, v0.8b, v1.8b +; CHECK-GI-NEXT: ret + %c = icmp sgt <8 x i8> %a, + ret <8 x i1> %c +} + +define <16 x i1> @icmp_sgt_v16i8_Zero_RHS(<16 x i8> %a) { +; CHECK-SD-LABEL: icmp_sgt_v16i8_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.16b, v0.16b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v16i8_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.16b, v0.16b, v1.16b +; CHECK-GI-NEXT: ret + %c = icmp sgt <16 x i8> %a, + ret <16 x i1> %c +} + +define <4 x i1> @icmp_sgt_v4i16_Zero_RHS(<4 x i16> %a) { +; CHECK-SD-LABEL: icmp_sgt_v4i16_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.4h, v0.4h, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v4i16_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.4h, v0.4h, v1.4h +; CHECK-GI-NEXT: ret + %c = icmp sgt <4 x i16> %a, + ret <4 x i1> %c +} + +define <8 x i1> @icmp_sgt_v8i16_Zero_RHS(<8 x i16> %a) { +; CHECK-SD-LABEL: icmp_sgt_v8i16_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.8h, v0.8h, #0 +; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v8i16_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.8h, v0.8h, v1.8h +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: ret + %c = icmp sgt <8 x i16> %a, + ret <8 x i1> %c +} + +define <2 x i1> @icmp_sgt_v2i32_Zero_RHS(<2 x i32> %a) { +; CHECK-SD-LABEL: icmp_sgt_v2i32_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.2s, v0.2s, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v2i32_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: ret + %c = icmp sgt <2 x i32> %a, + ret <2 x i1> %c +} + +define <4 x i1> @icmp_sgt_v4i32_Zero_RHS(<4 x i32> %a) { +; CHECK-SD-LABEL: icmp_sgt_v4i32_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.4s, v0.4s, #0 +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v4i32_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret + %c = icmp sgt <4 x i32> %a, + ret <4 x i1> %c +} + +define <2 x i1> @icmp_sgt_v2i64_Zero_RHS(<2 x i64> %a) { +; CHECK-SD-LABEL: icmp_sgt_v2i64_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.2d, v0.2d, #0 +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v2i64_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.2d, v0.2d, v1.2d +; CHECK-GI-NEXT: xtn v0.2s, v0.2d +; CHECK-GI-NEXT: ret + %c = icmp sgt <2 x i64> %a, + ret <2 x i1> %c +} + +define <8 x i1> @icmp_sle_v8i8_Zero_RHS(<8 x i8> %a) { +; CHECK-SD-LABEL: icmp_sle_v8i8_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.8b, v0.8b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v8i8_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.8b, v1.8b, v0.8b +; CHECK-GI-NEXT: ret + %c = icmp sle <8 x i8> %a, + ret <8 x i1> %c +} + +define <16 x i1> @icmp_sle_v16i8_Zero_RHS(<16 x i8> %a) { +; CHECK-SD-LABEL: icmp_sle_v16i8_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.16b, v0.16b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v16i8_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.16b, v1.16b, v0.16b +; CHECK-GI-NEXT: ret + %c = icmp sle <16 x i8> %a, + ret <16 x i1> %c +} + +define <4 x i1> @icmp_sle_v4i16_Zero_RHS(<4 x i16> %a) { +; CHECK-SD-LABEL: icmp_sle_v4i16_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.4h, v0.4h, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v4i16_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.4h, v1.4h, v0.4h +; CHECK-GI-NEXT: ret + %c = icmp sle <4 x i16> %a, + ret <4 x i1> %c +} + +define <8 x i1> @icmp_sle_v8i16_Zero_RHS(<8 x i16> %a) { +; CHECK-SD-LABEL: icmp_sle_v8i16_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.8h, v0.8h, #0 +; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v8i16_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.8h, v1.8h, v0.8h +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: ret + %c = icmp sle <8 x i16> %a, + ret <8 x i1> %c +} + +define <2 x i1> @icmp_sle_v2i32_Zero_RHS(<2 x i32> %a) { +; CHECK-SD-LABEL: icmp_sle_v2i32_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.2s, v0.2s, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v2i32_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.2s, v1.2s, v0.2s +; CHECK-GI-NEXT: ret + %c = icmp sle <2 x i32> %a, + ret <2 x i1> %c +} + +define <4 x i1> @icmp_sle_v4i32_Zero_RHS(<4 x i32> %a) { +; CHECK-SD-LABEL: icmp_sle_v4i32_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.4s, v0.4s, #0 +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v4i32_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.4s, v1.4s, v0.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret + %c = icmp sle <4 x i32> %a, + ret <4 x i1> %c +} + +define <2 x i1> @icmp_sle_v2i64_Zero_RHS(<2 x i64> %a) { +; CHECK-SD-LABEL: icmp_sle_v2i64_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.2d, v0.2d, #0 +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v2i64_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.2d, v1.2d, v0.2d +; CHECK-GI-NEXT: xtn v0.2s, v0.2d +; CHECK-GI-NEXT: ret + %c = icmp sle <2 x i64> %a, + ret <2 x i1> %c +} + +define <8 x i1> @icmp_slt_v8i8_Zero_RHS(<8 x i8> %a) { +; CHECK-SD-LABEL: icmp_slt_v8i8_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.8b, v0.8b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v8i8_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.8b, v1.8b, v0.8b +; CHECK-GI-NEXT: ret + %c = icmp slt <8 x i8> %a, + ret <8 x i1> %c +} + +define <16 x i1> @icmp_slt_v16i8_Zero_RHS(<16 x i8> %a) { +; CHECK-SD-LABEL: icmp_slt_v16i8_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.16b, v0.16b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v16i8_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.16b, v1.16b, v0.16b +; CHECK-GI-NEXT: ret + %c = icmp slt <16 x i8> %a, + ret <16 x i1> %c +} + +define <4 x i1> @icmp_slt_v4i16_Zero_RHS(<4 x i16> %a) { +; CHECK-SD-LABEL: icmp_slt_v4i16_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.4h, v0.4h, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v4i16_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.4h, v1.4h, v0.4h +; CHECK-GI-NEXT: ret + %c = icmp slt <4 x i16> %a, + ret <4 x i1> %c +} + +define <8 x i1> @icmp_slt_v8i16_Zero_RHS(<8 x i16> %a) { +; CHECK-SD-LABEL: icmp_slt_v8i16_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.8h, v0.8h, #0 +; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v8i16_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.8h, v1.8h, v0.8h +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: ret + %c = icmp slt <8 x i16> %a, + ret <8 x i1> %c +} + +define <2 x i1> @icmp_slt_v2i32_Zero_RHS(<2 x i32> %a) { +; CHECK-SD-LABEL: icmp_slt_v2i32_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.2s, v0.2s, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v2i32_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.2s, v1.2s, v0.2s +; CHECK-GI-NEXT: ret + %c = icmp slt <2 x i32> %a, + ret <2 x i1> %c +} + +define <4 x i1> @icmp_slt_v4i32_Zero_RHS(<4 x i32> %a) { +; CHECK-SD-LABEL: icmp_slt_v4i32_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.4s, v0.4s, #0 +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v4i32_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.4s, v1.4s, v0.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret + %c = icmp slt <4 x i32> %a, + ret <4 x i1> %c +} + +define <2 x i1> @icmp_slt_v2i64_Zero_RHS(<2 x i64> %a) { +; CHECK-SD-LABEL: icmp_slt_v2i64_Zero_RHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.2d, v0.2d, #0 +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v2i64_Zero_RHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.2d, v1.2d, v0.2d +; CHECK-GI-NEXT: xtn v0.2s, v0.2d +; CHECK-GI-NEXT: ret + %c = icmp slt <2 x i64> %a, + ret <2 x i1> %c +} + +; ===== ICMP Zero LHS ===== + +define <8 x i1> @icmp_eq_v8i8_Zero_LHS(<8 x i8> %a) { +; CHECK-SD-LABEL: icmp_eq_v8i8_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.8b, v0.8b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v8i8_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.8b, v1.8b, v0.8b +; CHECK-GI-NEXT: ret + %c = icmp eq <8 x i8> , %a + ret <8 x i1> %c +} + +define <16 x i1> @icmp_eq_v16i8_Zero_LHS(<16 x i8> %a) { +; CHECK-SD-LABEL: icmp_eq_v16i8_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.16b, v0.16b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v16i8_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.16b, v1.16b, v0.16b +; CHECK-GI-NEXT: ret + %c = icmp eq <16 x i8> , %a + ret <16 x i1> %c +} + +define <4 x i1> @icmp_eq_v4i16_Zero_LHS(<4 x i16> %a) { +; CHECK-SD-LABEL: icmp_eq_v4i16_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.4h, v0.4h, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v4i16_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.4h, v1.4h, v0.4h +; CHECK-GI-NEXT: ret + %c = icmp eq <4 x i16> , %a + ret <4 x i1> %c +} + +define <8 x i1> @icmp_eq_v8i16_Zero_LHS(<8 x i16> %a) { +; CHECK-SD-LABEL: icmp_eq_v8i16_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.8h, v0.8h, #0 +; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v8i16_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.8h, v1.8h, v0.8h +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: ret + %c = icmp eq <8 x i16> , %a + ret <8 x i1> %c +} + +define <2 x i1> @icmp_eq_v2i32_Zero_LHS(<2 x i32> %a) { +; CHECK-SD-LABEL: icmp_eq_v2i32_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.2s, v0.2s, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v2i32_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.2s, v1.2s, v0.2s +; CHECK-GI-NEXT: ret + %c = icmp eq <2 x i32> , %a + ret <2 x i1> %c +} + +define <4 x i1> @icmp_eq_v4i32_Zero_LHS(<4 x i32> %a) { +; CHECK-SD-LABEL: icmp_eq_v4i32_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0 +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v4i32_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.4s, v1.4s, v0.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret + %c = icmp eq <4 x i32> , %a + ret <4 x i1> %c +} + +define <2 x i1> @icmp_eq_v2i64_Zero_LHS(<2 x i64> %a) { +; CHECK-SD-LABEL: icmp_eq_v2i64_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmeq v0.2d, v0.2d, #0 +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_eq_v2i64_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmeq v0.2d, v1.2d, v0.2d +; CHECK-GI-NEXT: xtn v0.2s, v0.2d +; CHECK-GI-NEXT: ret + %c = icmp eq <2 x i64> , %a + ret <2 x i1> %c +} + +define <8 x i1> @icmp_sge_v8i8_Zero_LHS(<8 x i8> %a) { +; CHECK-SD-LABEL: icmp_sge_v8i8_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.8b, v0.8b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v8i8_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.8b, v1.8b, v0.8b +; CHECK-GI-NEXT: ret + %c = icmp sge <8 x i8> , %a + ret <8 x i1> %c +} + +define <16 x i1> @icmp_sge_v16i8_Zero_LHS(<16 x i8> %a) { +; CHECK-SD-LABEL: icmp_sge_v16i8_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.16b, v0.16b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v16i8_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.16b, v1.16b, v0.16b +; CHECK-GI-NEXT: ret + %c = icmp sge <16 x i8> , %a + ret <16 x i1> %c +} + +define <4 x i1> @icmp_sge_v4i16_Zero_LHS(<4 x i16> %a) { +; CHECK-SD-LABEL: icmp_sge_v4i16_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.4h, v0.4h, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v4i16_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.4h, v1.4h, v0.4h +; CHECK-GI-NEXT: ret + %c = icmp sge <4 x i16> , %a + ret <4 x i1> %c +} + +define <8 x i1> @icmp_sge_v8i16_Zero_LHS(<8 x i16> %a) { +; CHECK-SD-LABEL: icmp_sge_v8i16_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.8h, v0.8h, #0 +; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v8i16_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.8h, v1.8h, v0.8h +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: ret + %c = icmp sge <8 x i16> , %a + ret <8 x i1> %c +} + +define <2 x i1> @icmp_sge_v2i32_Zero_LHS(<2 x i32> %a) { +; CHECK-SD-LABEL: icmp_sge_v2i32_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.2s, v0.2s, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v2i32_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.2s, v1.2s, v0.2s +; CHECK-GI-NEXT: ret + %c = icmp sge <2 x i32> , %a + ret <2 x i1> %c +} + +define <4 x i1> @icmp_sge_v4i32_Zero_LHS(<4 x i32> %a) { +; CHECK-SD-LABEL: icmp_sge_v4i32_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.4s, v0.4s, #0 +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v4i32_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.4s, v1.4s, v0.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret + %c = icmp sge <4 x i32> , %a + ret <4 x i1> %c +} + +define <2 x i1> @icmp_sge_v2i64_Zero_LHS(<2 x i64> %a) { +; CHECK-SD-LABEL: icmp_sge_v2i64_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmle v0.2d, v0.2d, #0 +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sge_v2i64_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.2d, v1.2d, v0.2d +; CHECK-GI-NEXT: xtn v0.2s, v0.2d +; CHECK-GI-NEXT: ret + %c = icmp sge <2 x i64> , %a + ret <2 x i1> %c +} + +define <8 x i1> @icmp_sgt_v8i8_Zero_LHS(<8 x i8> %a) { +; CHECK-SD-LABEL: icmp_sgt_v8i8_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.8b, v0.8b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v8i8_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.8b, v1.8b, v0.8b +; CHECK-GI-NEXT: ret + %c = icmp sgt <8 x i8> , %a + ret <8 x i1> %c +} + +define <16 x i1> @icmp_sgt_v16i8_Zero_LHS(<16 x i8> %a) { +; CHECK-SD-LABEL: icmp_sgt_v16i8_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.16b, v0.16b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v16i8_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.16b, v1.16b, v0.16b +; CHECK-GI-NEXT: ret + %c = icmp sgt <16 x i8> , %a + ret <16 x i1> %c +} + +define <4 x i1> @icmp_sgt_v4i16_Zero_LHS(<4 x i16> %a) { +; CHECK-SD-LABEL: icmp_sgt_v4i16_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.4h, v0.4h, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v4i16_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.4h, v1.4h, v0.4h +; CHECK-GI-NEXT: ret + %c = icmp sgt <4 x i16> , %a + ret <4 x i1> %c +} + +define <8 x i1> @icmp_sgt_v8i16_Zero_LHS(<8 x i16> %a) { +; CHECK-SD-LABEL: icmp_sgt_v8i16_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.8h, v0.8h, #0 +; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v8i16_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.8h, v1.8h, v0.8h +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: ret + %c = icmp sgt <8 x i16> , %a + ret <8 x i1> %c +} + +define <2 x i1> @icmp_sgt_v2i32_Zero_LHS(<2 x i32> %a) { +; CHECK-SD-LABEL: icmp_sgt_v2i32_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.2s, v0.2s, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v2i32_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.2s, v1.2s, v0.2s +; CHECK-GI-NEXT: ret + %c = icmp sgt <2 x i32> , %a + ret <2 x i1> %c +} + +define <4 x i1> @icmp_sgt_v4i32_Zero_LHS(<4 x i32> %a) { +; CHECK-SD-LABEL: icmp_sgt_v4i32_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.4s, v0.4s, #0 +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v4i32_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.4s, v1.4s, v0.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret + %c = icmp sgt <4 x i32> , %a + ret <4 x i1> %c +} + +define <2 x i1> @icmp_sgt_v2i64_Zero_LHS(<2 x i64> %a) { +; CHECK-SD-LABEL: icmp_sgt_v2i64_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmlt v0.2d, v0.2d, #0 +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sgt_v2i64_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.2d, v1.2d, v0.2d +; CHECK-GI-NEXT: xtn v0.2s, v0.2d +; CHECK-GI-NEXT: ret + %c = icmp sgt <2 x i64> , %a + ret <2 x i1> %c +} + +define <8 x i1> @icmp_sle_v8i8_Zero_LHS(<8 x i8> %a) { +; CHECK-SD-LABEL: icmp_sle_v8i8_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.8b, v0.8b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v8i8_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.8b, v0.8b, v1.8b +; CHECK-GI-NEXT: ret + %c = icmp sle <8 x i8> , %a + ret <8 x i1> %c +} + +define <16 x i1> @icmp_sle_v16i8_Zero_LHS(<16 x i8> %a) { +; CHECK-SD-LABEL: icmp_sle_v16i8_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.16b, v0.16b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v16i8_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.16b, v0.16b, v1.16b +; CHECK-GI-NEXT: ret + %c = icmp sle <16 x i8> , %a + ret <16 x i1> %c +} + +define <4 x i1> @icmp_sle_v4i16_Zero_LHS(<4 x i16> %a) { +; CHECK-SD-LABEL: icmp_sle_v4i16_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.4h, v0.4h, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v4i16_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.4h, v0.4h, v1.4h +; CHECK-GI-NEXT: ret + %c = icmp sle <4 x i16> , %a + ret <4 x i1> %c +} + +define <8 x i1> @icmp_sle_v8i16_Zero_LHS(<8 x i16> %a) { +; CHECK-SD-LABEL: icmp_sle_v8i16_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.8h, v0.8h, #0 +; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v8i16_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.8h, v0.8h, v1.8h +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: ret + %c = icmp sle <8 x i16> , %a + ret <8 x i1> %c +} + +define <2 x i1> @icmp_sle_v2i32_Zero_LHS(<2 x i32> %a) { +; CHECK-SD-LABEL: icmp_sle_v2i32_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.2s, v0.2s, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v2i32_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: ret + %c = icmp sle <2 x i32> , %a + ret <2 x i1> %c +} + +define <4 x i1> @icmp_sle_v4i32_Zero_LHS(<4 x i32> %a) { +; CHECK-SD-LABEL: icmp_sle_v4i32_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.4s, v0.4s, #0 +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v4i32_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret + %c = icmp sle <4 x i32> , %a + ret <4 x i1> %c +} + +define <2 x i1> @icmp_sle_v2i64_Zero_LHS(<2 x i64> %a) { +; CHECK-SD-LABEL: icmp_sle_v2i64_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmge v0.2d, v0.2d, #0 +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_sle_v2i64_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmge v0.2d, v0.2d, v1.2d +; CHECK-GI-NEXT: xtn v0.2s, v0.2d +; CHECK-GI-NEXT: ret + %c = icmp sle <2 x i64> , %a + ret <2 x i1> %c +} + +define <8 x i1> @icmp_slt_v8i8_Zero_LHS(<8 x i8> %a) { +; CHECK-SD-LABEL: icmp_slt_v8i8_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.8b, v0.8b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v8i8_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.8b, v0.8b, v1.8b +; CHECK-GI-NEXT: ret + %c = icmp slt <8 x i8> , %a + ret <8 x i1> %c +} + +define <16 x i1> @icmp_slt_v16i8_Zero_LHS(<16 x i8> %a) { +; CHECK-SD-LABEL: icmp_slt_v16i8_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.16b, v0.16b, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v16i8_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.16b, v0.16b, v1.16b +; CHECK-GI-NEXT: ret + %c = icmp slt <16 x i8> , %a + ret <16 x i1> %c +} + +define <4 x i1> @icmp_slt_v4i16_Zero_LHS(<4 x i16> %a) { +; CHECK-SD-LABEL: icmp_slt_v4i16_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.4h, v0.4h, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v4i16_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.4h, v0.4h, v1.4h +; CHECK-GI-NEXT: ret + %c = icmp slt <4 x i16> , %a + ret <4 x i1> %c +} + +define <8 x i1> @icmp_slt_v8i16_Zero_LHS(<8 x i16> %a) { +; CHECK-SD-LABEL: icmp_slt_v8i16_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.8h, v0.8h, #0 +; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v8i16_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.8h, v0.8h, v1.8h +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: ret + %c = icmp slt <8 x i16> , %a + ret <8 x i1> %c +} + +define <2 x i1> @icmp_slt_v2i32_Zero_LHS(<2 x i32> %a) { +; CHECK-SD-LABEL: icmp_slt_v2i32_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.2s, v0.2s, #0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v2i32_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: ret + %c = icmp slt <2 x i32> , %a + ret <2 x i1> %c +} + +define <4 x i1> @icmp_slt_v4i32_Zero_LHS(<4 x i32> %a) { +; CHECK-SD-LABEL: icmp_slt_v4i32_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.4s, v0.4s, #0 +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v4i32_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret + %c = icmp slt <4 x i32> , %a + ret <4 x i1> %c +} + +define <2 x i1> @icmp_slt_v2i64_Zero_LHS(<2 x i64> %a) { +; CHECK-SD-LABEL: icmp_slt_v2i64_Zero_LHS: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmgt v0.2d, v0.2d, #0 +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: icmp_slt_v2i64_Zero_LHS: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-NEXT: cmgt v0.2d, v0.2d, v1.2d +; CHECK-GI-NEXT: xtn v0.2s, v0.2d +; CHECK-GI-NEXT: ret + %c = icmp slt <2 x i64> , %a + ret <2 x i1> %c +} -- GitLab From c4a9a374749deb5f2a932a7d4ef9321be1b2ae5d Mon Sep 17 00:00:00 2001 From: erichkeane Date: Thu, 9 May 2024 09:44:35 -0700 Subject: [PATCH 074/578] [OpenACC] device_type clause Sema for Compute constructs device_type, also spelled as dtype, specifies the applicability of the clauses following it, and takes a series of identifiers representing the architectures it applies to. As we don't have a source for the valid architectures yet, this patch just accepts all. Semantically, this also limits the list of clauses that can be applied after the device_type, so this implements that as well. --- clang/include/clang/AST/OpenACCClause.h | 59 +++++ .../clang/Basic/DiagnosticSemaKinds.td | 4 + clang/include/clang/Basic/OpenACCClauses.def | 2 + clang/include/clang/Parse/Parser.h | 3 +- clang/include/clang/Sema/SemaOpenACC.h | 23 +- clang/lib/AST/OpenACCClause.cpp | 28 ++- clang/lib/AST/StmtProfile.cpp | 3 + clang/lib/AST/TextNodeDumper.cpp | 13 ++ clang/lib/Parse/ParseOpenACC.cpp | 21 +- clang/lib/Sema/SemaOpenACC.cpp | 55 +++++ clang/lib/Sema/TreeTransform.h | 10 + clang/lib/Serialization/ASTReader.cpp | 17 +- clang/lib/Serialization/ASTWriter.cpp | 15 +- .../ast-print-openacc-compute-construct.cpp | 23 ++ clang/test/ParserOpenACC/parse-clauses.c | 28 +-- .../compute-construct-device_type-ast.cpp | 105 +++++++++ .../compute-construct-device_type-clause.c | 221 ++++++++++++++++++ .../compute-construct-device_type-clause.cpp | 25 ++ clang/tools/libclang/CIndex.cpp | 2 + 19 files changed, 622 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp create mode 100644 clang/test/SemaOpenACC/compute-construct-device_type-clause.c create mode 100644 clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 3d0b1ab9d31e..3998a3430ff9 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -17,6 +17,8 @@ #include "clang/AST/StmtIterator.h" #include "clang/Basic/OpenACCKinds.h" +#include + namespace clang { /// This is the base type for all OpenACC Clauses. class OpenACCClause { @@ -75,6 +77,63 @@ public: } }; +using DeviceTypeArgument = std::pair; +/// A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or +/// an identifier. The 'asterisk' means 'the rest'. +class OpenACCDeviceTypeClause final + : public OpenACCClauseWithParams, + public llvm::TrailingObjects { + // Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A + // nullptr IdentifierInfo* represents an asterisk. + unsigned NumArchs; + OpenACCDeviceTypeClause(OpenACCClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, + ArrayRef Archs, + SourceLocation EndLoc) + : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc), + NumArchs(Archs.size()) { + assert( + (K == OpenACCClauseKind::DeviceType || K == OpenACCClauseKind::DType) && + "Invalid clause kind for device-type"); + + assert(!llvm::any_of(Archs, [](const DeviceTypeArgument &Arg) { + return Arg.second.isInvalid(); + }) && "Invalid SourceLocation for an argument"); + + assert(Archs.size() == 1 || + !llvm::any_of(Archs, + [](const DeviceTypeArgument &Arg) { + return Arg.first == nullptr; + }) && + "Only a single asterisk version is permitted, and must be the " + "only one"); + + std::uninitialized_copy(Archs.begin(), Archs.end(), + getTrailingObjects()); + } + +public: + static bool classof(const OpenACCClause *C) { + return C->getClauseKind() == OpenACCClauseKind::DType || + C->getClauseKind() == OpenACCClauseKind::DeviceType; + } + bool hasAsterisk() const { + return getArchitectures().size() > 0 && + getArchitectures()[0].first == nullptr; + } + + ArrayRef getArchitectures() const { + return ArrayRef( + getTrailingObjects(), NumArchs); + } + + static OpenACCDeviceTypeClause * + Create(const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, ArrayRef Archs, + SourceLocation EndLoc); +}; + /// A 'default' clause, has the optional 'none' or 'present' argument. class OpenACCDefaultClause : public OpenACCClauseWithParams { friend class ASTReaderStmt; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9e82130c9360..6100fba51005 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12344,4 +12344,8 @@ def warn_acc_deprecated_alias_name def err_acc_var_not_pointer_type : Error<"expected pointer in '%0' clause, type is %1">; def note_acc_expected_pointer_var : Note<"expected variable of pointer type">; +def err_acc_clause_after_device_type + : Error<"OpenACC clause '%0' may not follow a '%1' clause in a " + "compute construct">; + } // end of sema component. diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def index afb7b30b7465..7ecc51799468 100644 --- a/clang/include/clang/Basic/OpenACCClauses.def +++ b/clang/include/clang/Basic/OpenACCClauses.def @@ -37,6 +37,8 @@ CLAUSE_ALIAS(PCreate, Create) CLAUSE_ALIAS(PresentOrCreate, Create) VISIT_CLAUSE(Default) VISIT_CLAUSE(DevicePtr) +VISIT_CLAUSE(DeviceType) +CLAUSE_ALIAS(DType, DeviceType) VISIT_CLAUSE(FirstPrivate) VISIT_CLAUSE(If) VISIT_CLAUSE(NoCreate) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 61589fb7766f..3910cba34a21 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3720,7 +3720,8 @@ private: SourceLocation Loc, llvm::SmallVectorImpl &IntExprs); /// Parses the 'device-type-list', which is a list of identifiers. - bool ParseOpenACCDeviceTypeList(); + bool ParseOpenACCDeviceTypeList( + llvm::SmallVector> &Archs); /// Parses the 'async-argument', which is an integral value with two /// 'special' values that are likely negative (but come from Macros). OpenACCIntExprParseResult ParseOpenACCAsyncArgument(OpenACCDirectiveKind DK, diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index e684ee6b2be1..f838fa97d33a 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -26,6 +26,9 @@ class OpenACCClause; class SemaOpenACC : public SemaBase { public: + // Redeclaration of the version in OpenACCClause.h. + using DeviceTypeArgument = std::pair; + /// A type to represent all the data for an OpenACC Clause that has been /// parsed, but not yet created/semantically analyzed. This is effectively a /// discriminated union on the 'Clause Kind', with all of the individual @@ -60,8 +63,12 @@ public: SmallVector QueueIdExprs; }; + struct DeviceTypeDetails { + SmallVector Archs; + }; + std::variant + IntExprDetails, VarListDetails, WaitDetails, DeviceTypeDetails> Details = std::monostate{}; public: @@ -209,6 +216,13 @@ public: return std::get(Details).IsZero; } + ArrayRef getDeviceTypeArchitectures() const { + assert((ClauseKind == OpenACCClauseKind::DeviceType || + ClauseKind == OpenACCClauseKind::DType) && + "Only 'device_type'/'dtype' has a device-type-arg list"); + return std::get(Details).Archs; + } + void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; } void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); } @@ -326,6 +340,13 @@ public: "Parsed clause kind does not have a wait-details"); Details = WaitDetails{DevNum, QueuesLoc, std::move(IntExprs)}; } + + void setDeviceTypeDetails(llvm::SmallVector &&Archs) { + assert((ClauseKind == OpenACCClauseKind::DeviceType || + ClauseKind == OpenACCClauseKind::DType) && + "Only 'device_type'/'dtype' has a device-type-arg list"); + Details = DeviceTypeDetails{std::move(Archs)}; + } }; SemaOpenACC(Sema &S); diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index ee13437b97b4..f80ecc90d396 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -18,7 +18,8 @@ using namespace clang; bool OpenACCClauseWithParams::classof(const OpenACCClause *C) { - return OpenACCClauseWithCondition::classof(C) || + return OpenACCDeviceTypeClause::classof(C) || + OpenACCClauseWithCondition::classof(C) || OpenACCClauseWithExprs::classof(C); } bool OpenACCClauseWithExprs::classof(const OpenACCClause *C) { @@ -298,6 +299,17 @@ OpenACCCreateClause::Create(const ASTContext &C, OpenACCClauseKind Spelling, VarList, EndLoc); } +OpenACCDeviceTypeClause *OpenACCDeviceTypeClause::Create( + const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, ArrayRef Archs, + SourceLocation EndLoc) { + void *Mem = + C.Allocate(OpenACCDeviceTypeClause::totalSizeToAlloc( + Archs.size())); + return new (Mem) + OpenACCDeviceTypeClause(K, BeginLoc, LParenLoc, Archs, EndLoc); +} + //===----------------------------------------------------------------------===// // OpenACC clauses printing methods //===----------------------------------------------------------------------===// @@ -451,3 +463,17 @@ void OpenACCClausePrinter::VisitWaitClause(const OpenACCWaitClause &C) { OS << ")"; } } + +void OpenACCClausePrinter::VisitDeviceTypeClause( + const OpenACCDeviceTypeClause &C) { + OS << C.getClauseKind(); + OS << "("; + llvm::interleaveComma(C.getArchitectures(), OS, + [&](const DeviceTypeArgument &Arch) { + if (Arch.first == nullptr) + OS << "*"; + else + OS << Arch.first; + }); + OS << ")"; +} diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 8fb8940142eb..caab4ab0ef16 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2585,6 +2585,9 @@ void OpenACCClauseProfiler::VisitWaitClause(const OpenACCWaitClause &Clause) { for (auto *E : Clause.getQueueIdExprs()) Profiler.VisitStmt(E); } +/// Nothing to do here, there are no sub-statements. +void OpenACCClauseProfiler::VisitDeviceTypeClause( + const OpenACCDeviceTypeClause &Clause) {} } // namespace void StmtProfiler::VisitOpenACCComputeConstruct( diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 12aa5858b798..efcd74717a4e 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -444,6 +444,19 @@ void TextNodeDumper::Visit(const OpenACCClause *C) { if (cast(C)->hasQueuesTag()) OS << " has queues tag"; break; + case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DType: + OS << "("; + llvm::interleaveComma( + cast(C)->getArchitectures(), OS, + [&](const DeviceTypeArgument &Arch) { + if (Arch.first == nullptr) + OS << "*"; + else + OS << Arch.first->getName(); + }); + OS << ")"; + break; default: // Nothing to do here. break; diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 0e10632c8317..261c9cdc088b 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -711,14 +711,15 @@ bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK, /// device_type( device-type-list ) /// /// The device_type clause may be abbreviated to dtype. -bool Parser::ParseOpenACCDeviceTypeList() { +bool Parser::ParseOpenACCDeviceTypeList( + llvm::SmallVector> &Archs) { if (expectIdentifierOrKeyword(*this)) { SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, Parser::StopBeforeMatch); - return false; + return true; } - ConsumeToken(); + Archs.emplace_back(getCurToken().getIdentifierInfo(), ConsumeToken()); while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { ExpectAndConsume(tok::comma); @@ -726,9 +727,9 @@ bool Parser::ParseOpenACCDeviceTypeList() { if (expectIdentifierOrKeyword(*this)) { SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, Parser::StopBeforeMatch); - return false; + return true; } - ConsumeToken(); + Archs.emplace_back(getCurToken().getIdentifierInfo(), ConsumeToken()); } return false; } @@ -1021,16 +1022,20 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( break; } case OpenACCClauseKind::DType: - case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DeviceType: { + llvm::SmallVector> Archs; if (getCurToken().is(tok::star)) { // FIXME: We want to mark that this is an 'everything else' type of // device_type in Sema. - ConsumeToken(); - } else if (ParseOpenACCDeviceTypeList()) { + ParsedClause.setDeviceTypeDetails({{nullptr, ConsumeToken()}}); + } else if (!ParseOpenACCDeviceTypeList(Archs)) { + ParsedClause.setDeviceTypeDetails(std::move(Archs)); + } else { Parens.skipToEnd(); return OpenACCCanContinue(); } break; + } case OpenACCClauseKind::Tile: if (ParseOpenACCSizeExprList()) { Parens.skipToEnd(); diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 656d30947a8d..f174b2fa63c6 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -255,6 +255,33 @@ bool checkAlreadyHasClauseOfKind( return false; } +/// Implement check from OpenACC3.3: section 2.5.4: +/// Only the async, wait, num_gangs, num_workers, and vector_length clauses may +/// follow a device_type clause. +bool checkValidAfterDeviceType( + SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause, + const SemaOpenACC::OpenACCParsedClause &NewClause) { + // This is only a requirement on compute constructs so far, so this is fine + // otherwise. + if (!isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind())) + return false; + switch (NewClause.getClauseKind()) { + case OpenACCClauseKind::Async: + case OpenACCClauseKind::Wait: + case OpenACCClauseKind::NumGangs: + case OpenACCClauseKind::NumWorkers: + case OpenACCClauseKind::VectorLength: + case OpenACCClauseKind::DType: + case OpenACCClauseKind::DeviceType: + return false; + default: + S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type) + << NewClause.getClauseKind() << DeviceTypeClause.getClauseKind(); + S.Diag(DeviceTypeClause.getBeginLoc(), diag::note_acc_previous_clause_here); + return true; + } +} + } // namespace SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {} @@ -273,6 +300,17 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, return nullptr; } + if (const auto *DevTypeClause = + llvm::find_if(ExistingClauses, + [&](const OpenACCClause *C) { + return isa(C); + }); + DevTypeClause != ExistingClauses.end()) { + if (checkValidAfterDeviceType( + *this, *cast(*DevTypeClause), Clause)) + return nullptr; + } + switch (Clause.getClauseKind()) { case OpenACCClauseKind::Default: { // Restrictions only properly implemented on 'compute' constructs, and @@ -651,6 +689,23 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, Clause.getDevNumExpr(), Clause.getQueuesLoc(), Clause.getQueueIdExprs(), Clause.getEndLoc()); } + case OpenACCClauseKind::DType: + case OpenACCClauseKind::DeviceType: { + // Restrictions only properly implemented on 'compute' constructs, and + // 'compute' constructs are the only construct that can do anything with + // this yet, so skip/treat as unimplemented in this case. + if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) + break; + + // TODO OpenACC: Once we get enough of the CodeGen implemented that we have + // a source for the list of valid architectures, we need to warn on unknown + // identifiers here. + + return OpenACCDeviceTypeClause::Create( + getASTContext(), Clause.getClauseKind(), Clause.getBeginLoc(), + Clause.getLParenLoc(), Clause.getDeviceTypeArchitectures(), + Clause.getEndLoc()); + } default: break; } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 126965088831..ab26d1b1199a 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -11480,6 +11480,16 @@ void OpenACCClauseTransform::VisitWaitClause( ParsedClause.getQueuesLoc(), ParsedClause.getQueueIdExprs(), ParsedClause.getEndLoc()); } + +template +void OpenACCClauseTransform::VisitDeviceTypeClause( + const OpenACCDeviceTypeClause &C) { + // Nothing to transform here, just create a new version of 'C'. + NewClause = OpenACCDeviceTypeClause::Create( + Self.getSema().getASTContext(), C.getClauseKind(), + ParsedClause.getBeginLoc(), ParsedClause.getLParenLoc(), + C.getArchitectures(), ParsedClause.getEndLoc()); +} } // namespace template OpenACCClause *TreeTransform::TransformOpenACCClause( diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 7627996d2c32..8f437a7c5f50 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11905,6 +11905,21 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { DevNumExpr, QueuesLoc, QueueIdExprs, EndLoc); } + case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DType: { + SourceLocation LParenLoc = readSourceLocation(); + llvm::SmallVector Archs; + unsigned NumArchs = readInt(); + + for (unsigned I = 0; I < NumArchs; ++I) { + IdentifierInfo *Ident = readBool() ? readIdentifier() : nullptr; + SourceLocation Loc = readSourceLocation(); + Archs.emplace_back(Ident, Loc); + } + + return OpenACCDeviceTypeClause::Create(getContext(), ClauseKind, BeginLoc, + LParenLoc, Archs, EndLoc); + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: @@ -11926,8 +11941,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { case OpenACCClauseKind::Bind: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: - case OpenACCClauseKind::DeviceType: - case OpenACCClauseKind::DType: case OpenACCClauseKind::Tile: case OpenACCClauseKind::Gang: case OpenACCClauseKind::Invalid: diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 6154ead589d3..7a9d392889bb 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7933,6 +7933,19 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeOpenACCIntExprList(WC->getQueueIdExprs()); return; } + case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DType: { + const auto *DTC = cast(C); + writeSourceLocation(DTC->getLParenLoc()); + writeUInt32(DTC->getArchitectures().size()); + for (const DeviceTypeArgument &Arg : DTC->getArchitectures()) { + writeBool(Arg.first); + if (Arg.first) + AddIdentifierRef(Arg.first); + writeSourceLocation(Arg.second); + } + return; + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: @@ -7954,8 +7967,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::Bind: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: - case OpenACCClauseKind::DeviceType: - case OpenACCClauseKind::DType: case OpenACCClauseKind::Tile: case OpenACCClauseKind::Gang: case OpenACCClauseKind::Invalid: diff --git a/clang/test/AST/ast-print-openacc-compute-construct.cpp b/clang/test/AST/ast-print-openacc-compute-construct.cpp index 0bfb90bcb587..cdd9ab3377d0 100644 --- a/clang/test/AST/ast-print-openacc-compute-construct.cpp +++ b/clang/test/AST/ast-print-openacc-compute-construct.cpp @@ -107,5 +107,28 @@ void foo() { // CHECK: #pragma acc parallel wait(devnum: i : queues: *iPtr, i) #pragma acc parallel wait(devnum:i:queues:*iPtr, i) while(true); + + bool SomeB; + struct SomeStruct{} SomeStructImpl; + +//#pragma acc parallel dtype(SomeB) +#pragma acc parallel dtype(SomeB) + while(true); + +//#pragma acc parallel device_type(SomeStruct) +#pragma acc parallel device_type(SomeStruct) + while(true); + +//#pragma acc parallel device_type(int) +#pragma acc parallel device_type(int) + while(true); + +//#pragma acc parallel dtype(bool) +#pragma acc parallel dtype(bool) + while(true); + +//#pragma acc parallel device_type (SomeStructImpl) +#pragma acc parallel device_type (SomeStructImpl) + while(true); } diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index 51858b441e93..694f28b86ec9 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -1126,12 +1126,10 @@ void device_type() { #pragma acc parallel dtype( {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel device_type() {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel dtype() {} @@ -1173,12 +1171,10 @@ void device_type() { #pragma acc parallel dtype(ident, ident2 {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel device_type(ident, ident2,) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel dtype(ident, ident2,) {} @@ -1200,33 +1196,25 @@ void device_type() { #pragma acc parallel dtype(*,ident) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel device_type(ident, *) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel dtype(ident, *) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel device_type("foo", 54) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel dtype(31, "bar") {} - // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} #pragma acc parallel device_type(ident, auto, int, float) {} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} #pragma acc parallel dtype(ident, auto, int, float) {} - // expected-warning@+2{{OpenACC clause 'device_type' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} #pragma acc parallel device_type(ident, auto, int, float) dtype(ident, auto, int, float) {} } diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp b/clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp new file mode 100644 index 000000000000..8a2423f4f542 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp @@ -0,0 +1,105 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s +#ifndef PCH_HELPER +#define PCH_HELPER + +struct SomeS{}; +void NormalUses() { + // CHECK: FunctionDecl{{.*}}NormalUses + // CHECK-NEXT: CompoundStmt + + SomeS SomeImpl; + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} SomeImpl 'SomeS' + // CHECK-NEXT: CXXConstructExpr + bool SomeVar; + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} SomeVar 'bool' + +#pragma acc parallel device_type(SomeS) dtype(SomeImpl) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(SomeS) + // CHECK-NEXT: dtype(SomeImpl) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(SomeVar) dtype(int) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(SomeVar) + // CHECK-NEXT: dtype(int) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(private) dtype(struct) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(private) + // CHECK-NEXT: dtype(struct) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(private) dtype(class) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(private) + // CHECK-NEXT: dtype(class) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(float) dtype(*) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(float) + // CHECK-NEXT: dtype(*) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(float, int) dtype(*) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(float, int) + // CHECK-NEXT: dtype(*) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +} + +template +void TemplUses() { + // CHECK-NEXT: FunctionTemplateDecl{{.*}}TemplUses + // CHECK-NEXT: TemplateTypeParmDecl{{.*}}T + // CHECK-NEXT: FunctionDecl{{.*}}TemplUses + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(T) dtype(T) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: dtype(T) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + + // Instantiations + // CHECK-NEXT: FunctionDecl{{.*}} TemplUses 'void ()' implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'int' + // CHECK-NEXT: BuiltinType{{.*}} 'int' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: dtype(T) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +} + +void Inst() { + TemplUses(); +} +#endif // PCH_HELPER diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-clause.c b/clang/test/SemaOpenACC/compute-construct-device_type-clause.c new file mode 100644 index 000000000000..15c9cf396c80 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-device_type-clause.c @@ -0,0 +1,221 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +#define MACRO +FOO + +void uses() { + typedef struct S{} STy; + STy SImpl; + +#pragma acc parallel device_type(I) + while(1); +#pragma acc serial device_type(S) dtype(STy) + while(1); +#pragma acc kernels dtype(SImpl) + while(1); +#pragma acc kernels dtype(int) device_type(*) + while(1); +#pragma acc kernels dtype(true) device_type(false) + while(1); + + // expected-error@+1{{expected identifier}} +#pragma acc kernels dtype(int, *) + while(1); + +#pragma acc parallel device_type(I, int) + while(1); + // expected-error@+2{{expected ','}} + // expected-error@+1{{expected identifier}} +#pragma acc kernels dtype(int{}) + while(1); + // expected-error@+1{{expected identifier}} +#pragma acc kernels dtype(5) + while(1); + // expected-error@+1{{expected identifier}} +#pragma acc kernels dtype(MACRO) + while(1); + + + // Only 'async', 'wait', num_gangs', 'num_workers', 'vector_length' allowed after 'device_type'. + + // expected-error@+2{{OpenACC clause 'finalize' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) finalize + while(1); + // expected-error@+2{{OpenACC clause 'if_present' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) if_present + while(1); + // expected-error@+2{{OpenACC clause 'seq' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) seq + while(1); + // expected-error@+2{{OpenACC clause 'independent' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) independent + while(1); + // expected-error@+2{{OpenACC clause 'auto' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) auto + while(1); + // expected-error@+2{{OpenACC clause 'worker' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) worker + while(1); + // expected-error@+2{{OpenACC clause 'nohost' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) nohost + while(1); + // expected-error@+2{{OpenACC clause 'default' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) default(none) + while(1); + // expected-error@+2{{OpenACC clause 'if' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) if(1) + while(1); + // expected-error@+2{{OpenACC clause 'self' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) self + while(1); + + int Var; + int *VarPtr; + // expected-error@+2{{OpenACC clause 'copy' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) copy(Var) + while(1); + // expected-error@+2{{OpenACC clause 'pcopy' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) pcopy(Var) + while(1); + // expected-error@+2{{OpenACC clause 'present_or_copy' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) present_or_copy(Var) + while(1); + // expected-error@+2{{OpenACC clause 'use_device' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) use_device(Var) + while(1); + // expected-error@+2{{OpenACC clause 'attach' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) attach(Var) + while(1); + // expected-error@+2{{OpenACC clause 'delete' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) delete(Var) + while(1); + // expected-error@+2{{OpenACC clause 'detach' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) detach(Var) + while(1); + // expected-error@+2{{OpenACC clause 'device' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) device(VarPtr) + while(1); + // expected-error@+2{{OpenACC clause 'deviceptr' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) deviceptr(VarPtr) + while(1); + // expected-error@+2{{OpenACC clause 'device_resident' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) device_resident(VarPtr) + while(1); + // expected-error@+2{{OpenACC clause 'firstprivate' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel device_type(*) firstprivate(Var) + while(1); + // expected-error@+2{{OpenACC clause 'host' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) host(Var) + while(1); + // expected-error@+2{{OpenACC clause 'link' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) link(Var) + while(1); + // expected-error@+2{{OpenACC clause 'no_create' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) no_create(Var) + while(1); + // expected-error@+2{{OpenACC clause 'present' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) present(Var) + while(1); + // expected-error@+2{{OpenACC clause 'private' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel device_type(*) private(Var) + while(1); + // expected-error@+2{{OpenACC clause 'copyout' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) copyout(Var) + while(1); + // expected-error@+2{{OpenACC clause 'pcopyout' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) pcopyout(Var) + while(1); + // expected-error@+2{{OpenACC clause 'present_or_copyout' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) present_or_copyout(Var) + while(1); + // expected-error@+2{{OpenACC clause 'copyin' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) copyin(Var) + while(1); + // expected-error@+2{{OpenACC clause 'pcopyin' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) pcopyin(Var) + while(1); + // expected-error@+2{{OpenACC clause 'present_or_copyin' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) present_or_copyin(Var) + while(1); + // expected-error@+2{{OpenACC clause 'create' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) create(Var) + while(1); + // expected-error@+2{{OpenACC clause 'pcreate' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) pcreate(Var) + while(1); + // expected-error@+2{{OpenACC clause 'present_or_create' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) present_or_create(Var) + while(1); + // expected-error@+2{{OpenACC clause 'reduction' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) reduction(+:Var) + while(1); + // expected-error@+2{{OpenACC clause 'collapse' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) collapse(1) + while(1); + // expected-error@+2{{OpenACC clause 'bind' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) bind(Var) + while(1); +#pragma acc kernels device_type(*) vector_length(1) + while(1); +#pragma acc kernels device_type(*) num_gangs(1) + while(1); +#pragma acc kernels device_type(*) num_workers(1) + while(1); + // expected-error@+2{{OpenACC clause 'device_num' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) device_num(1) + while(1); + // expected-error@+2{{OpenACC clause 'default_async' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) default_async(1) + while(1); +#pragma acc kernels device_type(*) async + while(1); + // expected-error@+2{{OpenACC clause 'tile' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) tile(Var, 1) + while(1); + // expected-error@+2{{OpenACC clause 'gang' may not follow a 'dtype' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels dtype(*) gang + while(1); +#pragma acc kernels device_type(*) wait + while(1); +} diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp b/clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp new file mode 100644 index 000000000000..ed40e8bbceae --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +template +void TemplUses() { +#pragma acc parallel device_type(I) + while(true); +#pragma acc parallel dtype(*) + while(true); +#pragma acc parallel device_type(class) + while(true); +#pragma acc parallel device_type(private) + while(true); +#pragma acc parallel device_type(bool) + while(true); +#pragma acc kernels dtype(true) device_type(false) + while(true); + // expected-error@+2{{expected ','}} + // expected-error@+1{{expected identifier}} +#pragma acc parallel device_type(T::value) + while(true); +} + +void Inst() { + TemplUses(); // #INST +} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index ae6659fe95e8..8b9417f985b5 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2857,6 +2857,8 @@ void OpenACCClauseEnqueue::VisitWaitClause(const OpenACCWaitClause &C) { for (Expr *QE : C.getQueueIdExprs()) Visitor.AddStmt(QE); } +void OpenACCClauseEnqueue::VisitDeviceTypeClause( + const OpenACCDeviceTypeClause &C) {} } // namespace void EnqueueVisitor::EnqueueChildren(const OpenACCClause *C) { -- GitLab From 67c18721eb2170a6cd7af461e16d994b1b83363a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 13 May 2024 14:47:21 +0200 Subject: [PATCH 075/578] [clang][Interp] Return false from visitExpr() if allocateLocal failed --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 630fdb60c351..c0eae5ab20ed 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2861,7 +2861,8 @@ bool ByteCodeExprGen::visitExpr(const Expr *E) { return this->emitRetValue(E) && RootScope.destroyLocals(); } - return RootScope.destroyLocals(); + RootScope.destroyLocals(); + return false; } /// Toplevel visitDecl(). -- GitLab From 2bd97ba390f9137f26eaf770a90c5f1cb72acbdb Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 13 May 2024 15:27:08 +0100 Subject: [PATCH 076/578] [X86] LowerGlobalOrExternal - cleanup SDLoc. NFC. Don't create a new local SDLoc and then take a reference to it, just create the SDLoc directly. --- llvm/lib/Target/X86/X86ISelLowering.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 0410cc33ca33..bbea2befdcc6 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -18559,7 +18559,7 @@ X86TargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const { SDValue X86TargetLowering::LowerGlobalOrExternal(SDValue Op, SelectionDAG &DAG, bool ForCall) const { // Unpack the global address or external symbol. - const SDLoc &dl = SDLoc(Op); + SDLoc dl(Op); const GlobalValue *GV = nullptr; int64_t Offset = 0; const char *ExternalSym = nullptr; -- GitLab From b4393c7d7ea538e92428c7769de590615509f8b4 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 13 May 2024 15:29:50 +0100 Subject: [PATCH 077/578] [X86] FP_TO_INTHelper - remove duplicate SDLoc. NFC. --- llvm/lib/Target/X86/X86ISelLowering.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index bbea2befdcc6..9d13c043c238 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -20113,7 +20113,7 @@ SDValue X86TargetLowering::FP_TO_INTHelper(SDValue Op, SelectionDAG &DAG, DAG.getVTList(MVT::Other), Ops, DstTy, MMO); - SDValue Res = DAG.getLoad(Op.getValueType(), SDLoc(Op), FIST, StackSlot, MPI); + SDValue Res = DAG.getLoad(Op.getValueType(), DL, FIST, StackSlot, MPI); Chain = Res.getValue(1); // If we need an unsigned fixup, XOR the result with adjust. -- GitLab From b5da0cd68287fa613052a3d3164f2e9de35bedd3 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 13 May 2024 15:36:29 +0100 Subject: [PATCH 078/578] [X86] LowerTruncateVecI1 - reuse existing SDLoc. NFC. --- llvm/lib/Target/X86/X86ISelLowering.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 9d13c043c238..d1be60f18cab 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -20591,14 +20591,12 @@ static SDValue LowerTruncateVecPack(MVT DstVT, SDValue In, const SDLoc &DL, return SDValue(); } -static SDValue LowerTruncateVecI1(SDValue Op, SelectionDAG &DAG, +static SDValue LowerTruncateVecI1(SDValue Op, const SDLoc &DL, + SelectionDAG &DAG, const X86Subtarget &Subtarget) { - - SDLoc DL(Op); MVT VT = Op.getSimpleValueType(); SDValue In = Op.getOperand(0); MVT InVT = In.getSimpleValueType(); - assert(VT.getVectorElementType() == MVT::i1 && "Unexpected vector type."); // Shift LSB to MSB and use VPMOVB/W2M or TESTD/Q. @@ -20717,7 +20715,7 @@ SDValue X86TargetLowering::LowerTRUNCATE(SDValue Op, SelectionDAG &DAG) const { } if (VT.getVectorElementType() == MVT::i1) - return LowerTruncateVecI1(Op, DAG, Subtarget); + return LowerTruncateVecI1(Op, DL, DAG, Subtarget); // Attempt to truncate with PACKUS/PACKSS even on AVX512 if we'd have to // concat from subvectors to use VPTRUNC etc. -- GitLab From 0cc60235d178ebe18db14b9731aa01c24abd1c66 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 13 May 2024 15:40:55 +0100 Subject: [PATCH 079/578] [X86] LowerFP_TO_INT - remove duplicate SDLoc. NFC. --- llvm/lib/Target/X86/X86ISelLowering.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index d1be60f18cab..bf1f3f335771 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -21171,8 +21171,8 @@ SDValue X86TargetLowering::LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const { LC = RTLIB::getFPTOUINT(SrcVT, VT); MakeLibCallOptions CallOptions; - std::pair Tmp = makeLibCall(DAG, LC, VT, Src, CallOptions, - SDLoc(Op), Chain); + std::pair Tmp = + makeLibCall(DAG, LC, VT, Src, CallOptions, dl, Chain); if (IsStrict) return DAG.getMergeValues({ Tmp.first, Tmp.second }, dl); -- GitLab From b7e4a8a08ecf73d2b34dca1b71d08d622da58bdc Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 13 May 2024 15:51:03 +0100 Subject: [PATCH 080/578] [X86] LowerIntVSETCC_AVX512 - reuse existing SDLoc. NFC. --- llvm/lib/Target/X86/X86ISelLowering.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index bf1f3f335771..ecc5b3b3bf84 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -23104,14 +23104,12 @@ static SDValue splitIntVSETCC(EVT VT, SDValue LHS, SDValue RHS, DAG.getNode(ISD::SETCC, dl, HiVT, LHS2, RHS2, CC)); } -static SDValue LowerIntVSETCC_AVX512(SDValue Op, SelectionDAG &DAG) { - +static SDValue LowerIntVSETCC_AVX512(SDValue Op, const SDLoc &dl, + SelectionDAG &DAG) { SDValue Op0 = Op.getOperand(0); SDValue Op1 = Op.getOperand(1); SDValue CC = Op.getOperand(2); MVT VT = Op.getSimpleValueType(); - SDLoc dl(Op); - assert(VT.getVectorElementType() == MVT::i1 && "Cannot set masked compare for this operation"); @@ -23387,7 +23385,7 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget &Subtarget, // But there is no compare instruction for i8 and i16 elements in KNL. assert((VTOp0.getScalarSizeInBits() >= 32 || Subtarget.hasBWI()) && "Unexpected operand type"); - return LowerIntVSETCC_AVX512(Op, DAG); + return LowerIntVSETCC_AVX512(Op, dl, DAG); } // Lower using XOP integer comparisons. -- GitLab From 999fb097102f75feac1601c061b8bdf0a4cf6112 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Mon, 13 May 2024 15:02:49 +0000 Subject: [PATCH 081/578] [gn build] Port 05cc2d5fe10c --- llvm/utils/gn/secondary/libcxx/include/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn index 9dc06399877f..210b26e8f166 100644 --- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn +++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn @@ -516,6 +516,7 @@ if (current_toolchain == default_toolchain) { "__ios/fpos.h", "__iterator/access.h", "__iterator/advance.h", + "__iterator/aliasing_iterator.h", "__iterator/back_insert_iterator.h", "__iterator/bounded_iter.h", "__iterator/common_iterator.h", -- GitLab From 9f858c7b79f9edff082050b930fee347887f8e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Warzy=C5=84ski?= Date: Mon, 13 May 2024 16:12:09 +0100 Subject: [PATCH 082/578] [mlir][vector][test] Update tests for vector.xfter_{read|write} (#91943) Updates tests in "vector-transfer-permutation-lowering.mlir" to make a clearer split into cases for : * xfer_read vs xfer_write * fixed-width vs scalable tests A new test case is added for fixed-width vectors for vector.transfer_read. This is to complement an existing test for scalable vectors. This is in preparation for #90835 and also for adding more tests for scalable vectors. --- .../vector-transfer-permutation-lowering.mlir | 94 ++++++++++++++----- 1 file changed, 68 insertions(+), 26 deletions(-) diff --git a/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir b/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir index 31bd19c0be8e..e48af3cd7aac 100644 --- a/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir +++ b/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir @@ -1,23 +1,84 @@ // RUN: mlir-opt %s --transform-interpreter --split-input-file | FileCheck %s -// CHECK-LABEL: func @lower_permutation_with_mask_fixed_width( +///---------------------------------------------------------------------------------------- +/// vector.transfer_write +///---------------------------------------------------------------------------------------- +/// Input: +/// * vector.transfer_write op with a map which _is not_ the permutation of a +/// minor identity +/// Output: +/// * vector.broadcast + vector.transfer_write with a map which _is_ the permutation of a +/// minor identity + +// CHECK-LABEL: func @permutation_with_mask_xfer_write_fixed_width( // CHECK: %[[vec:.*]] = arith.constant dense<-2.000000e+00> : vector<7x1xf32> // CHECK: %[[mask:.*]] = arith.constant dense<[true, false, true, false, true, true, true]> : vector<7xi1> // CHECK: %[[b:.*]] = vector.broadcast %[[mask]] : vector<7xi1> to vector<1x7xi1> // CHECK: %[[tp:.*]] = vector.transpose %[[b]], [1, 0] : vector<1x7xi1> to vector<7x1xi1> // CHECK: vector.transfer_write %[[vec]], %{{.*}}[%{{.*}}, %{{.*}}], %[[tp]] {in_bounds = [false, true]} : vector<7x1xf32>, memref -func.func @lower_permutation_with_mask_fixed_width(%A : memref, %base1 : index, - %base2 : index) { +func.func @permutation_with_mask_xfer_write_fixed_width(%mem : memref, %base1 : index, + %base2 : index) { + %fn1 = arith.constant -2.0 : f32 %vf0 = vector.splat %fn1 : vector<7xf32> %mask = arith.constant dense<[1, 0, 1, 0, 1, 1, 1]> : vector<7xi1> - vector.transfer_write %vf0, %A[%base1, %base2], %mask + vector.transfer_write %vf0, %mem[%base1, %base2], %mask {permutation_map = affine_map<(d0, d1) -> (d0)>, in_bounds = [false]} : vector<7xf32>, memref return } -// CHECK-LABEL: func.func @permutation_with_mask_scalable( +// CHECK: func.func @permutation_with_mask_xfer_write_scalable( +// CHECK-SAME: %[[ARG_0:.*]]: vector<4x[8]xi16>, +// CHECK-SAME: %[[ARG_1:.*]]: memref<1x4x?x1xi16>, +// CHECK-SAME: %[[MASK:.*]]: vector<4x[8]xi1>) { +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[BCAST_1:.*]] = vector.broadcast %[[ARG_0]] : vector<4x[8]xi16> to vector<1x4x[8]xi16> +// CHECK: %[[BCAST_2:.*]] = vector.broadcast %[[MASK]] : vector<4x[8]xi1> to vector<1x4x[8]xi1> +// CHECK: %[[TRANSPOSE_1:.*]] = vector.transpose %[[BCAST_2]], [1, 2, 0] : vector<1x4x[8]xi1> to vector<4x[8]x1xi1> +// CHECK: %[[TRANSPOSE_2:.*]] = vector.transpose %[[BCAST_1]], [1, 2, 0] : vector<1x4x[8]xi16> to vector<4x[8]x1xi16> +// CHECK: vector.transfer_write %[[TRANSPOSE_2]], %[[ARG_1]]{{.*}}, %[[TRANSPOSE_1]] {in_bounds = [true, true, true]} : vector<4x[8]x1xi16>, memref<1x4x?x1xi16> +func.func @permutation_with_mask_xfer_write_scalable(%arg0: vector<4x[8]xi16>, %mem: memref<1x4x?x1xi16>, %mask: vector<4x[8]xi1>){ + %c0 = arith.constant 0 : index + vector.transfer_write %arg0, %mem[%c0, %c0, %c0, %c0], %mask {in_bounds = [true, true], permutation_map = affine_map<(d0, d1, d2, d3) -> (d1, d2)> +} : vector<4x[8]xi16>, memref<1x4x?x1xi16> + + return +} + +///---------------------------------------------------------------------------------------- +/// vector.transfer_read +///---------------------------------------------------------------------------------------- +/// Input: +/// * vector.transfer_read op with a permutation map +/// Output: +/// * vector.transfer_read with a permutation map composed of leading zeros followed by a minor identiy + +/// vector.transpose op + +// CHECK-LABEL: func.func @permutation_with_mask_xfer_read_fixed_width( +// CHECK-SAME: %[[ARG_0:.*]]: memref, +// CHECK-SAME: %[[IDX_1:.*]]: index, +// CHECK-SAME: %[[IDX_2:.*]]: index) -> vector<8x4x2xf32> { +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[PASS_THROUGH:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[MASK:.*]] = vector.create_mask %[[IDX_2]], %[[IDX_1]] : vector<2x4xi1> +// CHECK: %[[T_READ:.*]] = vector.transfer_read %[[ARG_0]]{{\[}}%[[C0]], %[[C0]]], %[[PASS_THROUGH]], %[[MASK]] {in_bounds = [true, true]} : memref, vector<2x4xf32> +// CHECK: %[[BCAST:.*]] = vector.broadcast %[[T_READ]] : vector<2x4xf32> to vector<8x2x4xf32> +// CHECK: %[[TRANSPOSE:.*]] = vector.transpose %[[BCAST]], [0, 2, 1] : vector<8x2x4xf32> to vector<8x4x2xf32> +// CHECK: return %[[TRANSPOSE]] : vector<8x4x2xf32> +func.func @permutation_with_mask_xfer_read_fixed_width(%mem: memref, %dim_1: index, %dim_2: index) -> (vector<8x4x2xf32>) { + + %c0 = arith.constant 0 : index + %cst_0 = arith.constant 0.000000e+00 : f32 + + %mask = vector.create_mask %dim_2, %dim_1 : vector<2x4xi1> + %1 = vector.transfer_read %mem[%c0, %c0], %cst_0, %mask + {in_bounds = [true, true, true], permutation_map = affine_map<(d0, d1) -> (0, d1, d0)>} + : memref, vector<8x4x2xf32> + return %1 : vector<8x4x2xf32> +} + +// CHECK-LABEL: func.func @permutation_with_mask_xfer_read_scalable( // CHECK-SAME: %[[ARG_0:.*]]: memref, // CHECK-SAME: %[[IDX_1:.*]]: index, // CHECK-SAME: %[[IDX_2:.*]]: index) -> vector<8x[4]x2xf32> { @@ -28,37 +89,18 @@ func.func @lower_permutation_with_mask_fixed_width(%A : memref, %base1 // CHECK: %[[BCAST:.*]] = vector.broadcast %[[T_READ]] : vector<2x[4]xf32> to vector<8x2x[4]xf32> // CHECK: %[[TRANSPOSE:.*]] = vector.transpose %[[BCAST]], [0, 2, 1] : vector<8x2x[4]xf32> to vector<8x[4]x2xf32> // CHECK: return %[[TRANSPOSE]] : vector<8x[4]x2xf32> -// CHECK: } -func.func @permutation_with_mask_scalable(%2: memref, %dim_1: index, %dim_2: index) -> (vector<8x[4]x2xf32>) { +func.func @permutation_with_mask_xfer_read_scalable(%mem: memref, %dim_1: index, %dim_2: index) -> (vector<8x[4]x2xf32>) { %c0 = arith.constant 0 : index %cst_0 = arith.constant 0.000000e+00 : f32 %mask = vector.create_mask %dim_2, %dim_1 : vector<2x[4]xi1> - %1 = vector.transfer_read %2[%c0, %c0], %cst_0, %mask + %1 = vector.transfer_read %mem[%c0, %c0], %cst_0, %mask {in_bounds = [true, true, true], permutation_map = affine_map<(d0, d1) -> (0, d1, d0)>} : memref, vector<8x[4]x2xf32> return %1 : vector<8x[4]x2xf32> } -// CHECK: func.func @permutation_with_mask_transfer_write_scalable( -// CHECK-SAME: %[[ARG_0:.*]]: vector<4x[8]xi16>, -// CHECK-SAME: %[[ARG_1:.*]]: memref<1x4x?x1x1x1x1xi16>, -// CHECK-SAME: %[[MASK:.*]]: vector<4x[8]xi1>) { -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[BCAST_1:.*]] = vector.broadcast %[[ARG_0]] : vector<4x[8]xi16> to vector<1x1x1x1x4x[8]xi16> -// CHECK: %[[BCAST_2:.*]] = vector.broadcast %[[MASK]] : vector<4x[8]xi1> to vector<1x1x1x1x4x[8]xi1> -// CHECK: %[[TRANSPOSE_1:.*]] = vector.transpose %[[BCAST_2]], [4, 5, 0, 1, 2, 3] : vector<1x1x1x1x4x[8]xi1> to vector<4x[8]x1x1x1x1xi1> -// CHECK: %[[TRANSPOSE_2:.*]] = vector.transpose %[[BCAST_1]], [4, 5, 0, 1, 2, 3] : vector<1x1x1x1x4x[8]xi16> to vector<4x[8]x1x1x1x1xi16> -// CHECK: vector.transfer_write %[[TRANSPOSE_2]], %[[ARG_1]]{{\[}}%[[C0]], %[[C0]], %[[C0]], %[[C0]], %[[C0]], %[[C0]], %[[C0]]], %[[TRANSPOSE_1]] {in_bounds = [true, true, true, true, true, true]} : vector<4x[8]x1x1x1x1xi16>, memref<1x4x?x1x1x1x1xi16> -// CHECK: return -func.func @permutation_with_mask_transfer_write_scalable(%arg0: vector<4x[8]xi16>, %arg1: memref<1x4x?x1x1x1x1xi16>, %mask: vector<4x[8]xi1>){ - %c0 = arith.constant 0 : index - vector.transfer_write %arg0, %arg1[%c0, %c0, %c0, %c0, %c0, %c0, %c0], %mask {in_bounds = [true, true], permutation_map = affine_map<(d0, d1, d2, d3, d4, d5, d6) -> (d1, d2)> -} : vector<4x[8]xi16>, memref<1x4x?x1x1x1x1xi16> - - return -} module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%module_op: !transform.any_op {transform.readonly}) { %f = transform.structured.match ops{["func.func"]} in %module_op -- GitLab From 257013e4f5cbdf644646da9ec3d60d6209c9bf25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 13 May 2024 16:01:55 +0200 Subject: [PATCH 083/578] [clang][Interp] Handle VariableArrayTypes --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 4 +++- clang/lib/AST/Interp/Program.cpp | 3 ++- clang/test/AST/Interp/arrays.cpp | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index c0eae5ab20ed..7b10482dff23 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2159,7 +2159,9 @@ bool ByteCodeExprGen::VisitCXXConstructExpr( if (T->isArrayType()) { const ConstantArrayType *CAT = Ctx.getASTContext().getAsConstantArrayType(E->getType()); - assert(CAT); + if (!CAT) + return false; + size_t NumElems = CAT->getZExtSize(); const Function *Func = getFunction(E->getConstructor()); if (!Func || !Func->isConstexpr()) diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index 87c767f85e79..6606149f1f69 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -386,7 +386,8 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, // Array of unknown bounds - cannot be accessed and pointer arithmetic // is forbidden on pointers to such objects. - if (isa(ArrayType)) { + if (isa(ArrayType) || + isa(ArrayType)) { if (std::optional T = Ctx.classify(ElemTy)) { return allocateDescriptor(D, *T, MDSize, IsTemporary, Descriptor::UnknownSize{}); diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp index abfcd09338ca..70e87c4cd854 100644 --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -560,6 +560,11 @@ namespace LocalVLA { // both-note@-4 {{function parameter 'size' with unknown value}} #endif } + + void f (unsigned int m) { + int e[2][m]; + e[0][0] = 0; + } } char melchizedek[2]; -- GitLab From 1f6f5bf9307033980121fc534815a7b59453e122 Mon Sep 17 00:00:00 2001 From: erichkeane Date: Mon, 13 May 2024 08:23:19 -0700 Subject: [PATCH 084/578] Fix warning from c4a9a374 I wasn't able to reproduce the test crash, but I believe this might be a different definition of 'assert' on some platforms, so I believe this patch should fix it (and fixes the suggested warning). --- clang/include/clang/AST/OpenACCClause.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 3998a3430ff9..607a2b9d6536 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -101,13 +101,13 @@ class OpenACCDeviceTypeClause final return Arg.second.isInvalid(); }) && "Invalid SourceLocation for an argument"); - assert(Archs.size() == 1 || - !llvm::any_of(Archs, - [](const DeviceTypeArgument &Arg) { - return Arg.first == nullptr; - }) && - "Only a single asterisk version is permitted, and must be the " - "only one"); + assert( + (Archs.size() == 1 || !llvm::any_of(Archs, + [](const DeviceTypeArgument &Arg) { + return Arg.first == nullptr; + })) && + "Only a single asterisk version is permitted, and must be the " + "only one"); std::uninitialized_copy(Archs.begin(), Archs.end(), getTrailingObjects()); -- GitLab From be7c9e39572d876c16b6a8d7f4addaf9409071ff Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 13 May 2024 08:09:24 -0500 Subject: [PATCH 085/578] [flang][OpenMP] Decompose compound constructs, do recursive lowering (#90098) A compound construct with a list of clauses is broken up into individual leaf/composite constructs. Each such construct has the list of clauses that apply to it based on the OpenMP spec. Each lowering function (i.e. a function that generates MLIR ops) is now responsible for generating its body as described below. Functions that receive AST nodes extract the construct, and the clauses from the node. They then create a work queue consisting of individual constructs, and invoke a common dispatch function to process (lower) the queue. The dispatch function examines the current position in the queue, and invokes the appropriate lowering function. Each lowering function receives the queue as well, and once it needs to generate its body, it either invokes the dispatch function on the rest of the queue (if any), or processes nested evaluations if the work queue is at the end. Re-application of ca1bd5995f6ed934f9187305190a5abfac049173 with fixes for compilation errors. --- flang/lib/Lower/CMakeLists.txt | 1 + flang/lib/Lower/OpenMP/Clauses.cpp | 23 + flang/lib/Lower/OpenMP/Clauses.h | 17 +- flang/lib/Lower/OpenMP/Decomposer.cpp | 126 ++ flang/lib/Lower/OpenMP/Decomposer.h | 51 + flang/lib/Lower/OpenMP/OpenMP.cpp | 828 ++++++------ flang/lib/Lower/OpenMP/Utils.cpp | 6 - flang/lib/Lower/OpenMP/Utils.h | 1 - .../Lower/OpenMP/default-clause-byref.f90 | 5 +- flang/test/Lower/OpenMP/default-clause.f90 | 4 +- .../parallel-lastprivate-clause-scalar.f90 | 4 +- llvm/include/llvm/Frontend/OpenMP/ClauseT.h | 58 +- .../Frontend/OpenMP/ConstructCompositionT.h | 403 ++++++ .../Frontend/OpenMP/ConstructDecompositionT.h | 1160 +++++++++++++++++ llvm/unittests/Frontend/CMakeLists.txt | 1 + .../Frontend/OpenMPDecompositionTest.cpp | 999 ++++++++++++++ 16 files changed, 3234 insertions(+), 453 deletions(-) create mode 100644 flang/lib/Lower/OpenMP/Decomposer.cpp create mode 100644 flang/lib/Lower/OpenMP/Decomposer.h create mode 100644 llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h create mode 100644 llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h create mode 100644 llvm/unittests/Frontend/OpenMPDecompositionTest.cpp diff --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt index f92d1a2bc7de..1546409752e7 100644 --- a/flang/lib/Lower/CMakeLists.txt +++ b/flang/lib/Lower/CMakeLists.txt @@ -27,6 +27,7 @@ add_flang_library(FortranLower OpenMP/ClauseProcessor.cpp OpenMP/Clauses.cpp OpenMP/DataSharingProcessor.cpp + OpenMP/Decomposer.cpp OpenMP/OpenMP.cpp OpenMP/ReductionProcessor.cpp OpenMP/Utils.cpp diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 97337cfc08c7..87370c92964a 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -1227,4 +1227,27 @@ List makeClauses(const parser::OmpClauseList &clauses, return makeClause(s, semaCtx); }); } + +bool transferLocations(const List &from, List &to) { + bool allDone = true; + + for (Clause &clause : to) { + if (!clause.source.empty()) + continue; + auto found = + llvm::find_if(from, [&](const Clause &c) { return c.id == clause.id; }); + // This is not completely accurate, but should be good enough for now. + // It can be improved in the future if necessary, but in cases of + // synthesized clauses getting accurate location may be impossible. + if (found != from.end()) { + clause.source = found->source; + } else { + // Found a clause that won't have "source". + allDone = false; + } + } + + return allDone; +} + } // namespace Fortran::lower::omp diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h index 3e776425c733..ca610c652896 100644 --- a/flang/lib/Lower/OpenMP/Clauses.h +++ b/flang/lib/Lower/OpenMP/Clauses.h @@ -23,11 +23,15 @@ namespace Fortran::lower::omp { using namespace Fortran; -using SomeType = evaluate::SomeType; using SomeExpr = semantics::SomeExpr; using MaybeExpr = semantics::MaybeExpr; -using TypeTy = SomeType; +// evaluate::SomeType doesn't provide == operation. It's not really used in +// flang's clauses so far, so a trivial implementation is sufficient. +struct TypeTy : public evaluate::SomeType { + bool operator==(const TypeTy &t) const { return true; } +}; + using IdTy = semantics::Symbol *; using ExprTy = SomeExpr; @@ -222,6 +226,8 @@ using When = tomp::clause::WhenT; using Write = tomp::clause::WriteT; } // namespace clause +using tomp::type::operator==; + struct CancellationConstructType { using EmptyTrait = std::true_type; }; @@ -244,13 +250,16 @@ using ClauseBase = tomp::ClauseT; struct Clause : public ClauseBase { + Clause(ClauseBase &&base, const parser::CharBlock source = {}) + : ClauseBase(std::move(base)), source(source) {} + // "source" will be ignored by tomp::type::operator==. parser::CharBlock source; }; template Clause makeClause(llvm::omp::Clause id, Specific &&specific, parser::CharBlock source = {}) { - return Clause{{id, specific}, source}; + return Clause(typename Clause::BaseT{id, specific}, source); } Clause makeClause(const Fortran::parser::OmpClause &cls, @@ -258,6 +267,8 @@ Clause makeClause(const Fortran::parser::OmpClause &cls, List makeClauses(const parser::OmpClauseList &clauses, semantics::SemanticsContext &semaCtx); + +bool transferLocations(const List &from, List &to); } // namespace Fortran::lower::omp #endif // FORTRAN_LOWER_OPENMP_CLAUSES_H diff --git a/flang/lib/Lower/OpenMP/Decomposer.cpp b/flang/lib/Lower/OpenMP/Decomposer.cpp new file mode 100644 index 000000000000..e6897cb81e94 --- /dev/null +++ b/flang/lib/Lower/OpenMP/Decomposer.cpp @@ -0,0 +1,126 @@ +//===-- Decomposer.cpp -- Compound directive decomposition ----------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ +// +//===----------------------------------------------------------------------===// + +#include "Decomposer.h" + +#include "Clauses.h" +#include "Utils.h" +#include "flang/Lower/PFTBuilder.h" +#include "flang/Semantics/semantics.h" +#include "flang/Tools/CrossToolHelpers.h" +#include "mlir/IR/BuiltinOps.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Frontend/OpenMP/ClauseT.h" +#include "llvm/Frontend/OpenMP/ConstructCompositionT.h" +#include "llvm/Frontend/OpenMP/ConstructDecompositionT.h" +#include "llvm/Frontend/OpenMP/OMP.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include + +using namespace Fortran; + +namespace { +using namespace Fortran::lower::omp; + +struct ConstructDecomposition { + ConstructDecomposition(mlir::ModuleOp modOp, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &ev, + llvm::omp::Directive compound, + const List &clauses) + : semaCtx(semaCtx), mod(modOp), eval(ev) { + tomp::ConstructDecompositionT decompose(getOpenMPVersionAttribute(modOp), + *this, compound, + llvm::ArrayRef(clauses)); + output = std::move(decompose.output); + } + + // Given an object, return its base object if one exists. + std::optional getBaseObject(const Object &object) { + return lower::omp::getBaseObject(object, semaCtx); + } + + // Return the iteration variable of the associated loop if any. + std::optional getLoopIterVar() { + if (semantics::Symbol *symbol = getIterationVariableSymbol(eval)) + return Object{symbol, /*designator=*/{}}; + return std::nullopt; + } + + semantics::SemanticsContext &semaCtx; + mlir::ModuleOp mod; + lower::pft::Evaluation &eval; + List output; +}; +} // namespace + +static UnitConstruct mergeConstructs(uint32_t version, + llvm::ArrayRef units) { + tomp::ConstructCompositionT compose(version, units); + return compose.merged; +} + +namespace Fortran::lower::omp { +LLVM_DUMP_METHOD llvm::raw_ostream &operator<<(llvm::raw_ostream &os, + const UnitConstruct &uc) { + os << llvm::omp::getOpenMPDirectiveName(uc.id); + for (auto [index, clause] : llvm::enumerate(uc.clauses)) { + os << (index == 0 ? '\t' : ' '); + os << llvm::omp::getOpenMPClauseName(clause.id); + } + return os; +} + +ConstructQueue buildConstructQueue( + mlir::ModuleOp modOp, Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, const parser::CharBlock &source, + llvm::omp::Directive compound, const List &clauses) { + + List constructs; + + ConstructDecomposition decompose(modOp, semaCtx, eval, compound, clauses); + assert(!decompose.output.empty() && "Construct decomposition failed"); + + llvm::SmallVector loweringUnits; + std::ignore = + llvm::omp::getLeafOrCompositeConstructs(compound, loweringUnits); + uint32_t version = getOpenMPVersionAttribute(modOp); + + int leafIndex = 0; + for (llvm::omp::Directive dir_id : loweringUnits) { + llvm::ArrayRef leafsOrSelf = + llvm::omp::getLeafConstructsOrSelf(dir_id); + size_t numLeafs = leafsOrSelf.size(); + + llvm::ArrayRef toMerge{&decompose.output[leafIndex], + numLeafs}; + auto &uc = constructs.emplace_back(mergeConstructs(version, toMerge)); + + if (!transferLocations(clauses, uc.clauses)) { + // If some clauses are left without source information, use the + // directive's source. + for (auto &clause : uc.clauses) { + if (clause.source.empty()) + clause.source = source; + } + } + leafIndex += numLeafs; + } + + return constructs; +} +} // namespace Fortran::lower::omp diff --git a/flang/lib/Lower/OpenMP/Decomposer.h b/flang/lib/Lower/OpenMP/Decomposer.h new file mode 100644 index 000000000000..f42d8f5c1740 --- /dev/null +++ b/flang/lib/Lower/OpenMP/Decomposer.h @@ -0,0 +1,51 @@ +//===-- Decomposer.h -- Compound directive decomposition ------------------===// +// +// 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 FORTRAN_LOWER_OPENMP_DECOMPOSER_H +#define FORTRAN_LOWER_OPENMP_DECOMPOSER_H + +#include "Clauses.h" +#include "mlir/IR/BuiltinOps.h" +#include "llvm/Frontend/OpenMP/ConstructCompositionT.h" +#include "llvm/Frontend/OpenMP/ConstructDecompositionT.h" +#include "llvm/Frontend/OpenMP/OMP.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { +class raw_ostream; +} + +namespace Fortran { +namespace semantics { +class SemanticsContext; +} +namespace lower::pft { +struct Evaluation; +} +} // namespace Fortran + +namespace Fortran::lower::omp { +using UnitConstruct = tomp::DirectiveWithClauses; +using ConstructQueue = List; + +LLVM_DUMP_METHOD llvm::raw_ostream &operator<<(llvm::raw_ostream &os, + const UnitConstruct &uc); + +// Given a potentially compound construct with a list of clauses that +// apply to it, break it up into individual sub-constructs each with +// the subset of applicable clauses (plus implicit clauses, if any). +// From that create a work queue where each work item corresponds to +// the sub-construct with its clauses. +ConstructQueue buildConstructQueue(mlir::ModuleOp modOp, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::CharBlock &source, + llvm::omp::Directive compound, + const List &clauses); +} // namespace Fortran::lower::omp + +#endif // FORTRAN_LOWER_OPENMP_DECOMPOSER_H diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index f23902d6a823..eaf4b5f997ff 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -15,6 +15,7 @@ #include "ClauseProcessor.h" #include "Clauses.h" #include "DataSharingProcessor.h" +#include "Decomposer.h" #include "DirectivesCommon.h" #include "ReductionProcessor.h" #include "Utils.h" @@ -44,6 +45,13 @@ using namespace Fortran::lower::omp; // Code generation helper functions //===----------------------------------------------------------------------===// +static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item); + static Fortran::lower::pft::Evaluation * getCollapsedLoopEval(Fortran::lower::pft::Evaluation &eval, int collapseValue) { // Return the Evaluation of the innermost collapsed loop, or the current one @@ -460,81 +468,6 @@ markDeclareTarget(mlir::Operation *op, declareTargetOp.setDeclareTarget(deviceType, captureClause); } -/// Split a combined directive into an outer leaf directive and the (possibly -/// combined) rest of the combined directive. Composite directives and -/// non-compound directives are not split, in which case it will return the -/// input directive as its first output and an empty value as its second output. -static std::pair> -splitCombinedDirective(llvm::omp::Directive dir) { - using D = llvm::omp::Directive; - switch (dir) { - case D::OMPD_masked_taskloop: - return {D::OMPD_masked, D::OMPD_taskloop}; - case D::OMPD_masked_taskloop_simd: - return {D::OMPD_masked, D::OMPD_taskloop_simd}; - case D::OMPD_master_taskloop: - return {D::OMPD_master, D::OMPD_taskloop}; - case D::OMPD_master_taskloop_simd: - return {D::OMPD_master, D::OMPD_taskloop_simd}; - case D::OMPD_parallel_do: - return {D::OMPD_parallel, D::OMPD_do}; - case D::OMPD_parallel_do_simd: - return {D::OMPD_parallel, D::OMPD_do_simd}; - case D::OMPD_parallel_masked: - return {D::OMPD_parallel, D::OMPD_masked}; - case D::OMPD_parallel_masked_taskloop: - return {D::OMPD_parallel, D::OMPD_masked_taskloop}; - case D::OMPD_parallel_masked_taskloop_simd: - return {D::OMPD_parallel, D::OMPD_masked_taskloop_simd}; - case D::OMPD_parallel_master: - return {D::OMPD_parallel, D::OMPD_master}; - case D::OMPD_parallel_master_taskloop: - return {D::OMPD_parallel, D::OMPD_master_taskloop}; - case D::OMPD_parallel_master_taskloop_simd: - return {D::OMPD_parallel, D::OMPD_master_taskloop_simd}; - case D::OMPD_parallel_sections: - return {D::OMPD_parallel, D::OMPD_sections}; - case D::OMPD_parallel_workshare: - return {D::OMPD_parallel, D::OMPD_workshare}; - case D::OMPD_target_parallel: - return {D::OMPD_target, D::OMPD_parallel}; - case D::OMPD_target_parallel_do: - return {D::OMPD_target, D::OMPD_parallel_do}; - case D::OMPD_target_parallel_do_simd: - return {D::OMPD_target, D::OMPD_parallel_do_simd}; - case D::OMPD_target_simd: - return {D::OMPD_target, D::OMPD_simd}; - case D::OMPD_target_teams: - return {D::OMPD_target, D::OMPD_teams}; - case D::OMPD_target_teams_distribute: - return {D::OMPD_target, D::OMPD_teams_distribute}; - case D::OMPD_target_teams_distribute_parallel_do: - return {D::OMPD_target, D::OMPD_teams_distribute_parallel_do}; - case D::OMPD_target_teams_distribute_parallel_do_simd: - return {D::OMPD_target, D::OMPD_teams_distribute_parallel_do_simd}; - case D::OMPD_target_teams_distribute_simd: - return {D::OMPD_target, D::OMPD_teams_distribute_simd}; - case D::OMPD_teams_distribute: - return {D::OMPD_teams, D::OMPD_distribute}; - case D::OMPD_teams_distribute_parallel_do: - return {D::OMPD_teams, D::OMPD_distribute_parallel_do}; - case D::OMPD_teams_distribute_parallel_do_simd: - return {D::OMPD_teams, D::OMPD_distribute_parallel_do_simd}; - case D::OMPD_teams_distribute_simd: - return {D::OMPD_teams, D::OMPD_distribute_simd}; - case D::OMPD_parallel_loop: - return {D::OMPD_parallel, D::OMPD_loop}; - case D::OMPD_target_parallel_loop: - return {D::OMPD_target, D::OMPD_parallel_loop}; - case D::OMPD_target_teams_loop: - return {D::OMPD_target, D::OMPD_teams_loop}; - case D::OMPD_teams_loop: - return {D::OMPD_teams, D::OMPD_loop}; - default: - return {dir, std::nullopt}; - } -} - //===----------------------------------------------------------------------===// // Op body generation helper structures and functions //===----------------------------------------------------------------------===// @@ -555,11 +488,6 @@ struct OpWithBodyGenInfo { : converter(converter), symTable(symTable), semaCtx(semaCtx), loc(loc), eval(eval), dir(dir) {} - OpWithBodyGenInfo &setGenNested(bool value) { - genNested = value; - return *this; - } - OpWithBodyGenInfo &setOuterCombined(bool value) { outerCombined = value; return *this; @@ -600,8 +528,6 @@ struct OpWithBodyGenInfo { Fortran::lower::pft::Evaluation &eval; /// [in] leaf directive for which to generate the op body. llvm::omp::Directive dir; - /// [in] whether to generate FIR for nested evaluations - bool genNested = true; /// [in] is this an outer operation - prevents privatization. bool outerCombined = false; /// [in] list of clauses to process. @@ -620,9 +546,13 @@ struct OpWithBodyGenInfo { /// Create the body (block) for an OpenMP Operation. /// -/// \param [in] op - the operation the body belongs to. -/// \param [in] info - options controlling code-gen for the construction. -static void createBodyOfOp(mlir::Operation &op, OpWithBodyGenInfo &info) { +/// \param [in] op - the operation the body belongs to. +/// \param [in] info - options controlling code-gen for the construction. +/// \param [in] queue - work queue with nested constructs. +/// \param [in] item - item in the queue to generate body for. +static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, + const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = info.converter.getFirOpBuilder(); auto insertMarker = [](fir::FirOpBuilder &builder) { @@ -678,7 +608,10 @@ static void createBodyOfOp(mlir::Operation &op, OpWithBodyGenInfo &info) { } } - if (info.genNested) { + if (ConstructQueue::iterator next = std::next(item); next != queue.end()) { + genOMPDispatch(info.converter, info.symTable, info.semaCtx, info.eval, + info.loc, queue, next); + } else { // genFIR(Evaluation&) tries to patch up unterminated blocks, causing // a lot of complications for our approach if the terminator generation // is delayed past this point. Insert a temporary terminator here, then @@ -769,11 +702,12 @@ static void genBodyOfTargetDataOp( Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::omp::TargetDataOp &dataOp, llvm::ArrayRef useDeviceTypes, + Fortran::lower::pft::Evaluation &eval, mlir::omp::TargetDataOp &dataOp, + llvm::ArrayRef useDeviceTypes, llvm::ArrayRef useDeviceLocs, llvm::ArrayRef useDeviceSymbols, - const mlir::Location ¤tLocation) { + const mlir::Location ¤tLocation, const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Region ®ion = dataOp.getRegion(); @@ -826,8 +760,13 @@ static void genBodyOfTargetDataOp( // Set the insertion point after the marker. firOpBuilder.setInsertionPointAfter(undefMarker.getDefiningOp()); - if (genNested) + + if (ConstructQueue::iterator next = std::next(item); next != queue.end()) { + genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, + next); + } else { genNestedEvaluations(converter, eval); + } } // This functions creates a block for the body of the targetOp's region. It adds @@ -836,12 +775,13 @@ static void genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, + Fortran::lower::pft::Evaluation &eval, mlir::omp::TargetOp &targetOp, llvm::ArrayRef mapSyms, llvm::ArrayRef mapSymLocs, llvm::ArrayRef mapSymTypes, - const mlir::Location ¤tLocation) { + const mlir::Location ¤tLocation, + const ConstructQueue &queue, ConstructQueue::iterator item) { assert(mapSymTypes.size() == mapSymLocs.size()); fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); @@ -983,15 +923,22 @@ genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, // Create the insertion point after the marker. firOpBuilder.setInsertionPointAfter(undefMarker.getDefiningOp()); - if (genNested) + + if (ConstructQueue::iterator next = std::next(item); next != queue.end()) { + genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, + next); + } else { genNestedEvaluations(converter, eval); + } } template -static OpTy genOpWithBody(OpWithBodyGenInfo &info, Args &&...args) { +static OpTy genOpWithBody(const OpWithBodyGenInfo &info, + const ConstructQueue &queue, + ConstructQueue::iterator item, Args &&...args) { auto op = info.converter.getFirOpBuilder().create( info.loc, std::forward(args)...); - createBodyOfOp(*op, info); + createBodyOfOp(*op, info, queue, item); return op; } @@ -1276,7 +1223,8 @@ static mlir::omp::BarrierOp genBarrierOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const ConstructQueue &queue, ConstructQueue::iterator item) { return converter.getFirOpBuilder().create(loc); } @@ -1284,8 +1232,9 @@ static mlir::omp::CriticalOp genCriticalOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses, + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item, const std::optional &name) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::FlatSymbolRefAttr nameAttr; @@ -1308,17 +1257,17 @@ genCriticalOp(Fortran::lower::AbstractConverter &converter, return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, - llvm::omp::Directive::OMPD_critical) - .setGenNested(genNested), - nameAttr); + llvm::omp::Directive::OMPD_critical), + queue, item, nameAttr); } static mlir::omp::DistributeOp genDistributeOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Distribute construct"); return nullptr; } @@ -1328,7 +1277,8 @@ genFlushOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ObjectList &objects, const List &clauses) { + const ObjectList &objects, const List &clauses, + const ConstructQueue &queue, ConstructQueue::iterator item) { llvm::SmallVector operandRange; genFlushClauses(converter, semaCtx, objects, clauses, loc, operandRange); @@ -1340,12 +1290,13 @@ static mlir::omp::MasterOp genMasterOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, - llvm::omp::Directive::OMPD_master) - .setGenNested(genNested)); + llvm::omp::Directive::OMPD_master), + queue, item); } static mlir::omp::OrderedOp @@ -1353,7 +1304,8 @@ genOrderedOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses) { + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "OMPD_ordered"); return nullptr; } @@ -1362,25 +1314,25 @@ static mlir::omp::OrderedRegionOp genOrderedRegionOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { mlir::omp::OrderedRegionClauseOps clauseOps; genOrderedRegionClauses(converter, semaCtx, clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, - llvm::omp::Directive::OMPD_ordered) - .setGenNested(genNested), - clauseOps); + llvm::omp::Directive::OMPD_ordered), + queue, item, clauseOps); } static mlir::omp::ParallelOp genParallelOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses, - bool outerCombined = false) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item, bool outerCombined = false) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; mlir::omp::ParallelClauseOps clauseOps; @@ -1399,14 +1351,14 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, OpWithBodyGenInfo genInfo = OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_parallel) - .setGenNested(genNested) .setOuterCombined(outerCombined) .setClauses(&clauses) .setReductions(&reductionSyms, &reductionTypes) .setGenRegionEntryCb(reductionCallback); if (!enableDelayedPrivatization) - return genOpWithBody(genInfo, clauseOps); + return genOpWithBody(genInfo, queue, item, + clauseOps); bool privatize = !outerCombined; DataSharingProcessor dsp(converter, semaCtx, clauses, eval, @@ -1454,19 +1406,23 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, }; genInfo.setGenRegionEntryCb(genRegionEntryCB).setDataSharingProcessor(&dsp); - return genOpWithBody(genInfo, clauseOps); + return genOpWithBody(genInfo, queue, item, clauseOps); } static mlir::omp::SectionOp genSectionOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { + // Currently only private/firstprivate clause is handled, and + // all privatization is done within `omp.section` operations. return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_section) - .setGenNested(genNested)); + .setClauses(&clauses), + queue, item); } static mlir::omp::SectionsOp @@ -1474,12 +1430,77 @@ genSectionsOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const mlir::omp::SectionsClauseOps &clauseOps) { - return genOpWithBody( + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { + mlir::omp::SectionsClauseOps clauseOps; + genSectionsClauses(converter, semaCtx, clauses, loc, clauseOps); + + auto &builder = converter.getFirOpBuilder(); + + // Insert privatizations before SECTIONS + symTable.pushScope(); + DataSharingProcessor dsp(converter, semaCtx, clauses, eval); + dsp.processStep1(); + + List nonDsaClauses; + List lastprivates; + + for (const Clause &clause : clauses) { + if (clause.id == llvm::omp::Clause::OMPC_lastprivate) { + lastprivates.push_back(&std::get(clause.u)); + } else { + switch (clause.id) { + case llvm::omp::Clause::OMPC_firstprivate: + case llvm::omp::Clause::OMPC_private: + case llvm::omp::Clause::OMPC_shared: + break; + default: + nonDsaClauses.push_back(clause); + } + } + } + + // SECTIONS construct. + mlir::omp::SectionsOp sectionsOp = genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_sections) - .setGenNested(false), - clauseOps); + .setClauses(&nonDsaClauses), + queue, item, clauseOps); + + if (!lastprivates.empty()) { + mlir::Region §ionsBody = sectionsOp.getRegion(); + assert(sectionsBody.hasOneBlock()); + mlir::Block &body = sectionsBody.front(); + + auto lastSectionOp = llvm::find_if( + llvm::reverse(body.getOperations()), [](const mlir::Operation &op) { + return llvm::isa(op); + }); + assert(lastSectionOp != body.rend()); + + for (const clause::Lastprivate *lastp : lastprivates) { + builder.setInsertionPoint( + lastSectionOp->getRegion(0).back().getTerminator()); + mlir::OpBuilder::InsertPoint insp = builder.saveInsertionPoint(); + const auto &objList = std::get(lastp->t); + for (const Object &object : objList) { + Fortran::semantics::Symbol *sym = object.id(); + converter.copyHostAssociateVar(*sym, &insp); + } + } + } + + // Perform DataSharingProcessor's step2 out of SECTIONS + builder.setInsertionPointAfter(sectionsOp.getOperation()); + dsp.processStep2(sectionsOp, false); + // Emit implicit barrier to synchronize threads and avoid data + // races on post-update of lastprivate variables when `nowait` + // clause is present. + if (clauseOps.nowaitAttr && !lastprivates.empty()) + builder.create(loc); + + symTable.popScope(); + return sectionsOp; } static mlir::omp::SimdOp @@ -1487,7 +1508,8 @@ genSimdOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses) { + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); DataSharingProcessor dsp(converter, semaCtx, clauses, eval); dsp.processStep1(); @@ -1522,7 +1544,8 @@ genSimdOp(Fortran::lower::AbstractConverter &converter, *nestedEval, llvm::omp::Directive::OMPD_simd) .setClauses(&clauses) .setDataSharingProcessor(&dsp) - .setGenRegionEntryCb(ivCallback)); + .setGenRegionEntryCb(ivCallback), + queue, item); return simdOp; } @@ -1531,26 +1554,26 @@ static mlir::omp::SingleOp genSingleOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { mlir::omp::SingleClauseOps clauseOps; genSingleClauses(converter, semaCtx, clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_single) - .setGenNested(genNested) .setClauses(&clauses), - clauseOps); + queue, item, clauseOps); } static mlir::omp::TargetOp genTargetOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses, - bool outerCombined = false) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item, bool outerCombined = false) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; @@ -1657,8 +1680,8 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::visitAllSymbols(eval, captureImplicitMap); auto targetOp = firOpBuilder.create(loc, clauseOps); - genBodyOfTargetOp(converter, symTable, semaCtx, eval, genNested, targetOp, - mapSyms, mapLocs, mapTypes, loc); + genBodyOfTargetOp(converter, symTable, semaCtx, eval, targetOp, mapSyms, + mapLocs, mapTypes, loc, queue, item); return targetOp; } @@ -1666,8 +1689,9 @@ static mlir::omp::TargetDataOp genTargetDataOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TargetDataClauseOps clauseOps; llvm::SmallVector useDeviceTypes; @@ -1679,9 +1703,9 @@ genTargetDataOp(Fortran::lower::AbstractConverter &converter, auto targetDataOp = converter.getFirOpBuilder().create(loc, clauseOps); - genBodyOfTargetDataOp(converter, symTable, semaCtx, eval, genNested, - targetDataOp, useDeviceTypes, useDeviceLocs, - useDeviceSyms, loc); + genBodyOfTargetDataOp(converter, symTable, semaCtx, eval, targetDataOp, + useDeviceTypes, useDeviceLocs, useDeviceSyms, loc, + queue, item); return targetDataOp; } @@ -1690,8 +1714,9 @@ static OpTy genTargetEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - mlir::Location loc, - const List &clauses) { + mlir::Location loc, const List &clauses, + const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; @@ -1718,8 +1743,9 @@ static mlir::omp::TaskOp genTaskOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TaskClauseOps clauseOps; genTaskClauses(converter, semaCtx, stmtCtx, clauses, loc, clauseOps); @@ -1727,26 +1753,25 @@ genTaskOp(Fortran::lower::AbstractConverter &converter, return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_task) - .setGenNested(genNested) .setClauses(&clauses), - clauseOps); + queue, item, clauseOps); } static mlir::omp::TaskgroupOp genTaskgroupOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { mlir::omp::TaskgroupClauseOps clauseOps; genTaskgroupClauses(converter, semaCtx, clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_taskgroup) - .setGenNested(genNested) .setClauses(&clauses), - clauseOps); + queue, item, clauseOps); } static mlir::omp::TaskloopOp @@ -1754,7 +1779,8 @@ genTaskloopOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses) { + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Taskloop construct"); } @@ -1763,7 +1789,8 @@ genTaskwaitOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses) { + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { mlir::omp::TaskwaitClauseOps clauseOps; genTaskwaitClauses(converter, semaCtx, clauses, loc, clauseOps); return converter.getFirOpBuilder().create(loc, @@ -1774,7 +1801,8 @@ static mlir::omp::TaskyieldOp genTaskyieldOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const ConstructQueue &queue, ConstructQueue::iterator item) { return converter.getFirOpBuilder().create(loc); } @@ -1782,9 +1810,9 @@ static mlir::omp::TeamsOp genTeamsOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &clauses, - bool outerCombined = false) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item, bool outerCombined = false) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TeamsClauseOps clauseOps; genTeamsClauses(converter, semaCtx, stmtCtx, clauses, loc, clauseOps); @@ -1792,10 +1820,9 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter, return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_teams) - .setGenNested(genNested) .setOuterCombined(outerCombined) .setClauses(&clauses), - clauseOps); + queue, item, clauseOps); } static mlir::omp::WsloopOp @@ -1803,7 +1830,8 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses) { + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); DataSharingProcessor dsp(converter, semaCtx, clauses, eval); dsp.processStep1(); @@ -1844,7 +1872,8 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, .setClauses(&clauses) .setDataSharingProcessor(&dsp) .setReductions(&reductionSyms, &reductionTypes) - .setGenRegionEntryCb(ivCallback)); + .setGenRegionEntryCb(ivCallback), + queue, item); return wsloopOp; } @@ -1852,13 +1881,13 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, // Code generation functions for composite constructs //===----------------------------------------------------------------------===// -static void -genCompositeDistributeParallelDo(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const List &clauses, - mlir::Location loc) { +static void genCompositeDistributeParallelDo( + Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO"); } @@ -1866,8 +1895,9 @@ static void genCompositeDistributeParallelDoSimd( Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, const List &clauses, - mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, mlir::Location loc, + const List &clauses, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO SIMD"); } @@ -1876,7 +1906,9 @@ genCompositeDistributeSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &clauses, mlir::Location loc) { + mlir::Location loc, const List &clauses, + const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE SIMD"); } @@ -1884,8 +1916,9 @@ static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &clauses, - mlir::Location loc) { + mlir::Location loc, const List &clauses, + const ConstructQueue &queue, + ConstructQueue::iterator item) { ClauseProcessor cp(converter, semaCtx, clauses); cp.processTODO( @@ -1898,7 +1931,7 @@ static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, // When support for vectorization is enabled, then we need to add handling of // if clause. Currently if clause can be skipped because we always assume // SIMD length = 1. - genWsloopOp(converter, symTable, semaCtx, eval, loc, clauses); + genWsloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); } static void @@ -1906,10 +1939,128 @@ genCompositeTaskloopSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &clauses, mlir::Location loc) { + mlir::Location loc, const List &clauses, + const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Composite TASKLOOP SIMD"); } +//===----------------------------------------------------------------------===// +// Dispatch +//===----------------------------------------------------------------------===// + +static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { + assert(item != queue.end()); + const List &clauses = item->clauses; + + switch (llvm::omp::Directive dir = item->id) { + case llvm::omp::Directive::OMPD_distribute: + genDistributeOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_do: + genWsloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_loop: + case llvm::omp::Directive::OMPD_masked: + case llvm::omp::Directive::OMPD_tile: + case llvm::omp::Directive::OMPD_unroll: + TODO(loc, "Unhandled loop directive (" + + llvm::omp::getOpenMPDirectiveName(dir) + ")"); + break; + case llvm::omp::Directive::OMPD_master: + genMasterOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_ordered: + genOrderedRegionOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_parallel: + genParallelOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item, + /*outerCombined=*/false); + break; + case llvm::omp::Directive::OMPD_sections: + genSectionsOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_simd: + genSimdOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_single: + genSingleOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_target: + genTargetOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item, + /*outerCombined=*/false); + break; + case llvm::omp::Directive::OMPD_target_data: + genTargetDataOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_target_enter_data: + genTargetEnterExitUpdateDataOp( + converter, symTable, semaCtx, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_target_exit_data: + genTargetEnterExitUpdateDataOp( + converter, symTable, semaCtx, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_target_update: + genTargetEnterExitUpdateDataOp( + converter, symTable, semaCtx, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_task: + genTaskOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_taskgroup: + genTaskgroupOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_taskloop: + genTaskloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_teams: + genTeamsOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + // case llvm::omp::Directive::OMPD_workdistribute: + case llvm::omp::Directive::OMPD_workshare: + // FIXME: Workshare is not a commonly used OpenMP construct, an + // implementation for this feature will come later. For the codes + // that use this construct, add a single construct for now. + genSingleOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + break; + // Composite constructs + case llvm::omp::Directive::OMPD_distribute_parallel_do: + genCompositeDistributeParallelDo(converter, symTable, semaCtx, eval, loc, + clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: + genCompositeDistributeParallelDoSimd(converter, symTable, semaCtx, eval, + loc, clauses, queue, item); + break; + case llvm::omp::Directive::OMPD_distribute_simd: + genCompositeDistributeSimd(converter, symTable, semaCtx, eval, loc, clauses, + queue, item); + break; + case llvm::omp::Directive::OMPD_do_simd: + genCompositeDoSimd(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_taskloop_simd: + genCompositeTaskloopSimd(converter, symTable, semaCtx, eval, loc, clauses, + queue, item); + break; + default: + break; + } +} + //===----------------------------------------------------------------------===// // OpenMPDeclarativeConstruct visitors //===----------------------------------------------------------------------===// @@ -2020,36 +2171,47 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, semaCtx); mlir::Location currentLocation = converter.genLocation(directive.source); + ConstructQueue queue{ + buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, + eval, directive.source, directive.v, clauses)}; + switch (directive.v) { default: break; case llvm::omp::Directive::OMPD_barrier: - genBarrierOp(converter, symTable, semaCtx, eval, currentLocation); + genBarrierOp(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); break; case llvm::omp::Directive::OMPD_taskwait: - genTaskwaitOp(converter, symTable, semaCtx, eval, currentLocation, clauses); + genTaskwaitOp(converter, symTable, semaCtx, eval, currentLocation, clauses, + queue, queue.begin()); break; case llvm::omp::Directive::OMPD_taskyield: - genTaskyieldOp(converter, symTable, semaCtx, eval, currentLocation); + genTaskyieldOp(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); break; case llvm::omp::Directive::OMPD_target_data: - genTargetDataOp(converter, symTable, semaCtx, eval, /*genNested=*/true, - currentLocation, clauses); + genTargetDataOp(converter, symTable, semaCtx, eval, currentLocation, + clauses, queue, queue.begin()); break; case llvm::omp::Directive::OMPD_target_enter_data: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses); + converter, symTable, semaCtx, currentLocation, clauses, queue, + queue.begin()); break; case llvm::omp::Directive::OMPD_target_exit_data: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses); + converter, symTable, semaCtx, currentLocation, clauses, queue, + queue.begin()); break; case llvm::omp::Directive::OMPD_target_update: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses); + converter, symTable, semaCtx, currentLocation, clauses, queue, + queue.begin()); break; case llvm::omp::Directive::OMPD_ordered: - genOrderedOp(converter, symTable, semaCtx, eval, currentLocation, clauses); + genOrderedOp(converter, symTable, semaCtx, eval, currentLocation, clauses, + queue, queue.begin()); break; } } @@ -2073,8 +2235,12 @@ genOMP(Fortran::lower::AbstractConverter &converter, [&](auto &&s) { return makeClause(s.v, semaCtx); }) : List{}; mlir::Location currentLocation = converter.genLocation(verbatim.source); + + ConstructQueue queue{buildConstructQueue( + converter.getFirOpBuilder().getModule(), semaCtx, eval, verbatim.source, + llvm::omp::Directive::OMPD_flush, clauses)}; genFlushOp(converter, symTable, semaCtx, eval, currentLocation, objects, - clauses); + clauses, queue, queue.begin()); } static void @@ -2217,75 +2383,15 @@ genOMP(Fortran::lower::AbstractConverter &converter, } } - std::optional nextDir = origDirective; - bool outermostLeafConstruct = true; - while (nextDir) { - llvm::omp::Directive leafDir; - std::tie(leafDir, nextDir) = splitCombinedDirective(*nextDir); - const bool genNested = !nextDir; - const bool outerCombined = outermostLeafConstruct && nextDir.has_value(); - switch (leafDir) { - case llvm::omp::Directive::OMPD_master: - // 2.16 MASTER construct. - genMasterOp(converter, symTable, semaCtx, eval, genNested, - currentLocation); - break; - case llvm::omp::Directive::OMPD_ordered: - // 2.17.9 ORDERED construct. - genOrderedRegionOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_parallel: - // 2.6 PARALLEL construct. - genParallelOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses, outerCombined); - break; - case llvm::omp::Directive::OMPD_single: - // 2.8.2 SINGLE construct. - genSingleOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_target: - // 2.12.5 TARGET construct. - genTargetOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses, outerCombined); - break; - case llvm::omp::Directive::OMPD_target_data: - // 2.12.2 TARGET DATA construct. - genTargetDataOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_task: - // 2.10.1 TASK construct. - genTaskOp(converter, symTable, semaCtx, eval, genNested, currentLocation, - clauses); - break; - case llvm::omp::Directive::OMPD_taskgroup: - // 2.17.6 TASKGROUP construct. - genTaskgroupOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_teams: - // 2.7 TEAMS construct. - // FIXME Pass the outerCombined argument or rename it to better describe - // what it represents if it must always be `false` in this context. - genTeamsOp(converter, symTable, semaCtx, eval, genNested, currentLocation, - clauses); - break; - case llvm::omp::Directive::OMPD_workshare: - // 2.8.3 WORKSHARE construct. - // FIXME: Workshare is not a commonly used OpenMP construct, an - // implementation for this feature will come later. For the codes - // that use this construct, add a single construct for now. - genSingleOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - default: - llvm_unreachable("Unexpected block construct"); - break; - } - outermostLeafConstruct = false; - } + llvm::omp::Directive directive = + std::get(beginBlockDirective.t).v; + const parser::CharBlock &source = + std::get(beginBlockDirective.t).source; + ConstructQueue queue{ + buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, + eval, source, directive, clauses)}; + genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); } static void @@ -2298,10 +2404,15 @@ genOMP(Fortran::lower::AbstractConverter &converter, std::get(criticalConstruct.t); List clauses = makeClauses(std::get(cd.t), semaCtx); + + ConstructQueue queue{buildConstructQueue( + converter.getFirOpBuilder().getModule(), semaCtx, eval, cd.source, + llvm::omp::Directive::OMPD_critical, clauses)}; + const auto &name = std::get>(cd.t); mlir::Location currentLocation = converter.getCurrentLocation(); - genCriticalOp(converter, symTable, semaCtx, eval, /*genNested=*/true, - currentLocation, clauses, name); + genCriticalOp(converter, symTable, semaCtx, eval, currentLocation, clauses, + queue, queue.begin(), name); } static void @@ -2322,14 +2433,6 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, std::get(loopConstruct.t); List clauses = makeClauses( std::get(beginLoopDirective.t), semaCtx); - mlir::Location currentLocation = - converter.genLocation(beginLoopDirective.source); - const auto origDirective = - std::get(beginLoopDirective.t).v; - - assert(llvm::omp::loopConstructSet.test(origDirective) && - "Expected loop construct"); - if (auto &endLoopDirective = std::get>( loopConstruct.t)) { @@ -2338,101 +2441,18 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, semaCtx)); } - std::optional nextDir = origDirective; - while (nextDir) { - llvm::omp::Directive leafDir; - std::tie(leafDir, nextDir) = splitCombinedDirective(*nextDir); - if (llvm::omp::compositeConstructSet.test(leafDir)) { - assert(!nextDir && "Composite construct cannot be split"); - switch (leafDir) { - case llvm::omp::Directive::OMPD_distribute_parallel_do: - // 2.9.4.3 DISTRIBUTE PARALLEL Worksharing-Loop construct. - genCompositeDistributeParallelDo(converter, symTable, semaCtx, eval, - clauses, currentLocation); - break; - case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: - // 2.9.4.4 DISTRIBUTE PARALLEL Worksharing-Loop SIMD construct. - genCompositeDistributeParallelDoSimd(converter, symTable, semaCtx, eval, - clauses, currentLocation); - break; - case llvm::omp::Directive::OMPD_distribute_simd: - // 2.9.4.2 DISTRIBUTE SIMD construct. - genCompositeDistributeSimd(converter, symTable, semaCtx, eval, clauses, - currentLocation); - break; - case llvm::omp::Directive::OMPD_do_simd: - // 2.9.3.2 Worksharing-Loop SIMD construct. - genCompositeDoSimd(converter, symTable, semaCtx, eval, clauses, - currentLocation); - break; - case llvm::omp::Directive::OMPD_taskloop_simd: - // 2.10.3 TASKLOOP SIMD construct. - genCompositeTaskloopSimd(converter, symTable, semaCtx, eval, clauses, - currentLocation); - break; - default: - llvm_unreachable("Unexpected composite construct"); - } - } else { - const bool genNested = !nextDir; - switch (leafDir) { - case llvm::omp::Directive::OMPD_distribute: - // 2.9.4.1 DISTRIBUTE construct. - genDistributeOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_do: - // 2.9.2 Worksharing-Loop construct. - genWsloopOp(converter, symTable, semaCtx, eval, currentLocation, - clauses); - break; - case llvm::omp::Directive::OMPD_parallel: - // 2.6 PARALLEL construct. - // FIXME This is not necessarily always the outer leaf construct of a - // combined construct in this constext (e.g. distribute parallel do). - // Maybe rename the argument if it represents something else or - // initialize it properly. - genParallelOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses, - /*outerCombined=*/true); - break; - case llvm::omp::Directive::OMPD_simd: - // 2.9.3.1 SIMD construct. - genSimdOp(converter, symTable, semaCtx, eval, currentLocation, clauses); - break; - case llvm::omp::Directive::OMPD_target: - // 2.12.5 TARGET construct. - genTargetOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses, /*outerCombined=*/true); - break; - case llvm::omp::Directive::OMPD_taskloop: - // 2.10.2 TASKLOOP construct. - genTaskloopOp(converter, symTable, semaCtx, eval, currentLocation, - clauses); - break; - case llvm::omp::Directive::OMPD_teams: - // 2.7 TEAMS construct. - // FIXME This is not necessarily always the outer leaf construct of a - // combined construct in this constext (e.g. target teams distribute). - // Maybe rename the argument if it represents something else or - // initialize it properly. - genTeamsOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, clauses, /*outerCombined=*/true); - break; - case llvm::omp::Directive::OMPD_loop: - case llvm::omp::Directive::OMPD_masked: - case llvm::omp::Directive::OMPD_master: - case llvm::omp::Directive::OMPD_tile: - case llvm::omp::Directive::OMPD_unroll: - TODO(currentLocation, "Unhandled loop directive (" + - llvm::omp::getOpenMPDirectiveName(leafDir) + - ")"); - break; - default: - llvm_unreachable("Unexpected loop construct"); - } - } - } + mlir::Location currentLocation = + converter.genLocation(beginLoopDirective.source); + + llvm::omp::Directive directive = + std::get(beginLoopDirective.t).v; + const parser::CharBlock &source = + std::get(beginLoopDirective.t).source; + ConstructQueue queue{ + buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, + eval, source, directive, clauses)}; + genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); } static void @@ -2441,8 +2461,12 @@ genOMP(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPSectionConstruct §ionConstruct) { - // SECTION constructs are handled as a part of SECTIONS. - llvm_unreachable("Unexpected standalone OMP SECTION"); + mlir::Location loc = converter.getCurrentLocation(); + ConstructQueue queue{buildConstructQueue( + converter.getFirOpBuilder().getModule(), semaCtx, eval, + sectionConstruct.source, llvm::omp::Directive::OMPD_section, {})}; + genSectionOp(converter, symTable, semaCtx, eval, loc, + /*clauses=*/{}, queue, queue.begin()); } static void @@ -2461,77 +2485,17 @@ genOMP(Fortran::lower::AbstractConverter &converter, clauses.append(makeClauses( std::get(endSectionsDirective.t), semaCtx)); - - // Process clauses before optional omp.parallel, so that new variables are - // allocated outside of the parallel region mlir::Location currentLocation = converter.getCurrentLocation(); - mlir::omp::SectionsClauseOps clauseOps; - genSectionsClauses(converter, semaCtx, clauses, currentLocation, clauseOps); - - // Parallel wrapper of PARALLEL SECTIONS construct - llvm::omp::Directive dir = - std::get(beginSectionsDirective.t) - .v; - if (dir == llvm::omp::Directive::OMPD_parallel_sections) { - genParallelOp(converter, symTable, semaCtx, eval, - /*genNested=*/false, currentLocation, clauses, - /*outerCombined=*/true); - } - - // Insert privatizations before SECTIONS - symTable.pushScope(); - DataSharingProcessor dsp(converter, semaCtx, clauses, eval); - dsp.processStep1(); - - // SECTIONS construct. - mlir::omp::SectionsOp sectionsOp = genSectionsOp( - converter, symTable, semaCtx, eval, currentLocation, clauseOps); - - // Generate nested SECTION operations recursively. - const auto §ionBlocks = - std::get(sectionsConstruct.t); - auto &firOpBuilder = converter.getFirOpBuilder(); - auto ip = firOpBuilder.saveInsertionPoint(); - mlir::omp::SectionOp lastSectionOp; - for (const auto &[nblock, neval] : - llvm::zip(sectionBlocks.v, eval.getNestedEvaluations())) { - symTable.pushScope(); - lastSectionOp = genSectionOp(converter, symTable, semaCtx, neval, - /*genNested=*/true, currentLocation); - symTable.popScope(); - firOpBuilder.restoreInsertionPoint(ip); - } - - // For `omp.sections`, lastprivatized variables occur in - // lexically final `omp.section` operation. - bool hasLastPrivate = false; - if (lastSectionOp) { - for (const Clause &clause : clauses) { - if (const auto *lastPrivate = - std::get_if(&clause.u)) { - hasLastPrivate = true; - firOpBuilder.setInsertionPoint( - lastSectionOp.getRegion().back().getTerminator()); - mlir::OpBuilder::InsertPoint lastPrivIP = - converter.getFirOpBuilder().saveInsertionPoint(); - const auto &objList = std::get<1>(lastPrivate->t); - for (const Object &obj : objList) { - Fortran::semantics::Symbol *sym = obj.id(); - converter.copyHostAssociateVar(*sym, &lastPrivIP); - } - } - } - } - // Perform DataSharingProcessor's step2 out of SECTIONS - firOpBuilder.setInsertionPointAfter(sectionsOp.getOperation()); - dsp.processStep2(sectionsOp, false); - // Emit implicit barrier to synchronize threads and avoid data - // races on post-update of lastprivate variables when `nowait` - // clause is present. - if (clauseOps.nowaitAttr && hasLastPrivate) - firOpBuilder.create(converter.getCurrentLocation()); - symTable.popScope(); + llvm::omp::Directive directive = + std::get(beginSectionsDirective.t).v; + const parser::CharBlock &source = + std::get(beginSectionsDirective.t).source; + ConstructQueue queue{ + buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, + eval, source, directive, clauses)}; + genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); } static void genOMP(Fortran::lower::AbstractConverter &converter, diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp index eed63b226133..cb1d1a5a7f3d 100644 --- a/flang/lib/Lower/OpenMP/Utils.cpp +++ b/flang/lib/Lower/OpenMP/Utils.cpp @@ -51,12 +51,6 @@ int64_t getCollapseValue(const List &clauses) { return 1; } -uint32_t getOpenMPVersion(mlir::ModuleOp mod) { - if (mlir::Attribute verAttr = mod->getAttr("omp.version")) - return llvm::cast(verAttr).getVersion(); - llvm_unreachable("Expecting OpenMP version attribute in module"); -} - void genObjectList(const ObjectList &objects, Fortran::lower::AbstractConverter &converter, llvm::SmallVectorImpl &operands) { diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h index 8fbb18fa8656..345ce55620ee 100644 --- a/flang/lib/Lower/OpenMP/Utils.h +++ b/flang/lib/Lower/OpenMP/Utils.h @@ -93,7 +93,6 @@ void gatherFuncAndVarSyms( llvm::SmallVectorImpl &symbolAndClause); int64_t getCollapseValue(const List &clauses); -uint32_t getOpenMPVersion(mlir::ModuleOp mod); Fortran::semantics::Symbol * getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject); diff --git a/flang/test/Lower/OpenMP/default-clause-byref.f90 b/flang/test/Lower/OpenMP/default-clause-byref.f90 index 62ba67e5962f..7cc2bc2e0c71 100644 --- a/flang/test/Lower/OpenMP/default-clause-byref.f90 +++ b/flang/test/Lower/OpenMP/default-clause-byref.f90 @@ -161,12 +161,12 @@ subroutine nested_default_clause_tests !CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFnested_default_clause_testsEz"} !CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: omp.parallel { +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} !CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref !CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref -!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} -!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_testsEz"} !CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFnested_default_clause_testsEk"} @@ -221,6 +221,7 @@ subroutine nested_default_clause_tests !CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} !CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} !CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) diff --git a/flang/test/Lower/OpenMP/default-clause.f90 b/flang/test/Lower/OpenMP/default-clause.f90 index a90f0f4ef5f8..843ee6bb7910 100644 --- a/flang/test/Lower/OpenMP/default-clause.f90 +++ b/flang/test/Lower/OpenMP/default-clause.f90 @@ -160,12 +160,12 @@ end program default_clause_lowering !CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFnested_default_clause_test1Ez"} !CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFnested_default_clause_test1Ez"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: omp.parallel { +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_test1Ey"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_test1Ey"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_test1Ex"} !CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_test1Ex"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref !CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref -!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_test1Ey"} -!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_test1Ey"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_test1Ez"} !CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_test1Ez"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[PRIVATE_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFnested_default_clause_test1Ek"} diff --git a/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 b/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 index b7f11c8c722f..e6ee75c8a5be 100644 --- a/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 +++ b/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 @@ -145,10 +145,10 @@ end subroutine !CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) !CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg2"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) !CHECK: omp.parallel { -!CHECK-DAG: %[[CLONE1:.*]] = fir.alloca i32 {bindc_name = "arg1" -!CHECK-DAG: %[[CLONE1_DECL:.*]]:2 = hlfir.declare %[[CLONE1]] {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK-DAG: %[[CLONE2:.*]] = fir.alloca i32 {bindc_name = "arg2" !CHECK-DAG: %[[CLONE2_DECL:.*]]:2 = hlfir.declare %[[CLONE2]] {uniq_name = "_QFmult_lastprivate_int2Earg2"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK-DAG: %[[CLONE1:.*]] = fir.alloca i32 {bindc_name = "arg1" +!CHECK-DAG: %[[CLONE1_DECL:.*]]:2 = hlfir.declare %[[CLONE1]] {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: omp.wsloop { !CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} { diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h index daef02bcfc9a..13a37265762a 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h @@ -178,6 +178,12 @@ template using ListT = llvm::SmallVector; // provide their own specialization that conforms to the above requirements. template struct ObjectT; +// By default, object equality is only determined by its identity. +template +bool operator==(const ObjectT &o1, const ObjectT &o2) { + return o1.id() == o2.id(); +} + template using ObjectListT = ListT>; using DirectiveName = llvm::omp::Directive; @@ -264,6 +270,32 @@ struct ReductionIdentifierT { template // using IteratorT = ListT>; + +template +std::enable_if_t operator==(const T &a, + const T &b) { + return true; +} +template +std::enable_if_t operator==(const T &a, + const T &b) { + return true; +} +template +std::enable_if_t operator==(const T &a, + const T &b) { + return a.v == b.v; +} +template +std::enable_if_t operator==(const T &a, + const T &b) { + return a.t == b.t; +} +template +std::enable_if_t operator==(const T &a, + const T &b) { + return a.u == b.u; +} } // namespace type template using ListT = type::ListT; @@ -285,6 +317,8 @@ ListT makeList(ContainerTy &&container, FunctionTy &&func) { } namespace clause { +using type::operator==; + // V5.2: [8.3.1] `assumption` clauses template // struct AbsentT { @@ -726,7 +760,7 @@ struct LinearT { ENUM(LinearModifier, Ref, Val, Uval); using TupleTrait = std::true_type; - // Step == nullptr means 1. + // Step == nullopt means 1. std::tuple t; @@ -1142,9 +1176,11 @@ struct UsesAllocatorsT { using MemSpace = E; using TraitsArray = ObjectT; using Allocator = E; - using AllocatorSpec = - std::tuple; // Not a spec name - using Allocators = ListT; // Not a spec name + struct AllocatorSpec { // Not a spec name + using TupleTrait = std::true_type; + std::tuple t; + }; + using Allocators = ListT; // Not a spec name using WrapperTrait = std::true_type; Allocators v; }; @@ -1232,9 +1268,10 @@ using UnionOfAllClausesT = typename type::Union< // UnionClausesT, // WrapperClausesT // >::type; - } // namespace clause +using type::operator==; + // The variant wrapper that encapsulates all possible specific clauses. // The `Extras` arguments are additional types representing local extensions // to the clause set, e.g. @@ -1244,6 +1281,9 @@ using UnionOfAllClausesT = typename type::Union< // // // The member Clause::u will be a variant containing all specific clauses // defined above, plus MyClause1 and MyClause2. +// +// Note: Any derived class must be constructible from the base class +// ClauseT<...>. template struct ClauseT { @@ -1251,6 +1291,9 @@ struct ClauseT { using IdTy = IdType; using ExprTy = ExprType; + // Type of "self" to specify this type given a derived class type. + using BaseT = ClauseT; + using VariantTy = typename type::Union< clause::UnionOfAllClausesT, std::variant>::type; @@ -1260,6 +1303,11 @@ struct ClauseT { VariantTy u; }; +template struct DirectiveWithClauses { + llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown; + tomp::type::ListT clauses; +}; + } // namespace tomp #undef OPT diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h new file mode 100644 index 000000000000..edb65ed6d324 --- /dev/null +++ b/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h @@ -0,0 +1,403 @@ +//===- ConstructCompositionT.h -- Composing compound constructs -----------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// Given a list of leaf construct, each with a set of clauses, generate the +// compound construct whose leaf constructs are the given list, and whose clause +// list is the merged lists of individual leaf clauses. +// +// *** At the moment it assumes that the individual constructs and their clauses +// *** are a subset of those created by splitting a valid compound construct. +//===----------------------------------------------------------------------===// +#ifndef LLVM_FRONTEND_OPENMP_CONSTRUCTCOMPOSITIONT_H +#define LLVM_FRONTEND_OPENMP_CONSTRUCTCOMPOSITIONT_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Frontend/OpenMP/ClauseT.h" +#include "llvm/Frontend/OpenMP/OMP.h" + +#include +#include +#include +#include +#include +#include + +namespace tomp { +template struct ConstructCompositionT { + using ClauseTy = ClauseType; + + using TypeTy = typename ClauseTy::TypeTy; + using IdTy = typename ClauseTy::IdTy; + using ExprTy = typename ClauseTy::ExprTy; + + ConstructCompositionT(uint32_t version, + llvm::ArrayRef> leafs); + + DirectiveWithClauses merged; + +private: + // Use an ordered container, since we beed to maintain the order in which + // clauses are added to it. This is to avoid non-deterministic output. + using ClauseSet = ListT; + + enum class Presence { + All, // Clause is preesnt on all leaf constructs that allow it. + Some, // Clause is present on some, but not on all constructs. + None, // Clause is absent on all constructs. + }; + + template + ClauseTy makeClause(llvm::omp::Clause clauseId, S &&specific) { + return typename ClauseTy::BaseT{clauseId, std::move(specific)}; + } + + llvm::omp::Directive + makeCompound(llvm::ArrayRef> parts); + + Presence checkPresence(llvm::omp::Clause clauseId); + + // There are clauses that need special handling: + // 1. "if": the "directive-name-modifier" on the merged clause may need + // to be set appropriately. + // 2. "reduction": implies "privateness" of all objects (incompatible + // with "shared"); there are rules for merging modifiers + void mergeIf(); + void mergeReduction(); + void mergeDSA(); + + uint32_t version; + llvm::ArrayRef> leafs; + + // clause id -> set of leaf constructs that contain it + std::unordered_map clausePresence; + // clause id -> set of instances of that clause + std::unordered_map clauseSets; +}; + +template +ConstructCompositionT::ConstructCompositionT( + uint32_t version, llvm::ArrayRef> leafs) + : version(version), leafs(leafs) { + // Merge the list of constructs with clauses into a compound construct + // with a single list of clauses. + // The intended use of this function is in splitting compound constructs, + // while preserving composite constituent constructs: + // Step 1: split compound construct into leaf constructs. + // Step 2: identify composite sub-construct, and merge the constituent leafs. + // + // *** At the moment it assumes that the individual constructs and their + // *** clauses are a subset of those created by splitting a valid compound + // *** construct. + // + // 1. Deduplicate clauses + // - exact duplicates: e.g. shared(x) shared(x) -> shared(x) + // - special cases of clauses differing in modifier: + // (a) reduction: inscan + (none|default) = inscan + // (b) reduction: task + (none|default) = task + // (c) combine repeated "if" clauses if possible + // 2. Merge DSA clauses: e.g. private(x) private(y) -> private(x, y). + // 3. Resolve potential DSA conflicts (typically due to implied clauses). + + if (leafs.empty()) + return; + + merged.id = makeCompound(leafs); + + // Populate the two maps: + for (const auto &[index, leaf] : llvm::enumerate(leafs)) { + for (const auto &clause : leaf.clauses) { + // Update clausePresence. + auto &pset = clausePresence[clause.id]; + if (pset.size() < leafs.size()) + pset.resize(leafs.size()); + pset.set(index); + // Update clauseSets. + ClauseSet &cset = clauseSets[clause.id]; + if (!llvm::is_contained(cset, clause)) + cset.push_back(clause); + } + } + + mergeIf(); + mergeReduction(); + mergeDSA(); + + // Fir the rest of the clauses, just copy them. + for (auto &[id, clauses] : clauseSets) { + // Skip clauses we've already dealt with. + switch (id) { + case llvm::omp::Clause::OMPC_if: + case llvm::omp::Clause::OMPC_reduction: + case llvm::omp::Clause::OMPC_shared: + case llvm::omp::Clause::OMPC_private: + case llvm::omp::Clause::OMPC_firstprivate: + case llvm::omp::Clause::OMPC_lastprivate: + continue; + default: + break; + } + llvm::append_range(merged.clauses, clauses); + } +} + +template +llvm::omp::Directive ConstructCompositionT::makeCompound( + llvm::ArrayRef> parts) { + llvm::SmallVector dirIds; + llvm::transform(parts, std::back_inserter(dirIds), + [](auto &&dwc) { return dwc.id; }); + + return llvm::omp::getCompoundConstruct(dirIds); +} + +template +auto ConstructCompositionT::checkPresence(llvm::omp::Clause clauseId) + -> Presence { + auto found = clausePresence.find(clauseId); + if (found == clausePresence.end()) + return Presence::None; + + bool OnAll = true, OnNone = true; + for (const auto &[index, leaf] : llvm::enumerate(leafs)) { + if (!llvm::omp::isAllowedClauseForDirective(leaf.id, clauseId, version)) + continue; + + if (found->second.test(index)) + OnNone = false; + else + OnAll = false; + } + + if (OnNone) + return Presence::None; + if (OnAll) + return Presence::All; + return Presence::Some; +} + +template void ConstructCompositionT::mergeIf() { + using IfTy = tomp::clause::IfT; + // Deal with the "if" clauses. If it's on all leafs that allow it, then it + // will apply to the compound construct. Otherwise it will apply to the + // single (assumed) leaf construct. + // This assumes that the "if" clauses have the same expression. + Presence presence = checkPresence(llvm::omp::Clause::OMPC_if); + if (presence == Presence::None) + return; + + const ClauseTy &some = *clauseSets[llvm::omp::Clause::OMPC_if].begin(); + const auto &someIf = std::get(some.u); + + if (presence == Presence::All) { + // Create "if" without "directive-name-modifier". + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_if, + IfTy{{/*DirectiveNameModifier=*/std::nullopt, + /*IfExpression=*/std::get( + someIf.t)}})); + } else { + // Find out where it's present and create "if" with the corresponding + // "directive-name-modifier". + int Idx = clausePresence[llvm::omp::Clause::OMPC_if].find_first(); + assert(Idx >= 0); + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_if, + IfTy{{/*DirectiveNameModifier=*/leafs[Idx].id, + /*IfExpression=*/std::get( + someIf.t)}})); + } +} + +template void ConstructCompositionT::mergeReduction() { + Presence presence = checkPresence(llvm::omp::Clause::OMPC_reduction); + if (presence == Presence::None) + return; + + using ReductionTy = tomp::clause::ReductionT; + using ModifierTy = typename ReductionTy::ReductionModifier; + using IdentifiersTy = typename ReductionTy::ReductionIdentifiers; + using ListTy = typename ReductionTy::List; + // There are exceptions on which constructs "reduction" may appear + // (specifically "parallel", and "teams"). Assume that if "reduction" + // is present, it can be applied to the compound construct. + + // What's left is to see if there are any modifiers present. Again, + // assume that there are no conflicting modifiers. + // There can be, however, multiple reductions on different objects. + auto equal = [](const ClauseTy &red1, const ClauseTy &red2) { + // Extract actual reductions. + const auto r1 = std::get(red1.u); + const auto r2 = std::get(red2.u); + // Compare everything except modifiers. + if (std::get(r1.t) != std::get(r2.t)) + return false; + if (std::get(r1.t) != std::get(r2.t)) + return false; + return true; + }; + + auto getModifier = [](const ClauseTy &clause) { + const ReductionTy &red = std::get(clause.u); + return std::get>(red.t); + }; + + const ClauseSet &reductions = clauseSets[llvm::omp::Clause::OMPC_reduction]; + std::unordered_set visited; + while (reductions.size() != visited.size()) { + typename ClauseSet::const_iterator first; + + // Find first non-visited reduction. + for (first = reductions.begin(); first != reductions.end(); ++first) { + if (visited.count(&*first)) + continue; + visited.insert(&*first); + break; + } + + std::optional modifier = getModifier(*first); + + // Visit all other reductions that are "equal" (with respect to the + // definition above) to "first". Collect modifiers. + for (auto iter = std::next(first); iter != reductions.end(); ++iter) { + if (!equal(*first, *iter)) + continue; + visited.insert(&*iter); + if (!modifier || *modifier == ModifierTy::Default) + modifier = getModifier(*iter); + } + + const auto &firstRed = std::get(first->u); + merged.clauses.emplace_back(makeClause( + llvm::omp::Clause::OMPC_reduction, + ReductionTy{ + {/*ReductionModifier=*/modifier, + /*ReductionIdentifiers=*/std::get(firstRed.t), + /*List=*/std::get(firstRed.t)}})); + } +} + +template void ConstructCompositionT::mergeDSA() { + using ObjectTy = tomp::type::ObjectT; + + // Resolve data-sharing attributes. + enum DSA : int { + None = 0, + Shared = 1 << 0, + Private = 1 << 1, + FirstPrivate = 1 << 2, + LastPrivate = 1 << 3, + LastPrivateConditional = 1 << 4, + }; + + // Use ordered containers to avoid non-deterministic output. + llvm::SmallVector> objectDsa; + + auto getDsa = [&](const ObjectTy &object) -> std::pair & { + auto found = llvm::find_if(objectDsa, [&](std::pair &p) { + return p.first.id() == object.id(); + }); + if (found != objectDsa.end()) + return *found; + return objectDsa.emplace_back(object, DSA::None); + }; + + using SharedTy = tomp::clause::SharedT; + using PrivateTy = tomp::clause::PrivateT; + using FirstprivateTy = tomp::clause::FirstprivateT; + using LastprivateTy = tomp::clause::LastprivateT; + + // Visit clauses that affect DSA. + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_shared]) { + for (auto &object : std::get(clause.u).v) + getDsa(object).second |= DSA::Shared; + } + + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_private]) { + for (auto &object : std::get(clause.u).v) + getDsa(object).second |= DSA::Private; + } + + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_firstprivate]) { + for (auto &object : std::get(clause.u).v) + getDsa(object).second |= DSA::FirstPrivate; + } + + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_lastprivate]) { + using ModifierTy = typename LastprivateTy::LastprivateModifier; + using ListTy = typename LastprivateTy::List; + const auto &lastp = std::get(clause.u); + for (auto &object : std::get(lastp.t)) { + auto &mod = std::get>(lastp.t); + if (mod && *mod == ModifierTy::Conditional) { + getDsa(object).second |= DSA::LastPrivateConditional; + } else { + getDsa(object).second |= DSA::LastPrivate; + } + } + } + + // Check reductions as well, clear "shared" if set. + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_reduction]) { + using ReductionTy = tomp::clause::ReductionT; + using ListTy = typename ReductionTy::List; + for (auto &object : std::get(std::get(clause.u).t)) + getDsa(object).second &= ~DSA::Shared; + } + + tomp::ListT privateObj, sharedObj, firstpObj, lastpObj, lastpcObj; + for (auto &[object, dsa] : objectDsa) { + if (dsa & + (DSA::FirstPrivate | DSA::LastPrivate | DSA::LastPrivateConditional)) { + if (dsa & DSA::FirstPrivate) + firstpObj.push_back(object); // no else + if (dsa & DSA::LastPrivateConditional) + lastpcObj.push_back(object); + else if (dsa & DSA::LastPrivate) + lastpObj.push_back(object); + } else if (dsa & DSA::Private) { + privateObj.push_back(object); + } else if (dsa & DSA::Shared) { + sharedObj.push_back(object); + } + } + + // Materialize each clause. + if (!privateObj.empty()) { + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_private, + PrivateTy{/*List=*/std::move(privateObj)})); + } + if (!sharedObj.empty()) { + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_shared, + SharedTy{/*List=*/std::move(sharedObj)})); + } + if (!firstpObj.empty()) { + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_firstprivate, + FirstprivateTy{/*List=*/std::move(firstpObj)})); + } + if (!lastpObj.empty()) { + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_lastprivate, + LastprivateTy{{/*LastprivateModifier=*/std::nullopt, + /*List=*/std::move(lastpObj)}})); + } + if (!lastpcObj.empty()) { + auto conditional = LastprivateTy::LastprivateModifier::Conditional; + merged.clauses.emplace_back( + makeClause(llvm::omp::Clause::OMPC_lastprivate, + LastprivateTy{{/*LastprivateModifier=*/conditional, + /*List=*/std::move(lastpcObj)}})); + } +} +} // namespace tomp + +#endif // LLVM_FRONTEND_OPENMP_CONSTRUCTCOMPOSITIONT_H diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h new file mode 100644 index 000000000000..5f12c62b832f --- /dev/null +++ b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h @@ -0,0 +1,1160 @@ +//===- ConstructDecompositionT.h -- Decomposing compound constructs -------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// Given a compound construct with a set of clauses, generate the list of +// constituent leaf constructs, each with a list of clauses that apply to it. +// +// Note: Clauses that are not originally present, but that are implied by the +// OpenMP spec are materialized, and are present in the output. +// +// Note: Composite constructs will also be broken up into leaf constructs. +// If composite constructs require processing as a whole, the lists of clauses +// for each leaf constituent should be merged. +//===----------------------------------------------------------------------===// +#ifndef LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H +#define LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Frontend/OpenMP/ClauseT.h" +#include "llvm/Frontend/OpenMP/OMP.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline llvm::ArrayRef getWorksharing() { + static llvm::omp::Directive worksharing[] = { + llvm::omp::Directive::OMPD_do, llvm::omp::Directive::OMPD_for, + llvm::omp::Directive::OMPD_scope, llvm::omp::Directive::OMPD_sections, + llvm::omp::Directive::OMPD_single, llvm::omp::Directive::OMPD_workshare, + }; + return worksharing; +} + +static inline llvm::ArrayRef getWorksharingLoop() { + static llvm::omp::Directive worksharingLoop[] = { + llvm::omp::Directive::OMPD_do, + llvm::omp::Directive::OMPD_for, + }; + return worksharingLoop; +} + +namespace detail { +template +typename std::remove_reference_t::iterator +find_unique(Container &&container, Predicate &&pred) { + auto first = std::find_if(container.begin(), container.end(), pred); + if (first == container.end()) + return first; + auto second = std::find_if(std::next(first), container.end(), pred); + if (second == container.end()) + return first; + return container.end(); +} +} // namespace detail + +namespace tomp { + +// ClauseType - Either instance of ClauseT, or a type derived from ClauseT. +// +// This is the clause representation in the code using this infrastructure. +// +// HelperType - A class that implements two member functions: +// +// // Return the base object of the given object, if any. +// std::optional getBaseObject(const Object &object) const +// // Return the iteration variable of the outermost loop associated +// // with the construct being worked on, if any. +// std::optional getLoopIterVar() const +template +struct ConstructDecompositionT { + using ClauseTy = ClauseType; + + using TypeTy = typename ClauseTy::TypeTy; + using IdTy = typename ClauseTy::IdTy; + using ExprTy = typename ClauseTy::ExprTy; + using HelperTy = HelperType; + using ObjectTy = tomp::ObjectT; + + using ClauseSet = std::unordered_set; + + ConstructDecompositionT(uint32_t ver, HelperType &helper, + llvm::omp::Directive dir, + llvm::ArrayRef clauses) + : version(ver), construct(dir), helper(helper) { + for (const ClauseTy &clause : clauses) + nodes.push_back(&clause); + + bool success = split(); + if (!success) + return; + + // Copy the individual leaf directives with their clauses to the + // output list. Copy by value, since we don't own the storage + // with the input clauses, and the internal representation uses + // clause addresses. + for (auto &leaf : leafs) { + output.push_back({leaf.id, {}}); + auto &out = output.back(); + for (const ClauseTy *c : leaf.clauses) + out.clauses.push_back(*c); + } + } + + tomp::ListT> output; + +private: + bool split(); + + struct LeafReprInternal { + llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown; + tomp::type::ListT clauses; + }; + + LeafReprInternal *findDirective(llvm::omp::Directive dirId) { + auto found = llvm::find_if( + leafs, [&](const LeafReprInternal &leaf) { return leaf.id == dirId; }); + return found != leafs.end() ? &*found : nullptr; + } + + ClauseSet *findClausesWith(const ObjectTy &object) { + if (auto found = syms.find(object.id()); found != syms.end()) + return &found->second; + return nullptr; + } + + template + ClauseTy *makeClause(llvm::omp::Clause clauseId, S &&specific) { + implicit.push_back(typename ClauseTy::BaseT{clauseId, std::move(specific)}); + return &implicit.back(); + } + + void addClauseSymsToMap(const ObjectTy &object, const ClauseTy *); + void addClauseSymsToMap(const tomp::ObjectListT &objects, + const ClauseTy *); + void addClauseSymsToMap(const TypeTy &item, const ClauseTy *); + void addClauseSymsToMap(const ExprTy &item, const ClauseTy *); + void addClauseSymsToMap(const tomp::clause::MapT &item, + const ClauseTy *); + + template + void addClauseSymsToMap(const std::optional &item, const ClauseTy *); + template + void addClauseSymsToMap(const tomp::ListT &item, const ClauseTy *); + template + void addClauseSymsToMap(const std::tuple &item, const ClauseTy *, + std::index_sequence = {}); + template + std::enable_if_t>, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + template + std::enable_if_t::EmptyTrait::value, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + template + std::enable_if_t::IncompleteTrait::value, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + template + std::enable_if_t::WrapperTrait::value, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + template + std::enable_if_t::TupleTrait::value, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + template + std::enable_if_t::UnionTrait::value, void> + addClauseSymsToMap(U &&item, const ClauseTy *); + + // Apply a clause to the only directive that allows it. If there are no + // directives that allow it, or if there is more that one, do not apply + // anything and return false, otherwise return true. + bool applyToUnique(const ClauseTy *node); + + // Apply a clause to the first directive in given range that allows it. + // If such a directive does not exist, return false, otherwise return true. + template + bool applyToFirst(const ClauseTy *node, llvm::iterator_range range); + + // Apply a clause to the innermost directive that allows it. If such a + // directive does not exist, return false, otherwise return true. + bool applyToInnermost(const ClauseTy *node); + + // Apply a clause to the outermost directive that allows it. If such a + // directive does not exist, return false, otherwise return true. + bool applyToOutermost(const ClauseTy *node); + + template + bool applyIf(const ClauseTy *node, Predicate shouldApply); + + bool applyToAll(const ClauseTy *node); + + template + bool applyClause(Clause &&clause, const ClauseTy *node); + + bool applyClause(const tomp::clause::CollapseT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::PrivateT &clause, + const ClauseTy *); + bool + applyClause(const tomp::clause::FirstprivateT &clause, + const ClauseTy *); + bool + applyClause(const tomp::clause::LastprivateT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::SharedT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::DefaultT &clause, + const ClauseTy *); + bool + applyClause(const tomp::clause::ThreadLimitT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::OrderT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::AllocateT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::ReductionT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::IfT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::LinearT &clause, + const ClauseTy *); + bool applyClause(const tomp::clause::NowaitT &clause, + const ClauseTy *); + + uint32_t version; + llvm::omp::Directive construct; + HelperType &helper; + ListT leafs; + tomp::ListT nodes; + std::list implicit; // Container for materialized implicit clauses. + // Inserting must preserve element addresses. + std::unordered_map syms; + std::unordered_set mapBases; +}; + +// Deduction guide +template +ConstructDecompositionT(uint32_t, HelperType &, llvm::omp::Directive, + llvm::ArrayRef) + -> ConstructDecompositionT; + +template +void ConstructDecompositionT::addClauseSymsToMap(const ObjectTy &object, + const ClauseTy *node) { + syms[object.id()].insert(node); +} + +template +void ConstructDecompositionT::addClauseSymsToMap( + const tomp::ObjectListT &objects, const ClauseTy *node) { + for (auto &object : objects) + syms[object.id()].insert(node); +} + +template +void ConstructDecompositionT::addClauseSymsToMap(const TypeTy &item, + const ClauseTy *node) { + // Nothing to do for types. +} + +template +void ConstructDecompositionT::addClauseSymsToMap(const ExprTy &item, + const ClauseTy *node) { + // Nothing to do for expressions. +} + +template +void ConstructDecompositionT::addClauseSymsToMap( + const tomp::clause::MapT &item, + const ClauseTy *node) { + auto &objects = std::get>(item.t); + addClauseSymsToMap(objects, node); + for (auto &object : objects) { + if (auto base = helper.getBaseObject(object)) + mapBases.insert(base->id()); + } +} + +template +template +void ConstructDecompositionT::addClauseSymsToMap( + const std::optional &item, const ClauseTy *node) { + if (item) + addClauseSymsToMap(*item, node); +} + +template +template +void ConstructDecompositionT::addClauseSymsToMap( + const tomp::ListT &item, const ClauseTy *node) { + for (auto &s : item) + addClauseSymsToMap(s, node); +} + +template +template +void ConstructDecompositionT::addClauseSymsToMap( + const std::tuple &item, const ClauseTy *node, + std::index_sequence) { + (void)node; // Silence strange warning from GCC. + (addClauseSymsToMap(std::get(item), node), ...); +} + +template +template +std::enable_if_t>, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + // Nothing to do for enums. +} + +template +template +std::enable_if_t::EmptyTrait::value, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + // Nothing to do for an empty class. +} + +template +template +std::enable_if_t::IncompleteTrait::value, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + // Nothing to do for an incomplete class (they're empty). +} + +template +template +std::enable_if_t::WrapperTrait::value, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + addClauseSymsToMap(item.v, node); +} + +template +template +std::enable_if_t::TupleTrait::value, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + constexpr size_t tuple_size = + std::tuple_size_v>; + addClauseSymsToMap(item.t, node, std::make_index_sequence{}); +} + +template +template +std::enable_if_t::UnionTrait::value, void> +ConstructDecompositionT::addClauseSymsToMap(U &&item, + const ClauseTy *node) { + std::visit([&](auto &&s) { addClauseSymsToMap(s, node); }, item.u); +} + +// Apply a clause to the only directive that allows it. If there are no +// directives that allow it, or if there is more that one, do not apply +// anything and return false, otherwise return true. +template +bool ConstructDecompositionT::applyToUnique(const ClauseTy *node) { + auto unique = detail::find_unique(leafs, [=](const auto &dirInfo) { + return llvm::omp::isAllowedClauseForDirective(dirInfo.id, node->id, + version); + }); + + if (unique != leafs.end()) { + unique->clauses.push_back(node); + return true; + } + return false; +} + +// Apply a clause to the first directive in given range that allows it. +// If such a directive does not exist, return false, otherwise return true. +template +template +bool ConstructDecompositionT::applyToFirst( + const ClauseTy *node, llvm::iterator_range range) { + if (range.empty()) + return false; + + for (auto &leaf : range) { + if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version)) + continue; + leaf.clauses.push_back(node); + return true; + } + return false; +} + +// Apply a clause to the innermost directive that allows it. If such a +// directive does not exist, return false, otherwise return true. +template +bool ConstructDecompositionT::applyToInnermost(const ClauseTy *node) { + return applyToFirst(node, llvm::reverse(leafs)); +} + +// Apply a clause to the outermost directive that allows it. If such a +// directive does not exist, return false, otherwise return true. +template +bool ConstructDecompositionT::applyToOutermost(const ClauseTy *node) { + return applyToFirst(node, llvm::iterator_range(leafs)); +} + +template +template +bool ConstructDecompositionT::applyIf(const ClauseTy *node, + Predicate shouldApply) { + bool applied = false; + for (auto &leaf : leafs) { + if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version)) + continue; + if (!shouldApply(leaf)) + continue; + leaf.clauses.push_back(node); + applied = true; + } + + return applied; +} + +template +bool ConstructDecompositionT::applyToAll(const ClauseTy *node) { + return applyIf(node, [](auto) { return true; }); +} + +template +template +bool ConstructDecompositionT::applyClause(Clause &&clause, + const ClauseTy *node) { + // The default behavior is to find the unique directive to which the + // given clause may be applied. If there are no such directives, or + // if there are multiple ones, flag an error. + // From "OpenMP Application Programming Interface", Version 5.2: + // S Some clauses are permitted only on a single leaf construct of the + // S combined or composite construct, in which case the effect is as if + // S the clause is applied to that specific construct. (p339, 31-33) + if (applyToUnique(node)) + return true; + + return false; +} + +// COLLAPSE +// [5.2:93:20-21] +// Directives: distribute, do, for, loop, simd, taskloop +// +// [5.2:339:35] +// (35) The collapse clause is applied once to the combined or composite +// construct. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::CollapseT &clause, + const ClauseTy *node) { + // Apply "collapse" to the innermost directive. If it's not one that + // allows it flag an error. + if (!leafs.empty()) { + auto &last = leafs.back(); + + if (llvm::omp::isAllowedClauseForDirective(last.id, node->id, version)) { + last.clauses.push_back(node); + return true; + } + } + + return false; +} + +// PRIVATE +// [5.2:111:5-7] +// Directives: distribute, do, for, loop, parallel, scope, sections, simd, +// single, target, task, taskloop, teams +// +// [5.2:340:1-2] +// (1) The effect of the 1 private clause is as if it is applied only to the +// innermost leaf construct that permits it. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::PrivateT &clause, + const ClauseTy *node) { + return applyToInnermost(node); +} + +// FIRSTPRIVATE +// [5.2:112:5-7] +// Directives: distribute, do, for, parallel, scope, sections, single, target, +// task, taskloop, teams +// +// [5.2:340:3-20] +// (3) The effect of the firstprivate clause is as if it is applied to one or +// more leaf constructs as follows: +// (5) To the distribute construct if it is among the constituent constructs; +// (6) To the teams construct if it is among the constituent constructs and the +// distribute construct is not; +// (8) To a worksharing construct that accepts the clause if one is among the +// constituent constructs; +// (9) To the taskloop construct if it is among the constituent constructs; +// (10) To the parallel construct if it is among the constituent constructs and +// neither a taskloop construct nor a worksharing construct that accepts +// the clause is among them; +// (12) To the target construct if it is among the constituent constructs and +// the same list item neither appears in a lastprivate clause nor is the +// base variable or base pointer of a list item that appears in a map +// clause. +// +// (15) If the parallel construct is among the constituent constructs and the +// effect is not as if the firstprivate clause is applied to it by the above +// rules, then the effect is as if the shared clause with the same list item is +// applied to the parallel construct. +// (17) If the teams construct is among the constituent constructs and the +// effect is not as if the firstprivate clause is applied to it by the above +// rules, then the effect is as if the shared clause with the same list item is +// applied to the teams construct. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::FirstprivateT &clause, + const ClauseTy *node) { + bool applied = false; + + // [5.2:340:3-6] + auto dirDistribute = findDirective(llvm::omp::OMPD_distribute); + auto dirTeams = findDirective(llvm::omp::OMPD_teams); + if (dirDistribute != nullptr) { + dirDistribute->clauses.push_back(node); + applied = true; + // [5.2:340:17] + if (dirTeams != nullptr) { + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/clause.v}); + dirTeams->clauses.push_back(shared); + } + } else if (dirTeams != nullptr) { + dirTeams->clauses.push_back(node); + applied = true; + } + + // [5.2:340:8] + auto findWorksharing = [&]() { + auto worksharing = getWorksharing(); + for (auto &leaf : leafs) { + auto found = llvm::find(worksharing, leaf.id); + if (found != std::end(worksharing)) + return &leaf; + } + return static_cast(nullptr); + }; + + auto dirWorksharing = findWorksharing(); + if (dirWorksharing != nullptr) { + dirWorksharing->clauses.push_back(node); + applied = true; + } + + // [5.2:340:9] + auto dirTaskloop = findDirective(llvm::omp::OMPD_taskloop); + if (dirTaskloop != nullptr) { + dirTaskloop->clauses.push_back(node); + applied = true; + } + + // [5.2:340:10] + auto dirParallel = findDirective(llvm::omp::OMPD_parallel); + if (dirParallel != nullptr) { + if (dirTaskloop == nullptr && dirWorksharing == nullptr) { + dirParallel->clauses.push_back(node); + applied = true; + } else { + // [5.2:340:15] + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/clause.v}); + dirParallel->clauses.push_back(shared); + } + } + + // [5.2:340:12] + auto inLastprivate = [&](const ObjectTy &object) { + if (ClauseSet *set = findClausesWith(object)) { + return llvm::find_if(*set, [](const ClauseTy *c) { + return c->id == llvm::omp::Clause::OMPC_lastprivate; + }) != set->end(); + } + return false; + }; + + auto dirTarget = findDirective(llvm::omp::OMPD_target); + if (dirTarget != nullptr) { + tomp::ObjectListT objects; + llvm::copy_if( + clause.v, std::back_inserter(objects), [&](const ObjectTy &object) { + return !inLastprivate(object) && !mapBases.count(object.id()); + }); + if (!objects.empty()) { + auto *firstp = makeClause( + llvm::omp::Clause::OMPC_firstprivate, + tomp::clause::FirstprivateT{/*List=*/objects}); + dirTarget->clauses.push_back(firstp); + applied = true; + } + } + + // "task" is not handled by any of the cases above. + if (auto dirTask = findDirective(llvm::omp::OMPD_task)) { + dirTask->clauses.push_back(node); + applied = true; + } + + return applied; +} + +// LASTPRIVATE +// [5.2:115:7-8] +// Directives: distribute, do, for, loop, sections, simd, taskloop +// +// [5.2:340:21-30] +// (21) The effect of the lastprivate clause is as if it is applied to all leaf +// constructs that permit the clause. +// (22) If the parallel construct is among the constituent constructs and the +// list item is not also specified in the firstprivate clause, then the effect +// of the lastprivate clause is as if the shared clause with the same list item +// is applied to the parallel construct. +// (24) If the teams construct is among the constituent constructs and the list +// item is not also specified in the firstprivate clause, then the effect of the +// lastprivate clause is as if the shared clause with the same list item is +// applied to the teams construct. +// (27) If the target construct is among the constituent constructs and the list +// item is not the base variable or base pointer of a list item that appears in +// a map clause, the effect of the lastprivate clause is as if the same list +// item appears in a map clause with a map-type of tofrom. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::LastprivateT &clause, + const ClauseTy *node) { + bool applied = false; + + // [5.2:340:21] + applied = applyToAll(node); + if (!applied) + return false; + + auto inFirstprivate = [&](const ObjectTy &object) { + if (ClauseSet *set = findClausesWith(object)) { + return llvm::find_if(*set, [](const ClauseTy *c) { + return c->id == llvm::omp::Clause::OMPC_firstprivate; + }) != set->end(); + } + return false; + }; + + auto &objects = std::get>(clause.t); + + // Prepare list of objects that could end up in a "shared" clause. + tomp::ObjectListT sharedObjects; + llvm::copy_if( + objects, std::back_inserter(sharedObjects), + [&](const ObjectTy &object) { return !inFirstprivate(object); }); + + if (!sharedObjects.empty()) { + // [5.2:340:22] + if (auto dirParallel = findDirective(llvm::omp::OMPD_parallel)) { + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/sharedObjects}); + dirParallel->clauses.push_back(shared); + applied = true; + } + + // [5.2:340:24] + if (auto dirTeams = findDirective(llvm::omp::OMPD_teams)) { + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/sharedObjects}); + dirTeams->clauses.push_back(shared); + applied = true; + } + } + + // [5.2:340:27] + if (auto dirTarget = findDirective(llvm::omp::OMPD_target)) { + tomp::ObjectListT tofrom; + llvm::copy_if( + objects, std::back_inserter(tofrom), + [&](const ObjectTy &object) { return !mapBases.count(object.id()); }); + + if (!tofrom.empty()) { + using MapType = + typename tomp::clause::MapT::MapType; + auto *map = + makeClause(llvm::omp::Clause::OMPC_map, + tomp::clause::MapT{ + {/*MapType=*/MapType::Tofrom, + /*MapTypeModifier=*/std::nullopt, + /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, + /*LocatorList=*/std::move(tofrom)}}); + dirTarget->clauses.push_back(map); + applied = true; + } + } + + return applied; +} + +// SHARED +// [5.2:110:5-6] +// Directives: parallel, task, taskloop, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::SharedT &clause, + const ClauseTy *node) { + // [5.2:340:31] + return applyToAll(node); +} + +// DEFAULT +// [5.2:109:5-6] +// Directives: parallel, task, taskloop, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::DefaultT &clause, + const ClauseTy *node) { + // [5.2:340:31] + return applyToAll(node); +} + +// THREAD_LIMIT +// [5.2:277:14-15] +// Directives: target, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::ThreadLimitT &clause, + const ClauseTy *node) { + // [5.2:340:31] + return applyToAll(node); +} + +// ORDER +// [5.2:234:3-4] +// Directives: distribute, do, for, loop, simd +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::OrderT &clause, + const ClauseTy *node) { + // [5.2:340:31] + return applyToAll(node); +} + +// ALLOCATE +// [5.2:178:7-9] +// Directives: allocators, distribute, do, for, parallel, scope, sections, +// single, target, task, taskgroup, taskloop, teams +// +// [5.2:340:33-35] +// (33) The effect of the allocate clause is as if it is applied to all leaf +// constructs that permit the clause and to which a data-sharing attribute +// clause that may create a private copy of the same list item is applied. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::AllocateT &clause, + const ClauseTy *node) { + // This one needs to be applied at the end, once we know which clauses are + // assigned to which leaf constructs. + + // [5.2:340:33] + auto canMakePrivateCopy = [](llvm::omp::Clause id) { + switch (id) { + case llvm::omp::Clause::OMPC_firstprivate: + case llvm::omp::Clause::OMPC_lastprivate: + case llvm::omp::Clause::OMPC_private: + return true; + default: + return false; + } + }; + + bool applied = applyIf(node, [&](const auto &leaf) { + return llvm::any_of(leaf.clauses, [&](const ClauseTy *n) { + return canMakePrivateCopy(n->id); + }); + }); + + return applied; +} + +// REDUCTION +// [5.2:134:17-18] +// Directives: do, for, loop, parallel, scope, sections, simd, taskloop, teams +// +// [5.2:340:36-37], [5.2:341:1-13] +// (36) The effect of the reduction clause is as if it is applied to all leaf +// constructs that permit the clause, except for the following constructs: +// (1) The parallel construct, when combined with the sections, +// worksharing-loop, loop, or taskloop construct; and +// (3) The teams construct, when combined with the loop construct. +// (4) For the parallel and teams constructs above, the effect of the reduction +// clause instead is as if each list item or, for any list item that is an array +// item, its corresponding base array or base pointer appears in a shared clause +// for the construct. +// (6) If the task reduction-modifier is specified, the effect is as if it only +// modifies the behavior of the reduction clause on the innermost leaf construct +// that accepts the modifier (see Section 5.5.8). +// (8) If the inscan reduction-modifier is specified, the effect is as if it +// modifies the behavior of the reduction clause on all constructs of the +// combined construct to which the clause is applied and that accept the +// modifier. +// (10) If a list item in a reduction clause on a combined target construct does +// not have the same base variable or base pointer as a list item in a map +// clause on the construct, then the effect is as if the list item in the +// reduction clause appears as a list item in a map clause with a map-type of +// tofrom. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::ReductionT &clause, + const ClauseTy *node) { + using ReductionTy = tomp::clause::ReductionT; + + // [5.2:340:36], [5.2:341:1], [5.2:341:3] + bool applyToParallel = true, applyToTeams = true; + + auto dirParallel = findDirective(llvm::omp::Directive::OMPD_parallel); + if (dirParallel) { + auto exclusions = llvm::concat( + getWorksharingLoop(), tomp::ListT{ + llvm::omp::Directive::OMPD_loop, + llvm::omp::Directive::OMPD_sections, + llvm::omp::Directive::OMPD_taskloop, + }); + auto present = [&](llvm::omp::Directive id) { + return findDirective(id) != nullptr; + }; + + if (llvm::any_of(exclusions, present)) + applyToParallel = false; + } + + auto dirTeams = findDirective(llvm::omp::Directive::OMPD_teams); + if (dirTeams) { + // The only exclusion is OMPD_loop. + if (findDirective(llvm::omp::Directive::OMPD_loop)) + applyToTeams = false; + } + + using ReductionModifier = typename ReductionTy::ReductionModifier; + using ReductionIdentifiers = typename ReductionTy::ReductionIdentifiers; + + auto &objects = std::get>(clause.t); + auto &modifier = std::get>(clause.t); + + // Apply the reduction clause first to all directives according to the spec. + // If the reduction was applied at least once, proceed with the data sharing + // side-effects. + bool applied = false; + + // [5.2:341:6], [5.2:341:8] + auto isValidModifier = [](llvm::omp::Directive dir, ReductionModifier mod, + bool alreadyApplied) { + switch (mod) { + case ReductionModifier::Inscan: + // According to [5.2:135:11-13], "inscan" only applies to + // worksharing-loop, worksharing-loop-simd, or "simd" constructs. + return dir == llvm::omp::Directive::OMPD_simd || + llvm::is_contained(getWorksharingLoop(), dir); + case ReductionModifier::Task: + if (alreadyApplied) + return false; + // According to [5.2:135:16-18], "task" only applies to "parallel" and + // worksharing constructs. + return dir == llvm::omp::Directive::OMPD_parallel || + llvm::is_contained(getWorksharing(), dir); + case ReductionModifier::Default: + return true; + } + llvm_unreachable("Unexpected modifier"); + }; + + auto *unmodified = makeClause( + llvm::omp::Clause::OMPC_reduction, + ReductionTy{ + {/*ReductionModifier=*/std::nullopt, + /*ReductionIdentifiers=*/std::get(clause.t), + /*List=*/objects}}); + + ReductionModifier effective = + modifier.has_value() ? *modifier : ReductionModifier::Default; + bool effectiveApplied = false; + // Walk over the leaf constructs starting from the innermost, and apply + // the clause as required by the spec. + for (auto &leaf : llvm::reverse(leafs)) { + if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version)) + continue; + if (!applyToParallel && &leaf == dirParallel) + continue; + if (!applyToTeams && &leaf == dirTeams) + continue; + // Some form of the clause will be applied past this point. + if (isValidModifier(leaf.id, effective, effectiveApplied)) { + // Apply clause with modifier. + leaf.clauses.push_back(node); + effectiveApplied = true; + } else { + // Apply clause without modifier. + leaf.clauses.push_back(unmodified); + } + applied = true; + } + + if (!applied) + return false; + + tomp::ObjectListT sharedObjects; + llvm::transform(objects, std::back_inserter(sharedObjects), + [&](const ObjectTy &object) { + auto maybeBase = helper.getBaseObject(object); + return maybeBase ? *maybeBase : object; + }); + + // [5.2:341:4] + if (!sharedObjects.empty()) { + if (dirParallel && !applyToParallel) { + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/sharedObjects}); + dirParallel->clauses.push_back(shared); + } + if (dirTeams && !applyToTeams) { + auto *shared = makeClause( + llvm::omp::Clause::OMPC_shared, + tomp::clause::SharedT{/*List=*/sharedObjects}); + dirTeams->clauses.push_back(shared); + } + } + + // [5.2:341:10] + auto dirTarget = findDirective(llvm::omp::Directive::OMPD_target); + if (dirTarget && leafs.size() > 1) { + tomp::ObjectListT tofrom; + llvm::copy_if(objects, std::back_inserter(tofrom), + [&](const ObjectTy &object) { + if (auto maybeBase = helper.getBaseObject(object)) + return !mapBases.count(maybeBase->id()); + return !mapBases.count(object.id()); // XXX is this ok? + }); + if (!tofrom.empty()) { + using MapType = + typename tomp::clause::MapT::MapType; + auto *map = makeClause( + llvm::omp::Clause::OMPC_map, + tomp::clause::MapT{ + {/*MapType=*/MapType::Tofrom, /*MapTypeModifier=*/std::nullopt, + /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, + /*LocatorList=*/std::move(tofrom)}}); + + dirTarget->clauses.push_back(map); + applied = true; + } + } + + return applied; +} + +// IF +// [5.2:72:7-9] +// Directives: cancel, parallel, simd, target, target data, target enter data, +// target exit data, target update, task, taskloop +// +// [5.2:72:15-18] +// (15) For combined or composite constructs, the if clause only applies to the +// semantics of the construct named in the directive-name-modifier. +// (16) For a combined or composite construct, if no directive-name-modifier is +// specified then the if clause applies to all constituent constructs to which +// an if clause can apply. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::IfT &clause, + const ClauseTy *node) { + using DirectiveNameModifier = + typename clause::IfT::DirectiveNameModifier; + using IfExpression = typename clause::IfT::IfExpression; + auto &modifier = std::get>(clause.t); + + if (modifier) { + llvm::omp::Directive dirId = *modifier; + auto *unmodified = + makeClause(llvm::omp::Clause::OMPC_if, + tomp::clause::IfT{ + {/*DirectiveNameModifier=*/std::nullopt, + /*IfExpression=*/std::get(clause.t)}}); + + if (auto *hasDir = findDirective(dirId)) { + hasDir->clauses.push_back(unmodified); + return true; + } + return false; + } + + return applyToAll(node); +} + +// LINEAR +// [5.2:118:1-2] +// Directives: declare simd, do, for, simd +// +// [5.2:341:15-22] +// (15.1) The effect of the linear clause is as if it is applied to the +// innermost leaf construct. +// (15.2) Additionally, if the list item is not the iteration variable of a simd +// or worksharing-loop SIMD construct, the effect on the outer leaf constructs +// is as if the list item was specified in firstprivate and lastprivate clauses +// on the combined or composite construct, with the rules specified above +// applied. +// (19) If a list item of the linear clause is the iteration variable of a simd +// or worksharing-loop SIMD construct and it is not declared in the construct, +// the effect on the outer leaf constructs is as if the list item was specified +// in a lastprivate clause on the combined or composite construct with the rules +// specified above applied. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::LinearT &clause, + const ClauseTy *node) { + // [5.2:341:15.1] + if (!applyToInnermost(node)) + return false; + + // [5.2:341:15.2], [5.2:341:19] + auto dirSimd = findDirective(llvm::omp::Directive::OMPD_simd); + std::optional iterVar = helper.getLoopIterVar(); + const auto &objects = std::get>(clause.t); + + // Lists of objects that will be used to construct "firstprivate" and + // "lastprivate" clauses. + tomp::ObjectListT first, last; + + for (const ObjectTy &object : objects) { + last.push_back(object); + if (!dirSimd || !iterVar || object.id() != iterVar->id()) + first.push_back(object); + } + + if (!first.empty()) { + auto *firstp = makeClause( + llvm::omp::Clause::OMPC_firstprivate, + tomp::clause::FirstprivateT{/*List=*/first}); + nodes.push_back(firstp); // Appending to the main clause list. + } + if (!last.empty()) { + auto *lastp = + makeClause(llvm::omp::Clause::OMPC_lastprivate, + tomp::clause::LastprivateT{ + {/*LastprivateModifier=*/std::nullopt, /*List=*/last}}); + nodes.push_back(lastp); // Appending to the main clause list. + } + return true; +} + +// NOWAIT +// [5.2:308:11-13] +// Directives: dispatch, do, for, interop, scope, sections, single, target, +// target enter data, target exit data, target update, taskwait, workshare +// +// [5.2:341:23] +// (23) The effect of the nowait clause is as if it is applied to the outermost +// leaf construct that permits it. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::NowaitT &clause, + const ClauseTy *node) { + return applyToOutermost(node); +} + +template bool ConstructDecompositionT::split() { + bool success = true; + + for (llvm::omp::Directive leaf : + llvm::omp::getLeafConstructsOrSelf(construct)) + leafs.push_back(LeafReprInternal{leaf, /*clauses=*/{}}); + + for (const ClauseTy *node : nodes) + addClauseSymsToMap(*node, node); + + // First we need to apply LINEAR, because it can generate additional + // "firstprivate" and "lastprivate" clauses that apply to the combined/ + // composite construct. + // Collect them separately, because they may modify the clause list. + llvm::SmallVector linears; + for (const ClauseTy *node : nodes) { + if (node->id == llvm::omp::Clause::OMPC_linear) + linears.push_back(node); + } + for (const auto *node : linears) { + success = success && + applyClause(std::get>( + node->u), + node); + } + + // "allocate" clauses need to be applied last since they need to see + // which directives have data-privatizing clauses. + auto skip = [](const ClauseTy *node) { + switch (node->id) { + case llvm::omp::Clause::OMPC_allocate: + case llvm::omp::Clause::OMPC_linear: + return true; + default: + return false; + } + }; + + // Apply (almost) all clauses. + for (const ClauseTy *node : nodes) { + if (skip(node)) + continue; + success = + success && + std::visit([&](auto &&s) { return applyClause(s, node); }, node->u); + } + + // Apply "allocate". + for (const ClauseTy *node : nodes) { + if (node->id != llvm::omp::Clause::OMPC_allocate) + continue; + success = + success && + std::visit([&](auto &&s) { return applyClause(s, node); }, node->u); + } + + return success; +} + +} // namespace tomp + +#endif // LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H diff --git a/llvm/unittests/Frontend/CMakeLists.txt b/llvm/unittests/Frontend/CMakeLists.txt index 3f290b63ba64..85e113816e3b 100644 --- a/llvm/unittests/Frontend/CMakeLists.txt +++ b/llvm/unittests/Frontend/CMakeLists.txt @@ -15,6 +15,7 @@ add_llvm_unittest(LLVMFrontendTests OpenMPIRBuilderTest.cpp OpenMPParsingTest.cpp OpenMPCompositionTest.cpp + OpenMPDecompositionTest.cpp DEPENDS acc_gen diff --git a/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp b/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp new file mode 100644 index 000000000000..df48e9cc0ff4 --- /dev/null +++ b/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp @@ -0,0 +1,999 @@ +//===- llvm/unittests/Frontend/OpenMPDecompositionTest.cpp ----------------===// +// +// 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 "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Frontend/OpenMP/ClauseT.h" +#include "llvm/Frontend/OpenMP/ConstructDecompositionT.h" +#include "llvm/Frontend/OpenMP/OMP.h" +#include "gtest/gtest.h" + +#include +#include +#include +#include +#include +#include +#include + +// The actual tests start at comment "--- Test" below. + +// Create simple instantiations of all clauses to allow manual construction +// of clauses, and implement emitting of a directive with clauses to a string. +// +// The tests then follow the pattern +// 1. Create a list of clauses. +// 2. Pass them, together with a construct, to the decomposition class. +// 3. Extract individual resulting leaf constructs with clauses applied +// to them. +// 4. Convert them to strings and compare with expected outputs. + +namespace omp { +struct TypeTy {}; // placeholder +struct ExprTy {}; // placeholder +using IdTy = std::string; +} // namespace omp + +namespace tomp::type { +template <> struct ObjectT { + const omp::IdTy &id() const { return name; } + const std::optional ref() const { return omp::ExprTy{}; } + + omp::IdTy name; +}; +} // namespace tomp::type + +namespace omp { +template using List = tomp::type::ListT; + +using Object = tomp::ObjectT; + +namespace clause { +using DefinedOperator = tomp::type::DefinedOperatorT; +using ProcedureDesignator = tomp::type::ProcedureDesignatorT; +using ReductionOperator = tomp::type::ReductionIdentifierT; + +using AcqRel = tomp::clause::AcqRelT; +using Acquire = tomp::clause::AcquireT; +using AdjustArgs = tomp::clause::AdjustArgsT; +using Affinity = tomp::clause::AffinityT; +using Aligned = tomp::clause::AlignedT; +using Align = tomp::clause::AlignT; +using Allocate = tomp::clause::AllocateT; +using Allocator = tomp::clause::AllocatorT; +using AppendArgs = tomp::clause::AppendArgsT; +using AtomicDefaultMemOrder = + tomp::clause::AtomicDefaultMemOrderT; +using At = tomp::clause::AtT; +using Bind = tomp::clause::BindT; +using Capture = tomp::clause::CaptureT; +using Collapse = tomp::clause::CollapseT; +using Compare = tomp::clause::CompareT; +using Copyin = tomp::clause::CopyinT; +using Copyprivate = tomp::clause::CopyprivateT; +using Defaultmap = tomp::clause::DefaultmapT; +using Default = tomp::clause::DefaultT; +using Depend = tomp::clause::DependT; +using Destroy = tomp::clause::DestroyT; +using Detach = tomp::clause::DetachT; +using Device = tomp::clause::DeviceT; +using DeviceType = tomp::clause::DeviceTypeT; +using DistSchedule = tomp::clause::DistScheduleT; +using Doacross = tomp::clause::DoacrossT; +using DynamicAllocators = + tomp::clause::DynamicAllocatorsT; +using Enter = tomp::clause::EnterT; +using Exclusive = tomp::clause::ExclusiveT; +using Fail = tomp::clause::FailT; +using Filter = tomp::clause::FilterT; +using Final = tomp::clause::FinalT; +using Firstprivate = tomp::clause::FirstprivateT; +using From = tomp::clause::FromT; +using Full = tomp::clause::FullT; +using Grainsize = tomp::clause::GrainsizeT; +using HasDeviceAddr = tomp::clause::HasDeviceAddrT; +using Hint = tomp::clause::HintT; +using If = tomp::clause::IfT; +using Inbranch = tomp::clause::InbranchT; +using Inclusive = tomp::clause::InclusiveT; +using Indirect = tomp::clause::IndirectT; +using Init = tomp::clause::InitT; +using InReduction = tomp::clause::InReductionT; +using IsDevicePtr = tomp::clause::IsDevicePtrT; +using Lastprivate = tomp::clause::LastprivateT; +using Linear = tomp::clause::LinearT; +using Link = tomp::clause::LinkT; +using Map = tomp::clause::MapT; +using Match = tomp::clause::MatchT; +using Mergeable = tomp::clause::MergeableT; +using Message = tomp::clause::MessageT; +using Nocontext = tomp::clause::NocontextT; +using Nogroup = tomp::clause::NogroupT; +using Nontemporal = tomp::clause::NontemporalT; +using Notinbranch = tomp::clause::NotinbranchT; +using Novariants = tomp::clause::NovariantsT; +using Nowait = tomp::clause::NowaitT; +using NumTasks = tomp::clause::NumTasksT; +using NumTeams = tomp::clause::NumTeamsT; +using NumThreads = tomp::clause::NumThreadsT; +using OmpxAttribute = tomp::clause::OmpxAttributeT; +using OmpxBare = tomp::clause::OmpxBareT; +using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT; +using Ordered = tomp::clause::OrderedT; +using Order = tomp::clause::OrderT; +using Partial = tomp::clause::PartialT; +using Priority = tomp::clause::PriorityT; +using Private = tomp::clause::PrivateT; +using ProcBind = tomp::clause::ProcBindT; +using Read = tomp::clause::ReadT; +using Reduction = tomp::clause::ReductionT; +using Relaxed = tomp::clause::RelaxedT; +using Release = tomp::clause::ReleaseT; +using ReverseOffload = tomp::clause::ReverseOffloadT; +using Safelen = tomp::clause::SafelenT; +using Schedule = tomp::clause::ScheduleT; +using SeqCst = tomp::clause::SeqCstT; +using Severity = tomp::clause::SeverityT; +using Shared = tomp::clause::SharedT; +using Simdlen = tomp::clause::SimdlenT; +using Simd = tomp::clause::SimdT; +using Sizes = tomp::clause::SizesT; +using TaskReduction = tomp::clause::TaskReductionT; +using ThreadLimit = tomp::clause::ThreadLimitT; +using Threads = tomp::clause::ThreadsT; +using To = tomp::clause::ToT; +using UnifiedAddress = tomp::clause::UnifiedAddressT; +using UnifiedSharedMemory = + tomp::clause::UnifiedSharedMemoryT; +using Uniform = tomp::clause::UniformT; +using Unknown = tomp::clause::UnknownT; +using Untied = tomp::clause::UntiedT; +using Update = tomp::clause::UpdateT; +using UseDeviceAddr = tomp::clause::UseDeviceAddrT; +using UseDevicePtr = tomp::clause::UseDevicePtrT; +using UsesAllocators = tomp::clause::UsesAllocatorsT; +using Use = tomp::clause::UseT; +using Weak = tomp::clause::WeakT; +using When = tomp::clause::WhenT; +using Write = tomp::clause::WriteT; +} // namespace clause + +struct Helper { + std::optional getBaseObject(const Object &object) { + return std::nullopt; + } + std::optional getLoopIterVar() { return std::nullopt; } +}; + +using Clause = tomp::ClauseT; +using ConstructDecomposition = tomp::ConstructDecompositionT; +using DirectiveWithClauses = tomp::DirectiveWithClauses; +} // namespace omp + +struct StringifyClause { + static std::string join(const omp::List &Strings) { + std::stringstream Stream; + for (const auto &[Index, String] : llvm::enumerate(Strings)) { + if (Index != 0) + Stream << ", "; + Stream << String; + } + return Stream.str(); + } + + static std::string to_str(llvm::omp::Directive D) { + return getOpenMPDirectiveName(D).str(); + } + static std::string to_str(llvm::omp::Clause C) { + return getOpenMPClauseName(C).str(); + } + static std::string to_str(const omp::TypeTy &Type) { return "type"; } + static std::string to_str(const omp::ExprTy &Expr) { return "expr"; } + static std::string to_str(const omp::Object &Obj) { return Obj.id(); } + + template + static std::enable_if_t>, std::string> + to_str(U &&Item) { + return std::to_string(llvm::to_underlying(Item)); + } + + template static std::string to_str(const omp::List &Items) { + omp::List Names; + llvm::transform(Items, std::back_inserter(Names), + [](auto &&S) { return to_str(S); }); + return "(" + join(Names) + ")"; + } + + template + static std::string to_str(const std::optional &Item) { + if (Item) + return to_str(*Item); + return ""; + } + + template + static std::string to_str(const std::tuple &Tuple, + std::index_sequence) { + omp::List Strings; + (Strings.push_back(to_str(std::get(Tuple))), ...); + return "(" + join(Strings) + ")"; + } + + template + static std::enable_if_t::EmptyTrait::value, + std::string> + to_str(U &&Item) { + return ""; + } + + template + static std::enable_if_t::IncompleteTrait::value, + std::string> + to_str(U &&Item) { + return ""; + } + + template + static std::enable_if_t::WrapperTrait::value, + std::string> + to_str(U &&Item) { + // For a wrapper, stringify the wrappee, and only add parentheses if + // there aren't any already. + std::string Str = to_str(Item.v); + if (!Str.empty()) { + if (Str.front() == '(' && Str.back() == ')') + return Str; + } + return "(" + to_str(Item.v) + ")"; + } + + template + static std::enable_if_t::TupleTrait::value, + std::string> + to_str(U &&Item) { + constexpr size_t TupleSize = + std::tuple_size_v>; + return to_str(Item.t, std::make_index_sequence{}); + } + + template + static std::enable_if_t::UnionTrait::value, + std::string> + to_str(U &&Item) { + return std::visit([](auto &&S) { return to_str(S); }, Item.u); + } + + StringifyClause(const omp::Clause &C) + // Rely on content stringification to emit enclosing parentheses. + : Str(to_str(C.id) + to_str(C)) {} + + std::string Str; +}; + +std::string stringify(const omp::DirectiveWithClauses &DWC) { + std::stringstream Stream; + + Stream << getOpenMPDirectiveName(DWC.id).str(); + for (const omp::Clause &C : DWC.clauses) + Stream << ' ' << StringifyClause(C).Str; + + return Stream.str(); +} + +// --- Tests ---------------------------------------------------------- + +namespace { +using namespace llvm::omp; + +class OpenMPDecompositionTest : public testing::Test { +protected: + void SetUp() override {} + void TearDown() override {} + + omp::Helper Helper; + uint32_t AnyVersion = 999; +}; + +// PRIVATE +// [5.2:111:5-7] +// Directives: distribute, do, for, loop, parallel, scope, sections, simd, +// single, target, task, taskloop, teams +// +// [5.2:340:1-2] +// (1) The effect of the 1 private clause is as if it is applied only to the +// innermost leaf construct that permits it. +TEST_F(OpenMPDecompositionTest, Private1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_private, omp::clause::Private{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel"); // (1) + ASSERT_EQ(Dir1, "sections private(x)"); // (1) +} + +TEST_F(OpenMPDecompositionTest, Private2) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_private, omp::clause::Private{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel private(x)"); // (1) + ASSERT_EQ(Dir1, "masked"); // (1) +} + +// FIRSTPRIVATE +// [5.2:112:5-7] +// Directives: distribute, do, for, parallel, scope, sections, single, target, +// task, taskloop, teams +// +// [5.2:340:3-20] +// (3) The effect of the firstprivate clause is as if it is applied to one or +// more leaf constructs as follows: +// (5) To the distribute construct if it is among the constituent constructs; +// (6) To the teams construct if it is among the constituent constructs and the +// distribute construct is not; +// (8) To a worksharing construct that accepts the clause if one is among the +// constituent constructs; +// (9) To the taskloop construct if it is among the constituent constructs; +// (10) To the parallel construct if it is among the constituent constructs and +// neither a taskloop construct nor a worksharing construct that accepts +// the clause is among them; +// (12) To the target construct if it is among the constituent constructs and +// the same list item neither appears in a lastprivate clause nor is the +// base variable or base pointer of a list item that appears in a map +// clause. +// +// (15) If the parallel construct is among the constituent constructs and the +// effect is not as if the firstprivate clause is applied to it by the above +// rules, then the effect is as if the shared clause with the same list item is +// applied to the parallel construct. +// (17) If the teams construct is among the constituent constructs and the +// effect is not as if the firstprivate clause is applied to it by the above +// rules, then the effect is as if the shared clause with the same list item is +// applied to the teams construct. +TEST_F(OpenMPDecompositionTest, Firstprivate1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (10), (15) + ASSERT_EQ(Dir1, "sections firstprivate(x)"); // (8) +} + +TEST_F(OpenMPDecompositionTest, Firstprivate2) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_target_teams_distribute, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "target firstprivate(x)"); // (12) + ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17) + ASSERT_EQ(Dir2, "distribute firstprivate(x)"); // (5) +} + +TEST_F(OpenMPDecompositionTest, Firstprivate3) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_target_teams_distribute, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (12), (27) + ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17) + ASSERT_EQ(Dir2, "distribute firstprivate(x) lastprivate(, (x))"); // (5), (21) +} + +TEST_F(OpenMPDecompositionTest, Firstprivate4) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_teams, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "target firstprivate(x)"); // (12) + ASSERT_EQ(Dir1, "teams firstprivate(x)"); // (6) +} + +TEST_F(OpenMPDecompositionTest, Firstprivate5) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_parallel_masked_taskloop, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (10) + ASSERT_EQ(Dir1, "masked"); + ASSERT_EQ(Dir2, "taskloop firstprivate(x)"); // (9) +} + +TEST_F(OpenMPDecompositionTest, Firstprivate6) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel firstprivate(x)"); // (10) + ASSERT_EQ(Dir1, "masked"); +} + +TEST_F(OpenMPDecompositionTest, Firstprivate7) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + // Composite constructs are still decomposed. + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_distribute, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "teams shared(x)"); // (17) + ASSERT_EQ(Dir1, "distribute firstprivate(x)"); // (5) +} + +// LASTPRIVATE +// [5.2:115:7-8] +// Directives: distribute, do, for, loop, sections, simd, taskloop +// +// [5.2:340:21-30] +// (21) The effect of the lastprivate clause is as if it is applied to all leaf +// constructs that permit the clause. +// (22) If the parallel construct is among the constituent constructs and the +// list item is not also specified in the firstprivate clause, then the effect +// of the lastprivate clause is as if the shared clause with the same list item +// is applied to the parallel construct. +// (24) If the teams construct is among the constituent constructs and the list +// item is not also specified in the firstprivate clause, then the effect of the +// lastprivate clause is as if the shared clause with the same list item is +// applied to the teams construct. +// (27) If the target construct is among the constituent constructs and the list +// item is not the base variable or base pointer of a list item that appears in +// a map clause, the effect of the lastprivate clause is as if the same list +// item appears in a map clause with a map-type of tofrom. +TEST_F(OpenMPDecompositionTest, Lastprivate1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (21), (22) + ASSERT_EQ(Dir1, "sections lastprivate(, (x))"); // (21) +} + +TEST_F(OpenMPDecompositionTest, Lastprivate2) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_distribute, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "teams shared(x)"); // (21), (25) + ASSERT_EQ(Dir1, "distribute lastprivate(, (x))"); // (21) +} + +TEST_F(OpenMPDecompositionTest, Lastprivate3) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_do, + Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (21), (27) + ASSERT_EQ(Dir1, "parallel shared(x)"); // (22) + ASSERT_EQ(Dir2, "do lastprivate(, (x))"); // (21) +} + +// SHARED +// [5.2:110:5-6] +// Directives: parallel, task, taskloop, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +TEST_F(OpenMPDecompositionTest, Shared1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_shared, omp::clause::Shared{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_parallel_masked_taskloop, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (31) + ASSERT_EQ(Dir1, "masked"); // (31) + ASSERT_EQ(Dir2, "taskloop shared(x)"); // (31) +} + +// DEFAULT +// [5.2:109:5-6] +// Directives: parallel, task, taskloop, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +TEST_F(OpenMPDecompositionTest, Default1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_default, + omp::clause::Default{ + omp::clause::Default::DataSharingAttribute::Firstprivate}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_parallel_masked_taskloop, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "parallel default(0)"); // (31) + ASSERT_EQ(Dir1, "masked"); // (31) + ASSERT_EQ(Dir2, "taskloop default(0)"); // (31) +} + +// THREAD_LIMIT +// [5.2:277:14-15] +// Directives: target, teams +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +TEST_F(OpenMPDecompositionTest, ThreadLimit1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_thread_limit, omp::clause::ThreadLimit{omp::ExprTy{}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_target_teams_distribute, Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "target thread_limit(expr)"); // (31) + ASSERT_EQ(Dir1, "teams thread_limit(expr)"); // (31) + ASSERT_EQ(Dir2, "distribute"); // (31) +} + +// ORDER +// [5.2:234:3-4] +// Directives: distribute, do, for, loop, simd +// +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. +TEST_F(OpenMPDecompositionTest, Order1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_order, + omp::clause::Order{{omp::clause::Order::OrderModifier::Unconstrained, + omp::clause::Order::Ordering::Concurrent}}}, + }; + + omp::ConstructDecomposition Dec( + AnyVersion, Helper, OMPD_target_teams_distribute_parallel_for_simd, + Clauses); + ASSERT_EQ(Dec.output.size(), 6u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + std::string Dir4 = stringify(Dec.output[4]); + std::string Dir5 = stringify(Dec.output[5]); + ASSERT_EQ(Dir0, "target"); // (31) + ASSERT_EQ(Dir1, "teams"); // (31) + // XXX OMP.td doesn't list "order" as allowed for "distribute" + ASSERT_EQ(Dir2, "distribute"); // (31) + ASSERT_EQ(Dir3, "parallel"); // (31) + ASSERT_EQ(Dir4, "for order(1, 0)"); // (31) + ASSERT_EQ(Dir5, "simd order(1, 0)"); // (31) +} + +// ALLOCATE +// [5.2:178:7-9] +// Directives: allocators, distribute, do, for, parallel, scope, sections, +// single, target, task, taskgroup, taskloop, teams +// +// [5.2:340:33-35] +// (33) The effect of the allocate clause is as if it is applied to all leaf +// constructs that permit the clause and to which a data-sharing attribute +// clause that may create a private copy of the same list item is applied. +TEST_F(OpenMPDecompositionTest, Allocate1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_allocate, + omp::clause::Allocate{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, + {OMPC_private, omp::clause::Private{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel"); // (33) + ASSERT_EQ(Dir1, "sections private(x) allocate(, , , (x))"); // (33) +} + +// REDUCTION +// [5.2:134:17-18] +// Directives: do, for, loop, parallel, scope, sections, simd, taskloop, teams +// +// [5.2:340-341:36-13] +// (36) The effect of the reduction clause is as if it is applied to all leaf +// constructs that permit the clause, except for the following constructs: +// (1) The parallel construct, when combined with the sections, +// worksharing-loop, loop, or taskloop construct; and +// (3) The teams construct, when combined with the loop construct. +// (4) For the parallel and teams constructs above, the effect of the reduction +// clause instead is as if each list item or, for any list item that is an array +// item, its corresponding base array or base pointer appears in a shared clause +// for the construct. +// (6) If the task reduction-modifier is specified, the effect is as if it only +// modifies the behavior of the reduction clause on the innermost leaf construct +// that accepts the modifier (see Section 5.5.8). +// (8) If the inscan reduction-modifier is specified, the effect is as if it +// modifies the behavior of the reduction clause on all constructs of the +// combined construct to which the clause is applied and that accept the +// modifier. +// (10) If a list item in a reduction clause on a combined target construct does +// not have the same base variable or base pointer as a list item in a map +// clause on the construct, then the effect is as if the list item in the +// reduction clause appears as a list item in a map clause with a map-type of +// tofrom. +namespace red { +// Make is easier to construct reduction operators from built-in intrinsics. +omp::clause::ReductionOperator +makeOp(omp::clause::DefinedOperator::IntrinsicOperator Op) { + return omp::clause::ReductionOperator{omp::clause::DefinedOperator{Op}}; +} +} // namespace red + +TEST_F(OpenMPDecompositionTest, Reduction1) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (36), (1), (4) + ASSERT_EQ(Dir1, "sections reduction(, (3), (x))"); // (36) +} + +TEST_F(OpenMPDecompositionTest, Reduction2) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel reduction(, (3), (x))"); // (36), (1), (4) + ASSERT_EQ(Dir1, "masked"); // (36) +} + +TEST_F(OpenMPDecompositionTest, Reduction3) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_loop, Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "teams shared(x)"); // (36), (3), (4) + ASSERT_EQ(Dir1, "loop reduction(, (3), (x))"); // (36) +} + +TEST_F(OpenMPDecompositionTest, Reduction4) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_teams_distribute_parallel_for, Clauses); + ASSERT_EQ(Dec.output.size(), 4u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3) + ASSERT_EQ(Dir1, "distribute"); // (36) + ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) + ASSERT_EQ(Dir3, "for reduction(, (3), (x))"); // (36) +} + +TEST_F(OpenMPDecompositionTest, Reduction5) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + auto TaskMod = omp::clause::Reduction::ReductionModifier::Task; + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{TaskMod, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_teams_distribute_parallel_for, Clauses); + ASSERT_EQ(Dec.output.size(), 4u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3), (6) + ASSERT_EQ(Dir1, "distribute"); // (36) + ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) + ASSERT_EQ(Dir3, "for reduction(2, (3), (x))"); // (36), (6) +} + +TEST_F(OpenMPDecompositionTest, Reduction6) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + auto InscanMod = omp::clause::Reduction::ReductionModifier::Inscan; + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{InscanMod, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_teams_distribute_parallel_for, Clauses); + ASSERT_EQ(Dec.output.size(), 4u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3), (8) + ASSERT_EQ(Dir1, "distribute"); // (36) + ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) + ASSERT_EQ(Dir3, "for reduction(1, (3), (x))"); // (36), (8) +} + +TEST_F(OpenMPDecompositionTest, Reduction7) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + omp::List Clauses{ + {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_do, + Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + // XXX Currently OMP.td allows "reduction" on "target". + ASSERT_EQ(Dir0, + "target reduction(, (3), (x)) map(2, , , , (x))"); // (36), (10) + ASSERT_EQ(Dir1, "parallel shared(x)"); // (36), (1), (4) + ASSERT_EQ(Dir2, "do reduction(, (3), (x))"); // (36) +} + +// IF +// [5.2:72:7-9] +// Directives: cancel, parallel, simd, target, target data, target enter data, +// target exit data, target update, task, taskloop +// +// [5.2:72:15-18] +// (15) For combined or composite constructs, the if clause only applies to the +// semantics of the construct named in the directive-name-modifier. +// (16) For a combined or composite construct, if no directive-name-modifier is +// specified then the if clause applies to all constituent constructs to which +// an if clause can apply. +TEST_F(OpenMPDecompositionTest, If1) { + omp::List Clauses{ + {OMPC_if, + omp::clause::If{{llvm::omp::Directive::OMPD_parallel, omp::ExprTy{}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_target_parallel_for_simd, Clauses); + ASSERT_EQ(Dec.output.size(), 4u); + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + ASSERT_EQ(Dir0, "target"); // (15) + ASSERT_EQ(Dir1, "parallel if(, expr)"); // (15) + ASSERT_EQ(Dir2, "for"); // (15) + ASSERT_EQ(Dir3, "simd"); // (15) +} + +TEST_F(OpenMPDecompositionTest, If2) { + omp::List Clauses{ + {OMPC_if, omp::clause::If{{std::nullopt, omp::ExprTy{}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, + OMPD_target_parallel_for_simd, Clauses); + ASSERT_EQ(Dec.output.size(), 4u); + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + std::string Dir3 = stringify(Dec.output[3]); + ASSERT_EQ(Dir0, "target if(, expr)"); // (16) + ASSERT_EQ(Dir1, "parallel if(, expr)"); // (16) + ASSERT_EQ(Dir2, "for"); // (16) + ASSERT_EQ(Dir3, "simd if(, expr)"); // (16) +} + +// LINEAR +// [5.2:118:1-2] +// Directives: declare simd, do, for, simd +// +// [5.2:341:15-22] +// (15.1) The effect of the linear clause is as if it is applied to the +// innermost leaf construct. +// (15.2) Additionally, if the list item is not the iteration variable of a simd +// or worksharing-loop SIMD construct, the effect on the outer leaf constructs +// is as if the list item was specified in firstprivate and lastprivate clauses +// on the combined or composite construct, with the rules specified above +// applied. +// (19) If a list item of the linear clause is the iteration variable of a simd +// or worksharing-loop SIMD construct and it is not declared in the construct, +// the effect on the outer leaf constructs is as if the list item was specified +// in a lastprivate clause on the combined or composite construct with the rules +// specified above applied. +TEST_F(OpenMPDecompositionTest, Linear1) { + omp::Object x{"x"}; + + omp::List Clauses{ + {OMPC_linear, + omp::clause::Linear{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_for_simd, Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "for firstprivate(x) lastprivate(, (x))"); // (15.1), (15.2) + ASSERT_EQ(Dir1, "simd linear(, , , (x)) lastprivate(, (x))"); // (15.1) +} + +// NOWAIT +// [5.2:308:11-13] +// Directives: dispatch, do, for, interop, scope, sections, single, target, +// target enter data, target exit data, target update, taskwait, workshare +// +// [5.2:341:23] +// (23) The effect of the nowait clause is as if it is applied to the outermost +// leaf construct that permits it. +TEST_F(OpenMPDecompositionTest, Nowait1) { + omp::List Clauses{ + {OMPC_nowait, omp::clause::Nowait{}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_for, + Clauses); + ASSERT_EQ(Dec.output.size(), 3u); + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + std::string Dir2 = stringify(Dec.output[2]); + ASSERT_EQ(Dir0, "target nowait"); // (23) + ASSERT_EQ(Dir1, "parallel"); // (23) + ASSERT_EQ(Dir2, "for"); // (23) +} +} // namespace -- GitLab From e8eb52d167eb2bf972b3cfa67ff1028b86cd209d 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: Mon, 13 May 2024 08:34:36 -0700 Subject: [PATCH 086/578] [flang][cuda] Extends matching distance computation (#91810) Extends the computation of the matching distance in the generic resolution to support options described in the table: https://docs.nvidia.com/hpc-sdk/archive/24.3/compilers/cuda-fortran-prog-guide/index.html#cfref-var-attr-unified-data Options are added as language features in the `SemanticsContext` and a flag is added in bbc for testing purpose. --- flang/include/flang/Common/Fortran-features.h | 4 +- flang/include/flang/Common/Fortran.h | 4 +- flang/lib/Common/Fortran.cpp | 37 +++++++++---- flang/lib/Semantics/check-call.cpp | 2 +- flang/lib/Semantics/expression.cpp | 34 +++++++++--- flang/test/Semantics/cuf14.cuf | 55 +++++++++++++++++++ flang/test/Semantics/cuf15.cuf | 55 +++++++++++++++++++ flang/tools/bbc/bbc.cpp | 10 ++++ 8 files changed, 180 insertions(+), 21 deletions(-) create mode 100644 flang/test/Semantics/cuf14.cuf create mode 100644 flang/test/Semantics/cuf15.cuf diff --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h index 07ed7f43c1e7..f57fcdc895ad 100644 --- a/flang/include/flang/Common/Fortran-features.h +++ b/flang/include/flang/Common/Fortran-features.h @@ -49,7 +49,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines, IndistinguishableSpecifics, SubroutineAndFunctionSpecifics, EmptySequenceType, NonSequenceCrayPointee, BranchIntoConstruct, BadBranchTarget, ConvertedArgument, HollerithPolymorphic, ListDirectedSize, - NonBindCInteroperability) + NonBindCInteroperability, CudaManaged, CudaUnified) // Portability and suspicious usage warnings ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable, @@ -81,6 +81,8 @@ public: disable_.set(LanguageFeature::OpenACC); disable_.set(LanguageFeature::OpenMP); disable_.set(LanguageFeature::CUDA); // !@cuf + disable_.set(LanguageFeature::CudaManaged); + disable_.set(LanguageFeature::CudaUnified); disable_.set(LanguageFeature::ImplicitNoneTypeNever); disable_.set(LanguageFeature::ImplicitNoneTypeAlways); disable_.set(LanguageFeature::DefaultSave); diff --git a/flang/include/flang/Common/Fortran.h b/flang/include/flang/Common/Fortran.h index 3b965fe60c2f..0701e3e8b64c 100644 --- a/flang/include/flang/Common/Fortran.h +++ b/flang/include/flang/Common/Fortran.h @@ -19,6 +19,7 @@ #include namespace Fortran::common { +class LanguageFeatureControl; // Fortran has five kinds of intrinsic data types, plus the derived types. ENUM_CLASS(TypeCategory, Integer, Real, Complex, Character, Logical, Derived) @@ -115,7 +116,8 @@ static constexpr IgnoreTKRSet ignoreTKRAll{IgnoreTKR::Type, IgnoreTKR::Kind, std::string AsFortran(IgnoreTKRSet); bool AreCompatibleCUDADataAttrs(std::optional, - std::optional, IgnoreTKRSet, bool allowUnifiedMatchingRule); + std::optional, IgnoreTKRSet, bool allowUnifiedMatchingRule, + const LanguageFeatureControl *features = nullptr); static constexpr char blankCommonObjectName[] = "__BLNK__"; diff --git a/flang/lib/Common/Fortran.cpp b/flang/lib/Common/Fortran.cpp index 170ce8c22509..c014b1263a67 100644 --- a/flang/lib/Common/Fortran.cpp +++ b/flang/lib/Common/Fortran.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "flang/Common/Fortran.h" +#include "flang/Common/Fortran-features.h" namespace Fortran::common { @@ -102,7 +103,13 @@ std::string AsFortran(IgnoreTKRSet tkr) { /// dummy argument attribute while `y` represents the actual argument attribute. bool AreCompatibleCUDADataAttrs(std::optional x, std::optional y, IgnoreTKRSet ignoreTKR, - bool allowUnifiedMatchingRule) { + bool allowUnifiedMatchingRule, const LanguageFeatureControl *features) { + bool isCudaManaged{features + ? features->IsEnabled(common::LanguageFeature::CudaManaged) + : false}; + bool isCudaUnified{features + ? features->IsEnabled(common::LanguageFeature::CudaUnified) + : false}; if (!x && !y) { return true; } else if (x && y && *x == *y) { @@ -120,19 +127,27 @@ bool AreCompatibleCUDADataAttrs(std::optional x, return true; } else if (allowUnifiedMatchingRule) { if (!x) { // Dummy argument has no attribute -> host - if (y && (*y == CUDADataAttr::Managed || *y == CUDADataAttr::Unified)) { + if ((y && (*y == CUDADataAttr::Managed || *y == CUDADataAttr::Unified)) || + (!y && (isCudaUnified || isCudaManaged))) { return true; } } else { - if (*x == CUDADataAttr::Device && y && - (*y == CUDADataAttr::Managed || *y == CUDADataAttr::Unified)) { - return true; - } else if (*x == CUDADataAttr::Managed && y && - *y == CUDADataAttr::Unified) { - return true; - } else if (*x == CUDADataAttr::Unified && y && - *y == CUDADataAttr::Managed) { - return true; + if (*x == CUDADataAttr::Device) { + if ((y && + (*y == CUDADataAttr::Managed || *y == CUDADataAttr::Unified)) || + (!y && (isCudaUnified || isCudaManaged))) { + return true; + } + } else if (*x == CUDADataAttr::Managed) { + if ((y && *y == CUDADataAttr::Unified) || + (!y && (isCudaUnified || isCudaManaged))) { + return true; + } + } else if (*x == CUDADataAttr::Unified) { + if ((y && *y == CUDADataAttr::Managed) || + (!y && (isCudaUnified || isCudaManaged))) { + return true; + } } } return false; diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp index 94afcbb68b34..8f51ef5ebeba 100644 --- a/flang/lib/Semantics/check-call.cpp +++ b/flang/lib/Semantics/check-call.cpp @@ -914,7 +914,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, } if (!common::AreCompatibleCUDADataAttrs(dummyDataAttr, actualDataAttr, dummy.ignoreTKR, - /*allowUnifiedMatchingRule=*/true)) { + /*allowUnifiedMatchingRule=*/true, &context.languageFeatures())) { auto toStr{[](std::optional x) { return x ? "ATTRIBUTES("s + parser::ToUpperCaseLetters(common::EnumToString(*x)) + ")"s diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index c503ea3f0246..06e38da6626a 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -2501,8 +2501,13 @@ static constexpr int cudaInfMatchingValue{std::numeric_limits::max()}; // Compute the matching distance as described in section 3.2.3 of the CUDA // Fortran references. -static int GetMatchingDistance(const characteristics::DummyArgument &dummy, +static int GetMatchingDistance(const common::LanguageFeatureControl &features, + const characteristics::DummyArgument &dummy, const std::optional &actual) { + bool isCudaManaged{features.IsEnabled(common::LanguageFeature::CudaManaged)}; + bool isCudaUnified{features.IsEnabled(common::LanguageFeature::CudaUnified)}; + CHECK(!(isCudaUnified && isCudaManaged) && "expect only one enabled."); + std::optional actualDataAttr, dummyDataAttr; if (actual) { if (auto *expr{actual->UnwrapExpr()}) { @@ -2529,6 +2534,9 @@ static int GetMatchingDistance(const characteristics::DummyArgument &dummy, if (!dummyDataAttr) { if (!actualDataAttr) { + if (isCudaUnified || isCudaManaged) { + return 3; + } return 0; } else if (*actualDataAttr == common::CUDADataAttr::Device) { return cudaInfMatchingValue; @@ -2538,6 +2546,9 @@ static int GetMatchingDistance(const characteristics::DummyArgument &dummy, } } else if (*dummyDataAttr == common::CUDADataAttr::Device) { if (!actualDataAttr) { + if (isCudaUnified || isCudaManaged) { + return 2; + } return cudaInfMatchingValue; } else if (*actualDataAttr == common::CUDADataAttr::Device) { return 0; @@ -2546,7 +2557,10 @@ static int GetMatchingDistance(const characteristics::DummyArgument &dummy, return 2; } } else if (*dummyDataAttr == common::CUDADataAttr::Managed) { - if (!actualDataAttr || *actualDataAttr == common::CUDADataAttr::Device) { + if (!actualDataAttr) { + return isCudaUnified ? 1 : isCudaManaged ? 0 : cudaInfMatchingValue; + } + if (*actualDataAttr == common::CUDADataAttr::Device) { return cudaInfMatchingValue; } else if (*actualDataAttr == common::CUDADataAttr::Managed) { return 0; @@ -2554,7 +2568,10 @@ static int GetMatchingDistance(const characteristics::DummyArgument &dummy, return 1; } } else if (*dummyDataAttr == common::CUDADataAttr::Unified) { - if (!actualDataAttr || *actualDataAttr == common::CUDADataAttr::Device) { + if (!actualDataAttr) { + return isCudaUnified ? 0 : isCudaManaged ? 1 : cudaInfMatchingValue; + } + if (*actualDataAttr == common::CUDADataAttr::Device) { return cudaInfMatchingValue; } else if (*actualDataAttr == common::CUDADataAttr::Managed) { return 1; @@ -2566,6 +2583,7 @@ static int GetMatchingDistance(const characteristics::DummyArgument &dummy, } static int ComputeCudaMatchingDistance( + const common::LanguageFeatureControl &features, const characteristics::Procedure &procedure, const ActualArguments &actuals) { const auto &dummies{procedure.dummyArguments}; @@ -2574,7 +2592,7 @@ static int ComputeCudaMatchingDistance( for (std::size_t i{0}; i < dummies.size(); ++i) { const characteristics::DummyArgument &dummy{dummies[i]}; const std::optional &actual{actuals[i]}; - int d{GetMatchingDistance(dummy, actual)}; + int d{GetMatchingDistance(features, dummy, actual)}; if (d == cudaInfMatchingValue) return d; distance += d; @@ -2666,7 +2684,9 @@ std::pair ExpressionAnalyzer::ResolveGeneric( CheckCompatibleArguments(*procedure, localActuals)) { if ((procedure->IsElemental() && elemental) || (!procedure->IsElemental() && nonElemental)) { - int d{ComputeCudaMatchingDistance(*procedure, localActuals)}; + int d{ComputeCudaMatchingDistance( + context_.languageFeatures(), *procedure, localActuals)}; + llvm::errs() << "matching distance: " << d << "\n"; if (d != crtMatchingDistance) { if (d > crtMatchingDistance) { continue; @@ -2688,8 +2708,8 @@ std::pair ExpressionAnalyzer::ResolveGeneric( } else { elemental = &specific; } - crtMatchingDistance = - ComputeCudaMatchingDistance(*procedure, localActuals); + crtMatchingDistance = ComputeCudaMatchingDistance( + context_.languageFeatures(), *procedure, localActuals); } } } diff --git a/flang/test/Semantics/cuf14.cuf b/flang/test/Semantics/cuf14.cuf new file mode 100644 index 000000000000..29c9ecf90677 --- /dev/null +++ b/flang/test/Semantics/cuf14.cuf @@ -0,0 +1,55 @@ +! RUN: bbc -emit-hlfir -fcuda -gpu=unified %s -o - | FileCheck %s + +module matching + interface host_and_device + module procedure sub_host + module procedure sub_device + end interface + + interface all + module procedure sub_host + module procedure sub_device + module procedure sub_managed + module procedure sub_unified + end interface + + interface all_without_unified + module procedure sub_host + module procedure sub_device + module procedure sub_managed + end interface + +contains + subroutine sub_host(a) + integer :: a(:) + end + + subroutine sub_device(a) + integer, device :: a(:) + end + + subroutine sub_managed(a) + integer, managed :: a(:) + end + + subroutine sub_unified(a) + integer, unified :: a(:) + end +end module + +program m + use matching + + integer, allocatable :: actual_host(:) + + allocate(actual_host(10)) + + call host_and_device(actual_host) ! Should resolve to sub_device + call all(actual_host) ! Should resolved to unified + call all_without_unified(actual_host) ! Should resolved to managed +end + +! CHECK: fir.call @_QMmatchingPsub_device +! CHECK: fir.call @_QMmatchingPsub_unified +! CHECK: fir.call @_QMmatchingPsub_managed + diff --git a/flang/test/Semantics/cuf15.cuf b/flang/test/Semantics/cuf15.cuf new file mode 100644 index 000000000000..030dd6ff8ffe --- /dev/null +++ b/flang/test/Semantics/cuf15.cuf @@ -0,0 +1,55 @@ +! RUN: bbc -emit-hlfir -fcuda -gpu=managed %s -o - | FileCheck %s + +module matching + interface host_and_device + module procedure sub_host + module procedure sub_device + end interface + + interface all + module procedure sub_host + module procedure sub_device + module procedure sub_managed + module procedure sub_unified + end interface + + interface all_without_managed + module procedure sub_host + module procedure sub_device + module procedure sub_unified + end interface + +contains + subroutine sub_host(a) + integer :: a(:) + end + + subroutine sub_device(a) + integer, device :: a(:) + end + + subroutine sub_managed(a) + integer, managed :: a(:) + end + + subroutine sub_unified(a) + integer, unified :: a(:) + end +end module + +program m + use matching + + integer, allocatable :: actual_host(:) + + allocate(actual_host(10)) + + call host_and_device(actual_host) ! Should resolve to sub_device + call all(actual_host) ! Should resolved to unified + call all_without_managed(actual_host) ! Should resolved to managed +end + +! CHECK: fir.call @_QMmatchingPsub_device +! CHECK: fir.call @_QMmatchingPsub_managed +! CHECK: fir.call @_QMmatchingPsub_unified + diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp index ee2ff8562e9f..f7092d35eeb5 100644 --- a/flang/tools/bbc/bbc.cpp +++ b/flang/tools/bbc/bbc.cpp @@ -204,6 +204,10 @@ static llvm::cl::opt enableCUDA("fcuda", llvm::cl::desc("enable CUDA Fortran"), llvm::cl::init(false)); +static llvm::cl::opt + enableGPUMode("gpu", llvm::cl::desc("Enable GPU Mode managed|unified"), + llvm::cl::init("")); + static llvm::cl::opt fixedForm("ffixed-form", llvm::cl::desc("enable fixed form"), llvm::cl::init(false)); @@ -495,6 +499,12 @@ int main(int argc, char **argv) { options.features.Enable(Fortran::common::LanguageFeature::CUDA); } + if (enableGPUMode == "managed") { + options.features.Enable(Fortran::common::LanguageFeature::CudaManaged); + } else if (enableGPUMode == "unified") { + options.features.Enable(Fortran::common::LanguageFeature::CudaUnified); + } + if (fixedForm) { options.isFixedForm = fixedForm; } -- GitLab From 06f04b2e27f2586d3db2204ed4e54f8b78fea74e Mon Sep 17 00:00:00 2001 From: erichkeane Date: Mon, 13 May 2024 08:40:43 -0700 Subject: [PATCH 087/578] Revert "[OpenACC] device_type clause Sema for Compute constructs" This reverts commit c4a9a374749deb5f2a932a7d4ef9321be1b2ae5d. This and the followup patch keep hitting an assert I wrote on the build bots in a way that isn't clear. Reverting so I can fix it without a rush. --- clang/include/clang/AST/OpenACCClause.h | 59 ----- .../clang/Basic/DiagnosticSemaKinds.td | 4 - clang/include/clang/Basic/OpenACCClauses.def | 2 - clang/include/clang/Parse/Parser.h | 3 +- clang/include/clang/Sema/SemaOpenACC.h | 23 +- clang/lib/AST/OpenACCClause.cpp | 28 +-- clang/lib/AST/StmtProfile.cpp | 3 - clang/lib/AST/TextNodeDumper.cpp | 13 -- clang/lib/Parse/ParseOpenACC.cpp | 21 +- clang/lib/Sema/SemaOpenACC.cpp | 55 ----- clang/lib/Sema/TreeTransform.h | 10 - clang/lib/Serialization/ASTReader.cpp | 17 +- clang/lib/Serialization/ASTWriter.cpp | 15 +- .../ast-print-openacc-compute-construct.cpp | 23 -- clang/test/ParserOpenACC/parse-clauses.c | 28 ++- .../compute-construct-device_type-ast.cpp | 105 --------- .../compute-construct-device_type-clause.c | 221 ------------------ .../compute-construct-device_type-clause.cpp | 25 -- clang/tools/libclang/CIndex.cpp | 2 - 19 files changed, 35 insertions(+), 622 deletions(-) delete mode 100644 clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp delete mode 100644 clang/test/SemaOpenACC/compute-construct-device_type-clause.c delete mode 100644 clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 607a2b9d6536..3d0b1ab9d31e 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -17,8 +17,6 @@ #include "clang/AST/StmtIterator.h" #include "clang/Basic/OpenACCKinds.h" -#include - namespace clang { /// This is the base type for all OpenACC Clauses. class OpenACCClause { @@ -77,63 +75,6 @@ public: } }; -using DeviceTypeArgument = std::pair; -/// A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or -/// an identifier. The 'asterisk' means 'the rest'. -class OpenACCDeviceTypeClause final - : public OpenACCClauseWithParams, - public llvm::TrailingObjects { - // Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A - // nullptr IdentifierInfo* represents an asterisk. - unsigned NumArchs; - OpenACCDeviceTypeClause(OpenACCClauseKind K, SourceLocation BeginLoc, - SourceLocation LParenLoc, - ArrayRef Archs, - SourceLocation EndLoc) - : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc), - NumArchs(Archs.size()) { - assert( - (K == OpenACCClauseKind::DeviceType || K == OpenACCClauseKind::DType) && - "Invalid clause kind for device-type"); - - assert(!llvm::any_of(Archs, [](const DeviceTypeArgument &Arg) { - return Arg.second.isInvalid(); - }) && "Invalid SourceLocation for an argument"); - - assert( - (Archs.size() == 1 || !llvm::any_of(Archs, - [](const DeviceTypeArgument &Arg) { - return Arg.first == nullptr; - })) && - "Only a single asterisk version is permitted, and must be the " - "only one"); - - std::uninitialized_copy(Archs.begin(), Archs.end(), - getTrailingObjects()); - } - -public: - static bool classof(const OpenACCClause *C) { - return C->getClauseKind() == OpenACCClauseKind::DType || - C->getClauseKind() == OpenACCClauseKind::DeviceType; - } - bool hasAsterisk() const { - return getArchitectures().size() > 0 && - getArchitectures()[0].first == nullptr; - } - - ArrayRef getArchitectures() const { - return ArrayRef( - getTrailingObjects(), NumArchs); - } - - static OpenACCDeviceTypeClause * - Create(const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc, - SourceLocation LParenLoc, ArrayRef Archs, - SourceLocation EndLoc); -}; - /// A 'default' clause, has the optional 'none' or 'present' argument. class OpenACCDefaultClause : public OpenACCClauseWithParams { friend class ASTReaderStmt; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6100fba51005..9e82130c9360 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12344,8 +12344,4 @@ def warn_acc_deprecated_alias_name def err_acc_var_not_pointer_type : Error<"expected pointer in '%0' clause, type is %1">; def note_acc_expected_pointer_var : Note<"expected variable of pointer type">; -def err_acc_clause_after_device_type - : Error<"OpenACC clause '%0' may not follow a '%1' clause in a " - "compute construct">; - } // end of sema component. diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def index 7ecc51799468..afb7b30b7465 100644 --- a/clang/include/clang/Basic/OpenACCClauses.def +++ b/clang/include/clang/Basic/OpenACCClauses.def @@ -37,8 +37,6 @@ CLAUSE_ALIAS(PCreate, Create) CLAUSE_ALIAS(PresentOrCreate, Create) VISIT_CLAUSE(Default) VISIT_CLAUSE(DevicePtr) -VISIT_CLAUSE(DeviceType) -CLAUSE_ALIAS(DType, DeviceType) VISIT_CLAUSE(FirstPrivate) VISIT_CLAUSE(If) VISIT_CLAUSE(NoCreate) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 3910cba34a21..61589fb7766f 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3720,8 +3720,7 @@ private: SourceLocation Loc, llvm::SmallVectorImpl &IntExprs); /// Parses the 'device-type-list', which is a list of identifiers. - bool ParseOpenACCDeviceTypeList( - llvm::SmallVector> &Archs); + bool ParseOpenACCDeviceTypeList(); /// Parses the 'async-argument', which is an integral value with two /// 'special' values that are likely negative (but come from Macros). OpenACCIntExprParseResult ParseOpenACCAsyncArgument(OpenACCDirectiveKind DK, diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index f838fa97d33a..e684ee6b2be1 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -26,9 +26,6 @@ class OpenACCClause; class SemaOpenACC : public SemaBase { public: - // Redeclaration of the version in OpenACCClause.h. - using DeviceTypeArgument = std::pair; - /// A type to represent all the data for an OpenACC Clause that has been /// parsed, but not yet created/semantically analyzed. This is effectively a /// discriminated union on the 'Clause Kind', with all of the individual @@ -63,12 +60,8 @@ public: SmallVector QueueIdExprs; }; - struct DeviceTypeDetails { - SmallVector Archs; - }; - std::variant + IntExprDetails, VarListDetails, WaitDetails> Details = std::monostate{}; public: @@ -216,13 +209,6 @@ public: return std::get(Details).IsZero; } - ArrayRef getDeviceTypeArchitectures() const { - assert((ClauseKind == OpenACCClauseKind::DeviceType || - ClauseKind == OpenACCClauseKind::DType) && - "Only 'device_type'/'dtype' has a device-type-arg list"); - return std::get(Details).Archs; - } - void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; } void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); } @@ -340,13 +326,6 @@ public: "Parsed clause kind does not have a wait-details"); Details = WaitDetails{DevNum, QueuesLoc, std::move(IntExprs)}; } - - void setDeviceTypeDetails(llvm::SmallVector &&Archs) { - assert((ClauseKind == OpenACCClauseKind::DeviceType || - ClauseKind == OpenACCClauseKind::DType) && - "Only 'device_type'/'dtype' has a device-type-arg list"); - Details = DeviceTypeDetails{std::move(Archs)}; - } }; SemaOpenACC(Sema &S); diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index f80ecc90d396..ee13437b97b4 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -18,8 +18,7 @@ using namespace clang; bool OpenACCClauseWithParams::classof(const OpenACCClause *C) { - return OpenACCDeviceTypeClause::classof(C) || - OpenACCClauseWithCondition::classof(C) || + return OpenACCClauseWithCondition::classof(C) || OpenACCClauseWithExprs::classof(C); } bool OpenACCClauseWithExprs::classof(const OpenACCClause *C) { @@ -299,17 +298,6 @@ OpenACCCreateClause::Create(const ASTContext &C, OpenACCClauseKind Spelling, VarList, EndLoc); } -OpenACCDeviceTypeClause *OpenACCDeviceTypeClause::Create( - const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc, - SourceLocation LParenLoc, ArrayRef Archs, - SourceLocation EndLoc) { - void *Mem = - C.Allocate(OpenACCDeviceTypeClause::totalSizeToAlloc( - Archs.size())); - return new (Mem) - OpenACCDeviceTypeClause(K, BeginLoc, LParenLoc, Archs, EndLoc); -} - //===----------------------------------------------------------------------===// // OpenACC clauses printing methods //===----------------------------------------------------------------------===// @@ -463,17 +451,3 @@ void OpenACCClausePrinter::VisitWaitClause(const OpenACCWaitClause &C) { OS << ")"; } } - -void OpenACCClausePrinter::VisitDeviceTypeClause( - const OpenACCDeviceTypeClause &C) { - OS << C.getClauseKind(); - OS << "("; - llvm::interleaveComma(C.getArchitectures(), OS, - [&](const DeviceTypeArgument &Arch) { - if (Arch.first == nullptr) - OS << "*"; - else - OS << Arch.first; - }); - OS << ")"; -} diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index caab4ab0ef16..8fb8940142eb 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2585,9 +2585,6 @@ void OpenACCClauseProfiler::VisitWaitClause(const OpenACCWaitClause &Clause) { for (auto *E : Clause.getQueueIdExprs()) Profiler.VisitStmt(E); } -/// Nothing to do here, there are no sub-statements. -void OpenACCClauseProfiler::VisitDeviceTypeClause( - const OpenACCDeviceTypeClause &Clause) {} } // namespace void StmtProfiler::VisitOpenACCComputeConstruct( diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index efcd74717a4e..12aa5858b798 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -444,19 +444,6 @@ void TextNodeDumper::Visit(const OpenACCClause *C) { if (cast(C)->hasQueuesTag()) OS << " has queues tag"; break; - case OpenACCClauseKind::DeviceType: - case OpenACCClauseKind::DType: - OS << "("; - llvm::interleaveComma( - cast(C)->getArchitectures(), OS, - [&](const DeviceTypeArgument &Arch) { - if (Arch.first == nullptr) - OS << "*"; - else - OS << Arch.first->getName(); - }); - OS << ")"; - break; default: // Nothing to do here. break; diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 261c9cdc088b..0e10632c8317 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -711,15 +711,14 @@ bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK, /// device_type( device-type-list ) /// /// The device_type clause may be abbreviated to dtype. -bool Parser::ParseOpenACCDeviceTypeList( - llvm::SmallVector> &Archs) { +bool Parser::ParseOpenACCDeviceTypeList() { if (expectIdentifierOrKeyword(*this)) { SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, Parser::StopBeforeMatch); - return true; + return false; } - Archs.emplace_back(getCurToken().getIdentifierInfo(), ConsumeToken()); + ConsumeToken(); while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { ExpectAndConsume(tok::comma); @@ -727,9 +726,9 @@ bool Parser::ParseOpenACCDeviceTypeList( if (expectIdentifierOrKeyword(*this)) { SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, Parser::StopBeforeMatch); - return true; + return false; } - Archs.emplace_back(getCurToken().getIdentifierInfo(), ConsumeToken()); + ConsumeToken(); } return false; } @@ -1022,20 +1021,16 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( break; } case OpenACCClauseKind::DType: - case OpenACCClauseKind::DeviceType: { - llvm::SmallVector> Archs; + case OpenACCClauseKind::DeviceType: if (getCurToken().is(tok::star)) { // FIXME: We want to mark that this is an 'everything else' type of // device_type in Sema. - ParsedClause.setDeviceTypeDetails({{nullptr, ConsumeToken()}}); - } else if (!ParseOpenACCDeviceTypeList(Archs)) { - ParsedClause.setDeviceTypeDetails(std::move(Archs)); - } else { + ConsumeToken(); + } else if (ParseOpenACCDeviceTypeList()) { Parens.skipToEnd(); return OpenACCCanContinue(); } break; - } case OpenACCClauseKind::Tile: if (ParseOpenACCSizeExprList()) { Parens.skipToEnd(); diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index f174b2fa63c6..656d30947a8d 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -255,33 +255,6 @@ bool checkAlreadyHasClauseOfKind( return false; } -/// Implement check from OpenACC3.3: section 2.5.4: -/// Only the async, wait, num_gangs, num_workers, and vector_length clauses may -/// follow a device_type clause. -bool checkValidAfterDeviceType( - SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause, - const SemaOpenACC::OpenACCParsedClause &NewClause) { - // This is only a requirement on compute constructs so far, so this is fine - // otherwise. - if (!isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind())) - return false; - switch (NewClause.getClauseKind()) { - case OpenACCClauseKind::Async: - case OpenACCClauseKind::Wait: - case OpenACCClauseKind::NumGangs: - case OpenACCClauseKind::NumWorkers: - case OpenACCClauseKind::VectorLength: - case OpenACCClauseKind::DType: - case OpenACCClauseKind::DeviceType: - return false; - default: - S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type) - << NewClause.getClauseKind() << DeviceTypeClause.getClauseKind(); - S.Diag(DeviceTypeClause.getBeginLoc(), diag::note_acc_previous_clause_here); - return true; - } -} - } // namespace SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {} @@ -300,17 +273,6 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, return nullptr; } - if (const auto *DevTypeClause = - llvm::find_if(ExistingClauses, - [&](const OpenACCClause *C) { - return isa(C); - }); - DevTypeClause != ExistingClauses.end()) { - if (checkValidAfterDeviceType( - *this, *cast(*DevTypeClause), Clause)) - return nullptr; - } - switch (Clause.getClauseKind()) { case OpenACCClauseKind::Default: { // Restrictions only properly implemented on 'compute' constructs, and @@ -689,23 +651,6 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, Clause.getDevNumExpr(), Clause.getQueuesLoc(), Clause.getQueueIdExprs(), Clause.getEndLoc()); } - case OpenACCClauseKind::DType: - case OpenACCClauseKind::DeviceType: { - // Restrictions only properly implemented on 'compute' constructs, and - // 'compute' constructs are the only construct that can do anything with - // this yet, so skip/treat as unimplemented in this case. - if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) - break; - - // TODO OpenACC: Once we get enough of the CodeGen implemented that we have - // a source for the list of valid architectures, we need to warn on unknown - // identifiers here. - - return OpenACCDeviceTypeClause::Create( - getASTContext(), Clause.getClauseKind(), Clause.getBeginLoc(), - Clause.getLParenLoc(), Clause.getDeviceTypeArchitectures(), - Clause.getEndLoc()); - } default: break; } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index ab26d1b1199a..126965088831 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -11480,16 +11480,6 @@ void OpenACCClauseTransform::VisitWaitClause( ParsedClause.getQueuesLoc(), ParsedClause.getQueueIdExprs(), ParsedClause.getEndLoc()); } - -template -void OpenACCClauseTransform::VisitDeviceTypeClause( - const OpenACCDeviceTypeClause &C) { - // Nothing to transform here, just create a new version of 'C'. - NewClause = OpenACCDeviceTypeClause::Create( - Self.getSema().getASTContext(), C.getClauseKind(), - ParsedClause.getBeginLoc(), ParsedClause.getLParenLoc(), - C.getArchitectures(), ParsedClause.getEndLoc()); -} } // namespace template OpenACCClause *TreeTransform::TransformOpenACCClause( diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 8f437a7c5f50..7627996d2c32 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11905,21 +11905,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { DevNumExpr, QueuesLoc, QueueIdExprs, EndLoc); } - case OpenACCClauseKind::DeviceType: - case OpenACCClauseKind::DType: { - SourceLocation LParenLoc = readSourceLocation(); - llvm::SmallVector Archs; - unsigned NumArchs = readInt(); - - for (unsigned I = 0; I < NumArchs; ++I) { - IdentifierInfo *Ident = readBool() ? readIdentifier() : nullptr; - SourceLocation Loc = readSourceLocation(); - Archs.emplace_back(Ident, Loc); - } - - return OpenACCDeviceTypeClause::Create(getContext(), ClauseKind, BeginLoc, - LParenLoc, Archs, EndLoc); - } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: @@ -11941,6 +11926,8 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { case OpenACCClauseKind::Bind: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: + case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DType: case OpenACCClauseKind::Tile: case OpenACCClauseKind::Gang: case OpenACCClauseKind::Invalid: diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 7a9d392889bb..6154ead589d3 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7933,19 +7933,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeOpenACCIntExprList(WC->getQueueIdExprs()); return; } - case OpenACCClauseKind::DeviceType: - case OpenACCClauseKind::DType: { - const auto *DTC = cast(C); - writeSourceLocation(DTC->getLParenLoc()); - writeUInt32(DTC->getArchitectures().size()); - for (const DeviceTypeArgument &Arg : DTC->getArchitectures()) { - writeBool(Arg.first); - if (Arg.first) - AddIdentifierRef(Arg.first); - writeSourceLocation(Arg.second); - } - return; - } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: @@ -7967,6 +7954,8 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::Bind: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: + case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DType: case OpenACCClauseKind::Tile: case OpenACCClauseKind::Gang: case OpenACCClauseKind::Invalid: diff --git a/clang/test/AST/ast-print-openacc-compute-construct.cpp b/clang/test/AST/ast-print-openacc-compute-construct.cpp index cdd9ab3377d0..0bfb90bcb587 100644 --- a/clang/test/AST/ast-print-openacc-compute-construct.cpp +++ b/clang/test/AST/ast-print-openacc-compute-construct.cpp @@ -107,28 +107,5 @@ void foo() { // CHECK: #pragma acc parallel wait(devnum: i : queues: *iPtr, i) #pragma acc parallel wait(devnum:i:queues:*iPtr, i) while(true); - - bool SomeB; - struct SomeStruct{} SomeStructImpl; - -//#pragma acc parallel dtype(SomeB) -#pragma acc parallel dtype(SomeB) - while(true); - -//#pragma acc parallel device_type(SomeStruct) -#pragma acc parallel device_type(SomeStruct) - while(true); - -//#pragma acc parallel device_type(int) -#pragma acc parallel device_type(int) - while(true); - -//#pragma acc parallel dtype(bool) -#pragma acc parallel dtype(bool) - while(true); - -//#pragma acc parallel device_type (SomeStructImpl) -#pragma acc parallel device_type (SomeStructImpl) - while(true); } diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index 694f28b86ec9..51858b441e93 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -1126,10 +1126,12 @@ void device_type() { #pragma acc parallel dtype( {} - // expected-error@+1{{expected identifier}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} #pragma acc parallel device_type() {} - // expected-error@+1{{expected identifier}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} #pragma acc parallel dtype() {} @@ -1171,10 +1173,12 @@ void device_type() { #pragma acc parallel dtype(ident, ident2 {} - // expected-error@+1{{expected identifier}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} #pragma acc parallel device_type(ident, ident2,) {} - // expected-error@+1{{expected identifier}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} #pragma acc parallel dtype(ident, ident2,) {} @@ -1196,25 +1200,33 @@ void device_type() { #pragma acc parallel dtype(*,ident) {} - // expected-error@+1{{expected identifier}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} #pragma acc parallel device_type(ident, *) {} - // expected-error@+1{{expected identifier}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} #pragma acc parallel dtype(ident, *) {} - // expected-error@+1{{expected identifier}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} #pragma acc parallel device_type("foo", 54) {} - // expected-error@+1{{expected identifier}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} #pragma acc parallel dtype(31, "bar") {} + // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} #pragma acc parallel device_type(ident, auto, int, float) {} + // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} #pragma acc parallel dtype(ident, auto, int, float) {} + // expected-warning@+2{{OpenACC clause 'device_type' not yet implemented, clause ignored}} + // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} #pragma acc parallel device_type(ident, auto, int, float) dtype(ident, auto, int, float) {} } diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp b/clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp deleted file mode 100644 index 8a2423f4f542..000000000000 --- a/clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s - -// Test this with PCH. -// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s -// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s -#ifndef PCH_HELPER -#define PCH_HELPER - -struct SomeS{}; -void NormalUses() { - // CHECK: FunctionDecl{{.*}}NormalUses - // CHECK-NEXT: CompoundStmt - - SomeS SomeImpl; - // CHECK-NEXT: DeclStmt - // CHECK-NEXT: VarDecl{{.*}} SomeImpl 'SomeS' - // CHECK-NEXT: CXXConstructExpr - bool SomeVar; - // CHECK-NEXT: DeclStmt - // CHECK-NEXT: VarDecl{{.*}} SomeVar 'bool' - -#pragma acc parallel device_type(SomeS) dtype(SomeImpl) - while(true){} - // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel - // CHECK-NEXT: device_type(SomeS) - // CHECK-NEXT: dtype(SomeImpl) - // CHECK-NEXT: WhileStmt - // CHECK-NEXT: CXXBoolLiteralExpr - // CHECK-NEXT: CompoundStmt -#pragma acc parallel device_type(SomeVar) dtype(int) - while(true){} - // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel - // CHECK-NEXT: device_type(SomeVar) - // CHECK-NEXT: dtype(int) - // CHECK-NEXT: WhileStmt - // CHECK-NEXT: CXXBoolLiteralExpr - // CHECK-NEXT: CompoundStmt -#pragma acc parallel device_type(private) dtype(struct) - while(true){} - // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel - // CHECK-NEXT: device_type(private) - // CHECK-NEXT: dtype(struct) - // CHECK-NEXT: WhileStmt - // CHECK-NEXT: CXXBoolLiteralExpr - // CHECK-NEXT: CompoundStmt -#pragma acc parallel device_type(private) dtype(class) - while(true){} - // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel - // CHECK-NEXT: device_type(private) - // CHECK-NEXT: dtype(class) - // CHECK-NEXT: WhileStmt - // CHECK-NEXT: CXXBoolLiteralExpr - // CHECK-NEXT: CompoundStmt -#pragma acc parallel device_type(float) dtype(*) - while(true){} - // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel - // CHECK-NEXT: device_type(float) - // CHECK-NEXT: dtype(*) - // CHECK-NEXT: WhileStmt - // CHECK-NEXT: CXXBoolLiteralExpr - // CHECK-NEXT: CompoundStmt -#pragma acc parallel device_type(float, int) dtype(*) - while(true){} - // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel - // CHECK-NEXT: device_type(float, int) - // CHECK-NEXT: dtype(*) - // CHECK-NEXT: WhileStmt - // CHECK-NEXT: CXXBoolLiteralExpr - // CHECK-NEXT: CompoundStmt -} - -template -void TemplUses() { - // CHECK-NEXT: FunctionTemplateDecl{{.*}}TemplUses - // CHECK-NEXT: TemplateTypeParmDecl{{.*}}T - // CHECK-NEXT: FunctionDecl{{.*}}TemplUses - // CHECK-NEXT: CompoundStmt -#pragma acc parallel device_type(T) dtype(T) - while(true){} - // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel - // CHECK-NEXT: device_type(T) - // CHECK-NEXT: dtype(T) - // CHECK-NEXT: WhileStmt - // CHECK-NEXT: CXXBoolLiteralExpr - // CHECK-NEXT: CompoundStmt - - - // Instantiations - // CHECK-NEXT: FunctionDecl{{.*}} TemplUses 'void ()' implicit_instantiation - // CHECK-NEXT: TemplateArgument type 'int' - // CHECK-NEXT: BuiltinType{{.*}} 'int' - // CHECK-NEXT: CompoundStmt - - // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel - // CHECK-NEXT: device_type(T) - // CHECK-NEXT: dtype(T) - // CHECK-NEXT: WhileStmt - // CHECK-NEXT: CXXBoolLiteralExpr - // CHECK-NEXT: CompoundStmt -} - -void Inst() { - TemplUses(); -} -#endif // PCH_HELPER diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-clause.c b/clang/test/SemaOpenACC/compute-construct-device_type-clause.c deleted file mode 100644 index 15c9cf396c80..000000000000 --- a/clang/test/SemaOpenACC/compute-construct-device_type-clause.c +++ /dev/null @@ -1,221 +0,0 @@ -// RUN: %clang_cc1 %s -fopenacc -verify - -#define MACRO +FOO - -void uses() { - typedef struct S{} STy; - STy SImpl; - -#pragma acc parallel device_type(I) - while(1); -#pragma acc serial device_type(S) dtype(STy) - while(1); -#pragma acc kernels dtype(SImpl) - while(1); -#pragma acc kernels dtype(int) device_type(*) - while(1); -#pragma acc kernels dtype(true) device_type(false) - while(1); - - // expected-error@+1{{expected identifier}} -#pragma acc kernels dtype(int, *) - while(1); - -#pragma acc parallel device_type(I, int) - while(1); - // expected-error@+2{{expected ','}} - // expected-error@+1{{expected identifier}} -#pragma acc kernels dtype(int{}) - while(1); - // expected-error@+1{{expected identifier}} -#pragma acc kernels dtype(5) - while(1); - // expected-error@+1{{expected identifier}} -#pragma acc kernels dtype(MACRO) - while(1); - - - // Only 'async', 'wait', num_gangs', 'num_workers', 'vector_length' allowed after 'device_type'. - - // expected-error@+2{{OpenACC clause 'finalize' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) finalize - while(1); - // expected-error@+2{{OpenACC clause 'if_present' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) if_present - while(1); - // expected-error@+2{{OpenACC clause 'seq' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) seq - while(1); - // expected-error@+2{{OpenACC clause 'independent' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) independent - while(1); - // expected-error@+2{{OpenACC clause 'auto' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) auto - while(1); - // expected-error@+2{{OpenACC clause 'worker' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) worker - while(1); - // expected-error@+2{{OpenACC clause 'nohost' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) nohost - while(1); - // expected-error@+2{{OpenACC clause 'default' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) default(none) - while(1); - // expected-error@+2{{OpenACC clause 'if' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) if(1) - while(1); - // expected-error@+2{{OpenACC clause 'self' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) self - while(1); - - int Var; - int *VarPtr; - // expected-error@+2{{OpenACC clause 'copy' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) copy(Var) - while(1); - // expected-error@+2{{OpenACC clause 'pcopy' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) pcopy(Var) - while(1); - // expected-error@+2{{OpenACC clause 'present_or_copy' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) present_or_copy(Var) - while(1); - // expected-error@+2{{OpenACC clause 'use_device' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) use_device(Var) - while(1); - // expected-error@+2{{OpenACC clause 'attach' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) attach(Var) - while(1); - // expected-error@+2{{OpenACC clause 'delete' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) delete(Var) - while(1); - // expected-error@+2{{OpenACC clause 'detach' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) detach(Var) - while(1); - // expected-error@+2{{OpenACC clause 'device' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) device(VarPtr) - while(1); - // expected-error@+2{{OpenACC clause 'deviceptr' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) deviceptr(VarPtr) - while(1); - // expected-error@+2{{OpenACC clause 'device_resident' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) device_resident(VarPtr) - while(1); - // expected-error@+2{{OpenACC clause 'firstprivate' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc parallel device_type(*) firstprivate(Var) - while(1); - // expected-error@+2{{OpenACC clause 'host' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) host(Var) - while(1); - // expected-error@+2{{OpenACC clause 'link' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) link(Var) - while(1); - // expected-error@+2{{OpenACC clause 'no_create' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) no_create(Var) - while(1); - // expected-error@+2{{OpenACC clause 'present' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) present(Var) - while(1); - // expected-error@+2{{OpenACC clause 'private' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc parallel device_type(*) private(Var) - while(1); - // expected-error@+2{{OpenACC clause 'copyout' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) copyout(Var) - while(1); - // expected-error@+2{{OpenACC clause 'pcopyout' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) pcopyout(Var) - while(1); - // expected-error@+2{{OpenACC clause 'present_or_copyout' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) present_or_copyout(Var) - while(1); - // expected-error@+2{{OpenACC clause 'copyin' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) copyin(Var) - while(1); - // expected-error@+2{{OpenACC clause 'pcopyin' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) pcopyin(Var) - while(1); - // expected-error@+2{{OpenACC clause 'present_or_copyin' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) present_or_copyin(Var) - while(1); - // expected-error@+2{{OpenACC clause 'create' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) create(Var) - while(1); - // expected-error@+2{{OpenACC clause 'pcreate' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) pcreate(Var) - while(1); - // expected-error@+2{{OpenACC clause 'present_or_create' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) present_or_create(Var) - while(1); - // expected-error@+2{{OpenACC clause 'reduction' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) reduction(+:Var) - while(1); - // expected-error@+2{{OpenACC clause 'collapse' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) collapse(1) - while(1); - // expected-error@+2{{OpenACC clause 'bind' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) bind(Var) - while(1); -#pragma acc kernels device_type(*) vector_length(1) - while(1); -#pragma acc kernels device_type(*) num_gangs(1) - while(1); -#pragma acc kernels device_type(*) num_workers(1) - while(1); - // expected-error@+2{{OpenACC clause 'device_num' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) device_num(1) - while(1); - // expected-error@+2{{OpenACC clause 'default_async' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) default_async(1) - while(1); -#pragma acc kernels device_type(*) async - while(1); - // expected-error@+2{{OpenACC clause 'tile' may not follow a 'device_type' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels device_type(*) tile(Var, 1) - while(1); - // expected-error@+2{{OpenACC clause 'gang' may not follow a 'dtype' clause in a compute construct}} - // expected-note@+1{{previous clause is here}} -#pragma acc kernels dtype(*) gang - while(1); -#pragma acc kernels device_type(*) wait - while(1); -} diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp b/clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp deleted file mode 100644 index ed40e8bbceae..000000000000 --- a/clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// RUN: %clang_cc1 %s -fopenacc -verify - -template -void TemplUses() { -#pragma acc parallel device_type(I) - while(true); -#pragma acc parallel dtype(*) - while(true); -#pragma acc parallel device_type(class) - while(true); -#pragma acc parallel device_type(private) - while(true); -#pragma acc parallel device_type(bool) - while(true); -#pragma acc kernels dtype(true) device_type(false) - while(true); - // expected-error@+2{{expected ','}} - // expected-error@+1{{expected identifier}} -#pragma acc parallel device_type(T::value) - while(true); -} - -void Inst() { - TemplUses(); // #INST -} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 8b9417f985b5..ae6659fe95e8 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2857,8 +2857,6 @@ void OpenACCClauseEnqueue::VisitWaitClause(const OpenACCWaitClause &C) { for (Expr *QE : C.getQueueIdExprs()) Visitor.AddStmt(QE); } -void OpenACCClauseEnqueue::VisitDeviceTypeClause( - const OpenACCDeviceTypeClause &C) {} } // namespace void EnqueueVisitor::EnqueueChildren(const OpenACCClause *C) { -- GitLab From 1934e4afd6276cd2440357b788d7efe6a4abdebe Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 13 May 2024 10:41:36 -0500 Subject: [PATCH 088/578] [flang][OpenMP] Add explicit N to SmallVector to avoid size error This fixes https://lab.llvm.org/buildbot/#/builders/268/builds/13925, which somehow doesn't show in any of my local builds. --- llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h index edb65ed6d324..9dcb115a0c51 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h @@ -297,7 +297,7 @@ template void ConstructCompositionT::mergeDSA() { }; // Use ordered containers to avoid non-deterministic output. - llvm::SmallVector> objectDsa; + llvm::SmallVector, 8> objectDsa; auto getDsa = [&](const ObjectTy &object) -> std::pair & { auto found = llvm::find_if(objectDsa, [&](std::pair &p) { -- GitLab From 2d511cdc10be611999d2a3c8983a992dd90f892c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 13 May 2024 17:44:14 +0200 Subject: [PATCH 089/578] [clang][Interp][NFC] Add missing test diagnostic output This was left out from https://github.com/llvm/llvm-project/commit/257013e4f5cbdf644646da9ec3d60d6209c9bf25 --- clang/test/AST/Interp/arrays.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp index 70e87c4cd854..f6d265d4b3d1 100644 --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -563,6 +563,11 @@ namespace LocalVLA { void f (unsigned int m) { int e[2][m]; +#if __cplusplus >= 202002L + // both-note@-3 {{declared here}} + // both-warning@-3 2{{variable length array}} + // both-note@-4 {{function parameter 'm' with unknown value}} +#endif e[0][0] = 0; } } -- GitLab From d95f7c9cabf493ffdc615df47a420a80d4be8e5c Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Mon, 13 May 2024 08:52:59 -0700 Subject: [PATCH 090/578] [RISCV] Use the thread local stack protector for Android targets (#87672) Android supports per thread stack protectors that are individually managed and initialized, which can provide stronger protections than using the global stack protector cookie. This patch matches the convention for other architectures targeting Android platforms. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 6 ++++++ .../CodeGen/RISCV/stack-protector-target.ll | 17 +++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 60985edd9420..d0f62b1d5414 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -21052,6 +21052,12 @@ Value *RISCVTargetLowering::getIRStackGuard(IRBuilderBase &IRB) const { if (Subtarget.isTargetFuchsia()) return useTpOffset(IRB, -0x10); + // Android provides a fixed TLS slot for the stack cookie. See the definition + // of TLS_SLOT_STACK_GUARD in + // https://android.googlesource.com/platform/bionic/+/main/libc/platform/bionic/tls_defines.h + if (Subtarget.isTargetAndroid()) + return useTpOffset(IRB, -0x18); + return TargetLowering::getIRStackGuard(IRB); } diff --git a/llvm/test/CodeGen/RISCV/stack-protector-target.ll b/llvm/test/CodeGen/RISCV/stack-protector-target.ll index 50531d384982..a4bd0e9ceac9 100644 --- a/llvm/test/CodeGen/RISCV/stack-protector-target.ll +++ b/llvm/test/CodeGen/RISCV/stack-protector-target.ll @@ -50,21 +50,18 @@ define void @func() sspreq nounwind { ; ANDROID-RISCV64: # %bb.0: ; ANDROID-RISCV64-NEXT: addi sp, sp, -32 ; ANDROID-RISCV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill -; ANDROID-RISCV64-NEXT: sd s0, 16(sp) # 8-byte Folded Spill -; ANDROID-RISCV64-NEXT: lui s0, %hi(__stack_chk_guard) -; ANDROID-RISCV64-NEXT: ld a0, %lo(__stack_chk_guard)(s0) -; ANDROID-RISCV64-NEXT: sd a0, 8(sp) -; ANDROID-RISCV64-NEXT: addi a0, sp, 4 +; ANDROID-RISCV64-NEXT: ld a0, -24(tp) +; ANDROID-RISCV64-NEXT: sd a0, 16(sp) +; ANDROID-RISCV64-NEXT: addi a0, sp, 12 ; ANDROID-RISCV64-NEXT: call capture -; ANDROID-RISCV64-NEXT: ld a0, %lo(__stack_chk_guard)(s0) -; ANDROID-RISCV64-NEXT: ld a1, 8(sp) +; ANDROID-RISCV64-NEXT: ld a0, -24(tp) +; ANDROID-RISCV64-NEXT: ld a1, 16(sp) ; ANDROID-RISCV64-NEXT: bne a0, a1, .LBB0_2 -; ANDROID-RISCV64-NEXT: # %bb.1: +; ANDROID-RISCV64-NEXT: # %bb.1: # %SP_return ; ANDROID-RISCV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload -; ANDROID-RISCV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; ANDROID-RISCV64-NEXT: addi sp, sp, 32 ; ANDROID-RISCV64-NEXT: ret -; ANDROID-RISCV64-NEXT: .LBB0_2: +; ANDROID-RISCV64-NEXT: .LBB0_2: # %CallStackCheckFailBlk ; ANDROID-RISCV64-NEXT: call __stack_chk_fail %1 = alloca i32, align 4 call void @capture(ptr %1) -- GitLab From d94e0a1005ee1cfeeda829d9deb1f299deb7b10a Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Mon, 13 May 2024 15:53:36 +0000 Subject: [PATCH 091/578] [gn build] Port be7c9e39572d --- llvm/utils/gn/secondary/llvm/unittests/Frontend/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/llvm/unittests/Frontend/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/Frontend/BUILD.gn index 80ac77feec9a..6070a6f00419 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/Frontend/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/Frontend/BUILD.gn @@ -15,6 +15,7 @@ unittest("LLVMFrontendTests") { "OpenACCTest.cpp", "OpenMPCompositionTest.cpp", "OpenMPContextTest.cpp", + "OpenMPDecompositionTest.cpp", "OpenMPIRBuilderTest.cpp", "OpenMPParsingTest.cpp", ] -- GitLab From 754ff0f54a4b09a8e4b00783475c51f66b949b66 Mon Sep 17 00:00:00 2001 From: Alex Bradbury Date: Mon, 13 May 2024 17:05:28 +0100 Subject: [PATCH 092/578] [TableGen][RISCV] Use getAllDerivedDefinitionsIfDefined in RISCVTargetDefEmitter (#91941) getAllDerivedDefinitions produces a fatal error if there are no definitions. In practice this isn't much of a problem for llvm/lib/Target/RISCV/*.td where it's hard to imagine not having at least one of the required defitions. But it limits our ability to structure and maintain tests (which is how I came across this issue). This commit moves to using getAllDerivedDefinitionsIfDefined and aims to skip emission of data structures that make no sense if no definitions were found. --- llvm/utils/TableGen/RISCVTargetDefEmitter.cpp | 60 ++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp b/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp index 6784514032eb..bb409ea6ea69 100644 --- a/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp +++ b/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp @@ -48,37 +48,41 @@ static void emitRISCVExtensions(RecordKeeper &Records, raw_ostream &OS) { OS << "#undef GET_SUPPORTED_EXTENSIONS\n\n"; std::vector Extensions = - Records.getAllDerivedDefinitions("RISCVExtension"); + Records.getAllDerivedDefinitionsIfDefined("RISCVExtension"); llvm::sort(Extensions, [](const Record *Rec1, const Record *Rec2) { return getExtensionName(Rec1) < getExtensionName(Rec2); }); - printExtensionTable(OS, Extensions, /*Experimental=*/false); - printExtensionTable(OS, Extensions, /*Experimental=*/true); + if (!Extensions.empty()) { + printExtensionTable(OS, Extensions, /*Experimental=*/false); + printExtensionTable(OS, Extensions, /*Experimental=*/true); + } OS << "#endif // GET_SUPPORTED_EXTENSIONS\n\n"; OS << "#ifdef GET_IMPLIED_EXTENSIONS\n"; OS << "#undef GET_IMPLIED_EXTENSIONS\n\n"; - OS << "\nstatic constexpr ImpliedExtsEntry ImpliedExts[] = {\n"; - for (Record *Ext : Extensions) { - auto ImpliesList = Ext->getValueAsListOfDefs("Implies"); - if (ImpliesList.empty()) - continue; + if (!Extensions.empty()) { + OS << "\nstatic constexpr ImpliedExtsEntry ImpliedExts[] = {\n"; + for (Record *Ext : Extensions) { + auto ImpliesList = Ext->getValueAsListOfDefs("Implies"); + if (ImpliesList.empty()) + continue; - StringRef Name = getExtensionName(Ext); + StringRef Name = getExtensionName(Ext); - for (auto *ImpliedExt : ImpliesList) { - if (!ImpliedExt->isSubClassOf("RISCVExtension")) - continue; + for (auto *ImpliedExt : ImpliesList) { + if (!ImpliedExt->isSubClassOf("RISCVExtension")) + continue; - OS << " { {\"" << Name << "\"}, \"" << getExtensionName(ImpliedExt) - << "\"},\n"; + OS << " { {\"" << Name << "\"}, \"" << getExtensionName(ImpliedExt) + << "\"},\n"; + } } - } - OS << "};\n\n"; + OS << "};\n\n"; + } OS << "#endif // GET_IMPLIED_EXTENSIONS\n\n"; } @@ -122,19 +126,20 @@ static void emitRISCVProfiles(RecordKeeper &Records, raw_ostream &OS) { OS << "#ifdef GET_SUPPORTED_PROFILES\n"; OS << "#undef GET_SUPPORTED_PROFILES\n\n"; - OS << "static constexpr RISCVProfile SupportedProfiles[] = {\n"; + auto Profiles = Records.getAllDerivedDefinitionsIfDefined("RISCVProfile"); - auto Profiles = Records.getAllDerivedDefinitions("RISCVProfile"); - llvm::sort(Profiles, LessRecordFieldName()); + if (!Profiles.empty()) { + llvm::sort(Profiles, LessRecordFieldName()); + OS << "static constexpr RISCVProfile SupportedProfiles[] = {\n"; + for (const Record *Rec : Profiles) { + OS.indent(4) << "{\"" << Rec->getValueAsString("Name") << "\",\""; + printMArch(OS, Rec->getValueAsListOfDefs("Implies")); + OS << "\"},\n"; + } - for (const Record *Rec : Profiles) { - OS.indent(4) << "{\"" << Rec->getValueAsString("Name") << "\",\""; - printMArch(OS, Rec->getValueAsListOfDefs("Implies")); - OS << "\"},\n"; + OS << "};\n\n"; } - OS << "};\n\n"; - OS << "#endif // GET_SUPPORTED_PROFILES\n\n"; } @@ -144,7 +149,8 @@ static void emitRISCVProcs(RecordKeeper &RK, raw_ostream &OS) { << "#endif\n\n"; // Iterate on all definition records. - for (const Record *Rec : RK.getAllDerivedDefinitions("RISCVProcessorModel")) { + for (const Record *Rec : + RK.getAllDerivedDefinitionsIfDefined("RISCVProcessorModel")) { const std::vector &Features = Rec->getValueAsListOfDefs("Features"); bool FastScalarUnalignedAccess = any_of(Features, [&](auto &Feature) { @@ -177,7 +183,7 @@ static void emitRISCVProcs(RecordKeeper &RK, raw_ostream &OS) { << "#endif\n\n"; for (const Record *Rec : - RK.getAllDerivedDefinitions("RISCVTuneProcessorModel")) { + RK.getAllDerivedDefinitionsIfDefined("RISCVTuneProcessorModel")) { OS << "TUNE_PROC(" << Rec->getName() << ", " << "\"" << Rec->getValueAsString("Name") << "\")\n"; } -- GitLab From 89a080cb79972abae240c226090af9a3094e2269 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Mon, 25 Mar 2024 21:02:15 +0000 Subject: [PATCH 093/578] [llvm][NFC] Document cl::opt MisExpectTolerance and fix typo Pull Request: https://github.com/llvm/llvm-project/pull/90670 --- llvm/lib/Transforms/Utils/MisExpect.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Utils/MisExpect.cpp b/llvm/lib/Transforms/Utils/MisExpect.cpp index 6f5a25a26821..759289384ee0 100644 --- a/llvm/lib/Transforms/Utils/MisExpect.cpp +++ b/llvm/lib/Transforms/Utils/MisExpect.cpp @@ -59,9 +59,10 @@ static cl::opt PGOWarnMisExpect( cl::desc("Use this option to turn on/off " "warnings about incorrect usage of llvm.expect intrinsics.")); +// Command line option for setting the diagnostic tolerance threshold static cl::opt MisExpectTolerance( "misexpect-tolerance", cl::init(0), - cl::desc("Prevents emiting diagnostics when profile counts are " + cl::desc("Prevents emitting diagnostics when profile counts are " "within N% of the threshold..")); } // namespace llvm -- GitLab From 596a9c1f9b3179b3c77cbde1e96619292ce2a10a Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 13 May 2024 12:24:46 -0400 Subject: [PATCH 094/578] [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation (#91972) #90152 introduced a bug that occurs when typo-correction attempts to fix a reference to a non-existent member of the current instantiation (even though `operator->` may return a different type than the object type). This patch fixes it by simply considering the object expression to be of type `ASTContext::DependentTy` when the arrow operator is used with a dependent non-pointer non-function operand (after any implicit conversions). --- clang/lib/Sema/SemaExprMember.cpp | 49 ++++++++++--------- .../temp.res/temp.dep/temp.dep.type/p4.cpp | 27 ++++++++++ 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 9fa69da4f968..244488a0b562 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -995,8 +995,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // arrow operator was used with a dependent non-pointer object expression, // build a CXXDependentScopeMemberExpr. if (R.wasNotFoundInCurrentInstantiation() || - (IsArrow && !BaseExprType->isPointerType() && - BaseExprType->isDependentType()) || (R.getLookupName().getCXXOverloadedOperator() == OO_Equal && (SS.isSet() ? SS.getScopeRep()->isDependent() : BaseExprType->isDependentType()))) @@ -1322,28 +1320,28 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, else if (const ObjCObjectPointerType *Ptr = BaseType->getAs()) BaseType = Ptr->getPointeeType(); - else if (!BaseType->isDependentType()) { - if (BaseType->isRecordType()) { - // Recover from arrow accesses to records, e.g.: - // struct MyRecord foo; - // foo->bar - // This is actually well-formed in C++ if MyRecord has an - // overloaded operator->, but that should have been dealt with - // by now--or a diagnostic message already issued if a problem - // was encountered while looking for the overloaded operator->. - if (!S.getLangOpts().CPlusPlus) { - S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() - << FixItHint::CreateReplacement(OpLoc, "."); - } - IsArrow = false; - } else if (BaseType->isFunctionType()) { - goto fail; - } else { - S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) - << BaseType << BaseExpr.get()->getSourceRange(); - return ExprError(); + else if (BaseType->isFunctionType()) + goto fail; + else if (BaseType->isDependentType()) + BaseType = S.Context.DependentTy; + else if (BaseType->isRecordType()) { + // Recover from arrow accesses to records, e.g.: + // struct MyRecord foo; + // foo->bar + // This is actually well-formed in C++ if MyRecord has an + // overloaded operator->, but that should have been dealt with + // by now--or a diagnostic message already issued if a problem + // was encountered while looking for the overloaded operator->. + if (!S.getLangOpts().CPlusPlus) { + S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "."); } + IsArrow = false; + } else { + S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) + << BaseType << BaseExpr.get()->getSourceRange(); + return ExprError(); } } @@ -1363,7 +1361,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, } // Handle field access to simple records. - if (BaseType->getAsRecordDecl() || BaseType->isDependentType()) { + if (BaseType->getAsRecordDecl()) { TypoExpr *TE = nullptr; if (LookupMemberExprInRecord(S, R, BaseExpr.get(), BaseType, OpLoc, IsArrow, SS, HasTemplateArgs, TemplateKWLoc, TE)) @@ -1374,6 +1372,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, // failed, the lookup result will have been cleared--that combined with the // valid-but-null ExprResult will trigger the appropriate diagnostics. return ExprResult(TE); + } else if (BaseType->isDependentType()) { + R.setNotFoundInCurrentInstantiation(); + return ExprEmpty(); } // Handle ivar access to Objective-C objects. diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp index 1adbc33a701c..3ca7c6c7eb8e 100644 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp @@ -539,6 +539,17 @@ namespace N4 { a->y; a->f(); a->g(); + + a->T::x; + a->T::y; + a->T::f(); + a->T::g(); + + // FIXME: 'U' should be a dependent name, and its lookup context should be 'a.operator->()'! + a->U::x; // expected-error {{use of undeclared identifier 'U'}} + a->U::y; // expected-error {{use of undeclared identifier 'U'}} + a->U::f(); // expected-error {{use of undeclared identifier 'U'}} + a->U::g(); // expected-error {{use of undeclared identifier 'U'}} } void instantiated(D a) { @@ -546,9 +557,25 @@ namespace N4 { a->y; // expected-error {{no member named 'y' in 'N4::B'}} a->f(); a->g(); // expected-error {{no member named 'g' in 'N4::B'}} + + a->T::x; + a->T::y; // expected-error {{no member named 'y' in 'N4::B'}} + a->T::f(); + a->T::g(); // expected-error {{no member named 'g' in 'N4::B'}} } }; template void D::instantiated(D); // expected-note {{in instantiation of}} + template + struct Typo { + T *operator->(); + + void not_instantiated(Typo a) { + a->Not_instantiated; + a->typo; + a->T::Not_instantiated; + a->T::typo; + } + }; } // namespace N4 -- GitLab From 1066eb55477044a3a92f3a40471375194dfcdbc8 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Mon, 13 May 2024 09:33:43 -0700 Subject: [PATCH 095/578] [flang] Fix a warning This patch fixes: flang/lib/Lower/OpenMP/OpenMP.cpp:2346:14: error: unused variable 'origDirective' [-Werror,-Wunused-variable] --- flang/lib/Lower/OpenMP/OpenMP.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index eaf4b5f997ff..f9ba2fcbbca7 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -2352,6 +2352,7 @@ genOMP(Fortran::lower::AbstractConverter &converter, assert(llvm::omp::blockConstructSet.test(origDirective) && "Expected block construct"); + (void)origDirective; for (const Clause &clause : clauses) { mlir::Location clauseLocation = converter.genLocation(clause.source); -- GitLab From 79643565a890d29560782fea23877ae61ea5b987 Mon Sep 17 00:00:00 2001 From: chenlin Date: Tue, 14 May 2024 00:42:04 +0800 Subject: [PATCH 096/578] [LoopUnroll] Remove redundant debug instructions after blocks have been merged (#91246) Remove redundant debug instructions after blocks have been merged into the predecessor, It can reduce some compile time in some cases. This change only fixes the situation of loop unrolling, and other situations are not considered. "RemoveRedundantDbgInstrs" seems to be very time-consuming. Thus, we just add here after the "Dest" has been merged into the "Fold", this may be a more targeted solution!!! fixes: https://github.com/llvm/llvm-project/issues/89073 --- llvm/lib/Transforms/Utils/LoopUnroll.cpp | 4 ++ .../LoopUnroll/unroll-remove-redundant-dbg.ll | 50 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 llvm/test/Transforms/LoopUnroll/unroll-remove-redundant-dbg.ll diff --git a/llvm/lib/Transforms/Utils/LoopUnroll.cpp b/llvm/lib/Transforms/Utils/LoopUnroll.cpp index 20978cf2e748..1216538195fb 100644 --- a/llvm/lib/Transforms/Utils/LoopUnroll.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnroll.cpp @@ -377,6 +377,10 @@ void llvm::simplifyLoopAfterUnroll(Loop *L, bool SimplifyIVs, LoopInfo *LI, const DataLayout &DL = L->getHeader()->getModule()->getDataLayout(); SmallVector DeadInsts; for (BasicBlock *BB : L->getBlocks()) { + // Remove repeated debug instructions after loop unrolling. + if (BB->getParent()->getSubprogram()) + RemoveRedundantDbgInstrs(BB); + for (Instruction &Inst : llvm::make_early_inc_range(*BB)) { if (Value *V = simplifyInstruction(&Inst, {DL, nullptr, DT, AC})) if (LI->replacementPreservesLCSSAForm(&Inst, V)) diff --git a/llvm/test/Transforms/LoopUnroll/unroll-remove-redundant-dbg.ll b/llvm/test/Transforms/LoopUnroll/unroll-remove-redundant-dbg.ll new file mode 100644 index 000000000000..8e348281dc61 --- /dev/null +++ b/llvm/test/Transforms/LoopUnroll/unroll-remove-redundant-dbg.ll @@ -0,0 +1,50 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -S -passes=loop-unroll | FileCheck %s + +define i64 @d(i1 %tobool.not, i32 %add, i64 %conv23) !dbg !14{ +; There should be only one "llvm.dbg.vale" after loop unrolling +; CHECK-LABEL: @d( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 0, metadata [[META16:![0-9]+]], metadata !DIExpression()), !dbg [[DBG17:![0-9]+]] +; CHECK-NEXT: ret i64 5 +; +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %k.045 = phi i64 [ 0, %entry ], [ %k.046, %for.body ] + tail call void @llvm.dbg.value(metadata i32 0, metadata !13, metadata !DIExpression()), !dbg !17 + %k.046 = add nuw nsw i64 %k.045, 1 + %exitcond = icmp ne i64 %k.046, 5 + br i1 %exitcond, label %for.body, label %for.end22 + +for.end22: ; preds = %for.body + ret i64 %k.046 +} + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!12} + +!0 = distinct !DICompileUnit(language: DW_LANG_C89, file: !1, producer: "clang version 19.0.0git (https://github.com/llvm/llvm-project.git ec062f5b33ed22c61742e3c1486f6cba915801e0)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "unroll-remove-redundant-dbg.c", directory: "", checksumkind: CSK_MD5, checksum: "aa30a1d8c04deb9b0f3885c258d2b674") +!2 = !{!3, !8, !10} +!3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression()) +!4 = distinct !DIGlobalVariable(name: "a", scope: !0, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true) +!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint32_t", file: !6, line: 198, baseType: !7) +!6 = !DIFile(filename: "/usr/include/stdint.h", directory: "", checksumkind: CSK_MD5, checksum: "da031bcff2d0c1d65aa92e7e68a44ef3") +!7 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!8 = !DIGlobalVariableExpression(var: !9, expr: !DIExpression()) +!9 = distinct !DIGlobalVariable(name: "c", scope: !0, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true) +!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) +!11 = distinct !DIGlobalVariable(name: "b", scope: !0, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true) +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !DILocalVariable(name: "f", scope: !14, file: !1, line: 4, type: !5) +!14 = distinct !DISubprogram(name: "d", scope: !1, file: !1, line: 3, type: !15, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !16) +!15 = !DISubroutineType(types: !16) +!16 = !{} +!17 = !DILocation(line: 0, scope: !14) -- GitLab From 91a14dbf825b79ff143d1b16124763a4a80facab Mon Sep 17 00:00:00 2001 From: Jeremy Kun Date: Mon, 13 May 2024 09:47:34 -0700 Subject: [PATCH 097/578] Support polynomial attributes with floating point coefficients (#91137) In summary: - `Monomial` -> `MonomialBase` with two inheriting `IntMonomial` and `FloatMonomial` for the different coefficient types - `Polynomial` -> `PolynomialBase` with `IntPolynomial` and `FloatPolynomial` inheriting - `PolynomialAttr` -> `IntPolynomialAttr`, and new `FloatPolynomialAttr` attribute, both of which may be input to `polynomial.constant` - Refactoring common parts of attribute parsers. --------- Co-authored-by: Jeremy Kun --- .../mlir/Dialect/Polynomial/IR/Polynomial.h | 193 ++++++++++++++---- .../mlir/Dialect/Polynomial/IR/Polynomial.td | 139 ++++++++----- mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp | 78 +++---- .../Polynomial/IR/PolynomialAttributes.cpp | 172 +++++++--------- mlir/test/Dialect/Polynomial/attributes.mlir | 22 +- mlir/test/Dialect/Polynomial/ops.mlir | 64 +++--- mlir/test/Dialect/Polynomial/ops_errors.mlir | 66 +++--- mlir/test/Dialect/Polynomial/types.mlir | 65 +++--- 8 files changed, 451 insertions(+), 348 deletions(-) diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h index 3325a6fa3f9f..2b3f0e105c6c 100644 --- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h +++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h @@ -11,10 +11,13 @@ #include "mlir/Support/LLVM.h" #include "mlir/Support/LogicalResult.h" +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" namespace mlir { @@ -27,98 +30,202 @@ namespace polynomial { /// would want to specify 128-bit polynomials statically in the source code. constexpr unsigned apintBitWidth = 64; -/// A class representing a monomial of a single-variable polynomial with integer -/// coefficients. -class Monomial { +template +class MonomialBase { public: - Monomial(int64_t coeff, uint64_t expo) - : coefficient(apintBitWidth, coeff), exponent(apintBitWidth, expo) {} - - Monomial(const APInt &coeff, const APInt &expo) + MonomialBase(const CoefficientType &coeff, const APInt &expo) : coefficient(coeff), exponent(expo) {} + virtual ~MonomialBase() = 0; - Monomial() : coefficient(apintBitWidth, 0), exponent(apintBitWidth, 0) {} + const CoefficientType &getCoefficient() const { return coefficient; } + CoefficientType &getMutableCoefficient() { return coefficient; } + const APInt &getExponent() const { return exponent; } + void setCoefficient(const CoefficientType &coeff) { coefficient = coeff; } + void setExponent(const APInt &exp) { exponent = exp; } - bool operator==(const Monomial &other) const { + bool operator==(const MonomialBase &other) const { return other.coefficient == coefficient && other.exponent == exponent; } - bool operator!=(const Monomial &other) const { + bool operator!=(const MonomialBase &other) const { return other.coefficient != coefficient || other.exponent != exponent; } /// Monomials are ordered by exponent. - bool operator<(const Monomial &other) const { + bool operator<(const MonomialBase &other) const { return (exponent.ult(other.exponent)); } - friend ::llvm::hash_code hash_value(const Monomial &arg); + virtual bool isMonic() const = 0; + virtual void + coefficientToString(llvm::SmallString<16> &coeffString) const = 0; -public: - APInt coefficient; + template + friend ::llvm::hash_code hash_value(const MonomialBase &arg); - // Always unsigned +protected: + CoefficientType coefficient; APInt exponent; }; -/// A single-variable polynomial with integer coefficients. -/// -/// Eg: x^1024 + x + 1 -/// -/// The symbols used as the polynomial's indeterminate don't matter, so long as -/// it is used consistently throughout the polynomial. -class Polynomial { +/// A class representing a monomial of a single-variable polynomial with integer +/// coefficients. +class IntMonomial : public MonomialBase { public: - Polynomial() = delete; + IntMonomial(int64_t coeff, uint64_t expo) + : MonomialBase(APInt(apintBitWidth, coeff), APInt(apintBitWidth, expo)) {} - explicit Polynomial(ArrayRef terms) : terms(terms){}; + IntMonomial() + : MonomialBase(APInt(apintBitWidth, 0), APInt(apintBitWidth, 0)) {} - // Returns a Polynomial from a list of monomials. - // Fails if two monomials have the same exponent. - static FailureOr fromMonomials(ArrayRef monomials); + ~IntMonomial() = default; - /// Returns a polynomial with coefficients given by `coeffs`. The value - /// coeffs[i] is converted to a monomial with exponent i. - static Polynomial fromCoefficients(ArrayRef coeffs); + bool isMonic() const override { return coefficient == 1; } + + void coefficientToString(llvm::SmallString<16> &coeffString) const override { + coefficient.toStringSigned(coeffString); + } +}; + +/// A class representing a monomial of a single-variable polynomial with integer +/// coefficients. +class FloatMonomial : public MonomialBase { +public: + FloatMonomial(double coeff, uint64_t expo) + : MonomialBase(APFloat(coeff), APInt(apintBitWidth, expo)) {} + + FloatMonomial() : MonomialBase(APFloat((double)0), APInt(apintBitWidth, 0)) {} + + ~FloatMonomial() = default; + + bool isMonic() const override { return coefficient == APFloat(1.0); } + + void coefficientToString(llvm::SmallString<16> &coeffString) const override { + coefficient.toString(coeffString); + } +}; + +template +class PolynomialBase { +public: + PolynomialBase() = delete; + + explicit PolynomialBase(ArrayRef terms) : terms(terms){}; explicit operator bool() const { return !terms.empty(); } - bool operator==(const Polynomial &other) const { + bool operator==(const PolynomialBase &other) const { return other.terms == terms; } - bool operator!=(const Polynomial &other) const { + bool operator!=(const PolynomialBase &other) const { return !(other.terms == terms); } - // Prints polynomial to 'os'. - void print(raw_ostream &os) const; void print(raw_ostream &os, ::llvm::StringRef separator, - ::llvm::StringRef exponentiation) const; + ::llvm::StringRef exponentiation) const { + bool first = true; + for (const Monomial &term : getTerms()) { + if (first) { + first = false; + } else { + os << separator; + } + std::string coeffToPrint; + if (term.isMonic() && term.getExponent().uge(1)) { + coeffToPrint = ""; + } else { + llvm::SmallString<16> coeffString; + term.coefficientToString(coeffString); + coeffToPrint = coeffString.str(); + } + + if (term.getExponent() == 0) { + os << coeffToPrint; + } else if (term.getExponent() == 1) { + os << coeffToPrint << "x"; + } else { + llvm::SmallString<16> expString; + term.getExponent().toStringSigned(expString); + os << coeffToPrint << "x" << exponentiation << expString; + } + } + } + + // Prints polynomial to 'os'. + void print(raw_ostream &os) const { print(os, " + ", "**"); } + void dump() const; // Prints polynomial so that it can be used as a valid identifier - std::string toIdentifier() const; + std::string toIdentifier() const { + std::string result; + llvm::raw_string_ostream os(result); + print(os, "_", ""); + return os.str(); + } - unsigned getDegree() const; + unsigned getDegree() const { + return terms.back().getExponent().getZExtValue(); + } ArrayRef getTerms() const { return terms; } - friend ::llvm::hash_code hash_value(const Polynomial &arg); + template + friend ::llvm::hash_code hash_value(const PolynomialBase &arg); private: // The monomial terms for this polynomial. SmallVector terms; }; -// Make Polynomial hashable. -inline ::llvm::hash_code hash_value(const Polynomial &arg) { +/// A single-variable polynomial with integer coefficients. +/// +/// Eg: x^1024 + x + 1 +class IntPolynomial : public PolynomialBase { +public: + explicit IntPolynomial(ArrayRef terms) : PolynomialBase(terms) {} + + // Returns a Polynomial from a list of monomials. + // Fails if two monomials have the same exponent. + static FailureOr + fromMonomials(ArrayRef monomials); + + /// Returns a polynomial with coefficients given by `coeffs`. The value + /// coeffs[i] is converted to a monomial with exponent i. + static IntPolynomial fromCoefficients(ArrayRef coeffs); +}; + +/// A single-variable polynomial with double coefficients. +/// +/// Eg: 1.0 x^1024 + 3.5 x + 1e-05 +class FloatPolynomial : public PolynomialBase { +public: + explicit FloatPolynomial(ArrayRef terms) + : PolynomialBase(terms) {} + + // Returns a Polynomial from a list of monomials. + // Fails if two monomials have the same exponent. + static FailureOr + fromMonomials(ArrayRef monomials); + + /// Returns a polynomial with coefficients given by `coeffs`. The value + /// coeffs[i] is converted to a monomial with exponent i. + static FloatPolynomial fromCoefficients(ArrayRef coeffs); +}; + +// Make Polynomials hashable. +template +inline ::llvm::hash_code hash_value(const PolynomialBase &arg) { return ::llvm::hash_combine_range(arg.terms.begin(), arg.terms.end()); } -inline ::llvm::hash_code hash_value(const Monomial &arg) { +template +inline ::llvm::hash_code hash_value(const MonomialBase &arg) { return llvm::hash_combine(::llvm::hash_value(arg.coefficient), ::llvm::hash_value(arg.exponent)); } -inline raw_ostream &operator<<(raw_ostream &os, const Polynomial &polynomial) { +template +inline raw_ostream &operator<<(raw_ostream &os, + const PolynomialBase &polynomial) { polynomial.print(os); return os; } diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td index ed1f4ce8b7e5..ae8484501a50 100644 --- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td +++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td @@ -39,14 +39,14 @@ def Polynomial_Dialect : Dialect { %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring> // A constant polynomial in a ring with i32 coefficients, modulo (x^1024 + 1) - #modulus = #polynomial.polynomial<1 + x**1024> + #modulus = #polynomial.int_polynomial<1 + x**1024> #ring = #polynomial.ring %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring> // A constant polynomial in a ring with i32 coefficients, with a polynomial // modulus of (x^1024 + 1) and a coefficient modulus of 17. - #modulus = #polynomial.polynomial<1 + x**1024> - #ring = #polynomial.ring + #modulus = #polynomial.int_polynomial<1 + x**1024> + #ring = #polynomial.ring %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring> ``` }]; @@ -60,12 +60,12 @@ class Polynomial_Attr traits = []> let mnemonic = attrMnemonic; } -def Polynomial_PolynomialAttr : Polynomial_Attr<"Polynomial", "polynomial"> { - let summary = "An attribute containing a single-variable polynomial."; +def Polynomial_IntPolynomialAttr : Polynomial_Attr<"IntPolynomial", "int_polynomial"> { + let summary = "An attribute containing a single-variable polynomial with integer coefficients."; let description = [{ - A polynomial attribute represents a single-variable polynomial, which - is used to define the modulus of a `RingAttr`, as well as to define constants - and perform constant folding for `polynomial` ops. + A polynomial attribute represents a single-variable polynomial with integer + coefficients, which is used to define the modulus of a `RingAttr`, as well + as to define constants and perform constant folding for `polynomial` ops. The polynomial must be expressed as a list of monomial terms, with addition or subtraction between them. The choice of variable name is arbitrary, but @@ -76,10 +76,32 @@ def Polynomial_PolynomialAttr : Polynomial_Attr<"Polynomial", "polynomial"> { Example: ```mlir - #poly = #polynomial.polynomial + #poly = #polynomial.int_polynomial ``` }]; - let parameters = (ins "::mlir::polynomial::Polynomial":$polynomial); + let parameters = (ins "::mlir::polynomial::IntPolynomial":$polynomial); + let hasCustomAssemblyFormat = 1; +} + +def Polynomial_FloatPolynomialAttr : Polynomial_Attr<"FloatPolynomial", "float_polynomial"> { + let summary = "An attribute containing a single-variable polynomial with double precision floating point coefficients."; + let description = [{ + A polynomial attribute represents a single-variable polynomial with double + precision floating point coefficients. + + The polynomial must be expressed as a list of monomial terms, with addition + or subtraction between them. The choice of variable name is arbitrary, but + must be consistent across all the monomials used to define a single + attribute. The order of monomial terms is arbitrary, each monomial degree + must occur at most once. + + Example: + + ```mlir + #poly = #polynomial.float_polynomial<0.5 x**7 + 1.5> + ``` + }]; + let parameters = (ins "FloatPolynomial":$polynomial); let hasCustomAssemblyFormat = 1; } @@ -104,9 +126,9 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> { `x**1024 - 1`. ```mlir - #poly_mod = #polynomial.polynomial<-1 + x**1024> + #poly_mod = #polynomial.int_polynomial<-1 + x**1024> #ring = #polynomial.ring %0 = ... : polynomial.polynomial<#ring> @@ -123,19 +145,24 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> { let parameters = (ins "Type": $coefficientType, OptionalParameter<"::mlir::IntegerAttr">: $coefficientModulus, - OptionalParameter<"::mlir::polynomial::PolynomialAttr">: $polynomialModulus, + OptionalParameter<"::mlir::polynomial::IntPolynomialAttr">: $polynomialModulus, OptionalParameter<"::mlir::IntegerAttr">: $primitiveRoot ); - + let assemblyFormat = "`<` struct(params) `>`"; let builders = [ - AttrBuilder< + AttrBuilderWithInferredContext< (ins "::mlir::Type":$coefficientTy, - "::mlir::IntegerAttr":$coefficientModulusAttr, - "::mlir::polynomial::PolynomialAttr":$polynomialModulusAttr), [{ - return $_get($_ctxt, coefficientTy, coefficientModulusAttr, polynomialModulusAttr, nullptr); - }]> + CArg<"::mlir::IntegerAttr", "nullptr"> :$coefficientModulusAttr, + CArg<"::mlir::polynomial::IntPolynomialAttr", "nullptr"> :$polynomialModulusAttr, + CArg<"::mlir::IntegerAttr", "nullptr"> :$primitiveRootAttr), [{ + return $_get( + coefficientTy.getContext(), + coefficientTy, + coefficientModulusAttr, + polynomialModulusAttr, + primitiveRootAttr); + }]>, ]; - let hasCustomAssemblyFormat = 1; } class Polynomial_Type @@ -149,7 +176,7 @@ def Polynomial_PolynomialType : Polynomial_Type<"Polynomial", "polynomial"> { A type for polynomials in a polynomial quotient ring. }]; let parameters = (ins Polynomial_RingAttr:$ring); - let assemblyFormat = "`<` $ring `>`"; + let assemblyFormat = "`<` struct(params) `>`"; } def PolynomialLike: TypeOrContainer; @@ -187,10 +214,10 @@ def Polynomial_AddOp : Polynomial_BinaryOp<"add", [Commutative]> { ```mlir // add two polynomials modulo x^1024 - 1 - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> - %1 = polynomial.constant #polynomial.polynomial : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> + %1 = polynomial.constant #polynomial.int_polynomial : !polynomial.polynomial<#ring> %2 = polynomial.add %0, %1 : !polynomial.polynomial<#ring> ``` }]; @@ -211,10 +238,10 @@ def Polynomial_SubOp : Polynomial_BinaryOp<"sub"> { ```mlir // subtract two polynomials modulo x^1024 - 1 - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> - %1 = polynomial.constant #polynomial.polynomial : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> + %1 = polynomial.constant #polynomial.int_polynomial : !polynomial.polynomial<#ring> %2 = polynomial.sub %0, %1 : !polynomial.polynomial<#ring> ``` }]; @@ -235,10 +262,10 @@ def Polynomial_MulOp : Polynomial_BinaryOp<"mul", [Commutative]> { ```mlir // multiply two polynomials modulo x^1024 - 1 - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> - %1 = polynomial.constant #polynomial.polynomial : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> + %1 = polynomial.constant #polynomial.int_polynomial : !polynomial.polynomial<#ring> %2 = polynomial.mul %0, %1 : !polynomial.polynomial<#ring> ``` }]; @@ -260,9 +287,9 @@ def Polynomial_MulScalarOp : Polynomial_Op<"mul_scalar", [ ```mlir // multiply two polynomials modulo x^1024 - 1 - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> %1 = arith.constant 3 : i32 %2 = polynomial.mul_scalar %0, %1 : !polynomial.polynomial<#ring>, i32 ``` @@ -291,9 +318,9 @@ def Polynomial_LeadingTermOp: Polynomial_Op<"leading_term"> { Example: ```mlir - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> %1, %2 = polynomial.leading_term %0 : !polynomial.polynomial<#ring> -> (index, i32) ``` }]; @@ -314,8 +341,8 @@ def Polynomial_MonomialOp: Polynomial_Op<"monomial"> { Example: ```mlir - #poly = #polynomial.polynomial - #ring = #polynomial.ring + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring %deg = arith.constant 1023 : index %five = arith.constant 5 : i32 %0 = polynomial.monomial %five, %deg : (i32, index) -> !polynomial.polynomial<#ring> @@ -354,8 +381,8 @@ def Polynomial_FromTensorOp : Polynomial_Op<"from_tensor", [Pure]> { Example: ```mlir - #poly = #polynomial.polynomial - #ring = #polynomial.ring + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring %two = arith.constant 2 : i32 %five = arith.constant 5 : i32 %coeffs = tensor.from_elements %two, %two, %five : tensor<3xi32> @@ -393,8 +420,8 @@ def Polynomial_ToTensorOp : Polynomial_Op<"to_tensor", [Pure]> { Example: ```mlir - #poly = #polynomial.polynomial - #ring = #polynomial.ring + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring %two = arith.constant 2 : i32 %five = arith.constant 5 : i32 %coeffs = tensor.from_elements %two, %two, %five : tensor<3xi32> @@ -405,24 +432,32 @@ def Polynomial_ToTensorOp : Polynomial_Op<"to_tensor", [Pure]> { let arguments = (ins Polynomial_PolynomialType:$input); let results = (outs RankedTensorOf<[AnyInteger]>:$output); let assemblyFormat = "$input attr-dict `:` type($input) `->` type($output)"; - let hasVerifier = 1; } -def Polynomial_ConstantOp : Polynomial_Op<"constant", [Pure]> { +def Polynomial_AnyPolynomialAttr : AnyAttrOf<[ + Polynomial_FloatPolynomialAttr, + Polynomial_IntPolynomialAttr +]>; + +// Not deriving from Polynomial_Op due to need for custom assembly format +def Polynomial_ConstantOp : Op { let summary = "Define a constant polynomial via an attribute."; let description = [{ Example: ```mlir - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> + + #float_ring = #polynomial.ring + %0 = polynomial.constant #polynomial.float_polynomial<0.5 + 1.3e06 x**2> : !polynomial.polynomial<#float_ring> ``` }]; - let arguments = (ins Polynomial_PolynomialAttr:$input); + let arguments = (ins Polynomial_AnyPolynomialAttr:$value); let results = (outs Polynomial_PolynomialType:$output); - let assemblyFormat = "$input attr-dict `:` type($output)"; + let assemblyFormat = "attr-dict `:` type($output)"; } def Polynomial_NTTOp : Polynomial_Op<"ntt", [Pure]> { diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp index 5916ffba78e2..42e678fad060 100644 --- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp +++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp @@ -9,87 +9,63 @@ #include "mlir/Dialect/Polynomial/IR/Polynomial.h" #include "mlir/Support/LogicalResult.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/raw_ostream.h" namespace mlir { namespace polynomial { -FailureOr Polynomial::fromMonomials(ArrayRef monomials) { +template +MonomialBase::~MonomialBase() {} + +template +FailureOr fromMonomialsImpl(ArrayRef monomials) { // A polynomial's terms are canonically stored in order of increasing degree. - auto monomialsCopy = llvm::SmallVector(monomials); + auto monomialsCopy = llvm::SmallVector(monomials); std::sort(monomialsCopy.begin(), monomialsCopy.end()); // Ensure non-unique exponents are not present. Since we sorted the list by // exponent, a linear scan of adjancent monomials suffices. if (std::adjacent_find(monomialsCopy.begin(), monomialsCopy.end(), - [](const Monomial &lhs, const Monomial &rhs) { - return lhs.exponent == rhs.exponent; + [](const MonomialT &lhs, const MonomialT &rhs) { + return lhs.getExponent() == rhs.getExponent(); }) != monomialsCopy.end()) { return failure(); } - return Polynomial(monomialsCopy); + return PolyT(monomialsCopy); +} + +FailureOr +IntPolynomial::fromMonomials(ArrayRef monomials) { + return fromMonomialsImpl(monomials); +} + +FailureOr +FloatPolynomial::fromMonomials(ArrayRef monomials) { + return fromMonomialsImpl(monomials); } -Polynomial Polynomial::fromCoefficients(ArrayRef coeffs) { - llvm::SmallVector monomials; +template +PolyT fromCoefficientsImpl(ArrayRef coeffs) { + llvm::SmallVector monomials; auto size = coeffs.size(); monomials.reserve(size); for (size_t i = 0; i < size; i++) { monomials.emplace_back(coeffs[i], i); } - auto result = Polynomial::fromMonomials(monomials); + auto result = PolyT::fromMonomials(monomials); // Construction guarantees unique exponents, so the failure mode of // fromMonomials can be bypassed. assert(succeeded(result)); return result.value(); } -void Polynomial::print(raw_ostream &os, ::llvm::StringRef separator, - ::llvm::StringRef exponentiation) const { - bool first = true; - for (const Monomial &term : terms) { - if (first) { - first = false; - } else { - os << separator; - } - std::string coeffToPrint; - if (term.coefficient == 1 && term.exponent.uge(1)) { - coeffToPrint = ""; - } else { - llvm::SmallString<16> coeffString; - term.coefficient.toStringSigned(coeffString); - coeffToPrint = coeffString.str(); - } - - if (term.exponent == 0) { - os << coeffToPrint; - } else if (term.exponent == 1) { - os << coeffToPrint << "x"; - } else { - llvm::SmallString<16> expString; - term.exponent.toStringSigned(expString); - os << coeffToPrint << "x" << exponentiation << expString; - } - } -} - -void Polynomial::print(raw_ostream &os) const { print(os, " + ", "**"); } - -std::string Polynomial::toIdentifier() const { - std::string result; - llvm::raw_string_ostream os(result); - print(os, "_", ""); - return os.str(); +IntPolynomial IntPolynomial::fromCoefficients(ArrayRef coeffs) { + return fromCoefficientsImpl(coeffs); } -unsigned Polynomial::getDegree() const { - return terms.back().exponent.getZExtValue(); +FloatPolynomial FloatPolynomial::fromCoefficients(ArrayRef coeffs) { + return fromCoefficientsImpl(coeffs); } } // namespace polynomial diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp index 236bb7896635..890ce5226c30 100644 --- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp +++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/Polynomial/IR/Polynomial.h" #include "mlir/Support/LLVM.h" #include "mlir/Support/LogicalResult.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" @@ -17,22 +18,31 @@ namespace mlir { namespace polynomial { -void PolynomialAttr::print(AsmPrinter &p) const { - p << '<'; - p << getPolynomial(); - p << '>'; +void IntPolynomialAttr::print(AsmPrinter &p) const { + p << '<' << getPolynomial() << '>'; } +void FloatPolynomialAttr::print(AsmPrinter &p) const { + p << '<' << getPolynomial() << '>'; +} + +/// A callable that parses the coefficient using the appropriate method for the +/// given monomial type, and stores the parsed coefficient value on the +/// monomial. +template +using ParseCoefficientFn = std::function; + /// Try to parse a monomial. If successful, populate the fields of the outparam /// `monomial` with the results, and the `variable` outparam with the parsed /// variable name. Sets shouldParseMore to true if the monomial is followed by /// a '+'. -ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, - llvm::StringRef &variable, bool &isConstantTerm, - bool &shouldParseMore) { - APInt parsedCoeff(apintBitWidth, 1); - auto parsedCoeffResult = parser.parseOptionalInteger(parsedCoeff); - monomial.coefficient = parsedCoeff; +/// +template +ParseResult +parseMonomial(AsmParser &parser, Monomial &monomial, llvm::StringRef &variable, + bool &isConstantTerm, bool &shouldParseMore, + ParseCoefficientFn parseAndStoreCoefficient) { + OptionalParseResult parsedCoeffResult = parseAndStoreCoefficient(monomial); isConstantTerm = false; shouldParseMore = false; @@ -44,7 +54,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, if (!parsedCoeffResult.has_value()) { return failure(); } - monomial.exponent = APInt(apintBitWidth, 0); + monomial.setExponent(APInt(apintBitWidth, 0)); isConstantTerm = true; shouldParseMore = true; return success(); @@ -58,7 +68,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, return failure(); } - monomial.exponent = APInt(apintBitWidth, 0); + monomial.setExponent(APInt(apintBitWidth, 0)); isConstantTerm = true; return success(); } @@ -80,9 +90,9 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, return failure(); } - monomial.exponent = parsedExponent; + monomial.setExponent(parsedExponent); } else { - monomial.exponent = APInt(apintBitWidth, 1); + monomial.setExponent(APInt(apintBitWidth, 1)); } if (succeeded(parser.parseOptionalPlus())) { @@ -91,22 +101,21 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, return success(); } -Attribute PolynomialAttr::parse(AsmParser &parser, Type type) { - if (failed(parser.parseLess())) - return {}; - - llvm::SmallVector monomials; - llvm::StringSet<> variables; - +template +LogicalResult +parsePolynomialAttr(AsmParser &parser, llvm::SmallVector &monomials, + llvm::StringSet<> &variables, + ParseCoefficientFn parseAndStoreCoefficient) { while (true) { Monomial parsedMonomial; llvm::StringRef parsedVariableRef; bool isConstantTerm; bool shouldParseMore; - if (failed(parseMonomial(parser, parsedMonomial, parsedVariableRef, - isConstantTerm, shouldParseMore))) { + if (failed(parseMonomial( + parser, parsedMonomial, parsedVariableRef, isConstantTerm, + shouldParseMore, parseAndStoreCoefficient))) { parser.emitError(parser.getCurrentLocation(), "expected a monomial"); - return {}; + return failure(); } if (!isConstantTerm) { @@ -124,7 +133,7 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) { parser.emitError( parser.getCurrentLocation(), "expected + and more monomials, or > to end polynomial attribute"); - return {}; + return failure(); } if (variables.size() > 1) { @@ -133,96 +142,67 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) { parser.getCurrentLocation(), "polynomials must have one indeterminate, but there were multiple: " + vars); + return failure(); } - auto result = Polynomial::fromMonomials(monomials); - if (failed(result)) { - parser.emitError(parser.getCurrentLocation()) - << "parsed polynomial must have unique exponents among monomials"; - return {}; - } - return PolynomialAttr::get(parser.getContext(), result.value()); -} - -void RingAttr::print(AsmPrinter &p) const { - p << "#polynomial.ring monomials; + llvm::StringSet<> variables; - if (failed(parser.parseEqual())) + if (failed(parsePolynomialAttr( + parser, monomials, variables, + [&](IntMonomial &monomial) -> OptionalParseResult { + APInt parsedCoeff(apintBitWidth, 1); + OptionalParseResult result = + parser.parseOptionalInteger(parsedCoeff); + monomial.setCoefficient(parsedCoeff); + return result; + }))) { return {}; + } - Type ty; - if (failed(parser.parseType(ty))) + auto result = IntPolynomial::fromMonomials(monomials); + if (failed(result)) { + parser.emitError(parser.getCurrentLocation()) + << "parsed polynomial must have unique exponents among monomials"; return {}; + } + return IntPolynomialAttr::get(parser.getContext(), result.value()); +} - if (failed(parser.parseComma())) +Attribute FloatPolynomialAttr::parse(AsmParser &parser, Type type) { + if (failed(parser.parseLess())) return {}; - IntegerAttr coefficientModulusAttr = nullptr; - if (succeeded(parser.parseKeyword("coefficientModulus"))) { - if (failed(parser.parseEqual())) - return {}; - - IntegerType iType = mlir::dyn_cast(ty); - if (!iType) { - parser.emitError(parser.getCurrentLocation(), - "coefficientType must specify an integer type"); - return {}; - } - APInt coefficientModulus(iType.getWidth(), 0); - auto result = parser.parseInteger(coefficientModulus); - if (failed(result)) { - parser.emitError(parser.getCurrentLocation(), - "invalid coefficient modulus"); - return {}; - } - coefficientModulusAttr = IntegerAttr::get(iType, coefficientModulus); - - if (failed(parser.parseComma())) - return {}; - } - - PolynomialAttr polyAttr = nullptr; - if (succeeded(parser.parseKeyword("polynomialModulus"))) { - if (failed(parser.parseEqual())) - return {}; + llvm::SmallVector monomials; + llvm::StringSet<> variables; - PolynomialAttr attr; - if (failed(parser.parseAttribute(attr))) - return {}; - polyAttr = attr; - } + ParseCoefficientFn parseAndStoreCoefficient = + [&](FloatMonomial &monomial) -> OptionalParseResult { + double coeffValue = 1.0; + ParseResult result = parser.parseFloat(coeffValue); + monomial.setCoefficient(APFloat(coeffValue)); + return OptionalParseResult(result); + }; - Polynomial poly = polyAttr.getPolynomial(); - APInt root(coefficientModulusAttr.getValue().getBitWidth(), 0); - IntegerAttr rootAttr = nullptr; - if (succeeded(parser.parseOptionalComma())) { - if (failed(parser.parseKeyword("primitiveRoot")) || - failed(parser.parseEqual())) - return {}; - - ParseResult result = parser.parseInteger(root); - if (failed(result)) { - parser.emitError(parser.getCurrentLocation(), "invalid primitiveRoot"); - return {}; - } - rootAttr = IntegerAttr::get(coefficientModulusAttr.getType(), root); + if (failed(parsePolynomialAttr( + parser, monomials, variables, parseAndStoreCoefficient))) { + return {}; } - if (failed(parser.parseGreater())) + auto result = FloatPolynomial::fromMonomials(monomials); + if (failed(result)) { + parser.emitError(parser.getCurrentLocation()) + << "parsed polynomial must have unique exponents among monomials"; return {}; - - return RingAttr::get(parser.getContext(), ty, coefficientModulusAttr, - polyAttr, rootAttr); + } + return FloatPolynomialAttr::get(parser.getContext(), result.value()); } } // namespace polynomial diff --git a/mlir/test/Dialect/Polynomial/attributes.mlir b/mlir/test/Dialect/Polynomial/attributes.mlir index 3973ae394433..4bdfd44fd4d1 100644 --- a/mlir/test/Dialect/Polynomial/attributes.mlir +++ b/mlir/test/Dialect/Polynomial/attributes.mlir @@ -1,6 +1,6 @@ // RUN: mlir-opt %s --split-input-file --verify-diagnostics -#my_poly = #polynomial.polynomial +#my_poly = #polynomial.int_polynomial // expected-error@below {{polynomials must have one indeterminate, but there were multiple: x, y}} #ring1 = #polynomial.ring @@ -9,37 +9,31 @@ // expected-error@below {{expected integer value}} // expected-error@below {{expected a monomial}} // expected-error@below {{found invalid integer exponent}} -#my_poly = #polynomial.polynomial<5 + x**f> +#my_poly = #polynomial.int_polynomial<5 + x**f> #ring1 = #polynomial.ring // ----- -#my_poly = #polynomial.polynomial<5 + x**2 + 3x**2> +#my_poly = #polynomial.int_polynomial<5 + x**2 + 3x**2> // expected-error@below {{parsed polynomial must have unique exponents among monomials}} #ring1 = #polynomial.ring // ----- // expected-error@below {{expected + and more monomials, or > to end polynomial attribute}} -#my_poly = #polynomial.polynomial<5 + x**2 7> +#my_poly = #polynomial.int_polynomial<5 + x**2 7> #ring1 = #polynomial.ring // ----- // expected-error@below {{expected a monomial}} -#my_poly = #polynomial.polynomial<5 + x**2 +> +#my_poly = #polynomial.int_polynomial<5 + x**2 +> #ring1 = #polynomial.ring // ----- -#my_poly = #polynomial.polynomial<5 + x**2> -// expected-error@below {{coefficientType must specify an integer type}} -#ring1 = #polynomial.ring - -// ----- - -#my_poly = #polynomial.polynomial<5 + x**2> -// expected-error@below {{expected integer value}} -// expected-error@below {{invalid coefficient modulus}} +#my_poly = #polynomial.int_polynomial<5 + x**2> +// expected-error@below {{failed to parse Polynomial_RingAttr parameter 'coefficientModulus' which is to be a `::mlir::IntegerAttr`}} +// expected-error@below {{expected attribute value}} #ring1 = #polynomial.ring diff --git a/mlir/test/Dialect/Polynomial/ops.mlir b/mlir/test/Dialect/Polynomial/ops.mlir index a29cfc2e9cc5..ff709960c50e 100644 --- a/mlir/test/Dialect/Polynomial/ops.mlir +++ b/mlir/test/Dialect/Polynomial/ops.mlir @@ -2,85 +2,87 @@ // This simply tests for syntax. -#my_poly = #polynomial.polynomial<1 + x**1024> -#my_poly_2 = #polynomial.polynomial<2> -#my_poly_3 = #polynomial.polynomial<3x> -#my_poly_4 = #polynomial.polynomial +#my_poly = #polynomial.int_polynomial<1 + x**1024> +#my_poly_2 = #polynomial.int_polynomial<2> +#my_poly_3 = #polynomial.int_polynomial<3x> +#my_poly_4 = #polynomial.int_polynomial #ring1 = #polynomial.ring -#one_plus_x_squared = #polynomial.polynomial<1 + x**2> +#ring2 = #polynomial.ring +#one_plus_x_squared = #polynomial.int_polynomial<1 + x**2> -#ideal = #polynomial.polynomial<-1 + x**1024> +#ideal = #polynomial.int_polynomial<-1 + x**1024> #ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +!poly_ty = !polynomial.polynomial -#ntt_poly = #polynomial.polynomial<-1 + x**8> +#ntt_poly = #polynomial.int_polynomial<-1 + x**8> #ntt_ring = #polynomial.ring -!ntt_poly_ty = !polynomial.polynomial<#ntt_ring> +!ntt_poly_ty = !polynomial.polynomial module { - func.func @test_multiply() -> !polynomial.polynomial<#ring1> { + func.func @test_multiply() -> !polynomial.polynomial { %c0 = arith.constant 0 : index %two = arith.constant 2 : i16 %five = arith.constant 5 : i16 %coeffs1 = tensor.from_elements %two, %two, %five : tensor<3xi16> %coeffs2 = tensor.from_elements %five, %five, %two : tensor<3xi16> - %poly1 = polynomial.from_tensor %coeffs1 : tensor<3xi16> -> !polynomial.polynomial<#ring1> - %poly2 = polynomial.from_tensor %coeffs2 : tensor<3xi16> -> !polynomial.polynomial<#ring1> + %poly1 = polynomial.from_tensor %coeffs1 : tensor<3xi16> -> !polynomial.polynomial + %poly2 = polynomial.from_tensor %coeffs2 : tensor<3xi16> -> !polynomial.polynomial - %3 = polynomial.mul %poly1, %poly2 : !polynomial.polynomial<#ring1> + %3 = polynomial.mul %poly1, %poly2 : !polynomial.polynomial - return %3 : !polynomial.polynomial<#ring1> + return %3 : !polynomial.polynomial } - func.func @test_elementwise(%p0 : !polynomial.polynomial<#ring1>, %p1: !polynomial.polynomial<#ring1>) { - %tp0 = tensor.from_elements %p0, %p1 : tensor<2x!polynomial.polynomial<#ring1>> - %tp1 = tensor.from_elements %p1, %p0 : tensor<2x!polynomial.polynomial<#ring1>> + func.func @test_elementwise(%p0 : !polynomial.polynomial, %p1: !polynomial.polynomial) { + %tp0 = tensor.from_elements %p0, %p1 : tensor<2x!polynomial.polynomial> + %tp1 = tensor.from_elements %p1, %p0 : tensor<2x!polynomial.polynomial> %c = arith.constant 2 : i32 - %mul_const_sclr = polynomial.mul_scalar %tp0, %c : tensor<2x!polynomial.polynomial<#ring1>>, i32 + %mul_const_sclr = polynomial.mul_scalar %tp0, %c : tensor<2x!polynomial.polynomial>, i32 - %add = polynomial.add %tp0, %tp1 : tensor<2x!polynomial.polynomial<#ring1>> - %sub = polynomial.sub %tp0, %tp1 : tensor<2x!polynomial.polynomial<#ring1>> - %mul = polynomial.mul %tp0, %tp1 : tensor<2x!polynomial.polynomial<#ring1>> + %add = polynomial.add %tp0, %tp1 : tensor<2x!polynomial.polynomial> + %sub = polynomial.sub %tp0, %tp1 : tensor<2x!polynomial.polynomial> + %mul = polynomial.mul %tp0, %tp1 : tensor<2x!polynomial.polynomial> return } - func.func @test_to_from_tensor(%p0 : !polynomial.polynomial<#ring1>) { + func.func @test_to_from_tensor(%p0 : !polynomial.polynomial) { %c0 = arith.constant 0 : index %two = arith.constant 2 : i16 %coeffs1 = tensor.from_elements %two, %two : tensor<2xi16> // CHECK: from_tensor - %poly = polynomial.from_tensor %coeffs1 : tensor<2xi16> -> !polynomial.polynomial<#ring1> + %poly = polynomial.from_tensor %coeffs1 : tensor<2xi16> -> !polynomial.polynomial // CHECK: to_tensor - %tensor = polynomial.to_tensor %poly : !polynomial.polynomial<#ring1> -> tensor<1024xi16> + %tensor = polynomial.to_tensor %poly : !polynomial.polynomial -> tensor<1024xi16> return } - func.func @test_degree(%p0 : !polynomial.polynomial<#ring1>) { - %0, %1 = polynomial.leading_term %p0 : !polynomial.polynomial<#ring1> -> (index, i32) + func.func @test_degree(%p0 : !polynomial.polynomial) { + %0, %1 = polynomial.leading_term %p0 : !polynomial.polynomial -> (index, i32) return } func.func @test_monomial() { %deg = arith.constant 1023 : index %five = arith.constant 5 : i16 - %0 = polynomial.monomial %five, %deg : (i16, index) -> !polynomial.polynomial<#ring1> + %0 = polynomial.monomial %five, %deg : (i16, index) -> !polynomial.polynomial return } func.func @test_monic_monomial_mul() { %five = arith.constant 5 : index - %0 = polynomial.constant #one_plus_x_squared : !polynomial.polynomial<#ring1> - %1 = polynomial.monic_monomial_mul %0, %five : (!polynomial.polynomial<#ring1>, index) -> !polynomial.polynomial<#ring1> + %0 = polynomial.constant {value=#one_plus_x_squared} : !polynomial.polynomial + %1 = polynomial.monic_monomial_mul %0, %five : (!polynomial.polynomial, index) -> !polynomial.polynomial return } func.func @test_constant() { - %0 = polynomial.constant #one_plus_x_squared : !polynomial.polynomial<#ring1> - %1 = polynomial.constant <1 + x**2> : !polynomial.polynomial<#ring1> + %0 = polynomial.constant {value=#one_plus_x_squared} : !polynomial.polynomial + %1 = polynomial.constant {value=#polynomial.int_polynomial<1 + x**2>} : !polynomial.polynomial + %2 = polynomial.constant {value=#polynomial.float_polynomial<1.5 + 0.5 x**2>} : !polynomial.polynomial return } diff --git a/mlir/test/Dialect/Polynomial/ops_errors.mlir b/mlir/test/Dialect/Polynomial/ops_errors.mlir index 2c20e7bcbf1d..af8e4aa5da86 100644 --- a/mlir/test/Dialect/Polynomial/ops_errors.mlir +++ b/mlir/test/Dialect/Polynomial/ops_errors.mlir @@ -1,8 +1,8 @@ // RUN: mlir-opt --split-input-file --verify-diagnostics %s -#my_poly = #polynomial.polynomial<1 + x**1024> -#ring = #polynomial.ring -!ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<1 + x**1024> +#ring = #polynomial.ring +!ty = !polynomial.polynomial func.func @test_from_tensor_too_large_coeffs() { %two = arith.constant 2 : i32 @@ -15,13 +15,13 @@ func.func @test_from_tensor_too_large_coeffs() { // ----- -#my_poly = #polynomial.polynomial<1 + x**4> -#ring = #polynomial.ring -!ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<1 + x**4> +#ring = #polynomial.ring +!ty = !polynomial.polynomial func.func @test_from_tensor_wrong_tensor_type() { %two = arith.constant 2 : i32 %coeffs1 = tensor.from_elements %two, %two, %two, %two, %two : tensor<5xi32> - // expected-error@below {{input type 'tensor<5xi32>' does not match output type '!polynomial.polynomial<#polynomial.ring>>'}} + // expected-error@below {{input type 'tensor<5xi32>' does not match output type '!polynomial.polynomial>>'}} // expected-note@below {{at most the degree of the polynomialModulus of the output type's ring attribute}} %poly = polynomial.from_tensor %coeffs1 : tensor<5xi32> -> !ty return @@ -29,11 +29,11 @@ func.func @test_from_tensor_wrong_tensor_type() { // ----- -#my_poly = #polynomial.polynomial<1 + x**4> -#ring = #polynomial.ring -!ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<1 + x**4> +#ring = #polynomial.ring +!ty = !polynomial.polynomial func.func @test_to_tensor_wrong_output_tensor_type(%arg0 : !ty) { - // expected-error@below {{input type '!polynomial.polynomial<#polynomial.ring>>' does not match output type 'tensor<5xi32>'}} + // expected-error@below {{input type '!polynomial.polynomial>>' does not match output type 'tensor<5xi32>'}} // expected-note@below {{at most the degree of the polynomialModulus of the input type's ring attribute}} %tensor = polynomial.to_tensor %arg0 : !ty -> tensor<5xi32> return @@ -41,9 +41,9 @@ func.func @test_to_tensor_wrong_output_tensor_type(%arg0 : !ty) { // ----- -#my_poly = #polynomial.polynomial<1 + x**1024> -#ring = #polynomial.ring -!ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<1 + x**1024> +#ring = #polynomial.ring +!ty = !polynomial.polynomial func.func @test_mul_scalar_wrong_type(%arg0: !ty) -> !ty { %scalar = arith.constant 2 : i32 // should be i16 @@ -54,9 +54,9 @@ func.func @test_mul_scalar_wrong_type(%arg0: !ty) -> !ty { // ----- -#my_poly = #polynomial.polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_ntt // CHECK-NOT: polynomial.ntt @@ -68,9 +68,9 @@ func.func @test_invalid_ntt(%0 : !poly_ty) { // ----- -#my_poly = #polynomial.polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_ntt // CHECK-NOT: polynomial.ntt @@ -82,10 +82,10 @@ func.func @test_invalid_ntt(%0 : !poly_ty) { // ----- -#my_poly = #polynomial.polynomial<-1 + x**1024> -#ring = #polynomial.ring -#ring1 = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<-1 + x**1024> +#ring = #polynomial.ring +#ring1 = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_intt // CHECK-NOT: polynomial.intt @@ -97,9 +97,9 @@ func.func @test_invalid_intt(%0 : tensor<1024xi32, #ring1>) { // ----- -#my_poly = #polynomial.polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_intt // CHECK-NOT: polynomial.intt @@ -112,9 +112,9 @@ func.func @test_invalid_intt(%0 : tensor<1025xi32, #ring>) { // ----- -#my_poly = #polynomial.polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_ntt // CHECK-NOT: polynomial.ntt @@ -126,10 +126,10 @@ func.func @test_invalid_ntt(%0 : !poly_ty) { // ----- -#my_poly = #polynomial.polynomial<-1 + x**8> +#my_poly = #polynomial.int_polynomial<-1 + x**8> // A valid root is 31 -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_intt // CHECK-NOT: polynomial.intt diff --git a/mlir/test/Dialect/Polynomial/types.mlir b/mlir/test/Dialect/Polynomial/types.mlir index 00296a36e890..dcc5663ceb84 100644 --- a/mlir/test/Dialect/Polynomial/types.mlir +++ b/mlir/test/Dialect/Polynomial/types.mlir @@ -2,13 +2,13 @@ // CHECK-LABEL: func @test_types // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: #polynomial.ring< -// CHECK-SAME: coefficientType=i32, -// CHECK-SAME: coefficientModulus=2837465 : i32, -// CHECK-SAME: polynomialModulus=#polynomial.polynomial<1 + x**1024>>> -#my_poly = #polynomial.polynomial<1 + x**1024> -#ring1 = #polynomial.ring -!ty = !polynomial.polynomial<#ring1> +// CHECK-SAME: ring = < +// CHECK-SAME: coefficientType = i32, +// CHECK-SAME: coefficientModulus = 2837465 : i32, +// CHECK-SAME: polynomialModulus = <1 + x**1024>>> +#my_poly = #polynomial.int_polynomial<1 + x**1024> +#ring1 = #polynomial.ring +!ty = !polynomial.polynomial func.func @test_types(%0: !ty) -> !ty { return %0 : !ty } @@ -16,13 +16,13 @@ func.func @test_types(%0: !ty) -> !ty { // CHECK-LABEL: func @test_non_x_variable_64_bit // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: #polynomial.ring< -// CHECK-SAME: coefficientType=i64, -// CHECK-SAME: coefficientModulus=2837465 : i64, -// CHECK-SAME: polynomialModulus=#polynomial.polynomial<2 + 4x + x**3>>> -#my_poly_2 = #polynomial.polynomial -#ring2 = #polynomial.ring -!ty2 = !polynomial.polynomial<#ring2> +// CHECK-SAME: ring = < +// CHECK-SAME: coefficientType = i64, +// CHECK-SAME: coefficientModulus = 2837465 : i64, +// CHECK-SAME: polynomialModulus = <2 + 4x + x**3>>> +#my_poly_2 = #polynomial.int_polynomial +#ring2 = #polynomial.ring +!ty2 = !polynomial.polynomial func.func @test_non_x_variable_64_bit(%0: !ty2) -> !ty2 { return %0 : !ty2 } @@ -30,27 +30,36 @@ func.func @test_non_x_variable_64_bit(%0: !ty2) -> !ty2 { // CHECK-LABEL: func @test_linear_poly // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: #polynomial.ring< -// CHECK-SAME: coefficientType=i32, -// CHECK-SAME: coefficientModulus=12 : i32, -// CHECK-SAME: polynomialModulus=#polynomial.polynomial<4x>> -#my_poly_3 = #polynomial.polynomial<4x> -#ring3 = #polynomial.ring -!ty3 = !polynomial.polynomial<#ring3> +// CHECK-SAME: ring = < +// CHECK-SAME: coefficientType = i32, +// CHECK-SAME: coefficientModulus = 12 : i32, +// CHECK-SAME: polynomialModulus = <4x>> +#my_poly_3 = #polynomial.int_polynomial<4x> +#ring3 = #polynomial.ring +!ty3 = !polynomial.polynomial func.func @test_linear_poly(%0: !ty3) -> !ty3 { return %0 : !ty3 } // CHECK-LABEL: func @test_negative_leading_1 // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: #polynomial.ring< -// CHECK-SAME: coefficientType=i32, -// CHECK-SAME: coefficientModulus=2837465 : i32, -// CHECK-SAME: polynomialModulus=#polynomial.polynomial<-1 + x**1024>>> -#my_poly_4 = #polynomial.polynomial<-1 + x**1024> -#ring4 = #polynomial.ring -!ty4 = !polynomial.polynomial<#ring4> +// CHECK-SAME: ring = < +// CHECK-SAME: coefficientType = i32, +// CHECK-SAME: coefficientModulus = 2837465 : i32, +// CHECK-SAME: polynomialModulus = <-1 + x**1024>>> +#my_poly_4 = #polynomial.int_polynomial<-1 + x**1024> +#ring4 = #polynomial.ring +!ty4 = !polynomial.polynomial func.func @test_negative_leading_1(%0: !ty4) -> !ty4 { return %0 : !ty4 } +// CHECK-LABEL: func @test_float_coefficients +// CHECK-SAME: !polynomial.polynomial> +#my_poly_5 = #polynomial.float_polynomial<0.5 + 1.6e03 x**1024> +#ring5 = #polynomial.ring +!ty5 = !polynomial.polynomial +func.func @test_float_coefficients(%0: !ty5) -> !ty5 { + return %0 : !ty5 +} + -- GitLab From 6140b5bae475069f958f90a81fb9d69c969daab6 Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Mon, 13 May 2024 09:48:46 -0700 Subject: [PATCH 098/578] [RISCV] Use RISCVISD::SHL_ADD in transformAddShlImm (#89832) Doing so avoids negative interactions with other combines which don't know the shl_add is a single instruction. From the commit log, we've had several combine loops already. This was originally posted as part of #88791, where a bug was pointed out. That bug was fixed by #89789 which hits the same issue from another angle. To confirm the fix, I included the reduced test case here. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 18 +++++++------- llvm/test/CodeGen/RISCV/addimm-mulimm.ll | 26 +++++++++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index d0f62b1d5414..5a84ad4d436b 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -12987,10 +12987,9 @@ static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG, SDLoc DL(N); SDValue NS = (C0 < C1) ? N0->getOperand(0) : N1->getOperand(0); SDValue NL = (C0 > C1) ? N0->getOperand(0) : N1->getOperand(0); - SDValue NA0 = - DAG.getNode(ISD::SHL, DL, VT, NL, DAG.getConstant(Diff, DL, VT)); - SDValue NA1 = DAG.getNode(ISD::ADD, DL, VT, NA0, NS); - return DAG.getNode(ISD::SHL, DL, VT, NA1, DAG.getConstant(Bits, DL, VT)); + SDValue SHADD = DAG.getNode(RISCVISD::SHL_ADD, DL, VT, NL, + DAG.getConstant(Diff, DL, VT), NS); + return DAG.getNode(ISD::SHL, DL, VT, SHADD, DAG.getConstant(Bits, DL, VT)); } // Combine a constant select operand into its use: @@ -13226,14 +13225,17 @@ static SDValue combineAddOfBooleanXor(SDNode *N, SelectionDAG &DAG) { N0.getOperand(0)); } -static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, +static SDValue performADDCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget) { + SelectionDAG &DAG = DCI.DAG; if (SDValue V = combineAddOfBooleanXor(N, DAG)) return V; if (SDValue V = transformAddImmMulImm(N, DAG, Subtarget)) return V; - if (SDValue V = transformAddShlImm(N, DAG, Subtarget)) - return V; + if (!DCI.isBeforeLegalize() && !DCI.isCalledByLegalizer()) + if (SDValue V = transformAddShlImm(N, DAG, Subtarget)) + return V; if (SDValue V = combineBinOpToReduce(N, DAG, Subtarget)) return V; if (SDValue V = combineBinOpOfExtractToReduceTree(N, DAG, Subtarget)) @@ -16230,7 +16232,7 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, return V; if (SDValue V = combineToVWMACC(N, DAG, Subtarget)) return V; - return performADDCombine(N, DAG, Subtarget); + return performADDCombine(N, DCI, Subtarget); } case ISD::SUB: { if (SDValue V = combineBinOp_VLToVWBinOp_VL(N, DCI, Subtarget)) diff --git a/llvm/test/CodeGen/RISCV/addimm-mulimm.ll b/llvm/test/CodeGen/RISCV/addimm-mulimm.ll index e2f7be2e6d7f..a18526718461 100644 --- a/llvm/test/CodeGen/RISCV/addimm-mulimm.ll +++ b/llvm/test/CodeGen/RISCV/addimm-mulimm.ll @@ -944,3 +944,29 @@ define i1 @pr53831(i32 %x) { %tmp5 = icmp eq i32 %tmp4, %tmp2 ret i1 %tmp5 } + +define i64 @sh2add_uw(i64 signext %0, i32 signext %1) { +; RV32IMB-LABEL: sh2add_uw: +; RV32IMB: # %bb.0: # %entry +; RV32IMB-NEXT: srli a3, a2, 27 +; RV32IMB-NEXT: slli a2, a2, 5 +; RV32IMB-NEXT: srli a4, a0, 29 +; RV32IMB-NEXT: sh3add a1, a1, a4 +; RV32IMB-NEXT: sh3add a0, a0, a2 +; RV32IMB-NEXT: sltu a2, a0, a2 +; RV32IMB-NEXT: add a1, a3, a1 +; RV32IMB-NEXT: add a1, a1, a2 +; RV32IMB-NEXT: ret +; +; RV64IMB-LABEL: sh2add_uw: +; RV64IMB: # %bb.0: # %entry +; RV64IMB-NEXT: sh2add.uw a0, a1, a0 +; RV64IMB-NEXT: slli a0, a0, 3 +; RV64IMB-NEXT: ret +entry: + %2 = zext i32 %1 to i64 + %3 = shl i64 %2, 5 + %4 = shl i64 %0, 3 + %5 = add i64 %3, %4 + ret i64 %5 +} -- GitLab From 37ffbbb19576a884c5bb93b9ac0ae97f89523b6b Mon Sep 17 00:00:00 2001 From: Peiming Liu Date: Mon, 13 May 2024 09:53:15 -0700 Subject: [PATCH 099/578] [mlir][tensor][sparse] don't drop encoding when infer result type (#91817) A general question is: is it possible to support hooks here to infer the encoding? E.g., when the extracted tensor slice is rank-reduced, the encoding need to be updated accordingly as well. --- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 3 ++- .../Dialect/SparseTensor/canonicalize.mlir | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 mlir/test/Dialect/SparseTensor/canonicalize.mlir diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index 1f94397e823f..e41d59a0e0b9 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -2020,7 +2020,8 @@ RankedTensorType ExtractSliceOp::inferResultType( assert(static_cast(staticSizes.size()) == sourceTensorType.getRank() && "unexpected staticSizes not equal to rank of source"); - return RankedTensorType::get(staticSizes, sourceTensorType.getElementType()); + return RankedTensorType::get(staticSizes, sourceTensorType.getElementType(), + sourceTensorType.getEncoding()); } RankedTensorType ExtractSliceOp::inferResultType( diff --git a/mlir/test/Dialect/SparseTensor/canonicalize.mlir b/mlir/test/Dialect/SparseTensor/canonicalize.mlir new file mode 100644 index 000000000000..b1d3d7916c14 --- /dev/null +++ b/mlir/test/Dialect/SparseTensor/canonicalize.mlir @@ -0,0 +1,23 @@ +// RUN: mlir-opt %s -split-input-file -canonicalize="test-convergence" | FileCheck %s + +#BCOO = #sparse_tensor.encoding<{ + map = (d0, d1, d2) -> (d0 : dense, d1 : loose_compressed(nonunique), d2 : singleton) +}> + +// CHECK-DAG: #[[$BCOO:.*]] = #sparse_tensor.encoding<{ map = (d0, d1, d2) -> (d0 : dense, d1 : loose_compressed(nonunique), d2 : singleton) }> +// CHECK-LABEL: func @sparse_slice_canonicalize +// CHECK-SAME: %[[ARG0:.+]]: tensor +// CHECK: %[[SLICE:.+]] = tensor.extract_slice %[[ARG0]][0, %{{[a-zA-Z0-9_]+}}, 1] +// CHECK-SAME: [4, 1, %{{[a-zA-Z0-9_]+}}] [1, 1, 1] +// CHECK-SAME: : tensor to tensor<4x1x?xf32, #[[$BCOO]]> +// CHECK: %[[RESULT:.+]] = tensor.cast %[[SLICE]] +// CHECK: return %[[RESULT]] +func.func @sparse_slice_canonicalize(%arg0 : tensor, %arg1 : index, + %arg2 : index) -> tensor +{ + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c4 = arith.constant 4 : index + %0 = tensor.extract_slice %arg0[%c0, %arg1, %c1] [%c4, %c1, %arg2] [%c1, %c1, %c1] : tensor to tensor + return %0 : tensor +} -- GitLab From 2a114d171d4c1e6c742d039a289bf509b86668ac Mon Sep 17 00:00:00 2001 From: Jover Date: Tue, 14 May 2024 01:12:29 +0800 Subject: [PATCH 100/578] [clang-tidy] Ignore `if consteval` in else-after-return (#91588) --- .../readability/ElseAfterReturnCheck.cpp | 4 ++-- clang-tools-extra/docs/ReleaseNotes.rst | 4 ++++ .../else-after-return-if-consteval.cpp | 17 +++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return-if-consteval.cpp diff --git a/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp b/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp index 1e85caf68835..2b185e7594ad 100644 --- a/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp @@ -113,7 +113,7 @@ static bool containsDeclInScope(const Stmt *Node) { } static void removeElseAndBrackets(DiagnosticBuilder &Diag, ASTContext &Context, - const Stmt *Else, SourceLocation ElseLoc) { + const Stmt *Else, SourceLocation ElseLoc) { auto Remap = [&](SourceLocation Loc) { return Context.getSourceManager().getExpansionLoc(Loc); }; @@ -172,7 +172,7 @@ void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) { breakStmt().bind(InterruptingStr), cxxThrowExpr().bind(InterruptingStr))); Finder->addMatcher( compoundStmt( - forEach(ifStmt(unless(isConstexpr()), + forEach(ifStmt(unless(isConstexpr()), unless(isConsteval()), hasThen(stmt( anyOf(InterruptsControlFlow, compoundStmt(has(InterruptsControlFlow))))), diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index fc976ce3a33d..8183d394cf42 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -339,6 +339,10 @@ Changes in existing checks ` check by excluding include directives that form the filename using macro. +- Improved :doc:`readability-else-after-return + ` check to ignore + `if consteval` statements, for which the `else` branch must not be removed. + - Improved :doc:`readability-identifier-naming ` check in `GetConfigPerFile` mode by resolving symbolic links to header files. Fixed handling of Hungarian diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return-if-consteval.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return-if-consteval.cpp new file mode 100644 index 000000000000..8810d215ee97 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return-if-consteval.cpp @@ -0,0 +1,17 @@ +// RUN: %check_clang_tidy -std=c++23 %s readability-else-after-return %t + +// Consteval if is an exception to the rule, we cannot remove the else. +void f() { + if (sizeof(int) > 4) { + return; + } else { + return; + } + // CHECK-MESSAGES: [[@LINE-3]]:5: warning: do not use 'else' after 'return' + + if consteval { + return; + } else { + return; + } +} -- GitLab From ad727b1a6757c4c23b4121192b121fd67219820e Mon Sep 17 00:00:00 2001 From: Jeremy Kun Date: Mon, 13 May 2024 10:19:59 -0700 Subject: [PATCH 101/578] Revert "Support polynomial attributes with floating point coefficients (#91137)" (#92001) This reverts commit 91a14dbf825b79ff143d1b16124763a4a80facab. Not sure how to fix the build error this introduced, so reverting until I can figure it out https://lab.llvm.org/buildbot/#/builders/264/builds/10468 Co-authored-by: Jeremy Kun --- .../mlir/Dialect/Polynomial/IR/Polynomial.h | 193 ++++-------------- .../mlir/Dialect/Polynomial/IR/Polynomial.td | 139 +++++-------- mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp | 78 ++++--- .../Polynomial/IR/PolynomialAttributes.cpp | 172 +++++++++------- mlir/test/Dialect/Polynomial/attributes.mlir | 22 +- mlir/test/Dialect/Polynomial/ops.mlir | 64 +++--- mlir/test/Dialect/Polynomial/ops_errors.mlir | 66 +++--- mlir/test/Dialect/Polynomial/types.mlir | 65 +++--- 8 files changed, 348 insertions(+), 451 deletions(-) diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h index 2b3f0e105c6c..3325a6fa3f9f 100644 --- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h +++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h @@ -11,13 +11,10 @@ #include "mlir/Support/LLVM.h" #include "mlir/Support/LogicalResult.h" -#include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallVector.h" namespace mlir { @@ -30,202 +27,98 @@ namespace polynomial { /// would want to specify 128-bit polynomials statically in the source code. constexpr unsigned apintBitWidth = 64; -template -class MonomialBase { +/// A class representing a monomial of a single-variable polynomial with integer +/// coefficients. +class Monomial { public: - MonomialBase(const CoefficientType &coeff, const APInt &expo) + Monomial(int64_t coeff, uint64_t expo) + : coefficient(apintBitWidth, coeff), exponent(apintBitWidth, expo) {} + + Monomial(const APInt &coeff, const APInt &expo) : coefficient(coeff), exponent(expo) {} - virtual ~MonomialBase() = 0; - const CoefficientType &getCoefficient() const { return coefficient; } - CoefficientType &getMutableCoefficient() { return coefficient; } - const APInt &getExponent() const { return exponent; } - void setCoefficient(const CoefficientType &coeff) { coefficient = coeff; } - void setExponent(const APInt &exp) { exponent = exp; } + Monomial() : coefficient(apintBitWidth, 0), exponent(apintBitWidth, 0) {} - bool operator==(const MonomialBase &other) const { + bool operator==(const Monomial &other) const { return other.coefficient == coefficient && other.exponent == exponent; } - bool operator!=(const MonomialBase &other) const { + bool operator!=(const Monomial &other) const { return other.coefficient != coefficient || other.exponent != exponent; } /// Monomials are ordered by exponent. - bool operator<(const MonomialBase &other) const { + bool operator<(const Monomial &other) const { return (exponent.ult(other.exponent)); } - virtual bool isMonic() const = 0; - virtual void - coefficientToString(llvm::SmallString<16> &coeffString) const = 0; - - template - friend ::llvm::hash_code hash_value(const MonomialBase &arg); + friend ::llvm::hash_code hash_value(const Monomial &arg); -protected: - CoefficientType coefficient; - APInt exponent; -}; - -/// A class representing a monomial of a single-variable polynomial with integer -/// coefficients. -class IntMonomial : public MonomialBase { public: - IntMonomial(int64_t coeff, uint64_t expo) - : MonomialBase(APInt(apintBitWidth, coeff), APInt(apintBitWidth, expo)) {} - - IntMonomial() - : MonomialBase(APInt(apintBitWidth, 0), APInt(apintBitWidth, 0)) {} - - ~IntMonomial() = default; - - bool isMonic() const override { return coefficient == 1; } + APInt coefficient; - void coefficientToString(llvm::SmallString<16> &coeffString) const override { - coefficient.toStringSigned(coeffString); - } + // Always unsigned + APInt exponent; }; -/// A class representing a monomial of a single-variable polynomial with integer -/// coefficients. -class FloatMonomial : public MonomialBase { +/// A single-variable polynomial with integer coefficients. +/// +/// Eg: x^1024 + x + 1 +/// +/// The symbols used as the polynomial's indeterminate don't matter, so long as +/// it is used consistently throughout the polynomial. +class Polynomial { public: - FloatMonomial(double coeff, uint64_t expo) - : MonomialBase(APFloat(coeff), APInt(apintBitWidth, expo)) {} - - FloatMonomial() : MonomialBase(APFloat((double)0), APInt(apintBitWidth, 0)) {} + Polynomial() = delete; - ~FloatMonomial() = default; + explicit Polynomial(ArrayRef terms) : terms(terms){}; - bool isMonic() const override { return coefficient == APFloat(1.0); } - - void coefficientToString(llvm::SmallString<16> &coeffString) const override { - coefficient.toString(coeffString); - } -}; - -template -class PolynomialBase { -public: - PolynomialBase() = delete; + // Returns a Polynomial from a list of monomials. + // Fails if two monomials have the same exponent. + static FailureOr fromMonomials(ArrayRef monomials); - explicit PolynomialBase(ArrayRef terms) : terms(terms){}; + /// Returns a polynomial with coefficients given by `coeffs`. The value + /// coeffs[i] is converted to a monomial with exponent i. + static Polynomial fromCoefficients(ArrayRef coeffs); explicit operator bool() const { return !terms.empty(); } - bool operator==(const PolynomialBase &other) const { + bool operator==(const Polynomial &other) const { return other.terms == terms; } - bool operator!=(const PolynomialBase &other) const { + bool operator!=(const Polynomial &other) const { return !(other.terms == terms); } - void print(raw_ostream &os, ::llvm::StringRef separator, - ::llvm::StringRef exponentiation) const { - bool first = true; - for (const Monomial &term : getTerms()) { - if (first) { - first = false; - } else { - os << separator; - } - std::string coeffToPrint; - if (term.isMonic() && term.getExponent().uge(1)) { - coeffToPrint = ""; - } else { - llvm::SmallString<16> coeffString; - term.coefficientToString(coeffString); - coeffToPrint = coeffString.str(); - } - - if (term.getExponent() == 0) { - os << coeffToPrint; - } else if (term.getExponent() == 1) { - os << coeffToPrint << "x"; - } else { - llvm::SmallString<16> expString; - term.getExponent().toStringSigned(expString); - os << coeffToPrint << "x" << exponentiation << expString; - } - } - } - // Prints polynomial to 'os'. - void print(raw_ostream &os) const { print(os, " + ", "**"); } - + void print(raw_ostream &os) const; + void print(raw_ostream &os, ::llvm::StringRef separator, + ::llvm::StringRef exponentiation) const; void dump() const; // Prints polynomial so that it can be used as a valid identifier - std::string toIdentifier() const { - std::string result; - llvm::raw_string_ostream os(result); - print(os, "_", ""); - return os.str(); - } + std::string toIdentifier() const; - unsigned getDegree() const { - return terms.back().getExponent().getZExtValue(); - } + unsigned getDegree() const; ArrayRef getTerms() const { return terms; } - template - friend ::llvm::hash_code hash_value(const PolynomialBase &arg); + friend ::llvm::hash_code hash_value(const Polynomial &arg); private: // The monomial terms for this polynomial. SmallVector terms; }; -/// A single-variable polynomial with integer coefficients. -/// -/// Eg: x^1024 + x + 1 -class IntPolynomial : public PolynomialBase { -public: - explicit IntPolynomial(ArrayRef terms) : PolynomialBase(terms) {} - - // Returns a Polynomial from a list of monomials. - // Fails if two monomials have the same exponent. - static FailureOr - fromMonomials(ArrayRef monomials); - - /// Returns a polynomial with coefficients given by `coeffs`. The value - /// coeffs[i] is converted to a monomial with exponent i. - static IntPolynomial fromCoefficients(ArrayRef coeffs); -}; - -/// A single-variable polynomial with double coefficients. -/// -/// Eg: 1.0 x^1024 + 3.5 x + 1e-05 -class FloatPolynomial : public PolynomialBase { -public: - explicit FloatPolynomial(ArrayRef terms) - : PolynomialBase(terms) {} - - // Returns a Polynomial from a list of monomials. - // Fails if two monomials have the same exponent. - static FailureOr - fromMonomials(ArrayRef monomials); - - /// Returns a polynomial with coefficients given by `coeffs`. The value - /// coeffs[i] is converted to a monomial with exponent i. - static FloatPolynomial fromCoefficients(ArrayRef coeffs); -}; - -// Make Polynomials hashable. -template -inline ::llvm::hash_code hash_value(const PolynomialBase &arg) { +// Make Polynomial hashable. +inline ::llvm::hash_code hash_value(const Polynomial &arg) { return ::llvm::hash_combine_range(arg.terms.begin(), arg.terms.end()); } -template -inline ::llvm::hash_code hash_value(const MonomialBase &arg) { +inline ::llvm::hash_code hash_value(const Monomial &arg) { return llvm::hash_combine(::llvm::hash_value(arg.coefficient), ::llvm::hash_value(arg.exponent)); } -template -inline raw_ostream &operator<<(raw_ostream &os, - const PolynomialBase &polynomial) { +inline raw_ostream &operator<<(raw_ostream &os, const Polynomial &polynomial) { polynomial.print(os); return os; } diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td index ae8484501a50..ed1f4ce8b7e5 100644 --- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td +++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td @@ -39,14 +39,14 @@ def Polynomial_Dialect : Dialect { %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring> // A constant polynomial in a ring with i32 coefficients, modulo (x^1024 + 1) - #modulus = #polynomial.int_polynomial<1 + x**1024> + #modulus = #polynomial.polynomial<1 + x**1024> #ring = #polynomial.ring %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring> // A constant polynomial in a ring with i32 coefficients, with a polynomial // modulus of (x^1024 + 1) and a coefficient modulus of 17. - #modulus = #polynomial.int_polynomial<1 + x**1024> - #ring = #polynomial.ring + #modulus = #polynomial.polynomial<1 + x**1024> + #ring = #polynomial.ring %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring> ``` }]; @@ -60,12 +60,12 @@ class Polynomial_Attr traits = []> let mnemonic = attrMnemonic; } -def Polynomial_IntPolynomialAttr : Polynomial_Attr<"IntPolynomial", "int_polynomial"> { - let summary = "An attribute containing a single-variable polynomial with integer coefficients."; +def Polynomial_PolynomialAttr : Polynomial_Attr<"Polynomial", "polynomial"> { + let summary = "An attribute containing a single-variable polynomial."; let description = [{ - A polynomial attribute represents a single-variable polynomial with integer - coefficients, which is used to define the modulus of a `RingAttr`, as well - as to define constants and perform constant folding for `polynomial` ops. + A polynomial attribute represents a single-variable polynomial, which + is used to define the modulus of a `RingAttr`, as well as to define constants + and perform constant folding for `polynomial` ops. The polynomial must be expressed as a list of monomial terms, with addition or subtraction between them. The choice of variable name is arbitrary, but @@ -76,32 +76,10 @@ def Polynomial_IntPolynomialAttr : Polynomial_Attr<"IntPolynomial", "int_polynom Example: ```mlir - #poly = #polynomial.int_polynomial + #poly = #polynomial.polynomial ``` }]; - let parameters = (ins "::mlir::polynomial::IntPolynomial":$polynomial); - let hasCustomAssemblyFormat = 1; -} - -def Polynomial_FloatPolynomialAttr : Polynomial_Attr<"FloatPolynomial", "float_polynomial"> { - let summary = "An attribute containing a single-variable polynomial with double precision floating point coefficients."; - let description = [{ - A polynomial attribute represents a single-variable polynomial with double - precision floating point coefficients. - - The polynomial must be expressed as a list of monomial terms, with addition - or subtraction between them. The choice of variable name is arbitrary, but - must be consistent across all the monomials used to define a single - attribute. The order of monomial terms is arbitrary, each monomial degree - must occur at most once. - - Example: - - ```mlir - #poly = #polynomial.float_polynomial<0.5 x**7 + 1.5> - ``` - }]; - let parameters = (ins "FloatPolynomial":$polynomial); + let parameters = (ins "::mlir::polynomial::Polynomial":$polynomial); let hasCustomAssemblyFormat = 1; } @@ -126,9 +104,9 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> { `x**1024 - 1`. ```mlir - #poly_mod = #polynomial.int_polynomial<-1 + x**1024> + #poly_mod = #polynomial.polynomial<-1 + x**1024> #ring = #polynomial.ring %0 = ... : polynomial.polynomial<#ring> @@ -145,24 +123,19 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> { let parameters = (ins "Type": $coefficientType, OptionalParameter<"::mlir::IntegerAttr">: $coefficientModulus, - OptionalParameter<"::mlir::polynomial::IntPolynomialAttr">: $polynomialModulus, + OptionalParameter<"::mlir::polynomial::PolynomialAttr">: $polynomialModulus, OptionalParameter<"::mlir::IntegerAttr">: $primitiveRoot ); - let assemblyFormat = "`<` struct(params) `>`"; + let builders = [ - AttrBuilderWithInferredContext< + AttrBuilder< (ins "::mlir::Type":$coefficientTy, - CArg<"::mlir::IntegerAttr", "nullptr"> :$coefficientModulusAttr, - CArg<"::mlir::polynomial::IntPolynomialAttr", "nullptr"> :$polynomialModulusAttr, - CArg<"::mlir::IntegerAttr", "nullptr"> :$primitiveRootAttr), [{ - return $_get( - coefficientTy.getContext(), - coefficientTy, - coefficientModulusAttr, - polynomialModulusAttr, - primitiveRootAttr); - }]>, + "::mlir::IntegerAttr":$coefficientModulusAttr, + "::mlir::polynomial::PolynomialAttr":$polynomialModulusAttr), [{ + return $_get($_ctxt, coefficientTy, coefficientModulusAttr, polynomialModulusAttr, nullptr); + }]> ]; + let hasCustomAssemblyFormat = 1; } class Polynomial_Type @@ -176,7 +149,7 @@ def Polynomial_PolynomialType : Polynomial_Type<"Polynomial", "polynomial"> { A type for polynomials in a polynomial quotient ring. }]; let parameters = (ins Polynomial_RingAttr:$ring); - let assemblyFormat = "`<` struct(params) `>`"; + let assemblyFormat = "`<` $ring `>`"; } def PolynomialLike: TypeOrContainer; @@ -214,10 +187,10 @@ def Polynomial_AddOp : Polynomial_BinaryOp<"add", [Commutative]> { ```mlir // add two polynomials modulo x^1024 - 1 - #poly = #polynomial.int_polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> - %1 = polynomial.constant #polynomial.int_polynomial : !polynomial.polynomial<#ring> + #poly = #polynomial.polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> + %1 = polynomial.constant #polynomial.polynomial : !polynomial.polynomial<#ring> %2 = polynomial.add %0, %1 : !polynomial.polynomial<#ring> ``` }]; @@ -238,10 +211,10 @@ def Polynomial_SubOp : Polynomial_BinaryOp<"sub"> { ```mlir // subtract two polynomials modulo x^1024 - 1 - #poly = #polynomial.int_polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> - %1 = polynomial.constant #polynomial.int_polynomial : !polynomial.polynomial<#ring> + #poly = #polynomial.polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> + %1 = polynomial.constant #polynomial.polynomial : !polynomial.polynomial<#ring> %2 = polynomial.sub %0, %1 : !polynomial.polynomial<#ring> ``` }]; @@ -262,10 +235,10 @@ def Polynomial_MulOp : Polynomial_BinaryOp<"mul", [Commutative]> { ```mlir // multiply two polynomials modulo x^1024 - 1 - #poly = #polynomial.int_polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> - %1 = polynomial.constant #polynomial.int_polynomial : !polynomial.polynomial<#ring> + #poly = #polynomial.polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> + %1 = polynomial.constant #polynomial.polynomial : !polynomial.polynomial<#ring> %2 = polynomial.mul %0, %1 : !polynomial.polynomial<#ring> ``` }]; @@ -287,9 +260,9 @@ def Polynomial_MulScalarOp : Polynomial_Op<"mul_scalar", [ ```mlir // multiply two polynomials modulo x^1024 - 1 - #poly = #polynomial.int_polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> + #poly = #polynomial.polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> %1 = arith.constant 3 : i32 %2 = polynomial.mul_scalar %0, %1 : !polynomial.polynomial<#ring>, i32 ``` @@ -318,9 +291,9 @@ def Polynomial_LeadingTermOp: Polynomial_Op<"leading_term"> { Example: ```mlir - #poly = #polynomial.int_polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> + #poly = #polynomial.polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> %1, %2 = polynomial.leading_term %0 : !polynomial.polynomial<#ring> -> (index, i32) ``` }]; @@ -341,8 +314,8 @@ def Polynomial_MonomialOp: Polynomial_Op<"monomial"> { Example: ```mlir - #poly = #polynomial.int_polynomial - #ring = #polynomial.ring + #poly = #polynomial.polynomial + #ring = #polynomial.ring %deg = arith.constant 1023 : index %five = arith.constant 5 : i32 %0 = polynomial.monomial %five, %deg : (i32, index) -> !polynomial.polynomial<#ring> @@ -381,8 +354,8 @@ def Polynomial_FromTensorOp : Polynomial_Op<"from_tensor", [Pure]> { Example: ```mlir - #poly = #polynomial.int_polynomial - #ring = #polynomial.ring + #poly = #polynomial.polynomial + #ring = #polynomial.ring %two = arith.constant 2 : i32 %five = arith.constant 5 : i32 %coeffs = tensor.from_elements %two, %two, %five : tensor<3xi32> @@ -420,8 +393,8 @@ def Polynomial_ToTensorOp : Polynomial_Op<"to_tensor", [Pure]> { Example: ```mlir - #poly = #polynomial.int_polynomial - #ring = #polynomial.ring + #poly = #polynomial.polynomial + #ring = #polynomial.ring %two = arith.constant 2 : i32 %five = arith.constant 5 : i32 %coeffs = tensor.from_elements %two, %two, %five : tensor<3xi32> @@ -432,32 +405,24 @@ def Polynomial_ToTensorOp : Polynomial_Op<"to_tensor", [Pure]> { let arguments = (ins Polynomial_PolynomialType:$input); let results = (outs RankedTensorOf<[AnyInteger]>:$output); let assemblyFormat = "$input attr-dict `:` type($input) `->` type($output)"; + let hasVerifier = 1; } -def Polynomial_AnyPolynomialAttr : AnyAttrOf<[ - Polynomial_FloatPolynomialAttr, - Polynomial_IntPolynomialAttr -]>; - -// Not deriving from Polynomial_Op due to need for custom assembly format -def Polynomial_ConstantOp : Op { +def Polynomial_ConstantOp : Polynomial_Op<"constant", [Pure]> { let summary = "Define a constant polynomial via an attribute."; let description = [{ Example: ```mlir - #poly = #polynomial.int_polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> - - #float_ring = #polynomial.ring - %0 = polynomial.constant #polynomial.float_polynomial<0.5 + 1.3e06 x**2> : !polynomial.polynomial<#float_ring> + #poly = #polynomial.polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> ``` }]; - let arguments = (ins Polynomial_AnyPolynomialAttr:$value); + let arguments = (ins Polynomial_PolynomialAttr:$input); let results = (outs Polynomial_PolynomialType:$output); - let assemblyFormat = "attr-dict `:` type($output)"; + let assemblyFormat = "$input attr-dict `:` type($output)"; } def Polynomial_NTTOp : Polynomial_Op<"ntt", [Pure]> { diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp index 42e678fad060..5916ffba78e2 100644 --- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp +++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp @@ -9,63 +9,87 @@ #include "mlir/Dialect/Polynomial/IR/Polynomial.h" #include "mlir/Support/LogicalResult.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" namespace mlir { namespace polynomial { -template -MonomialBase::~MonomialBase() {} - -template -FailureOr fromMonomialsImpl(ArrayRef monomials) { +FailureOr Polynomial::fromMonomials(ArrayRef monomials) { // A polynomial's terms are canonically stored in order of increasing degree. - auto monomialsCopy = llvm::SmallVector(monomials); + auto monomialsCopy = llvm::SmallVector(monomials); std::sort(monomialsCopy.begin(), monomialsCopy.end()); // Ensure non-unique exponents are not present. Since we sorted the list by // exponent, a linear scan of adjancent monomials suffices. if (std::adjacent_find(monomialsCopy.begin(), monomialsCopy.end(), - [](const MonomialT &lhs, const MonomialT &rhs) { - return lhs.getExponent() == rhs.getExponent(); + [](const Monomial &lhs, const Monomial &rhs) { + return lhs.exponent == rhs.exponent; }) != monomialsCopy.end()) { return failure(); } - return PolyT(monomialsCopy); -} - -FailureOr -IntPolynomial::fromMonomials(ArrayRef monomials) { - return fromMonomialsImpl(monomials); -} - -FailureOr -FloatPolynomial::fromMonomials(ArrayRef monomials) { - return fromMonomialsImpl(monomials); + return Polynomial(monomialsCopy); } -template -PolyT fromCoefficientsImpl(ArrayRef coeffs) { - llvm::SmallVector monomials; +Polynomial Polynomial::fromCoefficients(ArrayRef coeffs) { + llvm::SmallVector monomials; auto size = coeffs.size(); monomials.reserve(size); for (size_t i = 0; i < size; i++) { monomials.emplace_back(coeffs[i], i); } - auto result = PolyT::fromMonomials(monomials); + auto result = Polynomial::fromMonomials(monomials); // Construction guarantees unique exponents, so the failure mode of // fromMonomials can be bypassed. assert(succeeded(result)); return result.value(); } -IntPolynomial IntPolynomial::fromCoefficients(ArrayRef coeffs) { - return fromCoefficientsImpl(coeffs); +void Polynomial::print(raw_ostream &os, ::llvm::StringRef separator, + ::llvm::StringRef exponentiation) const { + bool first = true; + for (const Monomial &term : terms) { + if (first) { + first = false; + } else { + os << separator; + } + std::string coeffToPrint; + if (term.coefficient == 1 && term.exponent.uge(1)) { + coeffToPrint = ""; + } else { + llvm::SmallString<16> coeffString; + term.coefficient.toStringSigned(coeffString); + coeffToPrint = coeffString.str(); + } + + if (term.exponent == 0) { + os << coeffToPrint; + } else if (term.exponent == 1) { + os << coeffToPrint << "x"; + } else { + llvm::SmallString<16> expString; + term.exponent.toStringSigned(expString); + os << coeffToPrint << "x" << exponentiation << expString; + } + } +} + +void Polynomial::print(raw_ostream &os) const { print(os, " + ", "**"); } + +std::string Polynomial::toIdentifier() const { + std::string result; + llvm::raw_string_ostream os(result); + print(os, "_", ""); + return os.str(); } -FloatPolynomial FloatPolynomial::fromCoefficients(ArrayRef coeffs) { - return fromCoefficientsImpl(coeffs); +unsigned Polynomial::getDegree() const { + return terms.back().exponent.getZExtValue(); } } // namespace polynomial diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp index 890ce5226c30..236bb7896635 100644 --- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp +++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp @@ -10,7 +10,6 @@ #include "mlir/Dialect/Polynomial/IR/Polynomial.h" #include "mlir/Support/LLVM.h" #include "mlir/Support/LogicalResult.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" @@ -18,31 +17,22 @@ namespace mlir { namespace polynomial { -void IntPolynomialAttr::print(AsmPrinter &p) const { - p << '<' << getPolynomial() << '>'; +void PolynomialAttr::print(AsmPrinter &p) const { + p << '<'; + p << getPolynomial(); + p << '>'; } -void FloatPolynomialAttr::print(AsmPrinter &p) const { - p << '<' << getPolynomial() << '>'; -} - -/// A callable that parses the coefficient using the appropriate method for the -/// given monomial type, and stores the parsed coefficient value on the -/// monomial. -template -using ParseCoefficientFn = std::function; - /// Try to parse a monomial. If successful, populate the fields of the outparam /// `monomial` with the results, and the `variable` outparam with the parsed /// variable name. Sets shouldParseMore to true if the monomial is followed by /// a '+'. -/// -template -ParseResult -parseMonomial(AsmParser &parser, Monomial &monomial, llvm::StringRef &variable, - bool &isConstantTerm, bool &shouldParseMore, - ParseCoefficientFn parseAndStoreCoefficient) { - OptionalParseResult parsedCoeffResult = parseAndStoreCoefficient(monomial); +ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, + llvm::StringRef &variable, bool &isConstantTerm, + bool &shouldParseMore) { + APInt parsedCoeff(apintBitWidth, 1); + auto parsedCoeffResult = parser.parseOptionalInteger(parsedCoeff); + monomial.coefficient = parsedCoeff; isConstantTerm = false; shouldParseMore = false; @@ -54,7 +44,7 @@ parseMonomial(AsmParser &parser, Monomial &monomial, llvm::StringRef &variable, if (!parsedCoeffResult.has_value()) { return failure(); } - monomial.setExponent(APInt(apintBitWidth, 0)); + monomial.exponent = APInt(apintBitWidth, 0); isConstantTerm = true; shouldParseMore = true; return success(); @@ -68,7 +58,7 @@ parseMonomial(AsmParser &parser, Monomial &monomial, llvm::StringRef &variable, return failure(); } - monomial.setExponent(APInt(apintBitWidth, 0)); + monomial.exponent = APInt(apintBitWidth, 0); isConstantTerm = true; return success(); } @@ -90,9 +80,9 @@ parseMonomial(AsmParser &parser, Monomial &monomial, llvm::StringRef &variable, return failure(); } - monomial.setExponent(parsedExponent); + monomial.exponent = parsedExponent; } else { - monomial.setExponent(APInt(apintBitWidth, 1)); + monomial.exponent = APInt(apintBitWidth, 1); } if (succeeded(parser.parseOptionalPlus())) { @@ -101,21 +91,22 @@ parseMonomial(AsmParser &parser, Monomial &monomial, llvm::StringRef &variable, return success(); } -template -LogicalResult -parsePolynomialAttr(AsmParser &parser, llvm::SmallVector &monomials, - llvm::StringSet<> &variables, - ParseCoefficientFn parseAndStoreCoefficient) { +Attribute PolynomialAttr::parse(AsmParser &parser, Type type) { + if (failed(parser.parseLess())) + return {}; + + llvm::SmallVector monomials; + llvm::StringSet<> variables; + while (true) { Monomial parsedMonomial; llvm::StringRef parsedVariableRef; bool isConstantTerm; bool shouldParseMore; - if (failed(parseMonomial( - parser, parsedMonomial, parsedVariableRef, isConstantTerm, - shouldParseMore, parseAndStoreCoefficient))) { + if (failed(parseMonomial(parser, parsedMonomial, parsedVariableRef, + isConstantTerm, shouldParseMore))) { parser.emitError(parser.getCurrentLocation(), "expected a monomial"); - return failure(); + return {}; } if (!isConstantTerm) { @@ -133,7 +124,7 @@ parsePolynomialAttr(AsmParser &parser, llvm::SmallVector &monomials, parser.emitError( parser.getCurrentLocation(), "expected + and more monomials, or > to end polynomial attribute"); - return failure(); + return {}; } if (variables.size() > 1) { @@ -142,67 +133,96 @@ parsePolynomialAttr(AsmParser &parser, llvm::SmallVector &monomials, parser.getCurrentLocation(), "polynomials must have one indeterminate, but there were multiple: " + vars); - return failure(); } - return success(); + auto result = Polynomial::fromMonomials(monomials); + if (failed(result)) { + parser.emitError(parser.getCurrentLocation()) + << "parsed polynomial must have unique exponents among monomials"; + return {}; + } + return PolynomialAttr::get(parser.getContext(), result.value()); } -Attribute IntPolynomialAttr::parse(AsmParser &parser, Type type) { +void RingAttr::print(AsmPrinter &p) const { + p << "#polynomial.ring( - parser, monomials, variables, - [&](IntMonomial &monomial) -> OptionalParseResult { - APInt parsedCoeff(apintBitWidth, 1); - OptionalParseResult result = - parser.parseOptionalInteger(parsedCoeff); - monomial.setCoefficient(parsedCoeff); - return result; - }))) { + if (failed(parser.parseEqual())) return {}; - } - auto result = IntPolynomial::fromMonomials(monomials); - if (failed(result)) { - parser.emitError(parser.getCurrentLocation()) - << "parsed polynomial must have unique exponents among monomials"; + Type ty; + if (failed(parser.parseType(ty))) return {}; - } - return IntPolynomialAttr::get(parser.getContext(), result.value()); -} -Attribute FloatPolynomialAttr::parse(AsmParser &parser, Type type) { - if (failed(parser.parseLess())) + if (failed(parser.parseComma())) return {}; - llvm::SmallVector monomials; - llvm::StringSet<> variables; + IntegerAttr coefficientModulusAttr = nullptr; + if (succeeded(parser.parseKeyword("coefficientModulus"))) { + if (failed(parser.parseEqual())) + return {}; - ParseCoefficientFn parseAndStoreCoefficient = - [&](FloatMonomial &monomial) -> OptionalParseResult { - double coeffValue = 1.0; - ParseResult result = parser.parseFloat(coeffValue); - monomial.setCoefficient(APFloat(coeffValue)); - return OptionalParseResult(result); - }; + IntegerType iType = mlir::dyn_cast(ty); + if (!iType) { + parser.emitError(parser.getCurrentLocation(), + "coefficientType must specify an integer type"); + return {}; + } + APInt coefficientModulus(iType.getWidth(), 0); + auto result = parser.parseInteger(coefficientModulus); + if (failed(result)) { + parser.emitError(parser.getCurrentLocation(), + "invalid coefficient modulus"); + return {}; + } + coefficientModulusAttr = IntegerAttr::get(iType, coefficientModulus); - if (failed(parsePolynomialAttr( - parser, monomials, variables, parseAndStoreCoefficient))) { - return {}; + if (failed(parser.parseComma())) + return {}; } - auto result = FloatPolynomial::fromMonomials(monomials); - if (failed(result)) { - parser.emitError(parser.getCurrentLocation()) - << "parsed polynomial must have unique exponents among monomials"; - return {}; + PolynomialAttr polyAttr = nullptr; + if (succeeded(parser.parseKeyword("polynomialModulus"))) { + if (failed(parser.parseEqual())) + return {}; + + PolynomialAttr attr; + if (failed(parser.parseAttribute(attr))) + return {}; + polyAttr = attr; } - return FloatPolynomialAttr::get(parser.getContext(), result.value()); + + Polynomial poly = polyAttr.getPolynomial(); + APInt root(coefficientModulusAttr.getValue().getBitWidth(), 0); + IntegerAttr rootAttr = nullptr; + if (succeeded(parser.parseOptionalComma())) { + if (failed(parser.parseKeyword("primitiveRoot")) || + failed(parser.parseEqual())) + return {}; + + ParseResult result = parser.parseInteger(root); + if (failed(result)) { + parser.emitError(parser.getCurrentLocation(), "invalid primitiveRoot"); + return {}; + } + rootAttr = IntegerAttr::get(coefficientModulusAttr.getType(), root); + } + + if (failed(parser.parseGreater())) + return {}; + + return RingAttr::get(parser.getContext(), ty, coefficientModulusAttr, + polyAttr, rootAttr); } } // namespace polynomial diff --git a/mlir/test/Dialect/Polynomial/attributes.mlir b/mlir/test/Dialect/Polynomial/attributes.mlir index 4bdfd44fd4d1..3973ae394433 100644 --- a/mlir/test/Dialect/Polynomial/attributes.mlir +++ b/mlir/test/Dialect/Polynomial/attributes.mlir @@ -1,6 +1,6 @@ // RUN: mlir-opt %s --split-input-file --verify-diagnostics -#my_poly = #polynomial.int_polynomial +#my_poly = #polynomial.polynomial // expected-error@below {{polynomials must have one indeterminate, but there were multiple: x, y}} #ring1 = #polynomial.ring @@ -9,31 +9,37 @@ // expected-error@below {{expected integer value}} // expected-error@below {{expected a monomial}} // expected-error@below {{found invalid integer exponent}} -#my_poly = #polynomial.int_polynomial<5 + x**f> +#my_poly = #polynomial.polynomial<5 + x**f> #ring1 = #polynomial.ring // ----- -#my_poly = #polynomial.int_polynomial<5 + x**2 + 3x**2> +#my_poly = #polynomial.polynomial<5 + x**2 + 3x**2> // expected-error@below {{parsed polynomial must have unique exponents among monomials}} #ring1 = #polynomial.ring // ----- // expected-error@below {{expected + and more monomials, or > to end polynomial attribute}} -#my_poly = #polynomial.int_polynomial<5 + x**2 7> +#my_poly = #polynomial.polynomial<5 + x**2 7> #ring1 = #polynomial.ring // ----- // expected-error@below {{expected a monomial}} -#my_poly = #polynomial.int_polynomial<5 + x**2 +> +#my_poly = #polynomial.polynomial<5 + x**2 +> #ring1 = #polynomial.ring // ----- -#my_poly = #polynomial.int_polynomial<5 + x**2> -// expected-error@below {{failed to parse Polynomial_RingAttr parameter 'coefficientModulus' which is to be a `::mlir::IntegerAttr`}} -// expected-error@below {{expected attribute value}} +#my_poly = #polynomial.polynomial<5 + x**2> +// expected-error@below {{coefficientType must specify an integer type}} +#ring1 = #polynomial.ring + +// ----- + +#my_poly = #polynomial.polynomial<5 + x**2> +// expected-error@below {{expected integer value}} +// expected-error@below {{invalid coefficient modulus}} #ring1 = #polynomial.ring diff --git a/mlir/test/Dialect/Polynomial/ops.mlir b/mlir/test/Dialect/Polynomial/ops.mlir index ff709960c50e..a29cfc2e9cc5 100644 --- a/mlir/test/Dialect/Polynomial/ops.mlir +++ b/mlir/test/Dialect/Polynomial/ops.mlir @@ -2,87 +2,85 @@ // This simply tests for syntax. -#my_poly = #polynomial.int_polynomial<1 + x**1024> -#my_poly_2 = #polynomial.int_polynomial<2> -#my_poly_3 = #polynomial.int_polynomial<3x> -#my_poly_4 = #polynomial.int_polynomial +#my_poly = #polynomial.polynomial<1 + x**1024> +#my_poly_2 = #polynomial.polynomial<2> +#my_poly_3 = #polynomial.polynomial<3x> +#my_poly_4 = #polynomial.polynomial #ring1 = #polynomial.ring -#ring2 = #polynomial.ring -#one_plus_x_squared = #polynomial.int_polynomial<1 + x**2> +#one_plus_x_squared = #polynomial.polynomial<1 + x**2> -#ideal = #polynomial.int_polynomial<-1 + x**1024> +#ideal = #polynomial.polynomial<-1 + x**1024> #ring = #polynomial.ring -!poly_ty = !polynomial.polynomial +!poly_ty = !polynomial.polynomial<#ring> -#ntt_poly = #polynomial.int_polynomial<-1 + x**8> +#ntt_poly = #polynomial.polynomial<-1 + x**8> #ntt_ring = #polynomial.ring -!ntt_poly_ty = !polynomial.polynomial +!ntt_poly_ty = !polynomial.polynomial<#ntt_ring> module { - func.func @test_multiply() -> !polynomial.polynomial { + func.func @test_multiply() -> !polynomial.polynomial<#ring1> { %c0 = arith.constant 0 : index %two = arith.constant 2 : i16 %five = arith.constant 5 : i16 %coeffs1 = tensor.from_elements %two, %two, %five : tensor<3xi16> %coeffs2 = tensor.from_elements %five, %five, %two : tensor<3xi16> - %poly1 = polynomial.from_tensor %coeffs1 : tensor<3xi16> -> !polynomial.polynomial - %poly2 = polynomial.from_tensor %coeffs2 : tensor<3xi16> -> !polynomial.polynomial + %poly1 = polynomial.from_tensor %coeffs1 : tensor<3xi16> -> !polynomial.polynomial<#ring1> + %poly2 = polynomial.from_tensor %coeffs2 : tensor<3xi16> -> !polynomial.polynomial<#ring1> - %3 = polynomial.mul %poly1, %poly2 : !polynomial.polynomial + %3 = polynomial.mul %poly1, %poly2 : !polynomial.polynomial<#ring1> - return %3 : !polynomial.polynomial + return %3 : !polynomial.polynomial<#ring1> } - func.func @test_elementwise(%p0 : !polynomial.polynomial, %p1: !polynomial.polynomial) { - %tp0 = tensor.from_elements %p0, %p1 : tensor<2x!polynomial.polynomial> - %tp1 = tensor.from_elements %p1, %p0 : tensor<2x!polynomial.polynomial> + func.func @test_elementwise(%p0 : !polynomial.polynomial<#ring1>, %p1: !polynomial.polynomial<#ring1>) { + %tp0 = tensor.from_elements %p0, %p1 : tensor<2x!polynomial.polynomial<#ring1>> + %tp1 = tensor.from_elements %p1, %p0 : tensor<2x!polynomial.polynomial<#ring1>> %c = arith.constant 2 : i32 - %mul_const_sclr = polynomial.mul_scalar %tp0, %c : tensor<2x!polynomial.polynomial>, i32 + %mul_const_sclr = polynomial.mul_scalar %tp0, %c : tensor<2x!polynomial.polynomial<#ring1>>, i32 - %add = polynomial.add %tp0, %tp1 : tensor<2x!polynomial.polynomial> - %sub = polynomial.sub %tp0, %tp1 : tensor<2x!polynomial.polynomial> - %mul = polynomial.mul %tp0, %tp1 : tensor<2x!polynomial.polynomial> + %add = polynomial.add %tp0, %tp1 : tensor<2x!polynomial.polynomial<#ring1>> + %sub = polynomial.sub %tp0, %tp1 : tensor<2x!polynomial.polynomial<#ring1>> + %mul = polynomial.mul %tp0, %tp1 : tensor<2x!polynomial.polynomial<#ring1>> return } - func.func @test_to_from_tensor(%p0 : !polynomial.polynomial) { + func.func @test_to_from_tensor(%p0 : !polynomial.polynomial<#ring1>) { %c0 = arith.constant 0 : index %two = arith.constant 2 : i16 %coeffs1 = tensor.from_elements %two, %two : tensor<2xi16> // CHECK: from_tensor - %poly = polynomial.from_tensor %coeffs1 : tensor<2xi16> -> !polynomial.polynomial + %poly = polynomial.from_tensor %coeffs1 : tensor<2xi16> -> !polynomial.polynomial<#ring1> // CHECK: to_tensor - %tensor = polynomial.to_tensor %poly : !polynomial.polynomial -> tensor<1024xi16> + %tensor = polynomial.to_tensor %poly : !polynomial.polynomial<#ring1> -> tensor<1024xi16> return } - func.func @test_degree(%p0 : !polynomial.polynomial) { - %0, %1 = polynomial.leading_term %p0 : !polynomial.polynomial -> (index, i32) + func.func @test_degree(%p0 : !polynomial.polynomial<#ring1>) { + %0, %1 = polynomial.leading_term %p0 : !polynomial.polynomial<#ring1> -> (index, i32) return } func.func @test_monomial() { %deg = arith.constant 1023 : index %five = arith.constant 5 : i16 - %0 = polynomial.monomial %five, %deg : (i16, index) -> !polynomial.polynomial + %0 = polynomial.monomial %five, %deg : (i16, index) -> !polynomial.polynomial<#ring1> return } func.func @test_monic_monomial_mul() { %five = arith.constant 5 : index - %0 = polynomial.constant {value=#one_plus_x_squared} : !polynomial.polynomial - %1 = polynomial.monic_monomial_mul %0, %five : (!polynomial.polynomial, index) -> !polynomial.polynomial + %0 = polynomial.constant #one_plus_x_squared : !polynomial.polynomial<#ring1> + %1 = polynomial.monic_monomial_mul %0, %five : (!polynomial.polynomial<#ring1>, index) -> !polynomial.polynomial<#ring1> return } func.func @test_constant() { - %0 = polynomial.constant {value=#one_plus_x_squared} : !polynomial.polynomial - %1 = polynomial.constant {value=#polynomial.int_polynomial<1 + x**2>} : !polynomial.polynomial - %2 = polynomial.constant {value=#polynomial.float_polynomial<1.5 + 0.5 x**2>} : !polynomial.polynomial + %0 = polynomial.constant #one_plus_x_squared : !polynomial.polynomial<#ring1> + %1 = polynomial.constant <1 + x**2> : !polynomial.polynomial<#ring1> return } diff --git a/mlir/test/Dialect/Polynomial/ops_errors.mlir b/mlir/test/Dialect/Polynomial/ops_errors.mlir index af8e4aa5da86..2c20e7bcbf1d 100644 --- a/mlir/test/Dialect/Polynomial/ops_errors.mlir +++ b/mlir/test/Dialect/Polynomial/ops_errors.mlir @@ -1,8 +1,8 @@ // RUN: mlir-opt --split-input-file --verify-diagnostics %s -#my_poly = #polynomial.int_polynomial<1 + x**1024> -#ring = #polynomial.ring -!ty = !polynomial.polynomial +#my_poly = #polynomial.polynomial<1 + x**1024> +#ring = #polynomial.ring +!ty = !polynomial.polynomial<#ring> func.func @test_from_tensor_too_large_coeffs() { %two = arith.constant 2 : i32 @@ -15,13 +15,13 @@ func.func @test_from_tensor_too_large_coeffs() { // ----- -#my_poly = #polynomial.int_polynomial<1 + x**4> -#ring = #polynomial.ring -!ty = !polynomial.polynomial +#my_poly = #polynomial.polynomial<1 + x**4> +#ring = #polynomial.ring +!ty = !polynomial.polynomial<#ring> func.func @test_from_tensor_wrong_tensor_type() { %two = arith.constant 2 : i32 %coeffs1 = tensor.from_elements %two, %two, %two, %two, %two : tensor<5xi32> - // expected-error@below {{input type 'tensor<5xi32>' does not match output type '!polynomial.polynomial>>'}} + // expected-error@below {{input type 'tensor<5xi32>' does not match output type '!polynomial.polynomial<#polynomial.ring>>'}} // expected-note@below {{at most the degree of the polynomialModulus of the output type's ring attribute}} %poly = polynomial.from_tensor %coeffs1 : tensor<5xi32> -> !ty return @@ -29,11 +29,11 @@ func.func @test_from_tensor_wrong_tensor_type() { // ----- -#my_poly = #polynomial.int_polynomial<1 + x**4> -#ring = #polynomial.ring -!ty = !polynomial.polynomial +#my_poly = #polynomial.polynomial<1 + x**4> +#ring = #polynomial.ring +!ty = !polynomial.polynomial<#ring> func.func @test_to_tensor_wrong_output_tensor_type(%arg0 : !ty) { - // expected-error@below {{input type '!polynomial.polynomial>>' does not match output type 'tensor<5xi32>'}} + // expected-error@below {{input type '!polynomial.polynomial<#polynomial.ring>>' does not match output type 'tensor<5xi32>'}} // expected-note@below {{at most the degree of the polynomialModulus of the input type's ring attribute}} %tensor = polynomial.to_tensor %arg0 : !ty -> tensor<5xi32> return @@ -41,9 +41,9 @@ func.func @test_to_tensor_wrong_output_tensor_type(%arg0 : !ty) { // ----- -#my_poly = #polynomial.int_polynomial<1 + x**1024> -#ring = #polynomial.ring -!ty = !polynomial.polynomial +#my_poly = #polynomial.polynomial<1 + x**1024> +#ring = #polynomial.ring +!ty = !polynomial.polynomial<#ring> func.func @test_mul_scalar_wrong_type(%arg0: !ty) -> !ty { %scalar = arith.constant 2 : i32 // should be i16 @@ -54,9 +54,9 @@ func.func @test_mul_scalar_wrong_type(%arg0: !ty) -> !ty { // ----- -#my_poly = #polynomial.int_polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial +#my_poly = #polynomial.polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial<#ring> // CHECK-NOT: @test_invalid_ntt // CHECK-NOT: polynomial.ntt @@ -68,9 +68,9 @@ func.func @test_invalid_ntt(%0 : !poly_ty) { // ----- -#my_poly = #polynomial.int_polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial +#my_poly = #polynomial.polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial<#ring> // CHECK-NOT: @test_invalid_ntt // CHECK-NOT: polynomial.ntt @@ -82,10 +82,10 @@ func.func @test_invalid_ntt(%0 : !poly_ty) { // ----- -#my_poly = #polynomial.int_polynomial<-1 + x**1024> -#ring = #polynomial.ring -#ring1 = #polynomial.ring -!poly_ty = !polynomial.polynomial +#my_poly = #polynomial.polynomial<-1 + x**1024> +#ring = #polynomial.ring +#ring1 = #polynomial.ring +!poly_ty = !polynomial.polynomial<#ring> // CHECK-NOT: @test_invalid_intt // CHECK-NOT: polynomial.intt @@ -97,9 +97,9 @@ func.func @test_invalid_intt(%0 : tensor<1024xi32, #ring1>) { // ----- -#my_poly = #polynomial.int_polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial +#my_poly = #polynomial.polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial<#ring> // CHECK-NOT: @test_invalid_intt // CHECK-NOT: polynomial.intt @@ -112,9 +112,9 @@ func.func @test_invalid_intt(%0 : tensor<1025xi32, #ring>) { // ----- -#my_poly = #polynomial.int_polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial +#my_poly = #polynomial.polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial<#ring> // CHECK-NOT: @test_invalid_ntt // CHECK-NOT: polynomial.ntt @@ -126,10 +126,10 @@ func.func @test_invalid_ntt(%0 : !poly_ty) { // ----- -#my_poly = #polynomial.int_polynomial<-1 + x**8> +#my_poly = #polynomial.polynomial<-1 + x**8> // A valid root is 31 -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial<#ring> // CHECK-NOT: @test_invalid_intt // CHECK-NOT: polynomial.intt diff --git a/mlir/test/Dialect/Polynomial/types.mlir b/mlir/test/Dialect/Polynomial/types.mlir index dcc5663ceb84..00296a36e890 100644 --- a/mlir/test/Dialect/Polynomial/types.mlir +++ b/mlir/test/Dialect/Polynomial/types.mlir @@ -2,13 +2,13 @@ // CHECK-LABEL: func @test_types // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: ring = < -// CHECK-SAME: coefficientType = i32, -// CHECK-SAME: coefficientModulus = 2837465 : i32, -// CHECK-SAME: polynomialModulus = <1 + x**1024>>> -#my_poly = #polynomial.int_polynomial<1 + x**1024> -#ring1 = #polynomial.ring -!ty = !polynomial.polynomial +// CHECK-SAME: #polynomial.ring< +// CHECK-SAME: coefficientType=i32, +// CHECK-SAME: coefficientModulus=2837465 : i32, +// CHECK-SAME: polynomialModulus=#polynomial.polynomial<1 + x**1024>>> +#my_poly = #polynomial.polynomial<1 + x**1024> +#ring1 = #polynomial.ring +!ty = !polynomial.polynomial<#ring1> func.func @test_types(%0: !ty) -> !ty { return %0 : !ty } @@ -16,13 +16,13 @@ func.func @test_types(%0: !ty) -> !ty { // CHECK-LABEL: func @test_non_x_variable_64_bit // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: ring = < -// CHECK-SAME: coefficientType = i64, -// CHECK-SAME: coefficientModulus = 2837465 : i64, -// CHECK-SAME: polynomialModulus = <2 + 4x + x**3>>> -#my_poly_2 = #polynomial.int_polynomial -#ring2 = #polynomial.ring -!ty2 = !polynomial.polynomial +// CHECK-SAME: #polynomial.ring< +// CHECK-SAME: coefficientType=i64, +// CHECK-SAME: coefficientModulus=2837465 : i64, +// CHECK-SAME: polynomialModulus=#polynomial.polynomial<2 + 4x + x**3>>> +#my_poly_2 = #polynomial.polynomial +#ring2 = #polynomial.ring +!ty2 = !polynomial.polynomial<#ring2> func.func @test_non_x_variable_64_bit(%0: !ty2) -> !ty2 { return %0 : !ty2 } @@ -30,36 +30,27 @@ func.func @test_non_x_variable_64_bit(%0: !ty2) -> !ty2 { // CHECK-LABEL: func @test_linear_poly // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: ring = < -// CHECK-SAME: coefficientType = i32, -// CHECK-SAME: coefficientModulus = 12 : i32, -// CHECK-SAME: polynomialModulus = <4x>> -#my_poly_3 = #polynomial.int_polynomial<4x> -#ring3 = #polynomial.ring -!ty3 = !polynomial.polynomial +// CHECK-SAME: #polynomial.ring< +// CHECK-SAME: coefficientType=i32, +// CHECK-SAME: coefficientModulus=12 : i32, +// CHECK-SAME: polynomialModulus=#polynomial.polynomial<4x>> +#my_poly_3 = #polynomial.polynomial<4x> +#ring3 = #polynomial.ring +!ty3 = !polynomial.polynomial<#ring3> func.func @test_linear_poly(%0: !ty3) -> !ty3 { return %0 : !ty3 } // CHECK-LABEL: func @test_negative_leading_1 // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: ring = < -// CHECK-SAME: coefficientType = i32, -// CHECK-SAME: coefficientModulus = 2837465 : i32, -// CHECK-SAME: polynomialModulus = <-1 + x**1024>>> -#my_poly_4 = #polynomial.int_polynomial<-1 + x**1024> -#ring4 = #polynomial.ring -!ty4 = !polynomial.polynomial +// CHECK-SAME: #polynomial.ring< +// CHECK-SAME: coefficientType=i32, +// CHECK-SAME: coefficientModulus=2837465 : i32, +// CHECK-SAME: polynomialModulus=#polynomial.polynomial<-1 + x**1024>>> +#my_poly_4 = #polynomial.polynomial<-1 + x**1024> +#ring4 = #polynomial.ring +!ty4 = !polynomial.polynomial<#ring4> func.func @test_negative_leading_1(%0: !ty4) -> !ty4 { return %0 : !ty4 } -// CHECK-LABEL: func @test_float_coefficients -// CHECK-SAME: !polynomial.polynomial> -#my_poly_5 = #polynomial.float_polynomial<0.5 + 1.6e03 x**1024> -#ring5 = #polynomial.ring -!ty5 = !polynomial.polynomial -func.func @test_float_coefficients(%0: !ty5) -> !ty5 { - return %0 : !ty5 -} - -- GitLab From cf40c93b5be5cd0011ebbf3a9eead224f7b7079a Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Mon, 13 May 2024 13:20:30 -0400 Subject: [PATCH 102/578] [mlir][vector] Add Vector-dialect interleave-to-shuffle pattern, enable in VectorToSPIRV (#91800) Context: https://github.com/iree-org/iree/issues/17346. Test IREE integrate showing it's fixing the problem it's intended to fix, i.e. it allows IREE to drop its local revert of https://github.com/llvm/llvm-project/pull/89131: https://github.com/iree-org/iree/pull/17359 This is added to VectorToSPIRV because SPIRV doesn't currently handle `vector.interleave` (see motivating context above). This is limited to 1D, non-scalable vectors. --- .../Vector/TransformOps/VectorTransformOps.td | 14 +++++++ .../Vector/Transforms/LoweringPatterns.h | 3 ++ .../VectorToSPIRV/VectorToSPIRV.cpp | 4 ++ .../TransformOps/VectorTransformOps.cpp | 5 +++ .../Transforms/LowerVectorInterleave.cpp | 41 +++++++++++++++++++ .../Vector/vector-interleave-to-shuffle.mlir | 21 ++++++++++ 6 files changed, 88 insertions(+) create mode 100644 mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir diff --git a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td index f6371f39c394..bc3c16d40520 100644 --- a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td +++ b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td @@ -306,6 +306,20 @@ def ApplyLowerInterleavePatternsOp : Op]> { + let description = [{ + Indicates that 1D vector interleave operations should be rewritten as + vector shuffle operations. + + This is motivated by some current codegen backends not handling vector + interleave operations. + }]; + + let assemblyFormat = "attr-dict"; +} + def ApplyRewriteNarrowTypePatternsOp : Op]> { diff --git a/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h b/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h index 350d2777cadf..8fd9904fabc0 100644 --- a/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h +++ b/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h @@ -273,6 +273,9 @@ void populateVectorInterleaveLoweringPatterns(RewritePatternSet &patterns, int64_t targetRank = 1, PatternBenefit benefit = 1); +void populateVectorInterleaveToShufflePatterns(RewritePatternSet &patterns, + PatternBenefit benefit = 1); + } // namespace vector } // namespace mlir #endif // MLIR_DIALECT_VECTOR_TRANSFORMS_LOWERINGPATTERNS_H diff --git a/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp b/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp index 868a3521e7a0..c2dd37f48146 100644 --- a/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp +++ b/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp @@ -18,6 +18,7 @@ #include "mlir/Dialect/SPIRV/IR/SPIRVTypes.h" #include "mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" +#include "mlir/Dialect/Vector/Transforms/LoweringPatterns.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinTypes.h" @@ -828,6 +829,9 @@ void mlir::populateVectorToSPIRVPatterns(SPIRVTypeConverter &typeConverter, // than the generic one that extracts all elements. patterns.add(typeConverter, patterns.getContext(), PatternBenefit(2)); + + // Need this until vector.interleave is handled. + vector::populateVectorInterleaveToShufflePatterns(patterns); } void mlir::populateVectorReductionToSPIRVDotProductPatterns( diff --git a/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp b/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp index 885644864c0f..61fd6bd972e3 100644 --- a/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp +++ b/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp @@ -164,6 +164,11 @@ void transform::ApplyLowerInterleavePatternsOp::populatePatterns( vector::populateVectorInterleaveLoweringPatterns(patterns); } +void transform::ApplyInterleaveToShufflePatternsOp::populatePatterns( + RewritePatternSet &patterns) { + vector::populateVectorInterleaveToShufflePatterns(patterns); +} + void transform::ApplyRewriteNarrowTypePatternsOp::populatePatterns( RewritePatternSet &patterns) { populateVectorNarrowTypeRewritePatterns(patterns); diff --git a/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp b/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp index 3a456076f8fb..5326760c9b4e 100644 --- a/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp @@ -16,6 +16,7 @@ #include "mlir/Dialect/Vector/Utils/VectorUtils.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/PatternMatch.h" +#include "mlir/Support/LogicalResult.h" #define DEBUG_TYPE "vector-interleave-lowering" @@ -77,9 +78,49 @@ private: int64_t targetRank = 1; }; +/// Rewrite vector.interleave op into an equivalent vector.shuffle op, when +/// applicable: `sourceType` must be 1D and non-scalable. +/// +/// Example: +/// +/// ```mlir +/// vector.interleave %a, %b : vector<7xi16> +/// ``` +/// +/// Is rewritten into: +/// +/// ```mlir +/// vector.shuffle %arg0, %arg1 [0, 7, 1, 8, 2, 9, 3, 10, 4, 11, 5, 12, 6, 13] +/// : vector<7xi16>, vector<7xi16> +/// ``` +class InterleaveToShuffle : public OpRewritePattern { +public: + InterleaveToShuffle(MLIRContext *context, PatternBenefit benefit = 1) + : OpRewritePattern(context, benefit) {}; + + LogicalResult matchAndRewrite(vector::InterleaveOp op, + PatternRewriter &rewriter) const override { + VectorType sourceType = op.getSourceVectorType(); + if (sourceType.getRank() != 1 || sourceType.isScalable()) { + return failure(); + } + int64_t n = sourceType.getNumElements(); + auto seq = llvm::seq(2 * n); + auto zip = llvm::to_vector(llvm::map_range( + seq, [n](int64_t i) { return (i % 2 ? n : 0) + i / 2; })); + rewriter.replaceOpWithNewOp(op, op.getLhs(), op.getRhs(), zip); + return success(); + } +}; + } // namespace void mlir::vector::populateVectorInterleaveLoweringPatterns( RewritePatternSet &patterns, int64_t targetRank, PatternBenefit benefit) { patterns.add(targetRank, patterns.getContext(), benefit); } + +void mlir::vector::populateVectorInterleaveToShufflePatterns( + RewritePatternSet &patterns, PatternBenefit benefit) { + patterns.add(patterns.getContext(), benefit); +} diff --git a/mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir b/mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir new file mode 100644 index 000000000000..ed3b3396bf3e --- /dev/null +++ b/mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir @@ -0,0 +1,21 @@ +// RUN: mlir-opt %s --transform-interpreter | FileCheck %s + +// CHECK-LABEL: @vector_interleave_to_shuffle +func.func @vector_interleave_to_shuffle(%a: vector<7xi16>, %b: vector<7xi16>) -> vector<14xi16> +{ + %0 = vector.interleave %a, %b : vector<7xi16> + return %0 : vector<14xi16> +} +// CHECK: vector.shuffle %arg0, %arg1 [0, 7, 1, 8, 2, 9, 3, 10, 4, 11, 5, 12, 6, 13] : vector<7xi16>, vector<7xi16> + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%module_op: !transform.any_op {transform.readonly}) { + %f = transform.structured.match ops{["func.func"]} in %module_op + : (!transform.any_op) -> !transform.any_op + + transform.apply_patterns to %f { + transform.apply_patterns.vector.interleave_to_shuffle + } : !transform.any_op + transform.yield + } +} -- GitLab From 0f7906645d18a38a6b80a1e8e1d425396f6ab353 Mon Sep 17 00:00:00 2001 From: Felix Schneider Date: Mon, 13 May 2024 19:27:38 +0200 Subject: [PATCH 103/578] [mlir][intrange] Fix `arith.shl` inference in case of overflow (#91737) When an overflow happens during shift left, i.e. the last sign bit or the most significant data bit gets shifted out, the current approach of inferring the range of results does not work anymore. This patch checks for possible overflow and returns the max range in that case. Fix https://github.com/llvm/llvm-project/issues/82158 --- .../Interfaces/Utils/InferIntRangeCommon.cpp | 19 ++++++++++-- mlir/test/Dialect/Arith/int-range-opts.mlir | 29 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp index 2b2d937d55d8..6af229cae10a 100644 --- a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp +++ b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp @@ -544,15 +544,30 @@ mlir::intrange::inferXor(ArrayRef argRanges) { ConstantIntRanges mlir::intrange::inferShl(ArrayRef argRanges) { 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(); + ConstArithFn shl = [](const APInt &l, const APInt &r) -> std::optional { return r.uge(r.getBitWidth()) ? std::optional() : l.shl(r); }; + + // 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(), lhs.umax()}, {rhs.umin(), rhs.umax()}, + minMaxBy(shl, {lhs.umin(), lhsUMax}, {rhsUMin, rhsUMax}, /*isSigned=*/false); ConstantIntRanges srange = - minMaxBy(shl, {lhs.smin(), lhs.smax()}, {rhs.umin(), rhs.umax()}, + minMaxBy(shl, {lhsSMin, lhsSMax}, {rhsUMin, rhsUMax}, /*isSigned=*/true); return urange.intersection(srange); } diff --git a/mlir/test/Dialect/Arith/int-range-opts.mlir b/mlir/test/Dialect/Arith/int-range-opts.mlir index be0a7e8ccd70..4c3c0854ed02 100644 --- a/mlir/test/Dialect/Arith/int-range-opts.mlir +++ b/mlir/test/Dialect/Arith/int-range-opts.mlir @@ -71,3 +71,32 @@ func.func @test() -> i1 { %1 = arith.cmpi sle, %0, %cst1 : index return %1: i1 } + +// ----- + +// CHECK-LABEL: func @test +// CHECK: test.reflect_bounds {smax = 24 : index, smin = 0 : index, umax = 24 : index, umin = 0 : index} +func.func @test() -> index { + %cst1 = arith.constant 1 : i8 + %0 = test.with_bounds { umin = 0 : index, umax = 12 : index, smin = 0 : index, smax = 12 : index } + %i8val = arith.index_cast %0 : index to i8 + %shifted = arith.shli %i8val, %cst1 : i8 + %si = arith.index_cast %shifted : i8 to index + %1 = test.reflect_bounds %si + return %1: index +} + +// ----- + +// CHECK-LABEL: func @test +// CHECK: test.reflect_bounds {smax = 127 : index, smin = -128 : index, umax = -1 : index, umin = 0 : index} +func.func @test() -> index { + %cst1 = arith.constant 1 : i8 + %0 = test.with_bounds { umin = 0 : index, umax = 127 : index, smin = 0 : index, smax = 127 : index } + %i8val = arith.index_cast %0 : index to i8 + %shifted = arith.shli %i8val, %cst1 : i8 + %si = arith.index_cast %shifted : i8 to index + %1 = test.reflect_bounds %si + return %1: index +} + -- GitLab From b8f802f783db481ecfd953c9abe74212a8348aff Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Mon, 13 May 2024 14:28:05 -0300 Subject: [PATCH 104/578] [clang] Allow pack expansions when partial ordering against template template parameters (#91833) When partial ordering alias templates against template template parameters, allow pack expansions when the alias has a fixed-size parameter list. These expansions were generally disallowed by proposed resolution for CWG1430. By previously diagnosing these when checking template template parameters, we would be too strict in trying to prevent any potential invalid use. This flows against the more general idea that template template parameters are weakly typed, that we would rather allow an argument that might be possibly misused, and only diagnose the actual misuses during instantiation. Since this interaction between P0522R0 and CWG1430 is also a backwards-compat breaking change, we implement provisional wording to allow these. Fixes https://github.com/llvm/llvm-project/issues/62529 --- clang/docs/ReleaseNotes.rst | 2 ++ clang/include/clang/Sema/Sema.h | 8 +++++++- clang/lib/Sema/SemaTemplate.cpp | 14 ++++++++++---- clang/lib/Sema/SemaTemplateDeduction.cpp | 4 +++- ...plate_cxx1z.cpp => temp_arg_template_p0522.cpp} | 12 ++++++++++-- 5 files changed, 32 insertions(+), 8 deletions(-) rename clang/test/SemaTemplate/{temp_arg_template_cxx1z.cpp => temp_arg_template_p0522.cpp} (91%) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4702b8c10cdb..28ac54127383 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -708,6 +708,8 @@ Bug Fixes to C++ Support expression. - Fix a bug in access control checking due to dealyed checking of friend declaration. Fixes (#GH12361). - Correctly treat the compound statement of an ``if consteval`` as an immediate context. Fixes (#GH91509). +- When partial ordering alias templates against template template parameters, + allow pack expansions when the alias has a fixed-size parameter list. Fixes (#GH62529). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4efd3878e861..869769f95fd7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9216,6 +9216,12 @@ public: /// receive true if the cause for the error is the associated constraints of /// the template not being satisfied by the template arguments. /// + /// \param PartialOrderingTTP If true, assume these template arguments are + /// the injected template arguments for a template template parameter. + /// This will relax the requirement that all its possible uses are valid: + /// TTP checking is loose, and assumes that invalid uses will be diagnosed + /// during instantiation. + /// /// \returns true if an error occurred, false otherwise. bool CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, @@ -9223,7 +9229,7 @@ public: SmallVectorImpl &SugaredConverted, SmallVectorImpl &CanonicalConverted, bool UpdateArgsWithConversions = true, - bool *ConstraintsNotSatisfied = nullptr); + bool *ConstraintsNotSatisfied = nullptr, bool PartialOrderingTTP = false); bool CheckTemplateTypeArgument( TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index bae00c629270..8219d5eed8db 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -6556,7 +6556,8 @@ bool Sema::CheckTemplateArgumentList( TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, SmallVectorImpl &SugaredConverted, SmallVectorImpl &CanonicalConverted, - bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) { + bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied, + bool PartialOrderingTTP) { if (ConstraintsNotSatisfied) *ConstraintsNotSatisfied = false; @@ -6627,9 +6628,14 @@ bool Sema::CheckTemplateArgumentList( bool PackExpansionIntoNonPack = NewArgs[ArgIdx].getArgument().isPackExpansion() && (!(*Param)->isTemplateParameterPack() || getExpandedPackSize(*Param)); - if (PackExpansionIntoNonPack && (isa(Template) || - isa(Template))) { - // Core issue 1430: we have a pack expansion as an argument to an + // CWG1430: Don't diagnose this pack expansion when partial + // ordering template template parameters. Some uses of the template could + // be valid, and invalid uses will be diagnosed later during + // instantiation. + if (PackExpansionIntoNonPack && !PartialOrderingTTP && + (isa(Template) || + isa(Template))) { + // CWG1430: we have a pack expansion as an argument to an // alias template, and it's not part of a parameter pack. This // can't be canonicalized, so reject it now. // As for concepts - we cannot normalize constraints where this diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index fe7e35d84151..853c0e1b5061 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -6243,7 +6243,9 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs( // specialized as A. SmallVector SugaredPArgs; if (CheckTemplateArgumentList(AArg, Loc, PArgList, false, SugaredPArgs, - PArgs) || + PArgs, /*UpdateArgsWithConversions=*/true, + /*ConstraintsNotSatisfied=*/nullptr, + /*PartialOrderTTP=*/true) || Trap.hasErrorOccurred()) return false; } diff --git a/clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_template_p0522.cpp similarity index 91% rename from clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp rename to clang/test/SemaTemplate/temp_arg_template_p0522.cpp index 372a00efc601..251b6fc7d2be 100644 --- a/clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp +++ b/clang/test/SemaTemplate/temp_arg_template_p0522.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s -// expected-note@temp_arg_template_cxx1z.cpp:* 1+{{}} +// expected-note@temp_arg_template_p0522.cpp:* 1+{{}} template typename> struct Ti; template typename> struct TPi; @@ -118,3 +118,11 @@ namespace Auto { TInt isf; // FIXME: this should be ill-formed TIntPtr ipsf; } + +namespace GH62529 { + // Note: the constraint here is just for bypassing a fast-path. + template requires(true) using A = int; + template class TT1, class T3> struct B {}; + template B f(); + auto t = f(); +} // namespace GH62529 -- GitLab From 8ef2011b2cd3a8fc2ef8d6ea0facb1a39a0dd621 Mon Sep 17 00:00:00 2001 From: erichkeane Date: Mon, 13 May 2024 08:43:15 -0700 Subject: [PATCH 105/578] Reapply "[OpenACC] device_type clause Sema for Compute constructs" device_type, also spelled as dtype, specifies the applicability of the clauses following it, and takes a series of identifiers representing the architectures it applies to. As we don't have a source for the valid architectures yet, this patch just accepts all. Semantically, this also limits the list of clauses that can be applied after the device_type, so this implements that as well. This reverts commit 06f04b2e27f2586d3db2204ed4e54f8b78fea74e. This reapplies commit c4a9a374749deb5f2a932a7d4ef9321be1b2ae5d. The build failures were caused by the patch depending on the order of evaluation of arguments to a function. This reapplication separates out the capture of one of the values. --- clang/include/clang/AST/OpenACCClause.h | 59 +++++ .../clang/Basic/DiagnosticSemaKinds.td | 4 + clang/include/clang/Basic/OpenACCClauses.def | 2 + clang/include/clang/Parse/Parser.h | 3 +- clang/include/clang/Sema/SemaOpenACC.h | 23 +- clang/lib/AST/OpenACCClause.cpp | 28 ++- clang/lib/AST/StmtProfile.cpp | 3 + clang/lib/AST/TextNodeDumper.cpp | 13 ++ clang/lib/Parse/ParseOpenACC.cpp | 23 +- clang/lib/Sema/SemaOpenACC.cpp | 55 +++++ clang/lib/Sema/TreeTransform.h | 10 + clang/lib/Serialization/ASTReader.cpp | 17 +- clang/lib/Serialization/ASTWriter.cpp | 15 +- .../ast-print-openacc-compute-construct.cpp | 23 ++ clang/test/ParserOpenACC/parse-clauses.c | 28 +-- .../compute-construct-device_type-ast.cpp | 105 +++++++++ .../compute-construct-device_type-clause.c | 221 ++++++++++++++++++ .../compute-construct-device_type-clause.cpp | 25 ++ clang/tools/libclang/CIndex.cpp | 2 + 19 files changed, 624 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp create mode 100644 clang/test/SemaOpenACC/compute-construct-device_type-clause.c create mode 100644 clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 3d0b1ab9d31e..607a2b9d6536 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -17,6 +17,8 @@ #include "clang/AST/StmtIterator.h" #include "clang/Basic/OpenACCKinds.h" +#include + namespace clang { /// This is the base type for all OpenACC Clauses. class OpenACCClause { @@ -75,6 +77,63 @@ public: } }; +using DeviceTypeArgument = std::pair; +/// A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or +/// an identifier. The 'asterisk' means 'the rest'. +class OpenACCDeviceTypeClause final + : public OpenACCClauseWithParams, + public llvm::TrailingObjects { + // Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A + // nullptr IdentifierInfo* represents an asterisk. + unsigned NumArchs; + OpenACCDeviceTypeClause(OpenACCClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, + ArrayRef Archs, + SourceLocation EndLoc) + : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc), + NumArchs(Archs.size()) { + assert( + (K == OpenACCClauseKind::DeviceType || K == OpenACCClauseKind::DType) && + "Invalid clause kind for device-type"); + + assert(!llvm::any_of(Archs, [](const DeviceTypeArgument &Arg) { + return Arg.second.isInvalid(); + }) && "Invalid SourceLocation for an argument"); + + assert( + (Archs.size() == 1 || !llvm::any_of(Archs, + [](const DeviceTypeArgument &Arg) { + return Arg.first == nullptr; + })) && + "Only a single asterisk version is permitted, and must be the " + "only one"); + + std::uninitialized_copy(Archs.begin(), Archs.end(), + getTrailingObjects()); + } + +public: + static bool classof(const OpenACCClause *C) { + return C->getClauseKind() == OpenACCClauseKind::DType || + C->getClauseKind() == OpenACCClauseKind::DeviceType; + } + bool hasAsterisk() const { + return getArchitectures().size() > 0 && + getArchitectures()[0].first == nullptr; + } + + ArrayRef getArchitectures() const { + return ArrayRef( + getTrailingObjects(), NumArchs); + } + + static OpenACCDeviceTypeClause * + Create(const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, ArrayRef Archs, + SourceLocation EndLoc); +}; + /// A 'default' clause, has the optional 'none' or 'present' argument. class OpenACCDefaultClause : public OpenACCClauseWithParams { friend class ASTReaderStmt; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9e82130c9360..6100fba51005 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12344,4 +12344,8 @@ def warn_acc_deprecated_alias_name def err_acc_var_not_pointer_type : Error<"expected pointer in '%0' clause, type is %1">; def note_acc_expected_pointer_var : Note<"expected variable of pointer type">; +def err_acc_clause_after_device_type + : Error<"OpenACC clause '%0' may not follow a '%1' clause in a " + "compute construct">; + } // end of sema component. diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def index afb7b30b7465..7ecc51799468 100644 --- a/clang/include/clang/Basic/OpenACCClauses.def +++ b/clang/include/clang/Basic/OpenACCClauses.def @@ -37,6 +37,8 @@ CLAUSE_ALIAS(PCreate, Create) CLAUSE_ALIAS(PresentOrCreate, Create) VISIT_CLAUSE(Default) VISIT_CLAUSE(DevicePtr) +VISIT_CLAUSE(DeviceType) +CLAUSE_ALIAS(DType, DeviceType) VISIT_CLAUSE(FirstPrivate) VISIT_CLAUSE(If) VISIT_CLAUSE(NoCreate) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 61589fb7766f..3910cba34a21 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3720,7 +3720,8 @@ private: SourceLocation Loc, llvm::SmallVectorImpl &IntExprs); /// Parses the 'device-type-list', which is a list of identifiers. - bool ParseOpenACCDeviceTypeList(); + bool ParseOpenACCDeviceTypeList( + llvm::SmallVector> &Archs); /// Parses the 'async-argument', which is an integral value with two /// 'special' values that are likely negative (but come from Macros). OpenACCIntExprParseResult ParseOpenACCAsyncArgument(OpenACCDirectiveKind DK, diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index e684ee6b2be1..f838fa97d33a 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -26,6 +26,9 @@ class OpenACCClause; class SemaOpenACC : public SemaBase { public: + // Redeclaration of the version in OpenACCClause.h. + using DeviceTypeArgument = std::pair; + /// A type to represent all the data for an OpenACC Clause that has been /// parsed, but not yet created/semantically analyzed. This is effectively a /// discriminated union on the 'Clause Kind', with all of the individual @@ -60,8 +63,12 @@ public: SmallVector QueueIdExprs; }; + struct DeviceTypeDetails { + SmallVector Archs; + }; + std::variant + IntExprDetails, VarListDetails, WaitDetails, DeviceTypeDetails> Details = std::monostate{}; public: @@ -209,6 +216,13 @@ public: return std::get(Details).IsZero; } + ArrayRef getDeviceTypeArchitectures() const { + assert((ClauseKind == OpenACCClauseKind::DeviceType || + ClauseKind == OpenACCClauseKind::DType) && + "Only 'device_type'/'dtype' has a device-type-arg list"); + return std::get(Details).Archs; + } + void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; } void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); } @@ -326,6 +340,13 @@ public: "Parsed clause kind does not have a wait-details"); Details = WaitDetails{DevNum, QueuesLoc, std::move(IntExprs)}; } + + void setDeviceTypeDetails(llvm::SmallVector &&Archs) { + assert((ClauseKind == OpenACCClauseKind::DeviceType || + ClauseKind == OpenACCClauseKind::DType) && + "Only 'device_type'/'dtype' has a device-type-arg list"); + Details = DeviceTypeDetails{std::move(Archs)}; + } }; SemaOpenACC(Sema &S); diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index ee13437b97b4..f80ecc90d396 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -18,7 +18,8 @@ using namespace clang; bool OpenACCClauseWithParams::classof(const OpenACCClause *C) { - return OpenACCClauseWithCondition::classof(C) || + return OpenACCDeviceTypeClause::classof(C) || + OpenACCClauseWithCondition::classof(C) || OpenACCClauseWithExprs::classof(C); } bool OpenACCClauseWithExprs::classof(const OpenACCClause *C) { @@ -298,6 +299,17 @@ OpenACCCreateClause::Create(const ASTContext &C, OpenACCClauseKind Spelling, VarList, EndLoc); } +OpenACCDeviceTypeClause *OpenACCDeviceTypeClause::Create( + const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, ArrayRef Archs, + SourceLocation EndLoc) { + void *Mem = + C.Allocate(OpenACCDeviceTypeClause::totalSizeToAlloc( + Archs.size())); + return new (Mem) + OpenACCDeviceTypeClause(K, BeginLoc, LParenLoc, Archs, EndLoc); +} + //===----------------------------------------------------------------------===// // OpenACC clauses printing methods //===----------------------------------------------------------------------===// @@ -451,3 +463,17 @@ void OpenACCClausePrinter::VisitWaitClause(const OpenACCWaitClause &C) { OS << ")"; } } + +void OpenACCClausePrinter::VisitDeviceTypeClause( + const OpenACCDeviceTypeClause &C) { + OS << C.getClauseKind(); + OS << "("; + llvm::interleaveComma(C.getArchitectures(), OS, + [&](const DeviceTypeArgument &Arch) { + if (Arch.first == nullptr) + OS << "*"; + else + OS << Arch.first; + }); + OS << ")"; +} diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 8fb8940142eb..caab4ab0ef16 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2585,6 +2585,9 @@ void OpenACCClauseProfiler::VisitWaitClause(const OpenACCWaitClause &Clause) { for (auto *E : Clause.getQueueIdExprs()) Profiler.VisitStmt(E); } +/// Nothing to do here, there are no sub-statements. +void OpenACCClauseProfiler::VisitDeviceTypeClause( + const OpenACCDeviceTypeClause &Clause) {} } // namespace void StmtProfiler::VisitOpenACCComputeConstruct( diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 12aa5858b798..efcd74717a4e 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -444,6 +444,19 @@ void TextNodeDumper::Visit(const OpenACCClause *C) { if (cast(C)->hasQueuesTag()) OS << " has queues tag"; break; + case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DType: + OS << "("; + llvm::interleaveComma( + cast(C)->getArchitectures(), OS, + [&](const DeviceTypeArgument &Arch) { + if (Arch.first == nullptr) + OS << "*"; + else + OS << Arch.first->getName(); + }); + OS << ")"; + break; default: // Nothing to do here. break; diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 0e10632c8317..5db3036b0003 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -711,14 +711,16 @@ bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK, /// device_type( device-type-list ) /// /// The device_type clause may be abbreviated to dtype. -bool Parser::ParseOpenACCDeviceTypeList() { +bool Parser::ParseOpenACCDeviceTypeList( + llvm::SmallVector> &Archs) { if (expectIdentifierOrKeyword(*this)) { SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, Parser::StopBeforeMatch); - return false; + return true; } - ConsumeToken(); + IdentifierInfo *Ident = getCurToken().getIdentifierInfo(); + Archs.emplace_back(Ident, ConsumeToken()); while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { ExpectAndConsume(tok::comma); @@ -726,9 +728,10 @@ bool Parser::ParseOpenACCDeviceTypeList() { if (expectIdentifierOrKeyword(*this)) { SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, Parser::StopBeforeMatch); - return false; + return true; } - ConsumeToken(); + Ident = getCurToken().getIdentifierInfo(); + Archs.emplace_back(Ident, ConsumeToken()); } return false; } @@ -1021,16 +1024,20 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( break; } case OpenACCClauseKind::DType: - case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DeviceType: { + llvm::SmallVector> Archs; if (getCurToken().is(tok::star)) { // FIXME: We want to mark that this is an 'everything else' type of // device_type in Sema. - ConsumeToken(); - } else if (ParseOpenACCDeviceTypeList()) { + ParsedClause.setDeviceTypeDetails({{nullptr, ConsumeToken()}}); + } else if (!ParseOpenACCDeviceTypeList(Archs)) { + ParsedClause.setDeviceTypeDetails(std::move(Archs)); + } else { Parens.skipToEnd(); return OpenACCCanContinue(); } break; + } case OpenACCClauseKind::Tile: if (ParseOpenACCSizeExprList()) { Parens.skipToEnd(); diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 656d30947a8d..f174b2fa63c6 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -255,6 +255,33 @@ bool checkAlreadyHasClauseOfKind( return false; } +/// Implement check from OpenACC3.3: section 2.5.4: +/// Only the async, wait, num_gangs, num_workers, and vector_length clauses may +/// follow a device_type clause. +bool checkValidAfterDeviceType( + SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause, + const SemaOpenACC::OpenACCParsedClause &NewClause) { + // This is only a requirement on compute constructs so far, so this is fine + // otherwise. + if (!isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind())) + return false; + switch (NewClause.getClauseKind()) { + case OpenACCClauseKind::Async: + case OpenACCClauseKind::Wait: + case OpenACCClauseKind::NumGangs: + case OpenACCClauseKind::NumWorkers: + case OpenACCClauseKind::VectorLength: + case OpenACCClauseKind::DType: + case OpenACCClauseKind::DeviceType: + return false; + default: + S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type) + << NewClause.getClauseKind() << DeviceTypeClause.getClauseKind(); + S.Diag(DeviceTypeClause.getBeginLoc(), diag::note_acc_previous_clause_here); + return true; + } +} + } // namespace SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {} @@ -273,6 +300,17 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, return nullptr; } + if (const auto *DevTypeClause = + llvm::find_if(ExistingClauses, + [&](const OpenACCClause *C) { + return isa(C); + }); + DevTypeClause != ExistingClauses.end()) { + if (checkValidAfterDeviceType( + *this, *cast(*DevTypeClause), Clause)) + return nullptr; + } + switch (Clause.getClauseKind()) { case OpenACCClauseKind::Default: { // Restrictions only properly implemented on 'compute' constructs, and @@ -651,6 +689,23 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, Clause.getDevNumExpr(), Clause.getQueuesLoc(), Clause.getQueueIdExprs(), Clause.getEndLoc()); } + case OpenACCClauseKind::DType: + case OpenACCClauseKind::DeviceType: { + // Restrictions only properly implemented on 'compute' constructs, and + // 'compute' constructs are the only construct that can do anything with + // this yet, so skip/treat as unimplemented in this case. + if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) + break; + + // TODO OpenACC: Once we get enough of the CodeGen implemented that we have + // a source for the list of valid architectures, we need to warn on unknown + // identifiers here. + + return OpenACCDeviceTypeClause::Create( + getASTContext(), Clause.getClauseKind(), Clause.getBeginLoc(), + Clause.getLParenLoc(), Clause.getDeviceTypeArchitectures(), + Clause.getEndLoc()); + } default: break; } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 126965088831..ab26d1b1199a 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -11480,6 +11480,16 @@ void OpenACCClauseTransform::VisitWaitClause( ParsedClause.getQueuesLoc(), ParsedClause.getQueueIdExprs(), ParsedClause.getEndLoc()); } + +template +void OpenACCClauseTransform::VisitDeviceTypeClause( + const OpenACCDeviceTypeClause &C) { + // Nothing to transform here, just create a new version of 'C'. + NewClause = OpenACCDeviceTypeClause::Create( + Self.getSema().getASTContext(), C.getClauseKind(), + ParsedClause.getBeginLoc(), ParsedClause.getLParenLoc(), + C.getArchitectures(), ParsedClause.getEndLoc()); +} } // namespace template OpenACCClause *TreeTransform::TransformOpenACCClause( diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 7627996d2c32..8f437a7c5f50 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11905,6 +11905,21 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { DevNumExpr, QueuesLoc, QueueIdExprs, EndLoc); } + case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DType: { + SourceLocation LParenLoc = readSourceLocation(); + llvm::SmallVector Archs; + unsigned NumArchs = readInt(); + + for (unsigned I = 0; I < NumArchs; ++I) { + IdentifierInfo *Ident = readBool() ? readIdentifier() : nullptr; + SourceLocation Loc = readSourceLocation(); + Archs.emplace_back(Ident, Loc); + } + + return OpenACCDeviceTypeClause::Create(getContext(), ClauseKind, BeginLoc, + LParenLoc, Archs, EndLoc); + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: @@ -11926,8 +11941,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { case OpenACCClauseKind::Bind: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: - case OpenACCClauseKind::DeviceType: - case OpenACCClauseKind::DType: case OpenACCClauseKind::Tile: case OpenACCClauseKind::Gang: case OpenACCClauseKind::Invalid: diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 6154ead589d3..7a9d392889bb 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7933,6 +7933,19 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeOpenACCIntExprList(WC->getQueueIdExprs()); return; } + case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DType: { + const auto *DTC = cast(C); + writeSourceLocation(DTC->getLParenLoc()); + writeUInt32(DTC->getArchitectures().size()); + for (const DeviceTypeArgument &Arg : DTC->getArchitectures()) { + writeBool(Arg.first); + if (Arg.first) + AddIdentifierRef(Arg.first); + writeSourceLocation(Arg.second); + } + return; + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: @@ -7954,8 +7967,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::Bind: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: - case OpenACCClauseKind::DeviceType: - case OpenACCClauseKind::DType: case OpenACCClauseKind::Tile: case OpenACCClauseKind::Gang: case OpenACCClauseKind::Invalid: diff --git a/clang/test/AST/ast-print-openacc-compute-construct.cpp b/clang/test/AST/ast-print-openacc-compute-construct.cpp index 0bfb90bcb587..cdd9ab3377d0 100644 --- a/clang/test/AST/ast-print-openacc-compute-construct.cpp +++ b/clang/test/AST/ast-print-openacc-compute-construct.cpp @@ -107,5 +107,28 @@ void foo() { // CHECK: #pragma acc parallel wait(devnum: i : queues: *iPtr, i) #pragma acc parallel wait(devnum:i:queues:*iPtr, i) while(true); + + bool SomeB; + struct SomeStruct{} SomeStructImpl; + +//#pragma acc parallel dtype(SomeB) +#pragma acc parallel dtype(SomeB) + while(true); + +//#pragma acc parallel device_type(SomeStruct) +#pragma acc parallel device_type(SomeStruct) + while(true); + +//#pragma acc parallel device_type(int) +#pragma acc parallel device_type(int) + while(true); + +//#pragma acc parallel dtype(bool) +#pragma acc parallel dtype(bool) + while(true); + +//#pragma acc parallel device_type (SomeStructImpl) +#pragma acc parallel device_type (SomeStructImpl) + while(true); } diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index 51858b441e93..694f28b86ec9 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -1126,12 +1126,10 @@ void device_type() { #pragma acc parallel dtype( {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel device_type() {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel dtype() {} @@ -1173,12 +1171,10 @@ void device_type() { #pragma acc parallel dtype(ident, ident2 {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel device_type(ident, ident2,) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel dtype(ident, ident2,) {} @@ -1200,33 +1196,25 @@ void device_type() { #pragma acc parallel dtype(*,ident) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel device_type(ident, *) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel dtype(ident, *) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel device_type("foo", 54) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc parallel dtype(31, "bar") {} - // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented, clause ignored}} #pragma acc parallel device_type(ident, auto, int, float) {} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} #pragma acc parallel dtype(ident, auto, int, float) {} - // expected-warning@+2{{OpenACC clause 'device_type' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC clause 'dtype' not yet implemented, clause ignored}} #pragma acc parallel device_type(ident, auto, int, float) dtype(ident, auto, int, float) {} } diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp b/clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp new file mode 100644 index 000000000000..8a2423f4f542 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-device_type-ast.cpp @@ -0,0 +1,105 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s +#ifndef PCH_HELPER +#define PCH_HELPER + +struct SomeS{}; +void NormalUses() { + // CHECK: FunctionDecl{{.*}}NormalUses + // CHECK-NEXT: CompoundStmt + + SomeS SomeImpl; + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} SomeImpl 'SomeS' + // CHECK-NEXT: CXXConstructExpr + bool SomeVar; + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} SomeVar 'bool' + +#pragma acc parallel device_type(SomeS) dtype(SomeImpl) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(SomeS) + // CHECK-NEXT: dtype(SomeImpl) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(SomeVar) dtype(int) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(SomeVar) + // CHECK-NEXT: dtype(int) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(private) dtype(struct) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(private) + // CHECK-NEXT: dtype(struct) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(private) dtype(class) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(private) + // CHECK-NEXT: dtype(class) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(float) dtype(*) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(float) + // CHECK-NEXT: dtype(*) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(float, int) dtype(*) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(float, int) + // CHECK-NEXT: dtype(*) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +} + +template +void TemplUses() { + // CHECK-NEXT: FunctionTemplateDecl{{.*}}TemplUses + // CHECK-NEXT: TemplateTypeParmDecl{{.*}}T + // CHECK-NEXT: FunctionDecl{{.*}}TemplUses + // CHECK-NEXT: CompoundStmt +#pragma acc parallel device_type(T) dtype(T) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: dtype(T) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + + // Instantiations + // CHECK-NEXT: FunctionDecl{{.*}} TemplUses 'void ()' implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'int' + // CHECK-NEXT: BuiltinType{{.*}} 'int' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: dtype(T) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt +} + +void Inst() { + TemplUses(); +} +#endif // PCH_HELPER diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-clause.c b/clang/test/SemaOpenACC/compute-construct-device_type-clause.c new file mode 100644 index 000000000000..15c9cf396c80 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-device_type-clause.c @@ -0,0 +1,221 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +#define MACRO +FOO + +void uses() { + typedef struct S{} STy; + STy SImpl; + +#pragma acc parallel device_type(I) + while(1); +#pragma acc serial device_type(S) dtype(STy) + while(1); +#pragma acc kernels dtype(SImpl) + while(1); +#pragma acc kernels dtype(int) device_type(*) + while(1); +#pragma acc kernels dtype(true) device_type(false) + while(1); + + // expected-error@+1{{expected identifier}} +#pragma acc kernels dtype(int, *) + while(1); + +#pragma acc parallel device_type(I, int) + while(1); + // expected-error@+2{{expected ','}} + // expected-error@+1{{expected identifier}} +#pragma acc kernels dtype(int{}) + while(1); + // expected-error@+1{{expected identifier}} +#pragma acc kernels dtype(5) + while(1); + // expected-error@+1{{expected identifier}} +#pragma acc kernels dtype(MACRO) + while(1); + + + // Only 'async', 'wait', num_gangs', 'num_workers', 'vector_length' allowed after 'device_type'. + + // expected-error@+2{{OpenACC clause 'finalize' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) finalize + while(1); + // expected-error@+2{{OpenACC clause 'if_present' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) if_present + while(1); + // expected-error@+2{{OpenACC clause 'seq' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) seq + while(1); + // expected-error@+2{{OpenACC clause 'independent' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) independent + while(1); + // expected-error@+2{{OpenACC clause 'auto' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) auto + while(1); + // expected-error@+2{{OpenACC clause 'worker' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) worker + while(1); + // expected-error@+2{{OpenACC clause 'nohost' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) nohost + while(1); + // expected-error@+2{{OpenACC clause 'default' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) default(none) + while(1); + // expected-error@+2{{OpenACC clause 'if' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) if(1) + while(1); + // expected-error@+2{{OpenACC clause 'self' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) self + while(1); + + int Var; + int *VarPtr; + // expected-error@+2{{OpenACC clause 'copy' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) copy(Var) + while(1); + // expected-error@+2{{OpenACC clause 'pcopy' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) pcopy(Var) + while(1); + // expected-error@+2{{OpenACC clause 'present_or_copy' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) present_or_copy(Var) + while(1); + // expected-error@+2{{OpenACC clause 'use_device' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) use_device(Var) + while(1); + // expected-error@+2{{OpenACC clause 'attach' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) attach(Var) + while(1); + // expected-error@+2{{OpenACC clause 'delete' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) delete(Var) + while(1); + // expected-error@+2{{OpenACC clause 'detach' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) detach(Var) + while(1); + // expected-error@+2{{OpenACC clause 'device' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) device(VarPtr) + while(1); + // expected-error@+2{{OpenACC clause 'deviceptr' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) deviceptr(VarPtr) + while(1); + // expected-error@+2{{OpenACC clause 'device_resident' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) device_resident(VarPtr) + while(1); + // expected-error@+2{{OpenACC clause 'firstprivate' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel device_type(*) firstprivate(Var) + while(1); + // expected-error@+2{{OpenACC clause 'host' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) host(Var) + while(1); + // expected-error@+2{{OpenACC clause 'link' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) link(Var) + while(1); + // expected-error@+2{{OpenACC clause 'no_create' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) no_create(Var) + while(1); + // expected-error@+2{{OpenACC clause 'present' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) present(Var) + while(1); + // expected-error@+2{{OpenACC clause 'private' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel device_type(*) private(Var) + while(1); + // expected-error@+2{{OpenACC clause 'copyout' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) copyout(Var) + while(1); + // expected-error@+2{{OpenACC clause 'pcopyout' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) pcopyout(Var) + while(1); + // expected-error@+2{{OpenACC clause 'present_or_copyout' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) present_or_copyout(Var) + while(1); + // expected-error@+2{{OpenACC clause 'copyin' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) copyin(Var) + while(1); + // expected-error@+2{{OpenACC clause 'pcopyin' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) pcopyin(Var) + while(1); + // expected-error@+2{{OpenACC clause 'present_or_copyin' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) present_or_copyin(Var) + while(1); + // expected-error@+2{{OpenACC clause 'create' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) create(Var) + while(1); + // expected-error@+2{{OpenACC clause 'pcreate' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) pcreate(Var) + while(1); + // expected-error@+2{{OpenACC clause 'present_or_create' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) present_or_create(Var) + while(1); + // expected-error@+2{{OpenACC clause 'reduction' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) reduction(+:Var) + while(1); + // expected-error@+2{{OpenACC clause 'collapse' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) collapse(1) + while(1); + // expected-error@+2{{OpenACC clause 'bind' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) bind(Var) + while(1); +#pragma acc kernels device_type(*) vector_length(1) + while(1); +#pragma acc kernels device_type(*) num_gangs(1) + while(1); +#pragma acc kernels device_type(*) num_workers(1) + while(1); + // expected-error@+2{{OpenACC clause 'device_num' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) device_num(1) + while(1); + // expected-error@+2{{OpenACC clause 'default_async' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) default_async(1) + while(1); +#pragma acc kernels device_type(*) async + while(1); + // expected-error@+2{{OpenACC clause 'tile' may not follow a 'device_type' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels device_type(*) tile(Var, 1) + while(1); + // expected-error@+2{{OpenACC clause 'gang' may not follow a 'dtype' clause in a compute construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels dtype(*) gang + while(1); +#pragma acc kernels device_type(*) wait + while(1); +} diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp b/clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp new file mode 100644 index 000000000000..ed40e8bbceae --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-device_type-clause.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +template +void TemplUses() { +#pragma acc parallel device_type(I) + while(true); +#pragma acc parallel dtype(*) + while(true); +#pragma acc parallel device_type(class) + while(true); +#pragma acc parallel device_type(private) + while(true); +#pragma acc parallel device_type(bool) + while(true); +#pragma acc kernels dtype(true) device_type(false) + while(true); + // expected-error@+2{{expected ','}} + // expected-error@+1{{expected identifier}} +#pragma acc parallel device_type(T::value) + while(true); +} + +void Inst() { + TemplUses(); // #INST +} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index ae6659fe95e8..8b9417f985b5 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2857,6 +2857,8 @@ void OpenACCClauseEnqueue::VisitWaitClause(const OpenACCWaitClause &C) { for (Expr *QE : C.getQueueIdExprs()) Visitor.AddStmt(QE); } +void OpenACCClauseEnqueue::VisitDeviceTypeClause( + const OpenACCDeviceTypeClause &C) {} } // namespace void EnqueueVisitor::EnqueueChildren(const OpenACCClause *C) { -- GitLab From 673114447b66335268467396a073cdaaadd0b601 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Mon, 13 May 2024 12:30:50 -0500 Subject: [PATCH 106/578] [LLD] Implement --enable-non-contiguous-regions (#90007) When enabled, input sections that would otherwise overflow a memory region are instead spilled to the next matching output section. This feature parallels the one in GNU LD, but there are some differences from its documented behavior: - /DISCARD/ only matches previously-unmatched sections (i.e., the flag does not affect it). - If a section fails to fit at any of its matches, the link fails instead of discarding the section. - The flag --enable-non-contiguous-regions-warnings is not implemented, as it exists to warn about such occurrences. The implementation places stubs at possible spill locations, and replaces them with the original input section when effecting spills. Spilling decisions occur after address assignment. Sections are spilled in reverse order of assignment, with each spill naively decreasing the size of the affected memory regions. This continues until the memory regions are brought back under size. Spilling anything causes another pass of address assignment, and this continues to fixed point. Spilling after rather than during assignment allows the algorithm to consider the size effects of unspillable input sections that appear later in the assignment. Otherwise, such sections (e.g. thunks) may force an overflow, even if spilling something earlier could have avoided it. A few notable feature interactions occur: - Stubs affect alignment, ONLY_IF_RO, etc, broadly as if a copy of the input section were actually placed there. - SHF_MERGE synthetic sections use the spill list of their first contained input section (the one that gives the section its name). - ICF occurs oblivious to spill sections; spill lists for merged-away sections become inert and are removed after assignment. - SHF_LINK_ORDER and .ARM.exidx are ordered according to the final section ordering, after all spilling has completed. - INSERT BEFORE/AFTER and OVERWRITE_SECTIONS are explicitly disallowed. --- lld/ELF/Config.h | 1 + lld/ELF/Driver.cpp | 4 +- lld/ELF/InputSection.cpp | 7 + lld/ELF/InputSection.h | 25 +- lld/ELF/LinkerScript.cpp | 181 +++++++++++- lld/ELF/LinkerScript.h | 15 +- lld/ELF/Options.td | 3 + lld/ELF/OutputSections.cpp | 7 +- lld/ELF/OutputSections.h | 2 +- lld/ELF/SyntheticSections.cpp | 7 + lld/ELF/SyntheticSections.h | 4 + lld/ELF/Writer.cpp | 22 +- lld/docs/ELF/linker_script.rst | 11 + lld/docs/ReleaseNotes.rst | 6 + lld/docs/ld.lld.1 | 2 + ...able-non-contiguous-regions-arm-exidx.test | 55 ++++ .../enable-non-contiguous-regions.test | 265 ++++++++++++++++++ 17 files changed, 600 insertions(+), 17 deletions(-) create mode 100644 lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test create mode 100644 lld/test/ELF/linkerscript/enable-non-contiguous-regions.test diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index c55b547a733c..dbb81412453a 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -238,6 +238,7 @@ struct Config { bool emitLLVM; bool emitRelocs; bool enableNewDtags; + bool enableNonContiguousRegions; bool executeOnly; bool exportDynamic; bool fixCortexA53Errata843419; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index dd33f4bd772f..828499fa05a3 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1250,6 +1250,8 @@ static void readConfigs(opt::InputArgList &args) { config->emitRelocs = args.hasArg(OPT_emit_relocs); config->enableNewDtags = args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true); + config->enableNonContiguousRegions = + args.hasArg(OPT_enable_non_contiguous_regions); config->entry = args.getLastArgValue(OPT_entry); errorHandler().errorHandlingScript = @@ -3085,7 +3087,7 @@ template void LinkerDriver::link(opt::InputArgList &args) { // sectionBases. for (SectionCommand *cmd : script->sectionCommands) if (auto *osd = dyn_cast(cmd)) - osd->osec.finalizeInputSections(); + osd->osec.finalizeInputSections(script.get()); } // Two input sections with different output sections should not be folded. diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index fa81611e7c9e..2a1ccd997f8b 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -161,6 +161,7 @@ uint64_t SectionBase::getOffset(uint64_t offset) const { } case Regular: case Synthetic: + case Spill: return cast(this)->outSecOff + offset; case EHFrame: { // Two code paths may reach here. First, clang_rt.crtbegin.o and GCC @@ -309,6 +310,12 @@ std::string InputSectionBase::getObjMsg(uint64_t off) const { .str(); } +PotentialSpillSection::PotentialSpillSection(const InputSectionBase &source, + InputSectionDescription &isd) + : InputSection(source.file, source.flags, source.type, source.addralign, {}, + source.name, SectionBase::Spill), + isd(&isd) {} + InputSection InputSection::discarded(nullptr, 0, 0, 0, ArrayRef(), ""); InputSection::InputSection(InputFile *f, uint64_t flags, uint32_t type, diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 1fb7077ca435..58e5306fd6dc 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -48,7 +48,7 @@ template struct RelsOrRelas { // sections. class SectionBase { public: - enum Kind { Regular, Synthetic, EHFrame, Merge, Output }; + enum Kind { Regular, Synthetic, Spill, EHFrame, Merge, Output }; Kind kind() const { return (Kind)sectionKind; } @@ -382,7 +382,8 @@ public: static bool classof(const SectionBase *s) { return s->kind() == SectionBase::Regular || - s->kind() == SectionBase::Synthetic; + s->kind() == SectionBase::Synthetic || + s->kind() == SectionBase::Spill; } // Write this section to a mmap'ed file, assuming Buf is pointing to @@ -425,6 +426,26 @@ private: template void copyShtGroup(uint8_t *buf); }; +// A marker for a potential spill location for another input section. This +// broadly acts as if it were the original section until address assignment. +// Then it is either replaced with the real input section or removed. +class PotentialSpillSection : public InputSection { +public: + // The containing input section description; used to quickly replace this stub + // with the actual section. + InputSectionDescription *isd; + + // Next potential spill location for the same source input section. + PotentialSpillSection *next = nullptr; + + PotentialSpillSection(const InputSectionBase &source, + InputSectionDescription &isd); + + static bool classof(const SectionBase *sec) { + return sec->kind() == InputSectionBase::Spill; + } +}; + static_assert(sizeof(InputSection) <= 160, "InputSection is too big"); class SyntheticSection : public InputSection { diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index c0a5014817b9..3ba59c112b8a 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -304,6 +304,9 @@ getChangedSymbolAssignment(const SymbolAssignmentMap &oldValues) { void LinkerScript::processInsertCommands() { SmallVector moves; for (const InsertCommand &cmd : insertCommands) { + if (config->enableNonContiguousRegions) + error("INSERT cannot be used with --enable-non-contiguous-regions"); + for (StringRef name : cmd.names) { // If base is empty, it may have been discarded by // adjustOutputSections(). We do not handle such output sections. @@ -486,10 +489,12 @@ static void sortInputSections(MutableArrayRef vec, // Compute and remember which sections the InputSectionDescription matches. SmallVector LinkerScript::computeInputSections(const InputSectionDescription *cmd, - ArrayRef sections) { + ArrayRef sections, + const OutputSection &outCmd) { SmallVector ret; SmallVector indexes; DenseSet seen; + DenseSet spills; auto sortByPositionThenCommandLine = [&](size_t begin, size_t end) { llvm::sort(MutableArrayRef(indexes).slice(begin, end - begin)); for (size_t i = begin; i != end; ++i) @@ -505,10 +510,10 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd, size_t sizeBeforeCurrPat = ret.size(); for (size_t i = 0, e = sections.size(); i != e; ++i) { - // Skip if the section is dead or has been matched by a previous input - // section description or a previous pattern. + // Skip if the section is dead or has been matched by a previous pattern + // in this input section description. InputSectionBase *sec = sections[i]; - if (!sec->isLive() || sec->parent || seen.contains(i)) + if (!sec->isLive() || seen.contains(i)) continue; // For --emit-relocs we have to ignore entries like @@ -529,6 +534,29 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd, (sec->flags & cmd->withoutFlags) != 0) continue; + if (sec->parent) { + // Skip if not allowing multiple matches. + if (!config->enableNonContiguousRegions) + continue; + + // Disallow spilling into /DISCARD/; special handling would be needed + // for this in address assignment, and the semantics are nebulous. + if (outCmd.name == "/DISCARD/") + continue; + + // Skip if the section's first match was /DISCARD/; such sections are + // always discarded. + if (sec->parent->name == "/DISCARD/") + continue; + + // Skip if the section was already matched by a different input section + // description within this output section. + if (sec->parent == &outCmd) + continue; + + spills.insert(sec); + } + ret.push_back(sec); indexes.push_back(i); seen.insert(i); @@ -555,6 +583,30 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd, // Matched sections after the last SORT* are sorted by (--sort-alignment, // input order). sortByPositionThenCommandLine(sizeAfterPrevSort, ret.size()); + + // The flag --enable-non-contiguous-regions may cause sections to match an + // InputSectionDescription in more than one OutputSection. Matches after the + // first were collected in the spills set, so replace these with potential + // spill sections. + if (!spills.empty()) { + for (InputSectionBase *&sec : ret) { + if (!spills.contains(sec)) + continue; + + // Append the spill input section to the list for the input section, + // creating it if necessary. + PotentialSpillSection *pss = make( + *sec, const_cast(*cmd)); + auto [it, inserted] = + potentialSpillLists.try_emplace(sec, PotentialSpillList{pss, pss}); + if (!inserted) { + PotentialSpillSection *&tail = it->second.tail; + tail = tail->next = pss; + } + sec = pss; + } + } + return ret; } @@ -577,7 +629,7 @@ void LinkerScript::discardSynthetic(OutputSection &outCmd) { part.armExidx->exidxSections.end()); for (SectionCommand *cmd : outCmd.commands) if (auto *isd = dyn_cast(cmd)) - for (InputSectionBase *s : computeInputSections(isd, secs)) + for (InputSectionBase *s : computeInputSections(isd, secs, outCmd)) discard(*s); } } @@ -588,7 +640,7 @@ LinkerScript::createInputSectionList(OutputSection &outCmd) { for (SectionCommand *cmd : outCmd.commands) { if (auto *isd = dyn_cast(cmd)) { - isd->sectionBases = computeInputSections(isd, ctx.inputSections); + isd->sectionBases = computeInputSections(isd, ctx.inputSections, outCmd); for (InputSectionBase *s : isd->sectionBases) s->parent = &outCmd; ret.insert(ret.end(), isd->sectionBases.begin(), isd->sectionBases.end()); @@ -644,6 +696,9 @@ void LinkerScript::processSectionCommands() { // Process OVERWRITE_SECTIONS first so that it can overwrite the main script // or orphans. + if (config->enableNonContiguousRegions && !overwriteSections.empty()) + error("OVERWRITE_SECTIONS cannot be used with " + "--enable-non-contiguous-regions"); DenseMap map; size_t i = 0; for (OutputDesc *osd : overwriteSections) { @@ -1066,8 +1121,12 @@ void LinkerScript::assignOffsets(OutputSection *sec) { // Handle a single input section description command. // It calculates and assigns the offsets for each section and also // updates the output section size. - for (InputSection *isec : cast(cmd)->sections) { + + auto §ions = cast(cmd)->sections; + for (InputSection *isec : sections) { assert(isec->getParent() == sec); + if (isa(isec)) + continue; const uint64_t pos = dot; dot = alignToPowerOf2(dot, isec->addralign); isec->outSecOff = dot - sec->addr; @@ -1364,6 +1423,114 @@ const Defined *LinkerScript::assignAddresses() { return getChangedSymbolAssignment(oldValues); } +static bool hasRegionOverflowed(MemoryRegion *mr) { + if (!mr) + return false; + return mr->curPos - mr->getOrigin() > mr->getLength(); +} + +// Spill input sections in reverse order of address assignment to (potentially) +// bring memory regions out of overflow. The size savings of a spill can only be +// estimated, since general linker script arithmetic may occur afterwards. +// Under-estimates may cause unnecessary spills, but over-estimates can always +// be corrected on the next pass. +bool LinkerScript::spillSections() { + if (!config->enableNonContiguousRegions) + return false; + + bool spilled = false; + for (SectionCommand *cmd : reverse(sectionCommands)) { + auto *od = dyn_cast(cmd); + if (!od) + continue; + OutputSection *osec = &od->osec; + if (!osec->memRegion) + continue; + + // Input sections that have replaced a potential spill and should be removed + // from their input section description. + DenseSet spilledInputSections; + + for (SectionCommand *cmd : reverse(osec->commands)) { + if (!hasRegionOverflowed(osec->memRegion) && + !hasRegionOverflowed(osec->lmaRegion)) + break; + + auto *isd = dyn_cast(cmd); + if (!isd) + continue; + for (InputSection *isec : reverse(isd->sections)) { + // Potential spill locations cannot be spilled. + if (isa(isec)) + continue; + + // Find the next potential spill location and remove it from the list. + auto it = potentialSpillLists.find(isec); + if (it == potentialSpillLists.end()) + continue; + PotentialSpillList &list = it->second; + PotentialSpillSection *spill = list.head; + if (spill->next) + list.head = spill->next; + else + potentialSpillLists.erase(isec); + + // Replace the next spill location with the spilled section and adjust + // its properties to match the new location. Note that the alignment of + // the spill section may have diverged from the original due to e.g. a + // SUBALIGN. Correct assignment requires the spill's alignment to be + // used, not the original. + spilledInputSections.insert(isec); + *llvm::find(spill->isd->sections, spill) = isec; + isec->parent = spill->parent; + isec->addralign = spill->addralign; + + // Record the (potential) reduction in the region's end position. + osec->memRegion->curPos -= isec->getSize(); + if (osec->lmaRegion) + osec->lmaRegion->curPos -= isec->getSize(); + + // Spilling continues until the end position no longer overflows the + // region. Then, another round of address assignment will either confirm + // the spill's success or lead to yet more spilling. + if (!hasRegionOverflowed(osec->memRegion) && + !hasRegionOverflowed(osec->lmaRegion)) + break; + } + + // Remove any spilled input sections to complete their move. + if (!spilledInputSections.empty()) { + spilled = true; + llvm::erase_if(isd->sections, [&](InputSection *isec) { + return spilledInputSections.contains(isec); + }); + } + } + } + + return spilled; +} + +// Erase any potential spill sections that were not used. +void LinkerScript::erasePotentialSpillSections() { + if (potentialSpillLists.empty()) + return; + + // Collect the set of input section descriptions that contain potential + // spills. + DenseSet isds; + for (const auto &[_, list] : potentialSpillLists) + for (PotentialSpillSection *s = list.head; s; s = s->next) + isds.insert(s->isd); + + for (InputSectionDescription *isd : isds) + llvm::erase_if(isd->sections, [](InputSection *s) { + return isa(s); + }); + + potentialSpillLists.clear(); +} + // Creates program headers as instructed by PHDRS linker script command. SmallVector LinkerScript::createPhdrs() { SmallVector ret; diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index b09cd12c46f9..734d4e7498aa 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -10,6 +10,7 @@ #define LLD_ELF_LINKER_SCRIPT_H #include "Config.h" +#include "InputSection.h" #include "Writer.h" #include "lld/Common/LLVM.h" #include "lld/Common/Strings.h" @@ -287,7 +288,8 @@ class LinkerScript final { SmallVector computeInputSections(const InputSectionDescription *, - ArrayRef); + ArrayRef, + const OutputSection &outCmd); SmallVector createInputSectionList(OutputSection &cmd); @@ -333,6 +335,8 @@ public: bool shouldKeep(InputSectionBase *s); const Defined *assignAddresses(); + bool spillSections(); + void erasePotentialSpillSections(); void allocateHeaders(SmallVector &phdrs); void processSectionCommands(); void processSymbolAssignments(); @@ -400,6 +404,15 @@ public: // // then provideMap should contain the mapping: 'v' -> ['a', 'b', 'c'] llvm::MapVector> provideMap; + + // List of potential spill locations (PotentialSpillSection) for an input + // section. + struct PotentialSpillList { + // Never nullptr. + PotentialSpillSection *head; + PotentialSpillSection *tail; + }; + llvm::DenseMap potentialSpillLists; }; struct ScriptWrapper { diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index b9e05a4b1fd5..883a6079bf50 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -197,6 +197,9 @@ def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">; def enable_new_dtags: F<"enable-new-dtags">, HelpText<"Enable new dynamic tags (default)">; +def enable_non_contiguous_regions : FF<"enable-non-contiguous-regions">, + HelpText<"Spill input sections to later matching output sections to avoid memory region overflow">; + def end_group: F<"end-group">, HelpText<"Ignored for compatibility with GNU unless you pass --warn-backrefs">; diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 9c667241360f..fcb4c4387aa9 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -186,7 +186,7 @@ static MergeSyntheticSection *createMergeSynthetic(StringRef name, // new synthetic sections at the location of the first input section // that it replaces. It then finalizes each synthetic section in order // to compute an output offset for each piece of each input section. -void OutputSection::finalizeInputSections() { +void OutputSection::finalizeInputSections(LinkerScript *script) { std::vector mergeSections; for (SectionCommand *cmd : commands) { auto *isd = dyn_cast(cmd); @@ -226,6 +226,11 @@ void OutputSection::finalizeInputSections() { i = std::prev(mergeSections.end()); syn->entsize = ms->entsize; isd->sections.push_back(syn); + // The merge synthetic section inherits the potential spill locations of + // its first contained section. + auto it = script->potentialSpillLists.find(ms); + if (it != script->potentialSpillLists.end()) + script->potentialSpillLists.try_emplace(syn, it->second); } (*i)->addSection(ms); } diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 421a0181feb5..78fede48a23f 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -75,7 +75,7 @@ public: void recordSection(InputSectionBase *isec); void commitSection(InputSection *isec); - void finalizeInputSections(); + void finalizeInputSections(LinkerScript *script = nullptr); // The following members are normally only used in linker scripts. MemoryRegion *memRegion = nullptr; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 7b9ada40c0f6..298c714adb3b 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4074,6 +4074,13 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) { // InputSection with the highest address and any InputSections that have // mergeable .ARM.exidx table entries are removed from it. void ARMExidxSyntheticSection::finalizeContents() { + // Ensure that any fixed-point iterations after the first see the original set + // of sections. + if (!originalExecutableSections.empty()) + executableSections = originalExecutableSections; + else if (config->enableNonContiguousRegions) + originalExecutableSections = executableSections; + // The executableSections and exidxSections that we use to derive the final // contents of this SyntheticSection are populated before // processSectionCommands() and ICF. A /DISCARD/ entry in SECTIONS command or diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 995fd4b344b0..34949025a45f 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1255,6 +1255,10 @@ private: // either find the .ARM.exidx section or know that we need to generate one. SmallVector executableSections; + // Value of executableSecitons before finalizeContents(), so that it can be + // run repeateadly during fixed point iteration. + SmallVector originalExecutableSections; + // The executable InputSection with the highest address to use for the // sentinel. We store separately from ExecutableSections as merging of // duplicate entries may mean this InputSection is removed from diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index e400ed2ae945..8d529f2bdb9f 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1403,13 +1403,18 @@ template void Writer::finalizeAddressDependentContent() { AArch64Err843419Patcher a64p; ARMErr657417Patcher a32p; script->assignAddresses(); + // .ARM.exidx and SHF_LINK_ORDER do not require precise addresses, but they // do require the relative addresses of OutputSections because linker scripts // can assign Virtual Addresses to OutputSections that are not monotonically - // increasing. - for (Partition &part : partitions) - finalizeSynthetic(part.armExidx.get()); - resolveShfLinkOrder(); + // increasing. Anything here must be repeatable, since spilling may change + // section order. + const auto finalizeOrderDependentContent = [this] { + for (Partition &part : partitions) + finalizeSynthetic(part.armExidx.get()); + resolveShfLinkOrder(); + }; + finalizeOrderDependentContent(); // Converts call x@GDPLT to call __tls_get_addr if (config->emachine == EM_HEXAGON) @@ -1419,6 +1424,8 @@ template void Writer::finalizeAddressDependentContent() { for (;;) { bool changed = target->needsThunks ? tc.createThunks(pass, outputSections) : target->relaxOnce(pass); + bool spilled = script->spillSections(); + changed |= spilled; ++pass; // With Thunk Size much smaller than branch range we expect to @@ -1464,6 +1471,9 @@ template void Writer::finalizeAddressDependentContent() { " does not converge"); break; } + } else if (spilled) { + // Spilling can change relative section order. + finalizeOrderDependentContent(); } } if (!config->relocatable) @@ -1483,6 +1493,10 @@ template void Writer::finalizeAddressDependentContent() { osec->name + " is not a multiple of alignment (" + Twine(osec->addralign) + ")"); } + + // Sizes are no longer allowed to grow, so all allowable spills have been + // taken. Remove any leftover potential spills. + script->erasePotentialSpillSections(); } // If Input Sections have been shrunk (basic block sections) then diff --git a/lld/docs/ELF/linker_script.rst b/lld/docs/ELF/linker_script.rst index 3606ef4fe4b8..7a35534be096 100644 --- a/lld/docs/ELF/linker_script.rst +++ b/lld/docs/ELF/linker_script.rst @@ -197,3 +197,14 @@ the current location to a max-page-size boundary, ensuring that the next LLD will insert ``.relro_padding`` immediately before the symbol assignment using ``DATA_SEGMENT_RELRO_END``. + +Non-contiguous regions +~~~~~~~~~~~~~~~~~~~~~~ + +The flag ``--enable-non-contiguous-regions`` allows input sections to spill to +later matches rather than causing the link to fail by overflowing a memory +region. Unlike GNU ld, ``/DISCARD/`` only matches previously-unmatched sections +(i.e., the flag does not affect it). Also, if a section fails to fit at any of +its matches, the link fails instead of discarding the section. Accordingly, the +GNU flag ``--enable-non-contiguous-regions-warnings`` is not implemented, as it +exists to warn about such occurrences. diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index f8fdebfeaecf..e7a913e025da 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -38,6 +38,12 @@ ELF Improvements * ``--debug-names`` is added to create a merged ``.debug_names`` index from input ``.debug_names`` sections. Type units are not handled yet. (`#86508 `_) +* ``--enable-non-contiguous-regions`` option allows automatically packing input + sections into memory regions by automatically spilling to later matches if a + region would overflow. This reduces the toil of manually packing regions + (typical for embedded). It also makes full LTO feasible in such cases, since + IR merging currently prevents the linker script from referring to input + files. (`#90007 `_) Breaking changes ---------------- diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index 9ea1a9c52f2a..0df13f07f560 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -222,6 +222,8 @@ segment header. Generate relocations in the output. .It Fl -enable-new-dtags Enable new dynamic tags. +.It Fl -enable-non-contiguous-regions +Spill input sections to later matching output sections to avoid memory region overflow. .It Fl -end-lib End a grouping of objects that should be treated as if they were together in an archive. diff --git a/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test b/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test new file mode 100644 index 000000000000..3f7b9c4e5f8b --- /dev/null +++ b/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test @@ -0,0 +1,55 @@ +## When spilling reorders input sections, the .ARM.exidx table is rebuilt using +## the new order. + +# REQUIRES: arm +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi test.s -o test.o +# RUN: ld.lld -T test.ld test.o -o test --enable-non-contiguous-regions +# RUN: llvm-readobj -x .ARM.exidx test | FileCheck %s + +# CHECK: 20000000 08849780 1c000000 10849880 +# CHECK-NEXT: 1c000000 01000000 + +#--- test.ld +MEMORY { + exidx : ORIGIN = 0, LENGTH = 32 + a : ORIGIN = 32, LENGTH = 4 + b : ORIGIN = 36, LENGTH = 4 + c : ORIGIN = 40, LENGTH = 4 +} + +SECTIONS { + .ARM.exidx : { *(.ARM.exidx) } >exidx + .first_chance : { *(.text .text.f2) } >a + .text.f1 : { *(.text.f1) } >b + .last_chance : { *(.text.f2) } >c +} + +#--- test.s + .syntax unified + .section .text, "ax",%progbits + .globl _start +_start: + .fnstart + bx lr + .save {r7, lr} + .setfp r7, sp, #0 + .fnend + + .section .text.f1, "ax", %progbits + .globl f1 +f1: + .fnstart + bx lr + .save {r8, lr} + .setfp r8, sp, #0 + .fnend + + .section .text.f2, "ax", %progbits + .globl f2 +f2: + .fnstart + bx lr + .save {r8, lr} + .setfp r8, sp, #0 + .fnend diff --git a/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test b/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test new file mode 100644 index 000000000000..392106fd476f --- /dev/null +++ b/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test @@ -0,0 +1,265 @@ +# REQUIRES: x86 + +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -n -filetype=obj -triple=x86_64 spill.s -o spill.o + +## An input section spills to a later match when the region of its first match +## would overflow. The spill uses the alignment of the later match. + +# RUN: ld.lld -T spill.ld spill.o -o spill --enable-non-contiguous-regions +# RUN: llvm-readelf -S spill | FileCheck %s --check-prefix=SPILL + +# SPILL: Name Type Address Off Size +# SPILL: .first_chance PROGBITS 0000000000000000 001000 000001 +# SPILL-NEXT: .last_chance PROGBITS 0000000000000008 001008 000002 + +## A spill off the end still fails the link. + +# RUN: not ld.lld -T spill-fail.ld spill.o --enable-non-contiguous-regions 2>&1 |\ +# RUN: FileCheck %s --check-prefix=SPILL-FAIL --implicit-check-not=error: + +# SPILL-FAIL: error: section '.last_chance' will not fit in region 'b': overflowed by 2 bytes + +## The above spill still occurs when the LMA would overflow, even though the +## VMA would fit. + +# RUN: ld.lld -T spill-lma.ld spill.o -o spill-lma --enable-non-contiguous-regions +# RUN: llvm-readelf -S spill-lma | FileCheck %s --check-prefix=SPILL-LMA + +# SPILL-LMA: Name Type Address Off Size +# SPILL-LMA: .first_chance PROGBITS 0000000000000000 001000 000001 +# SPILL-LMA-NEXT: .last_chance PROGBITS 0000000000000003 001003 000002 + +## A spill occurs to an additional match after the first. + +# RUN: ld.lld -T spill-later.ld spill.o -o spill-later --enable-non-contiguous-regions +# RUN: llvm-readelf -S spill-later | FileCheck %s --check-prefix=SPILL-LATER + +# SPILL-LATER: Name Type Address Off Size +# SPILL-LATER: .first_chance PROGBITS 0000000000000000 001000 000001 +# SPILL-LATER-NEXT: .second_chance PROGBITS 0000000000000002 001001 000000 +# SPILL-LATER-NEXT: .last_chance PROGBITS 0000000000000003 001003 000002 + +## A later overflow causes an earlier section to spill. + +# RUN: ld.lld -T spill-earlier.ld spill.o -o spill-earlier --enable-non-contiguous-regions +# RUN: llvm-readelf -S spill-earlier | FileCheck %s --check-prefix=SPILL-EARLIER + +# SPILL-EARLIER: Name Type Address Off Size +# SPILL-EARLIER: .first_chance PROGBITS 0000000000000000 001000 000002 +# SPILL-EARLIER-NEXT: .last_chance PROGBITS 0000000000000002 001002 000001 + +## An additional match in /DISCARD/ has no effect. + +# RUN: not ld.lld -T no-spill-into-discard.ld spill.o --enable-non-contiguous-regions 2>&1 |\ +# RUN: FileCheck %s --check-prefix=NO-SPILL-INTO-DISCARD --implicit-check-not=error: + +# NO-SPILL-INTO-DISCARD: error: section '.osec' will not fit in region 'a': overflowed by 1 bytes + +## An additional match after /DISCARD/ has no effect. + +# RUN: ld.lld -T no-spill-from-discard.ld spill.o -o no-spill-from-discard --enable-non-contiguous-regions +# RUN: llvm-readelf -S no-spill-from-discard | FileCheck %s --check-prefix=NO-SPILL-FROM-DISCARD + +# NO-SPILL-FROM-DISCARD: Name Type Address Off Size +# NO-SPILL-FROM-DISCARD-NOT: .osec + +## SHF_MERGEd sections are spilled according to the matches of the first merged +## input section (the one giving the resulting section its name). + +# RUN: llvm-mc -n -filetype=obj -triple=x86_64 merge.s -o merge.o +# RUN: ld.lld -T spill-merge.ld merge.o -o spill-merge --enable-non-contiguous-regions +# RUN: llvm-readelf -S spill-merge | FileCheck %s --check-prefix=SPILL-MERGE + +# SPILL-MERGE: Name Type Address Off Size +# SPILL-MERGE: .first PROGBITS 0000000000000000 000190 000000 +# SPILL-MERGE-NEXT: .second PROGBITS 0000000000000001 001001 000002 +# SPILL-MERGE-NEXT: .third PROGBITS 0000000000000003 001003 000000 + +## An error is reported for INSERT. + +# RUN: not ld.lld -T insert.ld spill.o --enable-non-contiguous-regions 2>&1 |\ +# RUN: FileCheck %s --check-prefix=INSERT + +# INSERT: error: INSERT cannot be used with --enable-non-contiguous-regions + +## An error is reported for OVERWRITE_SECTIONS. + +# RUN: not ld.lld -T overwrite-sections.ld spill.o --enable-non-contiguous-regions 2>&1 |\ +# RUN: FileCheck %s --check-prefix=OVERWRITE_SECTIONS + +# OVERWRITE_SECTIONS: error: OVERWRITE_SECTIONS cannot be used with --enable-non-contiguous-regions + +## SHF_LINK_ORDER is reordered when spilling changes relative section order. + +# RUN: llvm-mc -n -filetype=obj -triple=x86_64 link-order.s -o link-order.o +# RUN: ld.lld -T link-order.ld link-order.o -o link-order --enable-non-contiguous-regions +# RUN: llvm-readobj -x .order link-order | FileCheck %s --check-prefix=LINK-ORDER + +# LINK-ORDER: 020301 + +#--- spill.s +.section .one_byte_section,"a",@progbits +.fill 1 + +.section .two_byte_section,"a",@progbits +.fill 2 + +#--- spill.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 2 + b : ORIGIN = 2, LENGTH = 16 +} + +SECTIONS { + .first_chance : SUBALIGN(1) { *(.one_byte_section) *(.two_byte_section) } >a + .last_chance : SUBALIGN(8) { *(.two_byte_section) } >b +} + +#--- spill-fail.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 1 + b : ORIGIN = 2, LENGTH = 0 +} + +SECTIONS { + .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a + .last_chance : { *(.two_byte_section) } >b +} + +#--- spill-lma.ld +MEMORY { + vma_a : ORIGIN = 0, LENGTH = 3 + vma_b : ORIGIN = 3, LENGTH = 3 + lma_a : ORIGIN = 6, LENGTH = 2 + lma_b : ORIGIN = 8, LENGTH = 2 +} + +SECTIONS { + .first_chance : { *(.one_byte_section) *(.two_byte_section) } >vma_a AT>lma_a + .last_chance : { *(.two_byte_section) } >vma_b AT>lma_b +} + +#--- spill-later.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 2 + b : ORIGIN = 2, LENGTH = 1 + c : ORIGIN = 3, LENGTH = 2 +} + +SECTIONS { + .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a + .second_chance : { *(.two_byte_section) } >b + .last_chance : { *(.two_byte_section) } >c +} + +#--- spill-earlier.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 2 + b : ORIGIN = 2, LENGTH = 1 +} + +SECTIONS { + .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a + .last_chance : { *(.one_byte_section) } >b +} + +#--- no-spill-into-discard.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 1 +} + +SECTIONS { + .osec : { *(.two_byte_section) } >a + /DISCARD/ : { *(.one_byte_section) *(.two_byte_section) } +} + +#--- no-spill-from-discard.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 2 +} + +SECTIONS { + /DISCARD/ : { *(.one_byte_section) *(.two_byte_section) } + .osec : { *(.two_byte_section) } >a +} + +#--- merge.s +.section .a,"aM",@progbits,1 +.byte 0x12, 0x34 + +.section .b,"aM",@progbits,1 +.byte 0x12 + +#--- spill-merge.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 1 + b : ORIGIN = 1, LENGTH = 2 + c : ORIGIN = 3, LENGTH = 2 +} + +SECTIONS { + .first : { *(.a) *(.b) } >a + .second : { *(.a) } >b + .third : { *(.b) } >c +} + +#--- insert.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 1 +} + +SECTIONS { + .a : { *(.two_byte_section) } >a +} + +SECTIONS { + .b : { *(.one_byte_section) } >a +} INSERT AFTER .a; + +#--- overwrite-sections.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 1 +} + +SECTIONS { + .a : { *(.two_byte_section) } >a +} + +OVERWRITE_SECTIONS { + .b : { *(.one_byte_section) } >a +} + +#--- link-order.s +.section .a,"a",@progbits +.fill 1 + +.section .b,"a",@progbits +.fill 1 + +.section .c,"a",@progbits +.fill 1 + +.section .link_order.a,"ao",@progbits,.a +.byte 1 + +.section .link_order.b,"ao",@progbits,.b +.byte 2 + +.section .link_order.c,"ao",@progbits,.c +.byte 3 + +#--- link-order.ld +MEMORY { + order : ORIGIN = 0, LENGTH = 3 + potential_a : ORIGIN = 3, LENGTH = 0 + bc : ORIGIN = 3, LENGTH = 2 + actual_a : ORIGIN = 5, LENGTH = 1 +} + +SECTIONS { + .order : { *(.link_order.*) } > order + .potential_a : { *(.a) } >potential_a + .bc : { *(.b) *(.c) } >bc + .actual_a : { *(.a) } >actual_a +} -- GitLab From 81f34afa5c39584c2721000e2bcf3b8ec02a4f4d Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Mon, 13 May 2024 12:38:40 -0500 Subject: [PATCH 107/578] Revert "[LLD] Implement --enable-non-contiguous-regions" (#92005) Reverts llvm/llvm-project#90007 Broke in merging I think. --- lld/ELF/Config.h | 1 - lld/ELF/Driver.cpp | 4 +- lld/ELF/InputSection.cpp | 7 - lld/ELF/InputSection.h | 25 +- lld/ELF/LinkerScript.cpp | 181 +----------- lld/ELF/LinkerScript.h | 15 +- lld/ELF/Options.td | 3 - lld/ELF/OutputSections.cpp | 7 +- lld/ELF/OutputSections.h | 2 +- lld/ELF/SyntheticSections.cpp | 7 - lld/ELF/SyntheticSections.h | 4 - lld/ELF/Writer.cpp | 22 +- lld/docs/ELF/linker_script.rst | 11 - lld/docs/ReleaseNotes.rst | 6 - lld/docs/ld.lld.1 | 2 - ...able-non-contiguous-regions-arm-exidx.test | 55 ---- .../enable-non-contiguous-regions.test | 265 ------------------ 17 files changed, 17 insertions(+), 600 deletions(-) delete mode 100644 lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test delete mode 100644 lld/test/ELF/linkerscript/enable-non-contiguous-regions.test diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index dbb81412453a..c55b547a733c 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -238,7 +238,6 @@ struct Config { bool emitLLVM; bool emitRelocs; bool enableNewDtags; - bool enableNonContiguousRegions; bool executeOnly; bool exportDynamic; bool fixCortexA53Errata843419; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 828499fa05a3..dd33f4bd772f 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1250,8 +1250,6 @@ static void readConfigs(opt::InputArgList &args) { config->emitRelocs = args.hasArg(OPT_emit_relocs); config->enableNewDtags = args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true); - config->enableNonContiguousRegions = - args.hasArg(OPT_enable_non_contiguous_regions); config->entry = args.getLastArgValue(OPT_entry); errorHandler().errorHandlingScript = @@ -3087,7 +3085,7 @@ template void LinkerDriver::link(opt::InputArgList &args) { // sectionBases. for (SectionCommand *cmd : script->sectionCommands) if (auto *osd = dyn_cast(cmd)) - osd->osec.finalizeInputSections(script.get()); + osd->osec.finalizeInputSections(); } // Two input sections with different output sections should not be folded. diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 2a1ccd997f8b..fa81611e7c9e 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -161,7 +161,6 @@ uint64_t SectionBase::getOffset(uint64_t offset) const { } case Regular: case Synthetic: - case Spill: return cast(this)->outSecOff + offset; case EHFrame: { // Two code paths may reach here. First, clang_rt.crtbegin.o and GCC @@ -310,12 +309,6 @@ std::string InputSectionBase::getObjMsg(uint64_t off) const { .str(); } -PotentialSpillSection::PotentialSpillSection(const InputSectionBase &source, - InputSectionDescription &isd) - : InputSection(source.file, source.flags, source.type, source.addralign, {}, - source.name, SectionBase::Spill), - isd(&isd) {} - InputSection InputSection::discarded(nullptr, 0, 0, 0, ArrayRef(), ""); InputSection::InputSection(InputFile *f, uint64_t flags, uint32_t type, diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 58e5306fd6dc..1fb7077ca435 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -48,7 +48,7 @@ template struct RelsOrRelas { // sections. class SectionBase { public: - enum Kind { Regular, Synthetic, Spill, EHFrame, Merge, Output }; + enum Kind { Regular, Synthetic, EHFrame, Merge, Output }; Kind kind() const { return (Kind)sectionKind; } @@ -382,8 +382,7 @@ public: static bool classof(const SectionBase *s) { return s->kind() == SectionBase::Regular || - s->kind() == SectionBase::Synthetic || - s->kind() == SectionBase::Spill; + s->kind() == SectionBase::Synthetic; } // Write this section to a mmap'ed file, assuming Buf is pointing to @@ -426,26 +425,6 @@ private: template void copyShtGroup(uint8_t *buf); }; -// A marker for a potential spill location for another input section. This -// broadly acts as if it were the original section until address assignment. -// Then it is either replaced with the real input section or removed. -class PotentialSpillSection : public InputSection { -public: - // The containing input section description; used to quickly replace this stub - // with the actual section. - InputSectionDescription *isd; - - // Next potential spill location for the same source input section. - PotentialSpillSection *next = nullptr; - - PotentialSpillSection(const InputSectionBase &source, - InputSectionDescription &isd); - - static bool classof(const SectionBase *sec) { - return sec->kind() == InputSectionBase::Spill; - } -}; - static_assert(sizeof(InputSection) <= 160, "InputSection is too big"); class SyntheticSection : public InputSection { diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 3ba59c112b8a..c0a5014817b9 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -304,9 +304,6 @@ getChangedSymbolAssignment(const SymbolAssignmentMap &oldValues) { void LinkerScript::processInsertCommands() { SmallVector moves; for (const InsertCommand &cmd : insertCommands) { - if (config->enableNonContiguousRegions) - error("INSERT cannot be used with --enable-non-contiguous-regions"); - for (StringRef name : cmd.names) { // If base is empty, it may have been discarded by // adjustOutputSections(). We do not handle such output sections. @@ -489,12 +486,10 @@ static void sortInputSections(MutableArrayRef vec, // Compute and remember which sections the InputSectionDescription matches. SmallVector LinkerScript::computeInputSections(const InputSectionDescription *cmd, - ArrayRef sections, - const OutputSection &outCmd) { + ArrayRef sections) { SmallVector ret; SmallVector indexes; DenseSet seen; - DenseSet spills; auto sortByPositionThenCommandLine = [&](size_t begin, size_t end) { llvm::sort(MutableArrayRef(indexes).slice(begin, end - begin)); for (size_t i = begin; i != end; ++i) @@ -510,10 +505,10 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd, size_t sizeBeforeCurrPat = ret.size(); for (size_t i = 0, e = sections.size(); i != e; ++i) { - // Skip if the section is dead or has been matched by a previous pattern - // in this input section description. + // Skip if the section is dead or has been matched by a previous input + // section description or a previous pattern. InputSectionBase *sec = sections[i]; - if (!sec->isLive() || seen.contains(i)) + if (!sec->isLive() || sec->parent || seen.contains(i)) continue; // For --emit-relocs we have to ignore entries like @@ -534,29 +529,6 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd, (sec->flags & cmd->withoutFlags) != 0) continue; - if (sec->parent) { - // Skip if not allowing multiple matches. - if (!config->enableNonContiguousRegions) - continue; - - // Disallow spilling into /DISCARD/; special handling would be needed - // for this in address assignment, and the semantics are nebulous. - if (outCmd.name == "/DISCARD/") - continue; - - // Skip if the section's first match was /DISCARD/; such sections are - // always discarded. - if (sec->parent->name == "/DISCARD/") - continue; - - // Skip if the section was already matched by a different input section - // description within this output section. - if (sec->parent == &outCmd) - continue; - - spills.insert(sec); - } - ret.push_back(sec); indexes.push_back(i); seen.insert(i); @@ -583,30 +555,6 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd, // Matched sections after the last SORT* are sorted by (--sort-alignment, // input order). sortByPositionThenCommandLine(sizeAfterPrevSort, ret.size()); - - // The flag --enable-non-contiguous-regions may cause sections to match an - // InputSectionDescription in more than one OutputSection. Matches after the - // first were collected in the spills set, so replace these with potential - // spill sections. - if (!spills.empty()) { - for (InputSectionBase *&sec : ret) { - if (!spills.contains(sec)) - continue; - - // Append the spill input section to the list for the input section, - // creating it if necessary. - PotentialSpillSection *pss = make( - *sec, const_cast(*cmd)); - auto [it, inserted] = - potentialSpillLists.try_emplace(sec, PotentialSpillList{pss, pss}); - if (!inserted) { - PotentialSpillSection *&tail = it->second.tail; - tail = tail->next = pss; - } - sec = pss; - } - } - return ret; } @@ -629,7 +577,7 @@ void LinkerScript::discardSynthetic(OutputSection &outCmd) { part.armExidx->exidxSections.end()); for (SectionCommand *cmd : outCmd.commands) if (auto *isd = dyn_cast(cmd)) - for (InputSectionBase *s : computeInputSections(isd, secs, outCmd)) + for (InputSectionBase *s : computeInputSections(isd, secs)) discard(*s); } } @@ -640,7 +588,7 @@ LinkerScript::createInputSectionList(OutputSection &outCmd) { for (SectionCommand *cmd : outCmd.commands) { if (auto *isd = dyn_cast(cmd)) { - isd->sectionBases = computeInputSections(isd, ctx.inputSections, outCmd); + isd->sectionBases = computeInputSections(isd, ctx.inputSections); for (InputSectionBase *s : isd->sectionBases) s->parent = &outCmd; ret.insert(ret.end(), isd->sectionBases.begin(), isd->sectionBases.end()); @@ -696,9 +644,6 @@ void LinkerScript::processSectionCommands() { // Process OVERWRITE_SECTIONS first so that it can overwrite the main script // or orphans. - if (config->enableNonContiguousRegions && !overwriteSections.empty()) - error("OVERWRITE_SECTIONS cannot be used with " - "--enable-non-contiguous-regions"); DenseMap map; size_t i = 0; for (OutputDesc *osd : overwriteSections) { @@ -1121,12 +1066,8 @@ void LinkerScript::assignOffsets(OutputSection *sec) { // Handle a single input section description command. // It calculates and assigns the offsets for each section and also // updates the output section size. - - auto §ions = cast(cmd)->sections; - for (InputSection *isec : sections) { + for (InputSection *isec : cast(cmd)->sections) { assert(isec->getParent() == sec); - if (isa(isec)) - continue; const uint64_t pos = dot; dot = alignToPowerOf2(dot, isec->addralign); isec->outSecOff = dot - sec->addr; @@ -1423,114 +1364,6 @@ const Defined *LinkerScript::assignAddresses() { return getChangedSymbolAssignment(oldValues); } -static bool hasRegionOverflowed(MemoryRegion *mr) { - if (!mr) - return false; - return mr->curPos - mr->getOrigin() > mr->getLength(); -} - -// Spill input sections in reverse order of address assignment to (potentially) -// bring memory regions out of overflow. The size savings of a spill can only be -// estimated, since general linker script arithmetic may occur afterwards. -// Under-estimates may cause unnecessary spills, but over-estimates can always -// be corrected on the next pass. -bool LinkerScript::spillSections() { - if (!config->enableNonContiguousRegions) - return false; - - bool spilled = false; - for (SectionCommand *cmd : reverse(sectionCommands)) { - auto *od = dyn_cast(cmd); - if (!od) - continue; - OutputSection *osec = &od->osec; - if (!osec->memRegion) - continue; - - // Input sections that have replaced a potential spill and should be removed - // from their input section description. - DenseSet spilledInputSections; - - for (SectionCommand *cmd : reverse(osec->commands)) { - if (!hasRegionOverflowed(osec->memRegion) && - !hasRegionOverflowed(osec->lmaRegion)) - break; - - auto *isd = dyn_cast(cmd); - if (!isd) - continue; - for (InputSection *isec : reverse(isd->sections)) { - // Potential spill locations cannot be spilled. - if (isa(isec)) - continue; - - // Find the next potential spill location and remove it from the list. - auto it = potentialSpillLists.find(isec); - if (it == potentialSpillLists.end()) - continue; - PotentialSpillList &list = it->second; - PotentialSpillSection *spill = list.head; - if (spill->next) - list.head = spill->next; - else - potentialSpillLists.erase(isec); - - // Replace the next spill location with the spilled section and adjust - // its properties to match the new location. Note that the alignment of - // the spill section may have diverged from the original due to e.g. a - // SUBALIGN. Correct assignment requires the spill's alignment to be - // used, not the original. - spilledInputSections.insert(isec); - *llvm::find(spill->isd->sections, spill) = isec; - isec->parent = spill->parent; - isec->addralign = spill->addralign; - - // Record the (potential) reduction in the region's end position. - osec->memRegion->curPos -= isec->getSize(); - if (osec->lmaRegion) - osec->lmaRegion->curPos -= isec->getSize(); - - // Spilling continues until the end position no longer overflows the - // region. Then, another round of address assignment will either confirm - // the spill's success or lead to yet more spilling. - if (!hasRegionOverflowed(osec->memRegion) && - !hasRegionOverflowed(osec->lmaRegion)) - break; - } - - // Remove any spilled input sections to complete their move. - if (!spilledInputSections.empty()) { - spilled = true; - llvm::erase_if(isd->sections, [&](InputSection *isec) { - return spilledInputSections.contains(isec); - }); - } - } - } - - return spilled; -} - -// Erase any potential spill sections that were not used. -void LinkerScript::erasePotentialSpillSections() { - if (potentialSpillLists.empty()) - return; - - // Collect the set of input section descriptions that contain potential - // spills. - DenseSet isds; - for (const auto &[_, list] : potentialSpillLists) - for (PotentialSpillSection *s = list.head; s; s = s->next) - isds.insert(s->isd); - - for (InputSectionDescription *isd : isds) - llvm::erase_if(isd->sections, [](InputSection *s) { - return isa(s); - }); - - potentialSpillLists.clear(); -} - // Creates program headers as instructed by PHDRS linker script command. SmallVector LinkerScript::createPhdrs() { SmallVector ret; diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 734d4e7498aa..b09cd12c46f9 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -10,7 +10,6 @@ #define LLD_ELF_LINKER_SCRIPT_H #include "Config.h" -#include "InputSection.h" #include "Writer.h" #include "lld/Common/LLVM.h" #include "lld/Common/Strings.h" @@ -288,8 +287,7 @@ class LinkerScript final { SmallVector computeInputSections(const InputSectionDescription *, - ArrayRef, - const OutputSection &outCmd); + ArrayRef); SmallVector createInputSectionList(OutputSection &cmd); @@ -335,8 +333,6 @@ public: bool shouldKeep(InputSectionBase *s); const Defined *assignAddresses(); - bool spillSections(); - void erasePotentialSpillSections(); void allocateHeaders(SmallVector &phdrs); void processSectionCommands(); void processSymbolAssignments(); @@ -404,15 +400,6 @@ public: // // then provideMap should contain the mapping: 'v' -> ['a', 'b', 'c'] llvm::MapVector> provideMap; - - // List of potential spill locations (PotentialSpillSection) for an input - // section. - struct PotentialSpillList { - // Never nullptr. - PotentialSpillSection *head; - PotentialSpillSection *tail; - }; - llvm::DenseMap potentialSpillLists; }; struct ScriptWrapper { diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 883a6079bf50..b9e05a4b1fd5 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -197,9 +197,6 @@ def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">; def enable_new_dtags: F<"enable-new-dtags">, HelpText<"Enable new dynamic tags (default)">; -def enable_non_contiguous_regions : FF<"enable-non-contiguous-regions">, - HelpText<"Spill input sections to later matching output sections to avoid memory region overflow">; - def end_group: F<"end-group">, HelpText<"Ignored for compatibility with GNU unless you pass --warn-backrefs">; diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index fcb4c4387aa9..9c667241360f 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -186,7 +186,7 @@ static MergeSyntheticSection *createMergeSynthetic(StringRef name, // new synthetic sections at the location of the first input section // that it replaces. It then finalizes each synthetic section in order // to compute an output offset for each piece of each input section. -void OutputSection::finalizeInputSections(LinkerScript *script) { +void OutputSection::finalizeInputSections() { std::vector mergeSections; for (SectionCommand *cmd : commands) { auto *isd = dyn_cast(cmd); @@ -226,11 +226,6 @@ void OutputSection::finalizeInputSections(LinkerScript *script) { i = std::prev(mergeSections.end()); syn->entsize = ms->entsize; isd->sections.push_back(syn); - // The merge synthetic section inherits the potential spill locations of - // its first contained section. - auto it = script->potentialSpillLists.find(ms); - if (it != script->potentialSpillLists.end()) - script->potentialSpillLists.try_emplace(syn, it->second); } (*i)->addSection(ms); } diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 78fede48a23f..421a0181feb5 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -75,7 +75,7 @@ public: void recordSection(InputSectionBase *isec); void commitSection(InputSection *isec); - void finalizeInputSections(LinkerScript *script = nullptr); + void finalizeInputSections(); // The following members are normally only used in linker scripts. MemoryRegion *memRegion = nullptr; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 298c714adb3b..7b9ada40c0f6 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4074,13 +4074,6 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) { // InputSection with the highest address and any InputSections that have // mergeable .ARM.exidx table entries are removed from it. void ARMExidxSyntheticSection::finalizeContents() { - // Ensure that any fixed-point iterations after the first see the original set - // of sections. - if (!originalExecutableSections.empty()) - executableSections = originalExecutableSections; - else if (config->enableNonContiguousRegions) - originalExecutableSections = executableSections; - // The executableSections and exidxSections that we use to derive the final // contents of this SyntheticSection are populated before // processSectionCommands() and ICF. A /DISCARD/ entry in SECTIONS command or diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 34949025a45f..995fd4b344b0 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1255,10 +1255,6 @@ private: // either find the .ARM.exidx section or know that we need to generate one. SmallVector executableSections; - // Value of executableSecitons before finalizeContents(), so that it can be - // run repeateadly during fixed point iteration. - SmallVector originalExecutableSections; - // The executable InputSection with the highest address to use for the // sentinel. We store separately from ExecutableSections as merging of // duplicate entries may mean this InputSection is removed from diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 8d529f2bdb9f..e400ed2ae945 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1403,18 +1403,13 @@ template void Writer::finalizeAddressDependentContent() { AArch64Err843419Patcher a64p; ARMErr657417Patcher a32p; script->assignAddresses(); - // .ARM.exidx and SHF_LINK_ORDER do not require precise addresses, but they // do require the relative addresses of OutputSections because linker scripts // can assign Virtual Addresses to OutputSections that are not monotonically - // increasing. Anything here must be repeatable, since spilling may change - // section order. - const auto finalizeOrderDependentContent = [this] { - for (Partition &part : partitions) - finalizeSynthetic(part.armExidx.get()); - resolveShfLinkOrder(); - }; - finalizeOrderDependentContent(); + // increasing. + for (Partition &part : partitions) + finalizeSynthetic(part.armExidx.get()); + resolveShfLinkOrder(); // Converts call x@GDPLT to call __tls_get_addr if (config->emachine == EM_HEXAGON) @@ -1424,8 +1419,6 @@ template void Writer::finalizeAddressDependentContent() { for (;;) { bool changed = target->needsThunks ? tc.createThunks(pass, outputSections) : target->relaxOnce(pass); - bool spilled = script->spillSections(); - changed |= spilled; ++pass; // With Thunk Size much smaller than branch range we expect to @@ -1471,9 +1464,6 @@ template void Writer::finalizeAddressDependentContent() { " does not converge"); break; } - } else if (spilled) { - // Spilling can change relative section order. - finalizeOrderDependentContent(); } } if (!config->relocatable) @@ -1493,10 +1483,6 @@ template void Writer::finalizeAddressDependentContent() { osec->name + " is not a multiple of alignment (" + Twine(osec->addralign) + ")"); } - - // Sizes are no longer allowed to grow, so all allowable spills have been - // taken. Remove any leftover potential spills. - script->erasePotentialSpillSections(); } // If Input Sections have been shrunk (basic block sections) then diff --git a/lld/docs/ELF/linker_script.rst b/lld/docs/ELF/linker_script.rst index 7a35534be096..3606ef4fe4b8 100644 --- a/lld/docs/ELF/linker_script.rst +++ b/lld/docs/ELF/linker_script.rst @@ -197,14 +197,3 @@ the current location to a max-page-size boundary, ensuring that the next LLD will insert ``.relro_padding`` immediately before the symbol assignment using ``DATA_SEGMENT_RELRO_END``. - -Non-contiguous regions -~~~~~~~~~~~~~~~~~~~~~~ - -The flag ``--enable-non-contiguous-regions`` allows input sections to spill to -later matches rather than causing the link to fail by overflowing a memory -region. Unlike GNU ld, ``/DISCARD/`` only matches previously-unmatched sections -(i.e., the flag does not affect it). Also, if a section fails to fit at any of -its matches, the link fails instead of discarding the section. Accordingly, the -GNU flag ``--enable-non-contiguous-regions-warnings`` is not implemented, as it -exists to warn about such occurrences. diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index e7a913e025da..f8fdebfeaecf 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -38,12 +38,6 @@ ELF Improvements * ``--debug-names`` is added to create a merged ``.debug_names`` index from input ``.debug_names`` sections. Type units are not handled yet. (`#86508 `_) -* ``--enable-non-contiguous-regions`` option allows automatically packing input - sections into memory regions by automatically spilling to later matches if a - region would overflow. This reduces the toil of manually packing regions - (typical for embedded). It also makes full LTO feasible in such cases, since - IR merging currently prevents the linker script from referring to input - files. (`#90007 `_) Breaking changes ---------------- diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index 0df13f07f560..9ea1a9c52f2a 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -222,8 +222,6 @@ segment header. Generate relocations in the output. .It Fl -enable-new-dtags Enable new dynamic tags. -.It Fl -enable-non-contiguous-regions -Spill input sections to later matching output sections to avoid memory region overflow. .It Fl -end-lib End a grouping of objects that should be treated as if they were together in an archive. diff --git a/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test b/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test deleted file mode 100644 index 3f7b9c4e5f8b..000000000000 --- a/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test +++ /dev/null @@ -1,55 +0,0 @@ -## When spilling reorders input sections, the .ARM.exidx table is rebuilt using -## the new order. - -# REQUIRES: arm -# RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi test.s -o test.o -# RUN: ld.lld -T test.ld test.o -o test --enable-non-contiguous-regions -# RUN: llvm-readobj -x .ARM.exidx test | FileCheck %s - -# CHECK: 20000000 08849780 1c000000 10849880 -# CHECK-NEXT: 1c000000 01000000 - -#--- test.ld -MEMORY { - exidx : ORIGIN = 0, LENGTH = 32 - a : ORIGIN = 32, LENGTH = 4 - b : ORIGIN = 36, LENGTH = 4 - c : ORIGIN = 40, LENGTH = 4 -} - -SECTIONS { - .ARM.exidx : { *(.ARM.exidx) } >exidx - .first_chance : { *(.text .text.f2) } >a - .text.f1 : { *(.text.f1) } >b - .last_chance : { *(.text.f2) } >c -} - -#--- test.s - .syntax unified - .section .text, "ax",%progbits - .globl _start -_start: - .fnstart - bx lr - .save {r7, lr} - .setfp r7, sp, #0 - .fnend - - .section .text.f1, "ax", %progbits - .globl f1 -f1: - .fnstart - bx lr - .save {r8, lr} - .setfp r8, sp, #0 - .fnend - - .section .text.f2, "ax", %progbits - .globl f2 -f2: - .fnstart - bx lr - .save {r8, lr} - .setfp r8, sp, #0 - .fnend diff --git a/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test b/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test deleted file mode 100644 index 392106fd476f..000000000000 --- a/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test +++ /dev/null @@ -1,265 +0,0 @@ -# REQUIRES: x86 - -# RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc -n -filetype=obj -triple=x86_64 spill.s -o spill.o - -## An input section spills to a later match when the region of its first match -## would overflow. The spill uses the alignment of the later match. - -# RUN: ld.lld -T spill.ld spill.o -o spill --enable-non-contiguous-regions -# RUN: llvm-readelf -S spill | FileCheck %s --check-prefix=SPILL - -# SPILL: Name Type Address Off Size -# SPILL: .first_chance PROGBITS 0000000000000000 001000 000001 -# SPILL-NEXT: .last_chance PROGBITS 0000000000000008 001008 000002 - -## A spill off the end still fails the link. - -# RUN: not ld.lld -T spill-fail.ld spill.o --enable-non-contiguous-regions 2>&1 |\ -# RUN: FileCheck %s --check-prefix=SPILL-FAIL --implicit-check-not=error: - -# SPILL-FAIL: error: section '.last_chance' will not fit in region 'b': overflowed by 2 bytes - -## The above spill still occurs when the LMA would overflow, even though the -## VMA would fit. - -# RUN: ld.lld -T spill-lma.ld spill.o -o spill-lma --enable-non-contiguous-regions -# RUN: llvm-readelf -S spill-lma | FileCheck %s --check-prefix=SPILL-LMA - -# SPILL-LMA: Name Type Address Off Size -# SPILL-LMA: .first_chance PROGBITS 0000000000000000 001000 000001 -# SPILL-LMA-NEXT: .last_chance PROGBITS 0000000000000003 001003 000002 - -## A spill occurs to an additional match after the first. - -# RUN: ld.lld -T spill-later.ld spill.o -o spill-later --enable-non-contiguous-regions -# RUN: llvm-readelf -S spill-later | FileCheck %s --check-prefix=SPILL-LATER - -# SPILL-LATER: Name Type Address Off Size -# SPILL-LATER: .first_chance PROGBITS 0000000000000000 001000 000001 -# SPILL-LATER-NEXT: .second_chance PROGBITS 0000000000000002 001001 000000 -# SPILL-LATER-NEXT: .last_chance PROGBITS 0000000000000003 001003 000002 - -## A later overflow causes an earlier section to spill. - -# RUN: ld.lld -T spill-earlier.ld spill.o -o spill-earlier --enable-non-contiguous-regions -# RUN: llvm-readelf -S spill-earlier | FileCheck %s --check-prefix=SPILL-EARLIER - -# SPILL-EARLIER: Name Type Address Off Size -# SPILL-EARLIER: .first_chance PROGBITS 0000000000000000 001000 000002 -# SPILL-EARLIER-NEXT: .last_chance PROGBITS 0000000000000002 001002 000001 - -## An additional match in /DISCARD/ has no effect. - -# RUN: not ld.lld -T no-spill-into-discard.ld spill.o --enable-non-contiguous-regions 2>&1 |\ -# RUN: FileCheck %s --check-prefix=NO-SPILL-INTO-DISCARD --implicit-check-not=error: - -# NO-SPILL-INTO-DISCARD: error: section '.osec' will not fit in region 'a': overflowed by 1 bytes - -## An additional match after /DISCARD/ has no effect. - -# RUN: ld.lld -T no-spill-from-discard.ld spill.o -o no-spill-from-discard --enable-non-contiguous-regions -# RUN: llvm-readelf -S no-spill-from-discard | FileCheck %s --check-prefix=NO-SPILL-FROM-DISCARD - -# NO-SPILL-FROM-DISCARD: Name Type Address Off Size -# NO-SPILL-FROM-DISCARD-NOT: .osec - -## SHF_MERGEd sections are spilled according to the matches of the first merged -## input section (the one giving the resulting section its name). - -# RUN: llvm-mc -n -filetype=obj -triple=x86_64 merge.s -o merge.o -# RUN: ld.lld -T spill-merge.ld merge.o -o spill-merge --enable-non-contiguous-regions -# RUN: llvm-readelf -S spill-merge | FileCheck %s --check-prefix=SPILL-MERGE - -# SPILL-MERGE: Name Type Address Off Size -# SPILL-MERGE: .first PROGBITS 0000000000000000 000190 000000 -# SPILL-MERGE-NEXT: .second PROGBITS 0000000000000001 001001 000002 -# SPILL-MERGE-NEXT: .third PROGBITS 0000000000000003 001003 000000 - -## An error is reported for INSERT. - -# RUN: not ld.lld -T insert.ld spill.o --enable-non-contiguous-regions 2>&1 |\ -# RUN: FileCheck %s --check-prefix=INSERT - -# INSERT: error: INSERT cannot be used with --enable-non-contiguous-regions - -## An error is reported for OVERWRITE_SECTIONS. - -# RUN: not ld.lld -T overwrite-sections.ld spill.o --enable-non-contiguous-regions 2>&1 |\ -# RUN: FileCheck %s --check-prefix=OVERWRITE_SECTIONS - -# OVERWRITE_SECTIONS: error: OVERWRITE_SECTIONS cannot be used with --enable-non-contiguous-regions - -## SHF_LINK_ORDER is reordered when spilling changes relative section order. - -# RUN: llvm-mc -n -filetype=obj -triple=x86_64 link-order.s -o link-order.o -# RUN: ld.lld -T link-order.ld link-order.o -o link-order --enable-non-contiguous-regions -# RUN: llvm-readobj -x .order link-order | FileCheck %s --check-prefix=LINK-ORDER - -# LINK-ORDER: 020301 - -#--- spill.s -.section .one_byte_section,"a",@progbits -.fill 1 - -.section .two_byte_section,"a",@progbits -.fill 2 - -#--- spill.ld -MEMORY { - a : ORIGIN = 0, LENGTH = 2 - b : ORIGIN = 2, LENGTH = 16 -} - -SECTIONS { - .first_chance : SUBALIGN(1) { *(.one_byte_section) *(.two_byte_section) } >a - .last_chance : SUBALIGN(8) { *(.two_byte_section) } >b -} - -#--- spill-fail.ld -MEMORY { - a : ORIGIN = 0, LENGTH = 1 - b : ORIGIN = 2, LENGTH = 0 -} - -SECTIONS { - .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a - .last_chance : { *(.two_byte_section) } >b -} - -#--- spill-lma.ld -MEMORY { - vma_a : ORIGIN = 0, LENGTH = 3 - vma_b : ORIGIN = 3, LENGTH = 3 - lma_a : ORIGIN = 6, LENGTH = 2 - lma_b : ORIGIN = 8, LENGTH = 2 -} - -SECTIONS { - .first_chance : { *(.one_byte_section) *(.two_byte_section) } >vma_a AT>lma_a - .last_chance : { *(.two_byte_section) } >vma_b AT>lma_b -} - -#--- spill-later.ld -MEMORY { - a : ORIGIN = 0, LENGTH = 2 - b : ORIGIN = 2, LENGTH = 1 - c : ORIGIN = 3, LENGTH = 2 -} - -SECTIONS { - .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a - .second_chance : { *(.two_byte_section) } >b - .last_chance : { *(.two_byte_section) } >c -} - -#--- spill-earlier.ld -MEMORY { - a : ORIGIN = 0, LENGTH = 2 - b : ORIGIN = 2, LENGTH = 1 -} - -SECTIONS { - .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a - .last_chance : { *(.one_byte_section) } >b -} - -#--- no-spill-into-discard.ld -MEMORY { - a : ORIGIN = 0, LENGTH = 1 -} - -SECTIONS { - .osec : { *(.two_byte_section) } >a - /DISCARD/ : { *(.one_byte_section) *(.two_byte_section) } -} - -#--- no-spill-from-discard.ld -MEMORY { - a : ORIGIN = 0, LENGTH = 2 -} - -SECTIONS { - /DISCARD/ : { *(.one_byte_section) *(.two_byte_section) } - .osec : { *(.two_byte_section) } >a -} - -#--- merge.s -.section .a,"aM",@progbits,1 -.byte 0x12, 0x34 - -.section .b,"aM",@progbits,1 -.byte 0x12 - -#--- spill-merge.ld -MEMORY { - a : ORIGIN = 0, LENGTH = 1 - b : ORIGIN = 1, LENGTH = 2 - c : ORIGIN = 3, LENGTH = 2 -} - -SECTIONS { - .first : { *(.a) *(.b) } >a - .second : { *(.a) } >b - .third : { *(.b) } >c -} - -#--- insert.ld -MEMORY { - a : ORIGIN = 0, LENGTH = 1 -} - -SECTIONS { - .a : { *(.two_byte_section) } >a -} - -SECTIONS { - .b : { *(.one_byte_section) } >a -} INSERT AFTER .a; - -#--- overwrite-sections.ld -MEMORY { - a : ORIGIN = 0, LENGTH = 1 -} - -SECTIONS { - .a : { *(.two_byte_section) } >a -} - -OVERWRITE_SECTIONS { - .b : { *(.one_byte_section) } >a -} - -#--- link-order.s -.section .a,"a",@progbits -.fill 1 - -.section .b,"a",@progbits -.fill 1 - -.section .c,"a",@progbits -.fill 1 - -.section .link_order.a,"ao",@progbits,.a -.byte 1 - -.section .link_order.b,"ao",@progbits,.b -.byte 2 - -.section .link_order.c,"ao",@progbits,.c -.byte 3 - -#--- link-order.ld -MEMORY { - order : ORIGIN = 0, LENGTH = 3 - potential_a : ORIGIN = 3, LENGTH = 0 - bc : ORIGIN = 3, LENGTH = 2 - actual_a : ORIGIN = 5, LENGTH = 1 -} - -SECTIONS { - .order : { *(.link_order.*) } > order - .potential_a : { *(.a) } >potential_a - .bc : { *(.b) *(.c) } >bc - .actual_a : { *(.a) } >actual_a -} -- GitLab From 276c0bd4b386cc6b9d91e5e44ca7b053c11f13b5 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 13 May 2024 18:47:39 +0100 Subject: [PATCH 108/578] [lldb][ExpressionParser][NFCI] Log pointers as hex (#91989) This ensures that we log pointers as lower-case hex. E.g., instead of: ``` LayoutRecordType on (ASTContext*)0x000000010E78D600 'scratch ASTContext' for (RecordDecl*)0x000000010E797 ``` we now log: ``` LayoutRecordType on (ASTContext*)0x000000010e78d600 'scratch ASTContext' for (RecordDecl*)0x000000010e797 ``` Which is consistent with how the AST dump gets emitted into the log. This makes it easier to correlate pointers we log from LLDB and pointers that are part of any AST dumps in the same `expr` log. --- .../Clang/ClangASTImporter.cpp | 62 ++++++++++--------- .../ExpressionParser/Clang/ClangASTSource.cpp | 44 ++++++------- 2 files changed, 54 insertions(+), 52 deletions(-) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp index 30b50df79da9..44071d1ea71c 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp @@ -313,8 +313,8 @@ CompilerType ClangASTImporter::DeportType(TypeSystemClang &dst, return {}; LLDB_LOG(log, - " [ClangASTImporter] DeportType called on ({0}Type*){1} " - "from (ASTContext*){2} to (ASTContext*){3}", + " [ClangASTImporter] DeportType called on ({0}Type*){1:x} " + "from (ASTContext*){2:x} to (ASTContext*){3:x}", src_type.GetTypeName(), src_type.GetOpaqueQualType(), &src_ctxt->getASTContext(), &dst.getASTContext()); @@ -334,8 +334,8 @@ clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx = &decl->getASTContext(); LLDB_LOG(log, - " [ClangASTImporter] DeportDecl called on ({0}Decl*){1} from " - "(ASTContext*){2} to (ASTContext*){3}", + " [ClangASTImporter] DeportDecl called on ({0}Decl*){1:x} from " + "(ASTContext*){2:x} to (ASTContext*){3:x}", decl->getDeclKindName(), decl, src_ctx, dst_ctx); DeclContextOverride decl_context_override; @@ -352,8 +352,8 @@ clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx, return nullptr; LLDB_LOG(log, - " [ClangASTImporter] DeportDecl deported ({0}Decl*){1} to " - "({2}Decl*){3}", + " [ClangASTImporter] DeportDecl deported ({0}Decl*){1:x} to " + "({2}Decl*){3:x}", decl->getDeclKindName(), decl, result->getDeclKindName(), result); return result; @@ -637,8 +637,8 @@ bool ClangASTImporter::importRecordLayoutFromOrigin( clang::ASTContext &dest_ctx = record->getASTContext(); LLDB_LOG(log, - "LayoutRecordType on (ASTContext*){0} '{1}' for (RecordDecl*)" - "{2} [name = '{3}']", + "LayoutRecordType on (ASTContext*){0:x} '{1}' for (RecordDecl*)" + "{2:x} [name = '{3}']", &dest_ctx, TypeSystemClang::GetASTContext(&dest_ctx)->getDisplayName(), record, record->getName()); @@ -703,7 +703,7 @@ bool ClangASTImporter::importRecordLayoutFromOrigin( if (log) { LLDB_LOG(log, "LRT returned:"); - LLDB_LOG(log, "LRT Original = (RecordDecl*){0}", + LLDB_LOG(log, "LRT Original = (RecordDecl*){0:x}", static_cast(origin_record.decl)); LLDB_LOG(log, "LRT Size = {0}", size); LLDB_LOG(log, "LRT Alignment = {0}", alignment); @@ -711,11 +711,11 @@ bool ClangASTImporter::importRecordLayoutFromOrigin( for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end(); fi != fe; ++fi) { - LLDB_LOG(log, - "LRT (FieldDecl*){0}, Name = '{1}', Type = '{2}', Offset = " - "{3} bits", - *fi, fi->getName(), fi->getType().getAsString(), - field_offsets[*fi]); + LLDB_LOG( + log, + "LRT (FieldDecl*){0:x}, Name = '{1}', Type = '{2}', Offset = " + "{3} bits", + *fi, fi->getName(), fi->getType().getAsString(), field_offsets[*fi]); } DeclFromParser parser_cxx_record = DynCast(parser_record); @@ -734,7 +734,7 @@ bool ClangASTImporter::importRecordLayoutFromOrigin( DynCast(base_record); LLDB_LOG(log, - "LRT {0}(CXXRecordDecl*){1}, Name = '{2}', Offset = " + "LRT {0}(CXXRecordDecl*){1:x}, Name = '{2}', Offset = " "{3} chars", (is_virtual ? "Virtual " : ""), base_cxx_record.decl, base_cxx_record.decl->getName(), @@ -1025,7 +1025,7 @@ void ClangASTImporter::ForgetDestination(clang::ASTContext *dst_ast) { Log *log = GetLog(LLDBLog::Expressions); LLDB_LOG(log, - " [ClangASTImporter] Forgetting destination (ASTContext*){0}", + " [ClangASTImporter] Forgetting destination (ASTContext*){0:x}", dst_ast); m_metadata_map.erase(dst_ast); @@ -1039,7 +1039,7 @@ void ClangASTImporter::ForgetSource(clang::ASTContext *dst_ast, LLDB_LOG(log, " [ClangASTImporter] Forgetting source->dest " - "(ASTContext*){0}->(ASTContext*){1}", + "(ASTContext*){0:x}->(ASTContext*){1:x}", src_ast, dst_ast); if (!md) @@ -1164,9 +1164,10 @@ void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo( from_named_decl->printName(name_stream); name_stream.flush(); } - LLDB_LOG(log_ast, "==== [ClangASTImporter][TUDecl: {0}] Imported " - "({1}Decl*){2}, named {3} (from " - "(Decl*){4})", + LLDB_LOG(log_ast, + "==== [ClangASTImporter][TUDecl: {0:x}] Imported " + "({1}Decl*){2:x}, named {3} (from " + "(Decl*){4:x})", static_cast(to->getTranslationUnitDecl()), from->getDeclKindName(), static_cast(to), name_string, static_cast(from)); @@ -1294,14 +1295,15 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, from_named_decl->printName(name_stream); name_stream.flush(); - LLDB_LOG(log, - " [ClangASTImporter] Imported ({0}Decl*){1}, named {2} (from " - "(Decl*){3}), metadata {4}", - from->getDeclKindName(), to, name_string, from, user_id); + LLDB_LOG( + log, + " [ClangASTImporter] Imported ({0}Decl*){1:x}, named {2} (from " + "(Decl*){3:x}), metadata {4}", + from->getDeclKindName(), to, name_string, from, user_id); } else { LLDB_LOG(log, - " [ClangASTImporter] Imported ({0}Decl*){1} (from " - "(Decl*){2}), metadata {3}", + " [ClangASTImporter] Imported ({0}Decl*){1:x} (from " + "(Decl*){2:x}), metadata {3}", from->getDeclKindName(), to, from, user_id); } } @@ -1321,8 +1323,8 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, LLDB_LOG(log, " [ClangASTImporter] Propagated origin " - "(Decl*){0}/(ASTContext*){1} from (ASTContext*){2} to " - "(ASTContext*){3}", + "(Decl*){0:x}/(ASTContext*){1:x} from (ASTContext*){2:x} to " + "(ASTContext*){3:x}", origin.decl, origin.ctx, &from->getASTContext(), &to->getASTContext()); } @@ -1335,7 +1337,7 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, LLDB_LOG(log, " [ClangASTImporter] Decl has no origin information in " - "(ASTContext*){0}", + "(ASTContext*){0:x}", &from->getASTContext()); } @@ -1356,7 +1358,7 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, LLDB_LOG(log, " [ClangASTImporter] Sourced origin " - "(Decl*){0}/(ASTContext*){1} into (ASTContext*){2}", + "(Decl*){0:x}/(ASTContext*){1:x} into (ASTContext*){2:x}", from, m_source_ctx, &to->getASTContext()); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 75493eb10d73..82a7a2cc3f1e 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -193,7 +193,7 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) { if (!namespace_map) return nullptr; - LLDB_LOGV(log, " CTD Inspecting namespace map{0} ({1} entries)", + LLDB_LOGV(log, " CTD Inspecting namespace map{0:x} ({1} entries)", namespace_map.get(), namespace_map->size()); for (const ClangASTImporter::NamespaceMapItem &item : *namespace_map) { @@ -265,7 +265,7 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { if (log) { LLDB_LOG(log, " CompleteTagDecl on (ASTContext*){0} Completing " - "(TagDecl*){1} named {2}", + "(TagDecl*){1:x} named {2}", m_clang_ast_context->getDisplayName(), tag_decl, tag_decl->getName()); @@ -292,7 +292,7 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { Log *log = GetLog(LLDBLog::Expressions); LLDB_LOG(log, - " [CompleteObjCInterfaceDecl] on (ASTContext*){0} '{1}' " + " [CompleteObjCInterfaceDecl] on (ASTContext*){0:x} '{1}' " "Completing an ObjCInterfaceDecl named {1}", m_ast_context, m_clang_ast_context->getDisplayName(), interface_decl->getName()); @@ -385,7 +385,7 @@ void ClangASTSource::FindExternalLexicalDecls( if (log) { if (const NamedDecl *context_named_decl = dyn_cast(context_decl)) LLDB_LOG(log, - "FindExternalLexicalDecls on (ASTContext*){0} '{1}' in " + "FindExternalLexicalDecls on (ASTContext*){0:x} '{1}' in " "'{2}' ({3}Decl*){4}", m_ast_context, m_clang_ast_context->getDisplayName(), context_named_decl->getNameAsString().c_str(), @@ -393,14 +393,14 @@ void ClangASTSource::FindExternalLexicalDecls( static_cast(context_decl)); else if (context_decl) LLDB_LOG(log, - "FindExternalLexicalDecls on (ASTContext*){0} '{1}' in " + "FindExternalLexicalDecls on (ASTContext*){0:x} '{1}' in " "({2}Decl*){3}", m_ast_context, m_clang_ast_context->getDisplayName(), context_decl->getDeclKindName(), static_cast(context_decl)); else LLDB_LOG(log, - "FindExternalLexicalDecls on (ASTContext*){0} '{1}' in a " + "FindExternalLexicalDecls on (ASTContext*){0:x} '{1}' in a " "NULL context", m_ast_context, m_clang_ast_context->getDisplayName()); } @@ -410,7 +410,7 @@ void ClangASTSource::FindExternalLexicalDecls( if (!original.Valid()) return; - LLDB_LOG(log, " FELD Original decl {0} (Decl*){1:x}:\n{2}", + LLDB_LOG(log, " FELD Original decl (ASTContext*){0:x} (Decl*){1:x}:\n{2}", static_cast(original.ctx), static_cast(original.decl), ClangUtil::DumpDecl(original.decl)); @@ -508,19 +508,19 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { if (!context.m_decl_context) LLDB_LOG(log, "ClangASTSource::FindExternalVisibleDecls on " - "(ASTContext*){0} '{1}' for '{2}' in a NULL DeclContext", + "(ASTContext*){0:x} '{1}' for '{2}' in a NULL DeclContext", m_ast_context, m_clang_ast_context->getDisplayName(), name); else if (const NamedDecl *context_named_decl = dyn_cast(context.m_decl_context)) LLDB_LOG(log, "ClangASTSource::FindExternalVisibleDecls on " - "(ASTContext*){0} '{1}' for '{2}' in '{3}'", + "(ASTContext*){0:x} '{1}' for '{2}' in '{3}'", m_ast_context, m_clang_ast_context->getDisplayName(), name, context_named_decl->getName()); else LLDB_LOG(log, "ClangASTSource::FindExternalVisibleDecls on " - "(ASTContext*){0} '{1}' for '{2}' in a '{3}'", + "(ASTContext*){0:x} '{1}' for '{2}' in a '{3}'", m_ast_context, m_clang_ast_context->getDisplayName(), name, context.m_decl_context->getDeclKindName()); } @@ -542,7 +542,7 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { if (!context.m_namespace_map->empty()) { if (log && log->GetVerbose()) - LLDB_LOG(log, " CAS::FEVD Registering namespace map {0} ({1} entries)", + LLDB_LOG(log, " CAS::FEVD Registering namespace map {0:x} ({1} entries)", context.m_namespace_map.get(), context.m_namespace_map->size()); NamespaceDecl *clang_namespace_decl = @@ -918,7 +918,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { ConstString selector_name(ss.GetString()); LLDB_LOG(log, - "ClangASTSource::FindObjCMethodDecls on (ASTContext*){0} '{1}' " + "ClangASTSource::FindObjCMethodDecls on (ASTContext*){0:x} '{1}' " "for selector [{2} {3}]", m_ast_context, m_clang_ast_context->getDisplayName(), interface_decl->getName(), selector_name); @@ -1062,7 +1062,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { LLDB_LOG(log, "CAS::FOPD trying origin " - "(ObjCInterfaceDecl*){0}/(ASTContext*){1}...", + "(ObjCInterfaceDecl*){0:x}/(ASTContext*){1:x}...", complete_interface_decl, &complete_iface_decl->getASTContext()); FindObjCMethodDeclsWithOrigin(context, complete_interface_decl, @@ -1199,7 +1199,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { LLDB_LOG(log, "ClangASTSource::FindObjCPropertyAndIvarDecls on " - "(ASTContext*){0} '{1}' for '{2}.{3}'", + "(ASTContext*){0:x} '{1}' for '{2}.{3}'", m_ast_context, m_clang_ast_context->getDisplayName(), parser_iface_decl->getName(), context.m_decl_name.getAsString()); @@ -1208,7 +1208,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { LLDB_LOG(log, "CAS::FOPD couldn't find the property on origin " - "(ObjCInterfaceDecl*){0}/(ASTContext*){1}, searching " + "(ObjCInterfaceDecl*){0:x}/(ASTContext*){1:x}, searching " "elsewhere...", origin_iface_decl.decl, &origin_iface_decl->getASTContext()); @@ -1233,7 +1233,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { LLDB_LOG(log, "CAS::FOPD trying origin " - "(ObjCInterfaceDecl*){0}/(ASTContext*){1}...", + "(ObjCInterfaceDecl*){0:x}/(ASTContext*){1:x}...", complete_iface_decl.decl, &complete_iface_decl->getASTContext()); FindObjCPropertyAndIvarDeclsWithOrigin(context, complete_iface_decl); @@ -1265,8 +1265,8 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { break; LLDB_LOG(log, - "CAS::FOPD[{0}] trying module " - "(ObjCInterfaceDecl*){0}/(ASTContext*){1}...", + "CAS::FOPD[{0:x}] trying module " + "(ObjCInterfaceDecl*){0:x}/(ASTContext*){1:x}...", interface_decl_from_modules.decl, &interface_decl_from_modules->getASTContext()); @@ -1309,8 +1309,8 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { break; LLDB_LOG(log, - "CAS::FOPD[{0}] trying runtime " - "(ObjCInterfaceDecl*){0}/(ASTContext*){1}...", + "CAS::FOPD[{0:x}] trying runtime " + "(ObjCInterfaceDecl*){0:x}/(ASTContext*){1:x}...", interface_decl_from_runtime.decl, &interface_decl_from_runtime->getASTContext()); @@ -1329,7 +1329,7 @@ void ClangASTSource::LookupInNamespace(NameSearchContext &context) { ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); - LLDB_LOGV(log, " CAS::FEVD Inspecting namespace map {0} ({1} entries)", + LLDB_LOGV(log, " CAS::FEVD Inspecting namespace map {0:x} ({1} entries)", namespace_map.get(), namespace_map->size()); if (!namespace_map) @@ -1366,7 +1366,7 @@ void ClangASTSource::CompleteNamespaceMap( if (log) { if (parent_map && parent_map->size()) LLDB_LOG(log, - "CompleteNamespaceMap on (ASTContext*){0} '{1}' Searching " + "CompleteNamespaceMap on (ASTContext*){0:x} '{1}' Searching " "for namespace {2} in namespace {3}", m_ast_context, m_clang_ast_context->getDisplayName(), name, parent_map->begin()->second.GetName()); -- GitLab From 0df67fa212feb3cb503cd05c440afac446bb9457 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Mon, 13 May 2024 14:50:08 -0300 Subject: [PATCH 109/578] Revert "[clang] Revert default behavior change of P0522R0 implementation (#91811)" (#91837) With blocking issues fixed, re-enable relaxed template template argument matching by reverting these commits. This reverts commit 4198aebc96cb0236fc63e29a92d886e6a2e3fedb. This reverts commit 2d5634a4b39d8e5497b6a67caa54049b3cfade8e. --- clang/lib/Driver/ToolChains/Clang.cpp | 14 +++++++------- .../Driver/frelaxed-template-template-args.cpp | 6 +++--- clang/test/Driver/rewrite-legacy-objc.m | 6 +++--- clang/test/Driver/rewrite-objc.m | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index f0cc018b6668..42feb1650574 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7249,15 +7249,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.addOptOutFlag(CmdArgs, options::OPT_fassume_unique_vtables, options::OPT_fno_assume_unique_vtables); - // -fno-relaxed-template-template-args is deprecated. - if (Arg *A = Args.getLastArg(options::OPT_frelaxed_template_template_args, - options::OPT_fno_relaxed_template_template_args); - A && - A->getOption().matches(options::OPT_fno_relaxed_template_template_args)) + // -frelaxed-template-template-args is deprecated. + if (Arg *A = + Args.getLastArg(options::OPT_frelaxed_template_template_args, + options::OPT_fno_relaxed_template_template_args)) { D.Diag(diag::warn_drv_deprecated_arg) << A->getAsString(Args) << /*hasReplacement=*/false; - else - CmdArgs.push_back("-fno-relaxed-template-template-args"); + if (A->getOption().matches(options::OPT_fno_relaxed_template_template_args)) + CmdArgs.push_back("-fno-relaxed-template-template-args"); + } // -fsized-deallocation is off by default, as it is an ABI-breaking change for // most platforms. diff --git a/clang/test/Driver/frelaxed-template-template-args.cpp b/clang/test/Driver/frelaxed-template-template-args.cpp index 136c360276a1..57fc4e3da6e5 100644 --- a/clang/test/Driver/frelaxed-template-template-args.cpp +++ b/clang/test/Driver/frelaxed-template-template-args.cpp @@ -1,7 +1,7 @@ // RUN: %clang -fsyntax-only -### %s 2>&1 | FileCheck --check-prefix=CHECK-DEF %s -// RUN: %clang -fsyntax-only -frelaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-ON --allow-empty %s +// RUN: %clang -fsyntax-only -frelaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-ON %s // RUN: %clang -fsyntax-only -fno-relaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-OFF %s -// CHECK-DEF: "-cc1"{{.*}} "-fno-relaxed-template-template-args" -// CHECK-ON-NOT: warning: argument '-frelaxed-template-template-args' is deprecated [-Wdeprecated] +// CHECK-DEF-NOT: "-cc1"{{.*}} "-fno-relaxed-template-template-args" +// CHECK-ON: warning: argument '-frelaxed-template-template-args' is deprecated [-Wdeprecated] // CHECK-OFF: warning: argument '-fno-relaxed-template-template-args' is deprecated [-Wdeprecated] diff --git a/clang/test/Driver/rewrite-legacy-objc.m b/clang/test/Driver/rewrite-legacy-objc.m index d45fb8c405c5..413a7a7a61f0 100644 --- a/clang/test/Driver/rewrite-legacy-objc.m +++ b/clang/test/Driver/rewrite-legacy-objc.m @@ -3,11 +3,11 @@ // TEST0: "-cc1" // TEST0: "-rewrite-objc" // FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead. -// TEST0: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fno-relaxed-template-template-args" "-fmax-type-align=16" +// TEST0: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16" // TEST0: rewrite-legacy-objc.m" // RUN: %clang --target=i386-apple-macosx10.9.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \ // RUN: FileCheck -check-prefix=TEST1 %s // RUN: %clang --target=i386-apple-macosx10.6.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \ // RUN: FileCheck -check-prefix=TEST2 %s -// TEST1: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fno-relaxed-template-template-args" "-fmax-type-align=16" -// TEST2: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fno-relaxed-template-template-args" "-fmax-type-align=16" +// TEST1: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" +// TEST2: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" diff --git a/clang/test/Driver/rewrite-objc.m b/clang/test/Driver/rewrite-objc.m index d19d38d8ab83..de3577a770df 100644 --- a/clang/test/Driver/rewrite-objc.m +++ b/clang/test/Driver/rewrite-objc.m @@ -2,4 +2,4 @@ // RUN: FileCheck -check-prefix=TEST0 %s // TEST0: "-cc1" {{.*}} "-rewrite-objc" // FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead. -// TEST0: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fno-relaxed-template-template-args" "-fmax-type-align=16" +// TEST0: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16" -- GitLab From 5df01ed79c47b0b10ea6be87251ec6e0484515a5 Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Mon, 13 May 2024 13:50:27 -0400 Subject: [PATCH 110/578] Revert "[mlir][vector] Add Vector-dialect interleave-to-shuffle pattern, enable in VectorToSPIRV" (#92006) Reverts llvm/llvm-project#91800 Reason: https://lab.llvm.org/buildbot/#/builders/268/builds/13935 --- .../Vector/TransformOps/VectorTransformOps.td | 14 ------- .../Vector/Transforms/LoweringPatterns.h | 3 -- .../VectorToSPIRV/VectorToSPIRV.cpp | 4 -- .../TransformOps/VectorTransformOps.cpp | 5 --- .../Transforms/LowerVectorInterleave.cpp | 41 ------------------- .../Vector/vector-interleave-to-shuffle.mlir | 21 ---------- 6 files changed, 88 deletions(-) delete mode 100644 mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir diff --git a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td index bc3c16d40520..f6371f39c394 100644 --- a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td +++ b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td @@ -306,20 +306,6 @@ def ApplyLowerInterleavePatternsOp : Op]> { - let description = [{ - Indicates that 1D vector interleave operations should be rewritten as - vector shuffle operations. - - This is motivated by some current codegen backends not handling vector - interleave operations. - }]; - - let assemblyFormat = "attr-dict"; -} - def ApplyRewriteNarrowTypePatternsOp : Op]> { diff --git a/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h b/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h index 8fd9904fabc0..350d2777cadf 100644 --- a/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h +++ b/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h @@ -273,9 +273,6 @@ void populateVectorInterleaveLoweringPatterns(RewritePatternSet &patterns, int64_t targetRank = 1, PatternBenefit benefit = 1); -void populateVectorInterleaveToShufflePatterns(RewritePatternSet &patterns, - PatternBenefit benefit = 1); - } // namespace vector } // namespace mlir #endif // MLIR_DIALECT_VECTOR_TRANSFORMS_LOWERINGPATTERNS_H diff --git a/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp b/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp index c2dd37f48146..868a3521e7a0 100644 --- a/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp +++ b/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp @@ -18,7 +18,6 @@ #include "mlir/Dialect/SPIRV/IR/SPIRVTypes.h" #include "mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" -#include "mlir/Dialect/Vector/Transforms/LoweringPatterns.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinTypes.h" @@ -829,9 +828,6 @@ void mlir::populateVectorToSPIRVPatterns(SPIRVTypeConverter &typeConverter, // than the generic one that extracts all elements. patterns.add(typeConverter, patterns.getContext(), PatternBenefit(2)); - - // Need this until vector.interleave is handled. - vector::populateVectorInterleaveToShufflePatterns(patterns); } void mlir::populateVectorReductionToSPIRVDotProductPatterns( diff --git a/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp b/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp index 61fd6bd972e3..885644864c0f 100644 --- a/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp +++ b/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp @@ -164,11 +164,6 @@ void transform::ApplyLowerInterleavePatternsOp::populatePatterns( vector::populateVectorInterleaveLoweringPatterns(patterns); } -void transform::ApplyInterleaveToShufflePatternsOp::populatePatterns( - RewritePatternSet &patterns) { - vector::populateVectorInterleaveToShufflePatterns(patterns); -} - void transform::ApplyRewriteNarrowTypePatternsOp::populatePatterns( RewritePatternSet &patterns) { populateVectorNarrowTypeRewritePatterns(patterns); diff --git a/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp b/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp index 5326760c9b4e..3a456076f8fb 100644 --- a/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp @@ -16,7 +16,6 @@ #include "mlir/Dialect/Vector/Utils/VectorUtils.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/PatternMatch.h" -#include "mlir/Support/LogicalResult.h" #define DEBUG_TYPE "vector-interleave-lowering" @@ -78,49 +77,9 @@ private: int64_t targetRank = 1; }; -/// Rewrite vector.interleave op into an equivalent vector.shuffle op, when -/// applicable: `sourceType` must be 1D and non-scalable. -/// -/// Example: -/// -/// ```mlir -/// vector.interleave %a, %b : vector<7xi16> -/// ``` -/// -/// Is rewritten into: -/// -/// ```mlir -/// vector.shuffle %arg0, %arg1 [0, 7, 1, 8, 2, 9, 3, 10, 4, 11, 5, 12, 6, 13] -/// : vector<7xi16>, vector<7xi16> -/// ``` -class InterleaveToShuffle : public OpRewritePattern { -public: - InterleaveToShuffle(MLIRContext *context, PatternBenefit benefit = 1) - : OpRewritePattern(context, benefit) {}; - - LogicalResult matchAndRewrite(vector::InterleaveOp op, - PatternRewriter &rewriter) const override { - VectorType sourceType = op.getSourceVectorType(); - if (sourceType.getRank() != 1 || sourceType.isScalable()) { - return failure(); - } - int64_t n = sourceType.getNumElements(); - auto seq = llvm::seq(2 * n); - auto zip = llvm::to_vector(llvm::map_range( - seq, [n](int64_t i) { return (i % 2 ? n : 0) + i / 2; })); - rewriter.replaceOpWithNewOp(op, op.getLhs(), op.getRhs(), zip); - return success(); - } -}; - } // namespace void mlir::vector::populateVectorInterleaveLoweringPatterns( RewritePatternSet &patterns, int64_t targetRank, PatternBenefit benefit) { patterns.add(targetRank, patterns.getContext(), benefit); } - -void mlir::vector::populateVectorInterleaveToShufflePatterns( - RewritePatternSet &patterns, PatternBenefit benefit) { - patterns.add(patterns.getContext(), benefit); -} diff --git a/mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir b/mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir deleted file mode 100644 index ed3b3396bf3e..000000000000 --- a/mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir +++ /dev/null @@ -1,21 +0,0 @@ -// RUN: mlir-opt %s --transform-interpreter | FileCheck %s - -// CHECK-LABEL: @vector_interleave_to_shuffle -func.func @vector_interleave_to_shuffle(%a: vector<7xi16>, %b: vector<7xi16>) -> vector<14xi16> -{ - %0 = vector.interleave %a, %b : vector<7xi16> - return %0 : vector<14xi16> -} -// CHECK: vector.shuffle %arg0, %arg1 [0, 7, 1, 8, 2, 9, 3, 10, 4, 11, 5, 12, 6, 13] : vector<7xi16>, vector<7xi16> - -module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%module_op: !transform.any_op {transform.readonly}) { - %f = transform.structured.match ops{["func.func"]} in %module_op - : (!transform.any_op) -> !transform.any_op - - transform.apply_patterns to %f { - transform.apply_patterns.vector.interleave_to_shuffle - } : !transform.any_op - transform.yield - } -} -- GitLab From d03a1a6e5838c7c2c0836d71507dfdf7840ade49 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Tue, 14 May 2024 01:58:45 +0800 Subject: [PATCH 111/578] [ValueTracking] Compute knownbits from known fp classes (#86409) This patch calculates knownbits from fp instructions/dominating fcmp conditions. It will enable more optimizations with signbit idioms. --- llvm/include/llvm/IR/PatternMatch.h | 2 +- llvm/lib/Analysis/ValueTracking.cpp | 36 +++ .../AMDGPU/amdgpu-simplify-libcall-pow.ll | 14 +- .../AMDGPU/amdgpu-simplify-libcall-pown.ll | 12 +- llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll | 10 +- .../test/Transforms/InstCombine/known-bits.ll | 264 ++++++++++++++++++ 6 files changed, 319 insertions(+), 19 deletions(-) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 171ddab977de..0d6d86cb47e6 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -1904,7 +1904,7 @@ template struct ElementWiseBitCast_match { ElementWiseBitCast_match(const Op_t &OpMatch) : Op(OpMatch) {} template bool match(OpTy *V) { - BitCastInst *I = dyn_cast(V); + auto *I = dyn_cast(V); if (!I) return false; Type *SrcType = I->getSrcTy(); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 375385aca7a3..2fdbb6e3ef84 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1118,6 +1118,42 @@ static void computeKnownBitsFromOperator(const Operator *I, break; } + const Value *V; + // Handle bitcast from floating point to integer. + if (match(I, m_ElementWiseBitCast(m_Value(V))) && + V->getType()->isFPOrFPVectorTy()) { + Type *FPType = V->getType()->getScalarType(); + KnownFPClass Result = computeKnownFPClass(V, fcAllFlags, Depth + 1, Q); + FPClassTest FPClasses = Result.KnownFPClasses; + + if (Result.isKnownNever(fcNormal | fcSubnormal | fcNan)) { + Known.Zero.setAllBits(); + Known.One.setAllBits(); + + if (FPClasses & fcInf) + Known = Known.intersectWith(KnownBits::makeConstant( + APFloat::getInf(FPType->getFltSemantics()).bitcastToAPInt())); + + if (FPClasses & fcZero) + Known = Known.intersectWith(KnownBits::makeConstant( + APInt::getZero(FPType->getScalarSizeInBits()))); + } + + if (Result.SignBit) { + if (*Result.SignBit) + Known.makeNegative(); + else + Known.makeNonNegative(); + } else { + Known.Zero.clearSignBit(); + Known.One.clearSignBit(); + } + + assert(!Known.hasConflict() && "Bits known to be one AND zero?"); + + break; + } + // Handle cast from vector integer type to scalar or vector integer. auto *SrcVecTy = dyn_cast(SrcTy); if (!SrcVecTy || !SrcVecTy->getElementType()->isIntegerTy() || diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll index c4bd4bc126f7..5db25a59d33f 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll @@ -2216,7 +2216,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_sitofp(float %x, i32 %y) ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2304,7 +2304,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_uitofp(float %x, i32 %y) ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2353,7 +2353,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_uitofp_i256(float %x, i2 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2376,7 +2376,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_sitofp_i256(float %x, i2 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2399,7 +2399,7 @@ define <2 x float> @test_pow_afn_nnan_ninf_v2f32_known_integral_sitofp(<2 x floa ; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP4]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP5]] ; @@ -2448,7 +2448,7 @@ define <2 x float> @test_pow_afn_nnan_ninf_v2f32_known_integral_uitofp(<2 x floa ; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP4]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP5]] ; @@ -2560,7 +2560,7 @@ define float @test_pow_afn_f32_nnan_ninf__y_known_integral_trunc(float %x, float ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll index 8ddaf243db92..e298226ee7cc 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll @@ -680,7 +680,7 @@ define float @test_pown_afn_nnan_ninf_f32(float %x, i32 %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; @@ -703,7 +703,7 @@ define <2 x float> @test_pown_afn_nnan_ninf_v2f32(<2 x float> %x, <2 x i32> %y) ; CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP3]] ; @@ -772,7 +772,7 @@ define half @test_pown_afn_nnan_ninf_f16(half %x, i32 %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast half [[X]] to i16 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i16 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast half [[__EXP2]] to i16 -; CHECK-NEXT: [[TMP2:%.*]] = or i16 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i16 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i16 [[TMP2]] to half ; CHECK-NEXT: ret half [[TMP3]] ; @@ -795,7 +795,7 @@ define <2 x half> @test_pown_afn_nnan_ninf_v2f16(<2 x half> %x, <2 x i32> %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x half> [[X]] to <2 x i16> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i16> [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x half> [[__EXP2]] to <2 x i16> -; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i16> [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint <2 x i16> [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x i16> [[TMP2]] to <2 x half> ; CHECK-NEXT: ret <2 x half> [[TMP3]] ; @@ -829,7 +829,7 @@ define float @test_pown_fast_f32_strictfp(float %x, i32 %y) #1 { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; @@ -1075,7 +1075,7 @@ define float @test_pown_afn_ninf_nnan_f32__x_known_positive(float nofpclass(ninf ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; diff --git a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll index 204c8140d3f1..54ca33401ccf 100644 --- a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll +++ b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll @@ -360,7 +360,7 @@ declare half @_Z4pownDhi(half, i32) ; GCN-NATIVE: %0 = bitcast half %x to i16 ; GCN-NATIVE: %__pow_sign = and i16 %__yeven, %0 ; GCN-NATIVE: %1 = bitcast half %__exp2 to i16 -; GCN-NATIVE: %2 = or i16 %__pow_sign, %1 +; GCN-NATIVE: %2 = or disjoint i16 %__pow_sign, %1 ; GCN-NATIVE: %3 = bitcast i16 %2 to half define half @test_pown_f16(half %x, i32 %y) { entry: @@ -378,7 +378,7 @@ declare float @_Z4pownfi(float, i32) ; GCN: %[[r0:.*]] = bitcast float %tmp to i32 ; GCN: %__pow_sign = and i32 %[[r0]], -2147483648 ; GCN: %[[r1:.*]] = bitcast float %__exp2 to i32 -; GCN: %[[r2:.*]] = or i32 %__pow_sign, %[[r1]] +; GCN: %[[r2:.*]] = or disjoint i32 %__pow_sign, %[[r1]] ; GCN: store i32 %[[r2]], ptr addrspace(1) %a, align 4 define amdgpu_kernel void @test_pow(ptr addrspace(1) nocapture %a) { entry: @@ -414,7 +414,7 @@ entry: ; GCN: %[[r0:.*]] = bitcast float %tmp to i32 ; GCN: %__pow_sign = and i32 %__yeven, %[[r0]] ; GCN: %[[r1:.*]] = bitcast float %__exp2 to i32 -; GCN: %[[r2:.*]] = or i32 %__pow_sign, %[[r1]] +; GCN: %[[r2:.*]] = or disjoint i32 %__pow_sign, %[[r1]] ; GCN: store i32 %[[r2]], ptr addrspace(1) %a, align 4 define amdgpu_kernel void @test_pown(ptr addrspace(1) nocapture %a) { entry: @@ -438,7 +438,7 @@ declare <2 x half> @_Z3powDv2_DhS_(<2 x half>, <2 x half>) ; GCN: %1 = bitcast half %x to i16 ; GCN: %__pow_sign = and i16 %1, -32768 ; GCN: %2 = bitcast half %__exp2 to i16 -; GCN: %3 = or i16 %__pow_sign, %2 +; GCN: %3 = or disjoint i16 %__pow_sign, %2 ; GCN: %4 = bitcast i16 %3 to half define half @test_pow_fast_f16__y_13(half %x) { %powr = tail call fast half @_Z3powDhDh(half %x, half 13.0) @@ -453,7 +453,7 @@ define half @test_pow_fast_f16__y_13(half %x) { ; GCN: %1 = bitcast <2 x half> %x to <2 x i16> ; GCN: %__pow_sign = and <2 x i16> %1, ; GCN: %2 = bitcast <2 x half> %__exp2 to <2 x i16> -; GCN: %3 = or <2 x i16> %__pow_sign, %2 +; GCN: %3 = or disjoint <2 x i16> %__pow_sign, %2 ; GCN: %4 = bitcast <2 x i16> %3 to <2 x half> define <2 x half> @test_pow_fast_v2f16__y_13(<2 x half> %x) { %powr = tail call fast <2 x half> @_Z3powDv2_DhS_(<2 x half> %x, <2 x half> ) diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index 8b4249b2c25a..816bd6f352df 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1374,5 +1374,269 @@ define i8 @nonzero_reduce_xor_vscale_odd( %xx) { ret i8 %r } +define i1 @test_sign_pos(float %x) { +; CHECK-LABEL: @test_sign_pos( +; CHECK-NEXT: ret i1 true +; + %fabs = call float @llvm.fabs.f32(float %x) + %y = bitcast float %fabs to i32 + %sign = icmp sgt i32 %y, -1 + ret i1 %sign +} + +define i1 @test_sign_pos_half(half %x) { +; CHECK-LABEL: @test_sign_pos_half( +; CHECK-NEXT: ret i1 true +; + %fabs = call half @llvm.fabs.f16(half %x) + %y = bitcast half %fabs to i16 + %sign = icmp sgt i16 %y, -1 + ret i1 %sign +} + +define i1 @test_sign_pos_half_non_elementwise(<2 x half> %x) { +; CHECK-LABEL: @test_sign_pos_half_non_elementwise( +; CHECK-NEXT: [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]]) +; CHECK-NEXT: [[Y:%.*]] = bitcast <2 x half> [[FABS]] to i32 +; CHECK-NEXT: [[SIGN:%.*]] = icmp sgt i32 [[Y]], -1 +; CHECK-NEXT: ret i1 [[SIGN]] +; + %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x) + %y = bitcast <2 x half> %fabs to i32 + %sign = icmp sgt i32 %y, -1 + ret i1 %sign +} + +define i1 @test_sign_neg(float %x) { +; CHECK-LABEL: @test_sign_neg( +; CHECK-NEXT: ret i1 true +; + %fabs = call float @llvm.fabs.f32(float %x) + %fnabs = fneg float %fabs + %y = bitcast float %fnabs to i32 + %sign = icmp slt i32 %y, 0 + ret i1 %sign +} + +define <2 x i1> @test_sign_pos_vec(<2 x float> %x) { +; CHECK-LABEL: @test_sign_pos_vec( +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %x) + %y = bitcast <2 x float> %fabs to <2 x i32> + %sign = icmp slt <2 x i32> %y, zeroinitializer + ret <2 x i1> %sign +} + +define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) { +; CHECK-LABEL: @test_inf_only( +; CHECK-NEXT: ret i32 2139095040 +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2147483647 + ret i32 %and +} + +define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) { +; CHECK-LABEL: @test_inf_only_bfloat( +; CHECK-NEXT: ret i16 32640 +; + %y = bitcast bfloat %x to i16 + %and = and i16 %y, 32767 + ret i16 %and +} + +define i128 @test_inf_only_ppc_fp128(ppc_fp128 nofpclass(nan sub norm zero) %x) { +; CHECK-LABEL: @test_inf_only_ppc_fp128( +; CHECK-NEXT: ret i128 9218868437227405312 +; + %y = bitcast ppc_fp128 %x to i128 + %and = and i128 %y, 170141183460469231731687303715884105727 + ret i128 %and +} + +define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) { +; CHECK-LABEL: @test_zero_only( +; CHECK-NEXT: ret i32 0 +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2147483647 + ret i32 %and +} + +define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) { +; CHECK-LABEL: @test_zero_only_non_ieee( +; CHECK-NEXT: ret i80 0 +; + %y = bitcast x86_fp80 %x to i80 + %and = and i80 %y, 604462909807314587353087 + ret i80 %and +} + +define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) { +; CHECK-LABEL: @test_inf_nan_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2130706432 + ret i32 %and +} + +define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) { +; CHECK-LABEL: @test_sub_zero_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2130706432 + ret i32 %and +} + +define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) { +; CHECK-LABEL: @test_inf_zero_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 8388608 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 16777215 + ret i32 %and +} + + + +define i1 @test_simplify_icmp(i32 %x) { +; CHECK-LABEL: @test_simplify_icmp( +; CHECK-NEXT: ret i1 false +; + %cast1 = uitofp i32 %x to double + %cast2 = bitcast double %cast1 to i64 + %mask = and i64 %cast2, -140737488355328 + %cmp = icmp eq i64 %mask, -1970324836974592 + ret i1 %cmp +} + +define i32 @test_snan_quiet_bit1(float nofpclass(sub norm inf qnan) %x) { +; CHECK-LABEL: @test_snan_quiet_bit1( +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 4194304 +; CHECK-NEXT: ret i32 [[MASKED]] +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 4194304 + ret i32 %masked +} + +define i32 @test_snan_quiet_bit2(float nofpclass(sub norm inf qnan) %x) { +; CHECK-LABEL: @test_snan_quiet_bit2( +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 2097152 +; CHECK-NEXT: ret i32 [[MASKED]] +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 2097152 + ret i32 %masked +} + +define i32 @test_qnan_quiet_bit1(float nofpclass(sub norm inf snan) %x) { +; CHECK-LABEL: @test_qnan_quiet_bit1( +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 4194304 +; CHECK-NEXT: ret i32 [[MASKED]] +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 4194304 + ret i32 %masked +} + +define i32 @test_qnan_quiet_bit2(float nofpclass(sub norm inf snan) %x) { +; CHECK-LABEL: @test_qnan_quiet_bit2( +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 2097152 +; CHECK-NEXT: ret i32 [[MASKED]] +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 2097152 + ret i32 %masked +} + +define i16 @test_simplify_mask(i32 %ui, float %x) { +; CHECK-LABEL: @test_simplify_mask( +; CHECK-NEXT: [[CONV:%.*]] = uitofp i32 [[UI:%.*]] to float +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[CONV]], [[X:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]] +; CHECK: if.end: +; CHECK-NEXT: ret i16 31744 +; CHECK: if.else: +; CHECK-NEXT: ret i16 0 +; + %conv = uitofp i32 %ui to float + %cmp = fcmp olt float %x, %conv + br i1 %cmp, label %if.else, label %if.end + +if.end: + %cast = bitcast float %conv to i32 + %shr = lshr i32 %cast, 16 + %trunc = trunc i32 %shr to i16 + %and = and i16 %trunc, -32768 + %or = or disjoint i16 %and, 31744 + ret i16 %or + +if.else: + ret i16 0 +} + +; TODO: %cmp always evaluates to false + +define i1 @test_simplify_icmp2(double %x) { +; CHECK-LABEL: @test_simplify_icmp2( +; CHECK-NEXT: [[ABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]]) +; CHECK-NEXT: [[COND:%.*]] = fcmp oeq double [[ABS]], 0x7FF0000000000000 +; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[CAST:%.*]] = bitcast double [[X]] to i64 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[CAST]], 3458764513820540928 +; CHECK-NEXT: ret i1 [[CMP]] +; CHECK: if.else: +; CHECK-NEXT: ret i1 false +; + %abs = tail call double @llvm.fabs.f64(double %x) + %cond = fcmp oeq double %abs, 0x7FF0000000000000 + br i1 %cond, label %if.then, label %if.else + +if.then: + %cast = bitcast double %x to i64 + %cmp = icmp eq i64 %cast, 3458764513820540928 + ret i1 %cmp + +if.else: + ret i1 false +} + +define i32 @test_snan_only(float nofpclass(qnan sub norm zero inf) %x) { +; CHECK-LABEL: @test_snan_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 4194304 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 4194304 + ret i32 %and +} + +define i32 @test_qnan_only(float nofpclass(snan sub norm zero inf) %x) { +; CHECK-LABEL: @test_qnan_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 4194304 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 4194304 + ret i32 %and +} + declare void @use(i1) declare void @sink(i8) -- GitLab From 08177541267fff84a96701fc5fc232eb4f12f9d9 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 13 May 2024 10:37:12 -0700 Subject: [PATCH 112/578] [RISCV] Improve testing of loads with offset in local-stack-slot-allocation.ll. NFC The test we had didn't match it's description. Now we have one test with a large offset that requires a virtual base register and a test with a smaller offset that should not. There is currently a bug that causes the offset to double counted leading to the small case also using a virtual base register. --- .../RISCV/local-stack-slot-allocation.ll | 87 ++++++++++++------- 1 file changed, 54 insertions(+), 33 deletions(-) diff --git a/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll b/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll index 40d08513e3cf..c34e2bfdca08 100644 --- a/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll +++ b/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll @@ -47,48 +47,69 @@ define void @use_frame_base_reg() { } ; Test containing a load with its own local offset. Make sure isFrameOffsetLegal -; considers it and does not create a virtual base register. +; considers it and creates a virtual base register. define void @load_with_offset() { ; RV32I-LABEL: load_with_offset: ; RV32I: # %bb.0: -; RV32I-NEXT: lui a0, 25 -; RV32I-NEXT: addi a0, a0, -1792 -; RV32I-NEXT: sub sp, sp, a0 -; RV32I-NEXT: .cfi_def_cfa_offset 100608 -; RV32I-NEXT: lui a0, 25 -; RV32I-NEXT: add a0, sp, a0 -; RV32I-NEXT: lbu zero, -292(a0) -; RV32I-NEXT: lui a0, 24 -; RV32I-NEXT: add a0, sp, a0 -; RV32I-NEXT: lbu zero, 1704(a0) -; RV32I-NEXT: lui a0, 25 -; RV32I-NEXT: addi a0, a0, -1792 -; RV32I-NEXT: add sp, sp, a0 +; RV32I-NEXT: addi sp, sp, -2048 +; RV32I-NEXT: addi sp, sp, -464 +; RV32I-NEXT: .cfi_def_cfa_offset 2512 +; RV32I-NEXT: addi a0, sp, 2012 +; RV32I-NEXT: lbu a1, 0(a0) +; RV32I-NEXT: sb a1, 0(a0) +; RV32I-NEXT: addi sp, sp, 2032 +; RV32I-NEXT: addi sp, sp, 480 ; RV32I-NEXT: ret ; ; RV64I-LABEL: load_with_offset: ; RV64I: # %bb.0: -; RV64I-NEXT: lui a0, 25 -; RV64I-NEXT: addiw a0, a0, -1792 -; RV64I-NEXT: sub sp, sp, a0 -; RV64I-NEXT: .cfi_def_cfa_offset 100608 -; RV64I-NEXT: lui a0, 25 -; RV64I-NEXT: add a0, sp, a0 -; RV64I-NEXT: lbu zero, -292(a0) -; RV64I-NEXT: lui a0, 24 -; RV64I-NEXT: add a0, sp, a0 -; RV64I-NEXT: lbu zero, 1704(a0) -; RV64I-NEXT: lui a0, 25 -; RV64I-NEXT: addiw a0, a0, -1792 -; RV64I-NEXT: add sp, sp, a0 +; RV64I-NEXT: addi sp, sp, -2048 +; RV64I-NEXT: addi sp, sp, -464 +; RV64I-NEXT: .cfi_def_cfa_offset 2512 +; RV64I-NEXT: addi a0, sp, 2012 +; RV64I-NEXT: lbu a1, 0(a0) +; RV64I-NEXT: sb a1, 0(a0) +; RV64I-NEXT: addi sp, sp, 2032 +; RV64I-NEXT: addi sp, sp, 480 +; RV64I-NEXT: ret + + %va = alloca [2500 x i8], align 4 + %va_gep = getelementptr [2000 x i8], ptr %va, i64 0, i64 2000 + %load = load volatile i8, ptr %va_gep, align 4 + store volatile i8 %load, ptr %va_gep, align 4 + ret void +} + +; Test containing a load with its own local offset that is smaller than the +; previous test case. Make sure we don't create a virtual base register. +define void @load_with_offset2() { +; RV32I-LABEL: load_with_offset2: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -2048 +; RV32I-NEXT: addi sp, sp, -464 +; RV32I-NEXT: .cfi_def_cfa_offset 2512 +; RV32I-NEXT: addi a0, sp, 1412 +; RV32I-NEXT: lbu a1, 0(a0) +; RV32I-NEXT: sb a1, 0(a0) +; RV32I-NEXT: addi sp, sp, 2032 +; RV32I-NEXT: addi sp, sp, 480 +; RV32I-NEXT: ret +; +; RV64I-LABEL: load_with_offset2: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -2048 +; RV64I-NEXT: addi sp, sp, -464 +; RV64I-NEXT: .cfi_def_cfa_offset 2512 +; RV64I-NEXT: addi a0, sp, 1412 +; RV64I-NEXT: lbu a1, 0(a0) +; RV64I-NEXT: sb a1, 0(a0) +; RV64I-NEXT: addi sp, sp, 2032 +; RV64I-NEXT: addi sp, sp, 480 ; RV64I-NEXT: ret - %va = alloca [100 x i8], align 4 - %va1 = alloca [500 x i8], align 4 - %large = alloca [100000 x i8] - %va_gep = getelementptr [100 x i8], ptr %va, i64 16 - %va1_gep = getelementptr [100 x i8], ptr %va1, i64 0 + %va = alloca [2500 x i8], align 4 + %va_gep = getelementptr [2000 x i8], ptr %va, i64 0, i64 1400 %load = load volatile i8, ptr %va_gep, align 4 - %load1 = load volatile i8, ptr %va1_gep, align 4 + store volatile i8 %load, ptr %va_gep, align 4 ret void } -- GitLab From 026686bac606ac03d688a44f2ea4cb829d7b08bc Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 13 May 2024 10:51:17 -0700 Subject: [PATCH 113/578] [RISCV] Don't add getFrameIndexInstrOffset in RISCVRegisterInfo::needsFrameBaseReg. It's already added in isFrameOffsetLegal so adding it in needsFrameBaseReg causes it to be double counted. --- llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 1 - llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll | 10 ++++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index 6a48848e2022..c3281e409653 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -607,7 +607,6 @@ bool RISCVRegisterInfo::needsFrameBaseReg(MachineInstr *MI, const MachineFrameInfo &MFI = MF.getFrameInfo(); const RISCVFrameLowering *TFI = getFrameLowering(MF); const MachineRegisterInfo &MRI = MF.getRegInfo(); - Offset += getFrameIndexInstrOffset(MI, FIOperandNum); if (TFI->hasFP(MF) && !shouldRealignStack(MF)) { // Estimate the stack size used to store callee saved registers( diff --git a/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll b/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll index c34e2bfdca08..18e7992f30a3 100644 --- a/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll +++ b/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll @@ -88,9 +88,8 @@ define void @load_with_offset2() { ; RV32I-NEXT: addi sp, sp, -2048 ; RV32I-NEXT: addi sp, sp, -464 ; RV32I-NEXT: .cfi_def_cfa_offset 2512 -; RV32I-NEXT: addi a0, sp, 1412 -; RV32I-NEXT: lbu a1, 0(a0) -; RV32I-NEXT: sb a1, 0(a0) +; RV32I-NEXT: lbu a0, 1412(sp) +; RV32I-NEXT: sb a0, 1412(sp) ; RV32I-NEXT: addi sp, sp, 2032 ; RV32I-NEXT: addi sp, sp, 480 ; RV32I-NEXT: ret @@ -100,9 +99,8 @@ define void @load_with_offset2() { ; RV64I-NEXT: addi sp, sp, -2048 ; RV64I-NEXT: addi sp, sp, -464 ; RV64I-NEXT: .cfi_def_cfa_offset 2512 -; RV64I-NEXT: addi a0, sp, 1412 -; RV64I-NEXT: lbu a1, 0(a0) -; RV64I-NEXT: sb a1, 0(a0) +; RV64I-NEXT: lbu a0, 1412(sp) +; RV64I-NEXT: sb a0, 1412(sp) ; RV64I-NEXT: addi sp, sp, 2032 ; RV64I-NEXT: addi sp, sp, 480 ; RV64I-NEXT: ret -- GitLab From 66466ff151bd71fa64c63d951173efc589df2860 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Mon, 13 May 2024 12:30:50 -0500 Subject: [PATCH 114/578] Reland: [LLD] Implement --enable-non-contiguous-regions (#90007) When enabled, input sections that would otherwise overflow a memory region are instead spilled to the next matching output section. This feature parallels the one in GNU LD, but there are some differences from its documented behavior: - /DISCARD/ only matches previously-unmatched sections (i.e., the flag does not affect it). - If a section fails to fit at any of its matches, the link fails instead of discarding the section. - The flag --enable-non-contiguous-regions-warnings is not implemented, as it exists to warn about such occurrences. The implementation places stubs at possible spill locations, and replaces them with the original input section when effecting spills. Spilling decisions occur after address assignment. Sections are spilled in reverse order of assignment, with each spill naively decreasing the size of the affected memory regions. This continues until the memory regions are brought back under size. Spilling anything causes another pass of address assignment, and this continues to fixed point. Spilling after rather than during assignment allows the algorithm to consider the size effects of unspillable input sections that appear later in the assignment. Otherwise, such sections (e.g. thunks) may force an overflow, even if spilling something earlier could have avoided it. A few notable feature interactions occur: - Stubs affect alignment, ONLY_IF_RO, etc, broadly as if a copy of the input section were actually placed there. - SHF_MERGE synthetic sections use the spill list of their first contained input section (the one that gives the section its name). - ICF occurs oblivious to spill sections; spill lists for merged-away sections become inert and are removed after assignment. - SHF_LINK_ORDER and .ARM.exidx are ordered according to the final section ordering, after all spilling has completed. - INSERT BEFORE/AFTER and OVERWRITE_SECTIONS are explicitly disallowed. --- lld/ELF/Config.h | 1 + lld/ELF/Driver.cpp | 4 +- lld/ELF/InputSection.cpp | 7 + lld/ELF/InputSection.h | 25 +- lld/ELF/LinkerScript.cpp | 181 +++++++++++- lld/ELF/LinkerScript.h | 15 +- lld/ELF/Options.td | 3 + lld/ELF/OutputSections.cpp | 7 +- lld/ELF/OutputSections.h | 2 +- lld/ELF/SyntheticSections.cpp | 7 + lld/ELF/SyntheticSections.h | 4 + lld/ELF/Writer.cpp | 22 +- lld/docs/ELF/linker_script.rst | 11 + lld/docs/ReleaseNotes.rst | 6 + lld/docs/ld.lld.1 | 2 + ...able-non-contiguous-regions-arm-exidx.test | 55 ++++ .../enable-non-contiguous-regions.test | 265 ++++++++++++++++++ 17 files changed, 600 insertions(+), 17 deletions(-) create mode 100644 lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test create mode 100644 lld/test/ELF/linkerscript/enable-non-contiguous-regions.test diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index c55b547a733c..dbb81412453a 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -238,6 +238,7 @@ struct Config { bool emitLLVM; bool emitRelocs; bool enableNewDtags; + bool enableNonContiguousRegions; bool executeOnly; bool exportDynamic; bool fixCortexA53Errata843419; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index dd33f4bd772f..028cdcc83d2f 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1250,6 +1250,8 @@ static void readConfigs(opt::InputArgList &args) { config->emitRelocs = args.hasArg(OPT_emit_relocs); config->enableNewDtags = args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true); + config->enableNonContiguousRegions = + args.hasArg(OPT_enable_non_contiguous_regions); config->entry = args.getLastArgValue(OPT_entry); errorHandler().errorHandlingScript = @@ -3085,7 +3087,7 @@ template void LinkerDriver::link(opt::InputArgList &args) { // sectionBases. for (SectionCommand *cmd : script->sectionCommands) if (auto *osd = dyn_cast(cmd)) - osd->osec.finalizeInputSections(); + osd->osec.finalizeInputSections(&script.s); } // Two input sections with different output sections should not be folded. diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index fa81611e7c9e..2a1ccd997f8b 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -161,6 +161,7 @@ uint64_t SectionBase::getOffset(uint64_t offset) const { } case Regular: case Synthetic: + case Spill: return cast(this)->outSecOff + offset; case EHFrame: { // Two code paths may reach here. First, clang_rt.crtbegin.o and GCC @@ -309,6 +310,12 @@ std::string InputSectionBase::getObjMsg(uint64_t off) const { .str(); } +PotentialSpillSection::PotentialSpillSection(const InputSectionBase &source, + InputSectionDescription &isd) + : InputSection(source.file, source.flags, source.type, source.addralign, {}, + source.name, SectionBase::Spill), + isd(&isd) {} + InputSection InputSection::discarded(nullptr, 0, 0, 0, ArrayRef(), ""); InputSection::InputSection(InputFile *f, uint64_t flags, uint32_t type, diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 1fb7077ca435..58e5306fd6dc 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -48,7 +48,7 @@ template struct RelsOrRelas { // sections. class SectionBase { public: - enum Kind { Regular, Synthetic, EHFrame, Merge, Output }; + enum Kind { Regular, Synthetic, Spill, EHFrame, Merge, Output }; Kind kind() const { return (Kind)sectionKind; } @@ -382,7 +382,8 @@ public: static bool classof(const SectionBase *s) { return s->kind() == SectionBase::Regular || - s->kind() == SectionBase::Synthetic; + s->kind() == SectionBase::Synthetic || + s->kind() == SectionBase::Spill; } // Write this section to a mmap'ed file, assuming Buf is pointing to @@ -425,6 +426,26 @@ private: template void copyShtGroup(uint8_t *buf); }; +// A marker for a potential spill location for another input section. This +// broadly acts as if it were the original section until address assignment. +// Then it is either replaced with the real input section or removed. +class PotentialSpillSection : public InputSection { +public: + // The containing input section description; used to quickly replace this stub + // with the actual section. + InputSectionDescription *isd; + + // Next potential spill location for the same source input section. + PotentialSpillSection *next = nullptr; + + PotentialSpillSection(const InputSectionBase &source, + InputSectionDescription &isd); + + static bool classof(const SectionBase *sec) { + return sec->kind() == InputSectionBase::Spill; + } +}; + static_assert(sizeof(InputSection) <= 160, "InputSection is too big"); class SyntheticSection : public InputSection { diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index c0a5014817b9..3ba59c112b8a 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -304,6 +304,9 @@ getChangedSymbolAssignment(const SymbolAssignmentMap &oldValues) { void LinkerScript::processInsertCommands() { SmallVector moves; for (const InsertCommand &cmd : insertCommands) { + if (config->enableNonContiguousRegions) + error("INSERT cannot be used with --enable-non-contiguous-regions"); + for (StringRef name : cmd.names) { // If base is empty, it may have been discarded by // adjustOutputSections(). We do not handle such output sections. @@ -486,10 +489,12 @@ static void sortInputSections(MutableArrayRef vec, // Compute and remember which sections the InputSectionDescription matches. SmallVector LinkerScript::computeInputSections(const InputSectionDescription *cmd, - ArrayRef sections) { + ArrayRef sections, + const OutputSection &outCmd) { SmallVector ret; SmallVector indexes; DenseSet seen; + DenseSet spills; auto sortByPositionThenCommandLine = [&](size_t begin, size_t end) { llvm::sort(MutableArrayRef(indexes).slice(begin, end - begin)); for (size_t i = begin; i != end; ++i) @@ -505,10 +510,10 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd, size_t sizeBeforeCurrPat = ret.size(); for (size_t i = 0, e = sections.size(); i != e; ++i) { - // Skip if the section is dead or has been matched by a previous input - // section description or a previous pattern. + // Skip if the section is dead or has been matched by a previous pattern + // in this input section description. InputSectionBase *sec = sections[i]; - if (!sec->isLive() || sec->parent || seen.contains(i)) + if (!sec->isLive() || seen.contains(i)) continue; // For --emit-relocs we have to ignore entries like @@ -529,6 +534,29 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd, (sec->flags & cmd->withoutFlags) != 0) continue; + if (sec->parent) { + // Skip if not allowing multiple matches. + if (!config->enableNonContiguousRegions) + continue; + + // Disallow spilling into /DISCARD/; special handling would be needed + // for this in address assignment, and the semantics are nebulous. + if (outCmd.name == "/DISCARD/") + continue; + + // Skip if the section's first match was /DISCARD/; such sections are + // always discarded. + if (sec->parent->name == "/DISCARD/") + continue; + + // Skip if the section was already matched by a different input section + // description within this output section. + if (sec->parent == &outCmd) + continue; + + spills.insert(sec); + } + ret.push_back(sec); indexes.push_back(i); seen.insert(i); @@ -555,6 +583,30 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd, // Matched sections after the last SORT* are sorted by (--sort-alignment, // input order). sortByPositionThenCommandLine(sizeAfterPrevSort, ret.size()); + + // The flag --enable-non-contiguous-regions may cause sections to match an + // InputSectionDescription in more than one OutputSection. Matches after the + // first were collected in the spills set, so replace these with potential + // spill sections. + if (!spills.empty()) { + for (InputSectionBase *&sec : ret) { + if (!spills.contains(sec)) + continue; + + // Append the spill input section to the list for the input section, + // creating it if necessary. + PotentialSpillSection *pss = make( + *sec, const_cast(*cmd)); + auto [it, inserted] = + potentialSpillLists.try_emplace(sec, PotentialSpillList{pss, pss}); + if (!inserted) { + PotentialSpillSection *&tail = it->second.tail; + tail = tail->next = pss; + } + sec = pss; + } + } + return ret; } @@ -577,7 +629,7 @@ void LinkerScript::discardSynthetic(OutputSection &outCmd) { part.armExidx->exidxSections.end()); for (SectionCommand *cmd : outCmd.commands) if (auto *isd = dyn_cast(cmd)) - for (InputSectionBase *s : computeInputSections(isd, secs)) + for (InputSectionBase *s : computeInputSections(isd, secs, outCmd)) discard(*s); } } @@ -588,7 +640,7 @@ LinkerScript::createInputSectionList(OutputSection &outCmd) { for (SectionCommand *cmd : outCmd.commands) { if (auto *isd = dyn_cast(cmd)) { - isd->sectionBases = computeInputSections(isd, ctx.inputSections); + isd->sectionBases = computeInputSections(isd, ctx.inputSections, outCmd); for (InputSectionBase *s : isd->sectionBases) s->parent = &outCmd; ret.insert(ret.end(), isd->sectionBases.begin(), isd->sectionBases.end()); @@ -644,6 +696,9 @@ void LinkerScript::processSectionCommands() { // Process OVERWRITE_SECTIONS first so that it can overwrite the main script // or orphans. + if (config->enableNonContiguousRegions && !overwriteSections.empty()) + error("OVERWRITE_SECTIONS cannot be used with " + "--enable-non-contiguous-regions"); DenseMap map; size_t i = 0; for (OutputDesc *osd : overwriteSections) { @@ -1066,8 +1121,12 @@ void LinkerScript::assignOffsets(OutputSection *sec) { // Handle a single input section description command. // It calculates and assigns the offsets for each section and also // updates the output section size. - for (InputSection *isec : cast(cmd)->sections) { + + auto §ions = cast(cmd)->sections; + for (InputSection *isec : sections) { assert(isec->getParent() == sec); + if (isa(isec)) + continue; const uint64_t pos = dot; dot = alignToPowerOf2(dot, isec->addralign); isec->outSecOff = dot - sec->addr; @@ -1364,6 +1423,114 @@ const Defined *LinkerScript::assignAddresses() { return getChangedSymbolAssignment(oldValues); } +static bool hasRegionOverflowed(MemoryRegion *mr) { + if (!mr) + return false; + return mr->curPos - mr->getOrigin() > mr->getLength(); +} + +// Spill input sections in reverse order of address assignment to (potentially) +// bring memory regions out of overflow. The size savings of a spill can only be +// estimated, since general linker script arithmetic may occur afterwards. +// Under-estimates may cause unnecessary spills, but over-estimates can always +// be corrected on the next pass. +bool LinkerScript::spillSections() { + if (!config->enableNonContiguousRegions) + return false; + + bool spilled = false; + for (SectionCommand *cmd : reverse(sectionCommands)) { + auto *od = dyn_cast(cmd); + if (!od) + continue; + OutputSection *osec = &od->osec; + if (!osec->memRegion) + continue; + + // Input sections that have replaced a potential spill and should be removed + // from their input section description. + DenseSet spilledInputSections; + + for (SectionCommand *cmd : reverse(osec->commands)) { + if (!hasRegionOverflowed(osec->memRegion) && + !hasRegionOverflowed(osec->lmaRegion)) + break; + + auto *isd = dyn_cast(cmd); + if (!isd) + continue; + for (InputSection *isec : reverse(isd->sections)) { + // Potential spill locations cannot be spilled. + if (isa(isec)) + continue; + + // Find the next potential spill location and remove it from the list. + auto it = potentialSpillLists.find(isec); + if (it == potentialSpillLists.end()) + continue; + PotentialSpillList &list = it->second; + PotentialSpillSection *spill = list.head; + if (spill->next) + list.head = spill->next; + else + potentialSpillLists.erase(isec); + + // Replace the next spill location with the spilled section and adjust + // its properties to match the new location. Note that the alignment of + // the spill section may have diverged from the original due to e.g. a + // SUBALIGN. Correct assignment requires the spill's alignment to be + // used, not the original. + spilledInputSections.insert(isec); + *llvm::find(spill->isd->sections, spill) = isec; + isec->parent = spill->parent; + isec->addralign = spill->addralign; + + // Record the (potential) reduction in the region's end position. + osec->memRegion->curPos -= isec->getSize(); + if (osec->lmaRegion) + osec->lmaRegion->curPos -= isec->getSize(); + + // Spilling continues until the end position no longer overflows the + // region. Then, another round of address assignment will either confirm + // the spill's success or lead to yet more spilling. + if (!hasRegionOverflowed(osec->memRegion) && + !hasRegionOverflowed(osec->lmaRegion)) + break; + } + + // Remove any spilled input sections to complete their move. + if (!spilledInputSections.empty()) { + spilled = true; + llvm::erase_if(isd->sections, [&](InputSection *isec) { + return spilledInputSections.contains(isec); + }); + } + } + } + + return spilled; +} + +// Erase any potential spill sections that were not used. +void LinkerScript::erasePotentialSpillSections() { + if (potentialSpillLists.empty()) + return; + + // Collect the set of input section descriptions that contain potential + // spills. + DenseSet isds; + for (const auto &[_, list] : potentialSpillLists) + for (PotentialSpillSection *s = list.head; s; s = s->next) + isds.insert(s->isd); + + for (InputSectionDescription *isd : isds) + llvm::erase_if(isd->sections, [](InputSection *s) { + return isa(s); + }); + + potentialSpillLists.clear(); +} + // Creates program headers as instructed by PHDRS linker script command. SmallVector LinkerScript::createPhdrs() { SmallVector ret; diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index b09cd12c46f9..734d4e7498aa 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -10,6 +10,7 @@ #define LLD_ELF_LINKER_SCRIPT_H #include "Config.h" +#include "InputSection.h" #include "Writer.h" #include "lld/Common/LLVM.h" #include "lld/Common/Strings.h" @@ -287,7 +288,8 @@ class LinkerScript final { SmallVector computeInputSections(const InputSectionDescription *, - ArrayRef); + ArrayRef, + const OutputSection &outCmd); SmallVector createInputSectionList(OutputSection &cmd); @@ -333,6 +335,8 @@ public: bool shouldKeep(InputSectionBase *s); const Defined *assignAddresses(); + bool spillSections(); + void erasePotentialSpillSections(); void allocateHeaders(SmallVector &phdrs); void processSectionCommands(); void processSymbolAssignments(); @@ -400,6 +404,15 @@ public: // // then provideMap should contain the mapping: 'v' -> ['a', 'b', 'c'] llvm::MapVector> provideMap; + + // List of potential spill locations (PotentialSpillSection) for an input + // section. + struct PotentialSpillList { + // Never nullptr. + PotentialSpillSection *head; + PotentialSpillSection *tail; + }; + llvm::DenseMap potentialSpillLists; }; struct ScriptWrapper { diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index b9e05a4b1fd5..883a6079bf50 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -197,6 +197,9 @@ def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">; def enable_new_dtags: F<"enable-new-dtags">, HelpText<"Enable new dynamic tags (default)">; +def enable_non_contiguous_regions : FF<"enable-non-contiguous-regions">, + HelpText<"Spill input sections to later matching output sections to avoid memory region overflow">; + def end_group: F<"end-group">, HelpText<"Ignored for compatibility with GNU unless you pass --warn-backrefs">; diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 9c667241360f..fcb4c4387aa9 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -186,7 +186,7 @@ static MergeSyntheticSection *createMergeSynthetic(StringRef name, // new synthetic sections at the location of the first input section // that it replaces. It then finalizes each synthetic section in order // to compute an output offset for each piece of each input section. -void OutputSection::finalizeInputSections() { +void OutputSection::finalizeInputSections(LinkerScript *script) { std::vector mergeSections; for (SectionCommand *cmd : commands) { auto *isd = dyn_cast(cmd); @@ -226,6 +226,11 @@ void OutputSection::finalizeInputSections() { i = std::prev(mergeSections.end()); syn->entsize = ms->entsize; isd->sections.push_back(syn); + // The merge synthetic section inherits the potential spill locations of + // its first contained section. + auto it = script->potentialSpillLists.find(ms); + if (it != script->potentialSpillLists.end()) + script->potentialSpillLists.try_emplace(syn, it->second); } (*i)->addSection(ms); } diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 421a0181feb5..78fede48a23f 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -75,7 +75,7 @@ public: void recordSection(InputSectionBase *isec); void commitSection(InputSection *isec); - void finalizeInputSections(); + void finalizeInputSections(LinkerScript *script = nullptr); // The following members are normally only used in linker scripts. MemoryRegion *memRegion = nullptr; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 7b9ada40c0f6..298c714adb3b 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4074,6 +4074,13 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) { // InputSection with the highest address and any InputSections that have // mergeable .ARM.exidx table entries are removed from it. void ARMExidxSyntheticSection::finalizeContents() { + // Ensure that any fixed-point iterations after the first see the original set + // of sections. + if (!originalExecutableSections.empty()) + executableSections = originalExecutableSections; + else if (config->enableNonContiguousRegions) + originalExecutableSections = executableSections; + // The executableSections and exidxSections that we use to derive the final // contents of this SyntheticSection are populated before // processSectionCommands() and ICF. A /DISCARD/ entry in SECTIONS command or diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 995fd4b344b0..34949025a45f 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1255,6 +1255,10 @@ private: // either find the .ARM.exidx section or know that we need to generate one. SmallVector executableSections; + // Value of executableSecitons before finalizeContents(), so that it can be + // run repeateadly during fixed point iteration. + SmallVector originalExecutableSections; + // The executable InputSection with the highest address to use for the // sentinel. We store separately from ExecutableSections as merging of // duplicate entries may mean this InputSection is removed from diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index e400ed2ae945..8d529f2bdb9f 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1403,13 +1403,18 @@ template void Writer::finalizeAddressDependentContent() { AArch64Err843419Patcher a64p; ARMErr657417Patcher a32p; script->assignAddresses(); + // .ARM.exidx and SHF_LINK_ORDER do not require precise addresses, but they // do require the relative addresses of OutputSections because linker scripts // can assign Virtual Addresses to OutputSections that are not monotonically - // increasing. - for (Partition &part : partitions) - finalizeSynthetic(part.armExidx.get()); - resolveShfLinkOrder(); + // increasing. Anything here must be repeatable, since spilling may change + // section order. + const auto finalizeOrderDependentContent = [this] { + for (Partition &part : partitions) + finalizeSynthetic(part.armExidx.get()); + resolveShfLinkOrder(); + }; + finalizeOrderDependentContent(); // Converts call x@GDPLT to call __tls_get_addr if (config->emachine == EM_HEXAGON) @@ -1419,6 +1424,8 @@ template void Writer::finalizeAddressDependentContent() { for (;;) { bool changed = target->needsThunks ? tc.createThunks(pass, outputSections) : target->relaxOnce(pass); + bool spilled = script->spillSections(); + changed |= spilled; ++pass; // With Thunk Size much smaller than branch range we expect to @@ -1464,6 +1471,9 @@ template void Writer::finalizeAddressDependentContent() { " does not converge"); break; } + } else if (spilled) { + // Spilling can change relative section order. + finalizeOrderDependentContent(); } } if (!config->relocatable) @@ -1483,6 +1493,10 @@ template void Writer::finalizeAddressDependentContent() { osec->name + " is not a multiple of alignment (" + Twine(osec->addralign) + ")"); } + + // Sizes are no longer allowed to grow, so all allowable spills have been + // taken. Remove any leftover potential spills. + script->erasePotentialSpillSections(); } // If Input Sections have been shrunk (basic block sections) then diff --git a/lld/docs/ELF/linker_script.rst b/lld/docs/ELF/linker_script.rst index 3606ef4fe4b8..7a35534be096 100644 --- a/lld/docs/ELF/linker_script.rst +++ b/lld/docs/ELF/linker_script.rst @@ -197,3 +197,14 @@ the current location to a max-page-size boundary, ensuring that the next LLD will insert ``.relro_padding`` immediately before the symbol assignment using ``DATA_SEGMENT_RELRO_END``. + +Non-contiguous regions +~~~~~~~~~~~~~~~~~~~~~~ + +The flag ``--enable-non-contiguous-regions`` allows input sections to spill to +later matches rather than causing the link to fail by overflowing a memory +region. Unlike GNU ld, ``/DISCARD/`` only matches previously-unmatched sections +(i.e., the flag does not affect it). Also, if a section fails to fit at any of +its matches, the link fails instead of discarding the section. Accordingly, the +GNU flag ``--enable-non-contiguous-regions-warnings`` is not implemented, as it +exists to warn about such occurrences. diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index f8fdebfeaecf..e7a913e025da 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -38,6 +38,12 @@ ELF Improvements * ``--debug-names`` is added to create a merged ``.debug_names`` index from input ``.debug_names`` sections. Type units are not handled yet. (`#86508 `_) +* ``--enable-non-contiguous-regions`` option allows automatically packing input + sections into memory regions by automatically spilling to later matches if a + region would overflow. This reduces the toil of manually packing regions + (typical for embedded). It also makes full LTO feasible in such cases, since + IR merging currently prevents the linker script from referring to input + files. (`#90007 `_) Breaking changes ---------------- diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index 9ea1a9c52f2a..0df13f07f560 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -222,6 +222,8 @@ segment header. Generate relocations in the output. .It Fl -enable-new-dtags Enable new dynamic tags. +.It Fl -enable-non-contiguous-regions +Spill input sections to later matching output sections to avoid memory region overflow. .It Fl -end-lib End a grouping of objects that should be treated as if they were together in an archive. diff --git a/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test b/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test new file mode 100644 index 000000000000..3f7b9c4e5f8b --- /dev/null +++ b/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test @@ -0,0 +1,55 @@ +## When spilling reorders input sections, the .ARM.exidx table is rebuilt using +## the new order. + +# REQUIRES: arm +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi test.s -o test.o +# RUN: ld.lld -T test.ld test.o -o test --enable-non-contiguous-regions +# RUN: llvm-readobj -x .ARM.exidx test | FileCheck %s + +# CHECK: 20000000 08849780 1c000000 10849880 +# CHECK-NEXT: 1c000000 01000000 + +#--- test.ld +MEMORY { + exidx : ORIGIN = 0, LENGTH = 32 + a : ORIGIN = 32, LENGTH = 4 + b : ORIGIN = 36, LENGTH = 4 + c : ORIGIN = 40, LENGTH = 4 +} + +SECTIONS { + .ARM.exidx : { *(.ARM.exidx) } >exidx + .first_chance : { *(.text .text.f2) } >a + .text.f1 : { *(.text.f1) } >b + .last_chance : { *(.text.f2) } >c +} + +#--- test.s + .syntax unified + .section .text, "ax",%progbits + .globl _start +_start: + .fnstart + bx lr + .save {r7, lr} + .setfp r7, sp, #0 + .fnend + + .section .text.f1, "ax", %progbits + .globl f1 +f1: + .fnstart + bx lr + .save {r8, lr} + .setfp r8, sp, #0 + .fnend + + .section .text.f2, "ax", %progbits + .globl f2 +f2: + .fnstart + bx lr + .save {r8, lr} + .setfp r8, sp, #0 + .fnend diff --git a/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test b/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test new file mode 100644 index 000000000000..392106fd476f --- /dev/null +++ b/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test @@ -0,0 +1,265 @@ +# REQUIRES: x86 + +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -n -filetype=obj -triple=x86_64 spill.s -o spill.o + +## An input section spills to a later match when the region of its first match +## would overflow. The spill uses the alignment of the later match. + +# RUN: ld.lld -T spill.ld spill.o -o spill --enable-non-contiguous-regions +# RUN: llvm-readelf -S spill | FileCheck %s --check-prefix=SPILL + +# SPILL: Name Type Address Off Size +# SPILL: .first_chance PROGBITS 0000000000000000 001000 000001 +# SPILL-NEXT: .last_chance PROGBITS 0000000000000008 001008 000002 + +## A spill off the end still fails the link. + +# RUN: not ld.lld -T spill-fail.ld spill.o --enable-non-contiguous-regions 2>&1 |\ +# RUN: FileCheck %s --check-prefix=SPILL-FAIL --implicit-check-not=error: + +# SPILL-FAIL: error: section '.last_chance' will not fit in region 'b': overflowed by 2 bytes + +## The above spill still occurs when the LMA would overflow, even though the +## VMA would fit. + +# RUN: ld.lld -T spill-lma.ld spill.o -o spill-lma --enable-non-contiguous-regions +# RUN: llvm-readelf -S spill-lma | FileCheck %s --check-prefix=SPILL-LMA + +# SPILL-LMA: Name Type Address Off Size +# SPILL-LMA: .first_chance PROGBITS 0000000000000000 001000 000001 +# SPILL-LMA-NEXT: .last_chance PROGBITS 0000000000000003 001003 000002 + +## A spill occurs to an additional match after the first. + +# RUN: ld.lld -T spill-later.ld spill.o -o spill-later --enable-non-contiguous-regions +# RUN: llvm-readelf -S spill-later | FileCheck %s --check-prefix=SPILL-LATER + +# SPILL-LATER: Name Type Address Off Size +# SPILL-LATER: .first_chance PROGBITS 0000000000000000 001000 000001 +# SPILL-LATER-NEXT: .second_chance PROGBITS 0000000000000002 001001 000000 +# SPILL-LATER-NEXT: .last_chance PROGBITS 0000000000000003 001003 000002 + +## A later overflow causes an earlier section to spill. + +# RUN: ld.lld -T spill-earlier.ld spill.o -o spill-earlier --enable-non-contiguous-regions +# RUN: llvm-readelf -S spill-earlier | FileCheck %s --check-prefix=SPILL-EARLIER + +# SPILL-EARLIER: Name Type Address Off Size +# SPILL-EARLIER: .first_chance PROGBITS 0000000000000000 001000 000002 +# SPILL-EARLIER-NEXT: .last_chance PROGBITS 0000000000000002 001002 000001 + +## An additional match in /DISCARD/ has no effect. + +# RUN: not ld.lld -T no-spill-into-discard.ld spill.o --enable-non-contiguous-regions 2>&1 |\ +# RUN: FileCheck %s --check-prefix=NO-SPILL-INTO-DISCARD --implicit-check-not=error: + +# NO-SPILL-INTO-DISCARD: error: section '.osec' will not fit in region 'a': overflowed by 1 bytes + +## An additional match after /DISCARD/ has no effect. + +# RUN: ld.lld -T no-spill-from-discard.ld spill.o -o no-spill-from-discard --enable-non-contiguous-regions +# RUN: llvm-readelf -S no-spill-from-discard | FileCheck %s --check-prefix=NO-SPILL-FROM-DISCARD + +# NO-SPILL-FROM-DISCARD: Name Type Address Off Size +# NO-SPILL-FROM-DISCARD-NOT: .osec + +## SHF_MERGEd sections are spilled according to the matches of the first merged +## input section (the one giving the resulting section its name). + +# RUN: llvm-mc -n -filetype=obj -triple=x86_64 merge.s -o merge.o +# RUN: ld.lld -T spill-merge.ld merge.o -o spill-merge --enable-non-contiguous-regions +# RUN: llvm-readelf -S spill-merge | FileCheck %s --check-prefix=SPILL-MERGE + +# SPILL-MERGE: Name Type Address Off Size +# SPILL-MERGE: .first PROGBITS 0000000000000000 000190 000000 +# SPILL-MERGE-NEXT: .second PROGBITS 0000000000000001 001001 000002 +# SPILL-MERGE-NEXT: .third PROGBITS 0000000000000003 001003 000000 + +## An error is reported for INSERT. + +# RUN: not ld.lld -T insert.ld spill.o --enable-non-contiguous-regions 2>&1 |\ +# RUN: FileCheck %s --check-prefix=INSERT + +# INSERT: error: INSERT cannot be used with --enable-non-contiguous-regions + +## An error is reported for OVERWRITE_SECTIONS. + +# RUN: not ld.lld -T overwrite-sections.ld spill.o --enable-non-contiguous-regions 2>&1 |\ +# RUN: FileCheck %s --check-prefix=OVERWRITE_SECTIONS + +# OVERWRITE_SECTIONS: error: OVERWRITE_SECTIONS cannot be used with --enable-non-contiguous-regions + +## SHF_LINK_ORDER is reordered when spilling changes relative section order. + +# RUN: llvm-mc -n -filetype=obj -triple=x86_64 link-order.s -o link-order.o +# RUN: ld.lld -T link-order.ld link-order.o -o link-order --enable-non-contiguous-regions +# RUN: llvm-readobj -x .order link-order | FileCheck %s --check-prefix=LINK-ORDER + +# LINK-ORDER: 020301 + +#--- spill.s +.section .one_byte_section,"a",@progbits +.fill 1 + +.section .two_byte_section,"a",@progbits +.fill 2 + +#--- spill.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 2 + b : ORIGIN = 2, LENGTH = 16 +} + +SECTIONS { + .first_chance : SUBALIGN(1) { *(.one_byte_section) *(.two_byte_section) } >a + .last_chance : SUBALIGN(8) { *(.two_byte_section) } >b +} + +#--- spill-fail.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 1 + b : ORIGIN = 2, LENGTH = 0 +} + +SECTIONS { + .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a + .last_chance : { *(.two_byte_section) } >b +} + +#--- spill-lma.ld +MEMORY { + vma_a : ORIGIN = 0, LENGTH = 3 + vma_b : ORIGIN = 3, LENGTH = 3 + lma_a : ORIGIN = 6, LENGTH = 2 + lma_b : ORIGIN = 8, LENGTH = 2 +} + +SECTIONS { + .first_chance : { *(.one_byte_section) *(.two_byte_section) } >vma_a AT>lma_a + .last_chance : { *(.two_byte_section) } >vma_b AT>lma_b +} + +#--- spill-later.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 2 + b : ORIGIN = 2, LENGTH = 1 + c : ORIGIN = 3, LENGTH = 2 +} + +SECTIONS { + .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a + .second_chance : { *(.two_byte_section) } >b + .last_chance : { *(.two_byte_section) } >c +} + +#--- spill-earlier.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 2 + b : ORIGIN = 2, LENGTH = 1 +} + +SECTIONS { + .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a + .last_chance : { *(.one_byte_section) } >b +} + +#--- no-spill-into-discard.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 1 +} + +SECTIONS { + .osec : { *(.two_byte_section) } >a + /DISCARD/ : { *(.one_byte_section) *(.two_byte_section) } +} + +#--- no-spill-from-discard.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 2 +} + +SECTIONS { + /DISCARD/ : { *(.one_byte_section) *(.two_byte_section) } + .osec : { *(.two_byte_section) } >a +} + +#--- merge.s +.section .a,"aM",@progbits,1 +.byte 0x12, 0x34 + +.section .b,"aM",@progbits,1 +.byte 0x12 + +#--- spill-merge.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 1 + b : ORIGIN = 1, LENGTH = 2 + c : ORIGIN = 3, LENGTH = 2 +} + +SECTIONS { + .first : { *(.a) *(.b) } >a + .second : { *(.a) } >b + .third : { *(.b) } >c +} + +#--- insert.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 1 +} + +SECTIONS { + .a : { *(.two_byte_section) } >a +} + +SECTIONS { + .b : { *(.one_byte_section) } >a +} INSERT AFTER .a; + +#--- overwrite-sections.ld +MEMORY { + a : ORIGIN = 0, LENGTH = 1 +} + +SECTIONS { + .a : { *(.two_byte_section) } >a +} + +OVERWRITE_SECTIONS { + .b : { *(.one_byte_section) } >a +} + +#--- link-order.s +.section .a,"a",@progbits +.fill 1 + +.section .b,"a",@progbits +.fill 1 + +.section .c,"a",@progbits +.fill 1 + +.section .link_order.a,"ao",@progbits,.a +.byte 1 + +.section .link_order.b,"ao",@progbits,.b +.byte 2 + +.section .link_order.c,"ao",@progbits,.c +.byte 3 + +#--- link-order.ld +MEMORY { + order : ORIGIN = 0, LENGTH = 3 + potential_a : ORIGIN = 3, LENGTH = 0 + bc : ORIGIN = 3, LENGTH = 2 + actual_a : ORIGIN = 5, LENGTH = 1 +} + +SECTIONS { + .order : { *(.link_order.*) } > order + .potential_a : { *(.a) } >potential_a + .bc : { *(.b) *(.c) } >bc + .actual_a : { *(.a) } >actual_a +} -- GitLab From dc7ce3b41c936c4cc189b4bbf6a2e3b5475d9fc5 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 13 May 2024 19:12:49 +0100 Subject: [PATCH 115/578] [lldb][TypeSystem][NFCI] Log creation of new TypeSystem instances to expression log (#91985) We emit `ASTContext` and `TypeSystem` pointers into the `expr` log but there is no easy way (that I know of) to correlate the pointer value back to an easily readible form. This patch simply logs the name of the `TypeSystem` and the associated `ASTContext` into the `expr` channel whenever we create a new `TypeSystemClang`. The following is an example of the new log entries: ``` $ grep Created /tmp/lldb.log Created new TypeSystem for (ASTContext*)0x0000000101a2e200 'ASTContext for '/Users/michaelbuch/a.out'' Created new TypeSystem for (ASTContext*)0x0000000102512a00 'scratch ASTContext' Created new TypeSystem for (ASTContext*)0x0000000102116a00 'ClangModulesDeclVendor ASTContext' Created new TypeSystem for (ASTContext*)0x00000001022e8c00 'Expression ASTContext for ''' Created new TypeSystem for (ASTContext*)0x00000001103e7200 'AppleObjCTypeEncodingParser ASTContext' Created new TypeSystem for (ASTContext*)0x00000001103f7000 'AppleObjCDeclVendor AST' Created new TypeSystem for (ASTContext*)0x00000001104bfe00 'Expression ASTContext for ''' Created new TypeSystem for (ASTContext*)0x0000000101f01000 'Expression ASTContext for ''' Created new TypeSystem for (ASTContext*)0x00000001025d3c00 'Expression ASTContext for ''' Created new TypeSystem for (ASTContext*)0x0000000110422400 'Expression ASTContext for ''' Created new TypeSystem for (ASTContext*)0x000000011602c200 'Expression ASTContext for ''' Created new TypeSystem for (ASTContext*)0x0000000110641600 'Expression ASTContext for ''' Created new TypeSystem for (ASTContext*)0x0000000110617400 'Expression ASTContext for ''' ``` --- .../Plugins/TypeSystem/Clang/TypeSystemClang.cpp | 12 +++++++++++- .../Plugins/TypeSystem/Clang/TypeSystemClang.h | 8 +++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index d0033fcd9cdf..17a9c675fbba 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -501,6 +501,8 @@ TypeSystemClang::TypeSystemClang(llvm::StringRef name, // The caller didn't pass an ASTContext so create a new one for this // TypeSystemClang. CreateASTContext(); + + LogCreation(); } TypeSystemClang::TypeSystemClang(llvm::StringRef name, @@ -510,6 +512,8 @@ TypeSystemClang::TypeSystemClang(llvm::StringRef name, m_ast_up.reset(&existing_ctxt); GetASTMap().Insert(&existing_ctxt, this); + + LogCreation(); } // Destructor @@ -630,7 +634,7 @@ void TypeSystemClang::SetExternalSource( ast.setExternalSource(ast_source_up); } -ASTContext &TypeSystemClang::getASTContext() { +ASTContext &TypeSystemClang::getASTContext() const { assert(m_ast_up); return *m_ast_up; } @@ -9750,3 +9754,9 @@ bool TypeSystemClang::SetDeclIsForcefullyCompleted(const clang::TagDecl *td) { metadata->SetIsForcefullyCompleted(); return true; } + +void TypeSystemClang::LogCreation() const { + if (auto *log = GetLog(LLDBLog::Expressions)) + LLDB_LOG(log, "Created new TypeSystem for (ASTContext*){0:x} '{1}'", + &getASTContext(), getDisplayName()); +} diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 59ca69622d9e..042379d40bcb 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -162,7 +162,7 @@ public: llvm::StringRef getDisplayName() const { return m_display_name; } /// Returns the clang::ASTContext instance managed by this TypeSystemClang. - clang::ASTContext &getASTContext(); + clang::ASTContext &getASTContext() const; clang::MangleContext *getMangleContext(); @@ -1166,6 +1166,12 @@ private: bool IsTypeImpl(lldb::opaque_compiler_type_t type, llvm::function_ref predicate) const; + /// Emits information about this TypeSystem into the expression log. + /// + /// Helper method that is used in \ref TypeSystemClang::TypeSystemClang + /// on creation of a new instance. + void LogCreation() const; + // Classes that inherit from TypeSystemClang can see and modify these std::string m_target_triple; std::unique_ptr m_ast_up; -- GitLab From 4a67f809828e11988c6a097cb400fd7cbbf47628 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 13 May 2024 11:25:12 -0700 Subject: [PATCH 116/578] [test] Fix check prefixes --- .../CodeGen/AArch64/aarch64_tree_tests.ll | 40 +++++++++---------- llvm/test/CodeGen/SPARC/inlineasm-bad.ll | 5 +-- llvm/test/MC/AArch64/SVE/index.s | 16 ++++---- llvm/test/MC/XCOFF/inlineasm.s | 2 +- .../PhaseOrdering/lifetime-sanitizer.ll | 20 +++++----- .../test/tools/dsymutil/ARM/dwarf5-macho.test | 26 ++++++------ 6 files changed, 54 insertions(+), 55 deletions(-) diff --git a/llvm/test/CodeGen/AArch64/aarch64_tree_tests.ll b/llvm/test/CodeGen/AArch64/aarch64_tree_tests.ll index 0a06765a8f75..f66f96cf463b 100644 --- a/llvm/test/CodeGen/AArch64/aarch64_tree_tests.ll +++ b/llvm/test/CodeGen/AArch64/aarch64_tree_tests.ll @@ -1,19 +1,18 @@ -; RUN: llc < %s | FileCheck %s +; RUN: llc < %s | FileCheck %s ; ModuleID = 'aarch64_tree_tests.bc' target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" target triple = "arm64--linux-gnu" -; FIXME: Misspelled CHECK-LABEL -; CHECK-LABLE: @aarch64_tree_tests_and -; CHECK: .hword 32768 -; CHECK: .hword 32767 -; CHECK: .hword 4664 -; CHECK: .hword 32767 -; CHECK: .hword 32768 -; CHECK: .hword 32768 -; CHECK: .hword 0 -; CHECK: .hword 0 +; CHECK-LABEL: .LCPI0_0: +; CHECK-NEXT: .hword 32768 +; CHECK-NEXT: .hword 32767 +; CHECK-NEXT: .hword 4664 +; CHECK-NEXT: .hword 32767 +; CHECK-NEXT: .hword 32768 +; CHECK-NEXT: .hword 32768 +; CHECK-NEXT: .hword 0 +; CHECK-NEXT: .hword 0 ; Function Attrs: nounwind readnone define <8 x i16> @aarch64_tree_tests_and(<8 x i16> %a) { @@ -23,16 +22,15 @@ entry: ret <8 x i16> %ret } -; FIXME: Misspelled CHECK-LABEL -; CHECK-LABLE: @aarch64_tree_tests_or -; CHECK: .hword 32768 -; CHECK: .hword 32766 -; CHECK: .hword 4664 -; CHECK: .hword 32766 -; CHECK: .hword 32768 -; CHECK: .hword 32768 -; CHECK: .hword 65535 -; CHECK: .hword 65535 +; CHECK-LABEL: .LCPI1_0: +; CHECK-NEXT: .hword 32768 +; CHECK-NEXT: .hword 32766 +; CHECK-NEXT: .hword 4664 +; CHECK-NEXT: .hword 32766 +; CHECK-NEXT: .hword 32768 +; CHECK-NEXT: .hword 32768 +; CHECK-NEXT: .hword 65535 +; CHECK-NEXT: .hword 65535 ; Function Attrs: nounwind readnone define <8 x i16> @aarch64_tree_tests_or(<8 x i16> %a) { diff --git a/llvm/test/CodeGen/SPARC/inlineasm-bad.ll b/llvm/test/CodeGen/SPARC/inlineasm-bad.ll index 07eb67df6e5f..bfcf98ed7fd5 100644 --- a/llvm/test/CodeGen/SPARC/inlineasm-bad.ll +++ b/llvm/test/CodeGen/SPARC/inlineasm-bad.ll @@ -12,9 +12,8 @@ entry: ret void } -; CHECK-label:test_twinword_error -; CHECK: error: Hi part of pair should point to an even-numbered register -; CHECK: error: (note that in some cases it might be necessary to manually bind the input/output registers instead of relying on automatic allocation) +; CHECK: :0: error: Hi part of pair should point to an even-numbered register +; CHECK: :0: error: (note that in some cases it might be necessary to manually bind the input/output registers instead of relying on automatic allocation) define i64 @test_twinword_error(){ %1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "={i1}"() diff --git a/llvm/test/MC/AArch64/SVE/index.s b/llvm/test/MC/AArch64/SVE/index.s index c06fab25a82f..d4c106b9f0bf 100644 --- a/llvm/test/MC/AArch64/SVE/index.s +++ b/llvm/test/MC/AArch64/SVE/index.s @@ -180,16 +180,16 @@ index z21.b, w10, w21 // CHECK-UNKNOWN: 04354d55 index z31.h, wzr, wzr -// check-inst: index z31.h, wzr, wzr -// check-encoding: [0xff,0x4f,0x7f,0x04] -// check-error: instruction requires: sve or sme -// check-unknown: ff 4f 7f 04 +// CHECK-INST: index z31.h, wzr, wzr +// CHECK-ENCODING: [0xff,0x4f,0x7f,0x04] +// CHECK-ERROR: instruction requires: sve or sme +// CHECK-UNKNOWN: 047f4fff index z0.h, w0, w0 -// check-inst: index z0.h, w0, w0 -// check-encoding: [0x00,0x4c,0x60,0x04] -// check-error: instruction requires: sve or sme -// check-unknown: 00 4c 60 04 +// CHECK-INST: index z0.h, w0, w0 +// CHECK-ENCODING: [0x00,0x4c,0x60,0x04] +// CHECK-ERROR: instruction requires: sve or sme +// CHECK-UNKNOWN: 04604c00 index z31.s, wzr, wzr // CHECK-INST: index z31.s, wzr, wzr diff --git a/llvm/test/MC/XCOFF/inlineasm.s b/llvm/test/MC/XCOFF/inlineasm.s index 85a40024711a..e92d403f45a3 100644 --- a/llvm/test/MC/XCOFF/inlineasm.s +++ b/llvm/test/MC/XCOFF/inlineasm.s @@ -1,6 +1,6 @@ // RUN: llvm-mc -filetype=asm -triple powerpc-ibm-aix-xcoff %s | FileCheck %s -// CHECK-label: .csect .text[PR],2 +// CHECK-LABEL: .csect ..text..[PR],5 // CHECK:L..tmp0: // CHECK-NEXT: lwarx 3, 0, 4 // CHECK-NEXT: cmpw 5, 3 diff --git a/llvm/test/Transforms/PhaseOrdering/lifetime-sanitizer.ll b/llvm/test/Transforms/PhaseOrdering/lifetime-sanitizer.ll index 5f4d389265a8..21fa234535ca 100644 --- a/llvm/test/Transforms/PhaseOrdering/lifetime-sanitizer.ll +++ b/llvm/test/Transforms/PhaseOrdering/lifetime-sanitizer.ll @@ -1,11 +1,11 @@ -; RUN: opt < %s -O0 -S | FileCheck %s -; RUN: opt < %s -O1 -S | FileCheck %s -; RUN: opt < %s -O2 -S | FileCheck %s -; RUN: opt < %s -O3 -S | FileCheck %s -; RUN: opt < %s -passes='default' -S | FileCheck %s -; RUN: opt < %s -passes='default' -S | FileCheck %s -; RUN: opt < %s -passes='default' -S | FileCheck %s -; RUN: opt < %s -passes='default' -S | FileCheck %s +; RUN: opt < %s -O0 -S | FileCheck %s --check-prefixes=CHECK,NOOPT +; RUN: opt < %s -O1 -S | FileCheck %s --check-prefixes=CHECK,OPT +; RUN: opt < %s -O2 -S | FileCheck %s --check-prefixes=CHECK,OPT +; RUN: opt < %s -O3 -S | FileCheck %s --check-prefixes=CHECK,OPT +; RUN: opt < %s -passes='default' -S | FileCheck %s --check-prefixes=CHECK,NOOPT +; RUN: opt < %s -passes='default' -S | FileCheck %s --check-prefixes=CHECK,OPT +; RUN: opt < %s -passes='default' -S | FileCheck %s --check-prefixes=CHECK,OPT +; RUN: opt < %s -passes='default' -S | FileCheck %s --check-prefixes=CHECK,OPT declare void @llvm.lifetime.start.p0(i64, ptr nocapture) declare void @llvm.lifetime.end.p0(i64, ptr nocapture) @@ -63,7 +63,9 @@ entry: call void @llvm.lifetime.start.p0(i64 1, ptr %text) call void @llvm.lifetime.end.p0(i64 1, ptr %text) - ; CHECK-NO: call void @llvm.lifetime + ; OPT-NOT: call void @llvm.lifetime + ; NOOPT: call void @llvm.lifetime.start + ; NOOPT-NEXT: call void @llvm.lifetime.end call void @foo(ptr %text) ; Keep alloca alive diff --git a/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test b/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test index 5268324c2e10..08c8bba73928 100644 --- a/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test +++ b/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test @@ -109,16 +109,16 @@ CHECK-NEXT: 0x0000000e: [DW_RLE_offset_pair ]: {{.*}}[0x[[RANGELIST_OFFSET_STAR CHECK-NEXT: 0x00000011: [DW_RLE_end_of_list ] CHECK: .debug_names contents: -CHECK-NEX:T Name Index @ 0x0 { -CHECK-NEX:T Header { -CHECK-NEX:T Length: 0x7C -CHECK-NEX:T Format: DWARF32 -CHECK-NEX:T Version: 5 -CHECK-NEX:T CU count: 1 -CHECK-NEX:T Local TU count: 0 -CHECK-NEX:T Foreign TU count: 0 -CHECK-NEX:T Bucket count: 3 -CHECK-NEX:T Name count: 3 -CHECK-NEX:T Abbreviations table size: 0xD -CHECK-NEX:T Augmentation: 'LLVM0700' -CHECK-NEX:T } +CHECK-NEXT: Name Index @ 0x0 { +CHECK-NEXT: Header { +CHECK-NEXT: Length: +CHECK-NEXT: Format: DWARF32 +CHECK-NEXT: Version: 5 +CHECK-NEXT: CU count: 1 +CHECK-NEXT: Local TU count: 0 +CHECK-NEXT: Foreign TU count: 0 +CHECK-NEXT: Bucket count: 3 +CHECK-NEXT: Name count: 3 +CHECK-NEXT: Abbreviations table size: +CHECK-NEXT: Augmentation: 'LLVM0700' +CHECK-NEXT: } -- GitLab From bd679865c05b29450428ad460e59e2dcd07fe974 Mon Sep 17 00:00:00 2001 From: Leon Clark Date: Mon, 13 May 2024 19:39:26 +0100 Subject: [PATCH 117/578] [AMDGPU] Add tests for vector rebroadcast. (#91322) Co-authored-by: Leon Clark --- .../test/CodeGen/AMDGPU/vector_rebroadcast.ll | 1871 +++++++++++++++++ 1 file changed, 1871 insertions(+) create mode 100644 llvm/test/CodeGen/AMDGPU/vector_rebroadcast.ll diff --git a/llvm/test/CodeGen/AMDGPU/vector_rebroadcast.ll b/llvm/test/CodeGen/AMDGPU/vector_rebroadcast.ll new file mode 100644 index 000000000000..b079a94b5fcc --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/vector_rebroadcast.ll @@ -0,0 +1,1871 @@ +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s | FileCheck -check-prefix=GFX9 %s +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 < %s | FileCheck -check-prefix=GFX10 %s +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 < %s | FileCheck -check-prefix=GFX11 %s + +define <2 x i8> @shuffle_v2i8_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v2i8_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_ushort v0, v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_lshrrev_b16_e32 v0, 8, v0 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v2i8_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_ushort v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_lshrrev_b16 v0, 8, v0 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v2i8_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_u16 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_lshrrev_b16 v0, 8, v0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <2 x i8>, ptr addrspace(1) %arg0 + %val1 = shufflevector <2 x i8> %val0, <2 x i8> poison, <2 x i32> + ret <2 x i8> %val1 +} + +define <4 x i8> @shuffle_v4i8_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v4i8_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v4i8_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v4i8_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <4 x i8>, ptr addrspace(1) %arg0 + %val1 = shufflevector <4 x i8> %val0, <4 x i8> poison, <4 x i32> + ret <4 x i8> %val1 +} + +define <8 x i8> @shuffle_v8i8_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v8i8_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v8i8_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v8i8_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <8 x i8>, ptr addrspace(1) %arg0 + %val1 = shufflevector <8 x i8> %val0, <8 x i8> poison, <8 x i32> + ret <8 x i8> %val1 +} + +define <16 x i8> @shuffle_v16i8_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v16i8_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: v_mov_b32_e32 v8, v0 +; GFX9-NEXT: v_mov_b32_e32 v9, v0 +; GFX9-NEXT: v_mov_b32_e32 v10, v0 +; GFX9-NEXT: v_mov_b32_e32 v11, v0 +; GFX9-NEXT: v_mov_b32_e32 v12, v0 +; GFX9-NEXT: v_mov_b32_e32 v13, v0 +; GFX9-NEXT: v_mov_b32_e32 v14, v0 +; GFX9-NEXT: v_mov_b32_e32 v15, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v16i8_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: v_mov_b32_e32 v8, v0 +; GFX10-NEXT: v_mov_b32_e32 v9, v0 +; GFX10-NEXT: v_mov_b32_e32 v10, v0 +; GFX10-NEXT: v_mov_b32_e32 v11, v0 +; GFX10-NEXT: v_mov_b32_e32 v12, v0 +; GFX10-NEXT: v_mov_b32_e32 v13, v0 +; GFX10-NEXT: v_mov_b32_e32 v14, v0 +; GFX10-NEXT: v_mov_b32_e32 v15, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v16i8_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: v_mov_b32_e32 v8, v0 +; GFX11-NEXT: v_mov_b32_e32 v9, v0 +; GFX11-NEXT: v_mov_b32_e32 v10, v0 +; GFX11-NEXT: v_mov_b32_e32 v11, v0 +; GFX11-NEXT: v_mov_b32_e32 v12, v0 +; GFX11-NEXT: v_mov_b32_e32 v13, v0 +; GFX11-NEXT: v_mov_b32_e32 v14, v0 +; GFX11-NEXT: v_mov_b32_e32 v15, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <16 x i8>, ptr addrspace(1) %arg0 + %val1 = shufflevector <16 x i8> %val0, <16 x i8> poison, <16 x i32> + ret <16 x i8> %val1 +} + +define <32 x i8> @shuffle_v32i8_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v32i8_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: v_mov_b32_e32 v8, v0 +; GFX9-NEXT: v_mov_b32_e32 v9, v0 +; GFX9-NEXT: v_mov_b32_e32 v10, v0 +; GFX9-NEXT: v_mov_b32_e32 v11, v0 +; GFX9-NEXT: v_mov_b32_e32 v12, v0 +; GFX9-NEXT: v_mov_b32_e32 v13, v0 +; GFX9-NEXT: v_mov_b32_e32 v14, v0 +; GFX9-NEXT: v_mov_b32_e32 v15, v0 +; GFX9-NEXT: v_mov_b32_e32 v16, v0 +; GFX9-NEXT: v_mov_b32_e32 v17, v0 +; GFX9-NEXT: v_mov_b32_e32 v18, v0 +; GFX9-NEXT: v_mov_b32_e32 v19, v0 +; GFX9-NEXT: v_mov_b32_e32 v20, v0 +; GFX9-NEXT: v_mov_b32_e32 v21, v0 +; GFX9-NEXT: v_mov_b32_e32 v22, v0 +; GFX9-NEXT: v_mov_b32_e32 v23, v0 +; GFX9-NEXT: v_mov_b32_e32 v24, v0 +; GFX9-NEXT: v_mov_b32_e32 v25, v0 +; GFX9-NEXT: v_mov_b32_e32 v26, v0 +; GFX9-NEXT: v_mov_b32_e32 v27, v0 +; GFX9-NEXT: v_mov_b32_e32 v28, v0 +; GFX9-NEXT: v_mov_b32_e32 v29, v0 +; GFX9-NEXT: v_mov_b32_e32 v30, v0 +; GFX9-NEXT: v_mov_b32_e32 v31, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v32i8_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: v_mov_b32_e32 v8, v0 +; GFX10-NEXT: v_mov_b32_e32 v9, v0 +; GFX10-NEXT: v_mov_b32_e32 v10, v0 +; GFX10-NEXT: v_mov_b32_e32 v11, v0 +; GFX10-NEXT: v_mov_b32_e32 v12, v0 +; GFX10-NEXT: v_mov_b32_e32 v13, v0 +; GFX10-NEXT: v_mov_b32_e32 v14, v0 +; GFX10-NEXT: v_mov_b32_e32 v15, v0 +; GFX10-NEXT: v_mov_b32_e32 v16, v0 +; GFX10-NEXT: v_mov_b32_e32 v17, v0 +; GFX10-NEXT: v_mov_b32_e32 v18, v0 +; GFX10-NEXT: v_mov_b32_e32 v19, v0 +; GFX10-NEXT: v_mov_b32_e32 v20, v0 +; GFX10-NEXT: v_mov_b32_e32 v21, v0 +; GFX10-NEXT: v_mov_b32_e32 v22, v0 +; GFX10-NEXT: v_mov_b32_e32 v23, v0 +; GFX10-NEXT: v_mov_b32_e32 v24, v0 +; GFX10-NEXT: v_mov_b32_e32 v25, v0 +; GFX10-NEXT: v_mov_b32_e32 v26, v0 +; GFX10-NEXT: v_mov_b32_e32 v27, v0 +; GFX10-NEXT: v_mov_b32_e32 v28, v0 +; GFX10-NEXT: v_mov_b32_e32 v29, v0 +; GFX10-NEXT: v_mov_b32_e32 v30, v0 +; GFX10-NEXT: v_mov_b32_e32 v31, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v32i8_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_lshrrev_b32_e32 v0, 8, v0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: v_mov_b32_e32 v8, v0 +; GFX11-NEXT: v_mov_b32_e32 v9, v0 +; GFX11-NEXT: v_mov_b32_e32 v10, v0 +; GFX11-NEXT: v_mov_b32_e32 v11, v0 +; GFX11-NEXT: v_mov_b32_e32 v12, v0 +; GFX11-NEXT: v_mov_b32_e32 v13, v0 +; GFX11-NEXT: v_mov_b32_e32 v14, v0 +; GFX11-NEXT: v_mov_b32_e32 v15, v0 +; GFX11-NEXT: v_mov_b32_e32 v16, v0 +; GFX11-NEXT: v_mov_b32_e32 v17, v0 +; GFX11-NEXT: v_mov_b32_e32 v18, v0 +; GFX11-NEXT: v_mov_b32_e32 v19, v0 +; GFX11-NEXT: v_mov_b32_e32 v20, v0 +; GFX11-NEXT: v_mov_b32_e32 v21, v0 +; GFX11-NEXT: v_mov_b32_e32 v22, v0 +; GFX11-NEXT: v_mov_b32_e32 v23, v0 +; GFX11-NEXT: v_mov_b32_e32 v24, v0 +; GFX11-NEXT: v_mov_b32_e32 v25, v0 +; GFX11-NEXT: v_mov_b32_e32 v26, v0 +; GFX11-NEXT: v_mov_b32_e32 v27, v0 +; GFX11-NEXT: v_mov_b32_e32 v28, v0 +; GFX11-NEXT: v_mov_b32_e32 v29, v0 +; GFX11-NEXT: v_mov_b32_e32 v30, v0 +; GFX11-NEXT: v_mov_b32_e32 v31, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <32 x i8>, ptr addrspace(1) %arg0 + %val1 = shufflevector <32 x i8> %val0, <32 x i8> poison, <32 x i32> + ret <32 x i8> %val1 +} + +define <2 x i16> @shuffle_v2i16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v2i16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v2i16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v2i16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <2 x i16>, ptr addrspace(1) %arg0 + %val1 = shufflevector <2 x i16> %val0, <2 x i16> poison, <2 x i32> + ret <2 x i16> %val1 +} + +define <4 x i16> @shuffle_v4i16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v4i16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v4i16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v4i16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <4 x i16>, ptr addrspace(1) %arg0 + %val1 = shufflevector <4 x i16> %val0, <4 x i16> poison, <4 x i32> + ret <4 x i16> %val1 +} + +define <8 x i16> @shuffle_v8i16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v8i16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v8i16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v8i16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <8 x i16>, ptr addrspace(1) %arg0 + %val1 = shufflevector <8 x i16> %val0, <8 x i16> poison, <8 x i32> + ret <8 x i16> %val1 +} + +define <16 x i16> @shuffle_v16i16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v16i16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v16i16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v16i16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <16 x i16>, ptr addrspace(1) %arg0 + %val1 = shufflevector <16 x i16> %val0, <16 x i16> poison, <16 x i32> + ret <16 x i16> %val1 +} + +define <32 x i16> @shuffle_v32i16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v32i16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: v_mov_b32_e32 v8, v0 +; GFX9-NEXT: v_mov_b32_e32 v9, v0 +; GFX9-NEXT: v_mov_b32_e32 v10, v0 +; GFX9-NEXT: v_mov_b32_e32 v11, v0 +; GFX9-NEXT: v_mov_b32_e32 v12, v0 +; GFX9-NEXT: v_mov_b32_e32 v13, v0 +; GFX9-NEXT: v_mov_b32_e32 v14, v0 +; GFX9-NEXT: v_mov_b32_e32 v15, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v32i16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: v_mov_b32_e32 v8, v0 +; GFX10-NEXT: v_mov_b32_e32 v9, v0 +; GFX10-NEXT: v_mov_b32_e32 v10, v0 +; GFX10-NEXT: v_mov_b32_e32 v11, v0 +; GFX10-NEXT: v_mov_b32_e32 v12, v0 +; GFX10-NEXT: v_mov_b32_e32 v13, v0 +; GFX10-NEXT: v_mov_b32_e32 v14, v0 +; GFX10-NEXT: v_mov_b32_e32 v15, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v32i16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: v_mov_b32_e32 v8, v0 +; GFX11-NEXT: v_mov_b32_e32 v9, v0 +; GFX11-NEXT: v_mov_b32_e32 v10, v0 +; GFX11-NEXT: v_mov_b32_e32 v11, v0 +; GFX11-NEXT: v_mov_b32_e32 v12, v0 +; GFX11-NEXT: v_mov_b32_e32 v13, v0 +; GFX11-NEXT: v_mov_b32_e32 v14, v0 +; GFX11-NEXT: v_mov_b32_e32 v15, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <32 x i16>, ptr addrspace(1) %arg0 + %val1 = shufflevector <32 x i16> %val0, <32 x i16> poison, <32 x i32> + ret <32 x i16> %val1 +} + +define <2 x i32> @shuffle_v2i32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v2i32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off offset:4 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v2i32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off offset:4 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v2i32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off offset:4 +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <2 x i32>, ptr addrspace(1) %arg0 + %val1 = shufflevector <2 x i32> %val0, <2 x i32> poison, <2 x i32> + ret <2 x i32> %val1 +} + +define <4 x i32> @shuffle_v4i32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v4i32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off offset:4 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v4i32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off offset:4 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v4i32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off offset:4 +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <4 x i32>, ptr addrspace(1) %arg0 + %val1 = shufflevector <4 x i32> %val0, <4 x i32> poison, <4 x i32> + ret <4 x i32> %val1 +} + +define <8 x i32> @shuffle_v8i32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v8i32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off offset:4 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v8i32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off offset:4 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v8i32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off offset:4 +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <8 x i32>, ptr addrspace(1) %arg0 + %val1 = shufflevector <8 x i32> %val0, <8 x i32> poison, <8 x i32> + ret <8 x i32> %val1 +} + +define <16 x i32> @shuffle_v16i32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v16i32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off offset:4 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: v_mov_b32_e32 v8, v0 +; GFX9-NEXT: v_mov_b32_e32 v9, v0 +; GFX9-NEXT: v_mov_b32_e32 v10, v0 +; GFX9-NEXT: v_mov_b32_e32 v11, v0 +; GFX9-NEXT: v_mov_b32_e32 v12, v0 +; GFX9-NEXT: v_mov_b32_e32 v13, v0 +; GFX9-NEXT: v_mov_b32_e32 v14, v0 +; GFX9-NEXT: v_mov_b32_e32 v15, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v16i32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off offset:4 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: v_mov_b32_e32 v8, v0 +; GFX10-NEXT: v_mov_b32_e32 v9, v0 +; GFX10-NEXT: v_mov_b32_e32 v10, v0 +; GFX10-NEXT: v_mov_b32_e32 v11, v0 +; GFX10-NEXT: v_mov_b32_e32 v12, v0 +; GFX10-NEXT: v_mov_b32_e32 v13, v0 +; GFX10-NEXT: v_mov_b32_e32 v14, v0 +; GFX10-NEXT: v_mov_b32_e32 v15, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v16i32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off offset:4 +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: v_mov_b32_e32 v8, v0 +; GFX11-NEXT: v_mov_b32_e32 v9, v0 +; GFX11-NEXT: v_mov_b32_e32 v10, v0 +; GFX11-NEXT: v_mov_b32_e32 v11, v0 +; GFX11-NEXT: v_mov_b32_e32 v12, v0 +; GFX11-NEXT: v_mov_b32_e32 v13, v0 +; GFX11-NEXT: v_mov_b32_e32 v14, v0 +; GFX11-NEXT: v_mov_b32_e32 v15, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <16 x i32>, ptr addrspace(1) %arg0 + %val1 = shufflevector <16 x i32> %val0, <16 x i32> poison, <16 x i32> + ret <16 x i32> %val1 +} + +define <32 x i32> @shuffle_v32i32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v32i32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off offset:4 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: v_mov_b32_e32 v8, v0 +; GFX9-NEXT: v_mov_b32_e32 v9, v0 +; GFX9-NEXT: v_mov_b32_e32 v10, v0 +; GFX9-NEXT: v_mov_b32_e32 v11, v0 +; GFX9-NEXT: v_mov_b32_e32 v12, v0 +; GFX9-NEXT: v_mov_b32_e32 v13, v0 +; GFX9-NEXT: v_mov_b32_e32 v14, v0 +; GFX9-NEXT: v_mov_b32_e32 v15, v0 +; GFX9-NEXT: v_mov_b32_e32 v16, v0 +; GFX9-NEXT: v_mov_b32_e32 v17, v0 +; GFX9-NEXT: v_mov_b32_e32 v18, v0 +; GFX9-NEXT: v_mov_b32_e32 v19, v0 +; GFX9-NEXT: v_mov_b32_e32 v20, v0 +; GFX9-NEXT: v_mov_b32_e32 v21, v0 +; GFX9-NEXT: v_mov_b32_e32 v22, v0 +; GFX9-NEXT: v_mov_b32_e32 v23, v0 +; GFX9-NEXT: v_mov_b32_e32 v24, v0 +; GFX9-NEXT: v_mov_b32_e32 v25, v0 +; GFX9-NEXT: v_mov_b32_e32 v26, v0 +; GFX9-NEXT: v_mov_b32_e32 v27, v0 +; GFX9-NEXT: v_mov_b32_e32 v28, v0 +; GFX9-NEXT: v_mov_b32_e32 v29, v0 +; GFX9-NEXT: v_mov_b32_e32 v30, v0 +; GFX9-NEXT: v_mov_b32_e32 v31, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v32i32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off offset:4 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: v_mov_b32_e32 v8, v0 +; GFX10-NEXT: v_mov_b32_e32 v9, v0 +; GFX10-NEXT: v_mov_b32_e32 v10, v0 +; GFX10-NEXT: v_mov_b32_e32 v11, v0 +; GFX10-NEXT: v_mov_b32_e32 v12, v0 +; GFX10-NEXT: v_mov_b32_e32 v13, v0 +; GFX10-NEXT: v_mov_b32_e32 v14, v0 +; GFX10-NEXT: v_mov_b32_e32 v15, v0 +; GFX10-NEXT: v_mov_b32_e32 v16, v0 +; GFX10-NEXT: v_mov_b32_e32 v17, v0 +; GFX10-NEXT: v_mov_b32_e32 v18, v0 +; GFX10-NEXT: v_mov_b32_e32 v19, v0 +; GFX10-NEXT: v_mov_b32_e32 v20, v0 +; GFX10-NEXT: v_mov_b32_e32 v21, v0 +; GFX10-NEXT: v_mov_b32_e32 v22, v0 +; GFX10-NEXT: v_mov_b32_e32 v23, v0 +; GFX10-NEXT: v_mov_b32_e32 v24, v0 +; GFX10-NEXT: v_mov_b32_e32 v25, v0 +; GFX10-NEXT: v_mov_b32_e32 v26, v0 +; GFX10-NEXT: v_mov_b32_e32 v27, v0 +; GFX10-NEXT: v_mov_b32_e32 v28, v0 +; GFX10-NEXT: v_mov_b32_e32 v29, v0 +; GFX10-NEXT: v_mov_b32_e32 v30, v0 +; GFX10-NEXT: v_mov_b32_e32 v31, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v32i32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off offset:4 +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: v_mov_b32_e32 v8, v0 +; GFX11-NEXT: v_mov_b32_e32 v9, v0 +; GFX11-NEXT: v_mov_b32_e32 v10, v0 +; GFX11-NEXT: v_mov_b32_e32 v11, v0 +; GFX11-NEXT: v_mov_b32_e32 v12, v0 +; GFX11-NEXT: v_mov_b32_e32 v13, v0 +; GFX11-NEXT: v_mov_b32_e32 v14, v0 +; GFX11-NEXT: v_mov_b32_e32 v15, v0 +; GFX11-NEXT: v_mov_b32_e32 v16, v0 +; GFX11-NEXT: v_mov_b32_e32 v17, v0 +; GFX11-NEXT: v_mov_b32_e32 v18, v0 +; GFX11-NEXT: v_mov_b32_e32 v19, v0 +; GFX11-NEXT: v_mov_b32_e32 v20, v0 +; GFX11-NEXT: v_mov_b32_e32 v21, v0 +; GFX11-NEXT: v_mov_b32_e32 v22, v0 +; GFX11-NEXT: v_mov_b32_e32 v23, v0 +; GFX11-NEXT: v_mov_b32_e32 v24, v0 +; GFX11-NEXT: v_mov_b32_e32 v25, v0 +; GFX11-NEXT: v_mov_b32_e32 v26, v0 +; GFX11-NEXT: v_mov_b32_e32 v27, v0 +; GFX11-NEXT: v_mov_b32_e32 v28, v0 +; GFX11-NEXT: v_mov_b32_e32 v29, v0 +; GFX11-NEXT: v_mov_b32_e32 v30, v0 +; GFX11-NEXT: v_mov_b32_e32 v31, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <32 x i32>, ptr addrspace(1) %arg0 + %val1 = shufflevector <32 x i32> %val0, <32 x i32> poison, <32 x i32> + ret <32 x i32> %val1 +} + +define <2 x bfloat> @shuffle_v2bf16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v2bf16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v2bf16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v2bf16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <2 x bfloat>, ptr addrspace(1) %arg0 + %val1 = shufflevector <2 x bfloat> %val0, <2 x bfloat> poison, <2 x i32> + ret <2 x bfloat> %val1 +} + +define <3 x bfloat> @shuffle_v3bf16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v3bf16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v1, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v1, v1, s4 +; GFX9-NEXT: v_alignbit_b32 v1, s4, v1, 16 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v3bf16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v1, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v1, v1, 0x7060302 +; GFX10-NEXT: v_alignbit_b32 v1, s4, v1, 16 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v3bf16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v1, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v1, v1, 0x7060302 +; GFX11-NEXT: v_alignbit_b32 v1, s0, v1, 16 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <3 x bfloat>, ptr addrspace(1) %arg0 + %val1 = shufflevector <3 x bfloat> %val0, <3 x bfloat> poison, <3 x i32> + ret <3 x bfloat> %val1 +} + +define <4 x bfloat> @shuffle_v4bf16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v4bf16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v4bf16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v4bf16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <4 x bfloat>, ptr addrspace(1) %arg0 + %val1 = shufflevector <4 x bfloat> %val0, <4 x bfloat> poison, <4 x i32> + ret <4 x bfloat> %val1 +} + +define <6 x bfloat> @shuffle_v6bf16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v6bf16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v6bf16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v6bf16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <6 x bfloat>, ptr addrspace(1) %arg0 + %val1 = shufflevector <6 x bfloat> %val0, <6 x bfloat> poison, <6 x i32> + ret <6 x bfloat> %val1 +} + +define <8 x bfloat> @shuffle_v8bf16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v8bf16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v8bf16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v8bf16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <8 x bfloat>, ptr addrspace(1) %arg0 + %val1 = shufflevector <8 x bfloat> %val0, <8 x bfloat> poison, <8 x i32> + ret <8 x bfloat> %val1 +} + +define <16 x bfloat> @shuffle_v16bf16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v16bf16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v16bf16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v16bf16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <16 x bfloat>, ptr addrspace(1) %arg0 + %val1 = shufflevector <16 x bfloat> %val0, <16 x bfloat> poison, <16 x i32> + ret <16 x bfloat> %val1 +} + +define <32 x bfloat> @shuffle_v32bf16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v32bf16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: v_mov_b32_e32 v8, v0 +; GFX9-NEXT: v_mov_b32_e32 v9, v0 +; GFX9-NEXT: v_mov_b32_e32 v10, v0 +; GFX9-NEXT: v_mov_b32_e32 v11, v0 +; GFX9-NEXT: v_mov_b32_e32 v12, v0 +; GFX9-NEXT: v_mov_b32_e32 v13, v0 +; GFX9-NEXT: v_mov_b32_e32 v14, v0 +; GFX9-NEXT: v_mov_b32_e32 v15, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v32bf16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: v_mov_b32_e32 v8, v0 +; GFX10-NEXT: v_mov_b32_e32 v9, v0 +; GFX10-NEXT: v_mov_b32_e32 v10, v0 +; GFX10-NEXT: v_mov_b32_e32 v11, v0 +; GFX10-NEXT: v_mov_b32_e32 v12, v0 +; GFX10-NEXT: v_mov_b32_e32 v13, v0 +; GFX10-NEXT: v_mov_b32_e32 v14, v0 +; GFX10-NEXT: v_mov_b32_e32 v15, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v32bf16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: v_mov_b32_e32 v8, v0 +; GFX11-NEXT: v_mov_b32_e32 v9, v0 +; GFX11-NEXT: v_mov_b32_e32 v10, v0 +; GFX11-NEXT: v_mov_b32_e32 v11, v0 +; GFX11-NEXT: v_mov_b32_e32 v12, v0 +; GFX11-NEXT: v_mov_b32_e32 v13, v0 +; GFX11-NEXT: v_mov_b32_e32 v14, v0 +; GFX11-NEXT: v_mov_b32_e32 v15, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <32 x bfloat>, ptr addrspace(1) %arg0 + %val1 = shufflevector <32 x bfloat> %val0, <32 x bfloat> poison, <32 x i32> + ret <32 x bfloat> %val1 +} + +define <2 x half> @shuffle_v2f16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v2f16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v2f16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v2f16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <2 x half>, ptr addrspace(1) %arg0 + %val1 = shufflevector <2 x half> %val0, <2 x half> poison, <2 x i32> + ret <2 x half> %val1 +} + +define <3 x half> @shuffle_v3f16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v3f16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v1, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v1, v1, s4 +; GFX9-NEXT: v_alignbit_b32 v1, s4, v1, 16 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v3f16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v1, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v1, v1, 0x7060302 +; GFX10-NEXT: v_alignbit_b32 v1, s4, v1, 16 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v3f16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v1, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v1, v1, 0x7060302 +; GFX11-NEXT: v_alignbit_b32 v1, s0, v1, 16 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <3 x half>, ptr addrspace(1) %arg0 + %val1 = shufflevector <3 x half> %val0, <3 x half> poison, <3 x i32> + ret <3 x half> %val1 +} + +define <4 x half> @shuffle_v4f16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v4f16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v4f16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v4f16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <4 x half>, ptr addrspace(1) %arg0 + %val1 = shufflevector <4 x half> %val0, <4 x half> poison, <4 x i32> + ret <4 x half> %val1 +} + +define <6 x half> @shuffle_v6f16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v6f16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v6f16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v6f16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <6 x half>, ptr addrspace(1) %arg0 + %val1 = shufflevector <6 x half> %val0, <6 x half> poison, <6 x i32> + ret <6 x half> %val1 +} + +define <8 x half> @shuffle_v8f16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v8f16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v8f16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v8f16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <8 x half>, ptr addrspace(1) %arg0 + %val1 = shufflevector <8 x half> %val0, <8 x half> poison, <8 x i32> + ret <8 x half> %val1 +} + +define <16 x half> @shuffle_v16f16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v16f16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v16f16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v16f16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <16 x half>, ptr addrspace(1) %arg0 + %val1 = shufflevector <16 x half> %val0, <16 x half> poison, <16 x i32> + ret <16 x half> %val1 +} + +define <32 x half> @shuffle_v32f16_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v32f16_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, 0x7060302 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_perm_b32 v0, v0, v0, s4 +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-NEXT: v_mov_b32_e32 v7, v0 +; GFX9-NEXT: v_mov_b32_e32 v8, v0 +; GFX9-NEXT: v_mov_b32_e32 v9, v0 +; GFX9-NEXT: v_mov_b32_e32 v10, v0 +; GFX9-NEXT: v_mov_b32_e32 v11, v0 +; GFX9-NEXT: v_mov_b32_e32 v12, v0 +; GFX9-NEXT: v_mov_b32_e32 v13, v0 +; GFX9-NEXT: v_mov_b32_e32 v14, v0 +; GFX9-NEXT: v_mov_b32_e32 v15, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v32f16_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v0, v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX10-NEXT: v_mov_b32_e32 v1, v0 +; GFX10-NEXT: v_mov_b32_e32 v2, v0 +; GFX10-NEXT: v_mov_b32_e32 v3, v0 +; GFX10-NEXT: v_mov_b32_e32 v4, v0 +; GFX10-NEXT: v_mov_b32_e32 v5, v0 +; GFX10-NEXT: v_mov_b32_e32 v6, v0 +; GFX10-NEXT: v_mov_b32_e32 v7, v0 +; GFX10-NEXT: v_mov_b32_e32 v8, v0 +; GFX10-NEXT: v_mov_b32_e32 v9, v0 +; GFX10-NEXT: v_mov_b32_e32 v10, v0 +; GFX10-NEXT: v_mov_b32_e32 v11, v0 +; GFX10-NEXT: v_mov_b32_e32 v12, v0 +; GFX10-NEXT: v_mov_b32_e32 v13, v0 +; GFX10-NEXT: v_mov_b32_e32 v14, v0 +; GFX10-NEXT: v_mov_b32_e32 v15, v0 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v32f16_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v0, v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_perm_b32 v0, v0, v0, 0x7060302 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v1, v0 +; GFX11-NEXT: v_mov_b32_e32 v2, v0 +; GFX11-NEXT: v_mov_b32_e32 v3, v0 +; GFX11-NEXT: v_mov_b32_e32 v4, v0 +; GFX11-NEXT: v_mov_b32_e32 v5, v0 +; GFX11-NEXT: v_mov_b32_e32 v6, v0 +; GFX11-NEXT: v_mov_b32_e32 v7, v0 +; GFX11-NEXT: v_mov_b32_e32 v8, v0 +; GFX11-NEXT: v_mov_b32_e32 v9, v0 +; GFX11-NEXT: v_mov_b32_e32 v10, v0 +; GFX11-NEXT: v_mov_b32_e32 v11, v0 +; GFX11-NEXT: v_mov_b32_e32 v12, v0 +; GFX11-NEXT: v_mov_b32_e32 v13, v0 +; GFX11-NEXT: v_mov_b32_e32 v14, v0 +; GFX11-NEXT: v_mov_b32_e32 v15, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <32 x half>, ptr addrspace(1) %arg0 + %val1 = shufflevector <32 x half> %val0, <32 x half> poison, <32 x i32> + ret <32 x half> %val1 +} + +define <2 x float> @shuffle_v2f32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v2f32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx2 v[0:1], v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v0, v1 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v2f32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dwordx2 v[0:1], v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v0, v1 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v2f32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b64 v[0:1], v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v0, v1 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <2 x float>, ptr addrspace(1) %arg0 + %val1 = shufflevector <2 x float> %val0, <2 x float> poison, <2 x i32> + ret <2 x float> %val1 +} + +define <3 x float> @shuffle_v3f32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v3f32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx3 v[0:2], v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v0, v1 +; GFX9-NEXT: v_mov_b32_e32 v2, v1 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v3f32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dwordx3 v[0:2], v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v0, v1 +; GFX10-NEXT: v_mov_b32_e32 v2, v1 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v3f32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b96 v[0:2], v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v0, v1 +; GFX11-NEXT: v_mov_b32_e32 v2, v1 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <3 x float>, ptr addrspace(1) %arg0 + %val1 = shufflevector <3 x float> %val0, <3 x float> poison, <3 x i32> + ret <3 x float> %val1 +} + +define <4 x float> @shuffle_v4f32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v4f32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v0, v1 +; GFX9-NEXT: v_mov_b32_e32 v2, v1 +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v4f32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v0, v1 +; GFX10-NEXT: v_mov_b32_e32 v2, v1 +; GFX10-NEXT: v_mov_b32_e32 v3, v1 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v4f32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b128 v[0:3], v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v0, v1 +; GFX11-NEXT: v_mov_b32_e32 v2, v1 +; GFX11-NEXT: v_mov_b32_e32 v3, v1 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <4 x float>, ptr addrspace(1) %arg0 + %val1 = shufflevector <4 x float> %val0, <4 x float> poison, <4 x i32> + ret <4 x float> %val1 +} + +define <6 x float> @shuffle_v6f32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v6f32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v0, v1 +; GFX9-NEXT: v_mov_b32_e32 v2, v1 +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: v_mov_b32_e32 v4, v1 +; GFX9-NEXT: v_mov_b32_e32 v5, v1 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v6f32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v0, v1 +; GFX10-NEXT: v_mov_b32_e32 v2, v1 +; GFX10-NEXT: v_mov_b32_e32 v3, v1 +; GFX10-NEXT: v_mov_b32_e32 v4, v1 +; GFX10-NEXT: v_mov_b32_e32 v5, v1 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v6f32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b128 v[0:3], v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v0, v1 +; GFX11-NEXT: v_mov_b32_e32 v2, v1 +; GFX11-NEXT: v_mov_b32_e32 v3, v1 +; GFX11-NEXT: v_mov_b32_e32 v4, v1 +; GFX11-NEXT: v_mov_b32_e32 v5, v1 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <6 x float>, ptr addrspace(1) %arg0 + %val1 = shufflevector <6 x float> %val0, <6 x float> poison, <6 x i32> + ret <6 x float> %val1 +} + +define <8 x float> @shuffle_v8f32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v8f32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v0, v1 +; GFX9-NEXT: v_mov_b32_e32 v2, v1 +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: v_mov_b32_e32 v4, v1 +; GFX9-NEXT: v_mov_b32_e32 v5, v1 +; GFX9-NEXT: v_mov_b32_e32 v6, v1 +; GFX9-NEXT: v_mov_b32_e32 v7, v1 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v8f32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v0, v1 +; GFX10-NEXT: v_mov_b32_e32 v2, v1 +; GFX10-NEXT: v_mov_b32_e32 v3, v1 +; GFX10-NEXT: v_mov_b32_e32 v4, v1 +; GFX10-NEXT: v_mov_b32_e32 v5, v1 +; GFX10-NEXT: v_mov_b32_e32 v6, v1 +; GFX10-NEXT: v_mov_b32_e32 v7, v1 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v8f32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b128 v[0:3], v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v0, v1 +; GFX11-NEXT: v_mov_b32_e32 v2, v1 +; GFX11-NEXT: v_mov_b32_e32 v3, v1 +; GFX11-NEXT: v_mov_b32_e32 v4, v1 +; GFX11-NEXT: v_mov_b32_e32 v5, v1 +; GFX11-NEXT: v_mov_b32_e32 v6, v1 +; GFX11-NEXT: v_mov_b32_e32 v7, v1 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <8 x float>, ptr addrspace(1) %arg0 + %val1 = shufflevector <8 x float> %val0, <8 x float> poison, <8 x i32> + ret <8 x float> %val1 +} + +define <16 x float> @shuffle_v16f32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v16f32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v0, v1 +; GFX9-NEXT: v_mov_b32_e32 v2, v1 +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: v_mov_b32_e32 v4, v1 +; GFX9-NEXT: v_mov_b32_e32 v5, v1 +; GFX9-NEXT: v_mov_b32_e32 v6, v1 +; GFX9-NEXT: v_mov_b32_e32 v7, v1 +; GFX9-NEXT: v_mov_b32_e32 v8, v1 +; GFX9-NEXT: v_mov_b32_e32 v9, v1 +; GFX9-NEXT: v_mov_b32_e32 v10, v1 +; GFX9-NEXT: v_mov_b32_e32 v11, v1 +; GFX9-NEXT: v_mov_b32_e32 v12, v1 +; GFX9-NEXT: v_mov_b32_e32 v13, v1 +; GFX9-NEXT: v_mov_b32_e32 v14, v1 +; GFX9-NEXT: v_mov_b32_e32 v15, v1 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v16f32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v0, v1 +; GFX10-NEXT: v_mov_b32_e32 v2, v1 +; GFX10-NEXT: v_mov_b32_e32 v3, v1 +; GFX10-NEXT: v_mov_b32_e32 v4, v1 +; GFX10-NEXT: v_mov_b32_e32 v5, v1 +; GFX10-NEXT: v_mov_b32_e32 v6, v1 +; GFX10-NEXT: v_mov_b32_e32 v7, v1 +; GFX10-NEXT: v_mov_b32_e32 v8, v1 +; GFX10-NEXT: v_mov_b32_e32 v9, v1 +; GFX10-NEXT: v_mov_b32_e32 v10, v1 +; GFX10-NEXT: v_mov_b32_e32 v11, v1 +; GFX10-NEXT: v_mov_b32_e32 v12, v1 +; GFX10-NEXT: v_mov_b32_e32 v13, v1 +; GFX10-NEXT: v_mov_b32_e32 v14, v1 +; GFX10-NEXT: v_mov_b32_e32 v15, v1 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v16f32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b128 v[0:3], v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v0, v1 +; GFX11-NEXT: v_mov_b32_e32 v2, v1 +; GFX11-NEXT: v_mov_b32_e32 v3, v1 +; GFX11-NEXT: v_mov_b32_e32 v4, v1 +; GFX11-NEXT: v_mov_b32_e32 v5, v1 +; GFX11-NEXT: v_mov_b32_e32 v6, v1 +; GFX11-NEXT: v_mov_b32_e32 v7, v1 +; GFX11-NEXT: v_mov_b32_e32 v8, v1 +; GFX11-NEXT: v_mov_b32_e32 v9, v1 +; GFX11-NEXT: v_mov_b32_e32 v10, v1 +; GFX11-NEXT: v_mov_b32_e32 v11, v1 +; GFX11-NEXT: v_mov_b32_e32 v12, v1 +; GFX11-NEXT: v_mov_b32_e32 v13, v1 +; GFX11-NEXT: v_mov_b32_e32 v14, v1 +; GFX11-NEXT: v_mov_b32_e32 v15, v1 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <16 x float>, ptr addrspace(1) %arg0 + %val1 = shufflevector <16 x float> %val0, <16 x float> poison, <16 x i32> + ret <16 x float> %val1 +} + +define <32 x float> @shuffle_v32f32_rebroadcast(ptr addrspace(1) %arg0) { +; GFX9-LABEL: shuffle_v32f32_rebroadcast: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v0, v1 +; GFX9-NEXT: v_mov_b32_e32 v2, v1 +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: v_mov_b32_e32 v4, v1 +; GFX9-NEXT: v_mov_b32_e32 v5, v1 +; GFX9-NEXT: v_mov_b32_e32 v6, v1 +; GFX9-NEXT: v_mov_b32_e32 v7, v1 +; GFX9-NEXT: v_mov_b32_e32 v8, v1 +; GFX9-NEXT: v_mov_b32_e32 v9, v1 +; GFX9-NEXT: v_mov_b32_e32 v10, v1 +; GFX9-NEXT: v_mov_b32_e32 v11, v1 +; GFX9-NEXT: v_mov_b32_e32 v12, v1 +; GFX9-NEXT: v_mov_b32_e32 v13, v1 +; GFX9-NEXT: v_mov_b32_e32 v14, v1 +; GFX9-NEXT: v_mov_b32_e32 v15, v1 +; GFX9-NEXT: v_mov_b32_e32 v16, v1 +; GFX9-NEXT: v_mov_b32_e32 v17, v1 +; GFX9-NEXT: v_mov_b32_e32 v18, v1 +; GFX9-NEXT: v_mov_b32_e32 v19, v1 +; GFX9-NEXT: v_mov_b32_e32 v20, v1 +; GFX9-NEXT: v_mov_b32_e32 v21, v1 +; GFX9-NEXT: v_mov_b32_e32 v22, v1 +; GFX9-NEXT: v_mov_b32_e32 v23, v1 +; GFX9-NEXT: v_mov_b32_e32 v24, v1 +; GFX9-NEXT: v_mov_b32_e32 v25, v1 +; GFX9-NEXT: v_mov_b32_e32 v26, v1 +; GFX9-NEXT: v_mov_b32_e32 v27, v1 +; GFX9-NEXT: v_mov_b32_e32 v28, v1 +; GFX9-NEXT: v_mov_b32_e32 v29, v1 +; GFX9-NEXT: v_mov_b32_e32 v30, v1 +; GFX9-NEXT: v_mov_b32_e32 v31, v1 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: shuffle_v32f32_rebroadcast: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v0, v1 +; GFX10-NEXT: v_mov_b32_e32 v2, v1 +; GFX10-NEXT: v_mov_b32_e32 v3, v1 +; GFX10-NEXT: v_mov_b32_e32 v4, v1 +; GFX10-NEXT: v_mov_b32_e32 v5, v1 +; GFX10-NEXT: v_mov_b32_e32 v6, v1 +; GFX10-NEXT: v_mov_b32_e32 v7, v1 +; GFX10-NEXT: v_mov_b32_e32 v8, v1 +; GFX10-NEXT: v_mov_b32_e32 v9, v1 +; GFX10-NEXT: v_mov_b32_e32 v10, v1 +; GFX10-NEXT: v_mov_b32_e32 v11, v1 +; GFX10-NEXT: v_mov_b32_e32 v12, v1 +; GFX10-NEXT: v_mov_b32_e32 v13, v1 +; GFX10-NEXT: v_mov_b32_e32 v14, v1 +; GFX10-NEXT: v_mov_b32_e32 v15, v1 +; GFX10-NEXT: v_mov_b32_e32 v16, v1 +; GFX10-NEXT: v_mov_b32_e32 v17, v1 +; GFX10-NEXT: v_mov_b32_e32 v18, v1 +; GFX10-NEXT: v_mov_b32_e32 v19, v1 +; GFX10-NEXT: v_mov_b32_e32 v20, v1 +; GFX10-NEXT: v_mov_b32_e32 v21, v1 +; GFX10-NEXT: v_mov_b32_e32 v22, v1 +; GFX10-NEXT: v_mov_b32_e32 v23, v1 +; GFX10-NEXT: v_mov_b32_e32 v24, v1 +; GFX10-NEXT: v_mov_b32_e32 v25, v1 +; GFX10-NEXT: v_mov_b32_e32 v26, v1 +; GFX10-NEXT: v_mov_b32_e32 v27, v1 +; GFX10-NEXT: v_mov_b32_e32 v28, v1 +; GFX10-NEXT: v_mov_b32_e32 v29, v1 +; GFX10-NEXT: v_mov_b32_e32 v30, v1 +; GFX10-NEXT: v_mov_b32_e32 v31, v1 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: shuffle_v32f32_rebroadcast: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b128 v[0:3], v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v0, v1 +; GFX11-NEXT: v_mov_b32_e32 v2, v1 +; GFX11-NEXT: v_mov_b32_e32 v3, v1 +; GFX11-NEXT: v_mov_b32_e32 v4, v1 +; GFX11-NEXT: v_mov_b32_e32 v5, v1 +; GFX11-NEXT: v_mov_b32_e32 v6, v1 +; GFX11-NEXT: v_mov_b32_e32 v7, v1 +; GFX11-NEXT: v_mov_b32_e32 v8, v1 +; GFX11-NEXT: v_mov_b32_e32 v9, v1 +; GFX11-NEXT: v_mov_b32_e32 v10, v1 +; GFX11-NEXT: v_mov_b32_e32 v11, v1 +; GFX11-NEXT: v_mov_b32_e32 v12, v1 +; GFX11-NEXT: v_mov_b32_e32 v13, v1 +; GFX11-NEXT: v_mov_b32_e32 v14, v1 +; GFX11-NEXT: v_mov_b32_e32 v15, v1 +; GFX11-NEXT: v_mov_b32_e32 v16, v1 +; GFX11-NEXT: v_mov_b32_e32 v17, v1 +; GFX11-NEXT: v_mov_b32_e32 v18, v1 +; GFX11-NEXT: v_mov_b32_e32 v19, v1 +; GFX11-NEXT: v_mov_b32_e32 v20, v1 +; GFX11-NEXT: v_mov_b32_e32 v21, v1 +; GFX11-NEXT: v_mov_b32_e32 v22, v1 +; GFX11-NEXT: v_mov_b32_e32 v23, v1 +; GFX11-NEXT: v_mov_b32_e32 v24, v1 +; GFX11-NEXT: v_mov_b32_e32 v25, v1 +; GFX11-NEXT: v_mov_b32_e32 v26, v1 +; GFX11-NEXT: v_mov_b32_e32 v27, v1 +; GFX11-NEXT: v_mov_b32_e32 v28, v1 +; GFX11-NEXT: v_mov_b32_e32 v29, v1 +; GFX11-NEXT: v_mov_b32_e32 v30, v1 +; GFX11-NEXT: v_mov_b32_e32 v31, v1 +; GFX11-NEXT: s_setpc_b64 s[30:31] +entry: + %val0 = load <32 x float>, ptr addrspace(1) %arg0 + %val1 = shufflevector <32 x float> %val0, <32 x float> poison, <32 x i32> + ret <32 x float> %val1 +} -- GitLab From 69937982dbdd73172ec06580f6f93616edca8e9e Mon Sep 17 00:00:00 2001 From: Piotr Zegar Date: Mon, 13 May 2024 20:41:42 +0200 Subject: [PATCH 118/578] [clang-tidy] Ignore unevaluated context in bugprone-optional-value-conversion (#90410) Ignore optionals in unevaluated context, like static_assert or decltype. Closes #89593 --- .../clang-tidy/bugprone/OptionalValueConversionCheck.cpp | 4 +++- clang-tools-extra/docs/ReleaseNotes.rst | 4 ++++ .../checkers/bugprone/optional-value-conversion.cpp | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp index 9ab59e6b0474..600eab375527 100644 --- a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp @@ -71,7 +71,9 @@ void OptionalValueConversionCheck::registerMatchers(MatchFinder *Finder) { ofClass(matchers::matchesAnyListedName(OptionalTypes)))), hasType(ConstructTypeMatcher), hasArgument(0U, ignoringImpCasts(anyOf(OptionalDereferenceMatcher, - StdMoveCallMatcher)))) + StdMoveCallMatcher))), + unless(anyOf(hasAncestor(typeLoc()), + hasAncestor(expr(matchers::hasUnevaluatedContext()))))) .bind("expr"), this); } diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 8183d394cf42..8c76f5f60ee3 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -204,6 +204,10 @@ Changes in existing checks eliminating false positives resulting from direct usage of bitwise operators within parentheses. +- Improved :doc:`bugprone-optional-value-conversion + ` check by eliminating + false positives resulting from use of optionals in unevaluated context. + - Improved :doc:`bugprone-suspicious-include ` check by replacing the local options `HeaderFileExtensions` and `ImplementationFileExtensions` by the diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion.cpp index 72ef35c956d2..1228d64bb690 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion.cpp @@ -210,4 +210,6 @@ void correct(std::optional param) std::optional* p2 = &p; takeOptionalValue(p2->value_or(5U)); takeOptionalRef(p2->value_or(5U)); + + using Type = decltype(takeOptionalValue(*param)); } -- GitLab From af79372d6349cfba6beff26d54b7ad1b798fc4d5 Mon Sep 17 00:00:00 2001 From: Mike Crowe Date: Mon, 13 May 2024 19:42:44 +0100 Subject: [PATCH 119/578] [clang-tidy] Add modernize-use-std-format check (#90397) Add a new clang-tidy check that converts absl::StrFormat (and similar functions) to std::format (and similar functions.) Split the configuration of FormatStringConverter out to a separate Configuration class so that we don't risk confusion by passing two boolean configuration parameters into the constructor. Add AllowTrailingNewlineRemoval option since we never want to remove trailing newlines in this check. --- .../clang-tidy/modernize/CMakeLists.txt | 1 + .../modernize/ModernizeTidyModule.cpp | 2 + .../modernize/UseStdFormatCheck.cpp | 107 ++++++++++++++++ .../clang-tidy/modernize/UseStdFormatCheck.h | 51 ++++++++ .../clang-tidy/modernize/UseStdPrintCheck.cpp | 5 +- .../utils/FormatStringConverter.cpp | 16 ++- .../clang-tidy/utils/FormatStringConverter.h | 9 +- clang-tools-extra/docs/ReleaseNotes.rst | 9 ++ .../docs/clang-tidy/checks/list.rst | 1 + .../checks/modernize/use-std-format.rst | 84 ++++++++++++ .../modernize/use-std-format-custom.cpp | 52 ++++++++ .../checkers/modernize/use-std-format-fmt.cpp | 24 ++++ .../checkers/modernize/use-std-format.cpp | 120 ++++++++++++++++++ 13 files changed, 473 insertions(+), 8 deletions(-) create mode 100644 clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 8005d6e91c06..576805c4c7f1 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -41,6 +41,7 @@ add_clang_library(clangTidyModernizeModule UseNullptrCheck.cpp UseOverrideCheck.cpp UseStartsEndsWithCheck.cpp + UseStdFormatCheck.cpp UseStdNumbersCheck.cpp UseStdPrintCheck.cpp UseTrailingReturnTypeCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index 776558433c5b..b9c7a2dc383e 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -42,6 +42,7 @@ #include "UseNullptrCheck.h" #include "UseOverrideCheck.h" #include "UseStartsEndsWithCheck.h" +#include "UseStdFormatCheck.h" #include "UseStdNumbersCheck.h" #include "UseStdPrintCheck.h" #include "UseTrailingReturnTypeCheck.h" @@ -76,6 +77,7 @@ public: "modernize-use-designated-initializers"); CheckFactories.registerCheck( "modernize-use-starts-ends-with"); + CheckFactories.registerCheck("modernize-use-std-format"); CheckFactories.registerCheck( "modernize-use-std-numbers"); CheckFactories.registerCheck("modernize-use-std-print"); diff --git a/clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp new file mode 100644 index 000000000000..6cef21f1318a --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.cpp @@ -0,0 +1,107 @@ +//===--- UseStdFormatCheck.cpp - clang-tidy -------------------------------===// +// +// 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 "UseStdFormatCheck.h" +#include "../utils/FormatStringConverter.h" +#include "../utils/Matchers.h" +#include "../utils/OptionsUtils.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "clang/Tooling/FixIt.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::modernize { + +namespace { +AST_MATCHER(StringLiteral, isOrdinary) { return Node.isOrdinary(); } +} // namespace + +UseStdFormatCheck::UseStdFormatCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + StrictMode(Options.getLocalOrGlobal("StrictMode", false)), + StrFormatLikeFunctions(utils::options::parseStringList( + Options.get("StrFormatLikeFunctions", ""))), + ReplacementFormatFunction( + Options.get("ReplacementFormatFunction", "std::format")), + IncludeInserter(Options.getLocalOrGlobal("IncludeStyle", + utils::IncludeSorter::IS_LLVM), + areDiagsSelfContained()), + MaybeHeaderToInclude(Options.get("FormatHeader")) { + if (StrFormatLikeFunctions.empty()) + StrFormatLikeFunctions.push_back("absl::StrFormat"); + + if (!MaybeHeaderToInclude && ReplacementFormatFunction == "std::format") + MaybeHeaderToInclude = ""; +} + +void UseStdFormatCheck::registerPPCallbacks(const SourceManager &SM, + Preprocessor *PP, + Preprocessor *ModuleExpanderPP) { + IncludeInserter.registerPreprocessor(PP); +} + +void UseStdFormatCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + callExpr(argumentCountAtLeast(1), + hasArgument(0, stringLiteral(isOrdinary())), + callee(functionDecl(unless(cxxMethodDecl()), + matchers::matchesAnyListedName( + StrFormatLikeFunctions)) + .bind("func_decl"))) + .bind("strformat"), + this); +} + +void UseStdFormatCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + using utils::options::serializeStringList; + Options.store(Opts, "StrictMode", StrictMode); + Options.store(Opts, "StrFormatLikeFunctions", + serializeStringList(StrFormatLikeFunctions)); + Options.store(Opts, "ReplacementFormatFunction", ReplacementFormatFunction); + Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle()); + if (MaybeHeaderToInclude) + Options.store(Opts, "FormatHeader", *MaybeHeaderToInclude); +} + +void UseStdFormatCheck::check(const MatchFinder::MatchResult &Result) { + const unsigned FormatArgOffset = 0; + const auto *OldFunction = Result.Nodes.getNodeAs("func_decl"); + const auto *StrFormat = Result.Nodes.getNodeAs("strformat"); + + utils::FormatStringConverter::Configuration ConverterConfig; + ConverterConfig.StrictMode = StrictMode; + utils::FormatStringConverter Converter(Result.Context, StrFormat, + FormatArgOffset, ConverterConfig, + getLangOpts()); + const Expr *StrFormatCall = StrFormat->getCallee(); + if (!Converter.canApply()) { + diag(StrFormat->getBeginLoc(), + "unable to use '%0' instead of %1 because %2") + << StrFormatCall->getSourceRange() << ReplacementFormatFunction + << OldFunction->getIdentifier() + << Converter.conversionNotPossibleReason(); + return; + } + + DiagnosticBuilder Diag = + diag(StrFormatCall->getBeginLoc(), "use '%0' instead of %1") + << ReplacementFormatFunction << OldFunction->getIdentifier(); + Diag << FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(StrFormatCall->getSourceRange()), + ReplacementFormatFunction); + Converter.applyFixes(Diag, *Result.SourceManager); + + if (MaybeHeaderToInclude) + Diag << IncludeInserter.createIncludeInsertion( + Result.Context->getSourceManager().getFileID( + StrFormatCall->getBeginLoc()), + *MaybeHeaderToInclude); +} + +} // namespace clang::tidy::modernize diff --git a/clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.h b/clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.h new file mode 100644 index 000000000000..b59a4708c6e4 --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseStdFormatCheck.h @@ -0,0 +1,51 @@ +//===--- UseStdFormatCheck.h - clang-tidy -----------------------*- 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_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESTDFORMATCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESTDFORMATCHECK_H + +#include "../ClangTidyCheck.h" +#include "../utils/IncludeInserter.h" + +namespace clang::tidy::modernize { + +/// Converts calls to absl::StrFormat, or other functions via configuration +/// options, to C++20's std::format, or another function via a configuration +/// option, modifying the format string appropriately and removing +/// now-unnecessary calls to std::string::c_str() and std::string::data(). +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-std-format.html +class UseStdFormatCheck : public ClangTidyCheck { +public: + UseStdFormatCheck(StringRef Name, ClangTidyContext *Context); + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + if (ReplacementFormatFunction == "std::format") + return LangOpts.CPlusPlus20; + return LangOpts.CPlusPlus; + } + void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, + Preprocessor *ModuleExpanderPP) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + std::optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } + +private: + bool StrictMode; + std::vector StrFormatLikeFunctions; + StringRef ReplacementFormatFunction; + utils::IncludeInserter IncludeInserter; + std::optional MaybeHeaderToInclude; +}; + +} // namespace clang::tidy::modernize + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESTDFORMATCHECK_H diff --git a/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp index aa60c904a363..ff990feadc0c 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp @@ -129,8 +129,11 @@ void UseStdPrintCheck::check(const MatchFinder::MatchResult &Result) { FormatArgOffset = 1; } + utils::FormatStringConverter::Configuration ConverterConfig; + ConverterConfig.StrictMode = StrictMode; + ConverterConfig.AllowTrailingNewlineRemoval = true; utils::FormatStringConverter Converter( - Result.Context, Printf, FormatArgOffset, StrictMode, getLangOpts()); + Result.Context, Printf, FormatArgOffset, ConverterConfig, getLangOpts()); const Expr *PrintfCall = Printf->getCallee(); const StringRef ReplacementFunction = Converter.usePrintNewlineFunction() ? ReplacementPrintlnFunction diff --git a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp index ad10f745b6ac..845e71c5003b 100644 --- a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp +++ b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp @@ -198,10 +198,11 @@ static bool castMismatchedIntegerTypes(const CallExpr *Call, bool StrictMode) { FormatStringConverter::FormatStringConverter(ASTContext *ContextIn, const CallExpr *Call, unsigned FormatArgOffset, - bool StrictMode, + const Configuration ConfigIn, const LangOptions &LO) - : Context(ContextIn), - CastMismatchedIntegerTypes(castMismatchedIntegerTypes(Call, StrictMode)), + : Context(ContextIn), Config(ConfigIn), + CastMismatchedIntegerTypes( + castMismatchedIntegerTypes(Call, ConfigIn.StrictMode)), Args(Call->getArgs()), NumArgs(Call->getNumArgs()), ArgsOffset(FormatArgOffset + 1), LangOpts(LO) { assert(ArgsOffset <= NumArgs); @@ -627,9 +628,12 @@ void FormatStringConverter::finalizeFormatText() { // It's clearer to convert printf("Hello\r\n"); to std::print("Hello\r\n") // than to std::println("Hello\r"); - if (StringRef(StandardFormatString).ends_with("\\n") && - !StringRef(StandardFormatString).ends_with("\\\\n") && - !StringRef(StandardFormatString).ends_with("\\r\\n")) { + // Use StringRef until C++20 std::string::ends_with() is available. + const auto StandardFormatStringRef = StringRef(StandardFormatString); + if (Config.AllowTrailingNewlineRemoval && + StandardFormatStringRef.ends_with("\\n") && + !StandardFormatStringRef.ends_with("\\\\n") && + !StandardFormatStringRef.ends_with("\\r\\n")) { UsePrintNewlineFunction = true; FormatStringNeededRewriting = true; StandardFormatString.erase(StandardFormatString.end() - 2, diff --git a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.h b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.h index 1949870f62ed..1109a0b60226 100644 --- a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.h +++ b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.h @@ -32,8 +32,14 @@ class FormatStringConverter public: using ConversionSpecifier = clang::analyze_format_string::ConversionSpecifier; using PrintfSpecifier = analyze_printf::PrintfSpecifier; + + struct Configuration { + bool StrictMode = false; + bool AllowTrailingNewlineRemoval = false; + }; + FormatStringConverter(ASTContext *Context, const CallExpr *Call, - unsigned FormatArgOffset, bool StrictMode, + unsigned FormatArgOffset, Configuration Config, const LangOptions &LO); bool canApply() const { return ConversionNotPossibleReason.empty(); } @@ -45,6 +51,7 @@ public: private: ASTContext *Context; + const Configuration Config; const bool CastMismatchedIntegerTypes; const Expr *const *Args; const unsigned NumArgs; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 8c76f5f60ee3..898c7acc1310 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -150,6 +150,15 @@ New checks Finds initializer lists for aggregate types that could be written as designated initializers instead. +- New :doc:`modernize-use-std-format + ` check. + + Converts calls to ``absl::StrFormat``, or other functions via + configuration options, to C++20's ``std::format``, or another function + via a configuration option, modifying the format string appropriately and + removing now-unnecessary calls to ``std::string::c_str()`` and + ``std::string::data()``. + - New :doc:`readability-enum-initial-value ` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 046a5ff57ad1..85e4f0352ac2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -300,6 +300,7 @@ Clang-Tidy Checks :doc:`modernize-use-nullptr `, "Yes" :doc:`modernize-use-override `, "Yes" :doc:`modernize-use-starts-ends-with `, "Yes" + :doc:`modernize-use-std-format `, "Yes" :doc:`modernize-use-std-numbers `, "Yes" :doc:`modernize-use-std-print `, "Yes" :doc:`modernize-use-trailing-return-type `, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst new file mode 100644 index 000000000000..a1599f0fc58f --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst @@ -0,0 +1,84 @@ +.. title:: clang-tidy - modernize-use-std-format + +modernize-use-std-format +======================== + +Converts calls to ``absl::StrFormat``, or other functions via +configuration options, to C++20's ``std::format``, or another function +via a configuration option, modifying the format string appropriately and +removing now-unnecessary calls to ``std::string::c_str()`` and +``std::string::data()``. + +For example, it turns lines like + +.. code-block:: c++ + + return absl::StrFormat("The %s is %3d", description.c_str(), value); + +into: + +.. code-block:: c++ + + return std::format("The {} is {:3}", description, value); + +The check uses the same format-string-conversion algorithm as +`modernize-use-std-print <../modernize/use-std-print.html>`_ and its +shortcomings are described in the documentation for that check. + +Options +------- + +.. option:: StrictMode + + When `true`, the check will add casts when converting from variadic + functions and printing signed or unsigned integer types (including + fixed-width integer types from ````, ``ptrdiff_t``, ``size_t`` + and ``ssize_t``) as the opposite signedness to ensure that the output + would matches that of a simple wrapper for ``std::sprintf`` that + accepted a C-style variable argument list. For example, with + `StrictMode` enabled, + + .. code-block:: c++ + + extern std::string strprintf(const char *format, ...); + int i = -42; + unsigned int u = 0xffffffff; + return strprintf("%d %u\n", i, u); + + would be converted to + + .. code-block:: c++ + + return std::format("{} {}\n", static_cast(i), static_cast(u)); + + to ensure that the output will continue to be the unsigned representation + of -42 and the signed representation of 0xffffffff (often 4294967254 + and -1 respectively). When `false` (which is the default), these casts + will not be added which may cause a change in the output. Note that this + option makes no difference for the default value of + `StrFormatLikeFunctions` since ``absl::StrFormat`` takes a function + parameter pack and is not a variadic function. + +.. option:: StrFormatLikeFunctions + + A semicolon-separated list of (fully qualified) function names to + replace, with the requirement that the first parameter contains the + printf-style format string and the arguments to be formatted follow + immediately afterwards. The default value for this option is + `absl::StrFormat`. + +.. option:: ReplacementFormatFunction + + The function that will be used to replace the function set by the + `StrFormatLikeFunctions` option rather than the default + `std::format`. It is expected that the function provides an interface + that is compatible with ``std::format``. A suitable candidate would be + `fmt::format`. + +.. option:: FormatHeader + + The header that must be included for the declaration of + `ReplacementFormatFunction` so that a ``#include`` directive can be added if + required. If `ReplacementFormatFunction` is `std::format` then this option will + default to ````, otherwise this option will default to nothing + and no ``#include`` directive will be added. diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp new file mode 100644 index 000000000000..815e22b29155 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-custom.cpp @@ -0,0 +1,52 @@ +// RUN: %check_clang_tidy -check-suffixes=,STRICT \ +// RUN: -std=c++20 %s modernize-use-std-format %t -- \ +// RUN: -config="{CheckOptions: { \ +// RUN: modernize-use-std-format.StrictMode: true, \ +// RUN: modernize-use-std-format.StrFormatLikeFunctions: '::strprintf; mynamespace::strprintf2', \ +// RUN: modernize-use-std-format.ReplacementFormatFunction: 'fmt::format', \ +// RUN: modernize-use-std-format.FormatHeader: '' \ +// RUN: }}" \ +// RUN: -- -isystem %clang_tidy_headers +// RUN: %check_clang_tidy -check-suffixes=,NOTSTRICT \ +// RUN: -std=c++20 %s modernize-use-std-format %t -- \ +// RUN: -config="{CheckOptions: { \ +// RUN: modernize-use-std-format.StrFormatLikeFunctions: '::strprintf; mynamespace::strprintf2', \ +// RUN: modernize-use-std-format.ReplacementFormatFunction: 'fmt::format', \ +// RUN: modernize-use-std-format.FormatHeader: '' \ +// RUN: }}" \ +// RUN: -- -isystem %clang_tidy_headers + +#include +#include +// CHECK-FIXES: #include + +std::string strprintf(const char *, ...); + +namespace mynamespace { + std::string strprintf2(const char *, ...); +} + +std::string strprintf_test(const std::string &name, double value) { + return strprintf("'%s'='%f'\n", name.c_str(), value); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'fmt::format' instead of 'strprintf' [modernize-use-std-format] + // CHECK-FIXES: return fmt::format("'{}'='{:f}'\n", name, value); + + return mynamespace::strprintf2("'%s'='%f'\n", name.c_str(), value); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'fmt::format' instead of 'strprintf2' [modernize-use-std-format] + // CHECK-FIXES: return fmt::format("'{}'='{:f}'\n", name, value); +} + +std::string StrFormat_strict_conversion() { + const unsigned char uc = 'A'; + return strprintf("Integer %hhd from unsigned char\n", uc); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'fmt::format' instead of 'strprintf' [modernize-use-std-format] + // CHECK-FIXES-NOTSTRICT: return fmt::format("Integer {} from unsigned char\n", uc); + // CHECK-FIXES-STRICT: return fmt::format("Integer {} from unsigned char\n", static_cast(uc)); +} + +// Ensure that MatchesAnyListedNameMatcher::NameMatcher::match() can cope with a +// NamedDecl that has no name when we're trying to match unqualified_strprintf. +std::string A(const std::string &in) +{ + return "_" + in; +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp new file mode 100644 index 000000000000..9d136cf30916 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format-fmt.cpp @@ -0,0 +1,24 @@ +// RUN: %check_clang_tidy %s modernize-use-std-format %t -- \ +// RUN: -config="{CheckOptions: { \ +// RUN: StrictMode: true, \ +// RUN: modernize-use-std-format.StrFormatLikeFunctions: 'fmt::sprintf', \ +// RUN: modernize-use-std-format.ReplacementFormatFunction: 'fmt::format', \ +// RUN: modernize-use-std-format.FormatHeader: '' \ +// RUN: }}" \ +// RUN: -- -isystem %clang_tidy_headers + +// CHECK-FIXES: #include +#include + +namespace fmt +{ +// Use const char * for the format since the real type is hard to mock up. +template +std::string sprintf(const char *format, const Args&... args); +} // namespace fmt + +std::string fmt_sprintf_simple() { + return fmt::sprintf("Hello %s %d", "world", 42); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'fmt::format' instead of 'sprintf' [modernize-use-std-format] + // CHECK-FIXES: fmt::format("Hello {} {}", "world", 42); +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp new file mode 100644 index 000000000000..e8dea1dce2c9 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp @@ -0,0 +1,120 @@ +// RUN: %check_clang_tidy \ +// RUN: -std=c++20 %s modernize-use-std-format %t -- \ +// RUN: -config="{CheckOptions: {StrictMode: true}}" \ +// RUN: -- -isystem %clang_tidy_headers +// RUN: %check_clang_tidy \ +// RUN: -std=c++20 %s modernize-use-std-format %t -- \ +// RUN: -config="{CheckOptions: {StrictMode: false}}" \ +// RUN: -- -isystem %clang_tidy_headers +#include +// CHECK-FIXES: #include + +namespace absl +{ +// Use const char * for the format since the real type is hard to mock up. +template +std::string StrFormat(const char *format, const Args&... args); +} // namespace absl + +template +struct iterator { + T *operator->(); + T &operator*(); +}; + +std::string StrFormat_simple() { + return absl::StrFormat("Hello"); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: return std::format("Hello"); +} + +std::string StrFormat_complex(const char *name, double value) { + return absl::StrFormat("'%s'='%f'", name, value); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: return std::format("'{}'='{:f}'", name, value); +} + +std::string StrFormat_integer_conversions() { + return absl::StrFormat("int:%d int:%d char:%c char:%c", 65, 'A', 66, 'B'); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: return std::format("int:{} int:{:d} char:{:c} char:{}", 65, 'A', 66, 'B'); +} + +// FormatConverter is capable of removing newlines from the end of the format +// string. Ensure that isn't incorrectly happening for std::format. +std::string StrFormat_no_newline_removal() { + return absl::StrFormat("a line\n"); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: return std::format("a line\n"); +} + +// FormatConverter is capable of removing newlines from the end of the format +// string. Ensure that isn't incorrectly happening for std::format. +std::string StrFormat_cstr_removal(const std::string &s1, const std::string *s2) { + return absl::StrFormat("%s %s %s %s", s1.c_str(), s1.data(), s2->c_str(), s2->data()); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: return std::format("{} {} {} {}", s1, s1, *s2, *s2); +} + +std::string StrFormat_strict_conversion() { + const unsigned char uc = 'A'; + return absl::StrFormat("Integer %hhd from unsigned char\n", uc); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: return std::format("Integer {} from unsigned char\n", uc); +} + +std::string StrFormat_field_width_and_precision() { + auto s1 = absl::StrFormat("width only:%*d width and precision:%*.*f precision only:%.*f", 3, 42, 4, 2, 3.14159265358979323846, 5, 2.718); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: std::format("width only:{:{}} width and precision:{:{}.{}f} precision only:{:.{}f}", 42, 3, 3.14159265358979323846, 4, 2, 2.718, 5); + + auto s2 = absl::StrFormat("width and precision positional:%1$*2$.*3$f after", 3.14159265358979323846, 4, 2); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: std::format("width and precision positional:{0:{1}.{2}f} after", 3.14159265358979323846, 4, 2); + + const int width = 10, precision = 3; + const unsigned int ui1 = 42, ui2 = 43, ui3 = 44; + auto s3 = absl::StrFormat("casts width only:%*d width and precision:%*.*d precision only:%.*d\n", 3, ui1, 4, 2, ui2, 5, ui3); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES-NOTSTRICT: std::format("casts width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", ui1, 3, ui2, 4, 2, ui3, 5); + // CHECK-FIXES-STRICT: std::format("casts width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", static_cast(ui1), 3, static_cast(ui2), 4, 2, static_cast(ui3), 5); + + auto s4 = absl::StrFormat("c_str removal width only:%*s width and precision:%*.*s precision only:%.*s", 3, s1.c_str(), 4, 2, s2.c_str(), 5, s3.c_str()); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: std::format("c_str removal width only:{:>{}} width and precision:{:>{}.{}} precision only:{:.{}}", s1, 3, s2, 4, 2, s3, 5); + + const std::string *ps1 = &s1, *ps2 = &s2, *ps3 = &s3; + auto s5 = absl::StrFormat("c_str() removal pointer width only:%-*s width and precision:%-*.*s precision only:%-.*s", 3, ps1->c_str(), 4, 2, ps2->c_str(), 5, ps3->c_str()); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: std::format("c_str() removal pointer width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", *ps1, 3, *ps2, 4, 2, *ps3, 5); + + iterator is1, is2, is3; + auto s6 = absl::StrFormat("c_str() removal iterator width only:%-*s width and precision:%-*.*s precision only:%-.*s", 3, is1->c_str(), 4, 2, is2->c_str(), 5, is3->c_str()); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: std::format("c_str() removal iterator width only:{:{}} width and precision:{:{}.{}} precision only:{:.{}}", *is1, 3, *is2, 4, 2, *is3, 5); + + return s1 + s2 + s3 + s4 + s5 + s6; +} + +std::string StrFormat_macros() { + // The function call is replaced even though it comes from a macro. +#define FORMAT absl::StrFormat + auto s1 = FORMAT("Hello %d", 42); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: std::format("Hello {}", 42); + + // The format string is replaced even though it comes from a macro, this + // behaviour is required so that that macros are replaced. +#define FORMAT_STRING "Hello %s" + auto s2 = absl::StrFormat(FORMAT_STRING, 42); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: std::format("Hello {}", 42); + + // Arguments that are macros aren't replaced with their value, even if they are rearranged. +#define VALUE 3.14159265358979323846 +#define WIDTH 10 +#define PRECISION 4 + auto s3 = absl::StrFormat("Hello %*.*f", WIDTH, PRECISION, VALUE); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format] + // CHECK-FIXES: std::format("Hello {:{}.{}f}", VALUE, WIDTH, PRECISION); +} -- GitLab From 5944579ab20cfcb6d1a9d1a2fe3d4b478ea24c64 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Mon, 13 May 2024 18:43:29 +0000 Subject: [PATCH 120/578] [gn build] Port af79372d6349 --- .../gn/secondary/clang-tools-extra/clang-tidy/modernize/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/modernize/BUILD.gn b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/modernize/BUILD.gn index 0d27b786da1f..9b5e157385dd 100644 --- a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/modernize/BUILD.gn +++ b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/modernize/BUILD.gn @@ -50,6 +50,7 @@ static_library("modernize") { "UseNullptrCheck.cpp", "UseOverrideCheck.cpp", "UseStartsEndsWithCheck.cpp", + "UseStdFormatCheck.cpp", "UseStdNumbersCheck.cpp", "UseStdPrintCheck.cpp", "UseTrailingReturnTypeCheck.cpp", -- GitLab From a037d88929460ff9571927c56d6db215be086149 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Mon, 13 May 2024 15:10:25 -0400 Subject: [PATCH 121/578] [mlir][gpu] Support extf before contract when converting to MMA ops (#91988) This commit allows `inferFragType` to see through all arith.ext op and other elementwise users before reaching contract op for figuring out the fragment type. --- .../Conversion/VectorToGPU/VectorToGPU.cpp | 15 ++++++++--- .../VectorToGPU/vector-to-mma-ops.mlir | 27 +++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp b/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp index 782cc92f83fe..332f0a2eecfc 100644 --- a/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp +++ b/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp @@ -515,6 +515,14 @@ struct CombineTransferReadOpTranspose final // TODO: Change the GPU dialect to abstract the layout at the this level and // only care about it during lowering to NVVM. static const char *inferFragType(Operation *op) { + // We can have arith.ext ops before reaching contract ops. See through them + // and other kinds of elementwise ops. + if (op->hasOneUse()) { + Operation *userOp = *op->user_begin(); + if (userOp->hasTrait()) + return inferFragType(userOp); + } + for (Operation *users : op->getUsers()) { auto contract = dyn_cast(users); if (!contract) @@ -560,13 +568,12 @@ convertTransferReadOp(RewriterBase &rewriter, vector::TransferReadOp op, if (op->hasOneUse()) { auto *user = *op->user_begin(); // Infer the signedness of the mma type from the integer extend. - bool isSignedExtend = isa(user); - if (isSignedExtend || isa(user)) { + if (isa(user)) { elType = IntegerType::get( op.getContext(), cast(elType).getWidth(), - isSignedExtend ? IntegerType::Signed : IntegerType::Unsigned); + isa(user) ? IntegerType::Signed + : IntegerType::Unsigned); mappingResult = user->getResult(0); - fragType = inferFragType(user); } } gpu::MMAMatrixType type = diff --git a/mlir/test/Conversion/VectorToGPU/vector-to-mma-ops.mlir b/mlir/test/Conversion/VectorToGPU/vector-to-mma-ops.mlir index 962ed7de584a..8526ff139259 100644 --- a/mlir/test/Conversion/VectorToGPU/vector-to-mma-ops.mlir +++ b/mlir/test/Conversion/VectorToGPU/vector-to-mma-ops.mlir @@ -490,3 +490,30 @@ func.func @fold_transpose_into_transfer_read(%alloc: memref<64x128xf16>, %vector } // ----- + +#map1 = affine_map<(d0, d1, d2) -> (d0, d2)> +#map2 = affine_map<(d0, d1, d2) -> (d1, d2)> +#map3 = affine_map<(d0, d1, d2) -> (d0, d1)> + +// CHECK-LABEL: func @cast_f16_to_f32_read +// CHECK: %[[A:.+]] = gpu.subgroup_mma_load_matrix {{.+}} {leadDimension = 16 : index} : memref<16x16xf16> -> !gpu.mma_matrix<16x16xf16, "AOp"> +// CHECK: %[[C:.+]] = gpu.subgroup_mma_load_matrix {{.+}} {leadDimension = 16 : index} : memref<16x16xf16> -> !gpu.mma_matrix<16x16xf16, "COp"> +// CHECK: %[[AE:.+]] = gpu.subgroup_mma_elementwise extf %[[A]] : (!gpu.mma_matrix<16x16xf16, "AOp">) -> !gpu.mma_matrix<16x16xf32, "AOp"> +// CHECK: %[[CE:.+]] = gpu.subgroup_mma_elementwise extf %[[C]] : (!gpu.mma_matrix<16x16xf16, "COp">) -> !gpu.mma_matrix<16x16xf32, "COp"> +// CHECK: %[[B:.+]] = gpu.subgroup_mma_load_matrix {{.+}} {leadDimension = 16 : index, transpose} : memref<16x16xf16> -> !gpu.mma_matrix<16x16xf16, "BOp"> +// CHECK: %[[BE:.+]] = gpu.subgroup_mma_elementwise extf %[[B]] : (!gpu.mma_matrix<16x16xf16, "BOp">) -> !gpu.mma_matrix<16x16xf32, "BOp"> +// CHECK: gpu.subgroup_mma_compute %[[AE]], %[[BE]], %[[CE]] +func.func @cast_f16_to_f32_read(%arg0: memref<16x16xf16>, %arg1: memref<16x16xf16>, %arg2: memref<16x16xf16>, %arg3: memref<16x16xf32>) { + %c0 = arith.constant 0 : index + %cst = arith.constant 0.000000e+00 : f16 + %A = vector.transfer_read %arg0[%c0, %c0], %cst {in_bounds = [true, true]} : memref<16x16xf16>, vector<16x16xf16> + %B = vector.transfer_read %arg1[%c0, %c0], %cst {in_bounds = [true, true]} : memref<16x16xf16>, vector<16x16xf16> + %C = vector.transfer_read %arg2[%c0, %c0], %cst {in_bounds = [true, true]} : memref<16x16xf16>, vector<16x16xf16> + %Aext = arith.extf %A : vector<16x16xf16> to vector<16x16xf32> + %Bext = arith.extf %B : vector<16x16xf16> to vector<16x16xf32> + %Cext = arith.extf %C : vector<16x16xf16> to vector<16x16xf32> + %D = vector.contract {indexing_maps = [#map1, #map2, #map3], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind} + %Aext, %Bext, %Cext : vector<16x16xf32>, vector<16x16xf32> into vector<16x16xf32> + vector.transfer_write %D, %arg3[%c0, %c0] {in_bounds = [true, true]} : vector<16x16xf32>, memref<16x16xf32> + return +} -- GitLab From 54b17fa4eefb7ccb00fba8189e92fac2d46cc481 Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Sun, 12 May 2024 14:26:41 -0700 Subject: [PATCH 122/578] [BOLT] Preserve Offset annotation in fixDoubleJumps (#91898) Offset annotation was missed when optimizing an unconditional branch to a tail call. Test Plan: update bb-with-two-tail-calls.s --- bolt/lib/Passes/BinaryPasses.cpp | 3 +++ bolt/test/X86/bb-with-two-tail-calls.s | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index df6dbcddeed5..867f977cebca 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -715,6 +715,9 @@ static uint64_t fixDoubleJumps(BinaryFunction &Function, bool MarkInvalid) { Pred->removeSuccessor(&BB); Pred->eraseInstruction(Pred->findInstruction(Branch)); Pred->addTailCallInstruction(SuccSym); + MCInst *TailCall = Pred->getLastNonPseudoInstr(); + assert(TailCall); + MIB->setOffset(*TailCall, BB.getOffset()); } else { return false; } diff --git a/bolt/test/X86/bb-with-two-tail-calls.s b/bolt/test/X86/bb-with-two-tail-calls.s index caad7b3d735f..bb2b0cd4cc23 100644 --- a/bolt/test/X86/bb-with-two-tail-calls.s +++ b/bolt/test/X86/bb-with-two-tail-calls.s @@ -9,11 +9,11 @@ # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib # RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata --lite=0 --dyno-stats \ -# RUN: --print-sctc --print-only=_start 2>&1 | FileCheck %s +# RUN: --print-sctc --print-only=_start -enable-bat 2>&1 | FileCheck %s # CHECK-NOT: Assertion `BranchInfo.size() == 2 && "could only be called for blocks with 2 successors"' failed. # Two tail calls in the same basic block after SCTC: -# CHECK: {{.*}}: ja {{.*}} # TAILCALL # CTCTakenCount: {{.*}} -# CHECK-NEXT: {{.*}}: jmp {{.*}} # TAILCALL +# CHECK: {{.*}}: ja {{.*}} # TAILCALL # Offset: 7 # CTCTakenCount: 4 +# CHECK-NEXT: {{.*}}: jmp {{.*}} # TAILCALL # Offset: 12 .globl _start _start: -- GitLab From fd4b5f4b52e414bb6fee7c906a22867891fb46b5 Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Mon, 13 May 2024 12:32:16 -0700 Subject: [PATCH 123/578] [lldb] Add CMake dependency tracking for SBLanguages generation script (#91686) If you change the generation script and re-run ninja (or whatever drives your build), it currently will not regenerate SBLanguages.h. With dependency tracking, it should re-run when the script changes. --- lldb/source/API/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt index aa31caddfde3..76b42ecf63f9 100644 --- a/lldb/source/API/CMakeLists.txt +++ b/lldb/source/API/CMakeLists.txt @@ -23,14 +23,17 @@ endif() # Generate SBLanguages.h from Dwarf.def. set(sb_languages_file ${CMAKE_CURRENT_BINARY_DIR}/../../include/lldb/API/SBLanguages.h) +set(sb_languages_generator + ${LLDB_SOURCE_DIR}/scripts/generate-sbapi-dwarf-enum.py) add_custom_command( COMMENT "Generating SBLanguages.h from Dwarf.def" COMMAND "${Python3_EXECUTABLE}" - ${LLDB_SOURCE_DIR}/scripts/generate-sbapi-dwarf-enum.py + ${sb_languages_generator} ${LLVM_MAIN_INCLUDE_DIR}/llvm/BinaryFormat/Dwarf.def -o ${sb_languages_file} OUTPUT ${sb_languages_file} DEPENDS ${LLVM_MAIN_INCLUDE_DIR}/llvm/BinaryFormat/Dwarf.def + ${sb_languages_generator} WORKING_DIRECTORY ${LLVM_LIBRARY_OUTPUT_INTDIR} ) add_custom_target(lldb-sbapi-dwarf-enums -- GitLab From a1d43c14d8a672730af48d946acc41fa01cf301e Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Mon, 13 May 2024 15:36:28 -0400 Subject: [PATCH 124/578] [mlir][vector] Add Vector-dialect interleave-to-shuffle pattern, enable in VectorToSPIRV (#92012) This is the second attempt at merging #91800, which bounced due to a linker error apparently caused by an undeclared dependency. `MLIRVectorToSPIRV` needed to depend on `MLIRVectorTransforms`. In fact that was a preexisting issue already flagged by the tool in https://discourse.llvm.org/t/ninja-can-now-check-for-missing-cmake-dependencies-on-generated-files/74344. Context: https://github.com/iree-org/iree/issues/17346. Test IREE integrate showing it's fixing the problem it's intended to fix, i.e. it allows IREE to drop its local revert of https://github.com/llvm/llvm-project/pull/89131: https://github.com/iree-org/iree/pull/17359 This is added to VectorToSPIRV because SPIRV doesn't currently handle `vector.interleave` (see motivating context above). This is limited to 1D, non-scalable vectors. --- .../Vector/TransformOps/VectorTransformOps.td | 14 +++++++ .../Vector/Transforms/LoweringPatterns.h | 3 ++ .../Conversion/VectorToSPIRV/CMakeLists.txt | 1 + .../VectorToSPIRV/VectorToSPIRV.cpp | 4 ++ .../TransformOps/VectorTransformOps.cpp | 5 +++ .../Transforms/LowerVectorInterleave.cpp | 41 +++++++++++++++++++ .../Vector/vector-interleave-to-shuffle.mlir | 21 ++++++++++ .../llvm-project-overlay/mlir/BUILD.bazel | 1 + 8 files changed, 90 insertions(+) create mode 100644 mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir diff --git a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td index f6371f39c394..bc3c16d40520 100644 --- a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td +++ b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td @@ -306,6 +306,20 @@ def ApplyLowerInterleavePatternsOp : Op]> { + let description = [{ + Indicates that 1D vector interleave operations should be rewritten as + vector shuffle operations. + + This is motivated by some current codegen backends not handling vector + interleave operations. + }]; + + let assemblyFormat = "attr-dict"; +} + def ApplyRewriteNarrowTypePatternsOp : Op]> { diff --git a/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h b/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h index 350d2777cadf..8fd9904fabc0 100644 --- a/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h +++ b/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h @@ -273,6 +273,9 @@ void populateVectorInterleaveLoweringPatterns(RewritePatternSet &patterns, int64_t targetRank = 1, PatternBenefit benefit = 1); +void populateVectorInterleaveToShufflePatterns(RewritePatternSet &patterns, + PatternBenefit benefit = 1); + } // namespace vector } // namespace mlir #endif // MLIR_DIALECT_VECTOR_TRANSFORMS_LOWERINGPATTERNS_H diff --git a/mlir/lib/Conversion/VectorToSPIRV/CMakeLists.txt b/mlir/lib/Conversion/VectorToSPIRV/CMakeLists.txt index bb9f793d7fe0..113983146f5b 100644 --- a/mlir/lib/Conversion/VectorToSPIRV/CMakeLists.txt +++ b/mlir/lib/Conversion/VectorToSPIRV/CMakeLists.txt @@ -14,5 +14,6 @@ add_mlir_conversion_library(MLIRVectorToSPIRV MLIRSPIRVDialect MLIRSPIRVConversion MLIRVectorDialect + MLIRVectorTransforms MLIRTransforms ) diff --git a/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp b/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp index 868a3521e7a0..c2dd37f48146 100644 --- a/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp +++ b/mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp @@ -18,6 +18,7 @@ #include "mlir/Dialect/SPIRV/IR/SPIRVTypes.h" #include "mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" +#include "mlir/Dialect/Vector/Transforms/LoweringPatterns.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinTypes.h" @@ -828,6 +829,9 @@ void mlir::populateVectorToSPIRVPatterns(SPIRVTypeConverter &typeConverter, // than the generic one that extracts all elements. patterns.add(typeConverter, patterns.getContext(), PatternBenefit(2)); + + // Need this until vector.interleave is handled. + vector::populateVectorInterleaveToShufflePatterns(patterns); } void mlir::populateVectorReductionToSPIRVDotProductPatterns( diff --git a/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp b/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp index 885644864c0f..61fd6bd972e3 100644 --- a/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp +++ b/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp @@ -164,6 +164,11 @@ void transform::ApplyLowerInterleavePatternsOp::populatePatterns( vector::populateVectorInterleaveLoweringPatterns(patterns); } +void transform::ApplyInterleaveToShufflePatternsOp::populatePatterns( + RewritePatternSet &patterns) { + vector::populateVectorInterleaveToShufflePatterns(patterns); +} + void transform::ApplyRewriteNarrowTypePatternsOp::populatePatterns( RewritePatternSet &patterns) { populateVectorNarrowTypeRewritePatterns(patterns); diff --git a/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp b/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp index 3a456076f8fb..5326760c9b4e 100644 --- a/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp @@ -16,6 +16,7 @@ #include "mlir/Dialect/Vector/Utils/VectorUtils.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/PatternMatch.h" +#include "mlir/Support/LogicalResult.h" #define DEBUG_TYPE "vector-interleave-lowering" @@ -77,9 +78,49 @@ private: int64_t targetRank = 1; }; +/// Rewrite vector.interleave op into an equivalent vector.shuffle op, when +/// applicable: `sourceType` must be 1D and non-scalable. +/// +/// Example: +/// +/// ```mlir +/// vector.interleave %a, %b : vector<7xi16> +/// ``` +/// +/// Is rewritten into: +/// +/// ```mlir +/// vector.shuffle %arg0, %arg1 [0, 7, 1, 8, 2, 9, 3, 10, 4, 11, 5, 12, 6, 13] +/// : vector<7xi16>, vector<7xi16> +/// ``` +class InterleaveToShuffle : public OpRewritePattern { +public: + InterleaveToShuffle(MLIRContext *context, PatternBenefit benefit = 1) + : OpRewritePattern(context, benefit) {}; + + LogicalResult matchAndRewrite(vector::InterleaveOp op, + PatternRewriter &rewriter) const override { + VectorType sourceType = op.getSourceVectorType(); + if (sourceType.getRank() != 1 || sourceType.isScalable()) { + return failure(); + } + int64_t n = sourceType.getNumElements(); + auto seq = llvm::seq(2 * n); + auto zip = llvm::to_vector(llvm::map_range( + seq, [n](int64_t i) { return (i % 2 ? n : 0) + i / 2; })); + rewriter.replaceOpWithNewOp(op, op.getLhs(), op.getRhs(), zip); + return success(); + } +}; + } // namespace void mlir::vector::populateVectorInterleaveLoweringPatterns( RewritePatternSet &patterns, int64_t targetRank, PatternBenefit benefit) { patterns.add(targetRank, patterns.getContext(), benefit); } + +void mlir::vector::populateVectorInterleaveToShufflePatterns( + RewritePatternSet &patterns, PatternBenefit benefit) { + patterns.add(patterns.getContext(), benefit); +} diff --git a/mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir b/mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir new file mode 100644 index 000000000000..ed3b3396bf3e --- /dev/null +++ b/mlir/test/Dialect/Vector/vector-interleave-to-shuffle.mlir @@ -0,0 +1,21 @@ +// RUN: mlir-opt %s --transform-interpreter | FileCheck %s + +// CHECK-LABEL: @vector_interleave_to_shuffle +func.func @vector_interleave_to_shuffle(%a: vector<7xi16>, %b: vector<7xi16>) -> vector<14xi16> +{ + %0 = vector.interleave %a, %b : vector<7xi16> + return %0 : vector<14xi16> +} +// CHECK: vector.shuffle %arg0, %arg1 [0, 7, 1, 8, 2, 9, 3, 10, 4, 11, 5, 12, 6, 13] : vector<7xi16>, vector<7xi16> + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%module_op: !transform.any_op {transform.readonly}) { + %f = transform.structured.match ops{["func.func"]} in %module_op + : (!transform.any_op) -> !transform.any_op + + transform.apply_patterns to %f { + transform.apply_patterns.vector.interleave_to_shuffle + } : !transform.any_op + transform.yield + } +} diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 6304b7b548d8..debd8daf5549 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -5877,6 +5877,7 @@ cc_library( ":Support", ":TransformUtils", ":VectorDialect", + ":VectorTransforms", "//llvm:Support", ], ) -- GitLab From 31a203fa8af47a8b2e8e357857b114cf90638b2e Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Mon, 13 May 2024 23:37:59 +0400 Subject: [PATCH 125/578] [clang] Introduce `SemaObjC` (#89086) This is continuation of efforts to split `Sema` up, following the example of OpenMP, OpenACC, etc. Context can be found in https://github.com/llvm/llvm-project/pull/82217 and https://github.com/llvm/llvm-project/pull/84184. I split formatting changes into a separate commit to help reviewing the actual changes. --- clang/include/clang/Parse/Parser.h | 11 +- clang/include/clang/Sema/Sema.h | 1002 +---------- clang/include/clang/Sema/SemaObjC.h | 1014 +++++++++++ clang/lib/ARCMigrate/Transforms.cpp | 5 +- clang/lib/Parse/ParseDecl.cpp | 7 +- clang/lib/Parse/ParseExpr.cpp | 17 +- clang/lib/Parse/ParseInit.cpp | 9 +- clang/lib/Parse/ParseObjc.cpp | 255 ++- clang/lib/Parse/ParseStmt.cpp | 11 +- clang/lib/Sema/CMakeLists.txt | 1 + clang/lib/Sema/Sema.cpp | 14 +- clang/lib/Sema/SemaAPINotes.cpp | 3 +- clang/lib/Sema/SemaAttr.cpp | 16 - clang/lib/Sema/SemaAvailability.cpp | 7 +- clang/lib/Sema/SemaCast.cpp | 13 +- clang/lib/Sema/SemaChecking.cpp | 528 +----- clang/lib/Sema/SemaCodeComplete.cpp | 40 +- clang/lib/Sema/SemaDecl.cpp | 292 +--- clang/lib/Sema/SemaDeclAttr.cpp | 11 +- clang/lib/Sema/SemaDeclCXX.cpp | 58 +- clang/lib/Sema/SemaDeclObjC.cpp | 1444 +++++++++------- clang/lib/Sema/SemaExpr.cpp | 559 +------ clang/lib/Sema/SemaExprCXX.cpp | 17 +- clang/lib/Sema/SemaExprMember.cpp | 12 +- clang/lib/Sema/SemaExprObjC.cpp | 1342 ++++++++++----- clang/lib/Sema/SemaInit.cpp | 17 +- clang/lib/Sema/SemaLookup.cpp | 9 - clang/lib/Sema/SemaObjC.cpp | 1486 +++++++++++++++++ clang/lib/Sema/SemaObjCProperty.cpp | 290 ++-- clang/lib/Sema/SemaOverload.cpp | 78 +- clang/lib/Sema/SemaPseudoObject.cpp | 186 +-- clang/lib/Sema/SemaStmt.cpp | 307 +--- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 +- clang/lib/Sema/SemaType.cpp | 465 +----- clang/lib/Sema/TreeTransform.h | 113 +- clang/lib/Serialization/ASTCommon.cpp | 2 +- clang/lib/Serialization/ASTReader.cpp | 15 +- clang/lib/Serialization/ASTWriter.cpp | 14 +- 38 files changed, 4897 insertions(+), 4776 deletions(-) create mode 100644 clang/include/clang/Sema/SemaObjC.h create mode 100644 clang/lib/Sema/SemaObjC.cpp diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 3910cba34a21..7a8c2bcde804 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -18,6 +18,7 @@ #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Frontend/OpenMP/OMPContext.h" @@ -445,8 +446,8 @@ class Parser : public CodeCompletionHandler { /// True if we are within an Objective-C container while parsing C-like decls. /// /// This is necessary because Sema thinks we have left the container - /// to parse the C-like decls, meaning Actions.getObjCDeclContext() will - /// be NULL. + /// to parse the C-like decls, meaning Actions.ObjC().getObjCDeclContext() + /// will be NULL. bool ParsingInObjCContainer; /// Whether to skip parsing of function bodies. @@ -497,7 +498,7 @@ public: } ObjCContainerDecl *getObjCDeclContext() const { - return Actions.getObjCDeclContext(); + return Actions.ObjC().getObjCDeclContext(); } // Type forwarding. All of these are statically 'void*', but they may all be @@ -1083,11 +1084,11 @@ private: : P(p), DC(p.getObjCDeclContext()), WithinObjCContainer(P.ParsingInObjCContainer, DC != nullptr) { if (DC) - P.Actions.ActOnObjCTemporaryExitContainerContext(DC); + P.Actions.ObjC().ActOnObjCTemporaryExitContainerContext(DC); } ~ObjCDeclContextSwitch() { if (DC) - P.Actions.ActOnObjCReenterContainerContext(DC); + P.Actions.ObjC().ActOnObjCReenterContainerContext(DC); } }; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 869769f95fd7..6a414aa57f32 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -152,18 +152,9 @@ typedef ArrayRef> ModuleIdPath; class ModuleLoader; class MultiLevelTemplateArgumentList; class NamedDecl; -class ObjCCategoryDecl; -class ObjCCategoryImplDecl; -class ObjCCompatibleAliasDecl; -class ObjCContainerDecl; -class ObjCImplDecl; class ObjCImplementationDecl; class ObjCInterfaceDecl; -class ObjCIvarDecl; -template class ObjCList; -class ObjCMessageExpr; class ObjCMethodDecl; -class ObjCPropertyDecl; class ObjCProtocolDecl; struct OverloadCandidate; enum class OverloadCandidateParamOrder : char; @@ -178,6 +169,7 @@ class PseudoObjectExpr; class QualType; class SemaCUDA; class SemaHLSL; +class SemaObjC; class SemaOpenACC; class SemaOpenMP; class SemaSYCL; @@ -489,12 +481,9 @@ class Sema final : public SemaBase { // 29. C++ Variadic Templates (SemaTemplateVariadic.cpp) // 30. Constraints and Concepts (SemaConcept.cpp) // 31. Types (SemaType.cpp) - // 32. ObjC Declarations (SemaDeclObjC.cpp) - // 33. ObjC Expressions (SemaExprObjC.cpp) - // 34. ObjC @property and @synthesize (SemaObjCProperty.cpp) - // 35. Code Completion (SemaCodeComplete.cpp) - // 36. FixIt Helpers (SemaFixItUtils.cpp) - // 37. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) + // 32. Code Completion (SemaCodeComplete.cpp) + // 33. FixIt Helpers (SemaFixItUtils.cpp) + // 34. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) /// \name Semantic Analysis /// Implementations are in Sema.cpp @@ -1005,6 +994,11 @@ public: return *HLSLPtr; } + SemaObjC &ObjC() { + assert(ObjCPtr); + return *ObjCPtr; + } + SemaOpenACC &OpenACC() { assert(OpenACCPtr); return *OpenACCPtr; @@ -1020,6 +1014,9 @@ public: return *SYCLPtr; } + /// Source of additional semantic information. + IntrusiveRefCntPtr ExternalSource; + protected: friend class Parser; friend class InitializationSequence; @@ -1034,9 +1031,6 @@ private: Sema(const Sema &) = delete; void operator=(const Sema &) = delete; - /// Source of additional semantic information. - IntrusiveRefCntPtr ExternalSource; - /// The handler for the FileChanged preprocessor events. /// /// Used for diagnostics that implement custom semantic analysis for #include @@ -1052,6 +1046,7 @@ private: std::unique_ptr CUDAPtr; std::unique_ptr HLSLPtr; + std::unique_ptr ObjCPtr; std::unique_ptr OpenACCPtr; std::unique_ptr OpenMPPtr; std::unique_ptr SYCLPtr; @@ -1634,11 +1629,6 @@ public: void ActOnPragmaUnused(const Token &Identifier, Scope *curScope, SourceLocation PragmaLoc); - /// AddCFAuditedAttribute - Check whether we're currently within - /// '\#pragma clang arc_cf_code_audited' and, if so, consider adding - /// the appropriate attribute. - void AddCFAuditedAttribute(Decl *D); - void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute, SourceLocation PragmaLoc, attr::ParsedSubjectMatchRuleSet Rules); @@ -1978,12 +1968,6 @@ public: void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange); - /// checkRetainCycles - Check whether an Objective-C message send - /// might create an obvious retain cycle. - void checkRetainCycles(ObjCMessageExpr *msg); - void checkRetainCycles(Expr *receiver, Expr *argument); - void checkRetainCycles(VarDecl *Var, Expr *Init); - /// checkUnsafeAssigns - Check whether +1 expr is being assigned /// to weak/__unsafe_unretained type. bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS); @@ -2030,14 +2014,20 @@ public: bool CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, + const Expr *ThisArg, ArrayRef Args, + bool IsMemberFunction, SourceLocation Loc, SourceRange Range, + VariadicCallType CallType); + + void CheckTCBEnforcement(const SourceLocation CallExprLoc, + const NamedDecl *Callee); + private: void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, const ArraySubscriptExpr *ASE = nullptr, bool AllowOnePastEnd = true, bool IndexNegated = false); void CheckArrayAccess(const Expr *E); - bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc, - ArrayRef Args); bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, const FunctionProtoType *Proto); bool CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto); @@ -2050,12 +2040,6 @@ private: void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl, StringRef ParamName, QualType ArgTy, QualType ParamTy); - void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, - const Expr *ThisArg, ArrayRef Args, - bool IsMemberFunction, SourceLocation Loc, SourceRange Range, - VariadicCallType CallType); - - bool CheckObjCString(Expr *Arg); ExprResult CheckOSLogFormatStringArg(Expr *Arg); ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, @@ -2228,12 +2212,6 @@ private: void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field, Expr *Init); - /// Check whether receiver is mutable ObjC container which - /// attempts to add itself into the container - void CheckObjCCircularContainer(ObjCMessageExpr *Message); - - void CheckTCBEnforcement(const SourceLocation CallExprLoc, - const NamedDecl *Callee); /// A map from magic value to type information. std::unique_ptr> @@ -2636,7 +2614,7 @@ public: SmallVector ExternalDeclarations; /// Generally null except when we temporarily switch decl contexts, - /// like in \see ActOnObjCTemporaryExitContainerContext. + /// like in \see SemaObjC::ActOnObjCTemporaryExitContainerContext. DeclContext *OriginalLexicalContext; /// Is the module scope we are in a C++ Header Unit? @@ -2985,9 +2963,6 @@ public: SourceLocation ExplicitThisLoc = {}); ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T); - QualType AdjustParameterTypeForObjCAutoRefCount(QualType T, - SourceLocation NameLoc, - TypeSourceInfo *TSInfo); ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc, SourceLocation NameLoc, const IdentifierInfo *Name, QualType T, @@ -3225,8 +3200,6 @@ public: void ActOnLastBitfield(SourceLocation DeclStart, SmallVectorImpl &AllIvarDecls); - Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, - Expr *BitWidth, tok::ObjCKeywordKind visibility); // This is used for both record definitions and ObjC interface declarations. void ActOnFields(Scope *S, SourceLocation RecLoc, Decl *TagDecl, @@ -3248,8 +3221,6 @@ public: /// Invoked when we enter a tag definition that we're skipping. SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD); - void ActOnObjCContainerStartDefinition(ObjCContainerDecl *IDecl); - /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a /// C++ record definition's base-specifiers clause and are starting its /// member declarations. @@ -3266,15 +3237,6 @@ public: void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context); - void ActOnObjCContainerFinishDefinition(); - - /// Invoked when we must temporarily exit the objective-c container - /// scope for parsing/looking-up C constructs. - /// - /// Must be followed by a call to \see ActOnObjCReenterContainerContext - void ActOnObjCTemporaryExitContainerContext(ObjCContainerDecl *ObjCCtx); - void ActOnObjCReenterContainerContext(ObjCContainerDecl *ObjCCtx); - /// ActOnTagDefinitionError - Invoked when there was an unrecoverable /// error parsing the definition of a tag. void ActOnTagDefinitionError(Scope *S, Decl *TagDecl); @@ -3401,10 +3363,6 @@ public: /// variable. void DiagnoseUnusedButSetDecl(const VarDecl *VD, DiagReceiverTy DiagReceiver); - ObjCInterfaceDecl *getObjCInterfaceDecl(const IdentifierInfo *&Id, - SourceLocation IdLoc, - bool TypoCorrection = false); - Scope *getNonFieldDeclScope(Scope *S); FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID, @@ -3426,8 +3384,6 @@ public: /// Look for a locally scoped extern "C" declaration by the given name. NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name); - bool inferObjCARCLifetime(ValueDecl *decl); - void deduceOpenCLAddressSpace(ValueDecl *decl); static bool adjustContextForLocalExternDecl(DeclContext *&DC); @@ -3499,8 +3455,6 @@ public: SourceLocation WeakNameLoc, SourceLocation AliasNameLoc); - ObjCContainerDecl *getObjCDeclContext() const; - /// Status of the function emission on the CUDA/HIP/OpenMP host/device attrs. enum class FunctionEmissionStatus { Emitted, @@ -4339,8 +4293,6 @@ public: CXXConstructorDecl *Constructor, bool AnyErrors, ArrayRef Initializers = std::nullopt); - void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation); - /// MarkBaseAndMemberDestructorsReferenced - Given a record decl, /// mark all the non-trivial destructors of its members and bases as /// referenced. @@ -5390,14 +5342,6 @@ public: DeclContext *LookupCtx = nullptr, TypoExpr **Out = nullptr); - DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S, - IdentifierInfo *II); - ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV); - - ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S, - IdentifierInfo *II, - bool AllowBuiltinCreation = false); - /// If \p D cannot be odr-used in the current expression evaluation context, /// return a reason explaining why. Otherwise, return NOUR_None. NonOdrUseReason getNonOdrUseReasonInCurrentContext(ValueDecl *D); @@ -5715,19 +5659,6 @@ public: ArrayRef SubExprs, QualType T = QualType()); - // Note that LK_String is intentionally after the other literals, as - // this is used for diagnostics logic. - enum ObjCLiteralKind { - LK_Array, - LK_Dictionary, - LK_Numeric, - LK_Boxed, - LK_String, - LK_Block, - LK_None - }; - ObjCLiteralKind CheckLiteralKind(Expr *FromE); - ExprResult PerformObjectMemberConversion(Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, @@ -5763,14 +5694,6 @@ public: bool IsInvalidSMECallConversion(QualType FromType, QualType ToType); - const DeclContext *getCurObjCLexicalContext() const { - const DeclContext *DC = getCurLexicalContext(); - // A category implicitly has the attribute of the interface. - if (const ObjCCategoryDecl *CatD = dyn_cast(DC)) - DC = CatD->getClassInterface(); - return DC; - } - /// Abstract base class used for diagnosing integer constant /// expression violations. class VerifyICEDiagnoser { @@ -5908,9 +5831,6 @@ public: ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc); - QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, - SourceLocation QuestionLoc); - bool DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation QuestionLoc); @@ -6258,9 +6178,6 @@ public: Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType, BinaryOperatorKind Opc); - bool CheckConversionToObjCLiteral(QualType DstType, Expr *&SrcExpr, - bool Diagnose = true); - /// To be used for checking whether the arguments being passed to /// function exceeds the number of parameters expected for it. static bool TooManyArguments(size_t NumParams, size_t NumArgs, @@ -6593,13 +6510,6 @@ public: /// ActOnCXXBoolLiteral - Parse {true,false} literals. ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); - /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. - ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); - - ExprResult - ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef AvailSpecs, - SourceLocation AtLoc, SourceLocation RParen); - /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc); @@ -7468,9 +7378,6 @@ public: bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, QualType ObjectType, bool AllowBuiltinCreation = false, bool EnteringContext = false); - ObjCProtocolDecl *LookupProtocol( - IdentifierInfo *II, SourceLocation IdLoc, - RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration); bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class); void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, @@ -7499,6 +7406,20 @@ public: /// visible at the specified location. void makeMergedDefinitionVisible(NamedDecl *ND); + /// Check ODR hashes for C/ObjC when merging types from modules. + /// Differently from C++, actually parse the body and reject in case + /// of a mismatch. + template ::value>> + bool ActOnDuplicateODRHashDefinition(T *Duplicate, T *Previous) { + if (Duplicate->getODRHash() != Previous->getODRHash()) + return false; + + // Make the previous decl visible. + makeMergedDefinitionVisible(Previous); + return true; + } + /// Get the set of additional modules that should be checked during /// name lookup. A module and its imports become visible when instanting a /// template defined within it. @@ -7964,8 +7885,6 @@ public: bool &IncompatibleObjC); bool isObjCPointerConversion(QualType FromType, QualType ToType, QualType &ConvertedType, bool &IncompatibleObjC); - bool isObjCWritebackConversion(QualType FromType, QualType ToType, - QualType &ConvertedType); bool IsBlockPointerConversion(QualType FromType, QualType ToType, QualType &ConvertedType); @@ -8427,7 +8346,6 @@ public: DeclAccessPair FoundDecl, FunctionDecl *Fn); -private: /// - Returns a selector which best matches given argument list or /// nullptr if none could be found ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args, @@ -8448,10 +8366,6 @@ private: public: void maybeExtendBlockObject(ExprResult &E); - CastKind PrepareCastToObjCObjectPointer(ExprResult &E); - - enum ObjCSubscriptKind { OS_Array, OS_Dictionary, OS_Error }; - ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE); ExprResult checkPseudoObjectIncDec(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opcode, Expr *Op); @@ -8559,13 +8473,6 @@ public: StmtResult ActOnForEachLValueExpr(Expr *E); - ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc, - Expr *collection); - StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, Stmt *First, - Expr *collection, - SourceLocation RParenLoc); - StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body); - enum BuildForRangeKind { /// Initial building of a for-range statement. BFRK_Build, @@ -8632,24 +8539,6 @@ public: NamedReturnInfo &NRInfo, bool SupressSimplerImplicitMoves); - StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, - Decl *Parm, Stmt *Body); - - StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body); - - StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, - MultiStmtArg Catch, Stmt *Finally); - - StmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw); - StmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, - Scope *CurScope); - ExprResult ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, - Expr *operand); - StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SynchExpr, - Stmt *SynchBody); - - StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body); - StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, Stmt *HandlerBlock); StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, @@ -11471,36 +11360,6 @@ public: Default = AcceptSizeless }; - /// Build a an Objective-C protocol-qualified 'id' type where no - /// base type was specified. - TypeResult actOnObjCProtocolQualifierType( - SourceLocation lAngleLoc, ArrayRef protocols, - ArrayRef protocolLocs, SourceLocation rAngleLoc); - - /// Build a specialized and/or protocol-qualified Objective-C type. - TypeResult actOnObjCTypeArgsAndProtocolQualifiers( - Scope *S, SourceLocation Loc, ParsedType BaseType, - SourceLocation TypeArgsLAngleLoc, ArrayRef TypeArgs, - SourceLocation TypeArgsRAngleLoc, SourceLocation ProtocolLAngleLoc, - ArrayRef Protocols, ArrayRef ProtocolLocs, - SourceLocation ProtocolRAngleLoc); - - /// Build an Objective-C type parameter type. - QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, - SourceLocation ProtocolLAngleLoc, - ArrayRef Protocols, - ArrayRef ProtocolLocs, - SourceLocation ProtocolRAngleLoc, - bool FailOnError = false); - - /// Build an Objective-C object pointer type. - QualType BuildObjCObjectType( - QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc, - ArrayRef TypeArgs, SourceLocation TypeArgsRAngleLoc, - SourceLocation ProtocolLAngleLoc, ArrayRef Protocols, - ArrayRef ProtocolLocs, SourceLocation ProtocolRAngleLoc, - bool FailOnError, bool Rebuilding); - QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs, const DeclSpec *DS = nullptr); QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA, @@ -11582,10 +11441,6 @@ public: TypeResult ActOnTypeName(Declarator &D); - /// The parser has parsed the context-sensitive type 'instancetype' - /// in an Objective-C message declaration. Return the appropriate type. - ParsedType ActOnObjCInstanceType(SourceLocation Loc); - // Check whether the size of array element of type \p EltTy is a multiple of // its alignment and return false if it isn't. bool checkArrayElementAlignment(QualType EltTy, SourceLocation Loc); @@ -11602,13 +11457,6 @@ public: /// Retrieve the keyword associated IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability); - /// The struct behind the CFErrorRef pointer. - RecordDecl *CFError = nullptr; - bool isCFError(RecordDecl *D); - - /// Retrieve the identifier "NSError". - IdentifierInfo *getNSErrorIdent(); - /// Adjust the calling convention of a method to be the ABI default if it /// wasn't specified explicitly. This handles method types formed from /// function type typedefs and typename template arguments. @@ -11795,784 +11643,6 @@ private: IdentifierInfo *Ident__Nullable_result = nullptr; IdentifierInfo *Ident__Null_unspecified = nullptr; - IdentifierInfo *Ident_NSError = nullptr; - - ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - - /// \name ObjC Declarations - /// Implementations are in SemaDeclObjC.cpp - ///@{ - -public: - enum ObjCSpecialMethodKind { - OSMK_None, - OSMK_Alloc, - OSMK_New, - OSMK_Copy, - OSMK_RetainingInit, - OSMK_NonRetainingInit - }; - - /// Method selectors used in a \@selector expression. Used for implementation - /// of -Wselector. - llvm::MapVector ReferencedSelectors; - - class GlobalMethodPool { - public: - using Lists = std::pair; - using iterator = llvm::DenseMap::iterator; - iterator begin() { return Methods.begin(); } - iterator end() { return Methods.end(); } - iterator find(Selector Sel) { return Methods.find(Sel); } - std::pair insert(std::pair &&Val) { - return Methods.insert(Val); - } - int count(Selector Sel) const { return Methods.count(Sel); } - bool empty() const { return Methods.empty(); } - - private: - llvm::DenseMap Methods; - }; - - /// Method Pool - allows efficient lookup when typechecking messages to "id". - /// We need to maintain a list, since selectors can have differing signatures - /// across classes. In Cocoa, this happens to be extremely uncommon (only 1% - /// of selectors are "overloaded"). - /// At the head of the list it is recorded whether there were 0, 1, or >= 2 - /// methods inside categories with a particular selector. - GlobalMethodPool MethodPool; - - /// Check ODR hashes for C/ObjC when merging types from modules. - /// Differently from C++, actually parse the body and reject in case - /// of a mismatch. - template ::value>> - bool ActOnDuplicateODRHashDefinition(T *Duplicate, T *Previous) { - if (Duplicate->getODRHash() != Previous->getODRHash()) - return false; - - // Make the previous decl visible. - makeMergedDefinitionVisible(Previous); - return true; - } - - typedef llvm::SmallPtrSet SelectorSet; - - enum MethodMatchStrategy { MMS_loose, MMS_strict }; - - enum ObjCContainerKind { - OCK_None = -1, - OCK_Interface = 0, - OCK_Protocol, - OCK_Category, - OCK_ClassExtension, - OCK_Implementation, - OCK_CategoryImplementation - }; - ObjCContainerKind getObjCContainerKind() const; - - DeclResult actOnObjCTypeParam(Scope *S, ObjCTypeParamVariance variance, - SourceLocation varianceLoc, unsigned index, - IdentifierInfo *paramName, - SourceLocation paramLoc, - SourceLocation colonLoc, ParsedType typeBound); - - ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc, - ArrayRef typeParams, - SourceLocation rAngleLoc); - void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList); - - ObjCInterfaceDecl *ActOnStartClassInterface( - Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, - SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, - IdentifierInfo *SuperName, SourceLocation SuperLoc, - ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange, - Decl *const *ProtoRefs, unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, - const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody); - - void ActOnSuperClassOfClassInterface( - Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl, - IdentifierInfo *ClassName, SourceLocation ClassLoc, - IdentifierInfo *SuperName, SourceLocation SuperLoc, - ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange); - - void ActOnTypedefedProtocols(SmallVectorImpl &ProtocolRefs, - SmallVectorImpl &ProtocolLocs, - IdentifierInfo *SuperName, - SourceLocation SuperLoc); - - Decl *ActOnCompatibilityAlias(SourceLocation AtCompatibilityAliasLoc, - IdentifierInfo *AliasName, - SourceLocation AliasLocation, - IdentifierInfo *ClassName, - SourceLocation ClassLocation); - - bool CheckForwardProtocolDeclarationForCircularDependency( - IdentifierInfo *PName, SourceLocation &PLoc, SourceLocation PrevLoc, - const ObjCList &PList); - - ObjCProtocolDecl *ActOnStartProtocolInterface( - SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, - SourceLocation ProtocolLoc, Decl *const *ProtoRefNames, - unsigned NumProtoRefs, const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList, - SkipBodyInfo *SkipBody); - - ObjCCategoryDecl *ActOnStartCategoryInterface( - SourceLocation AtInterfaceLoc, const IdentifierInfo *ClassName, - SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, - const IdentifierInfo *CategoryName, SourceLocation CategoryLoc, - Decl *const *ProtoRefs, unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, - const ParsedAttributesView &AttrList); - - ObjCImplementationDecl *ActOnStartClassImplementation( - SourceLocation AtClassImplLoc, const IdentifierInfo *ClassName, - SourceLocation ClassLoc, const IdentifierInfo *SuperClassname, - SourceLocation SuperClassLoc, const ParsedAttributesView &AttrList); - - ObjCCategoryImplDecl *ActOnStartCategoryImplementation( - SourceLocation AtCatImplLoc, const IdentifierInfo *ClassName, - SourceLocation ClassLoc, const IdentifierInfo *CatName, - SourceLocation CatLoc, const ParsedAttributesView &AttrList); - - DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl, - ArrayRef Decls); - - DeclGroupPtrTy - ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, - ArrayRef IdentList, - const ParsedAttributesView &attrList); - - void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, - ArrayRef ProtocolId, - SmallVectorImpl &Protocols); - - void DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId, - SourceLocation ProtocolLoc, - IdentifierInfo *TypeArgId, - SourceLocation TypeArgLoc, - bool SelectProtocolFirst = false); - - /// Given a list of identifiers (and their locations), resolve the - /// names to either Objective-C protocol qualifiers or type - /// arguments, as appropriate. - void actOnObjCTypeArgsOrProtocolQualifiers( - Scope *S, ParsedType baseType, SourceLocation lAngleLoc, - ArrayRef identifiers, - ArrayRef identifierLocs, SourceLocation rAngleLoc, - SourceLocation &typeArgsLAngleLoc, SmallVectorImpl &typeArgs, - SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc, - SmallVectorImpl &protocols, SourceLocation &protocolRAngleLoc, - bool warnOnIncompleteProtocols); - - void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, - ObjCInterfaceDecl *ID); - - Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd, - ArrayRef allMethods = std::nullopt, - ArrayRef allTUVars = std::nullopt); - - struct ObjCArgInfo { - IdentifierInfo *Name; - SourceLocation NameLoc; - // The Type is null if no type was specified, and the DeclSpec is invalid - // in this case. - ParsedType Type; - ObjCDeclSpec DeclSpec; - - /// ArgAttrs - Attribute list for this argument. - ParsedAttributesView ArgAttrs; - }; - - Decl *ActOnMethodDeclaration( - Scope *S, - SourceLocation BeginLoc, // location of the + or -. - SourceLocation EndLoc, // location of the ; or {. - tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, - ArrayRef SelectorLocs, Selector Sel, - // optional arguments. The number of types/arguments is obtained - // from the Sel.getNumArgs(). - ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, - unsigned CNumArgs, // c-style args - const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodImplKind, - bool isVariadic, bool MethodDefinition); - - bool CheckARCMethodDecl(ObjCMethodDecl *method); - - bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); - - /// Check whether the given new method is a valid override of the - /// given overridden method, and set any properties that should be inherited. - void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, - const ObjCMethodDecl *Overridden); - - /// Describes the compatibility of a result type with its method. - enum ResultTypeCompatibilityKind { - RTC_Compatible, - RTC_Incompatible, - RTC_Unknown - }; - - void CheckObjCMethodDirectOverrides(ObjCMethodDecl *method, - ObjCMethodDecl *overridden); - - void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, - ObjCInterfaceDecl *CurrentClass, - ResultTypeCompatibilityKind RTC); - - /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global - /// pool. - void AddAnyMethodToGlobalPool(Decl *D); - - void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); - bool isObjCMethodDecl(Decl *D) { return D && isa(D); } - - /// CheckImplementationIvars - This routine checks if the instance variables - /// listed in the implelementation match those listed in the interface. - void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, - ObjCIvarDecl **Fields, unsigned nIvars, - SourceLocation Loc); - - void WarnConflictingTypedMethods(ObjCMethodDecl *Method, - ObjCMethodDecl *MethodDecl, - bool IsProtocolMethodDecl); - - void CheckConflictingOverridingMethod(ObjCMethodDecl *Method, - ObjCMethodDecl *Overridden, - bool IsProtocolMethodDecl); - - /// WarnExactTypedMethods - This routine issues a warning if method - /// implementation declaration matches exactly that of its declaration. - void WarnExactTypedMethods(ObjCMethodDecl *Method, ObjCMethodDecl *MethodDecl, - bool IsProtocolMethodDecl); - - /// MatchAllMethodDeclarations - Check methods declaraed in interface or - /// or protocol against those declared in their implementations. - void MatchAllMethodDeclarations( - const SelectorSet &InsMap, const SelectorSet &ClsMap, - SelectorSet &InsMapSeen, SelectorSet &ClsMapSeen, ObjCImplDecl *IMPDecl, - ObjCContainerDecl *IDecl, bool &IncompleteImpl, bool ImmediateClass, - bool WarnCategoryMethodImpl = false); - - /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in - /// category matches with those implemented in its primary class and - /// warns each time an exact match is found. - void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP); - - /// ImplMethodsVsClassMethods - This is main routine to warn if any method - /// remains unimplemented in the class or category \@implementation. - void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl *IMPDecl, - ObjCContainerDecl *IDecl, - bool IncompleteImpl = false); - - DeclGroupPtrTy ActOnForwardClassDeclaration( - SourceLocation Loc, IdentifierInfo **IdentList, SourceLocation *IdentLocs, - ArrayRef TypeParamLists, unsigned NumElts); - - /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns - /// true, or false, accordingly. - bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, - const ObjCMethodDecl *PrevMethod, - MethodMatchStrategy strategy = MMS_strict); - - /// Add the given method to the list of globally-known methods. - void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method); - - void ReadMethodPool(Selector Sel); - void updateOutOfDateSelector(Selector Sel); - - /// - Returns instance or factory methods in global method pool for - /// given selector. It checks the desired kind first, if none is found, and - /// parameter checkTheOther is set, it then checks the other kind. If no such - /// method or only one method is found, function returns false; otherwise, it - /// returns true. - bool - CollectMultipleMethodsInGlobalPool(Selector Sel, - SmallVectorImpl &Methods, - bool InstanceFirst, bool CheckTheOther, - const ObjCObjectType *TypeBound = nullptr); - - bool - AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod, - SourceRange R, bool receiverIdOrClass, - SmallVectorImpl &Methods); - - void - DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl &Methods, - Selector Sel, SourceRange R, - bool receiverIdOrClass); - - const ObjCMethodDecl * - SelectorsForTypoCorrection(Selector Sel, QualType ObjectType = QualType()); - /// LookupImplementedMethodInGlobalPool - Returns the method which has an - /// implementation. - ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel); - - void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID); - - /// Checks that the Objective-C declaration is declared in the global scope. - /// Emits an error and marks the declaration as invalid if it's not declared - /// in the global scope. - bool CheckObjCDeclScope(Decl *D); - - void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, - const IdentifierInfo *ClassName, - SmallVectorImpl &Decls); - - VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, - SourceLocation StartLoc, SourceLocation IdLoc, - const IdentifierInfo *Id, - bool Invalid = false); - - Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D); - - /// CollectIvarsToConstructOrDestruct - Collect those ivars which require - /// initialization. - void - CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, - SmallVectorImpl &Ivars); - - void DiagnoseUseOfUnimplementedSelectors(); - - /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar - /// which backs the property is not used in the property's accessor. - void DiagnoseUnusedBackingIvarInAccessor(Scope *S, - const ObjCImplementationDecl *ImplD); - - /// GetIvarBackingPropertyAccessor - If method is a property setter/getter and - /// it property has a backing ivar, returns this ivar; otherwise, returns - /// NULL. It also returns ivar's property on success. - ObjCIvarDecl * - GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, - const ObjCPropertyDecl *&PDecl) const; - - /// AddInstanceMethodToGlobalPool - All instance methods in a translation - /// unit are added to a global pool. This allows us to efficiently associate - /// a selector with a method declaraation for purposes of typechecking - /// messages sent to "id" (where the class of the object is unknown). - void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, - bool impl = false) { - AddMethodToGlobalPool(Method, impl, /*instance*/ true); - } - - /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods. - void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl = false) { - AddMethodToGlobalPool(Method, impl, /*instance*/ false); - } - -private: - /// AddMethodToGlobalPool - Add an instance or factory method to the global - /// pool. See descriptoin of AddInstanceMethodToGlobalPool. - void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance); - - /// LookupMethodInGlobalPool - Returns the instance or factory method and - /// optionally warns if there are multiple signatures. - ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R, - bool receiverIdOrClass, - bool instance); - - ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - - /// \name ObjC Expressions - /// Implementations are in SemaExprObjC.cpp - ///@{ - -public: - /// Caches identifiers/selectors for NSFoundation APIs. - std::unique_ptr NSAPIObj; - - /// The declaration of the Objective-C NSNumber class. - ObjCInterfaceDecl *NSNumberDecl; - - /// The declaration of the Objective-C NSValue class. - ObjCInterfaceDecl *NSValueDecl; - - /// Pointer to NSNumber type (NSNumber *). - QualType NSNumberPointer; - - /// Pointer to NSValue type (NSValue *). - QualType NSValuePointer; - - /// The Objective-C NSNumber methods used to create NSNumber literals. - ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods]; - - /// The declaration of the Objective-C NSString class. - ObjCInterfaceDecl *NSStringDecl; - - /// Pointer to NSString type (NSString *). - QualType NSStringPointer; - - /// The declaration of the stringWithUTF8String: method. - ObjCMethodDecl *StringWithUTF8StringMethod; - - /// The declaration of the valueWithBytes:objCType: method. - ObjCMethodDecl *ValueWithBytesObjCTypeMethod; - - /// The declaration of the Objective-C NSArray class. - ObjCInterfaceDecl *NSArrayDecl; - - /// The declaration of the arrayWithObjects:count: method. - ObjCMethodDecl *ArrayWithObjectsMethod; - - /// The declaration of the Objective-C NSDictionary class. - ObjCInterfaceDecl *NSDictionaryDecl; - - /// The declaration of the dictionaryWithObjects:forKeys:count: method. - ObjCMethodDecl *DictionaryWithObjectsMethod; - - /// id type. - QualType QIDNSCopying; - - /// will hold 'respondsToSelector:' - Selector RespondsToSelectorSel; - - ExprResult HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, - Expr *BaseExpr, SourceLocation OpLoc, - DeclarationName MemberName, - SourceLocation MemberLoc, - SourceLocation SuperLoc, - QualType SuperType, bool Super); - - ExprResult ActOnClassPropertyRefExpr(const IdentifierInfo &receiverName, - const IdentifierInfo &propertyName, - SourceLocation receiverNameLoc, - SourceLocation propertyNameLoc); - - // ParseObjCStringLiteral - Parse Objective-C string literals. - ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, - ArrayRef Strings); - - ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S); - - /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the - /// numeric literal expression. Type of the expression will be "NSNumber *" - /// or "id" if NSNumber is unavailable. - ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number); - ExprResult ActOnObjCBoolLiteral(SourceLocation AtLoc, SourceLocation ValueLoc, - bool Value); - ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements); - - /// BuildObjCBoxedExpr - builds an ObjCBoxedExpr AST node for the - /// '@' prefixed parenthesized expression. The type of the expression will - /// either be "NSNumber *", "NSString *" or "NSValue *" depending on the type - /// of ValueType, which is allowed to be a built-in numeric type, "char *", - /// "const char *" or C structure with attribute 'objc_boxable'. - ExprResult BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr); - - ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, - Expr *IndexExpr, - ObjCMethodDecl *getterMethod, - ObjCMethodDecl *setterMethod); - - ExprResult - BuildObjCDictionaryLiteral(SourceRange SR, - MutableArrayRef Elements); - - ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc, - TypeSourceInfo *EncodedTypeInfo, - SourceLocation RParenLoc); - - ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc, - SourceLocation EncodeLoc, - SourceLocation LParenLoc, ParsedType Ty, - SourceLocation RParenLoc); - - /// ParseObjCSelectorExpression - Build selector expression for \@selector - ExprResult ParseObjCSelectorExpression(Selector Sel, SourceLocation AtLoc, - SourceLocation SelLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc, - bool WarnMultipleSelectors); - - /// ParseObjCProtocolExpression - Build protocol expression for \@protocol - ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolName, - SourceLocation AtLoc, - SourceLocation ProtoLoc, - SourceLocation LParenLoc, - SourceLocation ProtoIdLoc, - SourceLocation RParenLoc); - - ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc); - - /// Describes the kind of message expression indicated by a message - /// send that starts with an identifier. - enum ObjCMessageKind { - /// The message is sent to 'super'. - ObjCSuperMessage, - /// The message is an instance message. - ObjCInstanceMessage, - /// The message is a class message, and the identifier is a type - /// name. - ObjCClassMessage - }; - - ObjCMessageKind getObjCMessageKind(Scope *S, IdentifierInfo *Name, - SourceLocation NameLoc, bool IsSuper, - bool HasTrailingDot, - ParsedType &ReceiverType); - - ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, Selector Sel, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, MultiExprArg Args); - - ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, - QualType ReceiverType, SourceLocation SuperLoc, - Selector Sel, ObjCMethodDecl *Method, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, MultiExprArg Args, - bool isImplicit = false); - - ExprResult BuildClassMessageImplicit(QualType ReceiverType, - bool isSuperReceiver, SourceLocation Loc, - Selector Sel, ObjCMethodDecl *Method, - MultiExprArg Args); - - ExprResult ActOnClassMessage(Scope *S, ParsedType Receiver, Selector Sel, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, MultiExprArg Args); - - ExprResult BuildInstanceMessage(Expr *Receiver, QualType ReceiverType, - SourceLocation SuperLoc, Selector Sel, - ObjCMethodDecl *Method, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, MultiExprArg Args, - bool isImplicit = false); - - ExprResult BuildInstanceMessageImplicit(Expr *Receiver, QualType ReceiverType, - SourceLocation Loc, Selector Sel, - ObjCMethodDecl *Method, - MultiExprArg Args); - - ExprResult ActOnInstanceMessage(Scope *S, Expr *Receiver, Selector Sel, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, MultiExprArg Args); - - ExprResult BuildObjCBridgedCast(SourceLocation LParenLoc, - ObjCBridgeCastKind Kind, - SourceLocation BridgeKeywordLoc, - TypeSourceInfo *TSInfo, Expr *SubExpr); - - ExprResult ActOnObjCBridgedCast(Scope *S, SourceLocation LParenLoc, - ObjCBridgeCastKind Kind, - SourceLocation BridgeKeywordLoc, - ParsedType Type, SourceLocation RParenLoc, - Expr *SubExpr); - - void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr); - - void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr); - - bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, - CastKind &Kind); - - bool checkObjCBridgeRelatedComponents(SourceLocation Loc, QualType DestType, - QualType SrcType, - ObjCInterfaceDecl *&RelatedClass, - ObjCMethodDecl *&ClassMethod, - ObjCMethodDecl *&InstanceMethod, - TypedefNameDecl *&TDNDecl, bool CfToNs, - bool Diagnose = true); - - bool CheckObjCBridgeRelatedConversions(SourceLocation Loc, QualType DestType, - QualType SrcType, Expr *&SrcExpr, - bool Diagnose = true); - - /// Private Helper predicate to check for 'self'. - bool isSelfExpr(Expr *RExpr); - bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method); - - ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, - const ObjCObjectPointerType *OPT, - bool IsInstance); - ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty, - bool IsInstance); - - bool isKnownName(StringRef name); - - enum ARCConversionResult { ACR_okay, ACR_unbridged, ACR_error }; - - /// Checks for invalid conversions and casts between - /// retainable pointers and other pointer kinds for ARC and Weak. - ARCConversionResult CheckObjCConversion(SourceRange castRange, - QualType castType, Expr *&op, - CheckedConversionKind CCK, - bool Diagnose = true, - bool DiagnoseCFAudited = false, - BinaryOperatorKind Opc = BO_PtrMemD); - - Expr *stripARCUnbridgedCast(Expr *e); - void diagnoseARCUnbridgedCast(Expr *e); - - bool CheckObjCARCUnavailableWeakConversion(QualType castType, - QualType ExprType); - - /// CheckMessageArgumentTypes - Check types in an Obj-C message send. - /// \param Method - May be null. - /// \param [out] ReturnType - The return type of the send. - /// \return true iff there were any incompatible types. - bool CheckMessageArgumentTypes(const Expr *Receiver, QualType ReceiverType, - MultiExprArg Args, Selector Sel, - ArrayRef SelectorLocs, - ObjCMethodDecl *Method, bool isClassMessage, - bool isSuperMessage, SourceLocation lbrac, - SourceLocation rbrac, SourceRange RecRange, - QualType &ReturnType, ExprValueKind &VK); - - /// Determine the result of a message send expression based on - /// the type of the receiver, the method expected to receive the message, - /// and the form of the message send. - QualType getMessageSendResultType(const Expr *Receiver, QualType ReceiverType, - ObjCMethodDecl *Method, bool isClassMessage, - bool isSuperMessage); - - /// If the given expression involves a message send to a method - /// with a related result type, emit a note describing what happened. - void EmitRelatedResultTypeNote(const Expr *E); - - /// Given that we had incompatible pointer types in a return - /// statement, check whether we're in a method with a related result - /// type, and if so, emit a note describing what happened. - void EmitRelatedResultTypeNoteForReturn(QualType destType); - - /// LookupInstanceMethodInGlobalPool - Returns the method and warns if - /// there are multiple signatures. - ObjCMethodDecl * - LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R, - bool receiverIdOrClass = false) { - return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, - /*instance*/ true); - } - - /// LookupFactoryMethodInGlobalPool - Returns the method and warns if - /// there are multiple signatures. - ObjCMethodDecl * - LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R, - bool receiverIdOrClass = false) { - return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, - /*instance*/ false); - } - - ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - - /// \name ObjC @property and @synthesize - /// Implementations are in SemaObjCProperty.cpp - ///@{ - -public: - /// Ensure attributes are consistent with type. - /// \param [in, out] Attributes The attributes to check; they will - /// be modified to be consistent with \p PropertyTy. - void CheckObjCPropertyAttributes(Decl *PropertyPtrTy, SourceLocation Loc, - unsigned &Attributes, - bool propertyInPrimaryClass); - - /// Process the specified property declaration and create decls for the - /// setters and getters as needed. - /// \param property The property declaration being processed - void ProcessPropertyDecl(ObjCPropertyDecl *property); - - Decl *ActOnProperty(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, - FieldDeclarator &FD, ObjCDeclSpec &ODS, - Selector GetterSel, Selector SetterSel, - tok::ObjCKeywordKind MethodImplKind, - DeclContext *lexicalDC = nullptr); - - Decl *ActOnPropertyImplDecl(Scope *S, SourceLocation AtLoc, - SourceLocation PropertyLoc, bool ImplKind, - IdentifierInfo *PropertyId, - IdentifierInfo *PropertyIvar, - SourceLocation PropertyIvarLoc, - ObjCPropertyQueryKind QueryKind); - - /// Called by ActOnProperty to handle \@property declarations in - /// class extensions. - ObjCPropertyDecl *HandlePropertyInClassExtension( - Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, - FieldDeclarator &FD, Selector GetterSel, SourceLocation GetterNameLoc, - Selector SetterSel, SourceLocation SetterNameLoc, const bool isReadWrite, - unsigned &Attributes, const unsigned AttributesAsWritten, QualType T, - TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind); - - /// Called by ActOnProperty and HandlePropertyInClassExtension to - /// handle creating the ObjcPropertyDecl for a category or \@interface. - ObjCPropertyDecl * - CreatePropertyDecl(Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc, - SourceLocation LParenLoc, FieldDeclarator &FD, - Selector GetterSel, SourceLocation GetterNameLoc, - Selector SetterSel, SourceLocation SetterNameLoc, - const bool isReadWrite, const unsigned Attributes, - const unsigned AttributesAsWritten, QualType T, - TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind, - DeclContext *lexicalDC = nullptr); - - void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, - ObjCPropertyDecl *SuperProperty, - const IdentifierInfo *Name, - bool OverridingProtocolProperty); - - bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, - ObjCMethodDecl *Getter, - SourceLocation Loc); - - /// DiagnoseUnimplementedProperties - This routine warns on those properties - /// which must be implemented by this implementation. - void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl *IMPDecl, - ObjCContainerDecl *CDecl, - bool SynthesizeProperties); - - /// Diagnose any null-resettable synthesized setters. - void diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl); - - /// DefaultSynthesizeProperties - This routine default synthesizes all - /// properties which must be synthesized in the class's \@implementation. - void DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl, - ObjCInterfaceDecl *IDecl, - SourceLocation AtEnd); - void DefaultSynthesizeProperties(Scope *S, Decl *D, SourceLocation AtEnd); - - /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is - /// an ivar synthesized for 'Method' and 'Method' is a property accessor - /// declared in class 'IFace'. - bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, - ObjCMethodDecl *Method, ObjCIvarDecl *IV); - - void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D); - - void - DiagnoseMissingDesignatedInitOverrides(const ObjCImplementationDecl *ImplD, - const ObjCInterfaceDecl *IFD); - - /// AtomicPropertySetterGetterRules - This routine enforces the rule (via - /// warning) when atomic property has one but not the other user-declared - /// setter or getter. - void AtomicPropertySetterGetterRules(ObjCImplDecl *IMPDecl, - ObjCInterfaceDecl *IDecl); - ///@} // diff --git a/clang/include/clang/Sema/SemaObjC.h b/clang/include/clang/Sema/SemaObjC.h new file mode 100644 index 000000000000..a9a0d1678095 --- /dev/null +++ b/clang/include/clang/Sema/SemaObjC.h @@ -0,0 +1,1014 @@ +//===----- SemaObjC.h ------ Semantic Analysis for Objective-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 for Objective-C. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMAOBJC_H +#define LLVM_CLANG_SEMA_SEMAOBJC_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/NSAPI.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/Type.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ObjCMethodList.h" +#include "clang/Sema/Ownership.h" +#include "clang/Sema/ParsedAttr.h" +#include "clang/Sema/Redeclaration.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/SemaBase.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +#include +#include +#include + +namespace clang { + +enum class CheckedConversionKind; +struct SkipBodyInfo; + +class SemaObjC : public SemaBase { +public: + SemaObjC(Sema &S); + + ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc, + Expr *collection); + StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, Stmt *First, + Expr *collection, + SourceLocation RParenLoc); + /// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach + /// statement. + StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body); + + StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, + Decl *Parm, Stmt *Body); + + StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body); + + StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, + MultiStmtArg Catch, Stmt *Finally); + + StmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw); + StmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, + Scope *CurScope); + ExprResult ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, + Expr *operand); + StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SynchExpr, + Stmt *SynchBody); + + StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body); + + /// Build a an Objective-C protocol-qualified 'id' type where no + /// base type was specified. + TypeResult actOnObjCProtocolQualifierType( + SourceLocation lAngleLoc, ArrayRef protocols, + ArrayRef protocolLocs, SourceLocation rAngleLoc); + + /// Build a specialized and/or protocol-qualified Objective-C type. + TypeResult actOnObjCTypeArgsAndProtocolQualifiers( + Scope *S, SourceLocation Loc, ParsedType BaseType, + SourceLocation TypeArgsLAngleLoc, ArrayRef TypeArgs, + SourceLocation TypeArgsRAngleLoc, SourceLocation ProtocolLAngleLoc, + ArrayRef Protocols, ArrayRef ProtocolLocs, + SourceLocation ProtocolRAngleLoc); + + /// Build an Objective-C type parameter type. + QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, + SourceLocation ProtocolLAngleLoc, + ArrayRef Protocols, + ArrayRef ProtocolLocs, + SourceLocation ProtocolRAngleLoc, + bool FailOnError = false); + + /// Build an Objective-C object pointer type. + QualType BuildObjCObjectType( + QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc, + ArrayRef TypeArgs, SourceLocation TypeArgsRAngleLoc, + SourceLocation ProtocolLAngleLoc, ArrayRef Protocols, + ArrayRef ProtocolLocs, SourceLocation ProtocolRAngleLoc, + bool FailOnError, bool Rebuilding); + + /// The parser has parsed the context-sensitive type 'instancetype' + /// in an Objective-C message declaration. Return the appropriate type. + ParsedType ActOnObjCInstanceType(SourceLocation Loc); + + /// checkRetainCycles - Check whether an Objective-C message send + /// might create an obvious retain cycle. + void checkRetainCycles(ObjCMessageExpr *msg); + void checkRetainCycles(Expr *receiver, Expr *argument); + void checkRetainCycles(VarDecl *Var, Expr *Init); + + bool CheckObjCString(Expr *Arg); + bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc, + ArrayRef Args); + /// Check whether receiver is mutable ObjC container which + /// attempts to add itself into the container + void CheckObjCCircularContainer(ObjCMessageExpr *Message); + + void ActOnObjCContainerStartDefinition(ObjCContainerDecl *IDecl); + void ActOnObjCContainerFinishDefinition(); + + /// Invoked when we must temporarily exit the objective-c container + /// scope for parsing/looking-up C constructs. + /// + /// Must be followed by a call to \see ActOnObjCReenterContainerContext + void ActOnObjCTemporaryExitContainerContext(ObjCContainerDecl *ObjCCtx); + void ActOnObjCReenterContainerContext(ObjCContainerDecl *ObjCCtx); + + const DeclContext *getCurObjCLexicalContext() const; + + ObjCProtocolDecl *LookupProtocol( + IdentifierInfo *II, SourceLocation IdLoc, + RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration); + + bool isObjCWritebackConversion(QualType FromType, QualType ToType, + QualType &ConvertedType); + + enum ObjCSubscriptKind { OS_Array, OS_Dictionary, OS_Error }; + ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE); + + /// AddCFAuditedAttribute - Check whether we're currently within + /// '\#pragma clang arc_cf_code_audited' and, if so, consider adding + /// the appropriate attribute. + void AddCFAuditedAttribute(Decl *D); + + /// The struct behind the CFErrorRef pointer. + RecordDecl *CFError = nullptr; + bool isCFError(RecordDecl *D); + + IdentifierInfo *getNSErrorIdent(); + +private: + IdentifierInfo *Ident_NSError = nullptr; + + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name ObjC Declarations + /// Implementations are in SemaDeclObjC.cpp + ///@{ + +public: + enum ObjCSpecialMethodKind { + OSMK_None, + OSMK_Alloc, + OSMK_New, + OSMK_Copy, + OSMK_RetainingInit, + OSMK_NonRetainingInit + }; + + /// Method selectors used in a \@selector expression. Used for implementation + /// of -Wselector. + llvm::MapVector ReferencedSelectors; + + class GlobalMethodPool { + public: + using Lists = std::pair; + using iterator = llvm::DenseMap::iterator; + iterator begin() { return Methods.begin(); } + iterator end() { return Methods.end(); } + iterator find(Selector Sel) { return Methods.find(Sel); } + std::pair insert(std::pair &&Val) { + return Methods.insert(Val); + } + int count(Selector Sel) const { return Methods.count(Sel); } + bool empty() const { return Methods.empty(); } + + private: + llvm::DenseMap Methods; + }; + + /// Method Pool - allows efficient lookup when typechecking messages to "id". + /// We need to maintain a list, since selectors can have differing signatures + /// across classes. In Cocoa, this happens to be extremely uncommon (only 1% + /// of selectors are "overloaded"). + /// At the head of the list it is recorded whether there were 0, 1, or >= 2 + /// methods inside categories with a particular selector. + GlobalMethodPool MethodPool; + + typedef llvm::SmallPtrSet SelectorSet; + + enum MethodMatchStrategy { MMS_loose, MMS_strict }; + + enum ObjCContainerKind { + OCK_None = -1, + OCK_Interface = 0, + OCK_Protocol, + OCK_Category, + OCK_ClassExtension, + OCK_Implementation, + OCK_CategoryImplementation + }; + ObjCContainerKind getObjCContainerKind() const; + + DeclResult actOnObjCTypeParam(Scope *S, ObjCTypeParamVariance variance, + SourceLocation varianceLoc, unsigned index, + IdentifierInfo *paramName, + SourceLocation paramLoc, + SourceLocation colonLoc, ParsedType typeBound); + + ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc, + ArrayRef typeParams, + SourceLocation rAngleLoc); + void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList); + + ObjCInterfaceDecl *ActOnStartClassInterface( + Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody); + + void ActOnSuperClassOfClassInterface( + Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange); + + void ActOnTypedefedProtocols(SmallVectorImpl &ProtocolRefs, + SmallVectorImpl &ProtocolLocs, + IdentifierInfo *SuperName, + SourceLocation SuperLoc); + + Decl *ActOnCompatibilityAlias(SourceLocation AtCompatibilityAliasLoc, + IdentifierInfo *AliasName, + SourceLocation AliasLocation, + IdentifierInfo *ClassName, + SourceLocation ClassLocation); + + bool CheckForwardProtocolDeclarationForCircularDependency( + IdentifierInfo *PName, SourceLocation &PLoc, SourceLocation PrevLoc, + const ObjCList &PList); + + ObjCProtocolDecl *ActOnStartProtocolInterface( + SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, Decl *const *ProtoRefNames, + unsigned NumProtoRefs, const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList, + SkipBodyInfo *SkipBody); + + ObjCCategoryDecl *ActOnStartCategoryInterface( + SourceLocation AtInterfaceLoc, const IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + const IdentifierInfo *CategoryName, SourceLocation CategoryLoc, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList); + + ObjCImplementationDecl *ActOnStartClassImplementation( + SourceLocation AtClassImplLoc, const IdentifierInfo *ClassName, + SourceLocation ClassLoc, const IdentifierInfo *SuperClassname, + SourceLocation SuperClassLoc, const ParsedAttributesView &AttrList); + + ObjCCategoryImplDecl *ActOnStartCategoryImplementation( + SourceLocation AtCatImplLoc, const IdentifierInfo *ClassName, + SourceLocation ClassLoc, const IdentifierInfo *CatName, + SourceLocation CatLoc, const ParsedAttributesView &AttrList); + + using DeclGroupPtrTy = OpaquePtr; + + DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl, + ArrayRef Decls); + + DeclGroupPtrTy + ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, + ArrayRef IdentList, + const ParsedAttributesView &attrList); + + void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, + ArrayRef ProtocolId, + SmallVectorImpl &Protocols); + + void DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId, + SourceLocation ProtocolLoc, + IdentifierInfo *TypeArgId, + SourceLocation TypeArgLoc, + bool SelectProtocolFirst = false); + + /// Given a list of identifiers (and their locations), resolve the + /// names to either Objective-C protocol qualifiers or type + /// arguments, as appropriate. + void actOnObjCTypeArgsOrProtocolQualifiers( + Scope *S, ParsedType baseType, SourceLocation lAngleLoc, + ArrayRef identifiers, + ArrayRef identifierLocs, SourceLocation rAngleLoc, + SourceLocation &typeArgsLAngleLoc, SmallVectorImpl &typeArgs, + SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc, + SmallVectorImpl &protocols, SourceLocation &protocolRAngleLoc, + bool warnOnIncompleteProtocols); + + void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, + ObjCInterfaceDecl *ID); + + Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd, + ArrayRef allMethods = std::nullopt, + ArrayRef allTUVars = std::nullopt); + + struct ObjCArgInfo { + IdentifierInfo *Name; + SourceLocation NameLoc; + // The Type is null if no type was specified, and the DeclSpec is invalid + // in this case. + ParsedType Type; + ObjCDeclSpec DeclSpec; + + /// ArgAttrs - Attribute list for this argument. + ParsedAttributesView ArgAttrs; + }; + + Decl *ActOnMethodDeclaration( + Scope *S, + SourceLocation BeginLoc, // location of the + or -. + SourceLocation EndLoc, // location of the ; or {. + tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + ArrayRef SelectorLocs, Selector Sel, + // optional arguments. The number of types/arguments is obtained + // from the Sel.getNumArgs(). + ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, + unsigned CNumArgs, // c-style args + const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodImplKind, + bool isVariadic, bool MethodDefinition); + + bool CheckARCMethodDecl(ObjCMethodDecl *method); + + bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); + + /// Check whether the given new method is a valid override of the + /// given overridden method, and set any properties that should be inherited. + void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, + const ObjCMethodDecl *Overridden); + + /// Describes the compatibility of a result type with its method. + enum ResultTypeCompatibilityKind { + RTC_Compatible, + RTC_Incompatible, + RTC_Unknown + }; + + void CheckObjCMethodDirectOverrides(ObjCMethodDecl *method, + ObjCMethodDecl *overridden); + + void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, + ObjCInterfaceDecl *CurrentClass, + ResultTypeCompatibilityKind RTC); + + /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global + /// pool. + void AddAnyMethodToGlobalPool(Decl *D); + + void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); + bool isObjCMethodDecl(Decl *D) { return D && isa(D); } + + /// CheckImplementationIvars - This routine checks if the instance variables + /// listed in the implelementation match those listed in the interface. + void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, + ObjCIvarDecl **Fields, unsigned nIvars, + SourceLocation Loc); + + void WarnConflictingTypedMethods(ObjCMethodDecl *Method, + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl); + + void CheckConflictingOverridingMethod(ObjCMethodDecl *Method, + ObjCMethodDecl *Overridden, + bool IsProtocolMethodDecl); + + /// WarnExactTypedMethods - This routine issues a warning if method + /// implementation declaration matches exactly that of its declaration. + void WarnExactTypedMethods(ObjCMethodDecl *Method, ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl); + + /// MatchAllMethodDeclarations - Check methods declaraed in interface or + /// or protocol against those declared in their implementations. + void MatchAllMethodDeclarations( + const SelectorSet &InsMap, const SelectorSet &ClsMap, + SelectorSet &InsMapSeen, SelectorSet &ClsMapSeen, ObjCImplDecl *IMPDecl, + ObjCContainerDecl *IDecl, bool &IncompleteImpl, bool ImmediateClass, + bool WarnCategoryMethodImpl = false); + + /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in + /// category matches with those implemented in its primary class and + /// warns each time an exact match is found. + void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP); + + /// ImplMethodsVsClassMethods - This is main routine to warn if any method + /// remains unimplemented in the class or category \@implementation. + void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl *IMPDecl, + ObjCContainerDecl *IDecl, + bool IncompleteImpl = false); + + DeclGroupPtrTy ActOnForwardClassDeclaration( + SourceLocation Loc, IdentifierInfo **IdentList, SourceLocation *IdentLocs, + ArrayRef TypeParamLists, unsigned NumElts); + + /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns + /// true, or false, accordingly. + bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, + const ObjCMethodDecl *PrevMethod, + MethodMatchStrategy strategy = MMS_strict); + + /// Add the given method to the list of globally-known methods. + void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method); + + void ReadMethodPool(Selector Sel); + void updateOutOfDateSelector(Selector Sel); + + /// - Returns instance or factory methods in global method pool for + /// given selector. It checks the desired kind first, if none is found, and + /// parameter checkTheOther is set, it then checks the other kind. If no such + /// method or only one method is found, function returns false; otherwise, it + /// returns true. + bool + CollectMultipleMethodsInGlobalPool(Selector Sel, + SmallVectorImpl &Methods, + bool InstanceFirst, bool CheckTheOther, + const ObjCObjectType *TypeBound = nullptr); + + bool + AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod, + SourceRange R, bool receiverIdOrClass, + SmallVectorImpl &Methods); + + void + DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl &Methods, + Selector Sel, SourceRange R, + bool receiverIdOrClass); + + const ObjCMethodDecl * + SelectorsForTypoCorrection(Selector Sel, QualType ObjectType = QualType()); + /// LookupImplementedMethodInGlobalPool - Returns the method which has an + /// implementation. + ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel); + + void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID); + + /// Checks that the Objective-C declaration is declared in the global scope. + /// Emits an error and marks the declaration as invalid if it's not declared + /// in the global scope. + bool CheckObjCDeclScope(Decl *D); + + void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, + const IdentifierInfo *ClassName, + SmallVectorImpl &Decls); + + VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, + SourceLocation StartLoc, SourceLocation IdLoc, + const IdentifierInfo *Id, + bool Invalid = false); + + Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D); + + /// CollectIvarsToConstructOrDestruct - Collect those ivars which require + /// initialization. + void + CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, + SmallVectorImpl &Ivars); + + void DiagnoseUseOfUnimplementedSelectors(); + + /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar + /// which backs the property is not used in the property's accessor. + void DiagnoseUnusedBackingIvarInAccessor(Scope *S, + const ObjCImplementationDecl *ImplD); + + /// GetIvarBackingPropertyAccessor - If method is a property setter/getter and + /// it property has a backing ivar, returns this ivar; otherwise, returns + /// NULL. It also returns ivar's property on success. + ObjCIvarDecl * + GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, + const ObjCPropertyDecl *&PDecl) const; + + /// AddInstanceMethodToGlobalPool - All instance methods in a translation + /// unit are added to a global pool. This allows us to efficiently associate + /// a selector with a method declaraation for purposes of typechecking + /// messages sent to "id" (where the class of the object is unknown). + void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, + bool impl = false) { + AddMethodToGlobalPool(Method, impl, /*instance*/ true); + } + + /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods. + void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl = false) { + AddMethodToGlobalPool(Method, impl, /*instance*/ false); + } + + QualType AdjustParameterTypeForObjCAutoRefCount(QualType T, + SourceLocation NameLoc, + TypeSourceInfo *TSInfo); + + /// Look for an Objective-C class in the translation unit. + /// + /// \param Id The name of the Objective-C class we're looking for. If + /// typo-correction fixes this name, the Id will be updated + /// to the fixed name. + /// + /// \param IdLoc The location of the name in the translation unit. + /// + /// \param DoTypoCorrection If true, this routine will attempt typo correction + /// if there is no class with the given name. + /// + /// \returns The declaration of the named Objective-C class, or NULL if the + /// class could not be found. + ObjCInterfaceDecl *getObjCInterfaceDecl(const IdentifierInfo *&Id, + SourceLocation IdLoc, + bool TypoCorrection = false); + + bool inferObjCARCLifetime(ValueDecl *decl); + + /// SetIvarInitializers - This routine builds initialization ASTs for the + /// Objective-C implementation whose ivars need be initialized. + void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation); + + Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, + Expr *BitWidth, tok::ObjCKeywordKind visibility); + + ObjCContainerDecl *getObjCDeclContext() const; + +private: + /// AddMethodToGlobalPool - Add an instance or factory method to the global + /// pool. See descriptoin of AddInstanceMethodToGlobalPool. + void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance); + + /// LookupMethodInGlobalPool - Returns the instance or factory method and + /// optionally warns if there are multiple signatures. + ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass, + bool instance); + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name ObjC Expressions + /// Implementations are in SemaExprObjC.cpp + ///@{ + +public: + /// Caches identifiers/selectors for NSFoundation APIs. + std::unique_ptr NSAPIObj; + + /// The declaration of the Objective-C NSNumber class. + ObjCInterfaceDecl *NSNumberDecl; + + /// The declaration of the Objective-C NSValue class. + ObjCInterfaceDecl *NSValueDecl; + + /// Pointer to NSNumber type (NSNumber *). + QualType NSNumberPointer; + + /// Pointer to NSValue type (NSValue *). + QualType NSValuePointer; + + /// The Objective-C NSNumber methods used to create NSNumber literals. + ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods]; + + /// The declaration of the Objective-C NSString class. + ObjCInterfaceDecl *NSStringDecl; + + /// Pointer to NSString type (NSString *). + QualType NSStringPointer; + + /// The declaration of the stringWithUTF8String: method. + ObjCMethodDecl *StringWithUTF8StringMethod; + + /// The declaration of the valueWithBytes:objCType: method. + ObjCMethodDecl *ValueWithBytesObjCTypeMethod; + + /// The declaration of the Objective-C NSArray class. + ObjCInterfaceDecl *NSArrayDecl; + + /// The declaration of the arrayWithObjects:count: method. + ObjCMethodDecl *ArrayWithObjectsMethod; + + /// The declaration of the Objective-C NSDictionary class. + ObjCInterfaceDecl *NSDictionaryDecl; + + /// The declaration of the dictionaryWithObjects:forKeys:count: method. + ObjCMethodDecl *DictionaryWithObjectsMethod; + + /// id type. + QualType QIDNSCopying; + + /// will hold 'respondsToSelector:' + Selector RespondsToSelectorSel; + + ExprResult HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, + Expr *BaseExpr, SourceLocation OpLoc, + DeclarationName MemberName, + SourceLocation MemberLoc, + SourceLocation SuperLoc, + QualType SuperType, bool Super); + + ExprResult ActOnClassPropertyRefExpr(const IdentifierInfo &receiverName, + const IdentifierInfo &propertyName, + SourceLocation receiverNameLoc, + SourceLocation propertyNameLoc); + + // ParseObjCStringLiteral - Parse Objective-C string literals. + ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, + ArrayRef Strings); + + ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S); + + /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the + /// numeric literal expression. Type of the expression will be "NSNumber *" + /// or "id" if NSNumber is unavailable. + ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number); + ExprResult ActOnObjCBoolLiteral(SourceLocation AtLoc, SourceLocation ValueLoc, + bool Value); + ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements); + + /// BuildObjCBoxedExpr - builds an ObjCBoxedExpr AST node for the + /// '@' prefixed parenthesized expression. The type of the expression will + /// either be "NSNumber *", "NSString *" or "NSValue *" depending on the type + /// of ValueType, which is allowed to be a built-in numeric type, "char *", + /// "const char *" or C structure with attribute 'objc_boxable'. + ExprResult BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr); + + ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, + Expr *IndexExpr, + ObjCMethodDecl *getterMethod, + ObjCMethodDecl *setterMethod); + + ExprResult + BuildObjCDictionaryLiteral(SourceRange SR, + MutableArrayRef Elements); + + ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc, + TypeSourceInfo *EncodedTypeInfo, + SourceLocation RParenLoc); + + ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc, + SourceLocation EncodeLoc, + SourceLocation LParenLoc, ParsedType Ty, + SourceLocation RParenLoc); + + /// ParseObjCSelectorExpression - Build selector expression for \@selector + ExprResult ParseObjCSelectorExpression(Selector Sel, SourceLocation AtLoc, + SourceLocation SelLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc, + bool WarnMultipleSelectors); + + /// ParseObjCProtocolExpression - Build protocol expression for \@protocol + ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolName, + SourceLocation AtLoc, + SourceLocation ProtoLoc, + SourceLocation LParenLoc, + SourceLocation ProtoIdLoc, + SourceLocation RParenLoc); + + ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc); + + /// Describes the kind of message expression indicated by a message + /// send that starts with an identifier. + enum ObjCMessageKind { + /// The message is sent to 'super'. + ObjCSuperMessage, + /// The message is an instance message. + ObjCInstanceMessage, + /// The message is a class message, and the identifier is a type + /// name. + ObjCClassMessage + }; + + ObjCMessageKind getObjCMessageKind(Scope *S, IdentifierInfo *Name, + SourceLocation NameLoc, bool IsSuper, + bool HasTrailingDot, + ParsedType &ReceiverType); + + ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, Selector Sel, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, MultiExprArg Args); + + ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, + QualType ReceiverType, SourceLocation SuperLoc, + Selector Sel, ObjCMethodDecl *Method, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, MultiExprArg Args, + bool isImplicit = false); + + ExprResult BuildClassMessageImplicit(QualType ReceiverType, + bool isSuperReceiver, SourceLocation Loc, + Selector Sel, ObjCMethodDecl *Method, + MultiExprArg Args); + + ExprResult ActOnClassMessage(Scope *S, ParsedType Receiver, Selector Sel, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, MultiExprArg Args); + + ExprResult BuildInstanceMessage(Expr *Receiver, QualType ReceiverType, + SourceLocation SuperLoc, Selector Sel, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, MultiExprArg Args, + bool isImplicit = false); + + ExprResult BuildInstanceMessageImplicit(Expr *Receiver, QualType ReceiverType, + SourceLocation Loc, Selector Sel, + ObjCMethodDecl *Method, + MultiExprArg Args); + + ExprResult ActOnInstanceMessage(Scope *S, Expr *Receiver, Selector Sel, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, MultiExprArg Args); + + ExprResult BuildObjCBridgedCast(SourceLocation LParenLoc, + ObjCBridgeCastKind Kind, + SourceLocation BridgeKeywordLoc, + TypeSourceInfo *TSInfo, Expr *SubExpr); + + ExprResult ActOnObjCBridgedCast(Scope *S, SourceLocation LParenLoc, + ObjCBridgeCastKind Kind, + SourceLocation BridgeKeywordLoc, + ParsedType Type, SourceLocation RParenLoc, + Expr *SubExpr); + + void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr); + + void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr); + + bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, + CastKind &Kind); + + bool checkObjCBridgeRelatedComponents(SourceLocation Loc, QualType DestType, + QualType SrcType, + ObjCInterfaceDecl *&RelatedClass, + ObjCMethodDecl *&ClassMethod, + ObjCMethodDecl *&InstanceMethod, + TypedefNameDecl *&TDNDecl, bool CfToNs, + bool Diagnose = true); + + bool CheckObjCBridgeRelatedConversions(SourceLocation Loc, QualType DestType, + QualType SrcType, Expr *&SrcExpr, + bool Diagnose = true); + + /// Private Helper predicate to check for 'self'. + bool isSelfExpr(Expr *RExpr); + bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method); + + ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, + const ObjCObjectPointerType *OPT, + bool IsInstance); + ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty, + bool IsInstance); + + bool isKnownName(StringRef name); + + enum ARCConversionResult { ACR_okay, ACR_unbridged, ACR_error }; + + /// Checks for invalid conversions and casts between + /// retainable pointers and other pointer kinds for ARC and Weak. + ARCConversionResult CheckObjCConversion(SourceRange castRange, + QualType castType, Expr *&op, + CheckedConversionKind CCK, + bool Diagnose = true, + bool DiagnoseCFAudited = false, + BinaryOperatorKind Opc = BO_PtrMemD); + + Expr *stripARCUnbridgedCast(Expr *e); + void diagnoseARCUnbridgedCast(Expr *e); + + bool CheckObjCARCUnavailableWeakConversion(QualType castType, + QualType ExprType); + + /// CheckMessageArgumentTypes - Check types in an Obj-C message send. + /// \param Method - May be null. + /// \param [out] ReturnType - The return type of the send. + /// \return true iff there were any incompatible types. + bool CheckMessageArgumentTypes(const Expr *Receiver, QualType ReceiverType, + MultiExprArg Args, Selector Sel, + ArrayRef SelectorLocs, + ObjCMethodDecl *Method, bool isClassMessage, + bool isSuperMessage, SourceLocation lbrac, + SourceLocation rbrac, SourceRange RecRange, + QualType &ReturnType, ExprValueKind &VK); + + /// Determine the result of a message send expression based on + /// the type of the receiver, the method expected to receive the message, + /// and the form of the message send. + QualType getMessageSendResultType(const Expr *Receiver, QualType ReceiverType, + ObjCMethodDecl *Method, bool isClassMessage, + bool isSuperMessage); + + /// If the given expression involves a message send to a method + /// with a related result type, emit a note describing what happened. + void EmitRelatedResultTypeNote(const Expr *E); + + /// Given that we had incompatible pointer types in a return + /// statement, check whether we're in a method with a related result + /// type, and if so, emit a note describing what happened. + void EmitRelatedResultTypeNoteForReturn(QualType destType); + + /// LookupInstanceMethodInGlobalPool - Returns the method and warns if + /// there are multiple signatures. + ObjCMethodDecl * + LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass = false) { + return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, + /*instance*/ true); + } + + /// LookupFactoryMethodInGlobalPool - Returns the method and warns if + /// there are multiple signatures. + ObjCMethodDecl * + LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass = false) { + return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, + /*instance*/ false); + } + + /// The parser has read a name in, and Sema has detected that we're currently + /// inside an ObjC method. Perform some additional checks and determine if we + /// should form a reference to an ivar. + /// + /// Ideally, most of this would be done by lookup, but there's + /// actually quite a lot of extra work involved. + DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S, + IdentifierInfo *II); + + /// The parser has read a name in, and Sema has detected that we're currently + /// inside an ObjC method. Perform some additional checks and determine if we + /// should form a reference to an ivar. If so, build an expression referencing + /// that ivar. + ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S, + IdentifierInfo *II, + bool AllowBuiltinCreation = false); + + ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV); + + /// FindCompositeObjCPointerType - Helper method to find composite type of + /// two objective-c pointer types of the two input expressions. + QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, + SourceLocation QuestionLoc); + + bool CheckConversionToObjCLiteral(QualType DstType, Expr *&SrcExpr, + bool Diagnose = true); + + /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. + ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); + + ExprResult + ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef AvailSpecs, + SourceLocation AtLoc, SourceLocation RParen); + + /// Prepare a conversion of the given expression to an ObjC object + /// pointer type. + CastKind PrepareCastToObjCObjectPointer(ExprResult &E); + + // Note that LK_String is intentionally after the other literals, as + // this is used for diagnostics logic. + enum ObjCLiteralKind { + LK_Array, + LK_Dictionary, + LK_Numeric, + LK_Boxed, + LK_String, + LK_Block, + LK_None + }; + ObjCLiteralKind CheckLiteralKind(Expr *FromE); + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name ObjC @property and @synthesize + /// Implementations are in SemaObjCProperty.cpp + ///@{ + +public: + /// Ensure attributes are consistent with type. + /// \param [in, out] Attributes The attributes to check; they will + /// be modified to be consistent with \p PropertyTy. + void CheckObjCPropertyAttributes(Decl *PropertyPtrTy, SourceLocation Loc, + unsigned &Attributes, + bool propertyInPrimaryClass); + + /// Process the specified property declaration and create decls for the + /// setters and getters as needed. + /// \param property The property declaration being processed + void ProcessPropertyDecl(ObjCPropertyDecl *property); + + Decl *ActOnProperty(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, + FieldDeclarator &FD, ObjCDeclSpec &ODS, + Selector GetterSel, Selector SetterSel, + tok::ObjCKeywordKind MethodImplKind, + DeclContext *lexicalDC = nullptr); + + Decl *ActOnPropertyImplDecl(Scope *S, SourceLocation AtLoc, + SourceLocation PropertyLoc, bool ImplKind, + IdentifierInfo *PropertyId, + IdentifierInfo *PropertyIvar, + SourceLocation PropertyIvarLoc, + ObjCPropertyQueryKind QueryKind); + + /// Called by ActOnProperty to handle \@property declarations in + /// class extensions. + ObjCPropertyDecl *HandlePropertyInClassExtension( + Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, + FieldDeclarator &FD, Selector GetterSel, SourceLocation GetterNameLoc, + Selector SetterSel, SourceLocation SetterNameLoc, const bool isReadWrite, + unsigned &Attributes, const unsigned AttributesAsWritten, QualType T, + TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind); + + /// Called by ActOnProperty and HandlePropertyInClassExtension to + /// handle creating the ObjcPropertyDecl for a category or \@interface. + ObjCPropertyDecl * + CreatePropertyDecl(Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc, + SourceLocation LParenLoc, FieldDeclarator &FD, + Selector GetterSel, SourceLocation GetterNameLoc, + Selector SetterSel, SourceLocation SetterNameLoc, + const bool isReadWrite, const unsigned Attributes, + const unsigned AttributesAsWritten, QualType T, + TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind, + DeclContext *lexicalDC = nullptr); + + void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, + ObjCPropertyDecl *SuperProperty, + const IdentifierInfo *Name, + bool OverridingProtocolProperty); + + bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, + ObjCMethodDecl *Getter, + SourceLocation Loc); + + /// DiagnoseUnimplementedProperties - This routine warns on those properties + /// which must be implemented by this implementation. + void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl *IMPDecl, + ObjCContainerDecl *CDecl, + bool SynthesizeProperties); + + /// Diagnose any null-resettable synthesized setters. + void diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl); + + /// DefaultSynthesizeProperties - This routine default synthesizes all + /// properties which must be synthesized in the class's \@implementation. + void DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl, + ObjCInterfaceDecl *IDecl, + SourceLocation AtEnd); + void DefaultSynthesizeProperties(Scope *S, Decl *D, SourceLocation AtEnd); + + /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is + /// an ivar synthesized for 'Method' and 'Method' is a property accessor + /// declared in class 'IFace'. + bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, + ObjCMethodDecl *Method, ObjCIvarDecl *IV); + + void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D); + + void + DiagnoseMissingDesignatedInitOverrides(const ObjCImplementationDecl *ImplD, + const ObjCInterfaceDecl *IFD); + + /// AtomicPropertySetterGetterRules - This routine enforces the rule (via + /// warning) when atomic property has one but not the other user-declared + /// setter or getter. + void AtomicPropertySetterGetterRules(ObjCImplDecl *IMPDecl, + ObjCInterfaceDecl *IDecl); + + ///@} +}; + +} // namespace clang + +#endif // LLVM_CLANG_SEMA_SEMAOBJC_H diff --git a/clang/lib/ARCMigrate/Transforms.cpp b/clang/lib/ARCMigrate/Transforms.cpp index 2808e35135dc..fda0e1c932fc 100644 --- a/clang/lib/ARCMigrate/Transforms.cpp +++ b/clang/lib/ARCMigrate/Transforms.cpp @@ -17,6 +17,7 @@ #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaObjC.h" using namespace clang; using namespace arcmt; @@ -26,8 +27,8 @@ ASTTraverser::~ASTTraverser() { } bool MigrationPass::CFBridgingFunctionsDefined() { if (!EnableCFBridgeFns) - EnableCFBridgeFns = SemaRef.isKnownName("CFBridgingRetain") && - SemaRef.isKnownName("CFBridgingRelease"); + EnableCFBridgeFns = SemaRef.ObjC().isKnownName("CFBridgingRetain") && + SemaRef.ObjC().isKnownName("CFBridgingRelease"); return *EnableCFBridgeFns; } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 7fbaee5690bd..6d026878d327 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -28,6 +28,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaDiagnostic.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" @@ -3945,7 +3946,7 @@ void Parser::ParseDeclarationSpecifiers( if (DSContext == DeclSpecContext::DSC_objc_method_result && isObjCInstancetype()) { - ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc); + ParsedType TypeRep = Actions.ObjC().ActOnObjCInstanceType(Loc); assert(TypeRep); isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, TypeRep, Policy); @@ -5002,8 +5003,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, continue; } SmallVector Fields; - Actions.ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(), - Tok.getIdentifierInfo(), Fields); + Actions.ObjC().ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(), + Tok.getIdentifierInfo(), Fields); ConsumeToken(); ExpectAndConsume(tok::r_paren); } diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 0551b8314f9f..9cd7d20fc4d5 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -31,6 +31,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenACC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/SemaSYCL.h" @@ -1227,8 +1228,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, IdentifierInfo &PropertyName = *Tok.getIdentifierInfo(); SourceLocation PropertyLoc = ConsumeToken(); - Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName, - ILoc, PropertyLoc); + Res = Actions.ObjC().ActOnClassPropertyRefExpr(II, PropertyName, ILoc, + PropertyLoc); break; } @@ -3093,9 +3094,9 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, if (Ty.isInvalid() || SubExpr.isInvalid()) return ExprError(); - return Actions.ActOnObjCBridgedCast(getCurScope(), OpenLoc, Kind, - BridgeKeywordLoc, Ty.get(), - RParenLoc, SubExpr.get()); + return Actions.ObjC().ActOnObjCBridgedCast(getCurScope(), OpenLoc, Kind, + BridgeKeywordLoc, Ty.get(), + RParenLoc, SubExpr.get()); } else if (ExprType >= CompoundLiteral && isTypeIdInParens(isAmbiguousTypeId)) { @@ -3811,7 +3812,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { /// '__objc_no' ExprResult Parser::ParseObjCBoolLiteral() { tok::TokenKind Kind = Tok.getKind(); - return Actions.ActOnObjCBoolLiteral(ConsumeToken(), Kind); + return Actions.ObjC().ActOnObjCBoolLiteral(ConsumeToken(), Kind); } /// Validate availability spec list, emitting diagnostics if necessary. Returns @@ -3932,6 +3933,6 @@ ExprResult Parser::ParseAvailabilityCheckExpr(SourceLocation BeginLoc) { if (Parens.consumeClose()) return ExprError(); - return Actions.ActOnObjCAvailabilityCheckExpr(AvailSpecs, BeginLoc, - Parens.getCloseLocation()); + return Actions.ObjC().ActOnObjCAvailabilityCheckExpr( + AvailSpecs, BeginLoc, Parens.getCloseLocation()); } diff --git a/clang/lib/Parse/ParseInit.cpp b/clang/lib/Parse/ParseInit.cpp index 423497bfcb66..04e4419f4d45 100644 --- a/clang/lib/Parse/ParseInit.cpp +++ b/clang/lib/Parse/ParseInit.cpp @@ -18,6 +18,7 @@ #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaObjC.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" using namespace clang; @@ -290,15 +291,15 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator( // Three cases. This is a message send to a type: [type foo] // This is a message send to super: [super foo] // This is a message sent to an expr: [super.bar foo] - switch (Actions.getObjCMessageKind( + switch (Actions.ObjC().getObjCMessageKind( getCurScope(), II, IILoc, II == Ident_super, NextToken().is(tok::period), ReceiverType)) { - case Sema::ObjCSuperMessage: + case SemaObjC::ObjCSuperMessage: CheckArrayDesignatorSyntax(*this, StartLoc, Desig); return ParseAssignmentExprWithObjCMessageExprStart( StartLoc, ConsumeToken(), nullptr, nullptr); - case Sema::ObjCClassMessage: + case SemaObjC::ObjCClassMessage: CheckArrayDesignatorSyntax(*this, StartLoc, Desig); ConsumeToken(); // the identifier if (!ReceiverType) { @@ -326,7 +327,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator( ReceiverType, nullptr); - case Sema::ObjCInstanceMessage: + case SemaObjC::ObjCInstanceMessage: // Fall through; we'll just parse the expression and // (possibly) treat this like an Objective-C message send // later. diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 8e54fe012c55..4cb04b353473 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -20,6 +20,7 @@ #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaObjC.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -132,7 +133,7 @@ public: void leave() { if (Params) - Actions.popObjCTypeParamList(S, Params); + Actions.ObjC().popObjCTypeParamList(S, Params); Params = nullptr; } }; @@ -179,23 +180,22 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class")) return Actions.ConvertDeclToDeclGroup(nullptr); - return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(), - ClassLocs.data(), - ClassTypeParams, - ClassNames.size()); + return Actions.ObjC().ActOnForwardClassDeclaration( + atLoc, ClassNames.data(), ClassLocs.data(), ClassTypeParams, + ClassNames.size()); } void Parser::CheckNestedObjCContexts(SourceLocation AtLoc) { - Sema::ObjCContainerKind ock = Actions.getObjCContainerKind(); - if (ock == Sema::OCK_None) + SemaObjC::ObjCContainerKind ock = Actions.ObjC().getObjCContainerKind(); + if (ock == SemaObjC::OCK_None) return; - Decl *Decl = Actions.getObjCDeclContext(); + Decl *Decl = Actions.ObjC().getObjCDeclContext(); if (CurParsedObjCImpl) { CurParsedObjCImpl->finish(AtLoc); } else { - Actions.ActOnAtEnd(getCurScope(), AtLoc); + Actions.ObjC().ActOnAtEnd(getCurScope(), AtLoc); } Diag(AtLoc, diag::err_objc_missing_end) << FixItHint::CreateInsertion(AtLoc, "@end\n"); @@ -305,7 +305,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, /*consumeLastToken=*/true)) return nullptr; - ObjCCategoryDecl *CategoryType = Actions.ActOnStartCategoryInterface( + ObjCCategoryDecl *CategoryType = Actions.ObjC().ActOnStartCategoryInterface( AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc, ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(), EndProtoLoc, attrs); @@ -360,9 +360,9 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, for (const auto &pair : ProtocolIdents) { protocolLocs.push_back(pair.second); } - Actions.FindProtocolDeclaration(/*WarnOnDeclarations=*/true, - /*ForObjCContainer=*/true, - ProtocolIdents, protocols); + Actions.ObjC().FindProtocolDeclaration(/*WarnOnDeclarations=*/true, + /*ForObjCContainer=*/true, + ProtocolIdents, protocols); } } else if (protocols.empty() && Tok.is(tok::less) && ParseObjCProtocolReferences(protocols, protocolLocs, true, true, @@ -372,11 +372,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, } if (Tok.isNot(tok::less)) - Actions.ActOnTypedefedProtocols(protocols, protocolLocs, - superClassId, superClassLoc); + Actions.ObjC().ActOnTypedefedProtocols(protocols, protocolLocs, + superClassId, superClassLoc); SkipBodyInfo SkipBody; - ObjCInterfaceDecl *ClsType = Actions.ActOnStartClassInterface( + ObjCInterfaceDecl *ClsType = Actions.ObjC().ActOnStartClassInterface( getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId, superClassLoc, typeArgs, SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(), @@ -468,7 +468,7 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( auto makeProtocolIdentsIntoTypeParameters = [&]() { unsigned index = 0; for (const auto &pair : protocolIdents) { - DeclResult typeParam = Actions.actOnObjCTypeParam( + DeclResult typeParam = Actions.ObjC().actOnObjCTypeParam( getCurScope(), ObjCTypeParamVariance::Invariant, SourceLocation(), index++, pair.first, pair.second, SourceLocation(), nullptr); if (typeParam.isUsable()) @@ -546,7 +546,7 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( } // Create the type parameter. - DeclResult typeParam = Actions.actOnObjCTypeParam( + DeclResult typeParam = Actions.ObjC().actOnObjCTypeParam( getCurScope(), variance, varianceLoc, typeParams.size(), paramName, paramLoc, colonLoc, boundType.isUsable() ? boundType.get() : nullptr); if (typeParam.isUsable()) @@ -587,11 +587,8 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( } // Form the type parameter list and enter its scope. - ObjCTypeParamList *list = Actions.actOnObjCTypeParamList( - getCurScope(), - lAngleLoc, - typeParams, - rAngleLoc); + ObjCTypeParamList *list = Actions.ObjC().actOnObjCTypeParamList( + getCurScope(), lAngleLoc, typeParams, rAngleLoc); Scope.enter(list); // Clear out the angle locations; they're used by the caller to indicate @@ -811,7 +808,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, SetterSel = SelectorTable::constructSetterSelector( PP.getIdentifierTable(), PP.getSelectorTable(), FD.D.getIdentifier()); - Decl *Property = Actions.ActOnProperty( + Decl *Property = Actions.ObjC().ActOnProperty( getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel, MethodImplKind); @@ -836,14 +833,14 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, Diag(Tok, diag::err_objc_missing_end) << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n"); Diag(CDecl->getBeginLoc(), diag::note_objc_container_start) - << (int)Actions.getObjCContainerKind(); + << (int)Actions.ObjC().getObjCContainerKind(); AtEnd.setBegin(Tok.getLocation()); AtEnd.setEnd(Tok.getLocation()); } // Insert collected methods declarations into the @interface object. // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. - Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables); + Actions.ObjC().ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables); } /// Diagnose redundant or conflicting nullability information. @@ -1437,7 +1434,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, methodAttrs); Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); - Decl *Result = Actions.ActOnMethodDeclaration( + Decl *Result = Actions.ObjC().ActOnMethodDeclaration( getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs, MethodImplKind, false, MethodDefinition); @@ -1447,14 +1444,14 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, SmallVector KeyIdents; SmallVector KeyLocs; - SmallVector ArgInfos; + SmallVector ArgInfos; ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | Scope::FunctionDeclarationScope | Scope::DeclScope); AttributePool allParamAttrs(AttrFactory); while (true) { ParsedAttributes paramAttrs(AttrFactory); - Sema::ObjCArgInfo ArgInfo; + SemaObjC::ObjCArgInfo ArgInfo; // Each iteration parses a single keyword argument. if (ExpectAndConsume(tok::colon)) @@ -1559,7 +1556,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), &KeyIdents[0]); - Decl *Result = Actions.ActOnMethodDeclaration( + Decl *Result = Actions.ObjC().ActOnMethodDeclaration( getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs, Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs, MethodImplKind, isVariadic, MethodDefinition); @@ -1609,8 +1606,8 @@ ParseObjCProtocolReferences(SmallVectorImpl &Protocols, return true; // Convert the list of protocols identifiers into a list of protocol decls. - Actions.FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer, - ProtocolIdents, Protocols); + Actions.ObjC().FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer, + ProtocolIdents, Protocols); return false; } @@ -1624,10 +1621,8 @@ TypeResult Parser::parseObjCProtocolQualifierType(SourceLocation &rAngleLoc) { (void)ParseObjCProtocolReferences(protocols, protocolLocs, false, false, lAngleLoc, rAngleLoc, /*consumeLastToken=*/true); - TypeResult result = Actions.actOnObjCProtocolQualifierType(lAngleLoc, - protocols, - protocolLocs, - rAngleLoc); + TypeResult result = Actions.ObjC().actOnObjCProtocolQualifierType( + lAngleLoc, protocols, protocolLocs, rAngleLoc); if (result.isUsable()) { Diag(lAngleLoc, diag::warn_objc_protocol_qualifier_missing_id) << FixItHint::CreateInsertion(lAngleLoc, "id") @@ -1706,19 +1701,11 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers( /*ObjCGenericList=*/true); // Let Sema figure out what we parsed. - Actions.actOnObjCTypeArgsOrProtocolQualifiers(getCurScope(), - baseType, - lAngleLoc, - identifiers, - identifierLocs, - rAngleLoc, - typeArgsLAngleLoc, - typeArgs, - typeArgsRAngleLoc, - protocolLAngleLoc, - protocols, - protocolRAngleLoc, - warnOnIncompleteProtocols); + Actions.ObjC().actOnObjCTypeArgsOrProtocolQualifiers( + getCurScope(), baseType, lAngleLoc, identifiers, identifierLocs, + rAngleLoc, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc, + protocolLAngleLoc, protocols, protocolRAngleLoc, + warnOnIncompleteProtocols); return; } @@ -1761,7 +1748,7 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers( } } else { invalid = true; - if (!Actions.LookupProtocol(identifiers[i], identifierLocs[i])) { + if (!Actions.ObjC().LookupProtocol(identifiers[i], identifierLocs[i])) { unknownTypeArgs.push_back(identifiers[i]); unknownTypeArgsLoc.push_back(identifierLocs[i]); } else if (!foundProtocolId) { @@ -1796,9 +1783,9 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers( // Diagnose the mix between type args and protocols. if (foundProtocolId && foundValidTypeId) - Actions.DiagnoseTypeArgsAndProtocols(foundProtocolId, foundProtocolSrcLoc, - foundValidTypeId, - foundValidTypeSrcLoc); + Actions.ObjC().DiagnoseTypeArgsAndProtocols( + foundProtocolId, foundProtocolSrcLoc, foundValidTypeId, + foundValidTypeSrcLoc); // Diagnose unknown arg types. ParsedType T; @@ -1904,17 +1891,9 @@ TypeResult Parser::parseObjCTypeArgsAndProtocolQualifiers( else endLoc = Tok.getLocation(); - return Actions.actOnObjCTypeArgsAndProtocolQualifiers( - getCurScope(), - loc, - type, - typeArgsLAngleLoc, - typeArgs, - typeArgsRAngleLoc, - protocolLAngleLoc, - protocols, - protocolLocs, - protocolRAngleLoc); + return Actions.ObjC().actOnObjCTypeArgsAndProtocolQualifiers( + getCurScope(), loc, type, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc, + protocolLAngleLoc, protocols, protocolLocs, protocolRAngleLoc); } void Parser::HelperActionsForIvarDeclarations( @@ -2029,7 +2008,7 @@ void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl, "Ivar should have interfaceDecl as its decl context"); // Install the declarator into the interface decl. FD.D.setObjCIvar(true); - Decl *Field = Actions.ActOnIvar( + Decl *Field = Actions.ObjC().ActOnIvar( getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D, FD.BitfieldSize, visibility); if (Field) @@ -2092,7 +2071,8 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol. IdentifierLocPair ProtoInfo(protocolName, nameLoc); - return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, attrs); + return Actions.ObjC().ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, + attrs); } CheckNestedObjCContexts(AtLoc); @@ -2119,7 +2099,8 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol")) return nullptr; - return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, attrs); + return Actions.ObjC().ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, + attrs); } // Last, and definitely not least, parse a protocol declaration. @@ -2134,7 +2115,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, return nullptr; SkipBodyInfo SkipBody; - ObjCProtocolDecl *ProtoType = Actions.ActOnStartProtocolInterface( + ObjCProtocolDecl *ProtoType = Actions.ObjC().ActOnStartProtocolInterface( AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(), EndProtoLoc, attrs, &SkipBody); @@ -2241,7 +2222,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, protocolLAngleLoc, protocolRAngleLoc, /*consumeLastToken=*/true); } - ObjCImpDecl = Actions.ActOnStartCategoryImplementation( + ObjCImpDecl = Actions.ObjC().ActOnStartCategoryImplementation( AtLoc, nameId, nameLoc, categoryId, categoryLoc, Attrs); } else { @@ -2255,7 +2236,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, superClassId = Tok.getIdentifierInfo(); superClassLoc = ConsumeToken(); // Consume super class name } - ObjCImpDecl = Actions.ActOnStartClassImplementation( + ObjCImpDecl = Actions.ObjC().ActOnStartClassImplementation( AtLoc, nameId, nameLoc, superClassId, superClassLoc, Attrs); if (Tok.is(tok::l_brace)) // we have ivars @@ -2291,7 +2272,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, } } - return Actions.ActOnFinishObjCImplementation(ObjCImpDecl, DeclsInGroup); + return Actions.ObjC().ActOnFinishObjCImplementation(ObjCImpDecl, + DeclsInGroup); } Parser::DeclGroupPtrTy @@ -2314,7 +2296,7 @@ Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() { P.Diag(P.Tok, diag::err_objc_missing_end) << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n"); P.Diag(Dcl->getBeginLoc(), diag::note_objc_container_start) - << Sema::OCK_Implementation; + << SemaObjC::OCK_Implementation; } } P.CurParsedObjCImpl = nullptr; @@ -2323,12 +2305,13 @@ Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() { void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) { assert(!Finished); - P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl, AtEnd.getBegin()); + P.Actions.ObjC().DefaultSynthesizeProperties(P.getCurScope(), Dcl, + AtEnd.getBegin()); for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], true/*Methods*/); - P.Actions.ActOnAtEnd(P.getCurScope(), AtEnd); + P.Actions.ObjC().ActOnAtEnd(P.getCurScope(), AtEnd); if (HasCFunction) for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) @@ -2361,8 +2344,8 @@ Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { IdentifierInfo *classId = Tok.getIdentifierInfo(); SourceLocation classLoc = ConsumeToken(); // consume class-name; ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias"); - return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc, - classId, classLoc); + return Actions.ObjC().ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc, + classId, classLoc); } /// property-synthesis: @@ -2411,10 +2394,9 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { propertyIvar = Tok.getIdentifierInfo(); propertyIvarLoc = ConsumeToken(); // consume ivar-name } - Actions.ActOnPropertyImplDecl( - getCurScope(), atLoc, propertyLoc, true, - propertyId, propertyIvar, propertyIvarLoc, - ObjCPropertyQueryKind::OBJC_PR_query_unknown); + Actions.ObjC().ActOnPropertyImplDecl( + getCurScope(), atLoc, propertyLoc, true, propertyId, propertyIvar, + propertyIvarLoc, ObjCPropertyQueryKind::OBJC_PR_query_unknown); if (Tok.isNot(tok::comma)) break; ConsumeToken(); // consume ',' @@ -2473,11 +2455,11 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { IdentifierInfo *propertyId = Tok.getIdentifierInfo(); SourceLocation propertyLoc = ConsumeToken(); // consume property name - Actions.ActOnPropertyImplDecl( - getCurScope(), atLoc, propertyLoc, false, - propertyId, nullptr, SourceLocation(), - isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class : - ObjCPropertyQueryKind::OBJC_PR_query_unknown); + Actions.ObjC().ActOnPropertyImplDecl( + getCurScope(), atLoc, propertyLoc, false, propertyId, nullptr, + SourceLocation(), + isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class + : ObjCPropertyQueryKind::OBJC_PR_query_unknown); if (Tok.isNot(tok::comma)) break; @@ -2502,7 +2484,7 @@ StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) { } // consume ';' ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw"); - return Actions.ActOnObjCAtThrowStmt(atLoc, Res.get(), getCurScope()); + return Actions.ObjC().ActOnObjCAtThrowStmt(atLoc, Res.get(), getCurScope()); } /// objc-synchronized-statement: @@ -2539,7 +2521,8 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { // Check the @synchronized operand now. if (!operand.isInvalid()) - operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.get()); + operand = + Actions.ObjC().ActOnObjCAtSynchronizedOperand(atLoc, operand.get()); // Parse the compound statement within a new scope. ParseScope bodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope); @@ -2554,7 +2537,8 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { if (body.isInvalid()) body = Actions.ActOnNullStmt(Tok.getLocation()); - return Actions.ActOnObjCAtSynchronizedStmt(atLoc, operand.get(), body.get()); + return Actions.ObjC().ActOnObjCAtSynchronizedStmt(atLoc, operand.get(), + body.get()); } /// objc-try-catch-statement: @@ -2611,7 +2595,8 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { // Inform the actions module about the declarator, so it // gets added to the current scope. - FirstPart = Actions.ActOnObjCExceptionDecl(getCurScope(), ParmDecl); + FirstPart = + Actions.ObjC().ActOnObjCExceptionDecl(getCurScope(), ParmDecl); } else ConsumeToken(); // consume '...' @@ -2630,10 +2615,8 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { if (CatchBody.isInvalid()) CatchBody = Actions.ActOnNullStmt(Tok.getLocation()); - StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, - RParenLoc, - FirstPart, - CatchBody.get()); + StmtResult Catch = Actions.ObjC().ActOnObjCAtCatchStmt( + AtCatchFinallyLoc, RParenLoc, FirstPart, CatchBody.get()); if (!Catch.isInvalid()) CatchStmts.push_back(Catch.get()); @@ -2669,8 +2652,8 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get()); } - FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, - FinallyBody.get()); + FinallyStmt = Actions.ObjC().ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, + FinallyBody.get()); catch_or_finally_seen = true; break; } @@ -2680,9 +2663,8 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { return StmtError(); } - return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.get(), - CatchStmts, - FinallyStmt.get()); + return Actions.ObjC().ActOnObjCAtTryStmt(atLoc, TryBody.get(), CatchStmts, + FinallyStmt.get()); } /// objc-autoreleasepool-statement: @@ -2704,8 +2686,8 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) { BodyScope.Exit(); if (AutoreleasePoolBody.isInvalid()) AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation()); - return Actions.ActOnObjCAutoreleasePoolStmt(atLoc, - AutoreleasePoolBody.get()); + return Actions.ObjC().ActOnObjCAutoreleasePoolStmt(atLoc, + AutoreleasePoolBody.get()); } /// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them @@ -2788,7 +2770,7 @@ Decl *Parser::ParseObjCMethodDefinition() { } // Allow the rest of sema to find private method decl implementations. - Actions.AddAnyMethodToGlobalPool(MDecl); + Actions.ObjC().AddAnyMethodToGlobalPool(MDecl); assert (CurParsedObjCImpl && "ParseObjCMethodDefinition - Method out of @implementation"); // Consume the tokens and store them for later parsing. @@ -2872,7 +2854,7 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { return Lit; return ParsePostfixExpressionSuffix( - Actions.BuildObjCNumericLiteral(AtLoc, Lit.get())); + Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get())); } case tok::string_literal: // primary-expression: string-literal @@ -3128,15 +3110,14 @@ ExprResult Parser::ParseObjCMessageExpression() { IdentifierInfo *Name = Tok.getIdentifierInfo(); SourceLocation NameLoc = Tok.getLocation(); ParsedType ReceiverType; - switch (Actions.getObjCMessageKind(getCurScope(), Name, NameLoc, - Name == Ident_super, - NextToken().is(tok::period), - ReceiverType)) { - case Sema::ObjCSuperMessage: + switch (Actions.ObjC().getObjCMessageKind( + getCurScope(), Name, NameLoc, Name == Ident_super, + NextToken().is(tok::period), ReceiverType)) { + case SemaObjC::ObjCSuperMessage: return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr, nullptr); - case Sema::ObjCClassMessage: + case SemaObjC::ObjCClassMessage: if (!ReceiverType) { SkipUntil(tok::r_square, StopAtSemi); return ExprError(); @@ -3162,7 +3143,7 @@ ExprResult Parser::ParseObjCMessageExpression() { return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), ReceiverType, nullptr); - case Sema::ObjCInstanceMessage: + case SemaObjC::ObjCInstanceMessage: // Fall through to parse an expression. break; } @@ -3375,13 +3356,14 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]); if (SuperLoc.isValid()) - return Actions.ActOnSuperMessage(getCurScope(), SuperLoc, Sel, - LBracLoc, KeyLocs, RBracLoc, KeyExprs); + return Actions.ObjC().ActOnSuperMessage( + getCurScope(), SuperLoc, Sel, LBracLoc, KeyLocs, RBracLoc, KeyExprs); else if (ReceiverType) - return Actions.ActOnClassMessage(getCurScope(), ReceiverType, Sel, - LBracLoc, KeyLocs, RBracLoc, KeyExprs); - return Actions.ActOnInstanceMessage(getCurScope(), ReceiverExpr, Sel, - LBracLoc, KeyLocs, RBracLoc, KeyExprs); + return Actions.ObjC().ActOnClassMessage(getCurScope(), ReceiverType, Sel, + LBracLoc, KeyLocs, RBracLoc, + KeyExprs); + return Actions.ObjC().ActOnInstanceMessage( + getCurScope(), ReceiverExpr, Sel, LBracLoc, KeyLocs, RBracLoc, KeyExprs); } ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { @@ -3410,7 +3392,7 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { AtStrings.push_back(Lit.get()); } - return Actions.ParseObjCStringLiteral(AtLocs.data(), AtStrings); + return Actions.ObjC().ParseObjCStringLiteral(AtLocs.data(), AtStrings); } /// ParseObjCBooleanLiteral - @@ -3421,7 +3403,7 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc, bool ArgValue) { SourceLocation EndLoc = ConsumeToken(); // consume the keyword. - return Actions.ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue); + return Actions.ObjC().ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue); } /// ParseObjCCharacterLiteral - @@ -3433,7 +3415,7 @@ ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) { return Lit; } ConsumeToken(); // Consume the literal token. - return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get()); + return Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get()); } /// ParseObjCNumericLiteral - @@ -3447,7 +3429,7 @@ ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) { return Lit; } ConsumeToken(); // Consume the literal token. - return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get()); + return Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get()); } /// ParseObjCBoxedExpr - @@ -3471,8 +3453,8 @@ Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) { // a boxed expression from a literal. SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation(); ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.get()); - return Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc), - ValueExpr.get()); + return Actions.ObjC().BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc), + ValueExpr.get()); } ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { @@ -3515,7 +3497,7 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { return ExprError(); MultiExprArg Args(ElementExprs); - return Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args); + return Actions.ObjC().BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args); } ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { @@ -3580,8 +3562,8 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { return ExprError(); // Create the ObjCDictionaryLiteral. - return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc), - Elements); + return Actions.ObjC().BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc), + Elements); } /// objc-encode-expression: @@ -3605,8 +3587,8 @@ Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) { if (Ty.isInvalid()) return ExprError(); - return Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, T.getOpenLocation(), - Ty.get(), T.getCloseLocation()); + return Actions.ObjC().ParseObjCEncodeExpression( + AtLoc, EncLoc, T.getOpenLocation(), Ty.get(), T.getCloseLocation()); } /// objc-protocol-expression @@ -3629,9 +3611,9 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { T.consumeClose(); - return Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc, - T.getOpenLocation(), ProtoIdLoc, - T.getCloseLocation()); + return Actions.ObjC().ParseObjCProtocolExpression( + protocolId, AtLoc, ProtoLoc, T.getOpenLocation(), ProtoIdLoc, + T.getCloseLocation()); } /// objc-selector-expression @@ -3695,18 +3677,17 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { ConsumeParen(); // ')' T.consumeClose(); Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]); - return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc, - T.getOpenLocation(), - T.getCloseLocation(), - !HasOptionalParen); + return Actions.ObjC().ParseObjCSelectorExpression( + Sel, AtLoc, SelectorLoc, T.getOpenLocation(), T.getCloseLocation(), + !HasOptionalParen); } void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { // MCDecl might be null due to error in method or c-function prototype, etc. Decl *MCDecl = LM.D; - bool skip = MCDecl && - ((parseMethod && !Actions.isObjCMethodDecl(MCDecl)) || - (!parseMethod && Actions.isObjCMethodDecl(MCDecl))); + bool skip = + MCDecl && ((parseMethod && !Actions.ObjC().isObjCMethodDecl(MCDecl)) || + (!parseMethod && Actions.ObjC().isObjCMethodDecl(MCDecl))); if (skip) return; @@ -3741,7 +3722,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { // Tell the actions module that we have entered a method or c-function definition // with the specified Declarator for the method/function. if (parseMethod) - Actions.ActOnStartOfObjCMethodDef(getCurScope(), MCDecl); + Actions.ObjC().ActOnStartOfObjCMethodDef(getCurScope(), MCDecl); else Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl); if (Tok.is(tok::kw_try)) diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 629421c01d17..e0116d300310 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -22,6 +22,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/STLExtras.h" @@ -2294,10 +2295,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { } else if (ForEach) { // Similarly, we need to do the semantic analysis for a for-range // statement immediately in order to close over temporaries correctly. - ForEachStmt = Actions.ActOnObjCForCollectionStmt(ForLoc, - FirstPart.get(), - Collection.get(), - T.getCloseLocation()); + ForEachStmt = Actions.ObjC().ActOnObjCForCollectionStmt( + ForLoc, FirstPart.get(), Collection.get(), T.getCloseLocation()); } else { // In OpenMP loop region loop control variable must be captured and be // private. Perform analysis of first part (if any). @@ -2345,8 +2344,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { return StmtError(); if (ForEach) - return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(), - Body.get()); + return Actions.ObjC().FinishObjCForCollectionStmt(ForEachStmt.get(), + Body.get()); if (ForRangeInfo.ParsedForRangeDecl()) return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get()); diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index a96439df6642..58e0a3b9679b 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -54,6 +54,7 @@ add_clang_library(clangSema SemaLambda.cpp SemaLookup.cpp SemaModule.cpp + SemaObjC.cpp SemaObjCProperty.cpp SemaOpenACC.cpp SemaOpenMP.cpp diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index a1e32d391ed0..7585f1c367be 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -45,6 +45,7 @@ #include "clang/Sema/SemaConsumer.h" #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenACC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/SemaSYCL.h" @@ -203,6 +204,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, CurScope(nullptr), Ident_super(nullptr), CUDAPtr(std::make_unique(*this)), HLSLPtr(std::make_unique(*this)), + ObjCPtr(std::make_unique(*this)), OpenACCPtr(std::make_unique(*this)), OpenMPPtr(std::make_unique(*this)), SYCLPtr(std::make_unique(*this)), @@ -224,20 +226,16 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, AccessCheckingSFINAE(false), CurrentInstantiationScope(nullptr), InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), SatisfactionCache(Context), - NSNumberDecl(nullptr), NSValueDecl(nullptr), NSStringDecl(nullptr), - StringWithUTF8StringMethod(nullptr), - ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), - ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), - DictionaryWithObjectsMethod(nullptr), CodeCompleter(CodeCompleter) { + CodeCompleter(CodeCompleter) { assert(pp.TUKind == TUKind); TUScope = nullptr; LoadedExternalKnownNamespaces = false; for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I) - NSNumberLiteralMethods[I] = nullptr; + ObjC().NSNumberLiteralMethods[I] = nullptr; if (getLangOpts().ObjC) - NSAPIObj.reset(new NSAPI(Context)); + ObjC().NSAPIObj.reset(new NSAPI(Context)); if (getLangOpts().CPlusPlus) FieldCollector.reset(new CXXFieldCollector()); @@ -1129,7 +1127,7 @@ void Sema::ActOnEndOfTranslationUnit() { // Complete translation units and modules define vtables and perform implicit // instantiations. PCH files do not. if (TUKind != TU_Prefix) { - DiagnoseUseOfUnimplementedSelectors(); + ObjC().DiagnoseUseOfUnimplementedSelectors(); ActOnEndOfTranslationUnitFragment( !ModuleScopes.empty() && ModuleScopes.back().Module->Kind == diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index c5998aca0d72..443bf162044f 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -16,6 +16,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Lexer.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" using namespace clang; @@ -372,7 +373,7 @@ static void ProcessAPINotes(Sema &S, Decl *D, if (auto Var = dyn_cast(D)) { // Make adjustments to parameter types. if (isa(Var)) { - Type = S.AdjustParameterTypeForObjCAutoRefCount( + Type = S.ObjC().AdjustParameterTypeForObjCAutoRefCount( Type, D->getLocation(), TypeInfo); Type = S.Context.getAdjustedParameterType(Type); } diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index a83b1e8afadb..bb44531495a5 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -860,22 +860,6 @@ void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, UnusedAttr::GNU_unused)); } -void Sema::AddCFAuditedAttribute(Decl *D) { - IdentifierInfo *Ident; - SourceLocation Loc; - std::tie(Ident, Loc) = PP.getPragmaARCCFCodeAuditedInfo(); - if (!Loc.isValid()) return; - - // Don't add a redundant or conflicting attribute. - if (D->hasAttr() || - D->hasAttr()) - return; - - AttributeCommonInfo Info(Ident, SourceRange(Loc), - AttributeCommonInfo::Form::Pragma()); - D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Info)); -} - namespace { std::optional diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 846a31a79673..5ebc25317bf3 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -19,6 +19,7 @@ #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaObjC.h" #include using namespace clang; @@ -98,11 +99,11 @@ ShouldDiagnoseAvailabilityOfDecl(Sema &S, const NamedDecl *D, // For +new, infer availability from -init. if (const auto *MD = dyn_cast(D)) { - if (S.NSAPIObj && ClassReceiver) { + if (S.ObjC().NSAPIObj && ClassReceiver) { ObjCMethodDecl *Init = ClassReceiver->lookupInstanceMethod( - S.NSAPIObj->getInitSelector()); + S.ObjC().NSAPIObj->getInitSelector()); if (Init && Result == AR_Available && MD->isClassMethod() && - MD->getSelector() == S.NSAPIObj->getNewSelector() && + MD->getSelector() == S.ObjC().NSAPIObj->getNewSelector() && MD->definedInNSObject(S.getASTContext())) { Result = Init->getAvailability(Message); D = Init; diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 126fd3797417..483ec7e36eae 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -24,6 +24,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include @@ -159,8 +160,8 @@ namespace { assert(Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()); Expr *src = SrcExpr.get(); - if (Self.CheckObjCConversion(OpRange, DestType, src, CCK) == - Sema::ACR_unbridged) + if (Self.ObjC().CheckObjCConversion(OpRange, DestType, src, CCK) == + SemaObjC::ACR_unbridged) IsARCUnbridgedCast = true; SrcExpr = src; } @@ -1499,7 +1500,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, // Allow ns-pointer to cf-pointer conversion in either direction // with static casts. if (!CStyle && - Self.CheckTollFreeBridgeStaticCast(DestType, SrcExpr.get(), Kind)) + Self.ObjC().CheckTollFreeBridgeStaticCast(DestType, SrcExpr.get(), Kind)) return TC_Success; // See if it looks like the user is trying to convert between @@ -2524,7 +2525,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, } else if (IsLValueCast) { Kind = CK_LValueBitCast; } else if (DestType->isObjCObjectPointerType()) { - Kind = Self.PrepareCastToObjCObjectPointer(SrcExpr); + Kind = Self.ObjC().PrepareCastToObjCObjectPointer(SrcExpr); } else if (DestType->isBlockPointerType()) { if (!SrcType->isBlockPointerType()) { Kind = CK_AnyPointerToBlockPointerCast; @@ -3217,8 +3218,8 @@ void CastOperation::CheckCStyleCast() { return; } } - } - else if (!Self.CheckObjCARCUnavailableWeakConversion(DestType, SrcType)) { + } else if (!Self.ObjC().CheckObjCARCUnavailableWeakConversion(DestType, + SrcType)) { Self.Diag(SrcExpr.get()->getBeginLoc(), diag::err_arc_convesion_of_weak_unavailable) << 1 << SrcType << DestType << SrcExpr.get()->getSourceRange(); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 54789dde5069..ecd182165114 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -62,6 +62,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" @@ -2488,7 +2489,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, return ExprError(); assert(TheCall->getNumArgs() == 1 && "Wrong # arguments to builtin CFStringMakeConstantString"); - if (CheckObjCString(TheCall->getArg(0))) + if (ObjC().CheckObjCString(TheCall->getArg(0))) return ExprError(); break; case Builtin::BI__builtin_ms_va_start: @@ -8195,20 +8196,6 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, return false; } -bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, - ArrayRef Args) { - VariadicCallType CallType = - Method->isVariadic() ? VariadicMethod : VariadicDoesNotApply; - - checkCall(Method, nullptr, /*ThisArg=*/nullptr, Args, - /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(), - CallType); - - CheckTCBEnforcement(lbrac, Method); - - return false; -} - bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, const FunctionProtoType *Proto) { QualType Ty; @@ -9362,38 +9349,6 @@ ExprResult Sema::BuiltinNontemporalOverloaded(ExprResult TheCallResult) { return TheCallResult; } -/// CheckObjCString - Checks that the argument to the builtin -/// CFString constructor is correct -/// Note: It might also make sense to do the UTF-16 conversion here (would -/// simplify the backend). -bool Sema::CheckObjCString(Expr *Arg) { - Arg = Arg->IgnoreParenCasts(); - StringLiteral *Literal = dyn_cast(Arg); - - if (!Literal || !Literal->isOrdinary()) { - Diag(Arg->getBeginLoc(), diag::err_cfstring_literal_not_string_constant) - << Arg->getSourceRange(); - return true; - } - - if (Literal->containsNonAsciiOrNull()) { - StringRef String = Literal->getString(); - unsigned NumBytes = String.size(); - SmallVector ToBuf(NumBytes); - const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data(); - llvm::UTF16 *ToPtr = &ToBuf[0]; - - llvm::ConversionResult Result = - llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr, - ToPtr + NumBytes, llvm::strictConversion); - // Check for conversion failure. - if (Result != llvm::conversionOK) - Diag(Arg->getBeginLoc(), diag::warn_cfstring_truncated) - << Arg->getSourceRange(); - } - return false; -} - /// CheckObjCString - Checks that the format string argument to the os_log() /// and os_trace() functions is correct, and converts it to const char *. ExprResult Sema::CheckOSLogFormatStringArg(Expr *Arg) { @@ -15279,7 +15234,7 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, // Special case for ObjC BOOL on targets where its a typedef for a signed char // (Namely, macOS). FIXME: IntRange::forValueOfType should do this. bool IsObjCSignedCharBool = S.getLangOpts().ObjC && - S.NSAPIObj->isObjCBOOLType(OtherT) && + S.ObjC().NSAPIObj->isObjCBOOLType(OtherT) && OtherT->isSpecificBuiltinType(BuiltinType::SChar); // Whether we're treating Other as being a bool because of the form of @@ -15709,7 +15664,7 @@ static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, static bool isObjCSignedCharBool(Sema &S, QualType Ty) { return Ty->isSpecificBuiltinType(BuiltinType::SChar) && - S.getLangOpts().ObjC && S.NSAPIObj->isObjCBOOLType(Ty); + S.getLangOpts().ObjC && S.ObjC().NSAPIObj->isObjCBOOLType(Ty); } static void adornObjCBoolConversionDiagWithTernaryFixit( @@ -16021,7 +15976,7 @@ static void checkObjCCollectionLiteralElement(Sema &S, /// target type. static void checkObjCArrayLiteral(Sema &S, QualType TargetType, ObjCArrayLiteral *ArrayLiteral) { - if (!S.NSArrayDecl) + if (!S.ObjC().NSArrayDecl) return; const auto *TargetObjCPtr = TargetType->getAs(); @@ -16029,8 +15984,8 @@ static void checkObjCArrayLiteral(Sema &S, QualType TargetType, return; if (TargetObjCPtr->isUnspecialized() || - TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() - != S.NSArrayDecl->getCanonicalDecl()) + TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() != + S.ObjC().NSArrayDecl->getCanonicalDecl()) return; auto TypeArgs = TargetObjCPtr->getTypeArgs(); @@ -16050,7 +16005,7 @@ static void checkObjCArrayLiteral(Sema &S, QualType TargetType, static void checkObjCDictionaryLiteral(Sema &S, QualType TargetType, ObjCDictionaryLiteral *DictionaryLiteral) { - if (!S.NSDictionaryDecl) + if (!S.ObjC().NSDictionaryDecl) return; const auto *TargetObjCPtr = TargetType->getAs(); @@ -16058,8 +16013,8 @@ checkObjCDictionaryLiteral(Sema &S, QualType TargetType, return; if (TargetObjCPtr->isUnspecialized() || - TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() - != S.NSDictionaryDecl->getCanonicalDecl()) + TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() != + S.ObjC().NSDictionaryDecl->getCanonicalDecl()) return; auto TypeArgs = TargetObjCPtr->getTypeArgs(); @@ -18794,465 +18749,6 @@ void Sema::CheckArrayAccess(const Expr *expr) { } } -//===--- CHECK: Objective-C retain cycles ----------------------------------// - -namespace { - -struct RetainCycleOwner { - VarDecl *Variable = nullptr; - SourceRange Range; - SourceLocation Loc; - bool Indirect = false; - - RetainCycleOwner() = default; - - void setLocsFrom(Expr *e) { - Loc = e->getExprLoc(); - Range = e->getSourceRange(); - } -}; - -} // namespace - -/// Consider whether capturing the given variable can possibly lead to -/// a retain cycle. -static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) { - // In ARC, it's captured strongly iff the variable has __strong - // lifetime. In MRR, it's captured strongly if the variable is - // __block and has an appropriate type. - if (var->getType().getObjCLifetime() != Qualifiers::OCL_Strong) - return false; - - owner.Variable = var; - if (ref) - owner.setLocsFrom(ref); - return true; -} - -static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) { - while (true) { - e = e->IgnoreParens(); - if (CastExpr *cast = dyn_cast(e)) { - switch (cast->getCastKind()) { - case CK_BitCast: - case CK_LValueBitCast: - case CK_LValueToRValue: - case CK_ARCReclaimReturnedObject: - e = cast->getSubExpr(); - continue; - - default: - return false; - } - } - - if (ObjCIvarRefExpr *ref = dyn_cast(e)) { - ObjCIvarDecl *ivar = ref->getDecl(); - if (ivar->getType().getObjCLifetime() != Qualifiers::OCL_Strong) - return false; - - // Try to find a retain cycle in the base. - if (!findRetainCycleOwner(S, ref->getBase(), owner)) - return false; - - if (ref->isFreeIvar()) owner.setLocsFrom(ref); - owner.Indirect = true; - return true; - } - - if (DeclRefExpr *ref = dyn_cast(e)) { - VarDecl *var = dyn_cast(ref->getDecl()); - if (!var) return false; - return considerVariable(var, ref, owner); - } - - if (MemberExpr *member = dyn_cast(e)) { - if (member->isArrow()) return false; - - // Don't count this as an indirect ownership. - e = member->getBase(); - continue; - } - - if (PseudoObjectExpr *pseudo = dyn_cast(e)) { - // Only pay attention to pseudo-objects on property references. - ObjCPropertyRefExpr *pre - = dyn_cast(pseudo->getSyntacticForm() - ->IgnoreParens()); - if (!pre) return false; - if (pre->isImplicitProperty()) return false; - ObjCPropertyDecl *property = pre->getExplicitProperty(); - if (!property->isRetaining() && - !(property->getPropertyIvarDecl() && - property->getPropertyIvarDecl()->getType() - .getObjCLifetime() == Qualifiers::OCL_Strong)) - return false; - - owner.Indirect = true; - if (pre->isSuperReceiver()) { - owner.Variable = S.getCurMethodDecl()->getSelfDecl(); - if (!owner.Variable) - return false; - owner.Loc = pre->getLocation(); - owner.Range = pre->getSourceRange(); - return true; - } - e = const_cast(cast(pre->getBase()) - ->getSourceExpr()); - continue; - } - - // Array ivars? - - return false; - } -} - -namespace { - - struct FindCaptureVisitor : EvaluatedExprVisitor { - VarDecl *Variable; - Expr *Capturer = nullptr; - bool VarWillBeReased = false; - - FindCaptureVisitor(ASTContext &Context, VarDecl *variable) - : EvaluatedExprVisitor(Context), - Variable(variable) {} - - void VisitDeclRefExpr(DeclRefExpr *ref) { - if (ref->getDecl() == Variable && !Capturer) - Capturer = ref; - } - - void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) { - if (Capturer) return; - Visit(ref->getBase()); - if (Capturer && ref->isFreeIvar()) - Capturer = ref; - } - - void VisitBlockExpr(BlockExpr *block) { - // Look inside nested blocks - if (block->getBlockDecl()->capturesVariable(Variable)) - Visit(block->getBlockDecl()->getBody()); - } - - void VisitOpaqueValueExpr(OpaqueValueExpr *OVE) { - if (Capturer) return; - if (OVE->getSourceExpr()) - Visit(OVE->getSourceExpr()); - } - - void VisitBinaryOperator(BinaryOperator *BinOp) { - if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign) - return; - Expr *LHS = BinOp->getLHS(); - if (const DeclRefExpr *DRE = dyn_cast_or_null(LHS)) { - if (DRE->getDecl() != Variable) - return; - if (Expr *RHS = BinOp->getRHS()) { - RHS = RHS->IgnoreParenCasts(); - std::optional Value; - VarWillBeReased = - (RHS && (Value = RHS->getIntegerConstantExpr(Context)) && - *Value == 0); - } - } - } - }; - -} // namespace - -/// Check whether the given argument is a block which captures a -/// variable. -static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) { - assert(owner.Variable && owner.Loc.isValid()); - - e = e->IgnoreParenCasts(); - - // Look through [^{...} copy] and Block_copy(^{...}). - if (ObjCMessageExpr *ME = dyn_cast(e)) { - Selector Cmd = ME->getSelector(); - if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") { - e = ME->getInstanceReceiver(); - if (!e) - return nullptr; - e = e->IgnoreParenCasts(); - } - } else if (CallExpr *CE = dyn_cast(e)) { - if (CE->getNumArgs() == 1) { - FunctionDecl *Fn = dyn_cast_or_null(CE->getCalleeDecl()); - if (Fn) { - const IdentifierInfo *FnI = Fn->getIdentifier(); - if (FnI && FnI->isStr("_Block_copy")) { - e = CE->getArg(0)->IgnoreParenCasts(); - } - } - } - } - - BlockExpr *block = dyn_cast(e); - if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable)) - return nullptr; - - FindCaptureVisitor visitor(S.Context, owner.Variable); - visitor.Visit(block->getBlockDecl()->getBody()); - return visitor.VarWillBeReased ? nullptr : visitor.Capturer; -} - -static void diagnoseRetainCycle(Sema &S, Expr *capturer, - RetainCycleOwner &owner) { - assert(capturer); - assert(owner.Variable && owner.Loc.isValid()); - - S.Diag(capturer->getExprLoc(), diag::warn_arc_retain_cycle) - << owner.Variable << capturer->getSourceRange(); - S.Diag(owner.Loc, diag::note_arc_retain_cycle_owner) - << owner.Indirect << owner.Range; -} - -/// Check for a keyword selector that starts with the word 'add' or -/// 'set'. -static bool isSetterLikeSelector(Selector sel) { - if (sel.isUnarySelector()) return false; - - StringRef str = sel.getNameForSlot(0); - str = str.ltrim('_'); - if (str.starts_with("set")) - str = str.substr(3); - else if (str.starts_with("add")) { - // Specially allow 'addOperationWithBlock:'. - if (sel.getNumArgs() == 1 && str.starts_with("addOperationWithBlock")) - return false; - str = str.substr(3); - } else - return false; - - if (str.empty()) return true; - return !isLowercase(str.front()); -} - -static std::optional -GetNSMutableArrayArgumentIndex(Sema &S, ObjCMessageExpr *Message) { - bool IsMutableArray = S.NSAPIObj->isSubclassOfNSClass( - Message->getReceiverInterface(), - NSAPI::ClassId_NSMutableArray); - if (!IsMutableArray) { - return std::nullopt; - } - - Selector Sel = Message->getSelector(); - - std::optional MKOpt = - S.NSAPIObj->getNSArrayMethodKind(Sel); - if (!MKOpt) { - return std::nullopt; - } - - NSAPI::NSArrayMethodKind MK = *MKOpt; - - switch (MK) { - case NSAPI::NSMutableArr_addObject: - case NSAPI::NSMutableArr_insertObjectAtIndex: - case NSAPI::NSMutableArr_setObjectAtIndexedSubscript: - return 0; - case NSAPI::NSMutableArr_replaceObjectAtIndex: - return 1; - - default: - return std::nullopt; - } - - return std::nullopt; -} - -static std::optional -GetNSMutableDictionaryArgumentIndex(Sema &S, ObjCMessageExpr *Message) { - bool IsMutableDictionary = S.NSAPIObj->isSubclassOfNSClass( - Message->getReceiverInterface(), - NSAPI::ClassId_NSMutableDictionary); - if (!IsMutableDictionary) { - return std::nullopt; - } - - Selector Sel = Message->getSelector(); - - std::optional MKOpt = - S.NSAPIObj->getNSDictionaryMethodKind(Sel); - if (!MKOpt) { - return std::nullopt; - } - - NSAPI::NSDictionaryMethodKind MK = *MKOpt; - - switch (MK) { - case NSAPI::NSMutableDict_setObjectForKey: - case NSAPI::NSMutableDict_setValueForKey: - case NSAPI::NSMutableDict_setObjectForKeyedSubscript: - return 0; - - default: - return std::nullopt; - } - - return std::nullopt; -} - -static std::optional GetNSSetArgumentIndex(Sema &S, - ObjCMessageExpr *Message) { - bool IsMutableSet = S.NSAPIObj->isSubclassOfNSClass( - Message->getReceiverInterface(), - NSAPI::ClassId_NSMutableSet); - - bool IsMutableOrderedSet = S.NSAPIObj->isSubclassOfNSClass( - Message->getReceiverInterface(), - NSAPI::ClassId_NSMutableOrderedSet); - if (!IsMutableSet && !IsMutableOrderedSet) { - return std::nullopt; - } - - Selector Sel = Message->getSelector(); - - std::optional MKOpt = - S.NSAPIObj->getNSSetMethodKind(Sel); - if (!MKOpt) { - return std::nullopt; - } - - NSAPI::NSSetMethodKind MK = *MKOpt; - - switch (MK) { - case NSAPI::NSMutableSet_addObject: - case NSAPI::NSOrderedSet_setObjectAtIndex: - case NSAPI::NSOrderedSet_setObjectAtIndexedSubscript: - case NSAPI::NSOrderedSet_insertObjectAtIndex: - return 0; - case NSAPI::NSOrderedSet_replaceObjectAtIndexWithObject: - return 1; - } - - return std::nullopt; -} - -void Sema::CheckObjCCircularContainer(ObjCMessageExpr *Message) { - if (!Message->isInstanceMessage()) { - return; - } - - std::optional ArgOpt; - - if (!(ArgOpt = GetNSMutableArrayArgumentIndex(*this, Message)) && - !(ArgOpt = GetNSMutableDictionaryArgumentIndex(*this, Message)) && - !(ArgOpt = GetNSSetArgumentIndex(*this, Message))) { - return; - } - - int ArgIndex = *ArgOpt; - - Expr *Arg = Message->getArg(ArgIndex)->IgnoreImpCasts(); - if (OpaqueValueExpr *OE = dyn_cast(Arg)) { - Arg = OE->getSourceExpr()->IgnoreImpCasts(); - } - - if (Message->getReceiverKind() == ObjCMessageExpr::SuperInstance) { - if (DeclRefExpr *ArgRE = dyn_cast(Arg)) { - if (ArgRE->isObjCSelfExpr()) { - Diag(Message->getSourceRange().getBegin(), - diag::warn_objc_circular_container) - << ArgRE->getDecl() << StringRef("'super'"); - } - } - } else { - Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts(); - - if (OpaqueValueExpr *OE = dyn_cast(Receiver)) { - Receiver = OE->getSourceExpr()->IgnoreImpCasts(); - } - - if (DeclRefExpr *ReceiverRE = dyn_cast(Receiver)) { - if (DeclRefExpr *ArgRE = dyn_cast(Arg)) { - if (ReceiverRE->getDecl() == ArgRE->getDecl()) { - ValueDecl *Decl = ReceiverRE->getDecl(); - Diag(Message->getSourceRange().getBegin(), - diag::warn_objc_circular_container) - << Decl << Decl; - if (!ArgRE->isObjCSelfExpr()) { - Diag(Decl->getLocation(), - diag::note_objc_circular_container_declared_here) - << Decl; - } - } - } - } else if (ObjCIvarRefExpr *IvarRE = dyn_cast(Receiver)) { - if (ObjCIvarRefExpr *IvarArgRE = dyn_cast(Arg)) { - if (IvarRE->getDecl() == IvarArgRE->getDecl()) { - ObjCIvarDecl *Decl = IvarRE->getDecl(); - Diag(Message->getSourceRange().getBegin(), - diag::warn_objc_circular_container) - << Decl << Decl; - Diag(Decl->getLocation(), - diag::note_objc_circular_container_declared_here) - << Decl; - } - } - } - } -} - -/// Check a message send to see if it's likely to cause a retain cycle. -void Sema::checkRetainCycles(ObjCMessageExpr *msg) { - // Only check instance methods whose selector looks like a setter. - if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector())) - return; - - // Try to find a variable that the receiver is strongly owned by. - RetainCycleOwner owner; - if (msg->getReceiverKind() == ObjCMessageExpr::Instance) { - if (!findRetainCycleOwner(*this, msg->getInstanceReceiver(), owner)) - return; - } else { - assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance); - owner.Variable = getCurMethodDecl()->getSelfDecl(); - owner.Loc = msg->getSuperLoc(); - owner.Range = msg->getSuperLoc(); - } - - // Check whether the receiver is captured by any of the arguments. - const ObjCMethodDecl *MD = msg->getMethodDecl(); - for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i) { - if (Expr *capturer = findCapturingExpr(*this, msg->getArg(i), owner)) { - // noescape blocks should not be retained by the method. - if (MD && MD->parameters()[i]->hasAttr()) - continue; - return diagnoseRetainCycle(*this, capturer, owner); - } - } -} - -/// Check a property assign to see if it's likely to cause a retain cycle. -void Sema::checkRetainCycles(Expr *receiver, Expr *argument) { - RetainCycleOwner owner; - if (!findRetainCycleOwner(*this, receiver, owner)) - return; - - if (Expr *capturer = findCapturingExpr(*this, argument, owner)) - diagnoseRetainCycle(*this, capturer, owner); -} - -void Sema::checkRetainCycles(VarDecl *Var, Expr *Init) { - RetainCycleOwner Owner; - if (!considerVariable(Var, /*DeclRefExpr=*/nullptr, Owner)) - return; - - // Because we don't have an expression for the variable, we have to set the - // location explicitly here. - Owner.Loc = Var->getLocation(); - Owner.Range = Var->getSourceRange(); - - if (Expr *Capturer = findCapturingExpr(*this, Init, Owner)) - diagnoseRetainCycle(*this, Capturer, Owner); -} - static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc, Expr *RHS, bool isProperty) { // Check if RHS is an Objective-C object literal, which also can get @@ -19262,8 +18758,8 @@ static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc, // This enum needs to match with the 'select' in // warn_objc_arc_literal_assign (off-by-1). - Sema::ObjCLiteralKind Kind = S.CheckLiteralKind(RHS); - if (Kind == Sema::LK_String || Kind == Sema::LK_None) + SemaObjC::ObjCLiteralKind Kind = S.ObjC().CheckLiteralKind(RHS); + if (Kind == SemaObjC::LK_String || Kind == SemaObjC::LK_None) return false; S.Diag(Loc, diag::warn_arc_literal_assign) diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 87aa0cacc249..328641ed9488 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -42,6 +42,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallBitVector.h" @@ -5862,7 +5863,8 @@ void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S, SourceLocation ClassNameLoc, bool IsBaseExprStatement) { const IdentifierInfo *ClassNamePtr = &ClassName; - ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc); + ObjCInterfaceDecl *IFace = + ObjC().getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc); if (!IFace) return; CodeCompletionContext CCContext( @@ -8176,15 +8178,16 @@ AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, N = SemaRef.getExternalSource()->GetNumExternalSelectors(); I != N; ++I) { Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I); - if (Sel.isNull() || SemaRef.MethodPool.count(Sel)) + if (Sel.isNull() || SemaRef.ObjC().MethodPool.count(Sel)) continue; - SemaRef.ReadMethodPool(Sel); + SemaRef.ObjC().ReadMethodPool(Sel); } } - for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(), - MEnd = SemaRef.MethodPool.end(); + for (SemaObjC::GlobalMethodPool::iterator + M = SemaRef.ObjC().MethodPool.begin(), + MEnd = SemaRef.ObjC().MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = &M->second.second; MethList && MethList->getMethod(); MethList = MethList->getNext()) { @@ -8346,15 +8349,15 @@ void Sema::CodeCompleteObjCInstanceMessage( for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || MethodPool.count(Sel)) + if (Sel.isNull() || ObjC().MethodPool.count(Sel)) continue; - ReadMethodPool(Sel); + ObjC().ReadMethodPool(Sel); } } - for (GlobalMethodPool::iterator M = MethodPool.begin(), - MEnd = MethodPool.end(); + for (SemaObjC::GlobalMethodPool::iterator M = ObjC().MethodPool.begin(), + MEnd = ObjC().MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = &M->second.first; MethList && MethList->getMethod(); MethList = MethList->getNext()) { @@ -8417,10 +8420,10 @@ void Sema::CodeCompleteObjCSelector( for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || MethodPool.count(Sel)) + if (Sel.isNull() || ObjC().MethodPool.count(Sel)) continue; - ReadMethodPool(Sel); + ObjC().ReadMethodPool(Sel); } } @@ -8428,8 +8431,8 @@ void Sema::CodeCompleteObjCSelector( CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_SelectorName); Results.EnterNewScope(); - for (GlobalMethodPool::iterator M = MethodPool.begin(), - MEnd = MethodPool.end(); + for (SemaObjC::GlobalMethodPool::iterator M = ObjC().MethodPool.begin(), + MEnd = ObjC().MethodPool.end(); M != MEnd; ++M) { Selector Sel = M->first; @@ -8497,7 +8500,8 @@ void Sema::CodeCompleteObjCProtocolReferences( // already seen. // FIXME: This doesn't work when caching code-completion results. for (const IdentifierLocPair &Pair : Protocols) - if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second)) + if (ObjCProtocolDecl *Protocol = + ObjC().LookupProtocol(Pair.first, Pair.second)) Results.Ignore(Protocol); // Add all protocols. @@ -9755,10 +9759,10 @@ void Sema::CodeCompleteObjCMethodDeclSelector( for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || MethodPool.count(Sel)) + if (Sel.isNull() || ObjC().MethodPool.count(Sel)) continue; - ReadMethodPool(Sel); + ObjC().ReadMethodPool(Sel); } } @@ -9772,8 +9776,8 @@ void Sema::CodeCompleteObjCMethodDeclSelector( Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType()); Results.EnterNewScope(); - for (GlobalMethodPool::iterator M = MethodPool.begin(), - MEnd = MethodPool.end(); + for (SemaObjC::GlobalMethodPool::iterator M = ObjC().MethodPool.begin(), + MEnd = ObjC().MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first : &M->second.second; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index fb913034bd83..0dbdf923df95 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -48,6 +48,7 @@ #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLForwardCompat.h" @@ -915,7 +916,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, // FIXME: This lookup really, really needs to be folded in to the normal // unqualified lookup mechanism. if (SS.isEmpty() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { - DeclResult Ivar = LookupIvarInObjCMethod(Result, S, Name); + DeclResult Ivar = ObjC().LookupIvarInObjCMethod(Result, S, Name); if (Ivar.isInvalid()) return NameClassification::Error(); if (Ivar.isUsable()) @@ -1033,7 +1034,7 @@ Corrected: // FIXME: This is a gross hack. if (ObjCIvarDecl *Ivar = Result.getAsSingle()) { DeclResult R = - LookupIvarInObjCMethod(Result, S, Ivar->getIdentifier()); + ObjC().LookupIvarInObjCMethod(Result, S, Ivar->getIdentifier()); if (R.isInvalid()) return NameClassification::Error(); if (R.isUsable()) @@ -1271,7 +1272,7 @@ ExprResult Sema::ActOnNameClassifiedAsNonType(Scope *S, const CXXScopeSpec &SS, const Token &NextToken) { if (getCurMethodDecl() && SS.isEmpty()) if (auto *Ivar = dyn_cast(Found->getUnderlyingDecl())) - return BuildIvarRefExpr(S, NameLoc, Ivar); + return ObjC().BuildIvarRefExpr(S, NameLoc, Ivar); // Reconstruct the lookup result. LookupResult Result(*this, Found->getDeclName(), NameLoc, LookupOrdinaryName); @@ -2310,45 +2311,6 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { } } -/// Look for an Objective-C class in the translation unit. -/// -/// \param Id The name of the Objective-C class we're looking for. If -/// typo-correction fixes this name, the Id will be updated -/// to the fixed name. -/// -/// \param IdLoc The location of the name in the translation unit. -/// -/// \param DoTypoCorrection If true, this routine will attempt typo correction -/// if there is no class with the given name. -/// -/// \returns The declaration of the named Objective-C class, or NULL if the -/// class could not be found. -ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(const IdentifierInfo *&Id, - SourceLocation IdLoc, - bool DoTypoCorrection) { - // The third "scope" argument is 0 since we aren't enabling lazy built-in - // creation from this context. - NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName); - - if (!IDecl && DoTypoCorrection) { - // Perform typo correction at the given location, but only if we - // find an Objective-C class name. - DeclFilterCCC CCC{}; - if (TypoCorrection C = - CorrectTypo(DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName, - TUScope, nullptr, CCC, CTK_ErrorRecovery)) { - diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id); - IDecl = C.getCorrectionDeclAs(); - Id = IDecl->getIdentifier(); - } - } - ObjCInterfaceDecl *Def = dyn_cast_or_null(IDecl); - // This routine must always return a class definition, if any. - if (Def && Def->getDefinition()) - Def = Def->getDefinition(); - return Def; -} - /// getNonFieldDeclScope - Retrieves the innermost scope, starting /// from S, where a non-field would be declared. This routine copes /// with the difference between C and C++ scoping rules in structs and @@ -4415,7 +4377,7 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, ni != ne && oi != oe; ++ni, ++oi) mergeParamDeclAttributes(*ni, *oi, *this); - CheckObjCMethodOverride(newMethod, oldMethod); + ObjC().CheckObjCMethodOverride(newMethod, oldMethod); } static void diagnoseVarDeclTypeMismatch(Sema &S, VarDecl *New, VarDecl* Old) { @@ -6982,50 +6944,6 @@ static void SetNestedNameSpecifier(Sema &S, DeclaratorDecl *DD, Declarator &D) { DD->setQualifierInfo(SS.getWithLocInContext(S.Context)); } -bool Sema::inferObjCARCLifetime(ValueDecl *decl) { - QualType type = decl->getType(); - Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime(); - if (lifetime == Qualifiers::OCL_Autoreleasing) { - // Various kinds of declaration aren't allowed to be __autoreleasing. - unsigned kind = -1U; - if (VarDecl *var = dyn_cast(decl)) { - if (var->hasAttr()) - kind = 0; // __block - else if (!var->hasLocalStorage()) - kind = 1; // global - } else if (isa(decl)) { - kind = 3; // ivar - } else if (isa(decl)) { - kind = 2; // field - } - - if (kind != -1U) { - Diag(decl->getLocation(), diag::err_arc_autoreleasing_var) - << kind; - } - } else if (lifetime == Qualifiers::OCL_None) { - // Try to infer lifetime. - if (!type->isObjCLifetimeType()) - return false; - - lifetime = type->getObjCARCImplicitLifetime(); - type = Context.getLifetimeQualifiedType(type, lifetime); - decl->setType(type); - } - - if (VarDecl *var = dyn_cast(decl)) { - // Thread-local variables cannot have lifetime. - if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone && - var->getTLSKind()) { - Diag(var->getLocation(), diag::err_arc_thread_ownership) - << var->getType(); - return true; - } - } - - return false; -} - void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) { if (Decl->getType().hasAddressSpace()) return; @@ -8064,7 +7982,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( // In auto-retain/release, infer strong retension for variables of // retainable type. - if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD)) + if (getLangOpts().ObjCAutoRefCount && ObjC().inferObjCARCLifetime(NewVD)) NewVD->setInvalidDecl(); // Handle GNU asm-label extension (encoded as an attribute). @@ -10878,7 +10796,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // If there's a #pragma clang arc_cf_code_audited in scope, consider // marking the function. - AddCFAuditedAttribute(NewFD); + ObjC().AddCFAuditedAttribute(NewFD); // If this is a function definition, check if we have to apply any // attributes (i.e. optnone and no_builtin) due to a pragma. @@ -13208,7 +13126,7 @@ bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, assert(VDecl->isLinkageValid()); // In ARC, infer lifetime. - if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) + if (getLangOpts().ObjCAutoRefCount && ObjC().inferObjCARCLifetime(VDecl)) VDecl->setInvalidDecl(); if (getLangOpts().OpenCL) @@ -13783,7 +13701,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init); if (VDecl->hasAttr()) - checkRetainCycles(VDecl, Init); + ObjC().checkRetainCycles(VDecl, Init); // It is safe to assign a weak reference into a strong variable. // Although this code can still have problems: @@ -15337,37 +15255,6 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue( } } -QualType Sema::AdjustParameterTypeForObjCAutoRefCount(QualType T, - SourceLocation NameLoc, - TypeSourceInfo *TSInfo) { - // In ARC, infer a lifetime qualifier for appropriate parameter types. - if (!getLangOpts().ObjCAutoRefCount || - T.getObjCLifetime() != Qualifiers::OCL_None || !T->isObjCLifetimeType()) - return T; - - Qualifiers::ObjCLifetime Lifetime; - - // Special cases for arrays: - // - if it's const, use __unsafe_unretained - // - otherwise, it's an error - if (T->isArrayType()) { - if (!T.isConstQualified()) { - if (DelayedDiagnostics.shouldDelayDiagnostics()) - DelayedDiagnostics.add(sema::DelayedDiagnostic::makeForbiddenType( - NameLoc, diag::err_arc_array_param_no_ownership, T, false)); - else - Diag(NameLoc, diag::err_arc_array_param_no_ownership) - << TSInfo->getTypeLoc().getSourceRange(); - } - Lifetime = Qualifiers::OCL_ExplicitNone; - } else { - Lifetime = T->getObjCARCImplicitLifetime(); - } - T = Context.getLifetimeQualifiedType(T, Lifetime); - - return T; -} - ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, SourceLocation NameLoc, const IdentifierInfo *Name, QualType T, @@ -16401,7 +16288,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (!SuperD) return false; return SuperD->getIdentifier() == - NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject); + ObjC().NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject); }; // Don't issue this warning for unavailable inits or direct subclasses // of NSObject. @@ -18348,12 +18235,6 @@ bool Sema::ActOnDuplicateDefinition(Decl *Prev, SkipBodyInfo &SkipBody) { return true; } -void Sema::ActOnObjCContainerStartDefinition(ObjCContainerDecl *IDecl) { - assert(IDecl->getLexicalParent() == CurContext && - "The next DeclContext should be lexically contained in the current one."); - CurContext = IDecl; -} - void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, SourceLocation FinalLoc, bool IsFinalSpelledSealed, @@ -18455,22 +18336,6 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, } } -void Sema::ActOnObjCContainerFinishDefinition() { - // Exit this scope of this interface definition. - PopDeclContext(); -} - -void Sema::ActOnObjCTemporaryExitContainerContext(ObjCContainerDecl *ObjCCtx) { - assert(ObjCCtx == CurContext && "Mismatch of container contexts"); - OriginalLexicalContext = ObjCCtx; - ActOnObjCContainerFinishDefinition(); -} - -void Sema::ActOnObjCReenterContainerContext(ObjCContainerDecl *ObjCCtx) { - ActOnObjCContainerStartDefinition(ObjCCtx); - OriginalLexicalContext = nullptr; -} - void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { AdjustDeclIfTemplate(TagD); TagDecl *Tag = cast(TagD); @@ -18870,7 +18735,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // In auto-retain/release, infer strong retension for fields of // retainable type. - if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewFD)) + if (getLangOpts().ObjCAutoRefCount && ObjC().inferObjCARCLifetime(NewFD)) NewFD->setInvalidDecl(); if (T.isObjCGCWeak()) @@ -18948,132 +18813,6 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { return false; } -/// TranslateIvarVisibility - Translate visibility from a token ID to an -/// AST enum value. -static ObjCIvarDecl::AccessControl -TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { - switch (ivarVisibility) { - default: llvm_unreachable("Unknown visitibility kind"); - case tok::objc_private: return ObjCIvarDecl::Private; - case tok::objc_public: return ObjCIvarDecl::Public; - case tok::objc_protected: return ObjCIvarDecl::Protected; - case tok::objc_package: return ObjCIvarDecl::Package; - } -} - -/// ActOnIvar - Each ivar field of an objective-c class is passed into this -/// in order to create an IvarDecl object for it. -Decl *Sema::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, - Expr *BitWidth, tok::ObjCKeywordKind Visibility) { - - const IdentifierInfo *II = D.getIdentifier(); - SourceLocation Loc = DeclStart; - if (II) Loc = D.getIdentifierLoc(); - - // FIXME: Unnamed fields can be handled in various different ways, for - // example, unnamed unions inject all members into the struct namespace! - - TypeSourceInfo *TInfo = GetTypeForDeclarator(D); - QualType T = TInfo->getType(); - - if (BitWidth) { - // 6.7.2.1p3, 6.7.2.1p4 - BitWidth = VerifyBitField(Loc, II, T, /*IsMsStruct*/false, BitWidth).get(); - if (!BitWidth) - D.setInvalidType(); - } else { - // Not a bitfield. - - // validate II. - - } - if (T->isReferenceType()) { - Diag(Loc, diag::err_ivar_reference_type); - D.setInvalidType(); - } - // C99 6.7.2.1p8: A member of a structure or union may have any type other - // than a variably modified type. - else if (T->isVariablyModifiedType()) { - if (!tryToFixVariablyModifiedVarType( - TInfo, T, Loc, diag::err_typecheck_ivar_variable_size)) - D.setInvalidType(); - } - - // Get the visibility (access control) for this ivar. - ObjCIvarDecl::AccessControl ac = - Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility) - : ObjCIvarDecl::None; - // Must set ivar's DeclContext to its enclosing interface. - ObjCContainerDecl *EnclosingDecl = cast(CurContext); - if (!EnclosingDecl || EnclosingDecl->isInvalidDecl()) - return nullptr; - ObjCContainerDecl *EnclosingContext; - if (ObjCImplementationDecl *IMPDecl = - dyn_cast(EnclosingDecl)) { - if (LangOpts.ObjCRuntime.isFragile()) { - // Case of ivar declared in an implementation. Context is that of its class. - EnclosingContext = IMPDecl->getClassInterface(); - assert(EnclosingContext && "Implementation has no class interface!"); - } - else - EnclosingContext = EnclosingDecl; - } else { - if (ObjCCategoryDecl *CDecl = - dyn_cast(EnclosingDecl)) { - if (LangOpts.ObjCRuntime.isFragile() || !CDecl->IsClassExtension()) { - Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension(); - return nullptr; - } - } - EnclosingContext = EnclosingDecl; - } - - // Construct the decl. - ObjCIvarDecl *NewID = ObjCIvarDecl::Create( - Context, EnclosingContext, DeclStart, Loc, II, T, TInfo, ac, BitWidth); - - if (T->containsErrors()) - NewID->setInvalidDecl(); - - if (II) { - NamedDecl *PrevDecl = - LookupSingleName(S, II, Loc, LookupMemberName, - RedeclarationKind::ForVisibleRedeclaration); - if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S) - && !isa(PrevDecl)) { - Diag(Loc, diag::err_duplicate_member) << II; - Diag(PrevDecl->getLocation(), diag::note_previous_declaration); - NewID->setInvalidDecl(); - } - } - - // Process attributes attached to the ivar. - ProcessDeclAttributes(S, NewID, D); - - if (D.isInvalidType()) - NewID->setInvalidDecl(); - - // In ARC, infer 'retaining' for ivars of retainable type. - if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewID)) - NewID->setInvalidDecl(); - - if (D.getDeclSpec().isModulePrivateSpecified()) - NewID->setModulePrivate(); - - if (II) { - // FIXME: When interfaces are DeclContexts, we'll need to add - // these to the interface. - S->AddDecl(NewID); - IdResolver.AddDecl(NewID); - } - - if (LangOpts.ObjCRuntime.isNonFragile() && - !NewID->isInvalidDecl() && isa(EnclosingDecl)) - Diag(Loc, diag::warn_ivars_in_interface); - - return NewID; -} - /// ActOnLastBitfield - This routine handles synthesized bitfields rules for /// class and class extensions. For every class \@interface and class /// extension \@interface, if the last ivar is a bitfield of any type, @@ -19777,7 +19516,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Must enforce the rule that ivars in the base classes may not be // duplicates. if (ID->getSuperClass()) - DiagnoseDuplicateIvars(ID, ID->getSuperClass()); + ObjC().DiagnoseDuplicateIvars(ID, ID->getSuperClass()); } else if (ObjCImplementationDecl *IMPDecl = dyn_cast(EnclosingDecl)) { assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl"); @@ -19785,7 +19524,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Ivar declared in @implementation never belongs to the implementation. // Only it is in implementation's lexical context. ClsFields[I]->setLexicalDeclContext(IMPDecl); - CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac); + ObjC().CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), + RBrac); IMPDecl->setIvarLBraceLoc(LBrac); IMPDecl->setIvarRBraceLoc(RBrac); } else if (ObjCCategoryDecl *CDecl = @@ -20659,10 +20399,6 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, } } -ObjCContainerDecl *Sema::getObjCDeclContext() const { - return (dyn_cast_or_null(CurContext)); -} - Sema::FunctionEmissionStatus Sema::getEmissionStatus(const FunctionDecl *FD, bool Final) { assert(FD && "Expected non-null FunctionDecl"); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 6d957ac09e1c..777171f4f15f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -42,6 +42,7 @@ #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" @@ -6560,13 +6561,13 @@ static bool isErrorParameter(Sema &S, QualType QT) { // Check for NSError**. if (const auto *OPT = Pointee->getAs()) if (const auto *ID = OPT->getInterfaceDecl()) - if (ID->getIdentifier() == S.getNSErrorIdent()) + if (ID->getIdentifier() == S.ObjC().getNSErrorIdent()) return true; // Check for CFError**. if (const auto *PT = Pointee->getAs()) if (const auto *RT = PT->getPointeeType()->getAs()) - if (S.isCFError(RT->getDecl())) + if (S.ObjC().isCFError(RT->getDecl())) return true; return false; @@ -6697,7 +6698,7 @@ static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D, // Check for NSError *. if (const auto *ObjCPtrTy = Param->getAs()) { if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) { - if (ID->getIdentifier() == S.getNSErrorIdent()) { + if (ID->getIdentifier() == S.ObjC().getNSErrorIdent()) { AnyErrorParams = true; break; } @@ -6706,7 +6707,7 @@ static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D, // Check for CFError *. if (const auto *PtrTy = Param->getAs()) { if (const auto *RT = PtrTy->getPointeeType()->getAs()) { - if (S.isCFError(RT->getDecl())) { + if (S.ObjC().isCFError(RT->getDecl())) { AnyErrorParams = true; break; } @@ -8837,7 +8838,7 @@ static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD, Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime(); - // Sema::inferObjCARCLifetime must run after processing decl attributes + // SemaObjC::inferObjCARCLifetime must run after processing decl attributes // (because __block lowers to an attribute), so if the lifetime hasn't been // explicitly specified, infer it locally now. if (LifetimeQual == Qualifiers::OCL_None) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 53238d355ea0..822538198505 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -44,6 +44,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/Template.h" #include "llvm/ADT/ArrayRef.h" @@ -17054,7 +17055,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, ExDecl->setExceptionVariable(true); // In ARC, infer 'retaining' for variables of retainable type. - if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(ExDecl)) + if (getLangOpts().ObjCAutoRefCount && ObjC().inferObjCARCLifetime(ExDecl)) Invalid = true; if (!Invalid && !ExDeclType->isDependentType()) { @@ -18853,61 +18854,6 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, } } -/// SetIvarInitializers - This routine builds initialization ASTs for the -/// Objective-C implementation whose ivars need be initialized. -void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { - if (!getLangOpts().CPlusPlus) - return; - if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { - SmallVector ivars; - CollectIvarsToConstructOrDestruct(OID, ivars); - if (ivars.empty()) - return; - SmallVector AllToInit; - for (unsigned i = 0; i < ivars.size(); i++) { - FieldDecl *Field = ivars[i]; - if (Field->isInvalidDecl()) - continue; - - CXXCtorInitializer *Member; - InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field); - InitializationKind InitKind = - InitializationKind::CreateDefault(ObjCImplementation->getLocation()); - - InitializationSequence InitSeq(*this, InitEntity, InitKind, std::nullopt); - ExprResult MemberInit = - InitSeq.Perform(*this, InitEntity, InitKind, std::nullopt); - MemberInit = MaybeCreateExprWithCleanups(MemberInit); - // Note, MemberInit could actually come back empty if no initialization - // is required (e.g., because it would call a trivial default constructor) - if (!MemberInit.get() || MemberInit.isInvalid()) - continue; - - Member = - new (Context) CXXCtorInitializer(Context, Field, SourceLocation(), - SourceLocation(), - MemberInit.getAs(), - SourceLocation()); - AllToInit.push_back(Member); - - // Be sure that the destructor is accessible and is marked as referenced. - if (const RecordType *RecordTy = - Context.getBaseElementType(Field->getType()) - ->getAs()) { - CXXRecordDecl *RD = cast(RecordTy->getDecl()); - if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { - MarkFunctionReferenced(Field->getLocation(), Destructor); - CheckDestructorAccess(Field->getLocation(), Destructor, - PDiag(diag::err_access_dtor_ivar) - << Context.getBaseElementType(Field->getType())); - } - } - } - ObjCImplementation->setIvarInitializers(Context, - AllToInit.data(), AllToInit.size()); - } -} - static void DelegatingCycleHelper(CXXConstructorDecl* Ctor, llvm::SmallPtrSet &Valid, diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 934ba174a426..6d4379283f19 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -21,10 +21,13 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" @@ -39,8 +42,9 @@ using namespace clang; /// /// \return true to indicate that there was an error and appropriate /// actions were taken -bool Sema::checkInitMethod(ObjCMethodDecl *method, - QualType receiverTypeIfCall) { +bool SemaObjC::checkInitMethod(ObjCMethodDecl *method, + QualType receiverTypeIfCall) { + ASTContext &Context = getASTContext(); if (method->isInvalidDecl()) return true; // This castAs is safe: methods that don't return an object @@ -97,7 +101,8 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method, // If we're in a system header, and this is not a call, just make // the method unusable. - if (receiverTypeIfCall.isNull() && getSourceManager().isInSystemHeader(loc)) { + if (receiverTypeIfCall.isNull() && + SemaRef.getSourceManager().isInSystemHeader(loc)) { method->addAttr(UnavailableAttr::CreateImplicit(Context, "", UnavailableAttr::IR_ARCInitReturnsUnrelated, loc)); return true; @@ -133,8 +138,9 @@ static void diagnoseNoescape(const ParmVarDecl *NewD, const ParmVarDecl *OldD, << cast(NewD->getDeclContext()); } -void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, - const ObjCMethodDecl *Overridden) { +void SemaObjC::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, + const ObjCMethodDecl *Overridden) { + ASTContext &Context = getASTContext(); if (Overridden->hasRelatedResultType() && !NewMethod->hasRelatedResultType()) { // This can only happen when the method follows a naming convention that @@ -216,13 +222,14 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, Diag(oldDecl->getLocation(), diag::note_previous_decl) << "parameter"; } - diagnoseNoescape(newDecl, oldDecl, *this); + diagnoseNoescape(newDecl, oldDecl, SemaRef); } } /// Check a method declaration for compatibility with the Objective-C /// ARC conventions. -bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) { +bool SemaObjC::CheckARCMethodDecl(ObjCMethodDecl *method) { + ASTContext &Context = getASTContext(); ObjCMethodFamily family = method->getMethodFamily(); switch (family) { case OMF_None: @@ -326,7 +333,7 @@ static void DiagnoseObjCImplementedDeprecations(Sema &S, const NamedDecl *ND, /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global /// pool. -void Sema::AddAnyMethodToGlobalPool(Decl *D) { +void SemaObjC::AddAnyMethodToGlobalPool(Decl *D) { ObjCMethodDecl *MDecl = dyn_cast_or_null(D); // If we don't have a valid method decl, simply return. @@ -359,12 +366,14 @@ HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) { /// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible /// and user declared, in the method definition's AST. -void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { - ImplicitlyRetainedSelfLocs.clear(); - assert((getCurMethodDecl() == nullptr) && "Methodparsing confused"); +void SemaObjC::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { + ASTContext &Context = getASTContext(); + SemaRef.ImplicitlyRetainedSelfLocs.clear(); + assert((SemaRef.getCurMethodDecl() == nullptr) && "Methodparsing confused"); ObjCMethodDecl *MDecl = dyn_cast_or_null(D); - PushExpressionEvaluationContext(ExprEvalContexts.back().Context); + SemaRef.PushExpressionEvaluationContext( + SemaRef.ExprEvalContexts.back().Context); // If we don't have a valid method decl, simply return. if (!MDecl) @@ -373,13 +382,13 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { QualType ResultType = MDecl->getReturnType(); if (!ResultType->isDependentType() && !ResultType->isVoidType() && !MDecl->isInvalidDecl() && - RequireCompleteType(MDecl->getLocation(), ResultType, - diag::err_func_def_incomplete_result)) + SemaRef.RequireCompleteType(MDecl->getLocation(), ResultType, + diag::err_func_def_incomplete_result)) MDecl->setInvalidDecl(); // Allow all of Sema to see that we are entering a method definition. - PushDeclContext(FnBodyScope, MDecl); - PushFunctionScope(); + SemaRef.PushDeclContext(FnBodyScope, MDecl); + SemaRef.PushFunctionScope(); // Create Decl objects for each parameter, entrring them in the scope for // binding to their use. @@ -387,23 +396,22 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { // Insert the invisible arguments, self and _cmd! MDecl->createImplicitParams(Context, MDecl->getClassInterface()); - PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope); - PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope); + SemaRef.PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope); + SemaRef.PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope); // The ObjC parser requires parameter names so there's no need to check. - CheckParmsForFunctionDef(MDecl->parameters(), - /*CheckParameterNames=*/false); + SemaRef.CheckParmsForFunctionDef(MDecl->parameters(), + /*CheckParameterNames=*/false); // Introduce all of the other parameters into this scope. for (auto *Param : MDecl->parameters()) { - if (!Param->isInvalidDecl() && - getLangOpts().ObjCAutoRefCount && - !HasExplicitOwnershipAttr(*this, Param)) + if (!Param->isInvalidDecl() && getLangOpts().ObjCAutoRefCount && + !HasExplicitOwnershipAttr(SemaRef, Param)) Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) << Param->getType(); if (Param->getIdentifier()) - PushOnScopeChains(Param, FnBodyScope); + SemaRef.PushOnScopeChains(Param, FnBodyScope); } // In ARC, disallow definition of retain/release/autorelease/retainCount @@ -456,17 +464,17 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { // No need to issue deprecated warning if deprecated mehod in class/category // is being implemented in its own implementation (no overriding is involved). if (!ImplDeclOfMethodDecl || ImplDeclOfMethodDecl != ImplDeclOfMethodDef) - DiagnoseObjCImplementedDeprecations(*this, IMD, MDecl->getLocation()); + DiagnoseObjCImplementedDeprecations(SemaRef, IMD, MDecl->getLocation()); } if (MDecl->getMethodFamily() == OMF_init) { if (MDecl->isDesignatedInitializerForTheInterface()) { - getCurFunction()->ObjCIsDesignatedInit = true; - getCurFunction()->ObjCWarnForNoDesignatedInitChain = + SemaRef.getCurFunction()->ObjCIsDesignatedInit = true; + SemaRef.getCurFunction()->ObjCWarnForNoDesignatedInitChain = IC->getSuperClass() != nullptr; } else if (IC->hasDesignatedInitializers()) { - getCurFunction()->ObjCIsSecondaryInit = true; - getCurFunction()->ObjCWarnForNoInitDelegation = true; + SemaRef.getCurFunction()->ObjCIsSecondaryInit = true; + SemaRef.getCurFunction()->ObjCWarnForNoInitDelegation = true; } } @@ -479,25 +487,25 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { if (Family == OMF_dealloc) { if (!(getLangOpts().ObjCAutoRefCount || getLangOpts().getGC() == LangOptions::GCOnly)) - getCurFunction()->ObjCShouldCallSuper = true; + SemaRef.getCurFunction()->ObjCShouldCallSuper = true; } else if (Family == OMF_finalize) { if (Context.getLangOpts().getGC() != LangOptions::NonGC) - getCurFunction()->ObjCShouldCallSuper = true; + SemaRef.getCurFunction()->ObjCShouldCallSuper = true; } else { const ObjCMethodDecl *SuperMethod = SuperClass->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod()); - getCurFunction()->ObjCShouldCallSuper = - (SuperMethod && SuperMethod->hasAttr()); + SemaRef.getCurFunction()->ObjCShouldCallSuper = + (SuperMethod && SuperMethod->hasAttr()); } } } // Some function attributes (like OptimizeNoneAttr) need actions before // parsing body started. - applyFunctionAttributesBeforeParsingBody(D); + SemaRef.applyFunctionAttributesBeforeParsingBody(D); } namespace { @@ -542,29 +550,26 @@ static void diagnoseUseOfProtocols(Sema &TheSema, } } -void Sema:: -ActOnSuperClassOfClassInterface(Scope *S, - SourceLocation AtInterfaceLoc, - ObjCInterfaceDecl *IDecl, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - IdentifierInfo *SuperName, - SourceLocation SuperLoc, - ArrayRef SuperTypeArgs, - SourceRange SuperTypeArgsRange) { +void SemaObjC::ActOnSuperClassOfClassInterface( + Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange) { + ASTContext &Context = getASTContext(); // Check if a different kind of symbol declared in this scope. - NamedDecl *PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc, - LookupOrdinaryName); + NamedDecl *PrevDecl = SemaRef.LookupSingleName( + SemaRef.TUScope, SuperName, SuperLoc, Sema::LookupOrdinaryName); if (!PrevDecl) { // Try to correct for a typo in the superclass name without correcting // to the class we're defining. ObjCInterfaceValidatorCCC CCC(IDecl); - if (TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, - TUScope, nullptr, CCC, CTK_ErrorRecovery)) { - diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest) - << SuperName << ClassName); + if (TypoCorrection Corrected = SemaRef.CorrectTypo( + DeclarationNameInfo(SuperName, SuperLoc), Sema::LookupOrdinaryName, + SemaRef.TUScope, nullptr, CCC, Sema::CTK_ErrorRecovery)) { + SemaRef.diagnoseTypo(Corrected, + SemaRef.PDiag(diag::err_undef_superclass_suggest) + << SuperName << ClassName); PrevDecl = Corrected.getCorrectionDeclAs(); } } @@ -580,7 +585,7 @@ ActOnSuperClassOfClassInterface(Scope *S, // Diagnose classes that inherit from deprecated classes. if (SuperClassDecl) { - (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc); + (void)SemaRef.DiagnoseUseOfDecl(SuperClassDecl, SuperLoc); SuperClassType = Context.getObjCInterfaceType(SuperClassDecl); } @@ -599,7 +604,8 @@ ActOnSuperClassOfClassInterface(Scope *S, // @interface NewI @end // typedef NewI DeprI __attribute__((deprecated("blah"))) // @interface SI : DeprI /* warn here */ @end - (void)DiagnoseUseOfDecl(const_cast(TDecl), SuperLoc); + (void)SemaRef.DiagnoseUseOfDecl( + const_cast(TDecl), SuperLoc); } } } @@ -619,12 +625,10 @@ ActOnSuperClassOfClassInterface(Scope *S, if (!SuperClassDecl) Diag(SuperLoc, diag::err_undef_superclass) << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); - else if (RequireCompleteType(SuperLoc, - SuperClassType, - diag::err_forward_superclass, - SuperClassDecl->getDeclName(), - ClassName, - SourceRange(AtInterfaceLoc, ClassLoc))) { + else if (SemaRef.RequireCompleteType( + SuperLoc, SuperClassType, diag::err_forward_superclass, + SuperClassDecl->getDeclName(), ClassName, + SourceRange(AtInterfaceLoc, ClassLoc))) { SuperClassDecl = nullptr; SuperClassType = QualType(); } @@ -639,22 +643,15 @@ ActOnSuperClassOfClassInterface(Scope *S, TypeSourceInfo *SuperClassTInfo = nullptr; if (!SuperTypeArgs.empty()) { TypeResult fullSuperClassType = actOnObjCTypeArgsAndProtocolQualifiers( - S, - SuperLoc, - CreateParsedType(SuperClassType, - nullptr), - SuperTypeArgsRange.getBegin(), - SuperTypeArgs, - SuperTypeArgsRange.getEnd(), - SourceLocation(), - { }, - { }, - SourceLocation()); + S, SuperLoc, SemaRef.CreateParsedType(SuperClassType, nullptr), + SuperTypeArgsRange.getBegin(), SuperTypeArgs, + SuperTypeArgsRange.getEnd(), SourceLocation(), {}, {}, + SourceLocation()); if (!fullSuperClassType.isUsable()) return; - SuperClassType = GetTypeFromParser(fullSuperClassType.get(), - &SuperClassTInfo); + SuperClassType = + SemaRef.GetTypeFromParser(fullSuperClassType.get(), &SuperClassTInfo); } if (!SuperClassTInfo) { @@ -667,26 +664,24 @@ ActOnSuperClassOfClassInterface(Scope *S, } } -DeclResult Sema::actOnObjCTypeParam(Scope *S, - ObjCTypeParamVariance variance, - SourceLocation varianceLoc, - unsigned index, - IdentifierInfo *paramName, - SourceLocation paramLoc, - SourceLocation colonLoc, - ParsedType parsedTypeBound) { +DeclResult SemaObjC::actOnObjCTypeParam( + Scope *S, ObjCTypeParamVariance variance, SourceLocation varianceLoc, + unsigned index, IdentifierInfo *paramName, SourceLocation paramLoc, + SourceLocation colonLoc, ParsedType parsedTypeBound) { + ASTContext &Context = getASTContext(); // If there was an explicitly-provided type bound, check it. TypeSourceInfo *typeBoundInfo = nullptr; if (parsedTypeBound) { // The type bound can be any Objective-C pointer type. - QualType typeBound = GetTypeFromParser(parsedTypeBound, &typeBoundInfo); + QualType typeBound = + SemaRef.GetTypeFromParser(parsedTypeBound, &typeBoundInfo); if (typeBound->isObjCObjectPointerType()) { // okay } else if (typeBound->isObjCObjectType()) { // The user forgot the * on an Objective-C pointer type, e.g., // "T : NSView". - SourceLocation starLoc = getLocForEndOfToken( - typeBoundInfo->getTypeLoc().getEndLoc()); + SourceLocation starLoc = + SemaRef.getLocForEndOfToken(typeBoundInfo->getTypeLoc().getEndLoc()); Diag(typeBoundInfo->getTypeLoc().getBeginLoc(), diag::err_objc_type_param_bound_missing_pointer) << typeBound << paramName @@ -766,15 +761,16 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S, } // Create the type parameter. - return ObjCTypeParamDecl::Create(Context, CurContext, variance, varianceLoc, - index, paramLoc, paramName, colonLoc, - typeBoundInfo); + return ObjCTypeParamDecl::Create(Context, SemaRef.CurContext, variance, + varianceLoc, index, paramLoc, paramName, + colonLoc, typeBoundInfo); } -ObjCTypeParamList *Sema::actOnObjCTypeParamList(Scope *S, - SourceLocation lAngleLoc, - ArrayRef typeParamsIn, - SourceLocation rAngleLoc) { +ObjCTypeParamList * +SemaObjC::actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc, + ArrayRef typeParamsIn, + SourceLocation rAngleLoc) { + ASTContext &Context = getASTContext(); // We know that the array only contains Objective-C type parameters. ArrayRef typeParams( @@ -798,7 +794,7 @@ ObjCTypeParamList *Sema::actOnObjCTypeParamList(Scope *S, knownParams.insert(std::make_pair(typeParam->getIdentifier(), typeParam)); // Push the type parameter into scope. - PushOnScopeChains(typeParam, S, /*AddToContext=*/false); + SemaRef.PushOnScopeChains(typeParam, S, /*AddToContext=*/false); } } @@ -806,11 +802,12 @@ ObjCTypeParamList *Sema::actOnObjCTypeParamList(Scope *S, return ObjCTypeParamList::create(Context, lAngleLoc, typeParams, rAngleLoc); } -void Sema::popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList) { +void SemaObjC::popObjCTypeParamList(Scope *S, + ObjCTypeParamList *typeParamList) { for (auto *typeParam : *typeParamList) { if (!typeParam->isInvalidDecl()) { S->RemoveDecl(typeParam); - IdResolver.RemoveDecl(typeParam); + SemaRef.IdResolver.RemoveDecl(typeParam); } } } @@ -975,7 +972,7 @@ static bool checkTypeParamListConsistency(Sema &S, return false; } -ObjCInterfaceDecl *Sema::ActOnStartClassInterface( +ObjCInterfaceDecl *SemaObjC::ActOnStartClassInterface( Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, IdentifierInfo *SuperName, SourceLocation SuperLoc, @@ -985,10 +982,11 @@ ObjCInterfaceDecl *Sema::ActOnStartClassInterface( const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) { assert(ClassName && "Missing class identifier"); + ASTContext &Context = getASTContext(); // Check for another declaration kind with the same name. - NamedDecl *PrevDecl = - LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, - forRedeclarationInCurContext()); + NamedDecl *PrevDecl = SemaRef.LookupSingleName( + SemaRef.TUScope, ClassName, ClassLoc, Sema::LookupOrdinaryName, + SemaRef.forRedeclarationInCurContext()); if (PrevDecl && !isa(PrevDecl)) { Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; @@ -1020,7 +1018,7 @@ ObjCInterfaceDecl *Sema::ActOnStartClassInterface( if (ObjCTypeParamList *prevTypeParamList = PrevIDecl->getTypeParamList()) { if (typeParamList) { // Both have type parameter lists; check for consistency. - if (checkTypeParamListConsistency(*this, prevTypeParamList, + if (checkTypeParamListConsistency(SemaRef, prevTypeParamList, typeParamList, TypeParamListContext::Definition)) { typeParamList = nullptr; @@ -1034,17 +1032,12 @@ ObjCInterfaceDecl *Sema::ActOnStartClassInterface( // Clone the type parameter list. SmallVector clonedTypeParams; for (auto *typeParam : *prevTypeParamList) { - clonedTypeParams.push_back( - ObjCTypeParamDecl::Create( - Context, - CurContext, - typeParam->getVariance(), - SourceLocation(), - typeParam->getIndex(), - SourceLocation(), - typeParam->getIdentifier(), - SourceLocation(), - Context.getTrivialTypeSourceInfo(typeParam->getUnderlyingType()))); + clonedTypeParams.push_back(ObjCTypeParamDecl::Create( + Context, SemaRef.CurContext, typeParam->getVariance(), + SourceLocation(), typeParam->getIndex(), SourceLocation(), + typeParam->getIdentifier(), SourceLocation(), + Context.getTrivialTypeSourceInfo( + typeParam->getUnderlyingType()))); } typeParamList = ObjCTypeParamList::create(Context, @@ -1055,13 +1048,13 @@ ObjCInterfaceDecl *Sema::ActOnStartClassInterface( } } - ObjCInterfaceDecl *IDecl - = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName, - typeParamList, PrevIDecl, ClassLoc); + ObjCInterfaceDecl *IDecl = + ObjCInterfaceDecl::Create(Context, SemaRef.CurContext, AtInterfaceLoc, + ClassName, typeParamList, PrevIDecl, ClassLoc); if (PrevIDecl) { // Class already seen. Was it a definition? if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) { - if (SkipBody && !hasVisibleDefinition(Def)) { + if (SkipBody && !SemaRef.hasVisibleDefinition(Def)) { SkipBody->CheckSameAsPrevious = true; SkipBody->New = IDecl; SkipBody->Previous = Def; @@ -1074,15 +1067,15 @@ ObjCInterfaceDecl *Sema::ActOnStartClassInterface( } } - ProcessDeclAttributeList(TUScope, IDecl, AttrList); - AddPragmaAttributes(TUScope, IDecl); - ProcessAPINotes(IDecl); + SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, IDecl, AttrList); + SemaRef.AddPragmaAttributes(SemaRef.TUScope, IDecl); + SemaRef.ProcessAPINotes(IDecl); // Merge attributes from previous declarations. if (PrevIDecl) - mergeDeclAttributes(IDecl, PrevIDecl); + SemaRef.mergeDeclAttributes(IDecl, PrevIDecl); - PushOnScopeChains(IDecl, TUScope); + SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope); // Start the definition of this class. If we're in a redefinition case, there // may already be a definition, so we'll end up adding to it. @@ -1093,7 +1086,7 @@ ObjCInterfaceDecl *Sema::ActOnStartClassInterface( if (SuperName) { // Diagnose availability in the context of the @interface. - ContextRAII SavedContext(*this, IDecl); + Sema::ContextRAII SavedContext(SemaRef, IDecl); ActOnSuperClassOfClassInterface(S, AtInterfaceLoc, IDecl, ClassName, ClassLoc, @@ -1105,7 +1098,7 @@ ObjCInterfaceDecl *Sema::ActOnStartClassInterface( // Check then save referenced protocols. if (NumProtoRefs) { - diagnoseUseOfProtocols(*this, IDecl, (ObjCProtocolDecl*const*)ProtoRefs, + diagnoseUseOfProtocols(SemaRef, IDecl, (ObjCProtocolDecl *const *)ProtoRefs, NumProtoRefs, ProtoLocs); IDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); @@ -1120,14 +1113,14 @@ ObjCInterfaceDecl *Sema::ActOnStartClassInterface( /// ActOnTypedefedProtocols - this action finds protocol list as part of the /// typedef'ed use for a qualified super class and adds them to the list /// of the protocols. -void Sema::ActOnTypedefedProtocols(SmallVectorImpl &ProtocolRefs, - SmallVectorImpl &ProtocolLocs, - IdentifierInfo *SuperName, - SourceLocation SuperLoc) { +void SemaObjC::ActOnTypedefedProtocols( + SmallVectorImpl &ProtocolRefs, + SmallVectorImpl &ProtocolLocs, IdentifierInfo *SuperName, + SourceLocation SuperLoc) { if (!SuperName) return; - NamedDecl* IDecl = LookupSingleName(TUScope, SuperName, SuperLoc, - LookupOrdinaryName); + NamedDecl *IDecl = SemaRef.LookupSingleName( + SemaRef.TUScope, SuperName, SuperLoc, Sema::LookupOrdinaryName); if (!IDecl) return; @@ -1147,33 +1140,34 @@ void Sema::ActOnTypedefedProtocols(SmallVectorImpl &ProtocolRefs, /// ActOnCompatibilityAlias - this action is called after complete parsing of /// a \@compatibility_alias declaration. It sets up the alias relationships. -Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc, - IdentifierInfo *AliasName, - SourceLocation AliasLocation, - IdentifierInfo *ClassName, - SourceLocation ClassLocation) { +Decl *SemaObjC::ActOnCompatibilityAlias(SourceLocation AtLoc, + IdentifierInfo *AliasName, + SourceLocation AliasLocation, + IdentifierInfo *ClassName, + SourceLocation ClassLocation) { + ASTContext &Context = getASTContext(); // Look for previous declaration of alias name - NamedDecl *ADecl = - LookupSingleName(TUScope, AliasName, AliasLocation, LookupOrdinaryName, - forRedeclarationInCurContext()); + NamedDecl *ADecl = SemaRef.LookupSingleName( + SemaRef.TUScope, AliasName, AliasLocation, Sema::LookupOrdinaryName, + SemaRef.forRedeclarationInCurContext()); if (ADecl) { Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName; Diag(ADecl->getLocation(), diag::note_previous_declaration); return nullptr; } // Check for class declaration - NamedDecl *CDeclU = - LookupSingleName(TUScope, ClassName, ClassLocation, LookupOrdinaryName, - forRedeclarationInCurContext()); + NamedDecl *CDeclU = SemaRef.LookupSingleName( + SemaRef.TUScope, ClassName, ClassLocation, Sema::LookupOrdinaryName, + SemaRef.forRedeclarationInCurContext()); if (const TypedefNameDecl *TDecl = dyn_cast_or_null(CDeclU)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { if (NamedDecl *IDecl = T->castAs()->getInterface()) { ClassName = IDecl->getIdentifier(); - CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, - LookupOrdinaryName, - forRedeclarationInCurContext()); + CDeclU = SemaRef.LookupSingleName( + SemaRef.TUScope, ClassName, ClassLocation, Sema::LookupOrdinaryName, + SemaRef.forRedeclarationInCurContext()); } } } @@ -1186,25 +1180,23 @@ Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc, } // Everything checked out, instantiate a new alias declaration AST. - ObjCCompatibleAliasDecl *AliasDecl = - ObjCCompatibleAliasDecl::Create(Context, CurContext, AtLoc, AliasName, CDecl); + ObjCCompatibleAliasDecl *AliasDecl = ObjCCompatibleAliasDecl::Create( + Context, SemaRef.CurContext, AtLoc, AliasName, CDecl); if (!CheckObjCDeclScope(AliasDecl)) - PushOnScopeChains(AliasDecl, TUScope); + SemaRef.PushOnScopeChains(AliasDecl, SemaRef.TUScope); return AliasDecl; } -bool Sema::CheckForwardProtocolDeclarationForCircularDependency( - IdentifierInfo *PName, - SourceLocation &Ploc, SourceLocation PrevLoc, - const ObjCList &PList) { +bool SemaObjC::CheckForwardProtocolDeclarationForCircularDependency( + IdentifierInfo *PName, SourceLocation &Ploc, SourceLocation PrevLoc, + const ObjCList &PList) { bool res = false; for (ObjCList::iterator I = PList.begin(), E = PList.end(); I != E; ++I) { - if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(), - Ploc)) { + if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(), Ploc)) { if (PDecl->getIdentifier() == PName) { Diag(Ploc, diag::err_protocol_has_circular_dependency); Diag(PrevLoc, diag::note_previous_definition); @@ -1222,27 +1214,28 @@ bool Sema::CheckForwardProtocolDeclarationForCircularDependency( return res; } -ObjCProtocolDecl *Sema::ActOnStartProtocolInterface( +ObjCProtocolDecl *SemaObjC::ActOnStartProtocolInterface( SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs, const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) { + ASTContext &Context = getASTContext(); bool err = false; // FIXME: Deal with AttrList. assert(ProtocolName && "Missing protocol identifier"); - ObjCProtocolDecl *PrevDecl = LookupProtocol(ProtocolName, ProtocolLoc, - forRedeclarationInCurContext()); + ObjCProtocolDecl *PrevDecl = LookupProtocol( + ProtocolName, ProtocolLoc, SemaRef.forRedeclarationInCurContext()); ObjCProtocolDecl *PDecl = nullptr; if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : nullptr) { // Create a new protocol that is completely distinct from previous // declarations, and do not make this protocol available for name lookup. // That way, we'll end up completely ignoring the duplicate. // FIXME: Can we turn this into an error? - PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, + PDecl = ObjCProtocolDecl::Create(Context, SemaRef.CurContext, ProtocolName, ProtocolLoc, AtProtoInterfaceLoc, /*PrevDecl=*/Def); - if (SkipBody && !hasVisibleDefinition(Def)) { + if (SkipBody && !SemaRef.hasVisibleDefinition(Def)) { SkipBody->CheckSameAsPrevious = true; SkipBody->New = PDecl; SkipBody->Previous = Def; @@ -1255,7 +1248,7 @@ ObjCProtocolDecl *Sema::ActOnStartProtocolInterface( // If we are using modules, add the decl to the context in order to // serialize something meaningful. if (getLangOpts().Modules) - PushOnScopeChains(PDecl, TUScope); + SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope); PDecl->startDuplicateDefinitionForComparison(); } else { if (PrevDecl) { @@ -1268,25 +1261,25 @@ ObjCProtocolDecl *Sema::ActOnStartProtocolInterface( } // Create the new declaration. - PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, + PDecl = ObjCProtocolDecl::Create(Context, SemaRef.CurContext, ProtocolName, ProtocolLoc, AtProtoInterfaceLoc, /*PrevDecl=*/PrevDecl); - PushOnScopeChains(PDecl, TUScope); + SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope); PDecl->startDefinition(); } - ProcessDeclAttributeList(TUScope, PDecl, AttrList); - AddPragmaAttributes(TUScope, PDecl); - ProcessAPINotes(PDecl); + SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, PDecl, AttrList); + SemaRef.AddPragmaAttributes(SemaRef.TUScope, PDecl); + SemaRef.ProcessAPINotes(PDecl); // Merge attributes from previous declarations. if (PrevDecl) - mergeDeclAttributes(PDecl, PrevDecl); + SemaRef.mergeDeclAttributes(PDecl, PrevDecl); if (!err && NumProtoRefs ) { /// Check then save referenced protocols. - diagnoseUseOfProtocols(*this, PDecl, (ObjCProtocolDecl*const*)ProtoRefs, + diagnoseUseOfProtocols(SemaRef, PDecl, (ObjCProtocolDecl *const *)ProtoRefs, NumProtoRefs, ProtoLocs); PDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); @@ -1316,20 +1309,22 @@ static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl, /// FindProtocolDeclaration - This routine looks up protocols and /// issues an error if they are not declared. It returns list of /// protocol declarations in its 'Protocols' argument. -void -Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, - ArrayRef ProtocolId, - SmallVectorImpl &Protocols) { +void SemaObjC::FindProtocolDeclaration(bool WarnOnDeclarations, + bool ForObjCContainer, + ArrayRef ProtocolId, + SmallVectorImpl &Protocols) { for (const IdentifierLocPair &Pair : ProtocolId) { ObjCProtocolDecl *PDecl = LookupProtocol(Pair.first, Pair.second); if (!PDecl) { DeclFilterCCC CCC{}; - TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(Pair.first, Pair.second), LookupObjCProtocolName, - TUScope, nullptr, CCC, CTK_ErrorRecovery); + TypoCorrection Corrected = + SemaRef.CorrectTypo(DeclarationNameInfo(Pair.first, Pair.second), + Sema::LookupObjCProtocolName, SemaRef.TUScope, + nullptr, CCC, Sema::CTK_ErrorRecovery); if ((PDecl = Corrected.getCorrectionDeclAs())) - diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest) - << Pair.first); + SemaRef.diagnoseTypo( + Corrected, SemaRef.PDiag(diag::err_undeclared_protocol_suggest) + << Pair.first); } if (!PDecl) { @@ -1343,7 +1338,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, // For an objc container, delay protocol reference checking until after we // can set the objc decl as the availability context, otherwise check now. if (!ForObjCContainer) { - (void)DiagnoseUseOfDecl(PDecl, Pair.second); + (void)SemaRef.DiagnoseUseOfDecl(PDecl, Pair.second); } // If this is a forward declaration and we are supposed to warn in this @@ -1419,30 +1414,25 @@ class ObjCTypeArgOrProtocolValidatorCCC final }; } // end anonymous namespace -void Sema::DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId, - SourceLocation ProtocolLoc, - IdentifierInfo *TypeArgId, - SourceLocation TypeArgLoc, - bool SelectProtocolFirst) { +void SemaObjC::DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId, + SourceLocation ProtocolLoc, + IdentifierInfo *TypeArgId, + SourceLocation TypeArgLoc, + bool SelectProtocolFirst) { Diag(TypeArgLoc, diag::err_objc_type_args_and_protocols) << SelectProtocolFirst << TypeArgId << ProtocolId << SourceRange(ProtocolLoc); } -void Sema::actOnObjCTypeArgsOrProtocolQualifiers( - Scope *S, - ParsedType baseType, - SourceLocation lAngleLoc, - ArrayRef identifiers, - ArrayRef identifierLocs, - SourceLocation rAngleLoc, - SourceLocation &typeArgsLAngleLoc, - SmallVectorImpl &typeArgs, - SourceLocation &typeArgsRAngleLoc, - SourceLocation &protocolLAngleLoc, - SmallVectorImpl &protocols, - SourceLocation &protocolRAngleLoc, - bool warnOnIncompleteProtocols) { +void SemaObjC::actOnObjCTypeArgsOrProtocolQualifiers( + Scope *S, ParsedType baseType, SourceLocation lAngleLoc, + ArrayRef identifiers, + ArrayRef identifierLocs, SourceLocation rAngleLoc, + SourceLocation &typeArgsLAngleLoc, SmallVectorImpl &typeArgs, + SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc, + SmallVectorImpl &protocols, SourceLocation &protocolRAngleLoc, + bool warnOnIncompleteProtocols) { + ASTContext &Context = getASTContext(); // Local function that updates the declaration specifiers with // protocol information. unsigned numProtocolsResolved = 0; @@ -1453,7 +1443,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // which case we want to warn about typos such as // "NSArray" (that should be NSArray). ObjCInterfaceDecl *baseClass = nullptr; - QualType base = GetTypeFromParser(baseType, nullptr); + QualType base = SemaRef.GetTypeFromParser(baseType, nullptr); bool allAreTypeNames = false; SourceLocation firstClassNameLoc; if (!base.isNull()) { @@ -1476,7 +1466,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // For an objc container, delay protocol reference checking until after we // can set the objc decl as the availability context, otherwise check now. if (!warnOnIncompleteProtocols) { - (void)DiagnoseUseOfDecl(proto, identifierLocs[i]); + (void)SemaRef.DiagnoseUseOfDecl(proto, identifierLocs[i]); } // If this is a forward protocol declaration, get its definition. @@ -1499,8 +1489,9 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // about such things), check whether this name refers to a type // as well. if (allAreTypeNames) { - if (auto *decl = LookupSingleName(S, identifiers[i], identifierLocs[i], - LookupOrdinaryName)) { + if (auto *decl = + SemaRef.LookupSingleName(S, identifiers[i], identifierLocs[i], + Sema::LookupOrdinaryName)) { if (isa(decl)) { if (firstClassNameLoc.isInvalid()) firstClassNameLoc = identifierLocs[i]; @@ -1531,9 +1522,9 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( if (allProtocolsDeclared) { Diag(firstClassNameLoc, diag::warn_objc_redundant_qualified_class_type) - << baseClass->getDeclName() << SourceRange(lAngleLoc, rAngleLoc) - << FixItHint::CreateInsertion(getLocForEndOfToken(firstClassNameLoc), - " *"); + << baseClass->getDeclName() << SourceRange(lAngleLoc, rAngleLoc) + << FixItHint::CreateInsertion( + SemaRef.getLocForEndOfToken(firstClassNameLoc), " *"); } } @@ -1562,8 +1553,8 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( SmallVector typeDecls; unsigned numTypeDeclsResolved = 0; for (unsigned i = 0, n = identifiers.size(); i != n; ++i) { - NamedDecl *decl = LookupSingleName(S, identifiers[i], identifierLocs[i], - LookupOrdinaryName); + NamedDecl *decl = SemaRef.LookupSingleName( + S, identifiers[i], identifierLocs[i], Sema::LookupOrdinaryName); if (!decl) { typeDecls.push_back(TypeOrClassDecl()); continue; @@ -1600,7 +1591,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( else type = Context.getObjCInterfaceType(typeDecl.get()); TypeSourceInfo *parsedTSInfo = Context.getTrivialTypeSourceInfo(type, loc); - ParsedType parsedType = CreateParsedType(type, parsedTSInfo); + ParsedType parsedType = SemaRef.CreateParsedType(type, parsedTSInfo); DS.SetTypeSpecType(DeclSpec::TST_typename, loc, prevSpec, diagID, parsedType, Context.getPrintingPolicy()); // Use the identifier location for the type source range. @@ -1613,7 +1604,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // If we have a typedef of an Objective-C class type that is missing a '*', // add the '*'. if (type->getAs()) { - SourceLocation starLoc = getLocForEndOfToken(loc); + SourceLocation starLoc = SemaRef.getLocForEndOfToken(loc); D.AddTypeInfo(DeclaratorChunk::getPointer(/*TypeQuals=*/0, starLoc, SourceLocation(), SourceLocation(), @@ -1629,7 +1620,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( } // Convert this to a type. - return ActOnTypeName(D); + return SemaRef.ActOnTypeName(D); }; // Local function that updates the declaration specifiers with @@ -1663,14 +1654,14 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // Error recovery: some names weren't found, or we have a mix of // type and protocol names. Go resolve all of the unresolved names // and complain if we can't find a consistent answer. - LookupNameKind lookupKind = LookupAnyName; + Sema::LookupNameKind lookupKind = Sema::LookupAnyName; for (unsigned i = 0, n = identifiers.size(); i != n; ++i) { // If we already have a protocol or type. Check whether it is the // right thing. if (protocols[i] || typeDecls[i]) { // If we haven't figured out whether we want types or protocols // yet, try to figure it out from this name. - if (lookupKind == LookupAnyName) { + if (lookupKind == Sema::LookupAnyName) { // If this name refers to both a protocol and a type (e.g., \c // NSObject), don't conclude anything yet. if (protocols[i] && typeDecls[i]) @@ -1678,19 +1669,19 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // Otherwise, let this name decide whether we'll be correcting // toward types or protocols. - lookupKind = protocols[i] ? LookupObjCProtocolName - : LookupOrdinaryName; + lookupKind = protocols[i] ? Sema::LookupObjCProtocolName + : Sema::LookupOrdinaryName; continue; } // If we want protocols and we have a protocol, there's nothing // more to do. - if (lookupKind == LookupObjCProtocolName && protocols[i]) + if (lookupKind == Sema::LookupObjCProtocolName && protocols[i]) continue; // If we want types and we have a type declaration, there's // nothing more to do. - if (lookupKind == LookupOrdinaryName && typeDecls[i]) + if (lookupKind == Sema::LookupOrdinaryName && typeDecls[i]) continue; // We have a conflict: some names refer to protocols and others @@ -1706,16 +1697,16 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // Perform typo correction on the name. ObjCTypeArgOrProtocolValidatorCCC CCC(Context, lookupKind); - TypoCorrection corrected = - CorrectTypo(DeclarationNameInfo(identifiers[i], identifierLocs[i]), - lookupKind, S, nullptr, CCC, CTK_ErrorRecovery); + TypoCorrection corrected = SemaRef.CorrectTypo( + DeclarationNameInfo(identifiers[i], identifierLocs[i]), lookupKind, S, + nullptr, CCC, Sema::CTK_ErrorRecovery); if (corrected) { // Did we find a protocol? if (auto proto = corrected.getCorrectionDeclAs()) { - diagnoseTypo(corrected, - PDiag(diag::err_undeclared_protocol_suggest) - << identifiers[i]); - lookupKind = LookupObjCProtocolName; + SemaRef.diagnoseTypo( + corrected, SemaRef.PDiag(diag::err_undeclared_protocol_suggest) + << identifiers[i]); + lookupKind = Sema::LookupObjCProtocolName; protocols[i] = proto; ++numProtocolsResolved; continue; @@ -1723,10 +1714,10 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // Did we find a type? if (auto typeDecl = corrected.getCorrectionDeclAs()) { - diagnoseTypo(corrected, - PDiag(diag::err_unknown_typename_suggest) - << identifiers[i]); - lookupKind = LookupOrdinaryName; + SemaRef.diagnoseTypo(corrected, + SemaRef.PDiag(diag::err_unknown_typename_suggest) + << identifiers[i]); + lookupKind = Sema::LookupOrdinaryName; typeDecls[i] = typeDecl; ++numTypeDeclsResolved; continue; @@ -1734,10 +1725,11 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // Did we find an Objective-C class? if (auto objcClass = corrected.getCorrectionDeclAs()) { - diagnoseTypo(corrected, - PDiag(diag::err_unknown_type_or_class_name_suggest) - << identifiers[i] << true); - lookupKind = LookupOrdinaryName; + SemaRef.diagnoseTypo( + corrected, + SemaRef.PDiag(diag::err_unknown_type_or_class_name_suggest) + << identifiers[i] << true); + lookupKind = Sema::LookupOrdinaryName; typeDecls[i] = objcClass; ++numTypeDeclsResolved; continue; @@ -1746,10 +1738,11 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // We couldn't find anything. Diag(identifierLocs[i], - (lookupKind == LookupAnyName ? diag::err_objc_type_arg_missing - : lookupKind == LookupObjCProtocolName ? diag::err_undeclared_protocol - : diag::err_unknown_typename)) - << identifiers[i]; + (lookupKind == Sema::LookupAnyName ? diag::err_objc_type_arg_missing + : lookupKind == Sema::LookupObjCProtocolName + ? diag::err_undeclared_protocol + : diag::err_unknown_typename)) + << identifiers[i]; protocols.clear(); typeArgs.clear(); return; @@ -1768,8 +1761,8 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( /// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of /// a class method in its extension. /// -void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, - ObjCInterfaceDecl *ID) { +void SemaObjC::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, + ObjCInterfaceDecl *ID) { if (!ID) return; // Possibly due to previous error @@ -1792,59 +1785,59 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, } /// ActOnForwardProtocolDeclaration - Handle \@protocol foo; -Sema::DeclGroupPtrTy -Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, - ArrayRef IdentList, - const ParsedAttributesView &attrList) { +SemaObjC::DeclGroupPtrTy SemaObjC::ActOnForwardProtocolDeclaration( + SourceLocation AtProtocolLoc, ArrayRef IdentList, + const ParsedAttributesView &attrList) { + ASTContext &Context = getASTContext(); SmallVector DeclsInGroup; for (const IdentifierLocPair &IdentPair : IdentList) { IdentifierInfo *Ident = IdentPair.first; - ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentPair.second, - forRedeclarationInCurContext()); - ObjCProtocolDecl *PDecl - = ObjCProtocolDecl::Create(Context, CurContext, Ident, - IdentPair.second, AtProtocolLoc, - PrevDecl); - - PushOnScopeChains(PDecl, TUScope); + ObjCProtocolDecl *PrevDecl = LookupProtocol( + Ident, IdentPair.second, SemaRef.forRedeclarationInCurContext()); + ObjCProtocolDecl *PDecl = + ObjCProtocolDecl::Create(Context, SemaRef.CurContext, Ident, + IdentPair.second, AtProtocolLoc, PrevDecl); + + SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope); CheckObjCDeclScope(PDecl); - ProcessDeclAttributeList(TUScope, PDecl, attrList); - AddPragmaAttributes(TUScope, PDecl); + SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, PDecl, attrList); + SemaRef.AddPragmaAttributes(SemaRef.TUScope, PDecl); if (PrevDecl) - mergeDeclAttributes(PDecl, PrevDecl); + SemaRef.mergeDeclAttributes(PDecl, PrevDecl); DeclsInGroup.push_back(PDecl); } - return BuildDeclaratorGroup(DeclsInGroup); + return SemaRef.BuildDeclaratorGroup(DeclsInGroup); } -ObjCCategoryDecl *Sema::ActOnStartCategoryInterface( +ObjCCategoryDecl *SemaObjC::ActOnStartCategoryInterface( SourceLocation AtInterfaceLoc, const IdentifierInfo *ClassName, SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, const IdentifierInfo *CategoryName, SourceLocation CategoryLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs, const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList) { + ASTContext &Context = getASTContext(); ObjCCategoryDecl *CDecl; ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); /// Check that class of this category is already completely declared. - if (!IDecl - || RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), - diag::err_category_forward_interface, - CategoryName == nullptr)) { + if (!IDecl || + SemaRef.RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), + diag::err_category_forward_interface, + CategoryName == nullptr)) { // Create an invalid ObjCCategoryDecl to serve as context for // the enclosing method declarations. We mark the decl invalid // to make it clear that this isn't a valid AST. - CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, - ClassLoc, CategoryLoc, CategoryName, - IDecl, typeParamList); + CDecl = ObjCCategoryDecl::Create(Context, SemaRef.CurContext, + AtInterfaceLoc, ClassLoc, CategoryLoc, + CategoryName, IDecl, typeParamList); CDecl->setInvalidDecl(); - CurContext->addDecl(CDecl); + SemaRef.CurContext->addDecl(CDecl); if (!IDecl) Diag(ClassLoc, diag::err_undef_interface) << ClassName; @@ -1872,10 +1865,10 @@ ObjCCategoryDecl *Sema::ActOnStartCategoryInterface( // If we have a type parameter list, check it. if (typeParamList) { if (auto prevTypeParamList = IDecl->getTypeParamList()) { - if (checkTypeParamListConsistency(*this, prevTypeParamList, typeParamList, - CategoryName - ? TypeParamListContext::Category - : TypeParamListContext::Extension)) + if (checkTypeParamListConsistency( + SemaRef, prevTypeParamList, typeParamList, + CategoryName ? TypeParamListContext::Category + : TypeParamListContext::Extension)) typeParamList = nullptr; } else { Diag(typeParamList->getLAngleLoc(), @@ -1888,20 +1881,20 @@ ObjCCategoryDecl *Sema::ActOnStartCategoryInterface( } } - CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, + CDecl = ObjCCategoryDecl::Create(Context, SemaRef.CurContext, AtInterfaceLoc, ClassLoc, CategoryLoc, CategoryName, IDecl, typeParamList); // FIXME: PushOnScopeChains? - CurContext->addDecl(CDecl); + SemaRef.CurContext->addDecl(CDecl); // Process the attributes before looking at protocols to ensure that the // availability attribute is attached to the category to provide availability // checking for protocol uses. - ProcessDeclAttributeList(TUScope, CDecl, AttrList); - AddPragmaAttributes(TUScope, CDecl); + SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, AttrList); + SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl); if (NumProtoRefs) { - diagnoseUseOfProtocols(*this, CDecl, (ObjCProtocolDecl*const*)ProtoRefs, + diagnoseUseOfProtocols(SemaRef, CDecl, (ObjCProtocolDecl *const *)ProtoRefs, NumProtoRefs, ProtoLocs); CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); @@ -1919,10 +1912,11 @@ ObjCCategoryDecl *Sema::ActOnStartCategoryInterface( /// ActOnStartCategoryImplementation - Perform semantic checks on the /// category implementation declaration and build an ObjCCategoryImplDecl /// object. -ObjCCategoryImplDecl *Sema::ActOnStartCategoryImplementation( +ObjCCategoryImplDecl *SemaObjC::ActOnStartCategoryImplementation( SourceLocation AtCatImplLoc, const IdentifierInfo *ClassName, SourceLocation ClassLoc, const IdentifierInfo *CatName, SourceLocation CatLoc, const ParsedAttributesView &Attrs) { + ASTContext &Context = getASTContext(); ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); ObjCCategoryDecl *CatIDecl = nullptr; if (IDecl && IDecl->hasDefinition()) { @@ -1930,31 +1924,32 @@ ObjCCategoryImplDecl *Sema::ActOnStartCategoryImplementation( if (!CatIDecl) { // Category @implementation with no corresponding @interface. // Create and install one. - CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, AtCatImplLoc, - ClassLoc, CatLoc, - CatName, IDecl, - /*typeParamList=*/nullptr); + CatIDecl = + ObjCCategoryDecl::Create(Context, SemaRef.CurContext, AtCatImplLoc, + ClassLoc, CatLoc, CatName, IDecl, + /*typeParamList=*/nullptr); CatIDecl->setImplicit(); } } ObjCCategoryImplDecl *CDecl = - ObjCCategoryImplDecl::Create(Context, CurContext, CatName, IDecl, - ClassLoc, AtCatImplLoc, CatLoc); + ObjCCategoryImplDecl::Create(Context, SemaRef.CurContext, CatName, IDecl, + ClassLoc, AtCatImplLoc, CatLoc); /// Check that class of this category is already completely declared. if (!IDecl) { Diag(ClassLoc, diag::err_undef_interface) << ClassName; CDecl->setInvalidDecl(); - } else if (RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), - diag::err_undef_interface)) { + } else if (SemaRef.RequireCompleteType(ClassLoc, + Context.getObjCInterfaceType(IDecl), + diag::err_undef_interface)) { CDecl->setInvalidDecl(); } - ProcessDeclAttributeList(TUScope, CDecl, Attrs); - AddPragmaAttributes(TUScope, CDecl); + SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, Attrs); + SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl); // FIXME: PushOnScopeChains? - CurContext->addDecl(CDecl); + SemaRef.CurContext->addDecl(CDecl); // If the interface has the objc_runtime_visible attribute, we // cannot implement a category for it. @@ -1975,7 +1970,7 @@ ObjCCategoryImplDecl *Sema::ActOnStartCategoryImplementation( CatIDecl->setImplementation(CDecl); // Warn on implementating category of deprecated class under // -Wdeprecated-implementations flag. - DiagnoseObjCImplementedDeprecations(*this, CatIDecl, + DiagnoseObjCImplementedDeprecations(SemaRef, CatIDecl, CDecl->getLocation()); } } @@ -1985,37 +1980,39 @@ ObjCCategoryImplDecl *Sema::ActOnStartCategoryImplementation( return CDecl; } -ObjCImplementationDecl *Sema::ActOnStartClassImplementation( +ObjCImplementationDecl *SemaObjC::ActOnStartClassImplementation( SourceLocation AtClassImplLoc, const IdentifierInfo *ClassName, SourceLocation ClassLoc, const IdentifierInfo *SuperClassname, SourceLocation SuperClassLoc, const ParsedAttributesView &Attrs) { + ASTContext &Context = getASTContext(); ObjCInterfaceDecl *IDecl = nullptr; // Check for another declaration kind with the same name. - NamedDecl *PrevDecl - = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, - forRedeclarationInCurContext()); + NamedDecl *PrevDecl = SemaRef.LookupSingleName( + SemaRef.TUScope, ClassName, ClassLoc, Sema::LookupOrdinaryName, + SemaRef.forRedeclarationInCurContext()); if (PrevDecl && !isa(PrevDecl)) { Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); } else if ((IDecl = dyn_cast_or_null(PrevDecl))) { // FIXME: This will produce an error if the definition of the interface has // been imported from a module but is not visible. - RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), - diag::warn_undef_interface); + SemaRef.RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), + diag::warn_undef_interface); } else { // We did not find anything with the name ClassName; try to correct for // typos in the class name. ObjCInterfaceValidatorCCC CCC{}; - TypoCorrection Corrected = - CorrectTypo(DeclarationNameInfo(ClassName, ClassLoc), - LookupOrdinaryName, TUScope, nullptr, CCC, CTK_NonError); + TypoCorrection Corrected = SemaRef.CorrectTypo( + DeclarationNameInfo(ClassName, ClassLoc), Sema::LookupOrdinaryName, + SemaRef.TUScope, nullptr, CCC, Sema::CTK_NonError); if (Corrected.getCorrectionDeclAs()) { // Suggest the (potentially) correct interface name. Don't provide a // code-modification hint or use the typo name for recovery, because // this is just a warning. The program may actually be correct. - diagnoseTypo(Corrected, - PDiag(diag::warn_undef_interface_suggest) << ClassName, - /*ErrorRecovery*/false); + SemaRef.diagnoseTypo(Corrected, + SemaRef.PDiag(diag::warn_undef_interface_suggest) + << ClassName, + /*ErrorRecovery*/ false); } else { Diag(ClassLoc, diag::warn_undef_interface) << ClassName; } @@ -2025,8 +2022,9 @@ ObjCImplementationDecl *Sema::ActOnStartClassImplementation( ObjCInterfaceDecl *SDecl = nullptr; if (SuperClassname) { // Check if a different kind of symbol declared in this scope. - PrevDecl = LookupSingleName(TUScope, SuperClassname, SuperClassLoc, - LookupOrdinaryName); + PrevDecl = + SemaRef.LookupSingleName(SemaRef.TUScope, SuperClassname, SuperClassLoc, + Sema::LookupOrdinaryName); if (PrevDecl && !isa(PrevDecl)) { Diag(SuperClassLoc, diag::err_redefinition_different_kind) << SuperClassname; @@ -2054,11 +2052,11 @@ ObjCImplementationDecl *Sema::ActOnStartClassImplementation( // FIXME: Do we support attributes on the @implementation? If so we should // copy them over. - IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc, - ClassName, /*typeParamList=*/nullptr, - /*PrevDecl=*/nullptr, ClassLoc, - true); - AddPragmaAttributes(TUScope, IDecl); + IDecl = + ObjCInterfaceDecl::Create(Context, SemaRef.CurContext, AtClassImplLoc, + ClassName, /*typeParamList=*/nullptr, + /*PrevDecl=*/nullptr, ClassLoc, true); + SemaRef.AddPragmaAttributes(SemaRef.TUScope, IDecl); IDecl->startDefinition(); if (SDecl) { IDecl->setSuperClass(Context.getTrivialTypeSourceInfo( @@ -2069,7 +2067,7 @@ ObjCImplementationDecl *Sema::ActOnStartClassImplementation( IDecl->setEndOfDefinitionLoc(ClassLoc); } - PushOnScopeChains(IDecl, TUScope); + SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope); } else { // Mark the interface as being completed, even if it was just as // @class ....; @@ -2078,12 +2076,12 @@ ObjCImplementationDecl *Sema::ActOnStartClassImplementation( IDecl->startDefinition(); } - ObjCImplementationDecl* IMPDecl = - ObjCImplementationDecl::Create(Context, CurContext, IDecl, SDecl, - ClassLoc, AtClassImplLoc, SuperClassLoc); + ObjCImplementationDecl *IMPDecl = + ObjCImplementationDecl::Create(Context, SemaRef.CurContext, IDecl, SDecl, + ClassLoc, AtClassImplLoc, SuperClassLoc); - ProcessDeclAttributeList(TUScope, IMPDecl, Attrs); - AddPragmaAttributes(TUScope, IMPDecl); + SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, IMPDecl, Attrs); + SemaRef.AddPragmaAttributes(SemaRef.TUScope, IMPDecl); if (CheckObjCDeclScope(IMPDecl)) { ActOnObjCContainerStartDefinition(IMPDecl); @@ -2099,10 +2097,10 @@ ObjCImplementationDecl *Sema::ActOnStartClassImplementation( IMPDecl->setInvalidDecl(); } else { // add it to the list. IDecl->setImplementation(IMPDecl); - PushOnScopeChains(IMPDecl, TUScope); + SemaRef.PushOnScopeChains(IMPDecl, SemaRef.TUScope); // Warn on implementating deprecated class under // -Wdeprecated-implementations flag. - DiagnoseObjCImplementedDeprecations(*this, IDecl, IMPDecl->getLocation()); + DiagnoseObjCImplementedDeprecations(SemaRef, IDecl, IMPDecl->getLocation()); } // If the superclass has the objc_runtime_visible attribute, we @@ -2118,8 +2116,9 @@ ObjCImplementationDecl *Sema::ActOnStartClassImplementation( return IMPDecl; } -Sema::DeclGroupPtrTy -Sema::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, ArrayRef Decls) { +SemaObjC::DeclGroupPtrTy +SemaObjC::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, + ArrayRef Decls) { SmallVector DeclsInGroup; DeclsInGroup.reserve(Decls.size() + 1); @@ -2134,13 +2133,14 @@ Sema::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, ArrayRef Decls) { DeclsInGroup.push_back(ObjCImpDecl); - return BuildDeclaratorGroup(DeclsInGroup); + return SemaRef.BuildDeclaratorGroup(DeclsInGroup); } -void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, - ObjCIvarDecl **ivars, unsigned numIvars, - SourceLocation RBrace) { +void SemaObjC::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, + ObjCIvarDecl **ivars, unsigned numIvars, + SourceLocation RBrace) { assert(ImpDecl && "missing implementation decl"); + ASTContext &Context = getASTContext(); ObjCInterfaceDecl* IDecl = ImpDecl->getClassInterface(); if (!IDecl) return; @@ -2156,7 +2156,7 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, // ObjCInterfaceDecl while in a 'non-fragile' runtime the ivar is // only in the ObjCImplementationDecl. In the non-fragile case the ivar // therefore also needs to be propagated to the ObjCInterfaceDecl. - if (!LangOpts.ObjCRuntime.isFragile()) + if (!getLangOpts().ObjCRuntime.isFragile()) IDecl->makeDeclVisibleInContext(ivars[i]); ImpDecl->addDecl(ivars[i]); } @@ -2168,7 +2168,7 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, return; assert(ivars && "missing @implementation ivars"); - if (LangOpts.ObjCRuntime.isNonFragile()) { + if (getLangOpts().ObjCRuntime.isNonFragile()) { if (ImpDecl->getSuperClass()) Diag(ImpDecl->getLocation(), diag::warn_on_superclass_use); for (unsigned i = 0; i < numIvars; i++) { @@ -2255,7 +2255,8 @@ static void WarnUndefinedMethod(Sema &S, ObjCImplDecl *Impl, // separate warnings. We will give that approach a try, as that // matches what we do with protocols. { - const Sema::SemaDiagnosticBuilder &B = S.Diag(Impl->getLocation(), DiagID); + const SemaBase::SemaDiagnosticBuilder &B = + S.Diag(Impl->getLocation(), DiagID); B << method; if (NeededFor) B << NeededFor; @@ -2585,22 +2586,21 @@ static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl, return true; } -void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, - ObjCMethodDecl *MethodDecl, - bool IsProtocolMethodDecl) { +void SemaObjC::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl) { if (getLangOpts().ObjCAutoRefCount && - checkMethodFamilyMismatch(*this, ImpMethodDecl, MethodDecl)) + checkMethodFamilyMismatch(SemaRef, ImpMethodDecl, MethodDecl)) return; - CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl, - IsProtocolMethodDecl, false, - true); + CheckMethodOverrideReturn(SemaRef, ImpMethodDecl, MethodDecl, + IsProtocolMethodDecl, false, true); for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(), EF = MethodDecl->param_end(); IM != EM && IF != EF; ++IM, ++IF) { - CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF, + CheckMethodOverrideParam(SemaRef, ImpMethodDecl, MethodDecl, *IM, *IF, IsProtocolMethodDecl, false, true); } @@ -2611,19 +2611,18 @@ void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, } } -void Sema::CheckConflictingOverridingMethod(ObjCMethodDecl *Method, - ObjCMethodDecl *Overridden, - bool IsProtocolMethodDecl) { +void SemaObjC::CheckConflictingOverridingMethod(ObjCMethodDecl *Method, + ObjCMethodDecl *Overridden, + bool IsProtocolMethodDecl) { - CheckMethodOverrideReturn(*this, Method, Overridden, - IsProtocolMethodDecl, true, - true); + CheckMethodOverrideReturn(SemaRef, Method, Overridden, IsProtocolMethodDecl, + true, true); for (ObjCMethodDecl::param_iterator IM = Method->param_begin(), IF = Overridden->param_begin(), EM = Method->param_end(), EF = Overridden->param_end(); IM != EM && IF != EF; ++IM, ++IF) { - CheckMethodOverrideParam(*this, Method, Overridden, *IM, *IF, + CheckMethodOverrideParam(SemaRef, Method, Overridden, *IM, *IF, IsProtocolMethodDecl, true, true); } @@ -2636,9 +2635,10 @@ void Sema::CheckConflictingOverridingMethod(ObjCMethodDecl *Method, /// WarnExactTypedMethods - This routine issues a warning if method /// implementation declaration matches exactly that of its declaration. -void Sema::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl, - ObjCMethodDecl *MethodDecl, - bool IsProtocolMethodDecl) { +void SemaObjC::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl, + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl) { + ASTContext &Context = getASTContext(); // don't issue warning when protocol method is optional because primary // class is not required to implement it and it is safe for protocol // to implement it. @@ -2651,16 +2651,15 @@ void Sema::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl, MethodDecl->hasAttr()) return; - bool match = CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl, - IsProtocolMethodDecl, false, false); + bool match = CheckMethodOverrideReturn(SemaRef, ImpMethodDecl, MethodDecl, + IsProtocolMethodDecl, false, false); if (match) for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(), EF = MethodDecl->param_end(); IM != EM && IF != EF; ++IM, ++IF) { - match = CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, - *IM, *IF, - IsProtocolMethodDecl, false, false); + match = CheckMethodOverrideParam(SemaRef, ImpMethodDecl, MethodDecl, *IM, + *IF, IsProtocolMethodDecl, false, false); if (!match) break; } @@ -2713,7 +2712,7 @@ static void findProtocolsWithExplicitImpls(const ObjCInterfaceDecl *Super, /// Declared in protocol, and those referenced by it. static void CheckProtocolMethodDefs( Sema &S, ObjCImplDecl *Impl, ObjCProtocolDecl *PDecl, bool &IncompleteImpl, - const Sema::SelectorSet &InsMap, const Sema::SelectorSet &ClsMap, + const SemaObjC::SelectorSet &InsMap, const SemaObjC::SelectorSet &ClsMap, ObjCContainerDecl *CDecl, LazyProtocolNameSet &ProtocolsExplictImpl) { ObjCCategoryDecl *C = dyn_cast(CDecl); ObjCInterfaceDecl *IDecl = C ? C->getClassInterface() @@ -2835,15 +2834,11 @@ static void CheckProtocolMethodDefs( /// MatchAllMethodDeclarations - Check methods declared in interface /// or protocol against those declared in their implementations. /// -void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, - const SelectorSet &ClsMap, - SelectorSet &InsMapSeen, - SelectorSet &ClsMapSeen, - ObjCImplDecl* IMPDecl, - ObjCContainerDecl* CDecl, - bool &IncompleteImpl, - bool ImmediateClass, - bool WarnCategoryMethodImpl) { +void SemaObjC::MatchAllMethodDeclarations( + const SelectorSet &InsMap, const SelectorSet &ClsMap, + SelectorSet &InsMapSeen, SelectorSet &ClsMapSeen, ObjCImplDecl *IMPDecl, + ObjCContainerDecl *CDecl, bool &IncompleteImpl, bool ImmediateClass, + bool WarnCategoryMethodImpl) { // Check and see if instance methods in class interface have been // implemented in the implementation class. If so, their types match. for (auto *I : CDecl->instance_methods()) { @@ -2852,7 +2847,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, if (!I->isPropertyAccessor() && !InsMap.count(I->getSelector())) { if (ImmediateClass) - WarnUndefinedMethod(*this, IMPDecl, I, IncompleteImpl, + WarnUndefinedMethod(SemaRef, IMPDecl, I, IncompleteImpl, diag::warn_undef_method_impl); continue; } else { @@ -2882,7 +2877,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, if (!I->isPropertyAccessor() && !ClsMap.count(I->getSelector())) { if (ImmediateClass) - WarnUndefinedMethod(*this, IMPDecl, I, IncompleteImpl, + WarnUndefinedMethod(SemaRef, IMPDecl, I, IncompleteImpl, diag::warn_undef_method_impl); } else { ObjCMethodDecl *ImpMethodDecl = @@ -2948,8 +2943,8 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in /// category matches with those implemented in its primary class and /// warns each time an exact match is found. -void Sema::CheckCategoryVsClassMethodMatches( - ObjCCategoryImplDecl *CatIMPDecl) { +void SemaObjC::CheckCategoryVsClassMethodMatches( + ObjCCategoryImplDecl *CatIMPDecl) { // Get category's primary class. ObjCCategoryDecl *CatDecl = CatIMPDecl->getCategoryDecl(); if (!CatDecl) @@ -2987,9 +2982,9 @@ void Sema::CheckCategoryVsClassMethodMatches( true /*WarnCategoryMethodImpl*/); } -void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, - ObjCContainerDecl* CDecl, - bool IncompleteImpl) { +void SemaObjC::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl *IMPDecl, + ObjCContainerDecl *CDecl, + bool IncompleteImpl) { SelectorSet InsMap; // Check and see if instance methods in class interface have been // implemented in the implementation class. @@ -3014,8 +3009,8 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, // an implementation or 2) there is a @synthesize/@dynamic implementation // of the property in the @implementation. if (const ObjCInterfaceDecl *IDecl = dyn_cast(CDecl)) { - bool SynthesizeProperties = LangOpts.ObjCDefaultSynthProperties && - LangOpts.ObjCRuntime.isNonFragile() && + bool SynthesizeProperties = getLangOpts().ObjCDefaultSynthProperties && + getLangOpts().ObjCRuntime.isNonFragile() && !IDecl->isObjCRequiresPropertyDefs(); DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, SynthesizeProperties); } @@ -3049,14 +3044,14 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, if (ObjCInterfaceDecl *I = dyn_cast (CDecl)) { for (auto *PI : I->all_referenced_protocols()) - CheckProtocolMethodDefs(*this, IMPDecl, PI, IncompleteImpl, InsMap, + CheckProtocolMethodDefs(SemaRef, IMPDecl, PI, IncompleteImpl, InsMap, ClsMap, I, ExplicitImplProtocols); } else if (ObjCCategoryDecl *C = dyn_cast(CDecl)) { // For extended class, unimplemented methods in its protocols will // be reported in the primary class. if (!C->IsClassExtension()) { for (auto *P : C->protocols()) - CheckProtocolMethodDefs(*this, IMPDecl, P, IncompleteImpl, InsMap, + CheckProtocolMethodDefs(SemaRef, IMPDecl, P, IncompleteImpl, InsMap, ClsMap, CDecl, ExplicitImplProtocols); DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, /*SynthesizeProperties=*/false); @@ -3065,18 +3060,17 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, llvm_unreachable("invalid ObjCContainerDecl type."); } -Sema::DeclGroupPtrTy -Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, - IdentifierInfo **IdentList, - SourceLocation *IdentLocs, - ArrayRef TypeParamLists, - unsigned NumElts) { +SemaObjC::DeclGroupPtrTy SemaObjC::ActOnForwardClassDeclaration( + SourceLocation AtClassLoc, IdentifierInfo **IdentList, + SourceLocation *IdentLocs, ArrayRef TypeParamLists, + unsigned NumElts) { + ASTContext &Context = getASTContext(); SmallVector DeclsInGroup; for (unsigned i = 0; i != NumElts; ++i) { // Check for another declaration kind with the same name. - NamedDecl *PrevDecl - = LookupSingleName(TUScope, IdentList[i], IdentLocs[i], - LookupOrdinaryName, forRedeclarationInCurContext()); + NamedDecl *PrevDecl = SemaRef.LookupSingleName( + SemaRef.TUScope, IdentList[i], IdentLocs[i], Sema::LookupOrdinaryName, + SemaRef.forRedeclarationInCurContext()); if (PrevDecl && !isa(PrevDecl)) { // GCC apparently allows the following idiom: // @@ -3131,8 +3125,8 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, if (ObjCTypeParamList *PrevTypeParams = PrevIDecl->getTypeParamList()) { // Check for consistency with the previous declaration. if (checkTypeParamListConsistency( - *this, PrevTypeParams, TypeParams, - TypeParamListContext::ForwardDeclaration)) { + SemaRef, PrevTypeParams, TypeParams, + TypeParamListContext::ForwardDeclaration)) { TypeParams = nullptr; } } else if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) { @@ -3147,29 +3141,29 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, } } - ObjCInterfaceDecl *IDecl - = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, - ClassName, TypeParams, PrevIDecl, - IdentLocs[i]); + ObjCInterfaceDecl *IDecl = ObjCInterfaceDecl::Create( + Context, SemaRef.CurContext, AtClassLoc, ClassName, TypeParams, + PrevIDecl, IdentLocs[i]); IDecl->setAtEndRange(IdentLocs[i]); if (PrevIDecl) - mergeDeclAttributes(IDecl, PrevIDecl); + SemaRef.mergeDeclAttributes(IDecl, PrevIDecl); - PushOnScopeChains(IDecl, TUScope); + SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope); CheckObjCDeclScope(IDecl); DeclsInGroup.push_back(IDecl); } - return BuildDeclaratorGroup(DeclsInGroup); + return SemaRef.BuildDeclaratorGroup(DeclsInGroup); } static bool tryMatchRecordTypes(ASTContext &Context, - Sema::MethodMatchStrategy strategy, + SemaObjC::MethodMatchStrategy strategy, const Type *left, const Type *right); -static bool matchTypes(ASTContext &Context, Sema::MethodMatchStrategy strategy, - QualType leftQT, QualType rightQT) { +static bool matchTypes(ASTContext &Context, + SemaObjC::MethodMatchStrategy strategy, QualType leftQT, + QualType rightQT) { const Type *left = Context.getCanonicalType(leftQT).getUnqualifiedType().getTypePtr(); const Type *right = @@ -3178,7 +3172,8 @@ static bool matchTypes(ASTContext &Context, Sema::MethodMatchStrategy strategy, if (left == right) return true; // If we're doing a strict match, the types have to match exactly. - if (strategy == Sema::MMS_strict) return false; + if (strategy == SemaObjC::MMS_strict) + return false; if (left->isIncompleteType() || right->isIncompleteType()) return false; @@ -3226,7 +3221,7 @@ static bool matchTypes(ASTContext &Context, Sema::MethodMatchStrategy strategy, } static bool tryMatchRecordTypes(ASTContext &Context, - Sema::MethodMatchStrategy strategy, + SemaObjC::MethodMatchStrategy strategy, const Type *lt, const Type *rt) { assert(lt && rt && lt != rt); @@ -3264,9 +3259,10 @@ static bool tryMatchRecordTypes(ASTContext &Context, /// MatchTwoMethodDeclarations - Checks that two methods have matching type and /// returns true, or false, accordingly. /// TODO: Handle protocol list; such as id in type comparisons -bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left, - const ObjCMethodDecl *right, - MethodMatchStrategy strategy) { +bool SemaObjC::MatchTwoMethodDeclarations(const ObjCMethodDecl *left, + const ObjCMethodDecl *right, + MethodMatchStrategy strategy) { + ASTContext &Context = getASTContext(); if (!matchTypes(Context, strategy, left->getReturnType(), right->getReturnType())) return false; @@ -3323,8 +3319,8 @@ static bool isMethodContextSameForKindofLookup(ObjCMethodDecl *Method, return MethodInterface == MethodInListInterface; } -void Sema::addMethodToGlobalList(ObjCMethodList *List, - ObjCMethodDecl *Method) { +void SemaObjC::addMethodToGlobalList(ObjCMethodList *List, + ObjCMethodDecl *Method) { // Record at the head of the list whether there were 0, 1, or >= 2 methods // inside categories. if (ObjCCategoryDecl *CD = @@ -3412,7 +3408,7 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, // We have a new signature for an existing method - add it. // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". - ObjCMethodList *Mem = BumpAlloc.Allocate(); + ObjCMethodList *Mem = SemaRef.BumpAlloc.Allocate(); // We insert it right before ListWithSameDeclaration. if (ListWithSameDeclaration) { @@ -3428,24 +3424,24 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, /// Read the contents of the method pool for a given selector from /// external storage. -void Sema::ReadMethodPool(Selector Sel) { - assert(ExternalSource && "We need an external AST source"); - ExternalSource->ReadMethodPool(Sel); +void SemaObjC::ReadMethodPool(Selector Sel) { + assert(SemaRef.ExternalSource && "We need an external AST source"); + SemaRef.ExternalSource->ReadMethodPool(Sel); } -void Sema::updateOutOfDateSelector(Selector Sel) { - if (!ExternalSource) +void SemaObjC::updateOutOfDateSelector(Selector Sel) { + if (!SemaRef.ExternalSource) return; - ExternalSource->updateOutOfDateSelector(Sel); + SemaRef.ExternalSource->updateOutOfDateSelector(Sel); } -void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, - bool instance) { +void SemaObjC::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, + bool instance) { // Ignore methods of invalid containers. if (cast(Method->getDeclContext())->isInvalidDecl()) return; - if (ExternalSource) + if (SemaRef.ExternalSource) ReadMethodPool(Method->getSelector()); GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector()); @@ -3518,11 +3514,10 @@ static bool FilterMethodsByTypeBound(ObjCMethodDecl *Method, /// We first select the type of the method: Instance or Factory, then collect /// all methods with that type. -bool Sema::CollectMultipleMethodsInGlobalPool( +bool SemaObjC::CollectMultipleMethodsInGlobalPool( Selector Sel, SmallVectorImpl &Methods, - bool InstanceFirst, bool CheckTheOther, - const ObjCObjectType *TypeBound) { - if (ExternalSource) + bool InstanceFirst, bool CheckTheOther, const ObjCObjectType *TypeBound) { + if (SemaRef.ExternalSource) ReadMethodPool(Sel); GlobalMethodPool::iterator Pos = MethodPool.find(Sel); @@ -3557,7 +3552,7 @@ bool Sema::CollectMultipleMethodsInGlobalPool( return Methods.size() > 1; } -bool Sema::AreMultipleMethodsInGlobalPool( +bool SemaObjC::AreMultipleMethodsInGlobalPool( Selector Sel, ObjCMethodDecl *BestMethod, SourceRange R, bool receiverIdOrClass, SmallVectorImpl &Methods) { // Diagnose finding more than one method in global pool. @@ -3582,10 +3577,10 @@ bool Sema::AreMultipleMethodsInGlobalPool( return MethList.hasMoreThanOneDecl(); } -ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, - bool receiverIdOrClass, - bool instance) { - if (ExternalSource) +ObjCMethodDecl *SemaObjC::LookupMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass, + bool instance) { + if (SemaRef.ExternalSource) ReadMethodPool(Sel); GlobalMethodPool::iterator Pos = MethodPool.find(Sel); @@ -3602,17 +3597,18 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, return nullptr; } -void Sema::DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl &Methods, - Selector Sel, SourceRange R, - bool receiverIdOrClass) { +void SemaObjC::DiagnoseMultipleMethodInGlobalPool( + SmallVectorImpl &Methods, Selector Sel, SourceRange R, + bool receiverIdOrClass) { // We found multiple methods, so we may have to complain. bool issueDiagnostic = false, issueError = false; // We support a warning which complains about *any* difference in // method signature. bool strictSelectorMatch = - receiverIdOrClass && - !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin()); + receiverIdOrClass && + !getDiagnostics().isIgnored(diag::warn_strict_multiple_method_decl, + R.getBegin()); if (strictSelectorMatch) { for (unsigned I = 1, N = Methods.size(); I != N; ++I) { if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) { @@ -3656,7 +3652,7 @@ void Sema::DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl & } } -ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { +ObjCMethodDecl *SemaObjC::LookupImplementedMethodInGlobalPool(Selector Sel) { GlobalMethodPool::iterator Pos = MethodPool.find(Sel); if (Pos == MethodPool.end()) return nullptr; @@ -3705,15 +3701,15 @@ static bool HelperIsMethodInObjCType(Sema &S, Selector Sel, QualType ObjectType) { if (ObjectType.isNull()) return true; - if (S.LookupMethodInObjectType(Sel, ObjectType, true/*Instance method*/)) + if (S.ObjC().LookupMethodInObjectType(Sel, ObjectType, + true /*Instance method*/)) return true; - return S.LookupMethodInObjectType(Sel, ObjectType, false/*Class method*/) != - nullptr; + return S.ObjC().LookupMethodInObjectType(Sel, ObjectType, + false /*Class method*/) != nullptr; } const ObjCMethodDecl * -Sema::SelectorsForTypoCorrection(Selector Sel, - QualType ObjectType) { +SemaObjC::SelectorsForTypoCorrection(Selector Sel, QualType ObjectType) { unsigned NumArgs = Sel.getNumArgs(); SmallVector Methods; bool ObjectIsId = true, ObjectIsClass = true; @@ -3743,8 +3739,8 @@ Sema::SelectorsForTypoCorrection(Selector Sel, if (ObjectIsId) Methods.push_back(M->getMethod()); else if (!ObjectIsClass && - HelperIsMethodInObjCType(*this, M->getMethod()->getSelector(), - ObjectType)) + HelperIsMethodInObjCType( + SemaRef, M->getMethod()->getSelector(), ObjectType)) Methods.push_back(M->getMethod()); } // class methods @@ -3755,8 +3751,8 @@ Sema::SelectorsForTypoCorrection(Selector Sel, if (ObjectIsClass) Methods.push_back(M->getMethod()); else if (!ObjectIsId && - HelperIsMethodInObjCType(*this, M->getMethod()->getSelector(), - ObjectType)) + HelperIsMethodInObjCType( + SemaRef, M->getMethod()->getSelector(), ObjectType)) Methods.push_back(M->getMethod()); } } @@ -3774,8 +3770,8 @@ Sema::SelectorsForTypoCorrection(Selector Sel, /// \@implementation. This becomes necessary because class extension can /// add ivars to a class in random order which will not be known until /// class's \@implementation is seen. -void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, - ObjCInterfaceDecl *SID) { +void SemaObjC::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, + ObjCInterfaceDecl *SID) { for (auto *Ivar : ID->ivars()) { if (Ivar->isInvalidDecl()) continue; @@ -3827,23 +3823,23 @@ static void DiagnoseRetainableFlexibleArrayMember(Sema &S, } } -Sema::ObjCContainerKind Sema::getObjCContainerKind() const { - switch (CurContext->getDeclKind()) { - case Decl::ObjCInterface: - return Sema::OCK_Interface; - case Decl::ObjCProtocol: - return Sema::OCK_Protocol; - case Decl::ObjCCategory: - if (cast(CurContext)->IsClassExtension()) - return Sema::OCK_ClassExtension; - return Sema::OCK_Category; - case Decl::ObjCImplementation: - return Sema::OCK_Implementation; - case Decl::ObjCCategoryImpl: - return Sema::OCK_CategoryImplementation; - - default: - return Sema::OCK_None; +SemaObjC::ObjCContainerKind SemaObjC::getObjCContainerKind() const { + switch (SemaRef.CurContext->getDeclKind()) { + case Decl::ObjCInterface: + return SemaObjC::OCK_Interface; + case Decl::ObjCProtocol: + return SemaObjC::OCK_Protocol; + case Decl::ObjCCategory: + if (cast(SemaRef.CurContext)->IsClassExtension()) + return SemaObjC::OCK_ClassExtension; + return SemaObjC::OCK_Category; + case Decl::ObjCImplementation: + return SemaObjC::OCK_Implementation; + case Decl::ObjCCategoryImpl: + return SemaObjC::OCK_CategoryImplementation; + + default: + return SemaObjC::OCK_None; } } @@ -3987,14 +3983,16 @@ static void DiagnoseCategoryDirectMembersProtocolConformance( } // Note: For class/category implementations, allMethods is always null. -Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef allMethods, - ArrayRef allTUVars) { - if (getObjCContainerKind() == Sema::OCK_None) +Decl *SemaObjC::ActOnAtEnd(Scope *S, SourceRange AtEnd, + ArrayRef allMethods, + ArrayRef allTUVars) { + ASTContext &Context = getASTContext(); + if (getObjCContainerKind() == SemaObjC::OCK_None) return nullptr; assert(AtEnd.isValid() && "Invalid location for '@end'"); - auto *OCD = cast(CurContext); + auto *OCD = cast(SemaRef.CurContext); Decl *ClassDecl = OCD; bool isInterfaceDeclKind = @@ -4006,7 +4004,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef allMethods, // ActOnPropertyImplDecl() creates them as not visible in case // they are overridden by an explicit method that is encountered // later. - if (auto *OID = dyn_cast(CurContext)) { + if (auto *OID = dyn_cast(SemaRef.CurContext)) { for (auto *PropImpl : OID->property_impls()) { if (auto *Getter = PropImpl->getGetterMethodDecl()) if (Getter->isSynthesizedAccessorStub()) @@ -4087,7 +4085,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef allMethods, DiagnoseClassExtensionDupMethods(C, CCPrimary); } - DiagnoseCategoryDirectMembersProtocolConformance(*this, C, C->protocols()); + DiagnoseCategoryDirectMembersProtocolConformance(SemaRef, C, + C->protocols()); } if (ObjCContainerDecl *CDecl = dyn_cast(ClassDecl)) { if (CDecl->getIdentifier()) @@ -4133,8 +4132,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef allMethods, DiagnoseUnusedBackingIvarInAccessor(S, IC); if (IDecl->hasDesignatedInitializers()) DiagnoseMissingDesignatedInitOverrides(IC, IDecl); - DiagnoseWeakIvars(*this, IC); - DiagnoseRetainableFlexibleArrayMember(*this, IDecl); + DiagnoseWeakIvars(SemaRef, IC); + DiagnoseRetainableFlexibleArrayMember(SemaRef, IDecl); bool HasRootClassAttr = IDecl->hasAttr(); if (IDecl->getSuperClass() == nullptr) { @@ -4142,14 +4141,14 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef allMethods, // __attribute((objc_root_class)). if (!HasRootClassAttr) { SourceLocation DeclLoc(IDecl->getLocation()); - SourceLocation SuperClassLoc(getLocForEndOfToken(DeclLoc)); + SourceLocation SuperClassLoc(SemaRef.getLocForEndOfToken(DeclLoc)); Diag(DeclLoc, diag::warn_objc_root_class_missing) << IDecl->getIdentifier(); // See if NSObject is in the current scope, and if it is, suggest // adding " : NSObject " to the class declaration. - NamedDecl *IF = LookupSingleName(TUScope, - NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject), - DeclLoc, LookupOrdinaryName); + NamedDecl *IF = SemaRef.LookupSingleName( + SemaRef.TUScope, NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject), + DeclLoc, Sema::LookupOrdinaryName); ObjCInterfaceDecl *NSObjectDecl = dyn_cast_or_null(IF); if (NSObjectDecl && NSObjectDecl->getDefinition()) { Diag(SuperClassLoc, diag::note_objc_needs_superclass) @@ -4178,7 +4177,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef allMethods, if (IDecl->hasAttr()) Diag(IC->getLocation(), diag::err_implementation_of_class_stub); - if (LangOpts.ObjCRuntime.isNonFragile()) { + if (getLangOpts().ObjCRuntime.isNonFragile()) { while (IDecl->getSuperClass()) { DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass()); IDecl = IDecl->getSuperClass(); @@ -4211,7 +4210,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef allMethods, !IntfDecl->hasAttr()) Diag(IntfDecl->getLocation(), diag::err_class_stub_subclassing_mismatch); } - DiagnoseVariableSizedIvars(*this, OCD); + DiagnoseVariableSizedIvars(SemaRef, OCD); if (isInterfaceDeclKind) { // Reject invalid vardecls. for (unsigned i = 0, e = allTUVars.size(); i != e; i++) { @@ -4229,10 +4228,10 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef allMethods, DeclGroupRef DG = allTUVars[i].get(); for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) (*I)->setTopLevelDeclInObjCContainer(); - Consumer.HandleTopLevelDeclInObjCContainer(DG); + SemaRef.Consumer.HandleTopLevelDeclInObjCContainer(DG); } - ActOnDocumentableDecl(ClassDecl); + SemaRef.ActOnDocumentableDecl(ClassDecl); return ClassDecl; } @@ -4246,7 +4245,7 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) { /// Check whether the declared result type of the given Objective-C /// method declaration is compatible with the method's class. /// -static Sema::ResultTypeCompatibilityKind +static SemaObjC::ResultTypeCompatibilityKind CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method, ObjCInterfaceDecl *CurrentClass) { QualType ResultType = Method->getReturnType(); @@ -4259,27 +4258,27 @@ CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method, // - it is id or qualified id, or if (ResultObjectType->isObjCIdType() || ResultObjectType->isObjCQualifiedIdType()) - return Sema::RTC_Compatible; + return SemaObjC::RTC_Compatible; if (CurrentClass) { if (ObjCInterfaceDecl *ResultClass = ResultObjectType->getInterfaceDecl()) { // - it is the same as the method's class type, or if (declaresSameEntity(CurrentClass, ResultClass)) - return Sema::RTC_Compatible; + return SemaObjC::RTC_Compatible; // - it is a superclass of the method's class type if (ResultClass->isSuperClassOf(CurrentClass)) - return Sema::RTC_Compatible; + return SemaObjC::RTC_Compatible; } } else { // Any Objective-C pointer type might be acceptable for a protocol // method; we just don't know. - return Sema::RTC_Unknown; + return SemaObjC::RTC_Unknown; } } - return Sema::RTC_Incompatible; + return SemaObjC::RTC_Incompatible; } namespace { @@ -4297,13 +4296,14 @@ public: // Bypass this search if we've never seen an instance/class method // with this selector before. - Sema::GlobalMethodPool::iterator it = S.MethodPool.find(selector); - if (it == S.MethodPool.end()) { + SemaObjC::GlobalMethodPool::iterator it = + S.ObjC().MethodPool.find(selector); + if (it == S.ObjC().MethodPool.end()) { if (!S.getExternalSource()) return; - S.ReadMethodPool(selector); + S.ObjC().ReadMethodPool(selector); - it = S.MethodPool.find(selector); - if (it == S.MethodPool.end()) + it = S.ObjC().MethodPool.find(selector); + if (it == S.ObjC().MethodPool.end()) return; } const ObjCMethodList &list = @@ -4430,8 +4430,8 @@ private: }; } // end anonymous namespace -void Sema::CheckObjCMethodDirectOverrides(ObjCMethodDecl *method, - ObjCMethodDecl *overridden) { +void SemaObjC::CheckObjCMethodDirectOverrides(ObjCMethodDecl *method, + ObjCMethodDecl *overridden) { if (overridden->isDirectMethod()) { const auto *attr = overridden->getAttr(); Diag(method->getLocation(), diag::err_objc_override_direct_method); @@ -4444,9 +4444,10 @@ void Sema::CheckObjCMethodDirectOverrides(ObjCMethodDecl *method, } } -void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, - ObjCInterfaceDecl *CurrentClass, - ResultTypeCompatibilityKind RTC) { +void SemaObjC::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, + ObjCInterfaceDecl *CurrentClass, + ResultTypeCompatibilityKind RTC) { + ASTContext &Context = getASTContext(); if (!ObjCMethod) return; auto IsMethodInCurrentClass = [CurrentClass](const ObjCMethodDecl *M) { @@ -4455,7 +4456,7 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, CurrentClass->getCanonicalDecl(); }; // Search for overridden methods and merge information down from them. - OverrideSearch overrides(*this, ObjCMethod); + OverrideSearch overrides(SemaRef, ObjCMethod); // Keep track if the method overrides any method in the class's base classes, // its protocols, or its categories' protocols; we will keep that info // in the ObjCMethodDecl. @@ -4487,7 +4488,7 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, // least 2 category methods recorded, otherwise only one will do. if (CategCount > 1 || !isa(overridden->getDeclContext())) { - OverrideSearch overrides(*this, overridden); + OverrideSearch overrides(SemaRef, overridden); for (ObjCMethodDecl *SuperOverridden : overrides) { if (isa(SuperOverridden->getDeclContext()) || !IsMethodInCurrentClass(SuperOverridden)) { @@ -4504,11 +4505,11 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, } // Propagate down the 'related result type' bit from overridden methods. - if (RTC != Sema::RTC_Incompatible && overridden->hasRelatedResultType()) + if (RTC != SemaObjC::RTC_Incompatible && overridden->hasRelatedResultType()) ObjCMethod->setRelatedResultType(); // Then merge the declarations. - mergeObjCMethodDecls(ObjCMethod, overridden); + SemaRef.mergeObjCMethodDecls(ObjCMethod, overridden); if (ObjCMethod->isImplicit() && overridden->isImplicit()) continue; // Conflicting properties are detected elsewhere. @@ -4727,7 +4728,7 @@ static void checkObjCDirectMethodClashes(Sema &S, ObjCInterfaceDecl *IDecl, diagClash(IMD); } -Decl *Sema::ActOnMethodDeclaration( +Decl *SemaObjC::ActOnMethodDeclaration( Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc, tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, ArrayRef SelectorLocs, Selector Sel, @@ -4737,21 +4738,22 @@ Decl *Sema::ActOnMethodDeclaration( unsigned CNumArgs, // c-style args const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind, bool isVariadic, bool MethodDefinition) { + ASTContext &Context = getASTContext(); // Make sure we can establish a context for the method. - if (!CurContext->isObjCContainer()) { + if (!SemaRef.CurContext->isObjCContainer()) { Diag(MethodLoc, diag::err_missing_method_context); return nullptr; } - Decl *ClassDecl = cast(CurContext); + Decl *ClassDecl = cast(SemaRef.CurContext); QualType resultDeclType; bool HasRelatedResultType = false; TypeSourceInfo *ReturnTInfo = nullptr; if (ReturnType) { - resultDeclType = GetTypeFromParser(ReturnType, &ReturnTInfo); + resultDeclType = SemaRef.GetTypeFromParser(ReturnType, &ReturnTInfo); - if (CheckFunctionReturnType(resultDeclType, MethodLoc)) + if (SemaRef.CheckFunctionReturnType(resultDeclType, MethodLoc)) return nullptr; QualType bareResultType = resultDeclType; @@ -4764,8 +4766,8 @@ Decl *Sema::ActOnMethodDeclaration( } ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create( - Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo, CurContext, - MethodType == tok::minus, isVariadic, + Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo, + SemaRef.CurContext, MethodType == tok::minus, isVariadic, /*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false, /*isImplicitlyDeclared=*/false, /*isDefined=*/false, MethodDeclKind == tok::objc_optional @@ -4783,12 +4785,13 @@ Decl *Sema::ActOnMethodDeclaration( ArgType = Context.getObjCIdType(); DI = nullptr; } else { - ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI); + ArgType = SemaRef.GetTypeFromParser(ArgInfo[i].Type, &DI); } - LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc, - LookupOrdinaryName, forRedeclarationInCurContext()); - LookupName(R, S); + LookupResult R(SemaRef, ArgInfo[i].Name, ArgInfo[i].NameLoc, + Sema::LookupOrdinaryName, + SemaRef.forRedeclarationInCurContext()); + SemaRef.LookupName(R, S); if (R.isSingleResult()) { NamedDecl *PrevDecl = R.getFoundDecl(); if (S->isDeclScope(PrevDecl)) { @@ -4805,9 +4808,9 @@ Decl *Sema::ActOnMethodDeclaration( ? DI->getTypeLoc().getBeginLoc() : ArgInfo[i].NameLoc; - ParmVarDecl* Param = CheckParameter(ObjCMethod, StartLoc, - ArgInfo[i].NameLoc, ArgInfo[i].Name, - ArgType, DI, SC_None); + ParmVarDecl *Param = + SemaRef.CheckParameter(ObjCMethod, StartLoc, ArgInfo[i].NameLoc, + ArgInfo[i].Name, ArgType, DI, SC_None); Param->setObjCMethodScopeInfo(i); @@ -4815,16 +4818,17 @@ Decl *Sema::ActOnMethodDeclaration( CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier())); // Apply the attributes to the parameter. - ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs); - AddPragmaAttributes(TUScope, Param); - ProcessAPINotes(Param); + SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, Param, + ArgInfo[i].ArgAttrs); + SemaRef.AddPragmaAttributes(SemaRef.TUScope, Param); + SemaRef.ProcessAPINotes(Param); if (Param->hasAttr()) { Diag(Param->getLocation(), diag::err_block_on_nonlocal); Param->setInvalidDecl(); } S->AddDecl(Param); - IdResolver.AddDecl(Param); + SemaRef.IdResolver.AddDecl(Param); Params.push_back(Param); } @@ -4846,9 +4850,9 @@ Decl *Sema::ActOnMethodDeclaration( ObjCMethod->setObjCDeclQualifier( CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier())); - ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); - AddPragmaAttributes(TUScope, ObjCMethod); - ProcessAPINotes(ObjCMethod); + SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, ObjCMethod, AttrList); + SemaRef.AddPragmaAttributes(SemaRef.TUScope, ObjCMethod); + SemaRef.ProcessAPINotes(ObjCMethod); // Add the method now. const ObjCMethodDecl *PrevMethod = nullptr; @@ -4902,7 +4906,7 @@ Decl *Sema::ActOnMethodDeclaration( if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) { if (auto *IMD = IDecl->lookupMethod(ObjCMethod->getSelector(), ObjCMethod->isInstanceMethod())) { - mergeInterfaceMethodToImpl(*this, ObjCMethod, IMD); + mergeInterfaceMethodToImpl(SemaRef, ObjCMethod, IMD); // The Idecl->lookupMethod() above will find declarations for ObjCMethod // in one of these places: @@ -4962,8 +4966,8 @@ Decl *Sema::ActOnMethodDeclaration( << ObjCMethod->getDeclName(); } } else { - mergeObjCDirectMembers(*this, ClassDecl, ObjCMethod); - checkObjCDirectMethodClashes(*this, IDecl, ObjCMethod, ImpDecl); + mergeObjCDirectMembers(SemaRef, ClassDecl, ObjCMethod); + checkObjCDirectMethodClashes(SemaRef, IDecl, ObjCMethod, ImpDecl); } // Warn if a method declared in a protocol to which a category or @@ -4979,12 +4983,12 @@ Decl *Sema::ActOnMethodDeclaration( auto OI = IMD->param_begin(), OE = IMD->param_end(); auto NI = ObjCMethod->param_begin(); for (; OI != OE; ++OI, ++NI) - diagnoseNoescape(*NI, *OI, C, P, *this); + diagnoseNoescape(*NI, *OI, C, P, SemaRef); } } } else { if (!isa(ClassDecl)) { - mergeObjCDirectMembers(*this, ClassDecl, ObjCMethod); + mergeObjCDirectMembers(SemaRef, ClassDecl, ObjCMethod); ObjCInterfaceDecl *IDecl = dyn_cast(ClassDecl); if (!IDecl) @@ -4993,7 +4997,7 @@ Decl *Sema::ActOnMethodDeclaration( // declaration by now, however for invalid code we'll keep parsing // but we won't find the primary interface and IDecl will be nil. if (IDecl) - checkObjCDirectMethodClashes(*this, IDecl, ObjCMethod); + checkObjCDirectMethodClashes(SemaRef, IDecl, ObjCMethod); } cast(ClassDecl)->addDecl(ObjCMethod); @@ -5022,8 +5026,8 @@ Decl *Sema::ActOnMethodDeclaration( CurrentClass = CatImpl->getClassInterface(); } - ResultTypeCompatibilityKind RTC - = CheckRelatedResultTypeCompatibility(*this, ObjCMethod, CurrentClass); + ResultTypeCompatibilityKind RTC = + CheckRelatedResultTypeCompatibility(SemaRef, ObjCMethod, CurrentClass); CheckObjCMethodOverrides(ObjCMethod, CurrentClass, RTC); @@ -5032,9 +5036,9 @@ Decl *Sema::ActOnMethodDeclaration( ARCError = CheckARCMethodDecl(ObjCMethod); // Infer the related result type when possible. - if (!ARCError && RTC == Sema::RTC_Compatible && + if (!ARCError && RTC == SemaObjC::RTC_Compatible && !ObjCMethod->hasRelatedResultType() && - LangOpts.ObjCInferRelatedResultType) { + getLangOpts().ObjCInferRelatedResultType) { bool InferRelatedResultType = false; switch (ObjCMethod->getMethodFamily()) { case OMF_None: @@ -5068,7 +5072,7 @@ Decl *Sema::ActOnMethodDeclaration( if (MethodDefinition && Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) - checkObjCMethodX86VectorTypes(*this, ObjCMethod); + checkObjCMethodX86VectorTypes(SemaRef, ObjCMethod); // + load method cannot have availability attributes. It get called on // startup, so it has to have the availability of the deployment target. @@ -5084,20 +5088,21 @@ Decl *Sema::ActOnMethodDeclaration( // Insert the invisible arguments, self and _cmd! ObjCMethod->createImplicitParams(Context, ObjCMethod->getClassInterface()); - ActOnDocumentableDecl(ObjCMethod); + SemaRef.ActOnDocumentableDecl(ObjCMethod); return ObjCMethod; } -bool Sema::CheckObjCDeclScope(Decl *D) { +bool SemaObjC::CheckObjCDeclScope(Decl *D) { // Following is also an error. But it is caused by a missing @end // and diagnostic is issued elsewhere. - if (isa(CurContext->getRedeclContext())) + if (isa(SemaRef.CurContext->getRedeclContext())) return false; // If we switched context to translation unit while we are still lexically in // an objc container, it means the parser missed emitting an error. - if (isa(getCurLexicalContext()->getRedeclContext())) + if (isa( + SemaRef.getCurLexicalContext()->getRedeclContext())) return false; Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope); @@ -5108,16 +5113,17 @@ bool Sema::CheckObjCDeclScope(Decl *D) { /// Called whenever \@defs(ClassName) is encountered in the source. Inserts the /// instance variables of ClassName into Decls. -void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, - const IdentifierInfo *ClassName, - SmallVectorImpl &Decls) { +void SemaObjC::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, + const IdentifierInfo *ClassName, + SmallVectorImpl &Decls) { + ASTContext &Context = getASTContext(); // Check that ClassName is a valid class ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart); if (!Class) { Diag(DeclStart, diag::err_undef_interface) << ClassName; return; } - if (LangOpts.ObjCRuntime.isNonFragile()) { + if (getLangOpts().ObjCRuntime.isNonFragile()) { Diag(DeclStart, diag::err_atdef_nonfragile_interface); return; } @@ -5142,17 +5148,19 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, D != Decls.end(); ++D) { FieldDecl *FD = cast(*D); if (getLangOpts().CPlusPlus) - PushOnScopeChains(FD, S); + SemaRef.PushOnScopeChains(FD, S); else if (RecordDecl *Record = dyn_cast(TagD)) Record->addDecl(FD); } } /// Build a type-check a new Objective-C exception variable declaration. -VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, - SourceLocation StartLoc, - SourceLocation IdLoc, - const IdentifierInfo *Id, bool Invalid) { +VarDecl *SemaObjC::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, + SourceLocation StartLoc, + SourceLocation IdLoc, + const IdentifierInfo *Id, + bool Invalid) { + ASTContext &Context = getASTContext(); // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage // duration shall not be qualified by an address-space qualifier." // Since all parameters have automatic store duration, they can not have @@ -5181,8 +5189,8 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, Diag(IdLoc, diag::err_catch_param_not_objc_type); } - VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id, - T, TInfo, SC_None); + VarDecl *New = VarDecl::Create(Context, SemaRef.CurContext, StartLoc, IdLoc, + Id, T, TInfo, SC_None); New->setExceptionVariable(true); // In ARC, infer 'retaining' for variables of retainable type. @@ -5194,7 +5202,7 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, return New; } -Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { +Decl *SemaObjC::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { const DeclSpec &DS = D.getDeclSpec(); // We allow the "register" storage class on exception variables because @@ -5215,14 +5223,14 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { << DeclSpec::getSpecifierName(TSCS); D.getMutableDeclSpec().ClearStorageClassSpecs(); - DiagnoseFunctionSpecifiers(D.getDeclSpec()); + SemaRef.DiagnoseFunctionSpecifiers(D.getDeclSpec()); // Check that there are no default arguments inside the type of this // exception object (C++ only). if (getLangOpts().CPlusPlus) - CheckExtraCXXDefaultArguments(D); + SemaRef.CheckExtraCXXDefaultArguments(D); - TypeSourceInfo *TInfo = GetTypeForDeclarator(D); + TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D); QualType ExceptionType = TInfo->getType(); VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, @@ -5241,9 +5249,9 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { // Add the parameter declaration into this scope. S->AddDecl(New); if (D.getIdentifier()) - IdResolver.AddDecl(New); + SemaRef.IdResolver.AddDecl(New); - ProcessDeclAttributes(S, New, D); + SemaRef.ProcessDeclAttributes(S, New, D); if (New->hasAttr()) Diag(New->getLocation(), diag::err_block_on_nonlocal); @@ -5252,8 +5260,9 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { /// CollectIvarsToConstructOrDestruct - Collect those ivars which require /// initialization. -void Sema::CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, - SmallVectorImpl &Ivars) { +void SemaObjC::CollectIvarsToConstructOrDestruct( + ObjCInterfaceDecl *OI, SmallVectorImpl &Ivars) { + ASTContext &Context = getASTContext(); for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv; Iv= Iv->getNextIvar()) { QualType QT = Context.getBaseElementType(Iv->getType()); @@ -5262,11 +5271,12 @@ void Sema::CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, } } -void Sema::DiagnoseUseOfUnimplementedSelectors() { +void SemaObjC::DiagnoseUseOfUnimplementedSelectors() { + ASTContext &Context = getASTContext(); // Load referenced selectors from the external source. - if (ExternalSource) { + if (SemaRef.ExternalSource) { SmallVector, 4> Sels; - ExternalSource->ReadReferencedSelectors(Sels); + SemaRef.ExternalSource->ReadReferencedSelectors(Sels); for (unsigned I = 0, N = Sels.size(); I != N; ++I) ReferencedSelectors[Sels[I].first] = Sels[I].second; } @@ -5286,8 +5296,8 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() { } ObjCIvarDecl * -Sema::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, - const ObjCPropertyDecl *&PDecl) const { +SemaObjC::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, + const ObjCPropertyDecl *&PDecl) const { if (Method->isClassMethod()) return nullptr; const ObjCInterfaceDecl *IDecl = Method->getClassInterface(); @@ -5311,51 +5321,51 @@ Sema::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, } namespace { - /// Used by Sema::DiagnoseUnusedBackingIvarInAccessor to check if a property - /// accessor references the backing ivar. - class UnusedBackingIvarChecker : - public RecursiveASTVisitor { - public: - Sema &S; - const ObjCMethodDecl *Method; - const ObjCIvarDecl *IvarD; - bool AccessedIvar; - bool InvokedSelfMethod; - - UnusedBackingIvarChecker(Sema &S, const ObjCMethodDecl *Method, - const ObjCIvarDecl *IvarD) - : S(S), Method(Method), IvarD(IvarD), - AccessedIvar(false), InvokedSelfMethod(false) { - assert(IvarD); - } - - bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - if (E->getDecl() == IvarD) { - AccessedIvar = true; - return false; - } - return true; +/// Used by SemaObjC::DiagnoseUnusedBackingIvarInAccessor to check if a property +/// accessor references the backing ivar. +class UnusedBackingIvarChecker + : public RecursiveASTVisitor { +public: + Sema &S; + const ObjCMethodDecl *Method; + const ObjCIvarDecl *IvarD; + bool AccessedIvar; + bool InvokedSelfMethod; + + UnusedBackingIvarChecker(Sema &S, const ObjCMethodDecl *Method, + const ObjCIvarDecl *IvarD) + : S(S), Method(Method), IvarD(IvarD), AccessedIvar(false), + InvokedSelfMethod(false) { + assert(IvarD); + } + + bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { + if (E->getDecl() == IvarD) { + AccessedIvar = true; + return false; } + return true; + } - bool VisitObjCMessageExpr(ObjCMessageExpr *E) { - if (E->getReceiverKind() == ObjCMessageExpr::Instance && - S.isSelfExpr(E->getInstanceReceiver(), Method)) { - InvokedSelfMethod = true; - } - return true; + bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + if (E->getReceiverKind() == ObjCMessageExpr::Instance && + S.ObjC().isSelfExpr(E->getInstanceReceiver(), Method)) { + InvokedSelfMethod = true; } - }; + return true; + } +}; } // end anonymous namespace -void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S, - const ObjCImplementationDecl *ImplD) { +void SemaObjC::DiagnoseUnusedBackingIvarInAccessor( + Scope *S, const ObjCImplementationDecl *ImplD) { if (S->hasUnrecoverableErrorOccurred()) return; for (const auto *CurMethod : ImplD->instance_methods()) { unsigned DIAG = diag::warn_unused_property_backing_ivar; SourceLocation Loc = CurMethod->getLocation(); - if (Diags.isIgnored(DIAG, Loc)) + if (getDiagnostics().isIgnored(DIAG, Loc)) continue; const ObjCPropertyDecl *PDecl; @@ -5366,7 +5376,7 @@ void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S, if (CurMethod->isSynthesizedAccessorStub()) continue; - UnusedBackingIvarChecker Checker(*this, CurMethod, IV); + UnusedBackingIvarChecker Checker(SemaRef, CurMethod, IV); Checker.TraverseStmt(CurMethod->getBody()); if (Checker.AccessedIvar) continue; @@ -5381,3 +5391,299 @@ void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S, } } } + +QualType SemaObjC::AdjustParameterTypeForObjCAutoRefCount( + QualType T, SourceLocation NameLoc, TypeSourceInfo *TSInfo) { + ASTContext &Context = getASTContext(); + // In ARC, infer a lifetime qualifier for appropriate parameter types. + if (!getLangOpts().ObjCAutoRefCount || + T.getObjCLifetime() != Qualifiers::OCL_None || !T->isObjCLifetimeType()) + return T; + + Qualifiers::ObjCLifetime Lifetime; + + // Special cases for arrays: + // - if it's const, use __unsafe_unretained + // - otherwise, it's an error + if (T->isArrayType()) { + if (!T.isConstQualified()) { + if (SemaRef.DelayedDiagnostics.shouldDelayDiagnostics()) + SemaRef.DelayedDiagnostics.add( + sema::DelayedDiagnostic::makeForbiddenType( + NameLoc, diag::err_arc_array_param_no_ownership, T, false)); + else + Diag(NameLoc, diag::err_arc_array_param_no_ownership) + << TSInfo->getTypeLoc().getSourceRange(); + } + Lifetime = Qualifiers::OCL_ExplicitNone; + } else { + Lifetime = T->getObjCARCImplicitLifetime(); + } + T = Context.getLifetimeQualifiedType(T, Lifetime); + + return T; +} + +ObjCInterfaceDecl *SemaObjC::getObjCInterfaceDecl(const IdentifierInfo *&Id, + SourceLocation IdLoc, + bool DoTypoCorrection) { + // The third "scope" argument is 0 since we aren't enabling lazy built-in + // creation from this context. + NamedDecl *IDecl = SemaRef.LookupSingleName(SemaRef.TUScope, Id, IdLoc, + Sema::LookupOrdinaryName); + + if (!IDecl && DoTypoCorrection) { + // Perform typo correction at the given location, but only if we + // find an Objective-C class name. + DeclFilterCCC CCC{}; + if (TypoCorrection C = SemaRef.CorrectTypo( + DeclarationNameInfo(Id, IdLoc), Sema::LookupOrdinaryName, + SemaRef.TUScope, nullptr, CCC, Sema::CTK_ErrorRecovery)) { + SemaRef.diagnoseTypo(C, SemaRef.PDiag(diag::err_undef_interface_suggest) + << Id); + IDecl = C.getCorrectionDeclAs(); + Id = IDecl->getIdentifier(); + } + } + ObjCInterfaceDecl *Def = dyn_cast_or_null(IDecl); + // This routine must always return a class definition, if any. + if (Def && Def->getDefinition()) + Def = Def->getDefinition(); + return Def; +} + +bool SemaObjC::inferObjCARCLifetime(ValueDecl *decl) { + ASTContext &Context = getASTContext(); + QualType type = decl->getType(); + Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime(); + if (lifetime == Qualifiers::OCL_Autoreleasing) { + // Various kinds of declaration aren't allowed to be __autoreleasing. + unsigned kind = -1U; + if (VarDecl *var = dyn_cast(decl)) { + if (var->hasAttr()) + kind = 0; // __block + else if (!var->hasLocalStorage()) + kind = 1; // global + } else if (isa(decl)) { + kind = 3; // ivar + } else if (isa(decl)) { + kind = 2; // field + } + + if (kind != -1U) { + Diag(decl->getLocation(), diag::err_arc_autoreleasing_var) << kind; + } + } else if (lifetime == Qualifiers::OCL_None) { + // Try to infer lifetime. + if (!type->isObjCLifetimeType()) + return false; + + lifetime = type->getObjCARCImplicitLifetime(); + type = Context.getLifetimeQualifiedType(type, lifetime); + decl->setType(type); + } + + if (VarDecl *var = dyn_cast(decl)) { + // Thread-local variables cannot have lifetime. + if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone && + var->getTLSKind()) { + Diag(var->getLocation(), diag::err_arc_thread_ownership) + << var->getType(); + return true; + } + } + + return false; +} + +ObjCContainerDecl *SemaObjC::getObjCDeclContext() const { + return (dyn_cast_or_null(SemaRef.CurContext)); +} + +void SemaObjC::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { + if (!getLangOpts().CPlusPlus) + return; + if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { + ASTContext &Context = getASTContext(); + SmallVector ivars; + CollectIvarsToConstructOrDestruct(OID, ivars); + if (ivars.empty()) + return; + SmallVector AllToInit; + for (unsigned i = 0; i < ivars.size(); i++) { + FieldDecl *Field = ivars[i]; + if (Field->isInvalidDecl()) + continue; + + CXXCtorInitializer *Member; + InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field); + InitializationKind InitKind = + InitializationKind::CreateDefault(ObjCImplementation->getLocation()); + + InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, + std::nullopt); + ExprResult MemberInit = + InitSeq.Perform(SemaRef, InitEntity, InitKind, std::nullopt); + MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); + // Note, MemberInit could actually come back empty if no initialization + // is required (e.g., because it would call a trivial default constructor) + if (!MemberInit.get() || MemberInit.isInvalid()) + continue; + + Member = new (Context) + CXXCtorInitializer(Context, Field, SourceLocation(), SourceLocation(), + MemberInit.getAs(), SourceLocation()); + AllToInit.push_back(Member); + + // Be sure that the destructor is accessible and is marked as referenced. + if (const RecordType *RecordTy = + Context.getBaseElementType(Field->getType()) + ->getAs()) { + CXXRecordDecl *RD = cast(RecordTy->getDecl()); + if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(RD)) { + SemaRef.MarkFunctionReferenced(Field->getLocation(), Destructor); + SemaRef.CheckDestructorAccess( + Field->getLocation(), Destructor, + SemaRef.PDiag(diag::err_access_dtor_ivar) + << Context.getBaseElementType(Field->getType())); + } + } + } + ObjCImplementation->setIvarInitializers(Context, AllToInit.data(), + AllToInit.size()); + } +} + +/// TranslateIvarVisibility - Translate visibility from a token ID to an +/// AST enum value. +static ObjCIvarDecl::AccessControl +TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { + switch (ivarVisibility) { + default: + llvm_unreachable("Unknown visitibility kind"); + case tok::objc_private: + return ObjCIvarDecl::Private; + case tok::objc_public: + return ObjCIvarDecl::Public; + case tok::objc_protected: + return ObjCIvarDecl::Protected; + case tok::objc_package: + return ObjCIvarDecl::Package; + } +} + +/// ActOnIvar - Each ivar field of an objective-c class is passed into this +/// in order to create an IvarDecl object for it. +Decl *SemaObjC::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, + Expr *BitWidth, tok::ObjCKeywordKind Visibility) { + + const IdentifierInfo *II = D.getIdentifier(); + SourceLocation Loc = DeclStart; + if (II) + Loc = D.getIdentifierLoc(); + + // FIXME: Unnamed fields can be handled in various different ways, for + // example, unnamed unions inject all members into the struct namespace! + + TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D); + QualType T = TInfo->getType(); + + if (BitWidth) { + // 6.7.2.1p3, 6.7.2.1p4 + BitWidth = + SemaRef.VerifyBitField(Loc, II, T, /*IsMsStruct*/ false, BitWidth) + .get(); + if (!BitWidth) + D.setInvalidType(); + } else { + // Not a bitfield. + + // validate II. + } + if (T->isReferenceType()) { + Diag(Loc, diag::err_ivar_reference_type); + D.setInvalidType(); + } + // C99 6.7.2.1p8: A member of a structure or union may have any type other + // than a variably modified type. + else if (T->isVariablyModifiedType()) { + if (!SemaRef.tryToFixVariablyModifiedVarType( + TInfo, T, Loc, diag::err_typecheck_ivar_variable_size)) + D.setInvalidType(); + } + + // Get the visibility (access control) for this ivar. + ObjCIvarDecl::AccessControl ac = Visibility != tok::objc_not_keyword + ? TranslateIvarVisibility(Visibility) + : ObjCIvarDecl::None; + // Must set ivar's DeclContext to its enclosing interface. + ObjCContainerDecl *EnclosingDecl = + cast(SemaRef.CurContext); + if (!EnclosingDecl || EnclosingDecl->isInvalidDecl()) + return nullptr; + ObjCContainerDecl *EnclosingContext; + if (ObjCImplementationDecl *IMPDecl = + dyn_cast(EnclosingDecl)) { + if (getLangOpts().ObjCRuntime.isFragile()) { + // Case of ivar declared in an implementation. Context is that of its + // class. + EnclosingContext = IMPDecl->getClassInterface(); + assert(EnclosingContext && "Implementation has no class interface!"); + } else + EnclosingContext = EnclosingDecl; + } else { + if (ObjCCategoryDecl *CDecl = dyn_cast(EnclosingDecl)) { + if (getLangOpts().ObjCRuntime.isFragile() || !CDecl->IsClassExtension()) { + Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension(); + return nullptr; + } + } + EnclosingContext = EnclosingDecl; + } + + // Construct the decl. + ObjCIvarDecl *NewID = + ObjCIvarDecl::Create(getASTContext(), EnclosingContext, DeclStart, Loc, + II, T, TInfo, ac, BitWidth); + + if (T->containsErrors()) + NewID->setInvalidDecl(); + + if (II) { + NamedDecl *PrevDecl = + SemaRef.LookupSingleName(S, II, Loc, Sema::LookupMemberName, + RedeclarationKind::ForVisibleRedeclaration); + if (PrevDecl && SemaRef.isDeclInScope(PrevDecl, EnclosingContext, S) && + !isa(PrevDecl)) { + Diag(Loc, diag::err_duplicate_member) << II; + Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + NewID->setInvalidDecl(); + } + } + + // Process attributes attached to the ivar. + SemaRef.ProcessDeclAttributes(S, NewID, D); + + if (D.isInvalidType()) + NewID->setInvalidDecl(); + + // In ARC, infer 'retaining' for ivars of retainable type. + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewID)) + NewID->setInvalidDecl(); + + if (D.getDeclSpec().isModulePrivateSpecified()) + NewID->setModulePrivate(); + + if (II) { + // FIXME: When interfaces are DeclContexts, we'll need to add + // these to the interface. + S->AddDecl(NewID); + SemaRef.IdResolver.AddDecl(NewID); + } + + if (getLangOpts().ObjCRuntime.isNonFragile() && !NewID->isInvalidDecl() && + isa(EnclosingDecl)) + Diag(Loc, diag::warn_ivars_in_interface); + + return NewID; +} diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index bb4b116fd73c..e6c3fa51d54d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -52,6 +52,7 @@ #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaFixItUtils.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" @@ -109,7 +110,7 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) { // should diagnose them. if (A->getSemanticSpelling() != UnusedAttr::CXX11_maybe_unused && A->getSemanticSpelling() != UnusedAttr::C23_maybe_unused) { - const Decl *DC = cast_or_null(S.getCurObjCLexicalContext()); + const Decl *DC = cast_or_null(S.ObjC().getCurObjCLexicalContext()); if (DC && !DC->hasAttr()) S.Diag(Loc, diag::warn_used_but_marked_unused) << D; } @@ -1051,9 +1052,9 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, if (PlaceholderTy->getKind() == BuiltinType::ARCUnbridgedCast && (CT == VariadicMethod || (FDecl && FDecl->hasAttr()))) { - E = stripARCUnbridgedCast(E); + E = ObjC().stripARCUnbridgedCast(E); - // Otherwise, do normal placeholder checking. + // Otherwise, do normal placeholder checking. } else { ExprResult ExprRes = CheckPlaceholderExpr(E); if (ExprRes.isInvalid()) @@ -2797,7 +2798,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // If this reference is in an Objective-C method, then we need to do // some special Objective-C lookup, too. if (IvarLookupFollowUp) { - ExprResult E(LookupInObjCMethod(R, S, II, true)); + ExprResult E(ObjC().LookupInObjCMethod(R, S, II, true)); if (E.isInvalid()) return ExprError(); @@ -2882,7 +2883,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // reference the ivar. if (ObjCIvarDecl *Ivar = R.getAsSingle()) { R.clear(); - ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier())); + ExprResult E(ObjC().LookupInObjCMethod(R, S, Ivar->getIdentifier())); // In a hopelessly buggy code, Objective-C instance variable // lookup fails and no expression will be built to reference it. if (!E.isInvalid() && !E.get()) @@ -3028,166 +3029,6 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( return BuildDeclarationNameExpr(SS, R, /* ADL */ false); } -/// The parser has read a name in, and Sema has detected that we're currently -/// inside an ObjC method. Perform some additional checks and determine if we -/// should form a reference to an ivar. -/// -/// Ideally, most of this would be done by lookup, but there's -/// actually quite a lot of extra work involved. -DeclResult Sema::LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S, - IdentifierInfo *II) { - SourceLocation Loc = Lookup.getNameLoc(); - ObjCMethodDecl *CurMethod = getCurMethodDecl(); - - // Check for error condition which is already reported. - if (!CurMethod) - return DeclResult(true); - - // There are two cases to handle here. 1) scoped lookup could have failed, - // in which case we should look for an ivar. 2) scoped lookup could have - // found a decl, but that decl is outside the current instance method (i.e. - // a global variable). In these two cases, we do a lookup for an ivar with - // this name, if the lookup sucedes, we replace it our current decl. - - // If we're in a class method, we don't normally want to look for - // ivars. But if we don't find anything else, and there's an - // ivar, that's an error. - bool IsClassMethod = CurMethod->isClassMethod(); - - bool LookForIvars; - if (Lookup.empty()) - LookForIvars = true; - else if (IsClassMethod) - LookForIvars = false; - else - LookForIvars = (Lookup.isSingleResult() && - Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); - ObjCInterfaceDecl *IFace = nullptr; - if (LookForIvars) { - IFace = CurMethod->getClassInterface(); - ObjCInterfaceDecl *ClassDeclared; - ObjCIvarDecl *IV = nullptr; - if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) { - // Diagnose using an ivar in a class method. - if (IsClassMethod) { - Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName(); - return DeclResult(true); - } - - // Diagnose the use of an ivar outside of the declaring class. - if (IV->getAccessControl() == ObjCIvarDecl::Private && - !declaresSameEntity(ClassDeclared, IFace) && - !getLangOpts().DebuggerSupport) - Diag(Loc, diag::err_private_ivar_access) << IV->getDeclName(); - - // Success. - return IV; - } - } else if (CurMethod->isInstanceMethod()) { - // We should warn if a local variable hides an ivar. - if (ObjCInterfaceDecl *IFace = CurMethod->getClassInterface()) { - ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { - if (IV->getAccessControl() != ObjCIvarDecl::Private || - declaresSameEntity(IFace, ClassDeclared)) - Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); - } - } - } else if (Lookup.isSingleResult() && - Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) { - // If accessing a stand-alone ivar in a class method, this is an error. - if (const ObjCIvarDecl *IV = - dyn_cast(Lookup.getFoundDecl())) { - Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName(); - return DeclResult(true); - } - } - - // Didn't encounter an error, didn't find an ivar. - return DeclResult(false); -} - -ExprResult Sema::BuildIvarRefExpr(Scope *S, SourceLocation Loc, - ObjCIvarDecl *IV) { - ObjCMethodDecl *CurMethod = getCurMethodDecl(); - assert(CurMethod && CurMethod->isInstanceMethod() && - "should not reference ivar from this context"); - - ObjCInterfaceDecl *IFace = CurMethod->getClassInterface(); - assert(IFace && "should not reference ivar from this context"); - - // If we're referencing an invalid decl, just return this as a silent - // error node. The error diagnostic was already emitted on the decl. - if (IV->isInvalidDecl()) - return ExprError(); - - // Check if referencing a field with __attribute__((deprecated)). - if (DiagnoseUseOfDecl(IV, Loc)) - return ExprError(); - - // FIXME: This should use a new expr for a direct reference, don't - // turn this into Self->ivar, just return a BareIVarExpr or something. - IdentifierInfo &II = Context.Idents.get("self"); - UnqualifiedId SelfName; - SelfName.setImplicitSelfParam(&II); - CXXScopeSpec SelfScopeSpec; - SourceLocation TemplateKWLoc; - ExprResult SelfExpr = - ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, SelfName, - /*HasTrailingLParen=*/false, - /*IsAddressOfOperand=*/false); - if (SelfExpr.isInvalid()) - return ExprError(); - - SelfExpr = DefaultLvalueConversion(SelfExpr.get()); - if (SelfExpr.isInvalid()) - return ExprError(); - - MarkAnyDeclReferenced(Loc, IV, true); - - ObjCMethodFamily MF = CurMethod->getMethodFamily(); - if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize && - !IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV)) - Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName(); - - ObjCIvarRefExpr *Result = new (Context) - ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc, - IV->getLocation(), SelfExpr.get(), true, true); - - if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { - if (!isUnevaluatedContext() && - !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc)) - getCurFunction()->recordUseOfWeak(Result); - } - if (getLangOpts().ObjCAutoRefCount && !isUnevaluatedContext()) - if (const BlockDecl *BD = CurContext->getInnermostBlockDecl()) - ImplicitlyRetainedSelfLocs.push_back({Loc, BD}); - - return Result; -} - -/// The parser has read a name in, and Sema has detected that we're currently -/// inside an ObjC method. Perform some additional checks and determine if we -/// should form a reference to an ivar. If so, build an expression referencing -/// that ivar. -ExprResult -Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, - IdentifierInfo *II, bool AllowBuiltinCreation) { - // FIXME: Integrate this lookup step into LookupParsedName. - DeclResult Ivar = LookupIvarInObjCMethod(Lookup, S, II); - if (Ivar.isInvalid()) - return ExprError(); - if (Ivar.isUsable()) - return BuildIvarRefExpr(S, Lookup.getNameLoc(), - cast(Ivar.get())); - - if (Lookup.empty() && II && AllowBuiltinCreation) - LookupBuiltin(Lookup); - - // Sentinel value saying that we didn't do anything special. - return ExprResult(false); -} - /// Cast a base object to a member's actual type. /// /// There are two relevant checks: @@ -5419,8 +5260,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // Use custom logic if this should be the pseudo-object subscript // expression. if (!LangOpts.isSubscriptPointerArithmetic()) - return BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, nullptr, - nullptr); + return ObjC().BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, + nullptr, nullptr); ResultType = PTy->getPointeeType(); } else if (const PointerType *PTy = RHSTy->getAs()) { @@ -6188,7 +6029,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, if (Arg->getType() == Context.ARCUnbridgedCastTy && FDecl && FDecl->hasAttr() && (!Param || !Param->hasAttr())) - Arg = stripARCUnbridgedCast(Arg); + Arg = ObjC().stripARCUnbridgedCast(Arg); else if (getLangOpts().ObjCAutoRefCount && FDecl && FDecl->hasAttr() && (!Param || !Param->hasAttr())) @@ -7500,21 +7341,6 @@ void Sema::maybeExtendBlockObject(ExprResult &E) { Cleanup.setExprNeedsCleanups(true); } -/// Prepare a conversion of the given expression to an ObjC object -/// pointer type. -CastKind Sema::PrepareCastToObjCObjectPointer(ExprResult &E) { - QualType type = E.get()->getType(); - if (type->isObjCObjectPointerType()) { - return CK_BitCast; - } else if (type->isBlockPointerType()) { - maybeExtendBlockObject(E); - return CK_BlockPointerToObjCPointerCast; - } else { - assert(type->isPointerType()); - return CK_CPointerToObjCPointerCast; - } -} - /// Prepares for a scalar cast, performing all the necessary stages /// except the final cast and returning the kind required. CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { @@ -8065,9 +7891,9 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, if (getLangOpts().CPlusPlus && !castType->isVoidType()) Diag(LParenLoc, diag::warn_old_style_cast) << CastExpr->getSourceRange(); - CheckTollFreeBridgeCast(castType, CastExpr); + ObjC().CheckTollFreeBridgeCast(castType, CastExpr); - CheckObjCBridgeRelatedCast(castType, CastExpr); + ObjC().CheckObjCBridgeRelatedCast(castType, CastExpr); DiscardMisalignedMemberAddress(castType.getTypePtr(), CastExpr); @@ -8817,8 +8643,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, if (!checkConditionalNullPointer(*this, LHS, RHSTy)) return RHSTy; // All objective-c pointer type analysis is done here. - QualType compositeType = FindCompositeObjCPointerType(LHS, RHS, - QuestionLoc); + QualType compositeType = + ObjC().FindCompositeObjCPointerType(LHS, RHS, QuestionLoc); if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); if (!compositeType.isNull()) @@ -8862,148 +8688,6 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, return QualType(); } -/// FindCompositeObjCPointerType - Helper method to find composite type of -/// two objective-c pointer types of the two input expressions. -QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, - SourceLocation QuestionLoc) { - QualType LHSTy = LHS.get()->getType(); - QualType RHSTy = RHS.get()->getType(); - - // Handle things like Class and struct objc_class*. Here we case the result - // to the pseudo-builtin, because that will be implicitly cast back to the - // redefinition type if an attempt is made to access its fields. - if (LHSTy->isObjCClassType() && - (Context.hasSameType(RHSTy, Context.getObjCClassRedefinitionType()))) { - RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_CPointerToObjCPointerCast); - return LHSTy; - } - if (RHSTy->isObjCClassType() && - (Context.hasSameType(LHSTy, Context.getObjCClassRedefinitionType()))) { - LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_CPointerToObjCPointerCast); - return RHSTy; - } - // And the same for struct objc_object* / id - if (LHSTy->isObjCIdType() && - (Context.hasSameType(RHSTy, Context.getObjCIdRedefinitionType()))) { - RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_CPointerToObjCPointerCast); - return LHSTy; - } - if (RHSTy->isObjCIdType() && - (Context.hasSameType(LHSTy, Context.getObjCIdRedefinitionType()))) { - LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_CPointerToObjCPointerCast); - return RHSTy; - } - // And the same for struct objc_selector* / SEL - if (Context.isObjCSelType(LHSTy) && - (Context.hasSameType(RHSTy, Context.getObjCSelRedefinitionType()))) { - RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_BitCast); - return LHSTy; - } - if (Context.isObjCSelType(RHSTy) && - (Context.hasSameType(LHSTy, Context.getObjCSelRedefinitionType()))) { - LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_BitCast); - return RHSTy; - } - // Check constraints for Objective-C object pointers types. - if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) { - - if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { - // Two identical object pointer types are always compatible. - return LHSTy; - } - const ObjCObjectPointerType *LHSOPT = LHSTy->castAs(); - const ObjCObjectPointerType *RHSOPT = RHSTy->castAs(); - QualType compositeType = LHSTy; - - // If both operands are interfaces and either operand can be - // assigned to the other, use that type as the composite - // type. This allows - // xxx ? (A*) a : (B*) b - // where B is a subclass of A. - // - // Additionally, as for assignment, if either type is 'id' - // allow silent coercion. Finally, if the types are - // incompatible then make sure to use 'id' as the composite - // type so the result is acceptable for sending messages to. - - // FIXME: Consider unifying with 'areComparableObjCPointerTypes'. - // It could return the composite type. - if (!(compositeType = - Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull()) { - // Nothing more to do. - } else if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) { - compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy; - } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) { - compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy; - } else if ((LHSOPT->isObjCQualifiedIdType() || - RHSOPT->isObjCQualifiedIdType()) && - Context.ObjCQualifiedIdTypesAreCompatible(LHSOPT, RHSOPT, - true)) { - // Need to handle "id" explicitly. - // GCC allows qualified id and any Objective-C type to devolve to - // id. Currently localizing to here until clear this should be - // part of ObjCQualifiedIdTypesAreCompatible. - compositeType = Context.getObjCIdType(); - } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) { - compositeType = Context.getObjCIdType(); - } else { - Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) - << LHSTy << RHSTy - << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); - QualType incompatTy = Context.getObjCIdType(); - LHS = ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast); - RHS = ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast); - return incompatTy; - } - // The object pointer types are compatible. - LHS = ImpCastExprToType(LHS.get(), compositeType, CK_BitCast); - RHS = ImpCastExprToType(RHS.get(), compositeType, CK_BitCast); - return compositeType; - } - // Check Objective-C object pointer types and 'void *' - if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) { - if (getLangOpts().ObjCAutoRefCount) { - // ARC forbids the implicit conversion of object pointers to 'void *', - // so these types are not compatible. - Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy - << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); - LHS = RHS = true; - return QualType(); - } - QualType lhptee = LHSTy->castAs()->getPointeeType(); - QualType rhptee = RHSTy->castAs()->getPointeeType(); - QualType destPointee - = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); - QualType destType = Context.getPointerType(destPointee); - // Add qualifiers if necessary. - LHS = ImpCastExprToType(LHS.get(), destType, CK_NoOp); - // Promote to void*. - RHS = ImpCastExprToType(RHS.get(), destType, CK_BitCast); - return destType; - } - if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { - if (getLangOpts().ObjCAutoRefCount) { - // ARC forbids the implicit conversion of object pointers to 'void *', - // so these types are not compatible. - Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy - << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); - LHS = RHS = true; - return QualType(); - } - QualType lhptee = LHSTy->castAs()->getPointeeType(); - QualType rhptee = RHSTy->castAs()->getPointeeType(); - QualType destPointee - = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); - QualType destType = Context.getPointerType(destPointee); - // Add qualifiers if necessary. - RHS = ImpCastExprToType(RHS.get(), destType, CK_NoOp); - // Promote to void*. - LHS = ImpCastExprToType(LHS.get(), destType, CK_BitCast); - return destType; - } - return QualType(); -} - /// SuggestParentheses - Emit a note with a fixit hint that wraps /// ParenRange in parentheses. static void SuggestParentheses(Sema &Self, SourceLocation Loc, @@ -9868,7 +9552,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, checkObjCPointerTypesForAssignment(*this, LHSType, RHSType); if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && result == Compatible && - !CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType)) + !ObjC().CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType)) result = IncompatibleObjCWeakRef; return result; } @@ -10094,7 +9778,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, return Incompatible; Sema::AssignConvertType result = Compatible; if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - !CheckObjCARCUnavailableWeakConversion(LHSType, RHSType)) + !ObjC().CheckObjCARCUnavailableWeakConversion(LHSType, RHSType)) result = IncompatibleObjCWeakRef; return result; } @@ -10200,16 +9884,16 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, // diagnostics and just checking for errors, e.g., during overload // resolution, return Incompatible to indicate the failure. if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - CheckObjCConversion(SourceRange(), Ty, E, - CheckedConversionKind::Implicit, Diagnose, - DiagnoseCFAudited) != ACR_okay) { + ObjC().CheckObjCConversion(SourceRange(), Ty, E, + CheckedConversionKind::Implicit, Diagnose, + DiagnoseCFAudited) != SemaObjC::ACR_okay) { if (!Diagnose) return Incompatible; } if (getLangOpts().ObjC && - (CheckObjCBridgeRelatedConversions(E->getBeginLoc(), LHSType, - E->getType(), E, Diagnose) || - CheckConversionToObjCLiteral(LHSType, E, Diagnose))) { + (ObjC().CheckObjCBridgeRelatedConversions(E->getBeginLoc(), LHSType, + E->getType(), E, Diagnose) || + ObjC().CheckConversionToObjCLiteral(LHSType, E, Diagnose))) { if (!Diagnose) return Incompatible; // Replace the expression with a corrected version and continue so we @@ -12026,19 +11710,20 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) { return false; // Try to find the -isEqual: method. - Selector IsEqualSel = S.NSAPIObj->getIsEqualSelector(); - ObjCMethodDecl *Method = S.LookupMethodInObjectType(IsEqualSel, - InterfaceType, - /*IsInstance=*/true); + Selector IsEqualSel = S.ObjC().NSAPIObj->getIsEqualSelector(); + ObjCMethodDecl *Method = + S.ObjC().LookupMethodInObjectType(IsEqualSel, InterfaceType, + /*IsInstance=*/true); if (!Method) { if (Type->isObjCIdType()) { // For 'id', just check the global pool. - Method = S.LookupInstanceMethodInGlobalPool(IsEqualSel, SourceRange(), - /*receiverId=*/true); + Method = + S.ObjC().LookupInstanceMethodInGlobalPool(IsEqualSel, SourceRange(), + /*receiverId=*/true); } else { // Check protocols. - Method = S.LookupMethodInQualifiedType(IsEqualSel, Type, - /*IsInstance=*/true); + Method = S.ObjC().LookupMethodInQualifiedType(IsEqualSel, Type, + /*IsInstance=*/true); } } @@ -12056,48 +11741,6 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) { return true; } -Sema::ObjCLiteralKind Sema::CheckLiteralKind(Expr *FromE) { - FromE = FromE->IgnoreParenImpCasts(); - switch (FromE->getStmtClass()) { - default: - break; - case Stmt::ObjCStringLiteralClass: - // "string literal" - return LK_String; - case Stmt::ObjCArrayLiteralClass: - // "array literal" - return LK_Array; - case Stmt::ObjCDictionaryLiteralClass: - // "dictionary literal" - return LK_Dictionary; - case Stmt::BlockExprClass: - return LK_Block; - case Stmt::ObjCBoxedExprClass: { - Expr *Inner = cast(FromE)->getSubExpr()->IgnoreParens(); - switch (Inner->getStmtClass()) { - case Stmt::IntegerLiteralClass: - case Stmt::FloatingLiteralClass: - case Stmt::CharacterLiteralClass: - case Stmt::ObjCBoolLiteralExprClass: - case Stmt::CXXBoolLiteralExprClass: - // "numeric literal" - return LK_Numeric; - case Stmt::ImplicitCastExprClass: { - CastKind CK = cast(Inner)->getCastKind(); - // Boolean literals can be represented by implicit casts. - if (CK == CK_IntegralToBoolean || CK == CK_IntegralCast) - return LK_Numeric; - break; - } - default: - break; - } - return LK_Boxed; - } - } - return LK_None; -} - static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, ExprResult &LHS, ExprResult &RHS, BinaryOperator::Opcode Opc){ @@ -12120,13 +11763,13 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, // This should be kept in sync with warn_objc_literal_comparison. // LK_String should always be after the other literals, since it has its own // warning flag. - Sema::ObjCLiteralKind LiteralKind = S.CheckLiteralKind(Literal); - assert(LiteralKind != Sema::LK_Block); - if (LiteralKind == Sema::LK_None) { + SemaObjC::ObjCLiteralKind LiteralKind = S.ObjC().CheckLiteralKind(Literal); + assert(LiteralKind != SemaObjC::LK_Block); + if (LiteralKind == SemaObjC::LK_None) { llvm_unreachable("Unknown Objective-C object literal kind"); } - if (LiteralKind == Sema::LK_String) + if (LiteralKind == SemaObjC::LK_String) S.Diag(Loc, diag::warn_objc_string_literal_comparison) << Literal->getSourceRange(); else @@ -12922,18 +12565,18 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, if (LHSIsNull && !RHSIsNull) { Expr *E = LHS.get(); if (getLangOpts().ObjCAutoRefCount) - CheckObjCConversion(SourceRange(), RHSType, E, - CheckedConversionKind::Implicit); + ObjC().CheckObjCConversion(SourceRange(), RHSType, E, + CheckedConversionKind::Implicit); LHS = ImpCastExprToType(E, RHSType, RPT ? CK_BitCast :CK_CPointerToObjCPointerCast); } else { Expr *E = RHS.get(); if (getLangOpts().ObjCAutoRefCount) - CheckObjCConversion(SourceRange(), LHSType, E, - CheckedConversionKind::Implicit, - /*Diagnose=*/true, - /*DiagnoseCFAudited=*/false, Opc); + ObjC().CheckObjCConversion(SourceRange(), LHSType, E, + CheckedConversionKind::Implicit, + /*Diagnose=*/true, + /*DiagnoseCFAudited=*/false, Opc); RHS = ImpCastExprToType(E, LHSType, LPT ? CK_BitCast :CK_CPointerToObjCPointerCast); } @@ -14144,7 +13787,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, const Expr *InnerLHS = LHSExpr->IgnoreParenCasts(); const DeclRefExpr *DRE = dyn_cast(InnerLHS); if (!DRE || DRE->getDecl()->hasAttr()) - checkRetainCycles(LHSExpr, RHS.get()); + ObjC().checkRetainCycles(LHSExpr, RHS.get()); } if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong || @@ -17091,61 +16734,6 @@ ExprResult Sema::BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy, SourceLocExpr(Context, Kind, ResultTy, BuiltinLoc, RPLoc, ParentContext); } -bool Sema::CheckConversionToObjCLiteral(QualType DstType, Expr *&Exp, - bool Diagnose) { - if (!getLangOpts().ObjC) - return false; - - const ObjCObjectPointerType *PT = DstType->getAs(); - if (!PT) - return false; - const ObjCInterfaceDecl *ID = PT->getInterfaceDecl(); - - // Ignore any parens, implicit casts (should only be - // array-to-pointer decays), and not-so-opaque values. The last is - // important for making this trigger for property assignments. - Expr *SrcExpr = Exp->IgnoreParenImpCasts(); - if (OpaqueValueExpr *OV = dyn_cast(SrcExpr)) - if (OV->getSourceExpr()) - SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts(); - - if (auto *SL = dyn_cast(SrcExpr)) { - if (!PT->isObjCIdType() && - !(ID && ID->getIdentifier()->isStr("NSString"))) - return false; - if (!SL->isOrdinary()) - return false; - - if (Diagnose) { - Diag(SL->getBeginLoc(), diag::err_missing_atsign_prefix) - << /*string*/0 << FixItHint::CreateInsertion(SL->getBeginLoc(), "@"); - Exp = BuildObjCStringLiteral(SL->getBeginLoc(), SL).get(); - } - return true; - } - - if ((isa(SrcExpr) || isa(SrcExpr) || - isa(SrcExpr) || isa(SrcExpr) || - isa(SrcExpr)) && - !SrcExpr->isNullPointerConstant( - getASTContext(), Expr::NPC_NeverValueDependent)) { - if (!ID || !ID->getIdentifier()->isStr("NSNumber")) - return false; - if (Diagnose) { - Diag(SrcExpr->getBeginLoc(), diag::err_missing_atsign_prefix) - << /*number*/1 - << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), "@"); - Expr *NumLit = - BuildObjCNumericLiteral(SrcExpr->getBeginLoc(), SrcExpr).get(); - if (NumLit) - Exp = NumLit; - } - return true; - } - - return false; -} - static bool maybeDiagnoseAssignmentToFunction(Sema &S, QualType DstType, const Expr *SrcExpr) { if (!DstType->isFunctionPointerType() || @@ -17439,10 +17027,10 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, FirstType, /*TakingAddress=*/true); if (CheckInferredResultType) - EmitRelatedResultTypeNote(SrcExpr); + ObjC().EmitRelatedResultTypeNote(SrcExpr); if (Action == AA_Returning && ConvTy == IncompatiblePointer) - EmitRelatedResultTypeNoteForReturn(DstType); + ObjC().EmitRelatedResultTypeNoteForReturn(DstType); if (Complained) *Complained = true; @@ -20611,7 +20199,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { Selector Sel = ME->getSelector(); // self = [ init...] - if (isSelfExpr(Op->getLHS()) && ME->getMethodFamily() == OMF_init) + if (ObjC().isSelfExpr(Op->getLHS()) && ME->getMethodFamily() == OMF_init) diagnostic = diag::warn_condition_is_idiomatic_assignment; // = [ nextObject] @@ -21342,8 +20930,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { // ARC unbridged casts. case BuiltinType::ARCUnbridgedCast: { - Expr *realCast = stripARCUnbridgedCast(E); - diagnoseARCUnbridgedCast(realCast); + Expr *realCast = ObjC().stripARCUnbridgedCast(E); + ObjC().diagnoseARCUnbridgedCast(realCast); return realCast; } @@ -21459,61 +21047,6 @@ bool Sema::CheckCaseExpression(Expr *E) { return false; } -/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. -ExprResult -Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { - assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) && - "Unknown Objective-C Boolean value!"); - QualType BoolT = Context.ObjCBuiltinBoolTy; - if (!Context.getBOOLDecl()) { - LookupResult Result(*this, &Context.Idents.get("BOOL"), OpLoc, - Sema::LookupOrdinaryName); - if (LookupName(Result, getCurScope()) && Result.isSingleResult()) { - NamedDecl *ND = Result.getFoundDecl(); - if (TypedefDecl *TD = dyn_cast(ND)) - Context.setBOOLDecl(TD); - } - } - if (Context.getBOOLDecl()) - BoolT = Context.getBOOLType(); - return new (Context) - ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes, BoolT, OpLoc); -} - -ExprResult Sema::ActOnObjCAvailabilityCheckExpr( - llvm::ArrayRef AvailSpecs, SourceLocation AtLoc, - SourceLocation RParen) { - auto FindSpecVersion = - [&](StringRef Platform) -> std::optional { - auto Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) { - return Spec.getPlatform() == Platform; - }); - // Transcribe the "ios" availability check to "maccatalyst" when compiling - // for "maccatalyst" if "maccatalyst" is not specified. - if (Spec == AvailSpecs.end() && Platform == "maccatalyst") { - Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) { - return Spec.getPlatform() == "ios"; - }); - } - if (Spec == AvailSpecs.end()) - return std::nullopt; - return Spec->getVersion(); - }; - - VersionTuple Version; - if (auto MaybeVersion = - FindSpecVersion(Context.getTargetInfo().getPlatformName())) - Version = *MaybeVersion; - - // The use of `@available` in the enclosing context should be analyzed to - // warn when it's used inappropriately (i.e. not if(@available)). - if (FunctionScopeInfo *Context = getCurFunctionAvailabilityContext()) - Context->HasPotentialAvailabilityViolations = true; - - return new (Context) - ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy); -} - ExprResult Sema::CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, ArrayRef SubExprs, QualType T) { if (!Context.getLangOpts().RecoveryAST) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c181092113e1..34e12078a8c9 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -41,6 +41,7 @@ #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaLambda.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/APInt.h" @@ -4619,10 +4620,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, if (From->getType()->isObjCObjectPointerType() && ToType->isObjCObjectPointerType()) - EmitRelatedResultTypeNote(From); + ObjC().EmitRelatedResultTypeNote(From); } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - !CheckObjCARCUnavailableWeakConversion(ToType, - From->getType())) { + !ObjC().CheckObjCARCUnavailableWeakConversion(ToType, + From->getType())) { if (Action == AA_Initializing) Diag(From->getBeginLoc(), diag::err_arc_weak_unavailable_assign); else @@ -4657,11 +4658,11 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // FIXME: doing this here is really ugly. if (Kind == CK_BlockPointerToObjCPointerCast) { ExprResult E = From; - (void) PrepareCastToObjCObjectPointer(E); + (void)ObjC().PrepareCastToObjCObjectPointer(E); From = E.get(); } if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) - CheckObjCConversion(SourceRange(), NewToType, From, CCK); + ObjC().CheckObjCConversion(SourceRange(), NewToType, From, CCK); From = ImpCastExprToType(From, NewToType, Kind, VK_PRValue, &BasePath, CCK) .get(); break; @@ -7098,7 +7099,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, return Composite; // Similarly, attempt to find composite type of two objective-c pointers. - Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc); + Composite = ObjC().FindCompositeObjCPointerType(LHS, RHS, QuestionLoc); if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); if (!Composite.isNull()) @@ -8691,8 +8692,8 @@ static ExprResult attemptRecovery(Sema &SemaRef, NewSS, /*TemplateKWLoc*/ SourceLocation(), R, /*TemplateArgs*/ nullptr, /*S*/ nullptr); } else if (auto *Ivar = dyn_cast(ND)) { - return SemaRef.LookupInObjCMethod(R, Consumer.getScope(), - Ivar->getIdentifier()); + return SemaRef.ObjC().LookupInObjCMethod(R, Consumer.getScope(), + Ivar->getIdentifier()); } } diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 244488a0b562..9aa60204bf29 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -21,6 +21,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" using namespace clang; @@ -1518,9 +1519,8 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, if (warn) { if (ObjCMethodDecl *MD = S.getCurMethodDecl()) { ObjCMethodFamily MF = MD->getMethodFamily(); - warn = (MF != OMF_init && MF != OMF_dealloc && - MF != OMF_finalize && - !S.IvarBacksCurrentMethodAccessor(IDecl, MD, IV)); + warn = (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize && + !S.ObjC().IvarBacksCurrentMethodAccessor(IDecl, MD, IV)); } if (warn) S.Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName(); @@ -1658,9 +1658,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, } // Normal property access. - return S.HandleExprPropertyRefExpr(OPT, BaseExpr.get(), OpLoc, MemberName, - MemberLoc, SourceLocation(), QualType(), - false); + return S.ObjC().HandleExprPropertyRefExpr( + OPT, BaseExpr.get(), OpLoc, MemberName, MemberLoc, SourceLocation(), + QualType(), false); } if (BaseType->isExtVectorBoolType()) { diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index b13a9d426983..462ab2c952b6 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -17,6 +17,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/Analysis/DomainSpecific/CocoaConventions.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Edit/Commit.h" #include "clang/Edit/Rewriters.h" #include "clang/Lex/Preprocessor.h" @@ -25,6 +26,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ConvertUTF.h" #include @@ -33,8 +35,9 @@ using namespace clang; using namespace sema; using llvm::ArrayRef; -ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, - ArrayRef Strings) { +ExprResult SemaObjC::ParseObjCStringLiteral(SourceLocation *AtLocs, + ArrayRef Strings) { + ASTContext &Context = getASTContext(); // Most ObjC strings are formed out of a single piece. However, we *can* // have strings formed out of multiple @ strings with multiple pptokens in // each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one @@ -79,7 +82,9 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, return BuildObjCStringLiteral(AtLocs[0], S); } -ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){ +ExprResult SemaObjC::BuildObjCStringLiteral(SourceLocation AtLoc, + StringLiteral *S) { + ASTContext &Context = getASTContext(); // Verify that this composite string is acceptable for ObjC strings. if (CheckObjCString(S)) return true; @@ -100,8 +105,8 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){ else NSIdent = &Context.Idents.get(StringClass); - NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc, - LookupOrdinaryName); + NamedDecl *IF = SemaRef.LookupSingleName(SemaRef.TUScope, NSIdent, AtLoc, + Sema::LookupOrdinaryName); if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null(IF)) { Context.setObjCConstantStringInterface(StrIF); Ty = Context.getObjCConstantStringInterface(); @@ -115,8 +120,8 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){ } } else { IdentifierInfo *NSIdent = NSAPIObj->getNSClassId(NSAPI::ClassId_NSString); - NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc, - LookupOrdinaryName); + NamedDecl *IF = SemaRef.LookupSingleName(SemaRef.TUScope, NSIdent, AtLoc, + Sema::LookupOrdinaryName); if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null(IF)) { Context.setObjCConstantStringInterface(StrIF); Ty = Context.getObjCConstantStringInterface(); @@ -168,25 +173,25 @@ static bool validateBoxingMethod(Sema &S, SourceLocation Loc, } /// Maps ObjCLiteralKind to NSClassIdKindKind -static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind( - Sema::ObjCLiteralKind LiteralKind) { +static NSAPI::NSClassIdKindKind +ClassKindFromLiteralKind(SemaObjC::ObjCLiteralKind LiteralKind) { switch (LiteralKind) { - case Sema::LK_Array: - return NSAPI::ClassId_NSArray; - case Sema::LK_Dictionary: - return NSAPI::ClassId_NSDictionary; - case Sema::LK_Numeric: - return NSAPI::ClassId_NSNumber; - case Sema::LK_String: - return NSAPI::ClassId_NSString; - case Sema::LK_Boxed: - return NSAPI::ClassId_NSValue; - - // there is no corresponding matching - // between LK_None/LK_Block and NSClassIdKindKind - case Sema::LK_Block: - case Sema::LK_None: - break; + case SemaObjC::LK_Array: + return NSAPI::ClassId_NSArray; + case SemaObjC::LK_Dictionary: + return NSAPI::ClassId_NSDictionary; + case SemaObjC::LK_Numeric: + return NSAPI::ClassId_NSNumber; + case SemaObjC::LK_String: + return NSAPI::ClassId_NSString; + case SemaObjC::LK_Boxed: + return NSAPI::ClassId_NSValue; + + // there is no corresponding matching + // between LK_None/LK_Block and NSClassIdKindKind + case SemaObjC::LK_Block: + case SemaObjC::LK_None: + break; } llvm_unreachable("LiteralKind can't be converted into a ClassKind"); } @@ -194,12 +199,13 @@ static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind( /// Validates ObjCInterfaceDecl availability. /// ObjCInterfaceDecl, used to create ObjC literals, should be defined /// if clang not in a debugger mode. -static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl, - SourceLocation Loc, - Sema::ObjCLiteralKind LiteralKind) { +static bool +ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl, + SourceLocation Loc, + SemaObjC::ObjCLiteralKind LiteralKind) { if (!Decl) { NSAPI::NSClassIdKindKind Kind = ClassKindFromLiteralKind(LiteralKind); - IdentifierInfo *II = S.NSAPIObj->getNSClassId(Kind); + IdentifierInfo *II = S.ObjC().NSAPIObj->getNSClassId(Kind); S.Diag(Loc, diag::err_undeclared_objc_literal_class) << II->getName() << LiteralKind; return false; @@ -216,11 +222,11 @@ static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl, /// Looks up ObjCInterfaceDecl of a given NSClassIdKindKind. /// Used to create ObjC literals, such as NSDictionary (@{}), /// NSArray (@[]) and Boxed Expressions (@()) -static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S, - SourceLocation Loc, - Sema::ObjCLiteralKind LiteralKind) { +static ObjCInterfaceDecl * +LookupObjCInterfaceDeclForLiteral(Sema &S, SourceLocation Loc, + SemaObjC::ObjCLiteralKind LiteralKind) { NSAPI::NSClassIdKindKind ClassKind = ClassKindFromLiteralKind(LiteralKind); - IdentifierInfo *II = S.NSAPIObj->getNSClassId(ClassKind); + IdentifierInfo *II = S.ObjC().NSAPIObj->getNSClassId(ClassKind); NamedDecl *IF = S.LookupSingleName(S.TUScope, II, Loc, Sema::LookupOrdinaryName); ObjCInterfaceDecl *ID = dyn_cast_or_null(IF); @@ -240,7 +246,7 @@ static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S, /// Retrieve the NSNumber factory method that should be used to create /// an Objective-C literal for the given type. -static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, +static ObjCMethodDecl *getNSNumberFactoryMethod(SemaObjC &S, SourceLocation Loc, QualType NumberType, bool isLiteral = false, SourceRange R = SourceRange()) { @@ -262,13 +268,13 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind, /*Instance=*/false); - ASTContext &CX = S.Context; + ASTContext &CX = S.SemaRef.Context; // Look up the NSNumber class, if we haven't done so already. It's cached // in the Sema instance. if (!S.NSNumberDecl) { - S.NSNumberDecl = LookupObjCInterfaceDeclForLiteral(S, Loc, - Sema::LK_Numeric); + S.NSNumberDecl = + LookupObjCInterfaceDeclForLiteral(S.SemaRef, Loc, SemaObjC::LK_Numeric); if (!S.NSNumberDecl) { return nullptr; } @@ -294,15 +300,14 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCImplementationControl::Required, /*HasRelatedResultType=*/false); - ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method, - SourceLocation(), SourceLocation(), - &CX.Idents.get("value"), - NumberType, /*TInfo=*/nullptr, - SC_None, nullptr); - Method->setMethodParams(S.Context, value, std::nullopt); + ParmVarDecl *value = + ParmVarDecl::Create(S.SemaRef.Context, Method, SourceLocation(), + SourceLocation(), &CX.Idents.get("value"), + NumberType, /*TInfo=*/nullptr, SC_None, nullptr); + Method->setMethodParams(S.SemaRef.Context, value, std::nullopt); } - if (!validateBoxingMethod(S, Loc, S.NSNumberDecl, Sel, Method)) + if (!validateBoxingMethod(S.SemaRef, Loc, S.NSNumberDecl, Sel, Method)) return nullptr; // Note: if the parameter type is out-of-line, we'll catch it later in the @@ -314,7 +319,9 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the /// numeric literal expression. Type of the expression will be "NSNumber *". -ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) { +ExprResult SemaObjC::BuildObjCNumericLiteral(SourceLocation AtLoc, + Expr *Number) { + ASTContext &Context = getASTContext(); // Determine the type of the literal. QualType NumberType = Number->getType(); if (CharacterLiteral *Char = dyn_cast(Number)) { @@ -352,31 +359,30 @@ ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) { ParmVarDecl *ParamDecl = Method->parameters()[0]; InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, ParamDecl); - ExprResult ConvertedNumber = PerformCopyInitialization(Entity, - SourceLocation(), - Number); + ExprResult ConvertedNumber = + SemaRef.PerformCopyInitialization(Entity, SourceLocation(), Number); if (ConvertedNumber.isInvalid()) return ExprError(); Number = ConvertedNumber.get(); // Use the effective source range of the literal, including the leading '@'. - return MaybeBindToTemporary( - new (Context) ObjCBoxedExpr(Number, NSNumberPointer, Method, - SourceRange(AtLoc, NR.getEnd()))); + return SemaRef.MaybeBindToTemporary(new (Context) ObjCBoxedExpr( + Number, NSNumberPointer, Method, SourceRange(AtLoc, NR.getEnd()))); } -ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc, - SourceLocation ValueLoc, - bool Value) { +ExprResult SemaObjC::ActOnObjCBoolLiteral(SourceLocation AtLoc, + SourceLocation ValueLoc, bool Value) { + ASTContext &Context = getASTContext(); ExprResult Inner; if (getLangOpts().CPlusPlus) { - Inner = ActOnCXXBoolLiteral(ValueLoc, Value? tok::kw_true : tok::kw_false); + Inner = SemaRef.ActOnCXXBoolLiteral(ValueLoc, + Value ? tok::kw_true : tok::kw_false); } else { // C doesn't actually have a way to represent literal values of type // _Bool. So, we'll use 0/1 and implicit cast to _Bool. - Inner = ActOnIntegerConstant(ValueLoc, Value? 1 : 0); - Inner = ImpCastExprToType(Inner.get(), Context.BoolTy, - CK_IntegralToBoolean); + Inner = SemaRef.ActOnIntegerConstant(ValueLoc, Value ? 1 : 0); + Inner = SemaRef.ImpCastExprToType(Inner.get(), Context.BoolTy, + CK_IntegralToBoolean); } return BuildObjCNumericLiteral(AtLoc, Inner.get()); @@ -428,7 +434,8 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, isa(OrigElement) || isa(OrigElement) || isa(OrigElement)) { - if (S.NSAPIObj->getNSNumberFactoryMethodKind(OrigElement->getType())) { + if (S.ObjC().NSAPIObj->getNSNumberFactoryMethodKind( + OrigElement->getType())) { int Which = isa(OrigElement) ? 1 : (isa(OrigElement) || isa(OrigElement)) ? 2 @@ -438,8 +445,8 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, << Which << OrigElement->getSourceRange() << FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@"); - Result = - S.BuildObjCNumericLiteral(OrigElement->getBeginLoc(), OrigElement); + Result = S.ObjC().BuildObjCNumericLiteral(OrigElement->getBeginLoc(), + OrigElement); if (Result.isInvalid()) return ExprError(); @@ -454,7 +461,8 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, << 0 << OrigElement->getSourceRange() << FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@"); - Result = S.BuildObjCStringLiteral(OrigElement->getBeginLoc(), String); + Result = + S.ObjC().BuildObjCStringLiteral(OrigElement->getBeginLoc(), String); if (Result.isInvalid()) return ExprError(); @@ -498,7 +506,8 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, Element->getBeginLoc(), Element); } -ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { +ExprResult SemaObjC::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { + ASTContext &Context = getASTContext(); if (ValueExpr->isTypeDependent()) { ObjCBoxedExpr *BoxedExpr = new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, nullptr, SR); @@ -507,7 +516,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { ObjCMethodDecl *BoxingMethod = nullptr; QualType BoxedType; // Convert the expression to an RValue, so we can check for pointer types... - ExprResult RValue = DefaultFunctionArrayLvalueConversion(ValueExpr); + ExprResult RValue = SemaRef.DefaultFunctionArrayLvalueConversion(ValueExpr); if (RValue.isInvalid()) { return ExprError(); } @@ -519,8 +528,8 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) { if (!NSStringDecl) { - NSStringDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, - Sema::LK_String); + NSStringDecl = + LookupObjCInterfaceDeclForLiteral(SemaRef, Loc, LK_String); if (!NSStringDecl) { return ExprError(); } @@ -582,9 +591,9 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { BoxingMethod = M; } - if (!validateBoxingMethod(*this, Loc, NSStringDecl, + if (!validateBoxingMethod(SemaRef, Loc, NSStringDecl, stringWithUTF8String, BoxingMethod)) - return ExprError(); + return ExprError(); StringWithUTF8StringMethod = BoxingMethod; } @@ -651,8 +660,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { // Look up the NSValue class, if we haven't done so already. It's cached // in the Sema instance. if (!NSValueDecl) { - NSValueDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, - Sema::LK_Boxed); + NSValueDecl = LookupObjCInterfaceDeclForLiteral(SemaRef, Loc, LK_Boxed); if (!NSValueDecl) { return ExprError(); } @@ -708,7 +716,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { BoxingMethod = M; } - if (!validateBoxingMethod(*this, Loc, NSValueDecl, + if (!validateBoxingMethod(SemaRef, Loc, NSValueDecl, ValueWithBytesObjCType, BoxingMethod)) return ExprError(); @@ -731,20 +739,20 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { return ExprError(); } - DiagnoseUseOfDecl(BoxingMethod, Loc); + SemaRef.DiagnoseUseOfDecl(BoxingMethod, Loc); ExprResult ConvertedValueExpr; if (ValueType->isObjCBoxableRecordType()) { InitializedEntity IE = InitializedEntity::InitializeTemporary(ValueType); - ConvertedValueExpr = PerformCopyInitialization(IE, ValueExpr->getExprLoc(), - ValueExpr); + ConvertedValueExpr = SemaRef.PerformCopyInitialization( + IE, ValueExpr->getExprLoc(), ValueExpr); } else { // Convert the expression to the type that the parameter requires. ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0]; InitializedEntity IE = InitializedEntity::InitializeParameter(Context, ParamDecl); - ConvertedValueExpr = PerformCopyInitialization(IE, SourceLocation(), - ValueExpr); + ConvertedValueExpr = + SemaRef.PerformCopyInitialization(IE, SourceLocation(), ValueExpr); } if (ConvertedValueExpr.isInvalid()) @@ -754,16 +762,16 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { ObjCBoxedExpr *BoxedExpr = new (Context) ObjCBoxedExpr(ValueExpr, BoxedType, BoxingMethod, SR); - return MaybeBindToTemporary(BoxedExpr); + return SemaRef.MaybeBindToTemporary(BoxedExpr); } /// Build an ObjC subscript pseudo-object expression, given that /// that's supported by the runtime. -ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, - Expr *IndexExpr, - ObjCMethodDecl *getterMethod, - ObjCMethodDecl *setterMethod) { - assert(!LangOpts.isSubscriptPointerArithmetic()); +ExprResult SemaObjC::BuildObjCSubscriptExpression( + SourceLocation RB, Expr *BaseExpr, Expr *IndexExpr, + ObjCMethodDecl *getterMethod, ObjCMethodDecl *setterMethod) { + assert(!getLangOpts().isSubscriptPointerArithmetic()); + ASTContext &Context = getASTContext(); // We can't get dependent types here; our callers should have // filtered them out. @@ -772,13 +780,13 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, // Filter out placeholders in the index. In theory, overloads could // be preserved here, although that might not actually work correctly. - ExprResult Result = CheckPlaceholderExpr(IndexExpr); + ExprResult Result = SemaRef.CheckPlaceholderExpr(IndexExpr); if (Result.isInvalid()) return ExprError(); IndexExpr = Result.get(); // Perform lvalue-to-rvalue conversion on the base. - Result = DefaultLvalueConversion(BaseExpr); + Result = SemaRef.DefaultLvalueConversion(BaseExpr); if (Result.isInvalid()) return ExprError(); BaseExpr = Result.get(); @@ -789,12 +797,14 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, getterMethod, setterMethod, RB); } -ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { +ExprResult SemaObjC::BuildObjCArrayLiteral(SourceRange SR, + MultiExprArg Elements) { + ASTContext &Context = getASTContext(); SourceLocation Loc = SR.getBegin(); if (!NSArrayDecl) { - NSArrayDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, - Sema::LK_Array); + NSArrayDecl = + LookupObjCInterfaceDeclForLiteral(SemaRef, Loc, SemaObjC::LK_Array); if (!NSArrayDecl) { return ExprError(); } @@ -835,7 +845,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { Method->setMethodParams(Context, Params, std::nullopt); } - if (!validateBoxingMethod(*this, Loc, NSArrayDecl, Sel, Method)) + if (!validateBoxingMethod(SemaRef, Loc, NSArrayDecl, Sel, Method)) return ExprError(); // Dig out the type that all elements should be converted to. @@ -875,9 +885,8 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { // performing conversions as necessary. Expr **ElementsBuffer = Elements.data(); for (unsigned I = 0, N = Elements.size(); I != N; ++I) { - ExprResult Converted = CheckObjCCollectionLiteralElement(*this, - ElementsBuffer[I], - RequiredType, true); + ExprResult Converted = CheckObjCCollectionLiteralElement( + SemaRef, ElementsBuffer[I], RequiredType, true); if (Converted.isInvalid()) return ExprError(); @@ -888,9 +897,8 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { = Context.getObjCObjectPointerType( Context.getObjCInterfaceType(NSArrayDecl)); - return MaybeBindToTemporary( - ObjCArrayLiteral::Create(Context, Elements, Ty, - ArrayWithObjectsMethod, SR)); + return SemaRef.MaybeBindToTemporary(ObjCArrayLiteral::Create( + Context, Elements, Ty, ArrayWithObjectsMethod, SR)); } /// Check for duplicate keys in an ObjC dictionary literal. For instance: @@ -949,13 +957,14 @@ CheckObjCDictionaryLiteralDuplicateKeys(Sema &S, } } -ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, - MutableArrayRef Elements) { +ExprResult SemaObjC::BuildObjCDictionaryLiteral( + SourceRange SR, MutableArrayRef Elements) { + ASTContext &Context = getASTContext(); SourceLocation Loc = SR.getBegin(); if (!NSDictionaryDecl) { - NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, - Sema::LK_Dictionary); + NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral( + SemaRef, Loc, SemaObjC::LK_Dictionary); if (!NSDictionaryDecl) { return ExprError(); } @@ -1005,9 +1014,9 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, Method->setMethodParams(Context, Params, std::nullopt); } - if (!validateBoxingMethod(*this, SR.getBegin(), NSDictionaryDecl, Sel, + if (!validateBoxingMethod(SemaRef, SR.getBegin(), NSDictionaryDecl, Sel, Method)) - return ExprError(); + return ExprError(); // Dig out the type that all values should be converted to. QualType ValueT = Method->parameters()[0]->getType(); @@ -1084,14 +1093,14 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, bool HasPackExpansions = false; for (ObjCDictionaryElement &Element : Elements) { // Check the key. - ExprResult Key = CheckObjCCollectionLiteralElement(*this, Element.Key, - KeyT); + ExprResult Key = + CheckObjCCollectionLiteralElement(SemaRef, Element.Key, KeyT); if (Key.isInvalid()) return ExprError(); // Check the value. - ExprResult Value - = CheckObjCCollectionLiteralElement(*this, Element.Value, ValueT); + ExprResult Value = + CheckObjCCollectionLiteralElement(SemaRef, Element.Value, ValueT); if (Value.isInvalid()) return ExprError(); @@ -1119,13 +1128,14 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, auto *Literal = ObjCDictionaryLiteral::Create(Context, Elements, HasPackExpansions, Ty, DictionaryWithObjectsMethod, SR); - CheckObjCDictionaryLiteralDuplicateKeys(*this, Literal); - return MaybeBindToTemporary(Literal); + CheckObjCDictionaryLiteralDuplicateKeys(SemaRef, Literal); + return SemaRef.MaybeBindToTemporary(Literal); } -ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, - TypeSourceInfo *EncodedTypeInfo, - SourceLocation RParenLoc) { +ExprResult SemaObjC::BuildObjCEncodeExpression(SourceLocation AtLoc, + TypeSourceInfo *EncodedTypeInfo, + SourceLocation RParenLoc) { + ASTContext &Context = getASTContext(); QualType EncodedType = EncodedTypeInfo->getType(); QualType StrTy; if (EncodedType->isDependentType()) @@ -1133,9 +1143,9 @@ ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, else { if (!EncodedType->getAsArrayTypeUnsafe() && //// Incomplete array is handled. !EncodedType->isVoidType()) // void is handled too. - if (RequireCompleteType(AtLoc, EncodedType, - diag::err_incomplete_type_objc_at_encode, - EncodedTypeInfo->getTypeLoc())) + if (SemaRef.RequireCompleteType(AtLoc, EncodedType, + diag::err_incomplete_type_objc_at_encode, + EncodedTypeInfo->getTypeLoc())) return ExprError(); std::string Str; @@ -1153,17 +1163,18 @@ ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc); } -ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, - SourceLocation EncodeLoc, - SourceLocation LParenLoc, - ParsedType ty, - SourceLocation RParenLoc) { +ExprResult SemaObjC::ParseObjCEncodeExpression(SourceLocation AtLoc, + SourceLocation EncodeLoc, + SourceLocation LParenLoc, + ParsedType ty, + SourceLocation RParenLoc) { + ASTContext &Context = getASTContext(); // FIXME: Preserve type source info ? TypeSourceInfo *TInfo; - QualType EncodedType = GetTypeFromParser(ty, &TInfo); + QualType EncodedType = SemaRef.GetTypeFromParser(ty, &TInfo); if (!TInfo) - TInfo = Context.getTrivialTypeSourceInfo(EncodedType, - getLocForEndOfToken(LParenLoc)); + TInfo = Context.getTrivialTypeSourceInfo( + EncodedType, SemaRef.getLocForEndOfToken(LParenLoc)); return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc); } @@ -1182,8 +1193,8 @@ static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S, isa(MatchingMethodDecl->getDeclContext()) || MatchingMethodDecl->getSelector() != Method->getSelector()) continue; - if (!S.MatchTwoMethodDeclarations(Method, - MatchingMethodDecl, Sema::MMS_loose)) { + if (!S.ObjC().MatchTwoMethodDeclarations(Method, MatchingMethodDecl, + SemaObjC::MMS_loose)) { if (!Warned) { Warned = true; S.Diag(AtLoc, diag::warn_multiple_selectors) @@ -1208,8 +1219,9 @@ static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc, S.Diags.isIgnored(diag::warn_multiple_selectors, SourceLocation())) return; bool Warned = false; - for (Sema::GlobalMethodPool::iterator b = S.MethodPool.begin(), - e = S.MethodPool.end(); b != e; b++) { + for (SemaObjC::GlobalMethodPool::iterator b = S.ObjC().MethodPool.begin(), + e = S.ObjC().MethodPool.end(); + b != e; b++) { // first, instance methods ObjCMethodList &InstMethList = b->second.first; if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc, @@ -1253,8 +1265,8 @@ static ObjCMethodDecl *LookupDirectMethodInMethodList(Sema &S, Selector Sel, static ObjCMethodDecl *LookupDirectMethodInGlobalPool(Sema &S, Selector Sel, bool &onlyDirect, bool &anyDirect) { - auto Iter = S.MethodPool.find(Sel); - if (Iter == S.MethodPool.end()) + auto Iter = S.ObjC().MethodPool.find(Sel); + if (Iter == S.ObjC().MethodPool.end()) return nullptr; ObjCMethodDecl *DirectInstance = LookupDirectMethodInMethodList( @@ -1286,12 +1298,13 @@ static ObjCMethodDecl *findMethodInCurrentClass(Sema &S, Selector Sel) { return nullptr; } -ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, - SourceLocation AtLoc, - SourceLocation SelLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc, - bool WarnMultipleSelectors) { +ExprResult SemaObjC::ParseObjCSelectorExpression(Selector Sel, + SourceLocation AtLoc, + SourceLocation SelLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc, + bool WarnMultipleSelectors) { + ASTContext &Context = getASTContext(); ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(LParenLoc, RParenLoc)); if (!Method) @@ -1309,13 +1322,13 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, } else Diag(SelLoc, diag::warn_undeclared_selector) << Sel; } else { - DiagnoseMismatchedSelectors(*this, AtLoc, Method, LParenLoc, RParenLoc, + DiagnoseMismatchedSelectors(SemaRef, AtLoc, Method, LParenLoc, RParenLoc, WarnMultipleSelectors); bool onlyDirect = true; bool anyDirect = false; ObjCMethodDecl *GlobalDirectMethod = - LookupDirectMethodInGlobalPool(*this, Sel, onlyDirect, anyDirect); + LookupDirectMethodInGlobalPool(SemaRef, Sel, onlyDirect, anyDirect); if (onlyDirect) { Diag(AtLoc, diag::err_direct_selector_expression) @@ -1326,7 +1339,8 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, // If we saw any direct methods, see if we see a direct member of the // current class. If so, the @selector will likely be used to refer to // this direct method. - ObjCMethodDecl *LikelyTargetMethod = findMethodInCurrentClass(*this, Sel); + ObjCMethodDecl *LikelyTargetMethod = + findMethodInCurrentClass(SemaRef, Sel); if (LikelyTargetMethod && LikelyTargetMethod->isDirectMethod()) { Diag(AtLoc, diag::warn_potentially_direct_selector_expression) << Sel; Diag(LikelyTargetMethod->getLocation(), @@ -1347,7 +1361,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, if (Method && Method->getImplementationControl() != ObjCImplementationControl::Optional && - !getSourceManager().isInSystemHeader(Method->getLocation())) + !SemaRef.getSourceManager().isInSystemHeader(Method->getLocation())) ReferencedSelectors.insert(std::make_pair(Sel, AtLoc)); // In ARC, forbid the user from using @selector for @@ -1380,12 +1394,13 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc); } -ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, - SourceLocation AtLoc, - SourceLocation ProtoLoc, - SourceLocation LParenLoc, - SourceLocation ProtoIdLoc, - SourceLocation RParenLoc) { +ExprResult SemaObjC::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, + SourceLocation AtLoc, + SourceLocation ProtoLoc, + SourceLocation LParenLoc, + SourceLocation ProtoIdLoc, + SourceLocation RParenLoc) { + ASTContext &Context = getASTContext(); ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoIdLoc); if (!PDecl) { Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId; @@ -1409,8 +1424,8 @@ ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, } /// Try to capture an implicit reference to 'self'. -ObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) { - DeclContext *DC = getFunctionLevelDeclContext(); +ObjCMethodDecl *SemaObjC::tryCaptureObjCSelf(SourceLocation Loc) { + DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); // If we're not in an ObjC method, error out. Note that, unlike the // C++ case, we don't require an instance method --- class methods @@ -1419,7 +1434,7 @@ ObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) { if (!method) return nullptr; - tryCaptureVariable(method->getSelfDecl(), Loc); + SemaRef.tryCaptureVariable(method->getSelfDecl(), Loc); return method; } @@ -1513,16 +1528,15 @@ static QualType getBaseMessageSendResultType(Sema &S, return transferNullability(ReceiverType); } -QualType Sema::getMessageSendResultType(const Expr *Receiver, - QualType ReceiverType, - ObjCMethodDecl *Method, - bool isClassMessage, - bool isSuperMessage) { +QualType SemaObjC::getMessageSendResultType(const Expr *Receiver, + QualType ReceiverType, + ObjCMethodDecl *Method, + bool isClassMessage, + bool isSuperMessage) { + ASTContext &Context = getASTContext(); // Produce the result type. - QualType resultType = getBaseMessageSendResultType(*this, ReceiverType, - Method, - isClassMessage, - isSuperMessage); + QualType resultType = getBaseMessageSendResultType( + SemaRef, ReceiverType, Method, isClassMessage, isSuperMessage); // If this is a class message, ignore the nullability of the receiver. if (isClassMessage) { @@ -1651,10 +1665,11 @@ findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD, return nullptr; } -void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) { +void SemaObjC::EmitRelatedResultTypeNoteForReturn(QualType destType) { + ASTContext &Context = getASTContext(); // Only complain if we're in an ObjC method and the required return // type doesn't match the method's declared return type. - ObjCMethodDecl *MD = dyn_cast(CurContext); + ObjCMethodDecl *MD = dyn_cast(SemaRef.CurContext); if (!MD || !MD->hasRelatedResultType() || Context.hasSameUnqualifiedType(destType, MD->getReturnType())) return; @@ -1680,7 +1695,8 @@ void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) { << family; } -void Sema::EmitRelatedResultTypeNote(const Expr *E) { +void SemaObjC::EmitRelatedResultTypeNote(const Expr *E) { + ASTContext &Context = getASTContext(); E = E->IgnoreParenImpCasts(); const ObjCMessageExpr *MsgSend = dyn_cast(E); if (!MsgSend) @@ -1706,12 +1722,13 @@ void Sema::EmitRelatedResultTypeNote(const Expr *E) { << MsgSend->getType(); } -bool Sema::CheckMessageArgumentTypes( +bool SemaObjC::CheckMessageArgumentTypes( const Expr *Receiver, QualType ReceiverType, MultiExprArg Args, Selector Sel, ArrayRef SelectorLocs, ObjCMethodDecl *Method, bool isClassMessage, bool isSuperMessage, SourceLocation lbrac, SourceLocation rbrac, SourceRange RecRange, QualType &ReturnType, ExprValueKind &VK) { + ASTContext &Context = getASTContext(); SourceLocation SelLoc; if (!SelectorLocs.empty() && SelectorLocs.front().isValid()) SelLoc = SelectorLocs.front(); @@ -1727,9 +1744,9 @@ bool Sema::CheckMessageArgumentTypes( ExprResult result; if (getLangOpts().DebuggerSupport) { QualType paramTy; // ignored - result = checkUnknownAnyArg(SelLoc, Args[i], paramTy); + result = SemaRef.checkUnknownAnyArg(SelLoc, Args[i], paramTy); } else { - result = DefaultArgumentPromotion(Args[i]); + result = SemaRef.DefaultArgumentPromotion(Args[i]); } if (result.isInvalid()) return true; @@ -1835,7 +1852,7 @@ bool Sema::CheckMessageArgumentTypes( // from the argument. if (param->getType() == Context.UnknownAnyTy) { QualType paramType; - ExprResult argE = checkUnknownAnyArg(SelLoc, argExpr, paramType); + ExprResult argE = SemaRef.checkUnknownAnyArg(SelLoc, argExpr, paramType); if (argE.isInvalid()) { IsError = true; } else { @@ -1855,14 +1872,15 @@ bool Sema::CheckMessageArgumentTypes( *typeArgs, ObjCSubstitutionContext::Parameter); - if (RequireCompleteType(argExpr->getSourceRange().getBegin(), - paramType, - diag::err_call_incomplete_argument, argExpr)) + if (SemaRef.RequireCompleteType( + argExpr->getSourceRange().getBegin(), paramType, + diag::err_call_incomplete_argument, argExpr)) return true; InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, param, paramType); - ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), argExpr); + ExprResult ArgE = + SemaRef.PerformCopyInitialization(Entity, SourceLocation(), argExpr); if (ArgE.isInvalid()) IsError = true; else { @@ -1875,7 +1893,7 @@ bool Sema::CheckMessageArgumentTypes( Args[i]->getType()->isBlockPointerType() && origParamType->isObjCObjectPointerType()) { ExprResult arg = Args[i]; - maybeExtendBlockObject(arg); + SemaRef.maybeExtendBlockObject(arg); Args[i] = arg.get(); } } @@ -1887,8 +1905,8 @@ bool Sema::CheckMessageArgumentTypes( if (Args[i]->isTypeDependent()) continue; - ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, - nullptr); + ExprResult Arg = SemaRef.DefaultVariadicArgumentPromotion( + Args[i], Sema::VariadicMethod, nullptr); IsError |= Arg.isInvalid(); Args[i] = Arg.get(); } @@ -1904,7 +1922,7 @@ bool Sema::CheckMessageArgumentTypes( } } - DiagnoseSentinelCalls(Method, SelLoc, Args); + SemaRef.DiagnoseSentinelCalls(Method, SelLoc, Args); // Do additional checkings on method. IsError |= @@ -1913,14 +1931,14 @@ bool Sema::CheckMessageArgumentTypes( return IsError; } -bool Sema::isSelfExpr(Expr *RExpr) { +bool SemaObjC::isSelfExpr(Expr *RExpr) { // 'self' is objc 'self' in an objc method only. - ObjCMethodDecl *Method = - dyn_cast_or_null(CurContext->getNonClosureAncestor()); + ObjCMethodDecl *Method = dyn_cast_or_null( + SemaRef.CurContext->getNonClosureAncestor()); return isSelfExpr(RExpr, Method); } -bool Sema::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) { +bool SemaObjC::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) { if (!method) return false; receiver = receiver->IgnoreParenLValueCasts(); @@ -1931,8 +1949,8 @@ bool Sema::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) { } /// LookupMethodInType - Look up a method in an ObjCObjectType. -ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type, - bool isInstance) { +ObjCMethodDecl *SemaObjC::LookupMethodInObjectType(Selector sel, QualType type, + bool isInstance) { const ObjCObjectType *objType = type->castAs(); if (ObjCInterfaceDecl *iface = objType->getInterface()) { // Look it up in the main interface (and categories, etc.) @@ -1955,10 +1973,8 @@ ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type, /// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier /// list of a qualified objective pointer type. -ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, - const ObjCObjectPointerType *OPT, - bool Instance) -{ +ObjCMethodDecl *SemaObjC::LookupMethodInQualifiedType( + Selector Sel, const ObjCObjectPointerType *OPT, bool Instance) { ObjCMethodDecl *MD = nullptr; for (const auto *PROTO : OPT->quals()) { if ((MD = PROTO->lookupMethod(Sel, Instance))) { @@ -1970,13 +1986,11 @@ ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, /// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an /// objective C interface. This is a property reference expression. -ExprResult Sema:: -HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, - Expr *BaseExpr, SourceLocation OpLoc, - DeclarationName MemberName, - SourceLocation MemberLoc, - SourceLocation SuperLoc, QualType SuperType, - bool Super) { +ExprResult SemaObjC::HandleExprPropertyRefExpr( + const ObjCObjectPointerType *OPT, Expr *BaseExpr, SourceLocation OpLoc, + DeclarationName MemberName, SourceLocation MemberLoc, + SourceLocation SuperLoc, QualType SuperType, bool Super) { + ASTContext &Context = getASTContext(); const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); ObjCInterfaceDecl *IFace = IFaceT->getDecl(); @@ -1990,15 +2004,15 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, SourceRange BaseRange = Super? SourceRange(SuperLoc) : BaseExpr->getSourceRange(); - if (RequireCompleteType(MemberLoc, OPT->getPointeeType(), - diag::err_property_not_found_forward_class, - MemberName, BaseRange)) + if (SemaRef.RequireCompleteType(MemberLoc, OPT->getPointeeType(), + diag::err_property_not_found_forward_class, + MemberName, BaseRange)) return ExprError(); if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration( Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { // Check whether we can reference this property. - if (DiagnoseUseOfDecl(PD, MemberLoc)) + if (SemaRef.DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); if (Super) return new (Context) @@ -2014,7 +2028,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration( Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { // Check whether we can reference this property. - if (DiagnoseUseOfDecl(PD, MemberLoc)) + if (SemaRef.DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); if (Super) @@ -2032,7 +2046,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // FIXME: The logic for looking up nullary and unary selectors should be // shared with the code in ActOnInstanceMessage. - Selector Sel = PP.getSelectorTable().getNullarySelector(Member); + Selector Sel = SemaRef.PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); // May be found in property's qualified list. @@ -2045,14 +2059,13 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (Getter) { // Check if we can reference this property. - if (DiagnoseUseOfDecl(Getter, MemberLoc)) + if (SemaRef.DiagnoseUseOfDecl(Getter, MemberLoc)) return ExprError(); } // If we found a getter then this may be a valid dot-reference, we // will look for the matching setter, in case it is needed. - Selector SetterSel = - SelectorTable::constructSetterSelector(PP.getIdentifierTable(), - PP.getSelectorTable(), Member); + Selector SetterSel = SelectorTable::constructSetterSelector( + SemaRef.PP.getIdentifierTable(), SemaRef.PP.getSelectorTable(), Member); ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); // May be found in property's qualified list. @@ -2065,7 +2078,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, Setter = IFace->lookupPrivateMethod(SetterSel); } - if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) + if (Setter && SemaRef.DiagnoseUseOfDecl(Setter, MemberLoc)) return ExprError(); // Special warning if member name used in a property-dot for a setter accessor @@ -2100,9 +2113,9 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // Attempt to correct for typos in property names. DeclFilterCCC CCC{}; - if (TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, - nullptr, nullptr, CCC, CTK_ErrorRecovery, IFace, false, OPT)) { + if (TypoCorrection Corrected = SemaRef.CorrectTypo( + DeclarationNameInfo(MemberName, MemberLoc), Sema::LookupOrdinaryName, + nullptr, nullptr, CCC, Sema::CTK_ErrorRecovery, IFace, false, OPT)) { DeclarationName TypoResult = Corrected.getCorrection(); if (TypoResult.isIdentifier() && TypoResult.getAsIdentifierInfo() == Member) { @@ -2120,8 +2133,9 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, return ExprError(); } } else { - diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest) - << MemberName << QualType(OPT, 0)); + SemaRef.diagnoseTypo(Corrected, + SemaRef.PDiag(diag::err_property_not_found_suggest) + << MemberName << QualType(OPT, 0)); return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc, TypoResult, MemberLoc, SuperLoc, SuperType, Super); @@ -2133,9 +2147,9 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, QualType T = Ivar->getType(); if (const ObjCObjectPointerType * OBJPT = T->getAsObjCInterfacePointerType()) { - if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(), - diag::err_property_not_as_forward_class, - MemberName, BaseExpr)) + if (SemaRef.RequireCompleteType(MemberLoc, OBJPT->getPointeeType(), + diag::err_property_not_as_forward_class, + MemberName, BaseExpr)) return ExprError(); } Diag(MemberLoc, @@ -2153,11 +2167,10 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, return ExprError(); } -ExprResult Sema::ActOnClassPropertyRefExpr(const IdentifierInfo &receiverName, - const IdentifierInfo &propertyName, - SourceLocation receiverNameLoc, - SourceLocation propertyNameLoc) { - +ExprResult SemaObjC::ActOnClassPropertyRefExpr( + const IdentifierInfo &receiverName, const IdentifierInfo &propertyName, + SourceLocation receiverNameLoc, SourceLocation propertyNameLoc) { + ASTContext &Context = getASTContext(); const IdentifierInfo *receiverNamePtr = &receiverName; ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr, receiverNameLoc); @@ -2208,9 +2221,10 @@ ExprResult Sema::ActOnClassPropertyRefExpr(const IdentifierInfo &receiverName, GetterSel = PD->getGetterName(); SetterSel = PD->getSetterName(); } else { - GetterSel = PP.getSelectorTable().getNullarySelector(&propertyName); + GetterSel = SemaRef.PP.getSelectorTable().getNullarySelector(&propertyName); SetterSel = SelectorTable::constructSetterSelector( - PP.getIdentifierTable(), PP.getSelectorTable(), &propertyName); + SemaRef.PP.getIdentifierTable(), SemaRef.PP.getSelectorTable(), + &propertyName); } // Search for a declared property first. @@ -2223,7 +2237,7 @@ ExprResult Sema::ActOnClassPropertyRefExpr(const IdentifierInfo &receiverName, if (Getter) { // FIXME: refactor/share with ActOnMemberReference(). // Check if we can reference this property. - if (DiagnoseUseOfDecl(Getter, propertyNameLoc)) + if (SemaRef.DiagnoseUseOfDecl(Getter, propertyNameLoc)) return ExprError(); } @@ -2238,7 +2252,7 @@ ExprResult Sema::ActOnClassPropertyRefExpr(const IdentifierInfo &receiverName, if (!Setter) Setter = IFace->getCategoryClassMethod(SetterSel); - if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc)) + if (Setter && SemaRef.DiagnoseUseOfDecl(Setter, propertyNameLoc)) return ExprError(); if (Getter || Setter) { @@ -2278,12 +2292,11 @@ class ObjCInterfaceOrSuperCCC final : public CorrectionCandidateCallback { } // end anonymous namespace -Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, - IdentifierInfo *Name, - SourceLocation NameLoc, - bool IsSuper, - bool HasTrailingDot, - ParsedType &ReceiverType) { +SemaObjC::ObjCMessageKind +SemaObjC::getObjCMessageKind(Scope *S, IdentifierInfo *Name, + SourceLocation NameLoc, bool IsSuper, + bool HasTrailingDot, ParsedType &ReceiverType) { + ASTContext &Context = getASTContext(); ReceiverType = nullptr; // If the identifier is "super" and there is no trailing dot, we're @@ -2292,8 +2305,8 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, if (IsSuper && S->isInObjcMethodScope()) return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage; - LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); - LookupName(Result, S); + LookupResult Result(SemaRef, Name, NameLoc, Sema::LookupOrdinaryName); + SemaRef.LookupName(Result, S); switch (Result.getResultKind()) { case LookupResult::NotFound: @@ -2301,7 +2314,7 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, // Objective-C method, look for ivars. If we find one, we're done! // FIXME: This is a hack. Ivar lookup should be part of normal // lookup. - if (ObjCMethodDecl *Method = getCurMethodDecl()) { + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { if (!Method->getClassInterface()) { // Fall back: let the parser try to parse it as an instance message. return ObjCInstanceMessage; @@ -2336,7 +2349,7 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, T = Context.getObjCInterfaceType(Class); else if (TypeDecl *Type = dyn_cast(ND)) { T = Context.getTypeDeclType(Type); - DiagnoseUseOfDecl(Type, NameLoc); + SemaRef.DiagnoseUseOfDecl(Type, NameLoc); } else return ObjCInstanceMessage; @@ -2344,30 +2357,30 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, // We have a class message, and T is the type we're // messaging. Build source-location information for it. TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); - ReceiverType = CreateParsedType(T, TSInfo); + ReceiverType = SemaRef.CreateParsedType(T, TSInfo); return ObjCClassMessage; } } - ObjCInterfaceOrSuperCCC CCC(getCurMethodDecl()); - if (TypoCorrection Corrected = CorrectTypo( + ObjCInterfaceOrSuperCCC CCC(SemaRef.getCurMethodDecl()); + if (TypoCorrection Corrected = SemaRef.CorrectTypo( Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr, CCC, - CTK_ErrorRecovery, nullptr, false, nullptr, false)) { + Sema::CTK_ErrorRecovery, nullptr, false, nullptr, false)) { if (Corrected.isKeyword()) { // If we've found the keyword "super" (the only keyword that would be // returned by CorrectTypo), this is a send to super. - diagnoseTypo(Corrected, - PDiag(diag::err_unknown_receiver_suggest) << Name); + SemaRef.diagnoseTypo( + Corrected, SemaRef.PDiag(diag::err_unknown_receiver_suggest) << Name); return ObjCSuperMessage; } else if (ObjCInterfaceDecl *Class = Corrected.getCorrectionDeclAs()) { // If we found a declaration, correct when it refers to an Objective-C // class. - diagnoseTypo(Corrected, - PDiag(diag::err_unknown_receiver_suggest) << Name); + SemaRef.diagnoseTypo( + Corrected, SemaRef.PDiag(diag::err_unknown_receiver_suggest) << Name); QualType T = Context.getObjCInterfaceType(Class); TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); - ReceiverType = CreateParsedType(T, TSInfo); + ReceiverType = SemaRef.CreateParsedType(T, TSInfo); return ObjCClassMessage; } } @@ -2376,13 +2389,12 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, return ObjCInstanceMessage; } -ExprResult Sema::ActOnSuperMessage(Scope *S, - SourceLocation SuperLoc, - Selector Sel, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, - MultiExprArg Args) { +ExprResult SemaObjC::ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, + Selector Sel, SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, + MultiExprArg Args) { + ASTContext &Context = getASTContext(); // Determine whether we are inside a method or not. ObjCMethodDecl *Method = tryCaptureObjCSelf(SuperLoc); if (!Method) { @@ -2408,7 +2420,7 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, // We are in a method whose class has a superclass, so 'super' // is acting as a keyword. if (Method->getSelector() == Sel) - getCurFunction()->ObjCShouldCallSuper = false; + SemaRef.getCurFunction()->ObjCShouldCallSuper = false; if (Method->isInstanceMethod()) { // Since we are in an instance method, this is an instance @@ -2427,12 +2439,12 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, LBracLoc, SelectorLocs, RBracLoc, Args); } -ExprResult Sema::BuildClassMessageImplicit(QualType ReceiverType, - bool isSuperReceiver, - SourceLocation Loc, - Selector Sel, - ObjCMethodDecl *Method, - MultiExprArg Args) { +ExprResult SemaObjC::BuildClassMessageImplicit(QualType ReceiverType, + bool isSuperReceiver, + SourceLocation Loc, Selector Sel, + ObjCMethodDecl *Method, + MultiExprArg Args) { + ASTContext &Context = getASTContext(); TypeSourceInfo *receiverTypeInfo = nullptr; if (!ReceiverType.isNull()) receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType); @@ -2456,7 +2468,7 @@ static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg, SourceManager &SM = S.SourceMgr; edit::Commit ECommit(SM, S.LangOpts); - if (refactor(Msg,*S.NSAPIObj, ECommit)) { + if (refactor(Msg, *S.ObjC().NSAPIObj, ECommit)) { auto Builder = S.Diag(MsgLoc, DiagID) << Msg->getSelector() << Msg->getSourceRange(); // FIXME: Don't emit diagnostic at all if fixits are non-commitable. @@ -2603,16 +2615,12 @@ DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S, /// \param RBracLoc The location of the closing square bracket ']'. /// /// \param ArgsIn The message arguments. -ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, - QualType ReceiverType, - SourceLocation SuperLoc, - Selector Sel, - ObjCMethodDecl *Method, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, - MultiExprArg ArgsIn, - bool isImplicit) { +ExprResult SemaObjC::BuildClassMessage( + TypeSourceInfo *ReceiverTypeInfo, QualType ReceiverType, + SourceLocation SuperLoc, Selector Sel, ObjCMethodDecl *Method, + SourceLocation LBracLoc, ArrayRef SelectorLocs, + SourceLocation RBracLoc, MultiExprArg ArgsIn, bool isImplicit) { + ASTContext &Context = getASTContext(); SourceLocation Loc = SuperLoc.isValid()? SuperLoc : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin(); if (LBracLoc.isInvalid()) { @@ -2650,17 +2658,17 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, assert(Class && "We don't know which class we're messaging?"); // objc++ diagnoses during typename annotation. if (!getLangOpts().CPlusPlus) - (void)DiagnoseUseOfDecl(Class, SelectorSlotLocs); + (void)SemaRef.DiagnoseUseOfDecl(Class, SelectorSlotLocs); // Find the method we are messaging. if (!Method) { SourceRange TypeRange = SuperLoc.isValid()? SourceRange(SuperLoc) : ReceiverTypeInfo->getTypeLoc().getSourceRange(); - if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class), - (getLangOpts().ObjCAutoRefCount - ? diag::err_arc_receiver_forward_class - : diag::warn_receiver_forward_class), - TypeRange)) { + if (SemaRef.RequireCompleteType(Loc, Context.getObjCInterfaceType(Class), + (getLangOpts().ObjCAutoRefCount + ? diag::err_arc_receiver_forward_class + : diag::warn_receiver_forward_class), + TypeRange)) { // A forward class used in messaging is treated as a 'Class' Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc)); @@ -2675,8 +2683,8 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, if (!Method) Method = Class->lookupPrivateClassMethod(Sel); - if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs, - nullptr, false, false, Class)) + if (Method && SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs, nullptr, + false, false, Class)) return ExprError(); } @@ -2693,8 +2701,9 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, return ExprError(); if (Method && !Method->getReturnType()->isVoidType() && - RequireCompleteType(LBracLoc, Method->getReturnType(), - diag::err_illegal_message_expr_incomplete_type)) + SemaRef.RequireCompleteType( + LBracLoc, Method->getReturnType(), + diag::err_illegal_message_expr_incomplete_type)) return ExprError(); if (Method && Method->isDirectMethod() && SuperLoc.isValid()) { @@ -2717,8 +2726,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, Diag(Method->getLocation(), diag::note_method_declared_at) << Method->getDeclName(); } - } - else if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { + } else if (ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl()) { // [super initialize] is allowed only within an +initialize implementation if (CurMeth->getMethodFamily() != OMF_initialize) { Diag(Loc, diag::warn_direct_super_initialize_call); @@ -2730,7 +2738,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, } } - DiagnoseCStringFormatDirectiveInObjCAPI(*this, Method, Sel, Args, NumArgs); + DiagnoseCStringFormatDirectiveInObjCAPI(SemaRef, Method, Sel, Args, NumArgs); // Construct the appropriate ObjCMessageExpr. ObjCMessageExpr *Result; @@ -2744,26 +2752,26 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, Context, ReturnType, VK, LBracLoc, ReceiverTypeInfo, Sel, SelectorLocs, Method, ArrayRef(Args, NumArgs), RBracLoc, isImplicit); if (!isImplicit) - checkCocoaAPI(*this, Result); + checkCocoaAPI(SemaRef, Result); } if (Method) - checkFoundationAPI(*this, SelLoc, Method, ArrayRef(Args, NumArgs), + checkFoundationAPI(SemaRef, SelLoc, Method, ArrayRef(Args, NumArgs), ReceiverType, /*IsClassObjectCall=*/true); - return MaybeBindToTemporary(Result); + return SemaRef.MaybeBindToTemporary(Result); } // ActOnClassMessage - used for both unary and keyword messages. // ArgExprs is optional - if it is present, the number of expressions // is obtained from Sel.getNumArgs(). -ExprResult Sema::ActOnClassMessage(Scope *S, - ParsedType Receiver, - Selector Sel, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, - MultiExprArg Args) { +ExprResult SemaObjC::ActOnClassMessage(Scope *S, ParsedType Receiver, + Selector Sel, SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, + MultiExprArg Args) { + ASTContext &Context = getASTContext(); TypeSourceInfo *ReceiverTypeInfo; - QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo); + QualType ReceiverType = + SemaRef.GetTypeFromParser(Receiver, &ReceiverTypeInfo); if (ReceiverType.isNull()) return ExprError(); @@ -2776,12 +2784,9 @@ ExprResult Sema::ActOnClassMessage(Scope *S, Args); } -ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver, - QualType ReceiverType, - SourceLocation Loc, - Selector Sel, - ObjCMethodDecl *Method, - MultiExprArg Args) { +ExprResult SemaObjC::BuildInstanceMessageImplicit( + Expr *Receiver, QualType ReceiverType, SourceLocation Loc, Selector Sel, + ObjCMethodDecl *Method, MultiExprArg Args) { return BuildInstanceMessage(Receiver, ReceiverType, /*SuperLoc=*/!Receiver ? Loc : SourceLocation(), Sel, Method, Loc, Loc, Loc, Args, @@ -2789,12 +2794,13 @@ ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver, } static bool isMethodDeclaredInRootProtocol(Sema &S, const ObjCMethodDecl *M) { - if (!S.NSAPIObj) + if (!S.ObjC().NSAPIObj) return false; const auto *Protocol = dyn_cast(M->getDeclContext()); if (!Protocol) return false; - const IdentifierInfo *II = S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject); + const IdentifierInfo *II = + S.ObjC().NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject); if (const auto *RootClass = dyn_cast_or_null( S.LookupSingleName(S.TUScope, II, Protocol->getBeginLoc(), Sema::LookupOrdinaryName))) { @@ -2834,19 +2840,15 @@ static bool isMethodDeclaredInRootProtocol(Sema &S, const ObjCMethodDecl *M) { /// \param RBracLoc The location of the closing square bracket ']'. /// /// \param ArgsIn The message arguments. -ExprResult Sema::BuildInstanceMessage(Expr *Receiver, - QualType ReceiverType, - SourceLocation SuperLoc, - Selector Sel, - ObjCMethodDecl *Method, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, - MultiExprArg ArgsIn, - bool isImplicit) { +ExprResult SemaObjC::BuildInstanceMessage( + Expr *Receiver, QualType ReceiverType, SourceLocation SuperLoc, + Selector Sel, ObjCMethodDecl *Method, SourceLocation LBracLoc, + ArrayRef SelectorLocs, SourceLocation RBracLoc, + MultiExprArg ArgsIn, bool isImplicit) { assert((Receiver || SuperLoc.isValid()) && "If the Receiver is null, the " "SuperLoc must be valid so we can " "use it instead."); + ASTContext &Context = getASTContext(); // The location of the receiver. SourceLocation Loc = SuperLoc.isValid() ? SuperLoc : Receiver->getBeginLoc(); @@ -2871,9 +2873,10 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (Receiver->hasPlaceholderType()) { ExprResult Result; if (Receiver->getType() == Context.UnknownAnyTy) - Result = forceUnknownAnyToType(Receiver, Context.getObjCIdType()); + Result = + SemaRef.forceUnknownAnyToType(Receiver, Context.getObjCIdType()); else - Result = CheckPlaceholderExpr(Receiver); + Result = SemaRef.CheckPlaceholderExpr(Receiver); if (Result.isInvalid()) return ExprError(); Receiver = Result.get(); } @@ -2892,7 +2895,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // If necessary, apply function/array conversion to the receiver. // C99 6.7.5.3p[7,8]. - ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver); + ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Receiver); if (Result.isInvalid()) return ExprError(); Receiver = Result.get(); @@ -2911,24 +2914,28 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // But not in ARC. Diag(Loc, diag::warn_bad_receiver_type) << ReceiverType << RecRange; if (ReceiverType->isPointerType()) { - Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), - CK_CPointerToObjCPointerCast).get(); + Receiver = SemaRef + .ImpCastExprToType(Receiver, Context.getObjCIdType(), + CK_CPointerToObjCPointerCast) + .get(); } else { // TODO: specialized warning on null receivers? bool IsNull = Receiver->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer; - Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), - Kind).get(); + Receiver = + SemaRef.ImpCastExprToType(Receiver, Context.getObjCIdType(), Kind) + .get(); } ReceiverType = Receiver->getType(); } else if (getLangOpts().CPlusPlus) { // The receiver must be a complete type. - if (RequireCompleteType(Loc, Receiver->getType(), - diag::err_incomplete_receiver_type)) + if (SemaRef.RequireCompleteType(Loc, Receiver->getType(), + diag::err_incomplete_receiver_type)) return ExprError(); - ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver); + ExprResult result = + SemaRef.PerformContextuallyConvertToObjCPointer(Receiver); if (result.isUsable()) { Receiver = result.get(); ReceiverType = Receiver->getType(); @@ -2957,14 +2964,14 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // select a better one. Method = Methods[0]; - if (ObjCMethodDecl *BestMethod = - SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod(), Methods)) + if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod( + Sel, ArgsIn, Method->isInstanceMethod(), Methods)) Method = BestMethod; if (!AreMultipleMethodsInGlobalPool(Sel, Method, SourceRange(LBracLoc, RBracLoc), receiverIsIdLike, Methods)) - DiagnoseUseOfDecl(Method, SelectorSlotLocs); + SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs); } } else if (ReceiverType->isObjCClassOrClassKindOfType() || ReceiverType->isObjCQualifiedClassType()) { @@ -2980,7 +2987,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (!Method) { Method = LookupMethodInQualifiedType(Sel, QClassTy, true); // warn if instance method found for a Class message. - if (Method && !isMethodDeclaredInRootProtocol(*this, Method)) { + if (Method && !isMethodDeclaredInRootProtocol(SemaRef, Method)) { Diag(SelLoc, diag::warn_instance_method_on_class_found) << Method->getSelector() << Sel; Diag(Method->getLocation(), diag::note_method_declared_at) @@ -2988,7 +2995,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } } else { - if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { + if (ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { // As a guess, try looking for the method in the current interface. // This very well may not produce the "right" method. @@ -2999,7 +3006,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (!Method) Method = ClassDecl->lookupPrivateClassMethod(Sel); - if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs)) + if (Method && SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs)) return ExprError(); } } @@ -3027,10 +3034,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } - if (ObjCMethodDecl *BestMethod = - SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod(), - Methods)) - Method = BestMethod; + if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod( + Sel, ArgsIn, Method->isInstanceMethod(), Methods)) + Method = BestMethod; } } } @@ -3047,7 +3053,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, Method = LookupMethodInQualifiedType(Sel, QIdTy, true); if (!Method) Method = LookupMethodInQualifiedType(Sel, QIdTy, false); - if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs)) + if (Method && SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs)) return ExprError(); } else if (const ObjCObjectPointerType *OCIType = ReceiverType->getAsObjCInterfacePointerType()) { @@ -3059,11 +3065,12 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // FIXME: In the non-ARC case, this will still be a hard error if the // definition is found in a module that's not visible. const ObjCInterfaceDecl *forwardClass = nullptr; - if (RequireCompleteType(Loc, OCIType->getPointeeType(), - getLangOpts().ObjCAutoRefCount - ? diag::err_arc_receiver_forward_instance - : diag::warn_receiver_forward_instance, - RecRange)) { + if (SemaRef.RequireCompleteType( + Loc, OCIType->getPointeeType(), + getLangOpts().ObjCAutoRefCount + ? diag::err_arc_receiver_forward_instance + : diag::warn_receiver_forward_instance, + RecRange)) { if (getLangOpts().ObjCAutoRefCount) return ExprError(); @@ -3104,9 +3111,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // to select a better one. Method = Methods[0]; - if (ObjCMethodDecl *BestMethod = - SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod(), - Methods)) + if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod( + Sel, ArgsIn, Method->isInstanceMethod(), Methods)) Method = BestMethod; AreMultipleMethodsInGlobalPool(Sel, Method, @@ -3121,7 +3127,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } } - if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs, forwardClass)) + if (Method && + SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs, forwardClass)) return ExprError(); } else { // Reject other random receiver types (e.g. structs). @@ -3132,8 +3139,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } FunctionScopeInfo *DIFunctionScopeInfo = - (Method && Method->getMethodFamily() == OMF_init) - ? getEnclosingFunction() : nullptr; + (Method && Method->getMethodFamily() == OMF_init) + ? SemaRef.getEnclosingFunction() + : nullptr; if (Method && Method->isDirectMethod()) { if (ReceiverType->isObjCIdType() && !isImplicit) { @@ -3199,7 +3207,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (!isDesignatedInitChain) { const ObjCMethodDecl *InitMethod = nullptr; bool isDesignated = - getCurMethodDecl()->isDesignatedInitializerForTheInterface(&InitMethod); + SemaRef.getCurMethodDecl()->isDesignatedInitializerForTheInterface( + &InitMethod); assert(isDesignated && InitMethod); (void)isDesignated; Diag(SelLoc, SuperLoc.isValid() ? @@ -3234,8 +3243,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, return ExprError(); if (Method && !Method->getReturnType()->isVoidType() && - RequireCompleteType(LBracLoc, Method->getReturnType(), - diag::err_illegal_message_expr_incomplete_type)) + SemaRef.RequireCompleteType( + LBracLoc, Method->getReturnType(), + diag::err_illegal_message_expr_incomplete_type)) return ExprError(); // In ARC, forbid the user from sending messages to @@ -3319,7 +3329,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } - DiagnoseCStringFormatDirectiveInObjCAPI(*this, Method, Sel, Args, NumArgs); + DiagnoseCStringFormatDirectiveInObjCAPI(SemaRef, Method, Sel, Args, NumArgs); // Construct the appropriate ObjCMessageExpr instance. ObjCMessageExpr *Result; @@ -3333,7 +3343,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, Context, ReturnType, VK, LBracLoc, Receiver, Sel, SelectorLocs, Method, ArrayRef(Args, NumArgs), RBracLoc, isImplicit); if (!isImplicit) - checkCocoaAPI(*this, Result); + checkCocoaAPI(SemaRef, Result); } if (Method) { bool IsClassObjectCall = ClassMessage; @@ -3344,7 +3354,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (Receiver && isSelfExpr(Receiver)) { if (const auto *OPT = ReceiverType->getAs()) { if (OPT->getObjectType()->isObjCClass()) { - if (const auto *CurMeth = getCurMethodDecl()) { + if (const auto *CurMeth = SemaRef.getCurMethodDecl()) { IsClassObjectCall = true; ReceiverType = Context.getObjCInterfaceType(CurMeth->getClassInterface()); @@ -3352,7 +3362,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } } - checkFoundationAPI(*this, SelLoc, Method, ArrayRef(Args, NumArgs), + checkFoundationAPI(SemaRef, SelLoc, Method, ArrayRef(Args, NumArgs), ReceiverType, IsClassObjectCall); } @@ -3362,7 +3372,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, (SuperLoc.isValid() || isSelfExpr(Receiver))) { // Only consider init calls *directly* in init implementations, // not within blocks. - ObjCMethodDecl *method = dyn_cast(CurContext); + ObjCMethodDecl *method = dyn_cast(SemaRef.CurContext); if (method && method->getMethodFamily() == OMF_init) { // The implicit assignment to self means we also don't want to // consume the result. @@ -3383,19 +3393,20 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak; if (!IsWeak && Sel.isUnarySelector()) IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak; - if (IsWeak && !isUnevaluatedContext() && - !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, LBracLoc)) - getCurFunction()->recordUseOfWeak(Result, Prop); + if (IsWeak && !SemaRef.isUnevaluatedContext() && + !getDiagnostics().isIgnored(diag::warn_arc_repeated_use_of_weak, + LBracLoc)) + SemaRef.getCurFunction()->recordUseOfWeak(Result, Prop); } } } CheckObjCCircularContainer(Result); - return MaybeBindToTemporary(Result); + return SemaRef.MaybeBindToTemporary(Result); } -static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) { +static void RemoveSelectorFromWarningCache(SemaObjC &S, Expr *Arg) { if (ObjCSelectorExpr *OSE = dyn_cast(Arg->IgnoreParenCasts())) { Selector Sel = OSE->getSelector(); @@ -3409,19 +3420,19 @@ static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) { // ActOnInstanceMessage - used for both unary and keyword messages. // ArgExprs is optional - if it is present, the number of expressions // is obtained from Sel.getNumArgs(). -ExprResult Sema::ActOnInstanceMessage(Scope *S, - Expr *Receiver, - Selector Sel, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, - MultiExprArg Args) { +ExprResult SemaObjC::ActOnInstanceMessage(Scope *S, Expr *Receiver, + Selector Sel, SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, + MultiExprArg Args) { + ASTContext &Context = getASTContext(); if (!Receiver) return ExprError(); // A ParenListExpr can show up while doing error recovery with invalid code. if (isa(Receiver)) { - ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Receiver); + ExprResult Result = + SemaRef.MaybeConvertParenListExprToParenExpr(S, Receiver); if (Result.isInvalid()) return ExprError(); Receiver = Result.get(); } @@ -3735,12 +3746,13 @@ namespace { }; } // end anonymous namespace -bool Sema::isKnownName(StringRef name) { +bool SemaObjC::isKnownName(StringRef name) { + ASTContext &Context = getASTContext(); if (name.empty()) return false; - LookupResult R(*this, &Context.Idents.get(name), SourceLocation(), + LookupResult R(SemaRef, &Context.Idents.get(name), SourceLocation(), Sema::LookupOrdinaryName); - return LookupName(R, TUScope, false); + return SemaRef.LookupName(R, SemaRef.TUScope, false); } template @@ -3921,7 +3933,7 @@ static void diagnoseObjCARCConversion(Sema &S, SourceRange castRange, << castType << castRange << castExpr->getSourceRange(); - bool br = S.isKnownName("CFBridgingRelease"); + bool br = S.ObjC().isKnownName("CFBridgingRelease"); ACCResult CreateRule = ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr); assert(CreateRule != ACC_bottom && "This cast should already be accepted."); @@ -3954,7 +3966,7 @@ static void diagnoseObjCARCConversion(Sema &S, SourceRange castRange, // Bridge from a CF type to an ARC type. if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) { - bool br = S.isKnownName("CFBridgingRetain"); + bool br = S.ObjC().isKnownName("CFBridgingRetain"); S.Diag(loc, diag::err_arc_cast_requires_bridge) << convKindForDiag << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type @@ -4130,7 +4142,7 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr, return true; } -void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) { +void SemaObjC::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) { if (!getLangOpts().ObjC) return; // warn in presence of __bridge casting to or from a toll free bridge cast. @@ -4138,49 +4150,47 @@ void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) { ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType); if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) { bool HasObjCBridgeAttr; - bool ObjCBridgeAttrWillNotWarn = - CheckObjCBridgeNSCast(*this, castType, castExpr, HasObjCBridgeAttr, - false); + bool ObjCBridgeAttrWillNotWarn = CheckObjCBridgeNSCast( + SemaRef, castType, castExpr, HasObjCBridgeAttr, false); if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr) return; bool HasObjCBridgeMutableAttr; bool ObjCBridgeMutableAttrWillNotWarn = - CheckObjCBridgeNSCast(*this, castType, castExpr, - HasObjCBridgeMutableAttr, false); + CheckObjCBridgeNSCast( + SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, false); if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr) return; if (HasObjCBridgeAttr) - CheckObjCBridgeNSCast(*this, castType, castExpr, HasObjCBridgeAttr, - true); + CheckObjCBridgeNSCast(SemaRef, castType, castExpr, + HasObjCBridgeAttr, true); else if (HasObjCBridgeMutableAttr) - CheckObjCBridgeNSCast(*this, castType, castExpr, - HasObjCBridgeMutableAttr, true); + CheckObjCBridgeNSCast( + SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, true); } else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) { bool HasObjCBridgeAttr; - bool ObjCBridgeAttrWillNotWarn = - CheckObjCBridgeCFCast(*this, castType, castExpr, HasObjCBridgeAttr, - false); + bool ObjCBridgeAttrWillNotWarn = CheckObjCBridgeCFCast( + SemaRef, castType, castExpr, HasObjCBridgeAttr, false); if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr) return; bool HasObjCBridgeMutableAttr; bool ObjCBridgeMutableAttrWillNotWarn = - CheckObjCBridgeCFCast(*this, castType, castExpr, - HasObjCBridgeMutableAttr, false); + CheckObjCBridgeCFCast( + SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, false); if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr) return; if (HasObjCBridgeAttr) - CheckObjCBridgeCFCast(*this, castType, castExpr, HasObjCBridgeAttr, - true); + CheckObjCBridgeCFCast(SemaRef, castType, castExpr, + HasObjCBridgeAttr, true); else if (HasObjCBridgeMutableAttr) - CheckObjCBridgeCFCast(*this, castType, castExpr, - HasObjCBridgeMutableAttr, true); + CheckObjCBridgeCFCast( + SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, true); } } -void Sema::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) { +void SemaObjC::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) { QualType SrcType = castExpr->getType(); if (ObjCPropertyRefExpr *PRE = dyn_cast(castExpr)) { if (PRE->isExplicitProperty()) { @@ -4201,8 +4211,8 @@ void Sema::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) { castExpr); } -bool Sema::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, - CastKind &Kind) { +bool SemaObjC::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, + CastKind &Kind) { if (!getLangOpts().ObjC) return false; ARCConversionTypeClass exprACTC = @@ -4218,13 +4228,12 @@ bool Sema::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, return false; } -bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, - QualType DestType, QualType SrcType, - ObjCInterfaceDecl *&RelatedClass, - ObjCMethodDecl *&ClassMethod, - ObjCMethodDecl *&InstanceMethod, - TypedefNameDecl *&TDNDecl, - bool CfToNs, bool Diagnose) { +bool SemaObjC::checkObjCBridgeRelatedComponents( + SourceLocation Loc, QualType DestType, QualType SrcType, + ObjCInterfaceDecl *&RelatedClass, ObjCMethodDecl *&ClassMethod, + ObjCMethodDecl *&InstanceMethod, TypedefNameDecl *&TDNDecl, bool CfToNs, + bool Diagnose) { + ASTContext &Context = getASTContext(); QualType T = CfToNs ? SrcType : DestType; ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl); if (!ObjCBAttr) @@ -4237,9 +4246,9 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, return false; NamedDecl *Target = nullptr; // Check for an existing type with this name. - LookupResult R(*this, DeclarationName(RCId), SourceLocation(), + LookupResult R(SemaRef, DeclarationName(RCId), SourceLocation(), Sema::LookupOrdinaryName); - if (!LookupName(R, TUScope)) { + if (!SemaRef.LookupName(R, SemaRef.TUScope)) { if (Diagnose) { Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId << SrcType << DestType; @@ -4291,10 +4300,12 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, return true; } -bool -Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, - QualType DestType, QualType SrcType, - Expr *&SrcExpr, bool Diagnose) { +bool SemaObjC::CheckObjCBridgeRelatedConversions(SourceLocation Loc, + QualType DestType, + QualType SrcType, + Expr *&SrcExpr, + bool Diagnose) { + ASTContext &Context = getASTContext(); ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType); ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType); bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable); @@ -4320,7 +4331,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, ExpressionString += " "; ExpressionString += ClassMethod->getSelector().getAsString(); SourceLocation SrcExprEndLoc = - getLocForEndOfToken(SrcExpr->getEndLoc()); + SemaRef.getLocForEndOfToken(SrcExpr->getEndLoc()); // Provide a fixit: [RelatedClass ClassMethod SrcExpr] Diag(Loc, diag::err_objc_bridged_related_known_method) << SrcType << DestType << ClassMethod->getSelector() << false @@ -4348,7 +4359,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, if (Diagnose) { std::string ExpressionString; SourceLocation SrcExprEndLoc = - getLocForEndOfToken(SrcExpr->getEndLoc()); + SemaRef.getLocForEndOfToken(SrcExpr->getEndLoc()); if (InstanceMethod->isPropertyAccessor()) if (const ObjCPropertyDecl *PDecl = InstanceMethod->findPropertyDecl()) { @@ -4384,11 +4395,12 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, return false; } -Sema::ARCConversionResult -Sema::CheckObjCConversion(SourceRange castRange, QualType castType, - Expr *&castExpr, CheckedConversionKind CCK, - bool Diagnose, bool DiagnoseCFAudited, - BinaryOperatorKind Opc) { +SemaObjC::ARCConversionResult +SemaObjC::CheckObjCConversion(SourceRange castRange, QualType castType, + Expr *&castExpr, CheckedConversionKind CCK, + bool Diagnose, bool DiagnoseCFAudited, + BinaryOperatorKind Opc) { + ASTContext &Context = getASTContext(); QualType castExprType = castExpr->getType(); // For the purposes of the classification, we assume reference types @@ -4449,11 +4461,11 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType, // pointers too, but only when the conversions are explicit. if (exprACTC == ACTC_indirectRetainable && (castACTC == ACTC_voidPtr || - (castACTC == ACTC_coreFoundation && isCast(CCK)))) + (castACTC == ACTC_coreFoundation && SemaRef.isCast(CCK)))) return ACR_okay; if (castACTC == ACTC_indirectRetainable && (exprACTC == ACTC_voidPtr || exprACTC == ACTC_coreFoundation) && - isCast(CCK)) + SemaRef.isCast(CCK)) return ACR_okay; switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) { @@ -4471,14 +4483,15 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType, castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(), CK_ARCConsumeObject, castExpr, nullptr, VK_PRValue, FPOptionsOverride()); - Cleanup.setExprNeedsCleanups(true); + SemaRef.Cleanup.setExprNeedsCleanups(true); return ACR_okay; } // If this is a non-implicit cast from id or block type to a // CoreFoundation type, delay complaining in case the cast is used // in an acceptable context. - if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) && isCast(CCK)) + if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) && + SemaRef.isCast(CCK)) return ACR_unbridged; // Issue a diagnostic about a missing @-sign when implicit casting a cstring @@ -4497,8 +4510,8 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType, !(exprACTC == ACTC_voidPtr && castACTC == ACTC_retainable && (Opc == BO_NE || Opc == BO_EQ))) { if (Diagnose) - diagnoseObjCARCConversion(*this, castRange, castType, castACTC, castExpr, - castExpr, exprACTC, CCK); + diagnoseObjCARCConversion(SemaRef, castRange, castType, castACTC, + castExpr, castExpr, exprACTC, CCK); return ACR_error; } return ACR_okay; @@ -4506,7 +4519,7 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType, /// Given that we saw an expression with the ARCUnbridgedCastTy /// placeholder type, complain bitterly. -void Sema::diagnoseARCUnbridgedCast(Expr *e) { +void SemaObjC::diagnoseARCUnbridgedCast(Expr *e) { // We expect the spurious ImplicitCastExpr to already have been stripped. assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); CastExpr *realCast = cast(e->IgnoreParens()); @@ -4533,14 +4546,15 @@ void Sema::diagnoseARCUnbridgedCast(Expr *e) { Expr *castExpr = realCast->getSubExpr(); assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable); - diagnoseObjCARCConversion(*this, castRange, castType, castACTC, - castExpr, realCast, ACTC_retainable, CCK); + diagnoseObjCARCConversion(SemaRef, castRange, castType, castACTC, castExpr, + realCast, ACTC_retainable, CCK); } /// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast /// type, remove the placeholder cast. -Expr *Sema::stripARCUnbridgedCast(Expr *e) { +Expr *SemaObjC::stripARCUnbridgedCast(Expr *e) { assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); + ASTContext &Context = getASTContext(); if (ParenExpr *pe = dyn_cast(e)) { Expr *sub = stripARCUnbridgedCast(pe->getSubExpr()); @@ -4551,7 +4565,7 @@ Expr *Sema::stripARCUnbridgedCast(Expr *e) { return UnaryOperator::Create(Context, sub, UO_Extension, sub->getType(), sub->getValueKind(), sub->getObjectKind(), uo->getOperatorLoc(), false, - CurFPFeatureOverrides()); + SemaRef.CurFPFeatureOverrides()); } else if (GenericSelectionExpr *gse = dyn_cast(e)) { assert(!gse->isResultDependent()); assert(!gse->isTypePredicate()); @@ -4579,8 +4593,9 @@ Expr *Sema::stripARCUnbridgedCast(Expr *e) { } } -bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType, - QualType exprType) { +bool SemaObjC::CheckObjCARCUnavailableWeakConversion(QualType castType, + QualType exprType) { + ASTContext &Context = getASTContext(); QualType canCastType = Context.getCanonicalType(castType).getUnqualifiedType(); QualType canExprType = @@ -4633,12 +4648,13 @@ static Expr *maybeUndoReclaimObject(Expr *e) { return e; } -ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, - ObjCBridgeCastKind Kind, - SourceLocation BridgeKeywordLoc, - TypeSourceInfo *TSInfo, - Expr *SubExpr) { - ExprResult SubResult = UsualUnaryConversions(SubExpr); +ExprResult SemaObjC::BuildObjCBridgedCast(SourceLocation LParenLoc, + ObjCBridgeCastKind Kind, + SourceLocation BridgeKeywordLoc, + TypeSourceInfo *TSInfo, + Expr *SubExpr) { + ASTContext &Context = getASTContext(); + ExprResult SubResult = SemaRef.UsualUnaryConversions(SubExpr); if (SubResult.isInvalid()) return ExprError(); SubExpr = SubResult.get(); @@ -4736,7 +4752,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, TSInfo, SubExpr); if (MustConsume) { - Cleanup.setExprNeedsCleanups(true); + SemaRef.Cleanup.setExprNeedsCleanups(true); Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result, nullptr, VK_PRValue, FPOptionsOverride()); } @@ -4744,15 +4760,15 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, return Result; } -ExprResult Sema::ActOnObjCBridgedCast(Scope *S, - SourceLocation LParenLoc, - ObjCBridgeCastKind Kind, - SourceLocation BridgeKeywordLoc, - ParsedType Type, - SourceLocation RParenLoc, - Expr *SubExpr) { +ExprResult SemaObjC::ActOnObjCBridgedCast(Scope *S, SourceLocation LParenLoc, + ObjCBridgeCastKind Kind, + SourceLocation BridgeKeywordLoc, + ParsedType Type, + SourceLocation RParenLoc, + Expr *SubExpr) { + ASTContext &Context = getASTContext(); TypeSourceInfo *TSInfo = nullptr; - QualType T = GetTypeFromParser(Type, &TSInfo); + QualType T = SemaRef.GetTypeFromParser(Type, &TSInfo); if (Kind == OBC_Bridge) CheckTollFreeBridgeCast(T, SubExpr); if (!TSInfo) @@ -4760,3 +4776,473 @@ ExprResult Sema::ActOnObjCBridgedCast(Scope *S, return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo, SubExpr); } + +DeclResult SemaObjC::LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S, + IdentifierInfo *II) { + SourceLocation Loc = Lookup.getNameLoc(); + ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl(); + + // Check for error condition which is already reported. + if (!CurMethod) + return DeclResult(true); + + // There are two cases to handle here. 1) scoped lookup could have failed, + // in which case we should look for an ivar. 2) scoped lookup could have + // found a decl, but that decl is outside the current instance method (i.e. + // a global variable). In these two cases, we do a lookup for an ivar with + // this name, if the lookup sucedes, we replace it our current decl. + + // If we're in a class method, we don't normally want to look for + // ivars. But if we don't find anything else, and there's an + // ivar, that's an error. + bool IsClassMethod = CurMethod->isClassMethod(); + + bool LookForIvars; + if (Lookup.empty()) + LookForIvars = true; + else if (IsClassMethod) + LookForIvars = false; + else + LookForIvars = (Lookup.isSingleResult() && + Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); + ObjCInterfaceDecl *IFace = nullptr; + if (LookForIvars) { + IFace = CurMethod->getClassInterface(); + ObjCInterfaceDecl *ClassDeclared; + ObjCIvarDecl *IV = nullptr; + if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) { + // Diagnose using an ivar in a class method. + if (IsClassMethod) { + Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName(); + return DeclResult(true); + } + + // Diagnose the use of an ivar outside of the declaring class. + if (IV->getAccessControl() == ObjCIvarDecl::Private && + !declaresSameEntity(ClassDeclared, IFace) && + !getLangOpts().DebuggerSupport) + Diag(Loc, diag::err_private_ivar_access) << IV->getDeclName(); + + // Success. + return IV; + } + } else if (CurMethod->isInstanceMethod()) { + // We should warn if a local variable hides an ivar. + if (ObjCInterfaceDecl *IFace = CurMethod->getClassInterface()) { + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + if (IV->getAccessControl() != ObjCIvarDecl::Private || + declaresSameEntity(IFace, ClassDeclared)) + Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); + } + } + } else if (Lookup.isSingleResult() && + Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) { + // If accessing a stand-alone ivar in a class method, this is an error. + if (const ObjCIvarDecl *IV = + dyn_cast(Lookup.getFoundDecl())) { + Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName(); + return DeclResult(true); + } + } + + // Didn't encounter an error, didn't find an ivar. + return DeclResult(false); +} + +ExprResult SemaObjC::LookupInObjCMethod(LookupResult &Lookup, Scope *S, + IdentifierInfo *II, + bool AllowBuiltinCreation) { + // FIXME: Integrate this lookup step into LookupParsedName. + DeclResult Ivar = LookupIvarInObjCMethod(Lookup, S, II); + if (Ivar.isInvalid()) + return ExprError(); + if (Ivar.isUsable()) + return BuildIvarRefExpr(S, Lookup.getNameLoc(), + cast(Ivar.get())); + + if (Lookup.empty() && II && AllowBuiltinCreation) + SemaRef.LookupBuiltin(Lookup); + + // Sentinel value saying that we didn't do anything special. + return ExprResult(false); +} + +ExprResult SemaObjC::BuildIvarRefExpr(Scope *S, SourceLocation Loc, + ObjCIvarDecl *IV) { + ASTContext &Context = getASTContext(); + ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl(); + assert(CurMethod && CurMethod->isInstanceMethod() && + "should not reference ivar from this context"); + + ObjCInterfaceDecl *IFace = CurMethod->getClassInterface(); + assert(IFace && "should not reference ivar from this context"); + + // If we're referencing an invalid decl, just return this as a silent + // error node. The error diagnostic was already emitted on the decl. + if (IV->isInvalidDecl()) + return ExprError(); + + // Check if referencing a field with __attribute__((deprecated)). + if (SemaRef.DiagnoseUseOfDecl(IV, Loc)) + return ExprError(); + + // FIXME: This should use a new expr for a direct reference, don't + // turn this into Self->ivar, just return a BareIVarExpr or something. + IdentifierInfo &II = Context.Idents.get("self"); + UnqualifiedId SelfName; + SelfName.setImplicitSelfParam(&II); + CXXScopeSpec SelfScopeSpec; + SourceLocation TemplateKWLoc; + ExprResult SelfExpr = + SemaRef.ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, SelfName, + /*HasTrailingLParen=*/false, + /*IsAddressOfOperand=*/false); + if (SelfExpr.isInvalid()) + return ExprError(); + + SelfExpr = SemaRef.DefaultLvalueConversion(SelfExpr.get()); + if (SelfExpr.isInvalid()) + return ExprError(); + + SemaRef.MarkAnyDeclReferenced(Loc, IV, true); + + ObjCMethodFamily MF = CurMethod->getMethodFamily(); + if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize && + !IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV)) + Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName(); + + ObjCIvarRefExpr *Result = new (Context) + ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc, + IV->getLocation(), SelfExpr.get(), true, true); + + if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { + if (!SemaRef.isUnevaluatedContext() && + !getDiagnostics().isIgnored(diag::warn_arc_repeated_use_of_weak, Loc)) + SemaRef.getCurFunction()->recordUseOfWeak(Result); + } + if (getLangOpts().ObjCAutoRefCount && !SemaRef.isUnevaluatedContext()) + if (const BlockDecl *BD = SemaRef.CurContext->getInnermostBlockDecl()) + SemaRef.ImplicitlyRetainedSelfLocs.push_back({Loc, BD}); + + return Result; +} + +QualType SemaObjC::FindCompositeObjCPointerType(ExprResult &LHS, + ExprResult &RHS, + SourceLocation QuestionLoc) { + ASTContext &Context = getASTContext(); + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); + + // Handle things like Class and struct objc_class*. Here we case the result + // to the pseudo-builtin, because that will be implicitly cast back to the + // redefinition type if an attempt is made to access its fields. + if (LHSTy->isObjCClassType() && + (Context.hasSameType(RHSTy, Context.getObjCClassRedefinitionType()))) { + RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSTy, + CK_CPointerToObjCPointerCast); + return LHSTy; + } + if (RHSTy->isObjCClassType() && + (Context.hasSameType(LHSTy, Context.getObjCClassRedefinitionType()))) { + LHS = SemaRef.ImpCastExprToType(LHS.get(), RHSTy, + CK_CPointerToObjCPointerCast); + return RHSTy; + } + // And the same for struct objc_object* / id + if (LHSTy->isObjCIdType() && + (Context.hasSameType(RHSTy, Context.getObjCIdRedefinitionType()))) { + RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSTy, + CK_CPointerToObjCPointerCast); + return LHSTy; + } + if (RHSTy->isObjCIdType() && + (Context.hasSameType(LHSTy, Context.getObjCIdRedefinitionType()))) { + LHS = SemaRef.ImpCastExprToType(LHS.get(), RHSTy, + CK_CPointerToObjCPointerCast); + return RHSTy; + } + // And the same for struct objc_selector* / SEL + if (Context.isObjCSelType(LHSTy) && + (Context.hasSameType(RHSTy, Context.getObjCSelRedefinitionType()))) { + RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSTy, CK_BitCast); + return LHSTy; + } + if (Context.isObjCSelType(RHSTy) && + (Context.hasSameType(LHSTy, Context.getObjCSelRedefinitionType()))) { + LHS = SemaRef.ImpCastExprToType(LHS.get(), RHSTy, CK_BitCast); + return RHSTy; + } + // Check constraints for Objective-C object pointers types. + if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) { + + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + // Two identical object pointer types are always compatible. + return LHSTy; + } + const ObjCObjectPointerType *LHSOPT = + LHSTy->castAs(); + const ObjCObjectPointerType *RHSOPT = + RHSTy->castAs(); + QualType compositeType = LHSTy; + + // If both operands are interfaces and either operand can be + // assigned to the other, use that type as the composite + // type. This allows + // xxx ? (A*) a : (B*) b + // where B is a subclass of A. + // + // Additionally, as for assignment, if either type is 'id' + // allow silent coercion. Finally, if the types are + // incompatible then make sure to use 'id' as the composite + // type so the result is acceptable for sending messages to. + + // FIXME: Consider unifying with 'areComparableObjCPointerTypes'. + // It could return the composite type. + if (!(compositeType = Context.areCommonBaseCompatible(LHSOPT, RHSOPT)) + .isNull()) { + // Nothing more to do. + } else if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) { + compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy; + } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) { + compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy; + } else if ((LHSOPT->isObjCQualifiedIdType() || + RHSOPT->isObjCQualifiedIdType()) && + Context.ObjCQualifiedIdTypesAreCompatible(LHSOPT, RHSOPT, + true)) { + // Need to handle "id" explicitly. + // GCC allows qualified id and any Objective-C type to devolve to + // id. Currently localizing to here until clear this should be + // part of ObjCQualifiedIdTypesAreCompatible. + compositeType = Context.getObjCIdType(); + } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) { + compositeType = Context.getObjCIdType(); + } else { + Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + QualType incompatTy = Context.getObjCIdType(); + LHS = SemaRef.ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast); + RHS = SemaRef.ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast); + return incompatTy; + } + // The object pointer types are compatible. + LHS = SemaRef.ImpCastExprToType(LHS.get(), compositeType, CK_BitCast); + RHS = SemaRef.ImpCastExprToType(RHS.get(), compositeType, CK_BitCast); + return compositeType; + } + // Check Objective-C object pointer types and 'void *' + if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) { + if (getLangOpts().ObjCAutoRefCount) { + // ARC forbids the implicit conversion of object pointers to 'void *', + // so these types are not compatible. + Diag(QuestionLoc, diag::err_cond_voidptr_arc) + << LHSTy << RHSTy << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + LHS = RHS = true; + return QualType(); + } + QualType lhptee = LHSTy->castAs()->getPointeeType(); + QualType rhptee = RHSTy->castAs()->getPointeeType(); + QualType destPointee = + Context.getQualifiedType(lhptee, rhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + // Add qualifiers if necessary. + LHS = SemaRef.ImpCastExprToType(LHS.get(), destType, CK_NoOp); + // Promote to void*. + RHS = SemaRef.ImpCastExprToType(RHS.get(), destType, CK_BitCast); + return destType; + } + if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { + if (getLangOpts().ObjCAutoRefCount) { + // ARC forbids the implicit conversion of object pointers to 'void *', + // so these types are not compatible. + Diag(QuestionLoc, diag::err_cond_voidptr_arc) + << LHSTy << RHSTy << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + LHS = RHS = true; + return QualType(); + } + QualType lhptee = LHSTy->castAs()->getPointeeType(); + QualType rhptee = RHSTy->castAs()->getPointeeType(); + QualType destPointee = + Context.getQualifiedType(rhptee, lhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + // Add qualifiers if necessary. + RHS = SemaRef.ImpCastExprToType(RHS.get(), destType, CK_NoOp); + // Promote to void*. + LHS = SemaRef.ImpCastExprToType(LHS.get(), destType, CK_BitCast); + return destType; + } + return QualType(); +} + +bool SemaObjC::CheckConversionToObjCLiteral(QualType DstType, Expr *&Exp, + bool Diagnose) { + if (!getLangOpts().ObjC) + return false; + + const ObjCObjectPointerType *PT = DstType->getAs(); + if (!PT) + return false; + const ObjCInterfaceDecl *ID = PT->getInterfaceDecl(); + + // Ignore any parens, implicit casts (should only be + // array-to-pointer decays), and not-so-opaque values. The last is + // important for making this trigger for property assignments. + Expr *SrcExpr = Exp->IgnoreParenImpCasts(); + if (OpaqueValueExpr *OV = dyn_cast(SrcExpr)) + if (OV->getSourceExpr()) + SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts(); + + if (auto *SL = dyn_cast(SrcExpr)) { + if (!PT->isObjCIdType() && !(ID && ID->getIdentifier()->isStr("NSString"))) + return false; + if (!SL->isOrdinary()) + return false; + + if (Diagnose) { + Diag(SL->getBeginLoc(), diag::err_missing_atsign_prefix) + << /*string*/ 0 << FixItHint::CreateInsertion(SL->getBeginLoc(), "@"); + Exp = BuildObjCStringLiteral(SL->getBeginLoc(), SL).get(); + } + return true; + } + + if ((isa(SrcExpr) || isa(SrcExpr) || + isa(SrcExpr) || isa(SrcExpr) || + isa(SrcExpr)) && + !SrcExpr->isNullPointerConstant(getASTContext(), + Expr::NPC_NeverValueDependent)) { + if (!ID || !ID->getIdentifier()->isStr("NSNumber")) + return false; + if (Diagnose) { + Diag(SrcExpr->getBeginLoc(), diag::err_missing_atsign_prefix) + << /*number*/ 1 + << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), "@"); + Expr *NumLit = + BuildObjCNumericLiteral(SrcExpr->getBeginLoc(), SrcExpr).get(); + if (NumLit) + Exp = NumLit; + } + return true; + } + + return false; +} + +/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. +ExprResult SemaObjC::ActOnObjCBoolLiteral(SourceLocation OpLoc, + tok::TokenKind Kind) { + assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) && + "Unknown Objective-C Boolean value!"); + ASTContext &Context = getASTContext(); + QualType BoolT = Context.ObjCBuiltinBoolTy; + if (!Context.getBOOLDecl()) { + LookupResult Result(SemaRef, &Context.Idents.get("BOOL"), OpLoc, + Sema::LookupOrdinaryName); + if (SemaRef.LookupName(Result, SemaRef.getCurScope()) && + Result.isSingleResult()) { + NamedDecl *ND = Result.getFoundDecl(); + if (TypedefDecl *TD = dyn_cast(ND)) + Context.setBOOLDecl(TD); + } + } + if (Context.getBOOLDecl()) + BoolT = Context.getBOOLType(); + return new (Context) + ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes, BoolT, OpLoc); +} + +ExprResult SemaObjC::ActOnObjCAvailabilityCheckExpr( + llvm::ArrayRef AvailSpecs, SourceLocation AtLoc, + SourceLocation RParen) { + ASTContext &Context = getASTContext(); + auto FindSpecVersion = + [&](StringRef Platform) -> std::optional { + auto Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) { + return Spec.getPlatform() == Platform; + }); + // Transcribe the "ios" availability check to "maccatalyst" when compiling + // for "maccatalyst" if "maccatalyst" is not specified. + if (Spec == AvailSpecs.end() && Platform == "maccatalyst") { + Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) { + return Spec.getPlatform() == "ios"; + }); + } + if (Spec == AvailSpecs.end()) + return std::nullopt; + return Spec->getVersion(); + }; + + VersionTuple Version; + if (auto MaybeVersion = + FindSpecVersion(Context.getTargetInfo().getPlatformName())) + Version = *MaybeVersion; + + // The use of `@available` in the enclosing context should be analyzed to + // warn when it's used inappropriately (i.e. not if(@available)). + if (FunctionScopeInfo *Context = SemaRef.getCurFunctionAvailabilityContext()) + Context->HasPotentialAvailabilityViolations = true; + + return new (Context) + ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy); +} + +/// Prepare a conversion of the given expression to an ObjC object +/// pointer type. +CastKind SemaObjC::PrepareCastToObjCObjectPointer(ExprResult &E) { + QualType type = E.get()->getType(); + if (type->isObjCObjectPointerType()) { + return CK_BitCast; + } else if (type->isBlockPointerType()) { + SemaRef.maybeExtendBlockObject(E); + return CK_BlockPointerToObjCPointerCast; + } else { + assert(type->isPointerType()); + return CK_CPointerToObjCPointerCast; + } +} + +SemaObjC::ObjCLiteralKind SemaObjC::CheckLiteralKind(Expr *FromE) { + FromE = FromE->IgnoreParenImpCasts(); + switch (FromE->getStmtClass()) { + default: + break; + case Stmt::ObjCStringLiteralClass: + // "string literal" + return LK_String; + case Stmt::ObjCArrayLiteralClass: + // "array literal" + return LK_Array; + case Stmt::ObjCDictionaryLiteralClass: + // "dictionary literal" + return LK_Dictionary; + case Stmt::BlockExprClass: + return LK_Block; + case Stmt::ObjCBoxedExprClass: { + Expr *Inner = cast(FromE)->getSubExpr()->IgnoreParens(); + switch (Inner->getStmtClass()) { + case Stmt::IntegerLiteralClass: + case Stmt::FloatingLiteralClass: + case Stmt::CharacterLiteralClass: + case Stmt::ObjCBoolLiteralExprClass: + case Stmt::CXXBoolLiteralExprClass: + // "numeric literal" + return LK_Numeric; + case Stmt::ImplicitCastExprClass: { + CastKind CK = cast(Inner)->getCastKind(); + // Boolean literals can be represented by implicit casts. + if (CK == CK_IntegralToBoolean || CK == CK_IntegralCast) + return LK_Numeric; + break; + } + default: + break; + } + return LK_Boxed; + } + } + return LK_None; +} diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index fe4a698a612e..708286e192f9 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -28,6 +28,7 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" @@ -6018,8 +6019,8 @@ static bool tryObjCWritebackConversion(Sema &S, // Handle write-back conversion. QualType ConvertedArgType; - if (!S.isObjCWritebackConversion(ArgType, Entity.getType(), - ConvertedArgType)) + if (!S.ObjC().isObjCWritebackConversion(ArgType, Entity.getType(), + ConvertedArgType)) return false; // We should copy unless we're passing to an argument explicitly @@ -6211,10 +6212,10 @@ void InitializationSequence::InitializeFrom(Sema &S, if (Args.size() == 1) { Initializer = Args[0]; if (S.getLangOpts().ObjC) { - if (S.CheckObjCBridgeRelatedConversions(Initializer->getBeginLoc(), - DestType, Initializer->getType(), - Initializer) || - S.CheckConversionToObjCLiteral(DestType, Initializer)) + if (S.ObjC().CheckObjCBridgeRelatedConversions( + Initializer->getBeginLoc(), DestType, Initializer->getType(), + Initializer) || + S.ObjC().CheckConversionToObjCLiteral(DestType, Initializer)) Args[0] = Initializer; } if (!isa(Initializer)) @@ -9558,12 +9559,12 @@ static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity, // Emit a possible note about the conversion failing because the // operand is a message send with a related result type. - S.EmitRelatedResultTypeNote(op); + S.ObjC().EmitRelatedResultTypeNote(op); // Emit a possible note about a return failing because we're // expecting a related result type. if (entity.getKind() == InitializedEntity::EK_Result) - S.EmitRelatedResultTypeNoteForReturn(destType); + S.ObjC().EmitRelatedResultTypeNoteForReturn(destType); } QualType fromType = op->getType(); QualType fromPointeeType = fromType.getCanonicalType()->getPointeeType(); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 7251aabc6af2..0834db95d42a 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3365,15 +3365,6 @@ NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name, return R.getAsSingle(); } -/// Find the protocol with the given name, if any. -ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II, - SourceLocation IdLoc, - RedeclarationKind Redecl) { - Decl *D = LookupSingleName(TUScope, II, IdLoc, - LookupObjCProtocolName, Redecl); - return cast_or_null(D); -} - void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, UnresolvedSetImpl &Functions) { // C++ [over.match.oper]p3: diff --git a/clang/lib/Sema/SemaObjC.cpp b/clang/lib/Sema/SemaObjC.cpp new file mode 100644 index 000000000000..1e6cc21a4870 --- /dev/null +++ b/clang/lib/Sema/SemaObjC.cpp @@ -0,0 +1,1486 @@ +//===----- SemaObjC.cpp ---- Semantic Analysis for Objective-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 implements semantic analysis for Objective-C. +/// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaObjC.h" +#include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/AST/StmtObjC.h" +#include "clang/Basic/DiagnosticSema.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/TemplateDeduction.h" +#include "llvm/Support/ConvertUTF.h" + +namespace clang { + +SemaObjC::SemaObjC(Sema &S) + : SemaBase(S), NSNumberDecl(nullptr), NSValueDecl(nullptr), + NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr), + ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), + ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), + DictionaryWithObjectsMethod(nullptr) {} + +StmtResult SemaObjC::ActOnObjCForCollectionStmt(SourceLocation ForLoc, + Stmt *First, Expr *collection, + SourceLocation RParenLoc) { + ASTContext &Context = getASTContext(); + SemaRef.setFunctionHasBranchProtectedScope(); + + ExprResult CollectionExprResult = + CheckObjCForCollectionOperand(ForLoc, collection); + + if (First) { + QualType FirstType; + if (DeclStmt *DS = dyn_cast(First)) { + if (!DS->isSingleDecl()) + return StmtError(Diag((*DS->decl_begin())->getLocation(), + diag::err_toomany_element_decls)); + + VarDecl *D = dyn_cast(DS->getSingleDecl()); + if (!D || D->isInvalidDecl()) + return StmtError(); + + FirstType = D->getType(); + // C99 6.8.5p3: The declaration part of a 'for' statement shall only + // declare identifiers for objects having storage class 'auto' or + // 'register'. + if (!D->hasLocalStorage()) + return StmtError( + Diag(D->getLocation(), diag::err_non_local_variable_decl_in_for)); + + // If the type contained 'auto', deduce the 'auto' to 'id'. + if (FirstType->getContainedAutoType()) { + SourceLocation Loc = D->getLocation(); + OpaqueValueExpr OpaqueId(Loc, Context.getObjCIdType(), VK_PRValue); + Expr *DeducedInit = &OpaqueId; + sema::TemplateDeductionInfo Info(Loc); + FirstType = QualType(); + TemplateDeductionResult Result = SemaRef.DeduceAutoType( + D->getTypeSourceInfo()->getTypeLoc(), DeducedInit, FirstType, Info); + if (Result != TemplateDeductionResult::Success && + Result != TemplateDeductionResult::AlreadyDiagnosed) + SemaRef.DiagnoseAutoDeductionFailure(D, DeducedInit); + if (FirstType.isNull()) { + D->setInvalidDecl(); + return StmtError(); + } + + D->setType(FirstType); + + if (!SemaRef.inTemplateInstantiation()) { + SourceLocation Loc = + D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); + Diag(Loc, diag::warn_auto_var_is_id) << D->getDeclName(); + } + } + + } else { + Expr *FirstE = cast(First); + if (!FirstE->isTypeDependent() && !FirstE->isLValue()) + return StmtError( + Diag(First->getBeginLoc(), diag::err_selector_element_not_lvalue) + << First->getSourceRange()); + + FirstType = static_cast(First)->getType(); + if (FirstType.isConstQualified()) + Diag(ForLoc, diag::err_selector_element_const_type) + << FirstType << First->getSourceRange(); + } + if (!FirstType->isDependentType() && + !FirstType->isObjCObjectPointerType() && + !FirstType->isBlockPointerType()) + return StmtError(Diag(ForLoc, diag::err_selector_element_type) + << FirstType << First->getSourceRange()); + } + + if (CollectionExprResult.isInvalid()) + return StmtError(); + + CollectionExprResult = SemaRef.ActOnFinishFullExpr(CollectionExprResult.get(), + /*DiscardedValue*/ false); + if (CollectionExprResult.isInvalid()) + return StmtError(); + + return new (Context) ObjCForCollectionStmt(First, CollectionExprResult.get(), + nullptr, ForLoc, RParenLoc); +} + +ExprResult SemaObjC::CheckObjCForCollectionOperand(SourceLocation forLoc, + Expr *collection) { + ASTContext &Context = getASTContext(); + if (!collection) + return ExprError(); + + ExprResult result = SemaRef.CorrectDelayedTyposInExpr(collection); + if (!result.isUsable()) + return ExprError(); + collection = result.get(); + + // Bail out early if we've got a type-dependent expression. + if (collection->isTypeDependent()) + return collection; + + // Perform normal l-value conversion. + result = SemaRef.DefaultFunctionArrayLvalueConversion(collection); + if (result.isInvalid()) + return ExprError(); + collection = result.get(); + + // The operand needs to have object-pointer type. + // TODO: should we do a contextual conversion? + const ObjCObjectPointerType *pointerType = + collection->getType()->getAs(); + if (!pointerType) + return Diag(forLoc, diag::err_collection_expr_type) + << collection->getType() << collection->getSourceRange(); + + // Check that the operand provides + // - countByEnumeratingWithState:objects:count: + const ObjCObjectType *objectType = pointerType->getObjectType(); + ObjCInterfaceDecl *iface = objectType->getInterface(); + + // If we have a forward-declared type, we can't do this check. + // Under ARC, it is an error not to have a forward-declared class. + if (iface && + (getLangOpts().ObjCAutoRefCount + ? SemaRef.RequireCompleteType(forLoc, QualType(objectType, 0), + diag::err_arc_collection_forward, + collection) + : !SemaRef.isCompleteType(forLoc, QualType(objectType, 0)))) { + // Otherwise, if we have any useful type information, check that + // the type declares the appropriate method. + } else if (iface || !objectType->qual_empty()) { + const IdentifierInfo *selectorIdents[] = { + &Context.Idents.get("countByEnumeratingWithState"), + &Context.Idents.get("objects"), &Context.Idents.get("count")}; + Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]); + + ObjCMethodDecl *method = nullptr; + + // If there's an interface, look in both the public and private APIs. + if (iface) { + method = iface->lookupInstanceMethod(selector); + if (!method) + method = iface->lookupPrivateMethod(selector); + } + + // Also check protocol qualifiers. + if (!method) + method = LookupMethodInQualifiedType(selector, pointerType, + /*instance*/ true); + + // If we didn't find it anywhere, give up. + if (!method) { + Diag(forLoc, diag::warn_collection_expr_type) + << collection->getType() << selector << collection->getSourceRange(); + } + + // TODO: check for an incompatible signature? + } + + // Wrap up any cleanups in the expression. + return collection; +} + +StmtResult SemaObjC::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) { + if (!S || !B) + return StmtError(); + ObjCForCollectionStmt *ForStmt = cast(S); + + ForStmt->setBody(B); + return S; +} + +StmtResult SemaObjC::ActOnObjCAtCatchStmt(SourceLocation AtLoc, + SourceLocation RParen, Decl *Parm, + Stmt *Body) { + ASTContext &Context = getASTContext(); + VarDecl *Var = cast_or_null(Parm); + if (Var && Var->isInvalidDecl()) + return StmtError(); + + return new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body); +} + +StmtResult SemaObjC::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) { + ASTContext &Context = getASTContext(); + return new (Context) ObjCAtFinallyStmt(AtLoc, Body); +} + +StmtResult SemaObjC::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, + MultiStmtArg CatchStmts, + Stmt *Finally) { + ASTContext &Context = getASTContext(); + if (!getLangOpts().ObjCExceptions) + Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try"; + + // Objective-C try is incompatible with SEH __try. + sema::FunctionScopeInfo *FSI = SemaRef.getCurFunction(); + if (FSI->FirstSEHTryLoc.isValid()) { + Diag(AtLoc, diag::err_mixing_cxx_try_seh_try) << 1; + Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'"; + } + + FSI->setHasObjCTry(AtLoc); + unsigned NumCatchStmts = CatchStmts.size(); + return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(), + NumCatchStmts, Finally); +} + +StmtResult SemaObjC::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { + ASTContext &Context = getASTContext(); + if (Throw) { + ExprResult Result = SemaRef.DefaultLvalueConversion(Throw); + if (Result.isInvalid()) + return StmtError(); + + Result = + SemaRef.ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false); + if (Result.isInvalid()) + return StmtError(); + Throw = Result.get(); + + QualType ThrowType = Throw->getType(); + // Make sure the expression type is an ObjC pointer or "void *". + if (!ThrowType->isDependentType() && + !ThrowType->isObjCObjectPointerType()) { + const PointerType *PT = ThrowType->getAs(); + if (!PT || !PT->getPointeeType()->isVoidType()) + return StmtError(Diag(AtLoc, diag::err_objc_throw_expects_object) + << Throw->getType() << Throw->getSourceRange()); + } + } + + return new (Context) ObjCAtThrowStmt(AtLoc, Throw); +} + +StmtResult SemaObjC::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, + Scope *CurScope) { + if (!getLangOpts().ObjCExceptions) + Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw"; + + if (!Throw) { + // @throw without an expression designates a rethrow (which must occur + // in the context of an @catch clause). + Scope *AtCatchParent = CurScope; + while (AtCatchParent && !AtCatchParent->isAtCatchScope()) + AtCatchParent = AtCatchParent->getParent(); + if (!AtCatchParent) + return StmtError(Diag(AtLoc, diag::err_rethrow_used_outside_catch)); + } + return BuildObjCAtThrowStmt(AtLoc, Throw); +} + +ExprResult SemaObjC::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, + Expr *operand) { + ExprResult result = SemaRef.DefaultLvalueConversion(operand); + if (result.isInvalid()) + return ExprError(); + operand = result.get(); + + // Make sure the expression type is an ObjC pointer or "void *". + QualType type = operand->getType(); + if (!type->isDependentType() && !type->isObjCObjectPointerType()) { + const PointerType *pointerType = type->getAs(); + if (!pointerType || !pointerType->getPointeeType()->isVoidType()) { + if (getLangOpts().CPlusPlus) { + if (SemaRef.RequireCompleteType(atLoc, type, + diag::err_incomplete_receiver_type)) + return Diag(atLoc, diag::err_objc_synchronized_expects_object) + << type << operand->getSourceRange(); + + ExprResult result = + SemaRef.PerformContextuallyConvertToObjCPointer(operand); + if (result.isInvalid()) + return ExprError(); + if (!result.isUsable()) + return Diag(atLoc, diag::err_objc_synchronized_expects_object) + << type << operand->getSourceRange(); + + operand = result.get(); + } else { + return Diag(atLoc, diag::err_objc_synchronized_expects_object) + << type << operand->getSourceRange(); + } + } + } + + // The operand to @synchronized is a full-expression. + return SemaRef.ActOnFinishFullExpr(operand, /*DiscardedValue*/ false); +} + +StmtResult SemaObjC::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, + Expr *SyncExpr, + Stmt *SyncBody) { + ASTContext &Context = getASTContext(); + // We can't jump into or indirect-jump out of a @synchronized block. + SemaRef.setFunctionHasBranchProtectedScope(); + return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody); +} + +StmtResult SemaObjC::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, + Stmt *Body) { + ASTContext &Context = getASTContext(); + SemaRef.setFunctionHasBranchProtectedScope(); + return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body); +} + +TypeResult SemaObjC::actOnObjCProtocolQualifierType( + SourceLocation lAngleLoc, ArrayRef protocols, + ArrayRef protocolLocs, SourceLocation rAngleLoc) { + ASTContext &Context = getASTContext(); + // Form id. + QualType Result = Context.getObjCObjectType( + Context.ObjCBuiltinIdTy, {}, + llvm::ArrayRef((ObjCProtocolDecl *const *)protocols.data(), + protocols.size()), + false); + Result = Context.getObjCObjectPointerType(Result); + + TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result); + TypeLoc ResultTL = ResultTInfo->getTypeLoc(); + + auto ObjCObjectPointerTL = ResultTL.castAs(); + ObjCObjectPointerTL.setStarLoc(SourceLocation()); // implicit + + auto ObjCObjectTL = + ObjCObjectPointerTL.getPointeeLoc().castAs(); + ObjCObjectTL.setHasBaseTypeAsWritten(false); + ObjCObjectTL.getBaseLoc().initialize(Context, SourceLocation()); + + // No type arguments. + ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation()); + ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation()); + + // Fill in protocol qualifiers. + ObjCObjectTL.setProtocolLAngleLoc(lAngleLoc); + ObjCObjectTL.setProtocolRAngleLoc(rAngleLoc); + for (unsigned i = 0, n = protocols.size(); i != n; ++i) + ObjCObjectTL.setProtocolLoc(i, protocolLocs[i]); + + // We're done. Return the completed type to the parser. + return SemaRef.CreateParsedType(Result, ResultTInfo); +} + +TypeResult SemaObjC::actOnObjCTypeArgsAndProtocolQualifiers( + Scope *S, SourceLocation Loc, ParsedType BaseType, + SourceLocation TypeArgsLAngleLoc, ArrayRef TypeArgs, + SourceLocation TypeArgsRAngleLoc, SourceLocation ProtocolLAngleLoc, + ArrayRef Protocols, ArrayRef ProtocolLocs, + SourceLocation ProtocolRAngleLoc) { + ASTContext &Context = getASTContext(); + TypeSourceInfo *BaseTypeInfo = nullptr; + QualType T = SemaRef.GetTypeFromParser(BaseType, &BaseTypeInfo); + if (T.isNull()) + return true; + + // Handle missing type-source info. + if (!BaseTypeInfo) + BaseTypeInfo = Context.getTrivialTypeSourceInfo(T, Loc); + + // Extract type arguments. + SmallVector ActualTypeArgInfos; + for (unsigned i = 0, n = TypeArgs.size(); i != n; ++i) { + TypeSourceInfo *TypeArgInfo = nullptr; + QualType TypeArg = SemaRef.GetTypeFromParser(TypeArgs[i], &TypeArgInfo); + if (TypeArg.isNull()) { + ActualTypeArgInfos.clear(); + break; + } + + assert(TypeArgInfo && "No type source info?"); + ActualTypeArgInfos.push_back(TypeArgInfo); + } + + // Build the object type. + QualType Result = BuildObjCObjectType( + T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(), + TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc, + ProtocolLAngleLoc, + llvm::ArrayRef((ObjCProtocolDecl *const *)Protocols.data(), + Protocols.size()), + ProtocolLocs, ProtocolRAngleLoc, + /*FailOnError=*/false, + /*Rebuilding=*/false); + + if (Result == T) + return BaseType; + + // Create source information for this type. + TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result); + TypeLoc ResultTL = ResultTInfo->getTypeLoc(); + + // For id or Class, we'll have an + // object pointer type. Fill in source information for it. + if (auto ObjCObjectPointerTL = ResultTL.getAs()) { + // The '*' is implicit. + ObjCObjectPointerTL.setStarLoc(SourceLocation()); + ResultTL = ObjCObjectPointerTL.getPointeeLoc(); + } + + if (auto OTPTL = ResultTL.getAs()) { + // Protocol qualifier information. + if (OTPTL.getNumProtocols() > 0) { + assert(OTPTL.getNumProtocols() == Protocols.size()); + OTPTL.setProtocolLAngleLoc(ProtocolLAngleLoc); + OTPTL.setProtocolRAngleLoc(ProtocolRAngleLoc); + for (unsigned i = 0, n = Protocols.size(); i != n; ++i) + OTPTL.setProtocolLoc(i, ProtocolLocs[i]); + } + + // We're done. Return the completed type to the parser. + return SemaRef.CreateParsedType(Result, ResultTInfo); + } + + auto ObjCObjectTL = ResultTL.castAs(); + + // Type argument information. + if (ObjCObjectTL.getNumTypeArgs() > 0) { + assert(ObjCObjectTL.getNumTypeArgs() == ActualTypeArgInfos.size()); + ObjCObjectTL.setTypeArgsLAngleLoc(TypeArgsLAngleLoc); + ObjCObjectTL.setTypeArgsRAngleLoc(TypeArgsRAngleLoc); + for (unsigned i = 0, n = ActualTypeArgInfos.size(); i != n; ++i) + ObjCObjectTL.setTypeArgTInfo(i, ActualTypeArgInfos[i]); + } else { + ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation()); + ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation()); + } + + // Protocol qualifier information. + if (ObjCObjectTL.getNumProtocols() > 0) { + assert(ObjCObjectTL.getNumProtocols() == Protocols.size()); + ObjCObjectTL.setProtocolLAngleLoc(ProtocolLAngleLoc); + ObjCObjectTL.setProtocolRAngleLoc(ProtocolRAngleLoc); + for (unsigned i = 0, n = Protocols.size(); i != n; ++i) + ObjCObjectTL.setProtocolLoc(i, ProtocolLocs[i]); + } else { + ObjCObjectTL.setProtocolLAngleLoc(SourceLocation()); + ObjCObjectTL.setProtocolRAngleLoc(SourceLocation()); + } + + // Base type. + ObjCObjectTL.setHasBaseTypeAsWritten(true); + if (ObjCObjectTL.getType() == T) + ObjCObjectTL.getBaseLoc().initializeFullCopy(BaseTypeInfo->getTypeLoc()); + else + ObjCObjectTL.getBaseLoc().initialize(Context, Loc); + + // We're done. Return the completed type to the parser. + return SemaRef.CreateParsedType(Result, ResultTInfo); +} + +QualType SemaObjC::BuildObjCTypeParamType( + const ObjCTypeParamDecl *Decl, SourceLocation ProtocolLAngleLoc, + ArrayRef Protocols, + ArrayRef ProtocolLocs, SourceLocation ProtocolRAngleLoc, + bool FailOnError) { + ASTContext &Context = getASTContext(); + QualType Result = QualType(Decl->getTypeForDecl(), 0); + if (!Protocols.empty()) { + bool HasError; + Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError); + if (HasError) { + Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers) + << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc); + if (FailOnError) + Result = QualType(); + } + if (FailOnError && Result.isNull()) + return QualType(); + } + + return Result; +} + +/// Apply Objective-C type arguments to the given type. +static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, + ArrayRef typeArgs, + SourceRange typeArgsRange, bool failOnError, + bool rebuilding) { + // We can only apply type arguments to an Objective-C class type. + const auto *objcObjectType = type->getAs(); + if (!objcObjectType || !objcObjectType->getInterface()) { + S.Diag(loc, diag::err_objc_type_args_non_class) << type << typeArgsRange; + + if (failOnError) + return QualType(); + return type; + } + + // The class type must be parameterized. + ObjCInterfaceDecl *objcClass = objcObjectType->getInterface(); + ObjCTypeParamList *typeParams = objcClass->getTypeParamList(); + if (!typeParams) { + S.Diag(loc, diag::err_objc_type_args_non_parameterized_class) + << objcClass->getDeclName() << FixItHint::CreateRemoval(typeArgsRange); + + if (failOnError) + return QualType(); + + return type; + } + + // The type must not already be specialized. + if (objcObjectType->isSpecialized()) { + S.Diag(loc, diag::err_objc_type_args_specialized_class) + << type << FixItHint::CreateRemoval(typeArgsRange); + + if (failOnError) + return QualType(); + + return type; + } + + // Check the type arguments. + SmallVector finalTypeArgs; + unsigned numTypeParams = typeParams->size(); + bool anyPackExpansions = false; + for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) { + TypeSourceInfo *typeArgInfo = typeArgs[i]; + QualType typeArg = typeArgInfo->getType(); + + // Type arguments cannot have explicit qualifiers or nullability. + // We ignore indirect sources of these, e.g. behind typedefs or + // template arguments. + if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) { + bool diagnosed = false; + SourceRange rangeToRemove; + if (auto attr = qual.getAs()) { + rangeToRemove = attr.getLocalSourceRange(); + if (attr.getTypePtr()->getImmediateNullability()) { + typeArg = attr.getTypePtr()->getModifiedType(); + S.Diag(attr.getBeginLoc(), + diag::err_objc_type_arg_explicit_nullability) + << typeArg << FixItHint::CreateRemoval(rangeToRemove); + diagnosed = true; + } + } + + // When rebuilding, qualifiers might have gotten here through a + // final substitution. + if (!rebuilding && !diagnosed) { + S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified) + << typeArg << typeArg.getQualifiers().getAsString() + << FixItHint::CreateRemoval(rangeToRemove); + } + } + + // Remove qualifiers even if they're non-local. + typeArg = typeArg.getUnqualifiedType(); + + finalTypeArgs.push_back(typeArg); + + if (typeArg->getAs()) + anyPackExpansions = true; + + // Find the corresponding type parameter, if there is one. + ObjCTypeParamDecl *typeParam = nullptr; + if (!anyPackExpansions) { + if (i < numTypeParams) { + typeParam = typeParams->begin()[i]; + } else { + // Too many arguments. + S.Diag(loc, diag::err_objc_type_args_wrong_arity) + << false << objcClass->getDeclName() << (unsigned)typeArgs.size() + << numTypeParams; + S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass; + + if (failOnError) + return QualType(); + + return type; + } + } + + // Objective-C object pointer types must be substitutable for the bounds. + if (const auto *typeArgObjC = typeArg->getAs()) { + // If we don't have a type parameter to match against, assume + // everything is fine. There was a prior pack expansion that + // means we won't be able to match anything. + if (!typeParam) { + assert(anyPackExpansions && "Too many arguments?"); + continue; + } + + // Retrieve the bound. + QualType bound = typeParam->getUnderlyingType(); + const auto *boundObjC = bound->castAs(); + + // Determine whether the type argument is substitutable for the bound. + if (typeArgObjC->isObjCIdType()) { + // When the type argument is 'id', the only acceptable type + // parameter bound is 'id'. + if (boundObjC->isObjCIdType()) + continue; + } else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) { + // Otherwise, we follow the assignability rules. + continue; + } + + // Diagnose the mismatch. + S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), + diag::err_objc_type_arg_does_not_match_bound) + << typeArg << bound << typeParam->getDeclName(); + S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) + << typeParam->getDeclName(); + + if (failOnError) + return QualType(); + + return type; + } + + // Block pointer types are permitted for unqualified 'id' bounds. + if (typeArg->isBlockPointerType()) { + // If we don't have a type parameter to match against, assume + // everything is fine. There was a prior pack expansion that + // means we won't be able to match anything. + if (!typeParam) { + assert(anyPackExpansions && "Too many arguments?"); + continue; + } + + // Retrieve the bound. + QualType bound = typeParam->getUnderlyingType(); + if (bound->isBlockCompatibleObjCPointerType(S.Context)) + continue; + + // Diagnose the mismatch. + S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), + diag::err_objc_type_arg_does_not_match_bound) + << typeArg << bound << typeParam->getDeclName(); + S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) + << typeParam->getDeclName(); + + if (failOnError) + return QualType(); + + return type; + } + + // Types that have __attribute__((NSObject)) are permitted. + if (typeArg->isObjCNSObjectType()) { + continue; + } + + // Dependent types will be checked at instantiation time. + if (typeArg->isDependentType()) { + continue; + } + + // Diagnose non-id-compatible type arguments. + S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), + diag::err_objc_type_arg_not_id_compatible) + << typeArg << typeArgInfo->getTypeLoc().getSourceRange(); + + if (failOnError) + return QualType(); + + return type; + } + + // Make sure we didn't have the wrong number of arguments. + if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) { + S.Diag(loc, diag::err_objc_type_args_wrong_arity) + << (typeArgs.size() < typeParams->size()) << objcClass->getDeclName() + << (unsigned)finalTypeArgs.size() << (unsigned)numTypeParams; + S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass; + + if (failOnError) + return QualType(); + + return type; + } + + // Success. Form the specialized type. + return S.Context.getObjCObjectType(type, finalTypeArgs, {}, false); +} + +QualType SemaObjC::BuildObjCObjectType( + QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc, + ArrayRef TypeArgs, SourceLocation TypeArgsRAngleLoc, + SourceLocation ProtocolLAngleLoc, ArrayRef Protocols, + ArrayRef ProtocolLocs, SourceLocation ProtocolRAngleLoc, + bool FailOnError, bool Rebuilding) { + ASTContext &Context = getASTContext(); + QualType Result = BaseType; + if (!TypeArgs.empty()) { + Result = + applyObjCTypeArgs(SemaRef, Loc, Result, TypeArgs, + SourceRange(TypeArgsLAngleLoc, TypeArgsRAngleLoc), + FailOnError, Rebuilding); + if (FailOnError && Result.isNull()) + return QualType(); + } + + if (!Protocols.empty()) { + bool HasError; + Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError); + if (HasError) { + Diag(Loc, diag::err_invalid_protocol_qualifiers) + << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc); + if (FailOnError) + Result = QualType(); + } + if (FailOnError && Result.isNull()) + return QualType(); + } + + return Result; +} + +ParsedType SemaObjC::ActOnObjCInstanceType(SourceLocation Loc) { + ASTContext &Context = getASTContext(); + QualType T = Context.getObjCInstanceType(); + TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc); + return SemaRef.CreateParsedType(T, TInfo); +} + +//===--- CHECK: Objective-C retain cycles ----------------------------------// + +namespace { + +struct RetainCycleOwner { + VarDecl *Variable = nullptr; + SourceRange Range; + SourceLocation Loc; + bool Indirect = false; + + RetainCycleOwner() = default; + + void setLocsFrom(Expr *e) { + Loc = e->getExprLoc(); + Range = e->getSourceRange(); + } +}; + +} // namespace + +/// Consider whether capturing the given variable can possibly lead to +/// a retain cycle. +static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) { + // In ARC, it's captured strongly iff the variable has __strong + // lifetime. In MRR, it's captured strongly if the variable is + // __block and has an appropriate type. + if (var->getType().getObjCLifetime() != Qualifiers::OCL_Strong) + return false; + + owner.Variable = var; + if (ref) + owner.setLocsFrom(ref); + return true; +} + +static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) { + while (true) { + e = e->IgnoreParens(); + if (CastExpr *cast = dyn_cast(e)) { + switch (cast->getCastKind()) { + case CK_BitCast: + case CK_LValueBitCast: + case CK_LValueToRValue: + case CK_ARCReclaimReturnedObject: + e = cast->getSubExpr(); + continue; + + default: + return false; + } + } + + if (ObjCIvarRefExpr *ref = dyn_cast(e)) { + ObjCIvarDecl *ivar = ref->getDecl(); + if (ivar->getType().getObjCLifetime() != Qualifiers::OCL_Strong) + return false; + + // Try to find a retain cycle in the base. + if (!findRetainCycleOwner(S, ref->getBase(), owner)) + return false; + + if (ref->isFreeIvar()) + owner.setLocsFrom(ref); + owner.Indirect = true; + return true; + } + + if (DeclRefExpr *ref = dyn_cast(e)) { + VarDecl *var = dyn_cast(ref->getDecl()); + if (!var) + return false; + return considerVariable(var, ref, owner); + } + + if (MemberExpr *member = dyn_cast(e)) { + if (member->isArrow()) + return false; + + // Don't count this as an indirect ownership. + e = member->getBase(); + continue; + } + + if (PseudoObjectExpr *pseudo = dyn_cast(e)) { + // Only pay attention to pseudo-objects on property references. + ObjCPropertyRefExpr *pre = dyn_cast( + pseudo->getSyntacticForm()->IgnoreParens()); + if (!pre) + return false; + if (pre->isImplicitProperty()) + return false; + ObjCPropertyDecl *property = pre->getExplicitProperty(); + if (!property->isRetaining() && + !(property->getPropertyIvarDecl() && + property->getPropertyIvarDecl()->getType().getObjCLifetime() == + Qualifiers::OCL_Strong)) + return false; + + owner.Indirect = true; + if (pre->isSuperReceiver()) { + owner.Variable = S.getCurMethodDecl()->getSelfDecl(); + if (!owner.Variable) + return false; + owner.Loc = pre->getLocation(); + owner.Range = pre->getSourceRange(); + return true; + } + e = const_cast( + cast(pre->getBase())->getSourceExpr()); + continue; + } + + // Array ivars? + + return false; + } +} + +namespace { + +struct FindCaptureVisitor : EvaluatedExprVisitor { + VarDecl *Variable; + Expr *Capturer = nullptr; + bool VarWillBeReased = false; + + FindCaptureVisitor(ASTContext &Context, VarDecl *variable) + : EvaluatedExprVisitor(Context), Variable(variable) {} + + void VisitDeclRefExpr(DeclRefExpr *ref) { + if (ref->getDecl() == Variable && !Capturer) + Capturer = ref; + } + + void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) { + if (Capturer) + return; + Visit(ref->getBase()); + if (Capturer && ref->isFreeIvar()) + Capturer = ref; + } + + void VisitBlockExpr(BlockExpr *block) { + // Look inside nested blocks + if (block->getBlockDecl()->capturesVariable(Variable)) + Visit(block->getBlockDecl()->getBody()); + } + + void VisitOpaqueValueExpr(OpaqueValueExpr *OVE) { + if (Capturer) + return; + if (OVE->getSourceExpr()) + Visit(OVE->getSourceExpr()); + } + + void VisitBinaryOperator(BinaryOperator *BinOp) { + if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign) + return; + Expr *LHS = BinOp->getLHS(); + if (const DeclRefExpr *DRE = dyn_cast_or_null(LHS)) { + if (DRE->getDecl() != Variable) + return; + if (Expr *RHS = BinOp->getRHS()) { + RHS = RHS->IgnoreParenCasts(); + std::optional Value; + VarWillBeReased = + (RHS && (Value = RHS->getIntegerConstantExpr(Context)) && + *Value == 0); + } + } + } +}; + +} // namespace + +/// Check whether the given argument is a block which captures a +/// variable. +static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) { + assert(owner.Variable && owner.Loc.isValid()); + + e = e->IgnoreParenCasts(); + + // Look through [^{...} copy] and Block_copy(^{...}). + if (ObjCMessageExpr *ME = dyn_cast(e)) { + Selector Cmd = ME->getSelector(); + if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") { + e = ME->getInstanceReceiver(); + if (!e) + return nullptr; + e = e->IgnoreParenCasts(); + } + } else if (CallExpr *CE = dyn_cast(e)) { + if (CE->getNumArgs() == 1) { + FunctionDecl *Fn = dyn_cast_or_null(CE->getCalleeDecl()); + if (Fn) { + const IdentifierInfo *FnI = Fn->getIdentifier(); + if (FnI && FnI->isStr("_Block_copy")) { + e = CE->getArg(0)->IgnoreParenCasts(); + } + } + } + } + + BlockExpr *block = dyn_cast(e); + if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable)) + return nullptr; + + FindCaptureVisitor visitor(S.Context, owner.Variable); + visitor.Visit(block->getBlockDecl()->getBody()); + return visitor.VarWillBeReased ? nullptr : visitor.Capturer; +} + +static void diagnoseRetainCycle(Sema &S, Expr *capturer, + RetainCycleOwner &owner) { + assert(capturer); + assert(owner.Variable && owner.Loc.isValid()); + + S.Diag(capturer->getExprLoc(), diag::warn_arc_retain_cycle) + << owner.Variable << capturer->getSourceRange(); + S.Diag(owner.Loc, diag::note_arc_retain_cycle_owner) + << owner.Indirect << owner.Range; +} + +/// Check for a keyword selector that starts with the word 'add' or +/// 'set'. +static bool isSetterLikeSelector(Selector sel) { + if (sel.isUnarySelector()) + return false; + + StringRef str = sel.getNameForSlot(0); + str = str.ltrim('_'); + if (str.starts_with("set")) + str = str.substr(3); + else if (str.starts_with("add")) { + // Specially allow 'addOperationWithBlock:'. + if (sel.getNumArgs() == 1 && str.starts_with("addOperationWithBlock")) + return false; + str = str.substr(3); + } else + return false; + + if (str.empty()) + return true; + return !isLowercase(str.front()); +} + +static std::optional +GetNSMutableArrayArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) { + bool IsMutableArray = S.NSAPIObj->isSubclassOfNSClass( + Message->getReceiverInterface(), NSAPI::ClassId_NSMutableArray); + if (!IsMutableArray) { + return std::nullopt; + } + + Selector Sel = Message->getSelector(); + + std::optional MKOpt = + S.NSAPIObj->getNSArrayMethodKind(Sel); + if (!MKOpt) { + return std::nullopt; + } + + NSAPI::NSArrayMethodKind MK = *MKOpt; + + switch (MK) { + case NSAPI::NSMutableArr_addObject: + case NSAPI::NSMutableArr_insertObjectAtIndex: + case NSAPI::NSMutableArr_setObjectAtIndexedSubscript: + return 0; + case NSAPI::NSMutableArr_replaceObjectAtIndex: + return 1; + + default: + return std::nullopt; + } + + return std::nullopt; +} + +static std::optional +GetNSMutableDictionaryArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) { + bool IsMutableDictionary = S.NSAPIObj->isSubclassOfNSClass( + Message->getReceiverInterface(), NSAPI::ClassId_NSMutableDictionary); + if (!IsMutableDictionary) { + return std::nullopt; + } + + Selector Sel = Message->getSelector(); + + std::optional MKOpt = + S.NSAPIObj->getNSDictionaryMethodKind(Sel); + if (!MKOpt) { + return std::nullopt; + } + + NSAPI::NSDictionaryMethodKind MK = *MKOpt; + + switch (MK) { + case NSAPI::NSMutableDict_setObjectForKey: + case NSAPI::NSMutableDict_setValueForKey: + case NSAPI::NSMutableDict_setObjectForKeyedSubscript: + return 0; + + default: + return std::nullopt; + } + + return std::nullopt; +} + +static std::optional GetNSSetArgumentIndex(SemaObjC &S, + ObjCMessageExpr *Message) { + bool IsMutableSet = S.NSAPIObj->isSubclassOfNSClass( + Message->getReceiverInterface(), NSAPI::ClassId_NSMutableSet); + + bool IsMutableOrderedSet = S.NSAPIObj->isSubclassOfNSClass( + Message->getReceiverInterface(), NSAPI::ClassId_NSMutableOrderedSet); + if (!IsMutableSet && !IsMutableOrderedSet) { + return std::nullopt; + } + + Selector Sel = Message->getSelector(); + + std::optional MKOpt = + S.NSAPIObj->getNSSetMethodKind(Sel); + if (!MKOpt) { + return std::nullopt; + } + + NSAPI::NSSetMethodKind MK = *MKOpt; + + switch (MK) { + case NSAPI::NSMutableSet_addObject: + case NSAPI::NSOrderedSet_setObjectAtIndex: + case NSAPI::NSOrderedSet_setObjectAtIndexedSubscript: + case NSAPI::NSOrderedSet_insertObjectAtIndex: + return 0; + case NSAPI::NSOrderedSet_replaceObjectAtIndexWithObject: + return 1; + } + + return std::nullopt; +} + +void SemaObjC::CheckObjCCircularContainer(ObjCMessageExpr *Message) { + if (!Message->isInstanceMessage()) { + return; + } + + std::optional ArgOpt; + + if (!(ArgOpt = GetNSMutableArrayArgumentIndex(*this, Message)) && + !(ArgOpt = GetNSMutableDictionaryArgumentIndex(*this, Message)) && + !(ArgOpt = GetNSSetArgumentIndex(*this, Message))) { + return; + } + + int ArgIndex = *ArgOpt; + + Expr *Arg = Message->getArg(ArgIndex)->IgnoreImpCasts(); + if (OpaqueValueExpr *OE = dyn_cast(Arg)) { + Arg = OE->getSourceExpr()->IgnoreImpCasts(); + } + + if (Message->getReceiverKind() == ObjCMessageExpr::SuperInstance) { + if (DeclRefExpr *ArgRE = dyn_cast(Arg)) { + if (ArgRE->isObjCSelfExpr()) { + Diag(Message->getSourceRange().getBegin(), + diag::warn_objc_circular_container) + << ArgRE->getDecl() << StringRef("'super'"); + } + } + } else { + Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts(); + + if (OpaqueValueExpr *OE = dyn_cast(Receiver)) { + Receiver = OE->getSourceExpr()->IgnoreImpCasts(); + } + + if (DeclRefExpr *ReceiverRE = dyn_cast(Receiver)) { + if (DeclRefExpr *ArgRE = dyn_cast(Arg)) { + if (ReceiverRE->getDecl() == ArgRE->getDecl()) { + ValueDecl *Decl = ReceiverRE->getDecl(); + Diag(Message->getSourceRange().getBegin(), + diag::warn_objc_circular_container) + << Decl << Decl; + if (!ArgRE->isObjCSelfExpr()) { + Diag(Decl->getLocation(), + diag::note_objc_circular_container_declared_here) + << Decl; + } + } + } + } else if (ObjCIvarRefExpr *IvarRE = dyn_cast(Receiver)) { + if (ObjCIvarRefExpr *IvarArgRE = dyn_cast(Arg)) { + if (IvarRE->getDecl() == IvarArgRE->getDecl()) { + ObjCIvarDecl *Decl = IvarRE->getDecl(); + Diag(Message->getSourceRange().getBegin(), + diag::warn_objc_circular_container) + << Decl << Decl; + Diag(Decl->getLocation(), + diag::note_objc_circular_container_declared_here) + << Decl; + } + } + } + } +} + +/// Check a message send to see if it's likely to cause a retain cycle. +void SemaObjC::checkRetainCycles(ObjCMessageExpr *msg) { + // Only check instance methods whose selector looks like a setter. + if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector())) + return; + + // Try to find a variable that the receiver is strongly owned by. + RetainCycleOwner owner; + if (msg->getReceiverKind() == ObjCMessageExpr::Instance) { + if (!findRetainCycleOwner(SemaRef, msg->getInstanceReceiver(), owner)) + return; + } else { + assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance); + owner.Variable = SemaRef.getCurMethodDecl()->getSelfDecl(); + owner.Loc = msg->getSuperLoc(); + owner.Range = msg->getSuperLoc(); + } + + // Check whether the receiver is captured by any of the arguments. + const ObjCMethodDecl *MD = msg->getMethodDecl(); + for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i) { + if (Expr *capturer = findCapturingExpr(SemaRef, msg->getArg(i), owner)) { + // noescape blocks should not be retained by the method. + if (MD && MD->parameters()[i]->hasAttr()) + continue; + return diagnoseRetainCycle(SemaRef, capturer, owner); + } + } +} + +/// Check a property assign to see if it's likely to cause a retain cycle. +void SemaObjC::checkRetainCycles(Expr *receiver, Expr *argument) { + RetainCycleOwner owner; + if (!findRetainCycleOwner(SemaRef, receiver, owner)) + return; + + if (Expr *capturer = findCapturingExpr(SemaRef, argument, owner)) + diagnoseRetainCycle(SemaRef, capturer, owner); +} + +void SemaObjC::checkRetainCycles(VarDecl *Var, Expr *Init) { + RetainCycleOwner Owner; + if (!considerVariable(Var, /*DeclRefExpr=*/nullptr, Owner)) + return; + + // Because we don't have an expression for the variable, we have to set the + // location explicitly here. + Owner.Loc = Var->getLocation(); + Owner.Range = Var->getSourceRange(); + + if (Expr *Capturer = findCapturingExpr(SemaRef, Init, Owner)) + diagnoseRetainCycle(SemaRef, Capturer, Owner); +} + +/// CheckObjCString - Checks that the argument to the builtin +/// CFString constructor is correct +/// Note: It might also make sense to do the UTF-16 conversion here (would +/// simplify the backend). +bool SemaObjC::CheckObjCString(Expr *Arg) { + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Literal = dyn_cast(Arg); + + if (!Literal || !Literal->isOrdinary()) { + Diag(Arg->getBeginLoc(), diag::err_cfstring_literal_not_string_constant) + << Arg->getSourceRange(); + return true; + } + + if (Literal->containsNonAsciiOrNull()) { + StringRef String = Literal->getString(); + unsigned NumBytes = String.size(); + SmallVector ToBuf(NumBytes); + const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data(); + llvm::UTF16 *ToPtr = &ToBuf[0]; + + llvm::ConversionResult Result = + llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr, + ToPtr + NumBytes, llvm::strictConversion); + // Check for conversion failure. + if (Result != llvm::conversionOK) + Diag(Arg->getBeginLoc(), diag::warn_cfstring_truncated) + << Arg->getSourceRange(); + } + return false; +} + +bool SemaObjC::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, + ArrayRef Args) { + Sema::VariadicCallType CallType = + Method->isVariadic() ? Sema::VariadicMethod : Sema::VariadicDoesNotApply; + + SemaRef.checkCall(Method, nullptr, /*ThisArg=*/nullptr, Args, + /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(), + CallType); + + SemaRef.CheckTCBEnforcement(lbrac, Method); + + return false; +} + +const DeclContext *SemaObjC::getCurObjCLexicalContext() const { + const DeclContext *DC = SemaRef.getCurLexicalContext(); + // A category implicitly has the attribute of the interface. + if (const ObjCCategoryDecl *CatD = dyn_cast(DC)) + DC = CatD->getClassInterface(); + return DC; +} + +/// Retrieve the identifier "NSError". +IdentifierInfo *SemaObjC::getNSErrorIdent() { + if (!Ident_NSError) + Ident_NSError = SemaRef.PP.getIdentifierInfo("NSError"); + + return Ident_NSError; +} + +void SemaObjC::ActOnObjCContainerStartDefinition(ObjCContainerDecl *IDecl) { + assert( + IDecl->getLexicalParent() == SemaRef.CurContext && + "The next DeclContext should be lexically contained in the current one."); + SemaRef.CurContext = IDecl; +} + +void SemaObjC::ActOnObjCContainerFinishDefinition() { + // Exit this scope of this interface definition. + SemaRef.PopDeclContext(); +} + +void SemaObjC::ActOnObjCTemporaryExitContainerContext( + ObjCContainerDecl *ObjCCtx) { + assert(ObjCCtx == SemaRef.CurContext && "Mismatch of container contexts"); + SemaRef.OriginalLexicalContext = ObjCCtx; + ActOnObjCContainerFinishDefinition(); +} + +void SemaObjC::ActOnObjCReenterContainerContext(ObjCContainerDecl *ObjCCtx) { + ActOnObjCContainerStartDefinition(ObjCCtx); + SemaRef.OriginalLexicalContext = nullptr; +} + +/// Find the protocol with the given name, if any. +ObjCProtocolDecl *SemaObjC::LookupProtocol(IdentifierInfo *II, + SourceLocation IdLoc, + RedeclarationKind Redecl) { + Decl *D = SemaRef.LookupSingleName(SemaRef.TUScope, II, IdLoc, + Sema::LookupObjCProtocolName, Redecl); + return cast_or_null(D); +} + +/// Determine whether this is an Objective-C writeback conversion, +/// used for parameter passing when performing automatic reference counting. +/// +/// \param FromType The type we're converting form. +/// +/// \param ToType The type we're converting to. +/// +/// \param ConvertedType The type that will be produced after applying +/// this conversion. +bool SemaObjC::isObjCWritebackConversion(QualType FromType, QualType ToType, + QualType &ConvertedType) { + ASTContext &Context = getASTContext(); + if (!getLangOpts().ObjCAutoRefCount || + Context.hasSameUnqualifiedType(FromType, ToType)) + return false; + + // Parameter must be a pointer to __autoreleasing (with no other qualifiers). + QualType ToPointee; + if (const PointerType *ToPointer = ToType->getAs()) + ToPointee = ToPointer->getPointeeType(); + else + return false; + + Qualifiers ToQuals = ToPointee.getQualifiers(); + if (!ToPointee->isObjCLifetimeType() || + ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing || + !ToQuals.withoutObjCLifetime().empty()) + return false; + + // Argument must be a pointer to __strong to __weak. + QualType FromPointee; + if (const PointerType *FromPointer = FromType->getAs()) + FromPointee = FromPointer->getPointeeType(); + else + return false; + + Qualifiers FromQuals = FromPointee.getQualifiers(); + if (!FromPointee->isObjCLifetimeType() || + (FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong && + FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak)) + return false; + + // Make sure that we have compatible qualifiers. + FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing); + if (!ToQuals.compatiblyIncludes(FromQuals)) + return false; + + // Remove qualifiers from the pointee type we're converting from; they + // aren't used in the compatibility check belong, and we'll be adding back + // qualifiers (with __autoreleasing) if the compatibility check succeeds. + FromPointee = FromPointee.getUnqualifiedType(); + + // The unqualified form of the pointee types must be compatible. + ToPointee = ToPointee.getUnqualifiedType(); + bool IncompatibleObjC; + if (Context.typesAreCompatible(FromPointee, ToPointee)) + FromPointee = ToPointee; + else if (!SemaRef.isObjCPointerConversion(FromPointee, ToPointee, FromPointee, + IncompatibleObjC)) + return false; + + /// Construct the type we're converting to, which is a pointer to + /// __autoreleasing pointee. + FromPointee = Context.getQualifiedType(FromPointee, FromQuals); + ConvertedType = Context.getPointerType(FromPointee); + return true; +} + +/// CheckSubscriptingKind - This routine decide what type +/// of indexing represented by "FromE" is being done. +SemaObjC::ObjCSubscriptKind SemaObjC::CheckSubscriptingKind(Expr *FromE) { + // If the expression already has integral or enumeration type, we're golden. + QualType T = FromE->getType(); + if (T->isIntegralOrEnumerationType()) + return SemaObjC::OS_Array; + + // If we don't have a class type in C++, there's no way we can get an + // expression of integral or enumeration type. + const RecordType *RecordTy = T->getAs(); + if (!RecordTy && (T->isObjCObjectPointerType() || T->isVoidPointerType())) + // All other scalar cases are assumed to be dictionary indexing which + // caller handles, with diagnostics if needed. + return SemaObjC::OS_Dictionary; + if (!getLangOpts().CPlusPlus || !RecordTy || RecordTy->isIncompleteType()) { + // No indexing can be done. Issue diagnostics and quit. + const Expr *IndexExpr = FromE->IgnoreParenImpCasts(); + if (isa(IndexExpr)) + Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer) + << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@"); + else + Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) << T; + return SemaObjC::OS_Error; + } + + // We must have a complete class type. + if (SemaRef.RequireCompleteType(FromE->getExprLoc(), T, + diag::err_objc_index_incomplete_class_type, + FromE)) + return SemaObjC::OS_Error; + + // Look for a conversion to an integral, enumeration type, or + // objective-C pointer type. + int NoIntegrals = 0, NoObjCIdPointers = 0; + SmallVector ConversionDecls; + + for (NamedDecl *D : cast(RecordTy->getDecl()) + ->getVisibleConversionFunctions()) { + if (CXXConversionDecl *Conversion = + dyn_cast(D->getUnderlyingDecl())) { + QualType CT = Conversion->getConversionType().getNonReferenceType(); + if (CT->isIntegralOrEnumerationType()) { + ++NoIntegrals; + ConversionDecls.push_back(Conversion); + } else if (CT->isObjCIdType() || CT->isBlockPointerType()) { + ++NoObjCIdPointers; + ConversionDecls.push_back(Conversion); + } + } + } + if (NoIntegrals == 1 && NoObjCIdPointers == 0) + return SemaObjC::OS_Array; + if (NoIntegrals == 0 && NoObjCIdPointers == 1) + return SemaObjC::OS_Dictionary; + if (NoIntegrals == 0 && NoObjCIdPointers == 0) { + // No conversion function was found. Issue diagnostic and return. + Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) + << FromE->getType(); + return SemaObjC::OS_Error; + } + Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion) + << FromE->getType(); + for (unsigned int i = 0; i < ConversionDecls.size(); i++) + Diag(ConversionDecls[i]->getLocation(), + diag::note_conv_function_declared_at); + + return SemaObjC::OS_Error; +} + +void SemaObjC::AddCFAuditedAttribute(Decl *D) { + ASTContext &Context = getASTContext(); + IdentifierInfo *Ident; + SourceLocation Loc; + std::tie(Ident, Loc) = SemaRef.PP.getPragmaARCCFCodeAuditedInfo(); + if (!Loc.isValid()) + return; + + // Don't add a redundant or conflicting attribute. + if (D->hasAttr() || + D->hasAttr()) + return; + + AttributeCommonInfo Info(Ident, SourceRange(Loc), + AttributeCommonInfo::Form::Pragma()); + D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Info)); +} + +bool SemaObjC::isCFError(RecordDecl *RD) { + // If we already know about CFError, test it directly. + if (CFError) + return CFError == RD; + + // Check whether this is CFError, which we identify based on its bridge to + // NSError. CFErrorRef used to be declared with "objc_bridge" but is now + // declared with "objc_bridge_mutable", so look for either one of the two + // attributes. + if (RD->getTagKind() == TagTypeKind::Struct) { + IdentifierInfo *bridgedType = nullptr; + if (auto bridgeAttr = RD->getAttr()) + bridgedType = bridgeAttr->getBridgedType(); + else if (auto bridgeAttr = RD->getAttr()) + bridgedType = bridgeAttr->getBridgedType(); + + if (bridgedType == getNSErrorIdent()) { + CFError = RD; + return true; + } + } + + return false; +} + +} // namespace clang diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 222a65a13dd0..031f2a6af877 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" @@ -20,6 +19,8 @@ #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallString.h" @@ -114,7 +115,8 @@ CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop, // Look for a property with the same name. if (ObjCPropertyDecl *ProtoProp = Proto->getProperty( Prop->getIdentifier(), Prop->isInstanceProperty())) { - S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true); + S.ObjC().DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), + true); return; } @@ -169,28 +171,26 @@ static unsigned getOwnershipRule(unsigned attr) { return result; } -Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, - SourceLocation LParenLoc, - FieldDeclarator &FD, - ObjCDeclSpec &ODS, - Selector GetterSel, - Selector SetterSel, - tok::ObjCKeywordKind MethodImplKind, - DeclContext *lexicalDC) { +Decl *SemaObjC::ActOnProperty(Scope *S, SourceLocation AtLoc, + SourceLocation LParenLoc, FieldDeclarator &FD, + ObjCDeclSpec &ODS, Selector GetterSel, + Selector SetterSel, + tok::ObjCKeywordKind MethodImplKind, + DeclContext *lexicalDC) { unsigned Attributes = ODS.getPropertyAttributes(); FD.D.setObjCWeakProperty((Attributes & ObjCPropertyAttribute::kind_weak) != 0); - TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D); + TypeSourceInfo *TSI = SemaRef.GetTypeForDeclarator(FD.D); QualType T = TSI->getType(); if (!getOwnershipRule(Attributes)) { - Attributes |= deducePropertyOwnershipFromType(*this, T); + Attributes |= deducePropertyOwnershipFromType(SemaRef, T); } bool isReadWrite = ((Attributes & ObjCPropertyAttribute::kind_readwrite) || // default is readwrite! !(Attributes & ObjCPropertyAttribute::kind_readonly)); // Proceed with constructing the ObjCPropertyDecls. - ObjCContainerDecl *ClassDecl = cast(CurContext); + ObjCContainerDecl *ClassDecl = cast(SemaRef.CurContext); ObjCPropertyDecl *Res = nullptr; if (ObjCCategoryDecl *CDecl = dyn_cast(ClassDecl)) { if (CDecl->IsClassExtension()) { @@ -223,7 +223,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, // Check consistency if the type has explicit ownership qualification. if (Res->getType().getObjCLifetime()) - checkPropertyDeclWithOwnership(*this, Res); + checkPropertyDeclWithOwnership(SemaRef, Res); llvm::SmallPtrSet KnownProtos; if (ObjCInterfaceDecl *IFace = dyn_cast(ClassDecl)) { @@ -243,12 +243,12 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, if (FoundInSuper) { // Also compare the property against a property in our protocols. for (auto *P : CurrentInterfaceDecl->protocols()) { - CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); + CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos); } } else { // Slower path: look in all protocols we referenced. for (auto *P : IFace->all_referenced_protocols()) { - CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); + CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos); } } } else if (ObjCCategoryDecl *Cat = dyn_cast(ClassDecl)) { @@ -257,14 +257,14 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, // when property in class extension is constructed. if (!Cat->IsClassExtension()) for (auto *P : Cat->protocols()) - CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); + CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos); } else { ObjCProtocolDecl *Proto = cast(ClassDecl); for (auto *P : Proto->protocols()) - CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); + CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos); } - ActOnDocumentableDecl(Res); + SemaRef.ActOnDocumentableDecl(Res); return Res; } @@ -401,24 +401,15 @@ static void checkAtomicPropertyMismatch(Sema &S, S.Diag(OldProperty->getLocation(), diag::note_property_declare); } -ObjCPropertyDecl * -Sema::HandlePropertyInClassExtension(Scope *S, - SourceLocation AtLoc, - SourceLocation LParenLoc, - FieldDeclarator &FD, - Selector GetterSel, - SourceLocation GetterNameLoc, - Selector SetterSel, - SourceLocation SetterNameLoc, - const bool isReadWrite, - unsigned &Attributes, - const unsigned AttributesAsWritten, - QualType T, - TypeSourceInfo *TSI, - tok::ObjCKeywordKind MethodImplKind) { - ObjCCategoryDecl *CDecl = cast(CurContext); +ObjCPropertyDecl *SemaObjC::HandlePropertyInClassExtension( + Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, + FieldDeclarator &FD, Selector GetterSel, SourceLocation GetterNameLoc, + Selector SetterSel, SourceLocation SetterNameLoc, const bool isReadWrite, + unsigned &Attributes, const unsigned AttributesAsWritten, QualType T, + TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind) { + ObjCCategoryDecl *CDecl = cast(SemaRef.CurContext); // Diagnose if this property is already in continuation class. - DeclContext *DC = CurContext; + DeclContext *DC = SemaRef.CurContext; const IdentifierInfo *PropertyId = FD.D.getIdentifier(); ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); @@ -515,7 +506,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, isReadWrite, Attributes, AttributesAsWritten, T, TSI, MethodImplKind, DC); - + ASTContext &Context = getASTContext(); // If there was no declaration of a property with the same name in // the primary class, we're done. if (!PIDecl) { @@ -536,9 +527,10 @@ Sema::HandlePropertyInClassExtension(Scope *S, QualType ClassExtPropertyT = Context.getCanonicalType(PDecl->getType()); if (!isa(PrimaryClassPropertyT) || !isa(ClassExtPropertyT) || - (!isObjCPointerConversion(ClassExtPropertyT, PrimaryClassPropertyT, - ConvertedType, IncompatibleObjC)) - || IncompatibleObjC) { + (!SemaRef.isObjCPointerConversion(ClassExtPropertyT, + PrimaryClassPropertyT, ConvertedType, + IncompatibleObjC)) || + IncompatibleObjC) { Diag(AtLoc, diag::err_type_mismatch_continuation_class) << PDecl->getType(); Diag(PIDecl->getLocation(), diag::note_property_declare); @@ -548,29 +540,22 @@ Sema::HandlePropertyInClassExtension(Scope *S, // Check that atomicity of property in class extension matches the previous // declaration. - checkAtomicPropertyMismatch(*this, PIDecl, PDecl, true); + checkAtomicPropertyMismatch(SemaRef, PIDecl, PDecl, true); // Make sure getter/setter are appropriately synthesized. ProcessPropertyDecl(PDecl); return PDecl; } -ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, - ObjCContainerDecl *CDecl, - SourceLocation AtLoc, - SourceLocation LParenLoc, - FieldDeclarator &FD, - Selector GetterSel, - SourceLocation GetterNameLoc, - Selector SetterSel, - SourceLocation SetterNameLoc, - const bool isReadWrite, - const unsigned Attributes, - const unsigned AttributesAsWritten, - QualType T, - TypeSourceInfo *TInfo, - tok::ObjCKeywordKind MethodImplKind, - DeclContext *lexicalDC){ +ObjCPropertyDecl *SemaObjC::CreatePropertyDecl( + Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc, + SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel, + SourceLocation GetterNameLoc, Selector SetterSel, + SourceLocation SetterNameLoc, const bool isReadWrite, + const unsigned Attributes, const unsigned AttributesAsWritten, QualType T, + TypeSourceInfo *TInfo, tok::ObjCKeywordKind MethodImplKind, + DeclContext *lexicalDC) { + ASTContext &Context = getASTContext(); const IdentifierInfo *PropertyId = FD.D.getIdentifier(); // Property defaults to 'assign' if it is readwrite, unless this is ARC @@ -603,7 +588,7 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, if (T->isObjCObjectType()) { SourceLocation StarLoc = TInfo->getTypeLoc().getEndLoc(); - StarLoc = getLocForEndOfToken(StarLoc); + StarLoc = SemaRef.getLocForEndOfToken(StarLoc); Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object) << FixItHint::CreateInsertion(StarLoc, "*"); T = Context.getObjCObjectPointerType(T); @@ -645,7 +630,7 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, PDecl->setPropertyAttributesAsWritten( makePropertyAttributesAsWritten(AttributesAsWritten)); - ProcessDeclAttributes(S, PDecl, FD.D); + SemaRef.ProcessDeclAttributes(S, PDecl, FD.D); if (Attributes & ObjCPropertyAttribute::kind_readonly) PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly); @@ -1074,16 +1059,13 @@ RedeclarePropertyAccessor(ASTContext &Context, ObjCImplementationDecl *Impl, /// builds the AST node for a property implementation declaration; declared /// as \@synthesize or \@dynamic. /// -Decl *Sema::ActOnPropertyImplDecl(Scope *S, - SourceLocation AtLoc, - SourceLocation PropertyLoc, - bool Synthesize, - IdentifierInfo *PropertyId, - IdentifierInfo *PropertyIvar, - SourceLocation PropertyIvarLoc, - ObjCPropertyQueryKind QueryKind) { +Decl *SemaObjC::ActOnPropertyImplDecl( + Scope *S, SourceLocation AtLoc, SourceLocation PropertyLoc, bool Synthesize, + IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar, + SourceLocation PropertyIvarLoc, ObjCPropertyQueryKind QueryKind) { + ASTContext &Context = getASTContext(); ObjCContainerDecl *ClassImpDecl = - dyn_cast(CurContext); + dyn_cast(SemaRef.CurContext); // Make sure we have a context for the property implementation declaration. if (!ClassImpDecl) { Diag(AtLoc, diag::err_missing_property_context); @@ -1167,7 +1149,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } } if (Synthesize && isa(property->getDeclContext())) - property = SelectPropertyForSynthesisFromProtocols(*this, AtLoc, IDecl, + property = SelectPropertyForSynthesisFromProtocols(SemaRef, AtLoc, IDecl, property); } else if ((CatImplClass = dyn_cast(ClassImpDecl))) { @@ -1212,9 +1194,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, QualType PropType = property->getType(); QualType PropertyIvarType = PropType.getNonReferenceType(); - if (RequireCompleteType(PropertyDiagLoc, PropertyIvarType, - diag::err_incomplete_synthesized_property, - property->getDeclName())) { + if (SemaRef.RequireCompleteType(PropertyDiagLoc, PropertyIvarType, + diag::err_incomplete_synthesized_property, + property->getDeclName())) { Diag(property->getLocation(), diag::note_property_declare); CompleteTypeErr = true; } @@ -1320,10 +1302,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, PropertyIvarType, /*TInfo=*/nullptr, ObjCIvarDecl::Private, (Expr *)nullptr, true); - if (RequireNonAbstractType(PropertyIvarLoc, - PropertyIvarType, - diag::err_abstract_type_in_decl, - AbstractSynthesizedIvarType)) { + if (SemaRef.RequireNonAbstractType(PropertyIvarLoc, PropertyIvarType, + diag::err_abstract_type_in_decl, + Sema::AbstractSynthesizedIvarType)) { Diag(property->getLocation(), diag::note_property_declare); // An abstract type is as bad as an incomplete type. CompleteTypeErr = true; @@ -1367,9 +1348,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, PropertyIvarType->castAs(), IvarType->castAs()); else { - compat = (CheckAssignmentConstraints(PropertyIvarLoc, PropertyIvarType, - IvarType) - == Compatible); + compat = (SemaRef.CheckAssignmentConstraints( + PropertyIvarLoc, PropertyIvarType, IvarType) == + Sema::Compatible); } if (!compat) { Diag(PropertyDiagLoc, diag::err_property_ivar_type) @@ -1413,19 +1394,17 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } if (getLangOpts().ObjCAutoRefCount || isARCWeak || Ivar->getType().getObjCLifetime()) - checkARCPropertyImpl(*this, PropertyLoc, property, Ivar); + checkARCPropertyImpl(SemaRef, PropertyLoc, property, Ivar); } else if (PropertyIvar) // @dynamic Diag(PropertyDiagLoc, diag::err_dynamic_property_ivar_decl); assert (property && "ActOnPropertyImplDecl - property declaration missing"); - ObjCPropertyImplDecl *PIDecl = - ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc, - property, - (Synthesize ? - ObjCPropertyImplDecl::Synthesize - : ObjCPropertyImplDecl::Dynamic), - Ivar, PropertyIvarLoc); + ObjCPropertyImplDecl *PIDecl = ObjCPropertyImplDecl::Create( + Context, SemaRef.CurContext, AtLoc, PropertyLoc, property, + (Synthesize ? ObjCPropertyImplDecl::Synthesize + : ObjCPropertyImplDecl::Dynamic), + Ivar, PropertyIvarLoc); if (CompleteTypeErr || !compat) PIDecl->setInvalidDecl(); @@ -1449,12 +1428,12 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // For Objective-C++, need to synthesize the AST for the IVAR object to be // returned by the getter as it must conform to C++'s copy-return rules. // FIXME. Eventually we want to do this for Objective-C as well. - SynthesizedFunctionScope Scope(*this, getterMethod); + Sema::SynthesizedFunctionScope Scope(SemaRef, getterMethod); ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); DeclRefExpr *SelfExpr = new (Context) DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue, PropertyDiagLoc); - MarkDeclRefReferenced(SelfExpr); + SemaRef.MarkDeclRefReferenced(SelfExpr); Expr *LoadSelfExpr = ImplicitCastExpr::Create( Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr, VK_PRValue, FPOptionsOverride()); @@ -1464,14 +1443,14 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, PropertyDiagLoc, Ivar->getLocation(), LoadSelfExpr, true, true); - ExprResult Res = PerformCopyInitialization( + ExprResult Res = SemaRef.PerformCopyInitialization( InitializedEntity::InitializeResult(PropertyDiagLoc, getterMethod->getReturnType()), PropertyDiagLoc, IvarRefExpr); if (!Res.isInvalid()) { Expr *ResExpr = Res.getAs(); if (ResExpr) - ResExpr = MaybeCreateExprWithCleanups(ResExpr); + ResExpr = SemaRef.MaybeCreateExprWithCleanups(ResExpr); PIDecl->setGetterCXXConstructor(ResExpr); } } @@ -1511,12 +1490,12 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && Ivar->getType()->isRecordType()) { // FIXME. Eventually we want to do this for Objective-C as well. - SynthesizedFunctionScope Scope(*this, setterMethod); + Sema::SynthesizedFunctionScope Scope(SemaRef, setterMethod); ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); DeclRefExpr *SelfExpr = new (Context) DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue, PropertyDiagLoc); - MarkDeclRefReferenced(SelfExpr); + SemaRef.MarkDeclRefReferenced(SelfExpr); Expr *LoadSelfExpr = ImplicitCastExpr::Create( Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr, VK_PRValue, FPOptionsOverride()); @@ -1531,9 +1510,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, QualType T = Param->getType().getNonReferenceType(); DeclRefExpr *rhs = new (Context) DeclRefExpr(Context, Param, false, T, VK_LValue, PropertyDiagLoc); - MarkDeclRefReferenced(rhs); - ExprResult Res = BuildBinOp(S, PropertyDiagLoc, - BO_Assign, lhs, rhs); + SemaRef.MarkDeclRefReferenced(rhs); + ExprResult Res = + SemaRef.BuildBinOp(S, PropertyDiagLoc, BO_Assign, lhs, rhs); if (property->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic) { Expr *callExpr = Res.getAs(); @@ -1630,11 +1609,11 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, /// DiagnosePropertyMismatch - Compares two properties for their /// attributes and types and warns on a variety of inconsistencies. /// -void -Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, - ObjCPropertyDecl *SuperProperty, - const IdentifierInfo *inheritedName, - bool OverridingProtocolProperty) { +void SemaObjC::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, + ObjCPropertyDecl *SuperProperty, + const IdentifierInfo *inheritedName, + bool OverridingProtocolProperty) { + ASTContext &Context = getASTContext(); ObjCPropertyAttribute::Kind CAttr = Property->getPropertyAttributes(); ObjCPropertyAttribute::Kind SAttr = SuperProperty->getPropertyAttributes(); @@ -1669,7 +1648,7 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, // Check for nonatomic; note that nonatomic is effectively // meaningless for readonly properties, so don't diagnose if the // atomic property is 'readonly'. - checkAtomicPropertyMismatch(*this, SuperProperty, Property, false); + checkAtomicPropertyMismatch(SemaRef, SuperProperty, Property, false); // Readonly properties from protocols can be implemented as "readwrite" // with a custom setter name. if (Property->getSetterName() != SuperProperty->getSetterName() && @@ -1695,19 +1674,20 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, // FIXME. For future support of covariant property types, revisit this. bool IncompatibleObjC = false; QualType ConvertedType; - if (!isObjCPointerConversion(RHSType, LHSType, - ConvertedType, IncompatibleObjC) || + if (!SemaRef.isObjCPointerConversion(RHSType, LHSType, ConvertedType, + IncompatibleObjC) || IncompatibleObjC) { - Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) - << Property->getType() << SuperProperty->getType() << inheritedName; + Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) + << Property->getType() << SuperProperty->getType() << inheritedName; Diag(SuperProperty->getLocation(), diag::note_property_declare); } } } -bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, - ObjCMethodDecl *GetterMethod, - SourceLocation Loc) { +bool SemaObjC::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, + ObjCMethodDecl *GetterMethod, + SourceLocation Loc) { + ASTContext &Context = getASTContext(); if (!GetterMethod) return false; QualType GetterType = GetterMethod->getReturnType().getNonReferenceType(); @@ -1721,13 +1701,13 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, PropertyRValueType->getAs()) && (getterObjCPtr = GetterType->getAs())) compat = Context.canAssignObjCInterfaces(getterObjCPtr, propertyObjCPtr); - else if (CheckAssignmentConstraints(Loc, GetterType, PropertyRValueType) - != Compatible) { - Diag(Loc, diag::err_property_accessor_type) - << property->getDeclName() << PropertyRValueType - << GetterMethod->getSelector() << GetterType; - Diag(GetterMethod->getLocation(), diag::note_declared_at); - return true; + else if (SemaRef.CheckAssignmentConstraints( + Loc, GetterType, PropertyRValueType) != Sema::Compatible) { + Diag(Loc, diag::err_property_accessor_type) + << property->getDeclName() << PropertyRValueType + << GetterMethod->getSelector() << GetterType; + Diag(GetterMethod->getLocation(), diag::note_declared_at); + return true; } else { compat = true; QualType lhsType = Context.getCanonicalType(PropertyRValueType); @@ -1831,9 +1811,9 @@ static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is /// an ivar synthesized for 'Method' and 'Method' is a property accessor /// declared in class 'IFace'. -bool -Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, - ObjCMethodDecl *Method, ObjCIvarDecl *IV) { +bool SemaObjC::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, + ObjCMethodDecl *Method, + ObjCIvarDecl *IV) { if (!IV->getSynthesize()) return false; ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(), @@ -1883,9 +1863,10 @@ static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl, /// Default synthesizes all properties which must be synthesized /// in class's \@implementation. -void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl, - ObjCInterfaceDecl *IDecl, - SourceLocation AtEnd) { +void SemaObjC::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl, + ObjCInterfaceDecl *IDecl, + SourceLocation AtEnd) { + ASTContext &Context = getASTContext(); ObjCInterfaceDecl::PropertyMap PropMap; IDecl->collectPropertiesToImplement(PropMap); if (PropMap.empty()) @@ -1977,9 +1958,10 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl, } } -void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D, - SourceLocation AtEnd) { - if (!LangOpts.ObjCDefaultSynthProperties || LangOpts.ObjCRuntime.isFragile()) +void SemaObjC::DefaultSynthesizeProperties(Scope *S, Decl *D, + SourceLocation AtEnd) { + if (!getLangOpts().ObjCDefaultSynthProperties || + getLangOpts().ObjCRuntime.isFragile()) return; ObjCImplementationDecl *IC=dyn_cast_or_null(D); if (!IC) @@ -2026,9 +2008,9 @@ static void DiagnoseUnimplementedAccessor( } } -void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, - ObjCContainerDecl *CDecl, - bool SynthesizeProperties) { +void SemaObjC::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl *IMPDecl, + ObjCContainerDecl *CDecl, + bool SynthesizeProperties) { ObjCContainerDecl::PropertyMap PropMap; ObjCInterfaceDecl *IDecl = dyn_cast(CDecl); @@ -2124,16 +2106,17 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, continue; // Diagnose unimplemented getters and setters. - DiagnoseUnimplementedAccessor(*this, - PrimaryClass, Prop->getGetterName(), IMPDecl, CDecl, C, Prop, InsMap); + DiagnoseUnimplementedAccessor(SemaRef, PrimaryClass, Prop->getGetterName(), + IMPDecl, CDecl, C, Prop, InsMap); if (!Prop->isReadOnly()) - DiagnoseUnimplementedAccessor(*this, - PrimaryClass, Prop->getSetterName(), - IMPDecl, CDecl, C, Prop, InsMap); + DiagnoseUnimplementedAccessor(SemaRef, PrimaryClass, + Prop->getSetterName(), IMPDecl, CDecl, C, + Prop, InsMap); } } -void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) { +void SemaObjC::diagnoseNullResettableSynthesizedSetters( + const ObjCImplDecl *impDecl) { for (const auto *propertyImpl : impDecl->property_impls()) { const auto *property = propertyImpl->getPropertyDecl(); // Warn about null_resettable properties with synthesized setters, @@ -2158,9 +2141,8 @@ void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) } } -void -Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, - ObjCInterfaceDecl* IDecl) { +void SemaObjC::AtomicPropertySetterGetterRules(ObjCImplDecl *IMPDecl, + ObjCInterfaceDecl *IDecl) { // Rules apply in non-GC mode only if (getLangOpts().getGC() != LangOptions::NonGC) return; @@ -2232,7 +2214,7 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, !(AttributesAsWritten & ObjCPropertyAttribute::kind_atomic)) { // @property () ... case. SourceLocation AfterLParen = - getLocForEndOfToken(Property->getLParenLoc()); + SemaRef.getLocForEndOfToken(Property->getLParenLoc()); StringRef NonatomicStr = AttributesAsWritten? "nonatomic, " : "nonatomic"; Diag(Property->getLocation(), @@ -2253,7 +2235,8 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, } } -void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) { +void SemaObjC::DiagnoseOwningPropertyGetterSynthesis( + const ObjCImplementationDecl *D) { if (getLangOpts().getGC() == LangOptions::GCOnly) return; @@ -2288,7 +2271,7 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D fixItLoc = getterRedecl->getEndLoc(); } - Preprocessor &PP = getPreprocessor(); + Preprocessor &PP = SemaRef.getPreprocessor(); TokenValue tokens[] = { tok::kw___attribute, tok::l_paren, tok::l_paren, PP.getIdentifierInfo("objc_method_family"), tok::l_paren, @@ -2312,9 +2295,8 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D } } -void Sema::DiagnoseMissingDesignatedInitOverrides( - const ObjCImplementationDecl *ImplD, - const ObjCInterfaceDecl *IFD) { +void SemaObjC::DiagnoseMissingDesignatedInitOverrides( + const ObjCImplementationDecl *ImplD, const ObjCInterfaceDecl *IFD) { assert(IFD->hasDesignatedInitializers()); const ObjCInterfaceDecl *SuperD = IFD->getSuperClass(); if (!SuperD) @@ -2371,7 +2353,8 @@ static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, /// have the property type and issue diagnostics if they don't. /// Also synthesize a getter/setter method if none exist (and update the /// appropriate lookup tables. -void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { +void SemaObjC::ProcessPropertyDecl(ObjCPropertyDecl *property) { + ASTContext &Context = getASTContext(); ObjCMethodDecl *GetterMethod, *SetterMethod; ObjCContainerDecl *CD = cast(property->getDeclContext()); if (CD->isInvalidDecl()) @@ -2492,7 +2475,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { : ObjCImplementationControl::Required); CD->addDecl(GetterMethod); - AddPropertyAttrs(*this, GetterMethod, property); + AddPropertyAttrs(SemaRef, GetterMethod, property); if (property->isDirectProperty()) GetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc)); @@ -2509,7 +2492,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { GetterMethod->addAttr(SectionAttr::CreateImplicit( Context, SA->getName(), Loc, SectionAttr::GNU_section)); - ProcessAPINotes(GetterMethod); + SemaRef.ProcessAPINotes(GetterMethod); if (getLangOpts().ObjCAutoRefCount) CheckARCMethodDecl(GetterMethod); @@ -2571,7 +2554,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { nullptr); SetterMethod->setMethodParams(Context, Argument, std::nullopt); - AddPropertyAttrs(*this, SetterMethod, property); + AddPropertyAttrs(SemaRef, SetterMethod, property); if (property->isDirectProperty()) SetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc)); @@ -2581,7 +2564,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { SetterMethod->addAttr(SectionAttr::CreateImplicit( Context, SA->getName(), Loc, SectionAttr::GNU_section)); - ProcessAPINotes(SetterMethod); + SemaRef.ProcessAPINotes(SetterMethod); // It's possible for the user to have set a very odd custom // setter selector that causes it to have a method family. @@ -2628,15 +2611,14 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { CurrentClass = Impl->getClassInterface(); } if (GetterMethod) - CheckObjCMethodOverrides(GetterMethod, CurrentClass, Sema::RTC_Unknown); + CheckObjCMethodOverrides(GetterMethod, CurrentClass, SemaObjC::RTC_Unknown); if (SetterMethod) - CheckObjCMethodOverrides(SetterMethod, CurrentClass, Sema::RTC_Unknown); + CheckObjCMethodOverrides(SetterMethod, CurrentClass, SemaObjC::RTC_Unknown); } -void Sema::CheckObjCPropertyAttributes(Decl *PDecl, - SourceLocation Loc, - unsigned &Attributes, - bool propertyInPrimaryClass) { +void SemaObjC::CheckObjCPropertyAttributes(Decl *PDecl, SourceLocation Loc, + unsigned &Attributes, + bool propertyInPrimaryClass) { // FIXME: Improve the reported location. if (!PDecl || PDecl->isInvalidDecl()) return; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f173300b5c96..2eb25237a0de 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -33,6 +33,7 @@ #include "clang/Sema/Overload.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/DenseSet.h" @@ -1086,7 +1087,7 @@ namespace { assert(E->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); Entry entry = { &E, E }; Entries.push_back(entry); - E = S.stripARCUnbridgedCast(E); + E = S.ObjC().stripARCUnbridgedCast(E); } void restore() { @@ -1778,8 +1779,8 @@ ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType, = getLangOpts().ObjCAutoRefCount && (Action == AA_Passing || Action == AA_Sending); if (getLangOpts().ObjC) - CheckObjCBridgeRelatedConversions(From->getBeginLoc(), ToType, - From->getType(), From); + ObjC().CheckObjCBridgeRelatedConversions(From->getBeginLoc(), ToType, + From->getType(), From); ImplicitConversionSequence ICS = ::TryImplicitConversion( *this, From, ToType, /*SuppressUserConversions=*/false, @@ -2272,7 +2273,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, } else if (S.IsBlockPointerConversion(FromType, ToType, FromType)) { SCS.Second = ICK_Block_Pointer_Conversion; } else if (AllowObjCWritebackConversion && - S.isObjCWritebackConversion(FromType, ToType, FromType)) { + S.ObjC().isObjCWritebackConversion(FromType, ToType, FromType)) { SCS.Second = ICK_Writeback_Conversion; } else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution, FromType, IncompatibleObjC)) { @@ -3060,73 +3061,6 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, return false; } -/// Determine whether this is an Objective-C writeback conversion, -/// used for parameter passing when performing automatic reference counting. -/// -/// \param FromType The type we're converting form. -/// -/// \param ToType The type we're converting to. -/// -/// \param ConvertedType The type that will be produced after applying -/// this conversion. -bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType, - QualType &ConvertedType) { - if (!getLangOpts().ObjCAutoRefCount || - Context.hasSameUnqualifiedType(FromType, ToType)) - return false; - - // Parameter must be a pointer to __autoreleasing (with no other qualifiers). - QualType ToPointee; - if (const PointerType *ToPointer = ToType->getAs()) - ToPointee = ToPointer->getPointeeType(); - else - return false; - - Qualifiers ToQuals = ToPointee.getQualifiers(); - if (!ToPointee->isObjCLifetimeType() || - ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing || - !ToQuals.withoutObjCLifetime().empty()) - return false; - - // Argument must be a pointer to __strong to __weak. - QualType FromPointee; - if (const PointerType *FromPointer = FromType->getAs()) - FromPointee = FromPointer->getPointeeType(); - else - return false; - - Qualifiers FromQuals = FromPointee.getQualifiers(); - if (!FromPointee->isObjCLifetimeType() || - (FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong && - FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak)) - return false; - - // Make sure that we have compatible qualifiers. - FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing); - if (!ToQuals.compatiblyIncludes(FromQuals)) - return false; - - // Remove qualifiers from the pointee type we're converting from; they - // aren't used in the compatibility check belong, and we'll be adding back - // qualifiers (with __autoreleasing) if the compatibility check succeeds. - FromPointee = FromPointee.getUnqualifiedType(); - - // The unqualified form of the pointee types must be compatible. - ToPointee = ToPointee.getUnqualifiedType(); - bool IncompatibleObjC; - if (Context.typesAreCompatible(FromPointee, ToPointee)) - FromPointee = ToPointee; - else if (!isObjCPointerConversion(FromPointee, ToPointee, FromPointee, - IncompatibleObjC)) - return false; - - /// Construct the type we're converting to, which is a pointer to - /// __autoreleasing pointee. - FromPointee = Context.getQualifiedType(FromPointee, FromQuals); - ConvertedType = Context.getPointerType(FromPointee); - return true; -} - bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, QualType& ConvertedType) { QualType ToPointeeType; @@ -7241,7 +7175,7 @@ Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance, // a consumed argument. if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) && !param->hasAttr()) - argExpr = stripARCUnbridgedCast(argExpr); + argExpr = ObjC().stripARCUnbridgedCast(argExpr); // If the parameter is __unknown_anytype, move on to the next method. if (param->getType() == Context.UnknownAnyTy) { diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp index c6a0a182d358..14ed9590afc6 100644 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -29,13 +29,14 @@ // //===----------------------------------------------------------------------===// -#include "clang/Sema/SemaInternal.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/Basic/CharInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "llvm/ADT/SmallString.h" using namespace clang; @@ -557,30 +558,31 @@ static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, // Special case for 'self' in class method implementations. if (PT->isObjCClassType() && - S.isSelfExpr(const_cast(PRE->getBase()))) { + S.ObjC().isSelfExpr(const_cast(PRE->getBase()))) { // This cast is safe because isSelfExpr is only true within // methods. ObjCMethodDecl *method = cast(S.CurContext->getNonClosureAncestor()); - return S.LookupMethodInObjectType(sel, - S.Context.getObjCInterfaceType(method->getClassInterface()), - /*instance*/ false); + return S.ObjC().LookupMethodInObjectType( + sel, S.Context.getObjCInterfaceType(method->getClassInterface()), + /*instance*/ false); } - return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); + return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true); } if (PRE->isSuperReceiver()) { if (const ObjCObjectPointerType *PT = PRE->getSuperReceiverType()->getAs()) - return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); + return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true); - return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false); + return S.ObjC().LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), + false); } assert(PRE->isClassReceiver() && "Invalid expression"); QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver()); - return S.LookupMethodInObjectType(sel, IT, false); + return S.ObjC().LookupMethodInObjectType(sel, IT, false); } bool ObjCPropertyOpBuilder::isWeakProperty() const { @@ -741,13 +743,13 @@ ExprResult ObjCPropertyOpBuilder::buildGet() { if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) || RefExpr->isObjectReceiver()) { assert(InstanceReceiver || RefExpr->isSuperReceiver()); - msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, - GenericLoc, Getter->getSelector(), - Getter, std::nullopt); + msg = S.ObjC().BuildInstanceMessageImplicit( + InstanceReceiver, receiverType, GenericLoc, Getter->getSelector(), + Getter, std::nullopt); } else { - msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), - GenericLoc, Getter->getSelector(), Getter, - std::nullopt); + msg = S.ObjC().BuildClassMessageImplicit( + receiverType, RefExpr->isSuperReceiver(), GenericLoc, + Getter->getSelector(), Getter, std::nullopt); } return msg; } @@ -801,14 +803,13 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true); if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) || RefExpr->isObjectReceiver()) { - msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, - GenericLoc, SetterSelector, Setter, - MultiExprArg(args, 1)); + msg = S.ObjC().BuildInstanceMessageImplicit(InstanceReceiver, receiverType, + GenericLoc, SetterSelector, + Setter, MultiExprArg(args, 1)); } else { - msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), - GenericLoc, - SetterSelector, Setter, - MultiExprArg(args, 1)); + msg = S.ObjC().BuildClassMessageImplicit( + receiverType, RefExpr->isSuperReceiver(), GenericLoc, SetterSelector, + Setter, MultiExprArg(args, 1)); } if (!msg.isInvalid() && captureSetValueAsResult) { @@ -836,8 +837,8 @@ ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { if (result.isInvalid()) return ExprError(); if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType()) - S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(), - Getter, RefExpr->getLocation()); + S.ObjC().DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(), + Getter, RefExpr->getLocation()); // As a special case, if the method returns 'id', try to get // a better type from the property. @@ -925,7 +926,7 @@ ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc, // Various warnings about property assignments in ARC. if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) { - S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS); + S.ObjC().checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS); S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); } @@ -1014,7 +1015,7 @@ ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc, // Various warnings about objc Index'ed assignments in ARC. if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) { - S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS); + S.ObjC().checkRetainCycles(InstanceBase->getSourceExpr(), RHS); S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); } @@ -1045,80 +1046,6 @@ Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { return syntacticBase; } -/// CheckSubscriptingKind - This routine decide what type -/// of indexing represented by "FromE" is being done. -Sema::ObjCSubscriptKind - Sema::CheckSubscriptingKind(Expr *FromE) { - // If the expression already has integral or enumeration type, we're golden. - QualType T = FromE->getType(); - if (T->isIntegralOrEnumerationType()) - return OS_Array; - - // If we don't have a class type in C++, there's no way we can get an - // expression of integral or enumeration type. - const RecordType *RecordTy = T->getAs(); - if (!RecordTy && - (T->isObjCObjectPointerType() || T->isVoidPointerType())) - // All other scalar cases are assumed to be dictionary indexing which - // caller handles, with diagnostics if needed. - return OS_Dictionary; - if (!getLangOpts().CPlusPlus || - !RecordTy || RecordTy->isIncompleteType()) { - // No indexing can be done. Issue diagnostics and quit. - const Expr *IndexExpr = FromE->IgnoreParenImpCasts(); - if (isa(IndexExpr)) - Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer) - << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@"); - else - Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) - << T; - return OS_Error; - } - - // We must have a complete class type. - if (RequireCompleteType(FromE->getExprLoc(), T, - diag::err_objc_index_incomplete_class_type, FromE)) - return OS_Error; - - // Look for a conversion to an integral, enumeration type, or - // objective-C pointer type. - int NoIntegrals=0, NoObjCIdPointers=0; - SmallVector ConversionDecls; - - for (NamedDecl *D : cast(RecordTy->getDecl()) - ->getVisibleConversionFunctions()) { - if (CXXConversionDecl *Conversion = - dyn_cast(D->getUnderlyingDecl())) { - QualType CT = Conversion->getConversionType().getNonReferenceType(); - if (CT->isIntegralOrEnumerationType()) { - ++NoIntegrals; - ConversionDecls.push_back(Conversion); - } - else if (CT->isObjCIdType() ||CT->isBlockPointerType()) { - ++NoObjCIdPointers; - ConversionDecls.push_back(Conversion); - } - } - } - if (NoIntegrals ==1 && NoObjCIdPointers == 0) - return OS_Array; - if (NoIntegrals == 0 && NoObjCIdPointers == 1) - return OS_Dictionary; - if (NoIntegrals == 0 && NoObjCIdPointers == 0) { - // No conversion function was found. Issue diagnostic and return. - Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) - << FromE->getType(); - return OS_Error; - } - Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion) - << FromE->getType(); - for (unsigned int i = 0; i < ConversionDecls.size(); i++) - Diag(ConversionDecls[i]->getLocation(), - diag::note_conv_function_declared_at); - - return OS_Error; -} - /// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF /// objects used as dictionary subscript key objects. static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT, @@ -1130,13 +1057,13 @@ static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT, const IdentifierInfo *KeyIdents[] = { &S.Context.Idents.get("objectForKeyedSubscript")}; Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); - ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT, - true /*instance*/); + ObjCMethodDecl *Getter = S.ObjC().LookupMethodInObjectType( + GetterSelector, ContainerT, true /*instance*/); if (!Getter) return; QualType T = Getter->parameters()[0]->getType(); - S.CheckObjCConversion(Key->getSourceRange(), T, Key, - CheckedConversionKind::Implicit); + S.ObjC().CheckObjCConversion(Key->getSourceRange(), T, Key, + CheckedConversionKind::Implicit); } bool ObjCSubscriptOpBuilder::findAtIndexGetter() { @@ -1151,15 +1078,15 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() { BaseT->getAs()) { ResultType = PTy->getPointeeType(); } - Sema::ObjCSubscriptKind Res = - S.CheckSubscriptingKind(RefExpr->getKeyExpr()); - if (Res == Sema::OS_Error) { + SemaObjC::ObjCSubscriptKind Res = + S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr()); + if (Res == SemaObjC::OS_Error) { if (S.getLangOpts().ObjCAutoRefCount) CheckKeyForObjCARCConversion(S, ResultType, RefExpr->getKeyExpr()); return false; } - bool arrayRef = (Res == Sema::OS_Array); + bool arrayRef = (Res == SemaObjC::OS_Array); if (ResultType.isNull()) { S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) @@ -1181,8 +1108,8 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() { AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); } - AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType, - true /*instance*/); + AtIndexGetter = S.ObjC().LookupMethodInObjectType( + AtIndexGetterSelector, ResultType, true /*instance*/); if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) { AtIndexGetter = ObjCMethodDecl::Create( @@ -1212,10 +1139,8 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() { << BaseExpr->getType() << 0 << arrayRef; return false; } - AtIndexGetter = - S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector, - RefExpr->getSourceRange(), - true); + AtIndexGetter = S.ObjC().LookupInstanceMethodInGlobalPool( + AtIndexGetterSelector, RefExpr->getSourceRange(), true); } if (AtIndexGetter) { @@ -1253,15 +1178,15 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { ResultType = PTy->getPointeeType(); } - Sema::ObjCSubscriptKind Res = - S.CheckSubscriptingKind(RefExpr->getKeyExpr()); - if (Res == Sema::OS_Error) { + SemaObjC::ObjCSubscriptKind Res = + S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr()); + if (Res == SemaObjC::OS_Error) { if (S.getLangOpts().ObjCAutoRefCount) CheckKeyForObjCARCConversion(S, ResultType, RefExpr->getKeyExpr()); return false; } - bool arrayRef = (Res == Sema::OS_Array); + bool arrayRef = (Res == SemaObjC::OS_Array); if (ResultType.isNull()) { S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) @@ -1284,8 +1209,8 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { &S.Context.Idents.get("atIndexedSubscript")}; AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); } - AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType, - true /*instance*/); + AtIndexSetter = S.ObjC().LookupMethodInObjectType( + AtIndexSetterSelector, ResultType, true /*instance*/); if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) { TypeSourceInfo *ReturnTInfo = nullptr; @@ -1327,10 +1252,8 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { << BaseExpr->getType() << 1 << arrayRef; return false; } - AtIndexSetter = - S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector, - RefExpr->getSourceRange(), - true); + AtIndexSetter = S.ObjC().LookupInstanceMethodInGlobalPool( + AtIndexSetterSelector, RefExpr->getSourceRange(), true); } bool err = false; @@ -1388,10 +1311,9 @@ ExprResult ObjCSubscriptOpBuilder::buildGet() { assert(InstanceBase); if (AtIndexGetter) S.DiagnoseUseOfDecl(AtIndexGetter, GenericLoc); - msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, - GenericLoc, - AtIndexGetterSelector, AtIndexGetter, - MultiExprArg(args, 1)); + msg = S.ObjC().BuildInstanceMessageImplicit( + InstanceBase, receiverType, GenericLoc, AtIndexGetterSelector, + AtIndexGetter, MultiExprArg(args, 1)); return msg; } @@ -1413,11 +1335,9 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, Expr *args[] = { op, Index }; // Build a message-send. - ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, - GenericLoc, - AtIndexSetterSelector, - AtIndexSetter, - MultiExprArg(args, 2)); + ExprResult msg = S.ObjC().BuildInstanceMessageImplicit( + InstanceBase, receiverType, GenericLoc, AtIndexSetterSelector, + AtIndexSetter, MultiExprArg(args, 2)); if (!msg.isInvalid() && captureSetValueAsResult) { ObjCMessageExpr *msgExpr = diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index a7b33f0db047..57465d4a77ac 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -35,6 +35,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -2236,165 +2237,6 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { return StmtResult(static_cast(FullExpr.get())); } -ExprResult -Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { - if (!collection) - return ExprError(); - - ExprResult result = CorrectDelayedTyposInExpr(collection); - if (!result.isUsable()) - return ExprError(); - collection = result.get(); - - // Bail out early if we've got a type-dependent expression. - if (collection->isTypeDependent()) return collection; - - // Perform normal l-value conversion. - result = DefaultFunctionArrayLvalueConversion(collection); - if (result.isInvalid()) - return ExprError(); - collection = result.get(); - - // The operand needs to have object-pointer type. - // TODO: should we do a contextual conversion? - const ObjCObjectPointerType *pointerType = - collection->getType()->getAs(); - if (!pointerType) - return Diag(forLoc, diag::err_collection_expr_type) - << collection->getType() << collection->getSourceRange(); - - // Check that the operand provides - // - countByEnumeratingWithState:objects:count: - const ObjCObjectType *objectType = pointerType->getObjectType(); - ObjCInterfaceDecl *iface = objectType->getInterface(); - - // If we have a forward-declared type, we can't do this check. - // Under ARC, it is an error not to have a forward-declared class. - if (iface && - (getLangOpts().ObjCAutoRefCount - ? RequireCompleteType(forLoc, QualType(objectType, 0), - diag::err_arc_collection_forward, collection) - : !isCompleteType(forLoc, QualType(objectType, 0)))) { - // Otherwise, if we have any useful type information, check that - // the type declares the appropriate method. - } else if (iface || !objectType->qual_empty()) { - const IdentifierInfo *selectorIdents[] = { - &Context.Idents.get("countByEnumeratingWithState"), - &Context.Idents.get("objects"), &Context.Idents.get("count")}; - Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]); - - ObjCMethodDecl *method = nullptr; - - // If there's an interface, look in both the public and private APIs. - if (iface) { - method = iface->lookupInstanceMethod(selector); - if (!method) method = iface->lookupPrivateMethod(selector); - } - - // Also check protocol qualifiers. - if (!method) - method = LookupMethodInQualifiedType(selector, pointerType, - /*instance*/ true); - - // If we didn't find it anywhere, give up. - if (!method) { - Diag(forLoc, diag::warn_collection_expr_type) - << collection->getType() << selector << collection->getSourceRange(); - } - - // TODO: check for an incompatible signature? - } - - // Wrap up any cleanups in the expression. - return collection; -} - -StmtResult -Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, - Stmt *First, Expr *collection, - SourceLocation RParenLoc) { - setFunctionHasBranchProtectedScope(); - - ExprResult CollectionExprResult = - CheckObjCForCollectionOperand(ForLoc, collection); - - if (First) { - QualType FirstType; - if (DeclStmt *DS = dyn_cast(First)) { - if (!DS->isSingleDecl()) - return StmtError(Diag((*DS->decl_begin())->getLocation(), - diag::err_toomany_element_decls)); - - VarDecl *D = dyn_cast(DS->getSingleDecl()); - if (!D || D->isInvalidDecl()) - return StmtError(); - - FirstType = D->getType(); - // C99 6.8.5p3: The declaration part of a 'for' statement shall only - // declare identifiers for objects having storage class 'auto' or - // 'register'. - if (!D->hasLocalStorage()) - return StmtError(Diag(D->getLocation(), - diag::err_non_local_variable_decl_in_for)); - - // If the type contained 'auto', deduce the 'auto' to 'id'. - if (FirstType->getContainedAutoType()) { - SourceLocation Loc = D->getLocation(); - OpaqueValueExpr OpaqueId(Loc, Context.getObjCIdType(), VK_PRValue); - Expr *DeducedInit = &OpaqueId; - TemplateDeductionInfo Info(Loc); - FirstType = QualType(); - TemplateDeductionResult Result = DeduceAutoType( - D->getTypeSourceInfo()->getTypeLoc(), DeducedInit, FirstType, Info); - if (Result != TemplateDeductionResult::Success && - Result != TemplateDeductionResult::AlreadyDiagnosed) - DiagnoseAutoDeductionFailure(D, DeducedInit); - if (FirstType.isNull()) { - D->setInvalidDecl(); - return StmtError(); - } - - D->setType(FirstType); - - if (!inTemplateInstantiation()) { - SourceLocation Loc = - D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); - Diag(Loc, diag::warn_auto_var_is_id) - << D->getDeclName(); - } - } - - } else { - Expr *FirstE = cast(First); - if (!FirstE->isTypeDependent() && !FirstE->isLValue()) - return StmtError( - Diag(First->getBeginLoc(), diag::err_selector_element_not_lvalue) - << First->getSourceRange()); - - FirstType = static_cast(First)->getType(); - if (FirstType.isConstQualified()) - Diag(ForLoc, diag::err_selector_element_const_type) - << FirstType << First->getSourceRange(); - } - if (!FirstType->isDependentType() && - !FirstType->isObjCObjectPointerType() && - !FirstType->isBlockPointerType()) - return StmtError(Diag(ForLoc, diag::err_selector_element_type) - << FirstType << First->getSourceRange()); - } - - if (CollectionExprResult.isInvalid()) - return StmtError(); - - CollectionExprResult = - ActOnFinishFullExpr(CollectionExprResult.get(), /*DiscardedValue*/ false); - if (CollectionExprResult.isInvalid()) - return StmtError(); - - return new (Context) ObjCForCollectionStmt(First, CollectionExprResult.get(), - nullptr, ForLoc, RParenLoc); -} - /// Finish building a variable declaration for a for-range statement. /// \return true if an error occurs. static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, @@ -2432,7 +2274,7 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, // FIXME: ARC may want to turn this into 'const __unsafe_unretained' if // we're doing the equivalent of fast iteration. if (SemaRef.getLangOpts().ObjCAutoRefCount && - SemaRef.inferObjCARCLifetime(Decl)) + SemaRef.ObjC().inferObjCARCLifetime(Decl)) Decl->setInvalidDecl(); SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false); @@ -2526,7 +2368,7 @@ StmtResult Sema::ActOnCXXForRangeStmt( if (InitStmt) return Diag(InitStmt->getBeginLoc(), diag::err_objc_for_range_init_stmt) << InitStmt->getSourceRange(); - return ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc); + return ObjC().ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc); } DeclStmt *DS = dyn_cast(First); @@ -3107,17 +2949,6 @@ StmtResult Sema::BuildCXXForRangeStmt( ColonLoc, RParenLoc); } -/// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach -/// statement. -StmtResult Sema::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) { - if (!S || !B) - return StmtError(); - ObjCForCollectionStmt * ForStmt = cast(S); - - ForStmt->setBody(B); - return S; -} - // Warn when the loop variable is a const reference that creates a copy. // Suggest using the non-reference type for copies. If a copy can be prevented // suggest the const reference type that would do so. @@ -3307,7 +3138,7 @@ StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) { return StmtError(); if (isa(S)) - return FinishObjCForCollectionStmt(S, B); + return ObjC().FinishObjCForCollectionStmt(S, B); CXXForRangeStmt *ForStmt = cast(S); ForStmt->setBody(B); @@ -4301,130 +4132,6 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, return Result; } -StmtResult -Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc, - SourceLocation RParen, Decl *Parm, - Stmt *Body) { - VarDecl *Var = cast_or_null(Parm); - if (Var && Var->isInvalidDecl()) - return StmtError(); - - return new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body); -} - -StmtResult -Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) { - return new (Context) ObjCAtFinallyStmt(AtLoc, Body); -} - -StmtResult -Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, - MultiStmtArg CatchStmts, Stmt *Finally) { - if (!getLangOpts().ObjCExceptions) - Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try"; - - // Objective-C try is incompatible with SEH __try. - sema::FunctionScopeInfo *FSI = getCurFunction(); - if (FSI->FirstSEHTryLoc.isValid()) { - Diag(AtLoc, diag::err_mixing_cxx_try_seh_try) << 1; - Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'"; - } - - FSI->setHasObjCTry(AtLoc); - unsigned NumCatchStmts = CatchStmts.size(); - return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(), - NumCatchStmts, Finally); -} - -StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { - if (Throw) { - ExprResult Result = DefaultLvalueConversion(Throw); - if (Result.isInvalid()) - return StmtError(); - - Result = ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false); - if (Result.isInvalid()) - return StmtError(); - Throw = Result.get(); - - QualType ThrowType = Throw->getType(); - // Make sure the expression type is an ObjC pointer or "void *". - if (!ThrowType->isDependentType() && - !ThrowType->isObjCObjectPointerType()) { - const PointerType *PT = ThrowType->getAs(); - if (!PT || !PT->getPointeeType()->isVoidType()) - return StmtError(Diag(AtLoc, diag::err_objc_throw_expects_object) - << Throw->getType() << Throw->getSourceRange()); - } - } - - return new (Context) ObjCAtThrowStmt(AtLoc, Throw); -} - -StmtResult -Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, - Scope *CurScope) { - if (!getLangOpts().ObjCExceptions) - Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw"; - - if (!Throw) { - // @throw without an expression designates a rethrow (which must occur - // in the context of an @catch clause). - Scope *AtCatchParent = CurScope; - while (AtCatchParent && !AtCatchParent->isAtCatchScope()) - AtCatchParent = AtCatchParent->getParent(); - if (!AtCatchParent) - return StmtError(Diag(AtLoc, diag::err_rethrow_used_outside_catch)); - } - return BuildObjCAtThrowStmt(AtLoc, Throw); -} - -ExprResult -Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) { - ExprResult result = DefaultLvalueConversion(operand); - if (result.isInvalid()) - return ExprError(); - operand = result.get(); - - // Make sure the expression type is an ObjC pointer or "void *". - QualType type = operand->getType(); - if (!type->isDependentType() && - !type->isObjCObjectPointerType()) { - const PointerType *pointerType = type->getAs(); - if (!pointerType || !pointerType->getPointeeType()->isVoidType()) { - if (getLangOpts().CPlusPlus) { - if (RequireCompleteType(atLoc, type, - diag::err_incomplete_receiver_type)) - return Diag(atLoc, diag::err_objc_synchronized_expects_object) - << type << operand->getSourceRange(); - - ExprResult result = PerformContextuallyConvertToObjCPointer(operand); - if (result.isInvalid()) - return ExprError(); - if (!result.isUsable()) - return Diag(atLoc, diag::err_objc_synchronized_expects_object) - << type << operand->getSourceRange(); - - operand = result.get(); - } else { - return Diag(atLoc, diag::err_objc_synchronized_expects_object) - << type << operand->getSourceRange(); - } - } - } - - // The operand to @synchronized is a full-expression. - return ActOnFinishFullExpr(operand, /*DiscardedValue*/ false); -} - -StmtResult -Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr, - Stmt *SyncBody) { - // We can't jump into or indirect-jump out of a @synchronized block. - setFunctionHasBranchProtectedScope(); - return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody); -} - /// ActOnCXXCatchBlock - Takes an exception declaration and a handler block /// and creates a proper catch handler from them. StmtResult @@ -4435,12 +4142,6 @@ Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, CXXCatchStmt(CatchLoc, cast_or_null(ExDecl), HandlerBlock); } -StmtResult -Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) { - setFunctionHasBranchProtectedScope(); - return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body); -} - namespace { class CatchHandlerType { QualType QT; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index fde2d920c785..e0c1f814f852 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -28,6 +28,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" @@ -1217,7 +1218,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, // In ARC, infer 'retaining' for variables of retainable type. if (SemaRef.getLangOpts().ObjCAutoRefCount && - SemaRef.inferObjCARCLifetime(Var)) + SemaRef.ObjC().inferObjCARCLifetime(Var)) Var->setInvalidDecl(); if (SemaRef.getLangOpts().OpenCL) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index fddc3545ecb6..bfa3799bda06 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -35,6 +35,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" @@ -849,424 +850,6 @@ static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator, return true; } -/// Apply Objective-C type arguments to the given type. -static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, - ArrayRef typeArgs, - SourceRange typeArgsRange, bool failOnError, - bool rebuilding) { - // We can only apply type arguments to an Objective-C class type. - const auto *objcObjectType = type->getAs(); - if (!objcObjectType || !objcObjectType->getInterface()) { - S.Diag(loc, diag::err_objc_type_args_non_class) - << type - << typeArgsRange; - - if (failOnError) - return QualType(); - return type; - } - - // The class type must be parameterized. - ObjCInterfaceDecl *objcClass = objcObjectType->getInterface(); - ObjCTypeParamList *typeParams = objcClass->getTypeParamList(); - if (!typeParams) { - S.Diag(loc, diag::err_objc_type_args_non_parameterized_class) - << objcClass->getDeclName() - << FixItHint::CreateRemoval(typeArgsRange); - - if (failOnError) - return QualType(); - - return type; - } - - // The type must not already be specialized. - if (objcObjectType->isSpecialized()) { - S.Diag(loc, diag::err_objc_type_args_specialized_class) - << type - << FixItHint::CreateRemoval(typeArgsRange); - - if (failOnError) - return QualType(); - - return type; - } - - // Check the type arguments. - SmallVector finalTypeArgs; - unsigned numTypeParams = typeParams->size(); - bool anyPackExpansions = false; - for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) { - TypeSourceInfo *typeArgInfo = typeArgs[i]; - QualType typeArg = typeArgInfo->getType(); - - // Type arguments cannot have explicit qualifiers or nullability. - // We ignore indirect sources of these, e.g. behind typedefs or - // template arguments. - if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) { - bool diagnosed = false; - SourceRange rangeToRemove; - if (auto attr = qual.getAs()) { - rangeToRemove = attr.getLocalSourceRange(); - if (attr.getTypePtr()->getImmediateNullability()) { - typeArg = attr.getTypePtr()->getModifiedType(); - S.Diag(attr.getBeginLoc(), - diag::err_objc_type_arg_explicit_nullability) - << typeArg << FixItHint::CreateRemoval(rangeToRemove); - diagnosed = true; - } - } - - // When rebuilding, qualifiers might have gotten here through a - // final substitution. - if (!rebuilding && !diagnosed) { - S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified) - << typeArg << typeArg.getQualifiers().getAsString() - << FixItHint::CreateRemoval(rangeToRemove); - } - } - - // Remove qualifiers even if they're non-local. - typeArg = typeArg.getUnqualifiedType(); - - finalTypeArgs.push_back(typeArg); - - if (typeArg->getAs()) - anyPackExpansions = true; - - // Find the corresponding type parameter, if there is one. - ObjCTypeParamDecl *typeParam = nullptr; - if (!anyPackExpansions) { - if (i < numTypeParams) { - typeParam = typeParams->begin()[i]; - } else { - // Too many arguments. - S.Diag(loc, diag::err_objc_type_args_wrong_arity) - << false - << objcClass->getDeclName() - << (unsigned)typeArgs.size() - << numTypeParams; - S.Diag(objcClass->getLocation(), diag::note_previous_decl) - << objcClass; - - if (failOnError) - return QualType(); - - return type; - } - } - - // Objective-C object pointer types must be substitutable for the bounds. - if (const auto *typeArgObjC = typeArg->getAs()) { - // If we don't have a type parameter to match against, assume - // everything is fine. There was a prior pack expansion that - // means we won't be able to match anything. - if (!typeParam) { - assert(anyPackExpansions && "Too many arguments?"); - continue; - } - - // Retrieve the bound. - QualType bound = typeParam->getUnderlyingType(); - const auto *boundObjC = bound->castAs(); - - // Determine whether the type argument is substitutable for the bound. - if (typeArgObjC->isObjCIdType()) { - // When the type argument is 'id', the only acceptable type - // parameter bound is 'id'. - if (boundObjC->isObjCIdType()) - continue; - } else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) { - // Otherwise, we follow the assignability rules. - continue; - } - - // Diagnose the mismatch. - S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), - diag::err_objc_type_arg_does_not_match_bound) - << typeArg << bound << typeParam->getDeclName(); - S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) - << typeParam->getDeclName(); - - if (failOnError) - return QualType(); - - return type; - } - - // Block pointer types are permitted for unqualified 'id' bounds. - if (typeArg->isBlockPointerType()) { - // If we don't have a type parameter to match against, assume - // everything is fine. There was a prior pack expansion that - // means we won't be able to match anything. - if (!typeParam) { - assert(anyPackExpansions && "Too many arguments?"); - continue; - } - - // Retrieve the bound. - QualType bound = typeParam->getUnderlyingType(); - if (bound->isBlockCompatibleObjCPointerType(S.Context)) - continue; - - // Diagnose the mismatch. - S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), - diag::err_objc_type_arg_does_not_match_bound) - << typeArg << bound << typeParam->getDeclName(); - S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) - << typeParam->getDeclName(); - - if (failOnError) - return QualType(); - - return type; - } - - // Types that have __attribute__((NSObject)) are permitted. - if (typeArg->isObjCNSObjectType()) { - continue; - } - - // Dependent types will be checked at instantiation time. - if (typeArg->isDependentType()) { - continue; - } - - // Diagnose non-id-compatible type arguments. - S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), - diag::err_objc_type_arg_not_id_compatible) - << typeArg << typeArgInfo->getTypeLoc().getSourceRange(); - - if (failOnError) - return QualType(); - - return type; - } - - // Make sure we didn't have the wrong number of arguments. - if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) { - S.Diag(loc, diag::err_objc_type_args_wrong_arity) - << (typeArgs.size() < typeParams->size()) - << objcClass->getDeclName() - << (unsigned)finalTypeArgs.size() - << (unsigned)numTypeParams; - S.Diag(objcClass->getLocation(), diag::note_previous_decl) - << objcClass; - - if (failOnError) - return QualType(); - - return type; - } - - // Success. Form the specialized type. - return S.Context.getObjCObjectType(type, finalTypeArgs, { }, false); -} - -QualType Sema::BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, - SourceLocation ProtocolLAngleLoc, - ArrayRef Protocols, - ArrayRef ProtocolLocs, - SourceLocation ProtocolRAngleLoc, - bool FailOnError) { - QualType Result = QualType(Decl->getTypeForDecl(), 0); - if (!Protocols.empty()) { - bool HasError; - Result = Context.applyObjCProtocolQualifiers(Result, Protocols, - HasError); - if (HasError) { - Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers) - << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc); - if (FailOnError) Result = QualType(); - } - if (FailOnError && Result.isNull()) - return QualType(); - } - - return Result; -} - -QualType Sema::BuildObjCObjectType( - QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc, - ArrayRef TypeArgs, SourceLocation TypeArgsRAngleLoc, - SourceLocation ProtocolLAngleLoc, ArrayRef Protocols, - ArrayRef ProtocolLocs, SourceLocation ProtocolRAngleLoc, - bool FailOnError, bool Rebuilding) { - QualType Result = BaseType; - if (!TypeArgs.empty()) { - Result = - applyObjCTypeArgs(*this, Loc, Result, TypeArgs, - SourceRange(TypeArgsLAngleLoc, TypeArgsRAngleLoc), - FailOnError, Rebuilding); - if (FailOnError && Result.isNull()) - return QualType(); - } - - if (!Protocols.empty()) { - bool HasError; - Result = Context.applyObjCProtocolQualifiers(Result, Protocols, - HasError); - if (HasError) { - Diag(Loc, diag::err_invalid_protocol_qualifiers) - << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc); - if (FailOnError) Result = QualType(); - } - if (FailOnError && Result.isNull()) - return QualType(); - } - - return Result; -} - -TypeResult Sema::actOnObjCProtocolQualifierType( - SourceLocation lAngleLoc, - ArrayRef protocols, - ArrayRef protocolLocs, - SourceLocation rAngleLoc) { - // Form id. - QualType Result = Context.getObjCObjectType( - Context.ObjCBuiltinIdTy, {}, - llvm::ArrayRef((ObjCProtocolDecl *const *)protocols.data(), - protocols.size()), - false); - Result = Context.getObjCObjectPointerType(Result); - - TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result); - TypeLoc ResultTL = ResultTInfo->getTypeLoc(); - - auto ObjCObjectPointerTL = ResultTL.castAs(); - ObjCObjectPointerTL.setStarLoc(SourceLocation()); // implicit - - auto ObjCObjectTL = ObjCObjectPointerTL.getPointeeLoc() - .castAs(); - ObjCObjectTL.setHasBaseTypeAsWritten(false); - ObjCObjectTL.getBaseLoc().initialize(Context, SourceLocation()); - - // No type arguments. - ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation()); - ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation()); - - // Fill in protocol qualifiers. - ObjCObjectTL.setProtocolLAngleLoc(lAngleLoc); - ObjCObjectTL.setProtocolRAngleLoc(rAngleLoc); - for (unsigned i = 0, n = protocols.size(); i != n; ++i) - ObjCObjectTL.setProtocolLoc(i, protocolLocs[i]); - - // We're done. Return the completed type to the parser. - return CreateParsedType(Result, ResultTInfo); -} - -TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers( - Scope *S, - SourceLocation Loc, - ParsedType BaseType, - SourceLocation TypeArgsLAngleLoc, - ArrayRef TypeArgs, - SourceLocation TypeArgsRAngleLoc, - SourceLocation ProtocolLAngleLoc, - ArrayRef Protocols, - ArrayRef ProtocolLocs, - SourceLocation ProtocolRAngleLoc) { - TypeSourceInfo *BaseTypeInfo = nullptr; - QualType T = GetTypeFromParser(BaseType, &BaseTypeInfo); - if (T.isNull()) - return true; - - // Handle missing type-source info. - if (!BaseTypeInfo) - BaseTypeInfo = Context.getTrivialTypeSourceInfo(T, Loc); - - // Extract type arguments. - SmallVector ActualTypeArgInfos; - for (unsigned i = 0, n = TypeArgs.size(); i != n; ++i) { - TypeSourceInfo *TypeArgInfo = nullptr; - QualType TypeArg = GetTypeFromParser(TypeArgs[i], &TypeArgInfo); - if (TypeArg.isNull()) { - ActualTypeArgInfos.clear(); - break; - } - - assert(TypeArgInfo && "No type source info?"); - ActualTypeArgInfos.push_back(TypeArgInfo); - } - - // Build the object type. - QualType Result = BuildObjCObjectType( - T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(), - TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc, - ProtocolLAngleLoc, - llvm::ArrayRef((ObjCProtocolDecl *const *)Protocols.data(), - Protocols.size()), - ProtocolLocs, ProtocolRAngleLoc, - /*FailOnError=*/false, - /*Rebuilding=*/false); - - if (Result == T) - return BaseType; - - // Create source information for this type. - TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result); - TypeLoc ResultTL = ResultTInfo->getTypeLoc(); - - // For id or Class, we'll have an - // object pointer type. Fill in source information for it. - if (auto ObjCObjectPointerTL = ResultTL.getAs()) { - // The '*' is implicit. - ObjCObjectPointerTL.setStarLoc(SourceLocation()); - ResultTL = ObjCObjectPointerTL.getPointeeLoc(); - } - - if (auto OTPTL = ResultTL.getAs()) { - // Protocol qualifier information. - if (OTPTL.getNumProtocols() > 0) { - assert(OTPTL.getNumProtocols() == Protocols.size()); - OTPTL.setProtocolLAngleLoc(ProtocolLAngleLoc); - OTPTL.setProtocolRAngleLoc(ProtocolRAngleLoc); - for (unsigned i = 0, n = Protocols.size(); i != n; ++i) - OTPTL.setProtocolLoc(i, ProtocolLocs[i]); - } - - // We're done. Return the completed type to the parser. - return CreateParsedType(Result, ResultTInfo); - } - - auto ObjCObjectTL = ResultTL.castAs(); - - // Type argument information. - if (ObjCObjectTL.getNumTypeArgs() > 0) { - assert(ObjCObjectTL.getNumTypeArgs() == ActualTypeArgInfos.size()); - ObjCObjectTL.setTypeArgsLAngleLoc(TypeArgsLAngleLoc); - ObjCObjectTL.setTypeArgsRAngleLoc(TypeArgsRAngleLoc); - for (unsigned i = 0, n = ActualTypeArgInfos.size(); i != n; ++i) - ObjCObjectTL.setTypeArgTInfo(i, ActualTypeArgInfos[i]); - } else { - ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation()); - ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation()); - } - - // Protocol qualifier information. - if (ObjCObjectTL.getNumProtocols() > 0) { - assert(ObjCObjectTL.getNumProtocols() == Protocols.size()); - ObjCObjectTL.setProtocolLAngleLoc(ProtocolLAngleLoc); - ObjCObjectTL.setProtocolRAngleLoc(ProtocolRAngleLoc); - for (unsigned i = 0, n = Protocols.size(); i != n; ++i) - ObjCObjectTL.setProtocolLoc(i, ProtocolLocs[i]); - } else { - ObjCObjectTL.setProtocolLAngleLoc(SourceLocation()); - ObjCObjectTL.setProtocolRAngleLoc(SourceLocation()); - } - - // Base type. - ObjCObjectTL.setHasBaseTypeAsWritten(true); - if (ObjCObjectTL.getType() == T) - ObjCObjectTL.getBaseLoc().initializeFullCopy(BaseTypeInfo->getTypeLoc()); - else - ObjCObjectTL.getBaseLoc().initialize(Context, Loc); - - // We're done. Return the completed type to the parser. - return CreateParsedType(Result, ResultTInfo); -} - static OpenCLAccessAttr::Spelling getImageAccess(const ParsedAttributesView &Attrs) { for (const ParsedAttr &AL : Attrs) @@ -4259,14 +3842,6 @@ IdentifierInfo *Sema::getNullabilityKeyword(NullabilityKind nullability) { llvm_unreachable("Unknown nullability kind."); } -/// Retrieve the identifier "NSError". -IdentifierInfo *Sema::getNSErrorIdent() { - if (!Ident_NSError) - Ident_NSError = PP.getIdentifierInfo("NSError"); - - return Ident_NSError; -} - /// Check whether there is a nullability attribute of any kind in the given /// attribute list. static bool hasNullabilityAttr(const ParsedAttributesView &attrs) { @@ -4392,7 +3967,7 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator, // If this is NSError**, report that. if (auto objcClassDecl = objcObjectPtr->getInterfaceDecl()) { - if (objcClassDecl->getIdentifier() == S.getNSErrorIdent() && + if (objcClassDecl->getIdentifier() == S.ObjC().getNSErrorIdent() && numNormalPointers == 2 && numTypeSpecifierPointers < 2) { return PointerDeclaratorKind::NSErrorPointerPointer; } @@ -4403,7 +3978,8 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator, // Look at Objective-C class types. if (auto objcClass = type->getAs()) { - if (objcClass->getInterface()->getIdentifier() == S.getNSErrorIdent()) { + if (objcClass->getInterface()->getIdentifier() == + S.ObjC().getNSErrorIdent()) { if (numNormalPointers == 2 && numTypeSpecifierPointers < 2) return PointerDeclaratorKind::NSErrorPointerPointer; } @@ -4420,7 +3996,7 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator, // If this is CFErrorRef*, report it as such. if (numNormalPointers == 2 && numTypeSpecifierPointers < 2 && - S.isCFError(recordDecl)) { + S.ObjC().isCFError(recordDecl)) { return PointerDeclaratorKind::CFErrorRefPointer; } break; @@ -4444,31 +4020,6 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator, } } -bool Sema::isCFError(RecordDecl *RD) { - // If we already know about CFError, test it directly. - if (CFError) - return CFError == RD; - - // Check whether this is CFError, which we identify based on its bridge to - // NSError. CFErrorRef used to be declared with "objc_bridge" but is now - // declared with "objc_bridge_mutable", so look for either one of the two - // attributes. - if (RD->getTagKind() == TagTypeKind::Struct) { - IdentifierInfo *bridgedType = nullptr; - if (auto bridgeAttr = RD->getAttr()) - bridgedType = bridgeAttr->getBridgedType(); - else if (auto bridgeAttr = RD->getAttr()) - bridgedType = bridgeAttr->getBridgedType(); - - if (bridgedType == getNSErrorIdent()) { - CFError = RD; - return true; - } - } - - return false; -} - static FileID getNullabilityCompletenessCheckFileID(Sema &S, SourceLocation loc) { // If we're anywhere in a function, method, or closure context, don't perform @@ -6839,12 +6390,6 @@ TypeResult Sema::ActOnTypeName(Declarator &D) { return CreateParsedType(T, TInfo); } -ParsedType Sema::ActOnObjCInstanceType(SourceLocation Loc) { - QualType T = Context.getObjCInstanceType(); - TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc); - return CreateParsedType(T, TInfo); -} - //===----------------------------------------------------------------------===// // Type Attribute Processing //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index ab26d1b1199a..2d903dc52556 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -39,6 +39,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaDiagnostic.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenACC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/SemaSYCL.h" @@ -1609,8 +1610,8 @@ public: Stmt *TryBody, MultiStmtArg CatchStmts, Stmt *Finally) { - return getSema().ActOnObjCAtTryStmt(AtLoc, TryBody, CatchStmts, - Finally); + return getSema().ObjC().ActOnObjCAtTryStmt(AtLoc, TryBody, CatchStmts, + Finally); } /// Rebuild an Objective-C exception declaration. @@ -1619,10 +1620,9 @@ public: /// Subclasses may override this routine to provide different behavior. VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, TypeSourceInfo *TInfo, QualType T) { - return getSema().BuildObjCExceptionDecl(TInfo, T, - ExceptionDecl->getInnerLocStart(), - ExceptionDecl->getLocation(), - ExceptionDecl->getIdentifier()); + return getSema().ObjC().BuildObjCExceptionDecl( + TInfo, T, ExceptionDecl->getInnerLocStart(), + ExceptionDecl->getLocation(), ExceptionDecl->getIdentifier()); } /// Build a new Objective-C \@catch statement. @@ -1633,8 +1633,7 @@ public: SourceLocation RParenLoc, VarDecl *Var, Stmt *Body) { - return getSema().ActOnObjCAtCatchStmt(AtLoc, RParenLoc, - Var, Body); + return getSema().ObjC().ActOnObjCAtCatchStmt(AtLoc, RParenLoc, Var, Body); } /// Build a new Objective-C \@finally statement. @@ -1643,7 +1642,7 @@ public: /// Subclasses may override this routine to provide different behavior. StmtResult RebuildObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) { - return getSema().ActOnObjCAtFinallyStmt(AtLoc, Body); + return getSema().ObjC().ActOnObjCAtFinallyStmt(AtLoc, Body); } /// Build a new Objective-C \@throw statement. @@ -1652,7 +1651,7 @@ public: /// Subclasses may override this routine to provide different behavior. StmtResult RebuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Operand) { - return getSema().BuildObjCAtThrowStmt(AtLoc, Operand); + return getSema().ObjC().BuildObjCAtThrowStmt(AtLoc, Operand); } /// Build a new OpenMP Canonical loop. @@ -2492,7 +2491,7 @@ public: /// Subclasses may override this routine to provide different behavior. ExprResult RebuildObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *object) { - return getSema().ActOnObjCAtSynchronizedOperand(atLoc, object); + return getSema().ObjC().ActOnObjCAtSynchronizedOperand(atLoc, object); } /// Build a new Objective-C \@synchronized statement. @@ -2501,7 +2500,7 @@ public: /// Subclasses may override this routine to provide different behavior. StmtResult RebuildObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *Object, Stmt *Body) { - return getSema().ActOnObjCAtSynchronizedStmt(AtLoc, Object, Body); + return getSema().ObjC().ActOnObjCAtSynchronizedStmt(AtLoc, Object, Body); } /// Build a new Objective-C \@autoreleasepool statement. @@ -2510,7 +2509,7 @@ public: /// Subclasses may override this routine to provide different behavior. StmtResult RebuildObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) { - return getSema().ActOnObjCAutoreleasePoolStmt(AtLoc, Body); + return getSema().ObjC().ActOnObjCAutoreleasePoolStmt(AtLoc, Body); } /// Build a new Objective-C fast enumeration statement. @@ -2522,14 +2521,13 @@ public: Expr *Collection, SourceLocation RParenLoc, Stmt *Body) { - StmtResult ForEachStmt = getSema().ActOnObjCForCollectionStmt(ForLoc, - Element, - Collection, - RParenLoc); + StmtResult ForEachStmt = getSema().ObjC().ActOnObjCForCollectionStmt( + ForLoc, Element, Collection, RParenLoc); if (ForEachStmt.isInvalid()) return StmtError(); - return getSema().FinishObjCForCollectionStmt(ForEachStmt.get(), Body); + return getSema().ObjC().FinishObjCForCollectionStmt(ForEachStmt.get(), + Body); } /// Build a new C++ exception declaration. @@ -2595,8 +2593,8 @@ public: diag::err_objc_for_range_init_stmt) << Init->getSourceRange(); } - return getSema().ActOnObjCForCollectionStmt(ForLoc, LoopVar, - RangeExpr, RParenLoc); + return getSema().ObjC().ActOnObjCForCollectionStmt( + ForLoc, LoopVar, RangeExpr, RParenLoc); } } } @@ -3720,7 +3718,7 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { - return getSema().BuildObjCBoxedExpr(SR, ValueExpr); + return getSema().ObjC().BuildObjCBoxedExpr(SR, ValueExpr); } /// Build a new Objective-C array literal. @@ -3729,16 +3727,16 @@ public: /// Subclasses may override this routine to provide different behavior. ExprResult RebuildObjCArrayLiteral(SourceRange Range, Expr **Elements, unsigned NumElements) { - return getSema().BuildObjCArrayLiteral(Range, - MultiExprArg(Elements, NumElements)); + return getSema().ObjC().BuildObjCArrayLiteral( + Range, MultiExprArg(Elements, NumElements)); } ExprResult RebuildObjCSubscriptRefExpr(SourceLocation RB, Expr *Base, Expr *Key, ObjCMethodDecl *getterMethod, ObjCMethodDecl *setterMethod) { - return getSema().BuildObjCSubscriptExpression(RB, Base, Key, - getterMethod, setterMethod); + return getSema().ObjC().BuildObjCSubscriptExpression( + RB, Base, Key, getterMethod, setterMethod); } /// Build a new Objective-C dictionary literal. @@ -3747,7 +3745,7 @@ public: /// Subclasses may override this routine to provide different behavior. ExprResult RebuildObjCDictionaryLiteral(SourceRange Range, MutableArrayRef Elements) { - return getSema().BuildObjCDictionaryLiteral(Range, Elements); + return getSema().ObjC().BuildObjCDictionaryLiteral(Range, Elements); } /// Build a new Objective-C \@encode expression. @@ -3757,7 +3755,8 @@ public: ExprResult RebuildObjCEncodeExpr(SourceLocation AtLoc, TypeSourceInfo *EncodeTypeInfo, SourceLocation RParenLoc) { - return SemaRef.BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo, RParenLoc); + return SemaRef.ObjC().BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo, + RParenLoc); } /// Build a new Objective-C class message. @@ -3768,11 +3767,10 @@ public: SourceLocation LBracLoc, MultiExprArg Args, SourceLocation RBracLoc) { - return SemaRef.BuildClassMessage(ReceiverTypeInfo, - ReceiverTypeInfo->getType(), - /*SuperLoc=*/SourceLocation(), - Sel, Method, LBracLoc, SelectorLocs, - RBracLoc, Args); + return SemaRef.ObjC().BuildClassMessage( + ReceiverTypeInfo, ReceiverTypeInfo->getType(), + /*SuperLoc=*/SourceLocation(), Sel, Method, LBracLoc, SelectorLocs, + RBracLoc, Args); } /// Build a new Objective-C instance message. @@ -3783,11 +3781,10 @@ public: SourceLocation LBracLoc, MultiExprArg Args, SourceLocation RBracLoc) { - return SemaRef.BuildInstanceMessage(Receiver, - Receiver->getType(), - /*SuperLoc=*/SourceLocation(), - Sel, Method, LBracLoc, SelectorLocs, - RBracLoc, Args); + return SemaRef.ObjC().BuildInstanceMessage(Receiver, Receiver->getType(), + /*SuperLoc=*/SourceLocation(), + Sel, Method, LBracLoc, + SelectorLocs, RBracLoc, Args); } /// Build a new Objective-C instance/class message to 'super'. @@ -3799,18 +3796,13 @@ public: SourceLocation LBracLoc, MultiExprArg Args, SourceLocation RBracLoc) { - return Method->isInstanceMethod() ? SemaRef.BuildInstanceMessage(nullptr, - SuperType, - SuperLoc, - Sel, Method, LBracLoc, SelectorLocs, - RBracLoc, Args) - : SemaRef.BuildClassMessage(nullptr, - SuperType, - SuperLoc, - Sel, Method, LBracLoc, SelectorLocs, - RBracLoc, Args); - - + return Method->isInstanceMethod() + ? SemaRef.ObjC().BuildInstanceMessage( + nullptr, SuperType, SuperLoc, Sel, Method, LBracLoc, + SelectorLocs, RBracLoc, Args) + : SemaRef.ObjC().BuildClassMessage(nullptr, SuperType, SuperLoc, + Sel, Method, LBracLoc, + SelectorLocs, RBracLoc, Args); } /// Build a new Objective-C ivar reference expression. @@ -15450,9 +15442,9 @@ TransformObjCBridgedCastExpr(ObjCBridgedCastExpr *E) { Result.get() == E->getSubExpr()) return E; - return SemaRef.BuildObjCBridgedCast(E->getLParenLoc(), E->getBridgeKind(), - E->getBridgeKeywordLoc(), TSInfo, - Result.get()); + return SemaRef.ObjC().BuildObjCBridgedCast( + E->getLParenLoc(), E->getBridgeKind(), E->getBridgeKeywordLoc(), TSInfo, + Result.get()); } template @@ -15840,10 +15832,9 @@ QualType TreeTransform::RebuildObjCTypeParamType( ArrayRef Protocols, ArrayRef ProtocolLocs, SourceLocation ProtocolRAngleLoc) { - return SemaRef.BuildObjCTypeParamType(Decl, - ProtocolLAngleLoc, Protocols, - ProtocolLocs, ProtocolRAngleLoc, - /*FailOnError=*/true); + return SemaRef.ObjC().BuildObjCTypeParamType( + Decl, ProtocolLAngleLoc, Protocols, ProtocolLocs, ProtocolRAngleLoc, + /*FailOnError=*/true); } template @@ -15857,11 +15848,11 @@ QualType TreeTransform::RebuildObjCObjectType( ArrayRef Protocols, ArrayRef ProtocolLocs, SourceLocation ProtocolRAngleLoc) { - return SemaRef.BuildObjCObjectType(BaseType, Loc, TypeArgsLAngleLoc, TypeArgs, - TypeArgsRAngleLoc, ProtocolLAngleLoc, - Protocols, ProtocolLocs, ProtocolRAngleLoc, - /*FailOnError=*/true, - /*Rebuilding=*/true); + return SemaRef.ObjC().BuildObjCObjectType( + BaseType, Loc, TypeArgsLAngleLoc, TypeArgs, TypeArgsRAngleLoc, + ProtocolLAngleLoc, Protocols, ProtocolLocs, ProtocolRAngleLoc, + /*FailOnError=*/true, + /*Rebuilding=*/true); } template diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index 63c5140086d8..bc662a87a7bf 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -341,7 +341,7 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) { // FIXME: These are defined in one place, but properties in class extensions // end up being back-patched into the main interface. See - // Sema::HandlePropertyInClassExtension for the offending code. + // SemaObjC::HandlePropertyInClassExtension for the offending code. case Decl::ObjCInterface: return nullptr; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 8f437a7c5f50..510f61d9cccd 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -78,6 +78,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/Weak.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTDeserializationListener.h" @@ -4233,9 +4234,9 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, /// Move the given method to the back of the global list of methods. static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) { // Find the entry for this selector in the method pool. - Sema::GlobalMethodPool::iterator Known - = S.MethodPool.find(Method->getSelector()); - if (Known == S.MethodPool.end()) + SemaObjC::GlobalMethodPool::iterator Known = + S.ObjC().MethodPool.find(Method->getSelector()); + if (Known == S.ObjC().MethodPool.end()) return; // Retrieve the appropriate method list. @@ -8551,7 +8552,7 @@ namespace serialization { static void addMethodsToPool(Sema &S, ArrayRef Methods, ObjCMethodList &List) { for (ObjCMethodDecl *M : llvm::reverse(Methods)) - S.addMethodToGlobalList(&List, M); + S.ObjC().addMethodToGlobalList(&List, M); } void ASTReader::ReadMethodPool(Selector Sel) { @@ -8576,8 +8577,10 @@ void ASTReader::ReadMethodPool(Selector Sel) { return; Sema &S = *getSema(); - Sema::GlobalMethodPool::iterator Pos = - S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethodPool::Lists())) + SemaObjC::GlobalMethodPool::iterator Pos = + S.ObjC() + .MethodPool + .insert(std::make_pair(Sel, SemaObjC::GlobalMethodPool::Lists())) .first; Pos->second.first.setBits(Visitor.getInstanceBits()); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 7a9d392889bb..129bc337c892 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -66,6 +66,7 @@ #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaObjC.h" #include "clang/Sema/Weak.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTReader.h" @@ -3547,7 +3548,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { using namespace llvm; // Do we have to do anything at all? - if (SemaRef.MethodPool.empty() && SelectorIDs.empty()) + if (SemaRef.ObjC().MethodPool.empty() && SelectorIDs.empty()) return; unsigned NumTableEntries = 0; // Create and write out the blob that contains selectors and the method pool. @@ -3561,13 +3562,14 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { for (auto &SelectorAndID : SelectorIDs) { Selector S = SelectorAndID.first; SelectorID ID = SelectorAndID.second; - Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S); + SemaObjC::GlobalMethodPool::iterator F = + SemaRef.ObjC().MethodPool.find(S); ASTMethodPoolTrait::data_type Data = { ID, ObjCMethodList(), ObjCMethodList() }; - if (F != SemaRef.MethodPool.end()) { + if (F != SemaRef.ObjC().MethodPool.end()) { Data.Instance = F->second.first; Data.Factory = F->second.second; } @@ -3652,7 +3654,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) { using namespace llvm; - if (SemaRef.ReferencedSelectors.empty()) + if (SemaRef.ObjC().ReferencedSelectors.empty()) return; RecordData Record; @@ -3661,7 +3663,7 @@ void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) { // Note: this writes out all references even for a dependent AST. But it is // very tricky to fix, and given that @selector shouldn't really appear in // headers, probably not worth it. It's not a correctness issue. - for (auto &SelectorAndLocation : SemaRef.ReferencedSelectors) { + for (auto &SelectorAndLocation : SemaRef.ObjC().ReferencedSelectors) { Selector Sel = SelectorAndLocation.first; SourceLocation Loc = SelectorAndLocation.second; Writer.AddSelectorRef(Sel); @@ -5346,7 +5348,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, for (auto &SelectorAndID : SelectorIDs) AllSelectors.push_back(SelectorAndID.first); for (auto &Selector : AllSelectors) - SemaRef.updateOutOfDateSelector(Selector); + SemaRef.ObjC().updateOutOfDateSelector(Selector); // Form the record of special types. RecordData SpecialTypes; -- GitLab From bb867b59b86ec48bb8a4e399cbb7ee99c7981d32 Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Mon, 13 May 2024 15:39:35 -0400 Subject: [PATCH 126/578] [MLIR] NFC: change variable name to lowercase to follow mlir convention. (#91974) --- mlir/tools/mlir-src-sharder/mlir-src-sharder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/tools/mlir-src-sharder/mlir-src-sharder.cpp b/mlir/tools/mlir-src-sharder/mlir-src-sharder.cpp index 5bfc24ef3b47..b15f2ce54405 100644 --- a/mlir/tools/mlir-src-sharder/mlir-src-sharder.cpp +++ b/mlir/tools/mlir-src-sharder/mlir-src-sharder.cpp @@ -66,7 +66,7 @@ int main(int argc, char **argv) { // of `llvm-tblgen`, which caused `TestOps.cpp` to fail due to // "Unknnown command line argument '-D...`" when a macros name is // present. The following is a workaround to re-register it again. - llvm::cl::list MacroNames( + llvm::cl::list macroNames( "D", llvm::cl::desc( "Name of the macro to be defined -- ignored by mlir-src-sharder"), -- GitLab From e1223804458a99f82dc110d41647410bdac420df Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 13 May 2024 20:30:09 +0100 Subject: [PATCH 127/578] [LV] Use VPBuilder to create Select (NFCI). --- llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 261933966b74..8b4cb5a6658d 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -8377,10 +8377,7 @@ VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I, VPValue *Mask = getBlockInMask(I->getParent()); VPValue *One = Plan.getOrAddLiveIn(ConstantInt::get(I->getType(), 1u, false)); - auto *SafeRHS = - new VPInstruction(Instruction::Select, {Mask, Ops[1], One}, - I->getDebugLoc()); - VPBB->appendRecipe(SafeRHS); + auto *SafeRHS = Builder.createSelect(Mask, Ops[1], One, I->getDebugLoc()); Ops[1] = SafeRHS; return new VPWidenRecipe(*I, make_range(Ops.begin(), Ops.end())); } -- GitLab From a4b3422536c712dcb198223822424ff15fb9e45b Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Mon, 13 May 2024 19:45:57 +0000 Subject: [PATCH 128/578] [gn build] Port 31a203fa8af4 --- llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn index e9ba5fb132b0..f6c9526278dd 100644 --- a/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn @@ -78,6 +78,7 @@ static_library("Sema") { "SemaLambda.cpp", "SemaLookup.cpp", "SemaModule.cpp", + "SemaObjC.cpp", "SemaObjCProperty.cpp", "SemaOpenACC.cpp", "SemaOpenMP.cpp", -- GitLab From a6d7828f4c50c1ec7b0b5f61fe59d7a768175dcc Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 13 May 2024 12:53:16 -0700 Subject: [PATCH 129/578] [test] Use conventional -emit-llvm-only This avoids 'Permission denied' when PWD is read-only. While here, change the triple from a Linux one to a generic ELF one. --- clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_fmlas16.c | 4 ++-- .../Sema/aarch64-sme2-intrinsics/acle_sme2_mopa_nonwide.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_fmlas16.c b/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_fmlas16.c index b1582569971d..66aba36ff68a 100644 --- a/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_fmlas16.c +++ b/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_fmlas16.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -verify -emit-llvm %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -verify -emit-llvm-only %s // REQUIRES: aarch64-registered-target @@ -87,4 +87,4 @@ void test_imm(uint32_t slice, svfloat16_t zm, svfloat16x2_t zn2,svfloat16x4_t zn svmls_lane_za16_bf16_vg1x2(slice, bzn2, bzm, -1); // expected-error@+1 {{argument value 18446744073709551615 is outside the valid range [0, 7]}} svmls_lane_za16_bf16_vg1x4(slice, bzn4, bzm, -1); -} \ No newline at end of file +} diff --git a/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_mopa_nonwide.c b/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_mopa_nonwide.c index 201ad4b8ff7f..1331bf2050b7 100644 --- a/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_mopa_nonwide.c +++ b/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_mopa_nonwide.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -verify -emit-llvm %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -verify -emit-llvm-only %s // REQUIRES: aarch64-registered-target -- GitLab From c3028a230557405b0f10bdd7d450f7f92747bbe3 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 13 May 2024 12:33:30 -0700 Subject: [PATCH 130/578] [RISCV] Don't exlude the frame pointer from the callee saved registers in RISCVRegisterInfo::needsFrameBaseReg. Instead of using getReservedRegs, just check the subtarget reserved list. getReservedRegs considers the frame pointer to be reserved when it is being used, but we do need to save/restore it so it should be counted as a callee saved register. AArch64 hardcodes their callee saved size, but the comment mentions the Frame Pointer being counted. --- llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 4 +- .../RISCV/local-stack-slot-allocation.ll | 47 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index c3281e409653..7ac73b59f36c 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -609,13 +609,13 @@ bool RISCVRegisterInfo::needsFrameBaseReg(MachineInstr *MI, const MachineRegisterInfo &MRI = MF.getRegInfo(); if (TFI->hasFP(MF) && !shouldRealignStack(MF)) { + auto &Subtarget = MF.getSubtarget(); // Estimate the stack size used to store callee saved registers( // excludes reserved registers). unsigned CalleeSavedSize = 0; - BitVector ReservedRegs = getReservedRegs(MF); for (const MCPhysReg *R = MRI.getCalleeSavedRegs(); MCPhysReg Reg = *R; ++R) { - if (!ReservedRegs.test(Reg)) + if (!Subtarget.isRegisterReservedByUser(Reg)) CalleeSavedSize += getSpillSize(*getMinimalPhysRegClass(Reg)); } diff --git a/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll b/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll index 18e7992f30a3..1d5487e19e89 100644 --- a/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll +++ b/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll @@ -111,3 +111,50 @@ define void @load_with_offset2() { store volatile i8 %load, ptr %va_gep, align 4 ret void } + +define void @frame_pointer() "frame-pointer"="all" { +; RV32I-LABEL: frame_pointer: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -2032 +; RV32I-NEXT: .cfi_def_cfa_offset 2032 +; RV32I-NEXT: sw ra, 2028(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw s0, 2024(sp) # 4-byte Folded Spill +; RV32I-NEXT: .cfi_offset ra, -4 +; RV32I-NEXT: .cfi_offset s0, -8 +; RV32I-NEXT: addi s0, sp, 2032 +; RV32I-NEXT: .cfi_def_cfa s0, 0 +; RV32I-NEXT: addi sp, sp, -480 +; RV32I-NEXT: lbu a0, -1960(s0) +; RV32I-NEXT: sb a0, -1960(s0) +; RV32I-NEXT: addi sp, sp, 480 +; RV32I-NEXT: lw ra, 2028(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw s0, 2024(sp) # 4-byte Folded Reload +; RV32I-NEXT: addi sp, sp, 2032 +; RV32I-NEXT: ret +; +; RV64I-LABEL: frame_pointer: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -2032 +; RV64I-NEXT: .cfi_def_cfa_offset 2032 +; RV64I-NEXT: sd ra, 2024(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s0, 2016(sp) # 8-byte Folded Spill +; RV64I-NEXT: .cfi_offset ra, -8 +; RV64I-NEXT: .cfi_offset s0, -16 +; RV64I-NEXT: addi s0, sp, 2032 +; RV64I-NEXT: .cfi_def_cfa s0, 0 +; RV64I-NEXT: addi sp, sp, -496 +; RV64I-NEXT: addi a0, s0, -1972 +; RV64I-NEXT: lbu a1, 0(a0) +; RV64I-NEXT: sb a1, 0(a0) +; RV64I-NEXT: addi sp, sp, 496 +; RV64I-NEXT: ld ra, 2024(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s0, 2016(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 2032 +; RV64I-NEXT: ret + + %va = alloca [2500 x i8], align 4 + %va_gep = getelementptr [2000 x i8], ptr %va, i64 0, i64 552 + %load = load volatile i8, ptr %va_gep, align 4 + store volatile i8 %load, ptr %va_gep, align 4 + ret void +} -- GitLab From 55e59083cb610f30ad21fe8c8cdb9900534937ec Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 13 May 2024 13:26:17 -0700 Subject: [PATCH 131/578] [RISCV] Exclude vector callee saved registers from RISCVRegisterInfo::needsFrameBaseReg The vector callee saved registers shouldn't affect the frame pointer offset so we don't want to consider them. I've listed the GPR, FPR32, and FPR64 register classes explicitly because getMinimalPhysRegClass is slow and this function is called frequently. So explicitly listing the interesting classs should be a compile time improvement. --- llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 12 +++++-- .../CodeGen/RISCV/rvv/callee-saved-regs.ll | 31 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index 7ac73b59f36c..129b4cb4e8cb 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -615,8 +615,16 @@ bool RISCVRegisterInfo::needsFrameBaseReg(MachineInstr *MI, unsigned CalleeSavedSize = 0; for (const MCPhysReg *R = MRI.getCalleeSavedRegs(); MCPhysReg Reg = *R; ++R) { - if (!Subtarget.isRegisterReservedByUser(Reg)) - CalleeSavedSize += getSpillSize(*getMinimalPhysRegClass(Reg)); + if (Subtarget.isRegisterReservedByUser(Reg)) + continue; + + if (RISCV::GPRRegClass.contains(Reg)) + CalleeSavedSize += getSpillSize(RISCV::GPRRegClass); + else if (RISCV::FPR64RegClass.contains(Reg)) + CalleeSavedSize += getSpillSize(RISCV::FPR64RegClass); + else if (RISCV::FPR32RegClass.contains(Reg)) + CalleeSavedSize += getSpillSize(RISCV::FPR32RegClass); + // Ignore vector registers. } int64_t MaxFPOffset = Offset - CalleeSavedSize; diff --git a/llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll b/llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll index 84936d88e187..2177bbfe5b2a 100644 --- a/llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll +++ b/llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll @@ -93,3 +93,34 @@ entry: ret %va } + +; Make sure the local stack allocation pass doesn't count vector registers. The +; sizes are chosen to be on the edge of what RISCVRegister::needsFrameBaseReg +; considers to need a virtual base register. +define riscv_vector_cc void @local_stack_allocation_frame_pointer() "frame-pointer"="all" { +; SPILL-O2-LABEL: local_stack_allocation_frame_pointer: +; SPILL-O2: # %bb.0: +; SPILL-O2-NEXT: addi sp, sp, -2032 +; SPILL-O2-NEXT: .cfi_def_cfa_offset 2032 +; SPILL-O2-NEXT: sw ra, 2028(sp) # 4-byte Folded Spill +; SPILL-O2-NEXT: sw s0, 2024(sp) # 4-byte Folded Spill +; SPILL-O2-NEXT: .cfi_offset ra, -4 +; SPILL-O2-NEXT: .cfi_offset s0, -8 +; SPILL-O2-NEXT: addi s0, sp, 2032 +; SPILL-O2-NEXT: .cfi_def_cfa s0, 0 +; SPILL-O2-NEXT: addi sp, sp, -480 +; SPILL-O2-NEXT: lbu a0, -1912(s0) +; SPILL-O2-NEXT: sb a0, -1912(s0) +; SPILL-O2-NEXT: addi sp, s0, -2048 +; SPILL-O2-NEXT: addi sp, sp, -464 +; SPILL-O2-NEXT: addi sp, sp, 480 +; SPILL-O2-NEXT: lw ra, 2028(sp) # 4-byte Folded Reload +; SPILL-O2-NEXT: lw s0, 2024(sp) # 4-byte Folded Reload +; SPILL-O2-NEXT: addi sp, sp, 2032 +; SPILL-O2-NEXT: ret + %va = alloca [2500 x i8], align 4 + %va_gep = getelementptr [2000 x i8], ptr %va, i64 0, i64 600 + %load = load volatile i8, ptr %va_gep, align 4 + store volatile i8 %load, ptr %va_gep, align 4 + ret void +} -- GitLab From 34de2151e2328db800bcd226f31cb6b0cdcf08bb Mon Sep 17 00:00:00 2001 From: David Green Date: Mon, 13 May 2024 21:58:41 +0100 Subject: [PATCH 132/578] [AArch64][GlobalISel] Improve legalization of G_PTR_ADD (#91763) The testing we have for vector ptradd was a bit lacking. In adding tests this patch found a couple of issues mostly with the way v3 vectors of ptrs were sometimes legalized via i64, and with non-i64 additions. It does not attempt to fix the issue with mergevalues from returning vector ptrs. --- .../CodeGen/GlobalISel/LegalizerHelper.cpp | 7 +- .../AArch64/GISel/AArch64LegalizerInfo.cpp | 5 +- llvm/test/CodeGen/AArch64/ptradd.ll | 221 ++++++++++++++++++ 3 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/ptradd.ll diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 6a76ad7f5db7..40507845d8d8 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -69,8 +69,9 @@ getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy) { unsigned EltSize = OrigTy.getScalarSizeInBits(); if (LeftoverSize % EltSize != 0) return {-1, -1}; - LeftoverTy = LLT::scalarOrVector( - ElementCount::getFixed(LeftoverSize / EltSize), EltSize); + LeftoverTy = + LLT::scalarOrVector(ElementCount::getFixed(LeftoverSize / EltSize), + OrigTy.getElementType()); } else { LeftoverTy = LLT::scalar(LeftoverSize); } @@ -212,7 +213,7 @@ void LegalizerHelper::mergeMixedSubvectors(Register DstReg, appendVectorElts(AllElts, PartRegs[i]); Register Leftover = PartRegs[PartRegs.size() - 1]; - if (MRI.getType(Leftover).isScalar()) + if (!MRI.getType(Leftover).isVector()) AllElts.push_back(Leftover); else appendVectorElts(AllElts, Leftover); diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp index b8274f0f872c..a21be7de6f42 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -177,9 +177,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) getActionDefinitionsBuilder(G_PTR_ADD) .legalFor({{p0, s64}, {v2p0, v2s64}}) - .clampScalar(1, s64, s64) - .clampNumElements(0, v2p0, v2p0) - .clampNumElements(1, v2s64, v2s64); + .clampScalarOrElt(1, s64, s64) + .clampNumElements(0, v2p0, v2p0); getActionDefinitionsBuilder(G_PTRMASK).legalFor({{p0, s64}}); diff --git a/llvm/test/CodeGen/AArch64/ptradd.ll b/llvm/test/CodeGen/AArch64/ptradd.ll new file mode 100644 index 000000000000..107db8723c64 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptradd.ll @@ -0,0 +1,221 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=aarch64-none-eabi | FileCheck %s --check-prefixes=CHECK,CHECK-SD +; RUN: llc < %s -mtriple=aarch64-none-eabi -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI + +; Note: these tests use stores instead of returns as the return handling for +; vector ptrs is currently sometimes create invalid unmerge values. + +define void @vector_gep_i32(ptr %b, i32 %off, ptr %p) { +; CHECK-LABEL: vector_gep_i32: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: add x8, x0, w1, sxtw +; CHECK-NEXT: str x8, [x2] +; CHECK-NEXT: ret +entry: + %g = getelementptr i8, ptr %b, i32 %off + store ptr %g, ptr %p + ret void +} + +define void @vector_gep_i64(ptr %b, i64 %off, ptr %p) { +; CHECK-LABEL: vector_gep_i64: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: add x8, x0, x1 +; CHECK-NEXT: str x8, [x2] +; CHECK-NEXT: ret +entry: + %g = getelementptr i8, ptr %b, i64 %off + store ptr %g, ptr %p + ret void +} + +define void @vector_gep_v1i32(<1 x ptr> %b, <1 x i32> %off, ptr %p) { +; CHECK-SD-LABEL: vector_gep_v1i32: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: shl d1, d1, #32 +; CHECK-SD-NEXT: ssra d0, d1, #32 +; CHECK-SD-NEXT: str d0, [x0] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_gep_v1i32: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: fmov w8, s1 +; CHECK-GI-NEXT: fmov x9, d0 +; CHECK-GI-NEXT: add x8, x9, w8, sxtw +; CHECK-GI-NEXT: str x8, [x0] +; CHECK-GI-NEXT: ret +entry: + %g = getelementptr i8, <1 x ptr> %b, <1 x i32> %off + store <1 x ptr> %g, ptr %p + ret void +} + +define void @vector_gep_v2i32(<2 x ptr> %b, <2 x i32> %off, ptr %p) { +; CHECK-LABEL: vector_gep_v2i32: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: saddw v0.2d, v0.2d, v1.2s +; CHECK-NEXT: str q0, [x0] +; CHECK-NEXT: ret +entry: + %g = getelementptr i8, <2 x ptr> %b, <2 x i32> %off + store <2 x ptr> %g, ptr %p + ret void +} + +define void @vector_gep_v3i32(<3 x ptr> %b, <3 x i32> %off, ptr %p) { +; CHECK-SD-LABEL: vector_gep_v3i32: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-SD-NEXT: // kill: def $d2 killed $d2 def $q2 +; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] +; CHECK-SD-NEXT: saddw2 v2.2d, v2.2d, v3.4s +; CHECK-SD-NEXT: str d2, [x0, #16] +; CHECK-SD-NEXT: saddw v0.2d, v0.2d, v3.2s +; CHECK-SD-NEXT: str q0, [x0] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_gep_v3i32: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: smov x8, v3.s[0] +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: smov x9, v3.s[1] +; CHECK-GI-NEXT: mov s3, v3.s[2] +; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] +; CHECK-GI-NEXT: fmov d1, x8 +; CHECK-GI-NEXT: fmov x8, d2 +; CHECK-GI-NEXT: mov v1.d[1], x9 +; CHECK-GI-NEXT: fmov w9, s3 +; CHECK-GI-NEXT: add x8, x8, w9, sxtw +; CHECK-GI-NEXT: add v0.2d, v0.2d, v1.2d +; CHECK-GI-NEXT: str x8, [x0, #16] +; CHECK-GI-NEXT: str q0, [x0] +; CHECK-GI-NEXT: ret +entry: + %g = getelementptr i8, <3 x ptr> %b, <3 x i32> %off + store <3 x ptr> %g, ptr %p + ret void +} + +define void @vector_gep_v4i32(<4 x ptr> %b, <4 x i32> %off, ptr %p) { +; CHECK-SD-LABEL: vector_gep_v4i32: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: saddw2 v1.2d, v1.2d, v2.4s +; CHECK-SD-NEXT: saddw v0.2d, v0.2d, v2.2s +; CHECK-SD-NEXT: stp q0, q1, [x0] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_gep_v4i32: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: saddw v0.2d, v0.2d, v2.2s +; CHECK-GI-NEXT: saddw2 v1.2d, v1.2d, v2.4s +; CHECK-GI-NEXT: stp q0, q1, [x0] +; CHECK-GI-NEXT: ret +entry: + %g = getelementptr i8, <4 x ptr> %b, <4 x i32> %off + store <4 x ptr> %g, ptr %p + ret void +} + +define void @vector_gep_v1i64(<1 x ptr> %b, <1 x i64> %off, ptr %p) { +; CHECK-SD-LABEL: vector_gep_v1i64: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: add d0, d0, d1 +; CHECK-SD-NEXT: str d0, [x0] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_gep_v1i64: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: fmov x8, d0 +; CHECK-GI-NEXT: fmov x9, d1 +; CHECK-GI-NEXT: add x8, x8, x9 +; CHECK-GI-NEXT: str x8, [x0] +; CHECK-GI-NEXT: ret +entry: + %g = getelementptr i8, <1 x ptr> %b, <1 x i64> %off + store <1 x ptr> %g, ptr %p + ret void +} + +define void @vector_gep_v2i64(<2 x ptr> %b, <2 x i64> %off, ptr %p) { +; CHECK-LABEL: vector_gep_v2i64: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: add v0.2d, v0.2d, v1.2d +; CHECK-NEXT: str q0, [x0] +; CHECK-NEXT: ret +entry: + %g = getelementptr i8, <2 x ptr> %b, <2 x i64> %off + store <2 x ptr> %g, ptr %p + ret void +} + +define void @vector_gep_v3i64(<3 x ptr> %b, <3 x i64> %off, ptr %p) { +; CHECK-SD-LABEL: vector_gep_v3i64: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: // kill: def $d3 killed $d3 def $q3 +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-SD-NEXT: // kill: def $d4 killed $d4 def $q4 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-SD-NEXT: mov v3.d[1], v4.d[0] +; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] +; CHECK-SD-NEXT: add d1, d2, d5 +; CHECK-SD-NEXT: str d1, [x0, #16] +; CHECK-SD-NEXT: add v0.2d, v0.2d, v3.2d +; CHECK-SD-NEXT: str q0, [x0] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_gep_v3i64: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: // kill: def $d3 killed $d3 def $q3 +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: // kill: def $d4 killed $d4 def $q4 +; CHECK-GI-NEXT: fmov x8, d2 +; CHECK-GI-NEXT: fmov x9, d5 +; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] +; CHECK-GI-NEXT: mov v3.d[1], v4.d[0] +; CHECK-GI-NEXT: add x8, x8, x9 +; CHECK-GI-NEXT: str x8, [x0, #16] +; CHECK-GI-NEXT: add v0.2d, v0.2d, v3.2d +; CHECK-GI-NEXT: str q0, [x0] +; CHECK-GI-NEXT: ret +entry: + %g = getelementptr i8, <3 x ptr> %b, <3 x i64> %off + store <3 x ptr> %g, ptr %p + ret void +} + +define void @vector_gep_v4i64(<4 x ptr> %b, <4 x i64> %off, ptr %p) { +; CHECK-SD-LABEL: vector_gep_v4i64: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: add v1.2d, v1.2d, v3.2d +; CHECK-SD-NEXT: add v0.2d, v0.2d, v2.2d +; CHECK-SD-NEXT: stp q0, q1, [x0] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_gep_v4i64: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: add v0.2d, v0.2d, v2.2d +; CHECK-GI-NEXT: add v1.2d, v1.2d, v3.2d +; CHECK-GI-NEXT: stp q0, q1, [x0] +; CHECK-GI-NEXT: ret +entry: + %g = getelementptr i8, <4 x ptr> %b, <4 x i64> %off + store <4 x ptr> %g, ptr %p + ret void +} + +define void @vector_gep_v4i128(<2 x ptr> %b, <2 x i128> %off, ptr %p) { +; CHECK-LABEL: vector_gep_v4i128: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: fmov d1, x0 +; CHECK-NEXT: mov v1.d[1], x2 +; CHECK-NEXT: add v0.2d, v0.2d, v1.2d +; CHECK-NEXT: str q0, [x4] +; CHECK-NEXT: ret +entry: + %g = getelementptr i8, <2 x ptr> %b, <2 x i128> %off + store <2 x ptr> %g, ptr %p + ret void +} -- GitLab From ef9090fcb5b8d1c9f56c11d567987ffa1000a486 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 13 May 2024 14:01:00 -0700 Subject: [PATCH 133/578] [test] Fix check prefixes --- .../AArch64/vec3-loads-ext-trunc-stores.ll | 36 ------------------- .../test/CodeGen/NVPTX/global-variable-big.ll | 5 +-- .../MemorySanitizer/X86/msan_x86_bts_asm.ll | 5 --- .../first-order-recurrence-complex.ll | 4 --- 4 files changed, 1 insertion(+), 49 deletions(-) diff --git a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll index 71d55df66517..66c884e95fa4 100644 --- a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll +++ b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll @@ -217,42 +217,6 @@ define <4 x i32> @load_v3i8_to_4xi32_const_offset_3(ptr %src) { } define <4 x i32> @volatile_load_v3i8_to_4xi32(ptr %src) { -; check-label: volatile_load_v3i8_to_4xi32: -; check: ; %bb.0: -; check-next: sub sp, sp, #16 -; check-next: .cfi_def_cfa_offset 16 -; check-next: ldrh w8, [x0] -; check-next: movi.2d v1, #0x0000ff000000ff -; check-next: strh w8, [sp, #12] -; check-next: ldr s0, [sp, #12] -; check-next: ldrsb w8, [x0, #2] -; check-next: ushll.8h v0, v0, #0 -; check-next: mov.h v0[1], v0[1] -; check-next: mov.h v0[2], w8 -; check-next: ushll.4s v0, v0, #0 -; check-next: and.16b v0, v0, v1 -; check-next: add sp, sp, #16 -; check-next: ret -; -; be-label: volatile_load_v3i8_to_4xi32: -; be: // %bb.0: -; be-next: sub sp, sp, #16 -; be-next: .cfi_def_cfa_offset 16 -; be-next: ldrh w8, [x0] -; be-next: movi v1.2d, #0x0000ff000000ff -; be-next: strh w8, [sp, #12] -; be-next: ldr s0, [sp, #12] -; be-next: ldrsb w8, [x0, #2] -; be-next: rev32 v0.8b, v0.8b -; be-next: ushll v0.8h, v0.8b, #0 -; be-next: mov v0.h[1], v0.h[1] -; be-next: mov v0.h[2], w8 -; be-next: ushll v0.4s, v0.4h, #0 -; be-next: and v0.16b, v0.16b, v1.16b -; be-next: rev64 v0.4s, v0.4s -; be-next: ext v0.16b, v0.16b, v0.16b, #8 -; be-next: add sp, sp, #16 -; be-next: ret ; CHECK-LABEL: volatile_load_v3i8_to_4xi32: ; CHECK: ; %bb.0: ; CHECK-NEXT: sub sp, sp, #16 diff --git a/llvm/test/CodeGen/NVPTX/global-variable-big.ll b/llvm/test/CodeGen/NVPTX/global-variable-big.ll index f4194df4434d..e8d7fb3815b7 100644 --- a/llvm/test/CodeGen/NVPTX/global-variable-big.ll +++ b/llvm/test/CodeGen/NVPTX/global-variable-big.ll @@ -11,8 +11,5 @@ target triple = "nvptx64-nvidia-cuda" ; CHECK: .visible .global .align 16 .b8 gv[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; ; Make sure that we do not overflow on large number of elements. -; CHECK-LABEL large_data -; CHECK: .visible .global .align 1 .b8 large_data[4831838208] +; CHECK: .visible .global .align 1 .b8 large_data[4831838208]; @large_data = global [4831838208 x i8] zeroinitializer - - diff --git a/llvm/test/Instrumentation/MemorySanitizer/X86/msan_x86_bts_asm.ll b/llvm/test/Instrumentation/MemorySanitizer/X86/msan_x86_bts_asm.ll index 5eeba197c763..dd2fecb081be 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/X86/msan_x86_bts_asm.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/X86/msan_x86_bts_asm.ll @@ -73,11 +73,6 @@ if.else: ; preds = %entry ; CHECK: call void asm "btsq $2, $1; setc $0" -; Calculating the shadow offset of %bit. -; CHECKz: [[PTR:%.*]] = ptrtoint {{.*}} %bit to i64 -; CHECKz: [[SH_NUM:%.*]] = xor i64 [[PTR]] -; CHECKz: [[SHADOW:%.*]] = inttoptr i64 [[SH_NUM]] {{.*}} - ; CHECK: [[META:%.*]] = call {{.*}} @__msan_metadata_ptr_for_load_1(ptr %bit) ; CHECK: [[SHADOW:%.*]] = extractvalue { ptr, ptr } [[META]], 0 diff --git a/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll b/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll index 95671078a776..149e4705885b 100644 --- a/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll +++ b/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll @@ -332,10 +332,6 @@ define void @cannot_sink_reduction(i32 %x, ptr %ptr, i64 %tc) { ; CHECK: exit: ; CHECK-NEXT: ret void ; - - - -; CHECK-NET: ret void entry: br label %preheader -- GitLab From 70e227a404e51f9248c7ad5d79953805b2afacb4 Mon Sep 17 00:00:00 2001 From: Aart Bik Date: Mon, 13 May 2024 14:02:29 -0700 Subject: [PATCH 134/578] [mlir][sparse] recognize ReLu operation during sparsification (#92016) This is a proof of concept recognition of the most basic forms of ReLu operations, used to show-case sparsification of end-to-end PyTorch models. In the long run, we must avoid lowering such constructs too early (with this need for raising them back). See discussion at https://discourse.llvm.org/t/min-max-abs-relu-recognition-starter-project/78918 --- .../mlir/Dialect/SparseTensor/Utils/Merger.h | 3 +- .../lib/Dialect/SparseTensor/Utils/Merger.cpp | 100 ++++++++++++++++-- .../Dialect/SparseTensor/sparse_relu.mlir | 34 ++++++ .../Dialect/SparseTensor/MergerTest.cpp | 1 + 4 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 mlir/test/Dialect/SparseTensor/sparse_relu.mlir diff --git a/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h b/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h index 7f9820df984b..b8d278152dc0 100644 --- a/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h +++ b/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h @@ -144,6 +144,7 @@ enum class TensorExp::Kind { kExpm1C, kLog1pF, kLog1pC, + kRelu, kSinF, kSinC, kTanhF, @@ -316,7 +317,7 @@ public: /// lattice point on an expression E is simply copied over, but with OP E /// as new expression. Returns the identifier of the new set. LatSetId mapSet(TensorExp::Kind kind, LatSetId s, Value v = Value(), - Operation *op = nullptr); + Operation *op = nullptr, Attribute attr = nullptr); /// Maps the binary operator to the same operation but with one of its operand /// set to zero, i.e. each lattice point on an expression E is simply copied diff --git a/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp b/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp index 308fbd965259..0258f797143c 100644 --- a/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp +++ b/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp @@ -44,6 +44,7 @@ static ExpArity getExpArity(TensorExp::Kind k) { case TensorExp::Kind::kExpm1C: case TensorExp::Kind::kLog1pF: case TensorExp::Kind::kLog1pC: + case TensorExp::Kind::kRelu: case TensorExp::Kind::kSinF: case TensorExp::Kind::kSinC: case TensorExp::Kind::kTanhF: @@ -104,7 +105,7 @@ static ExpArity getExpArity(TensorExp::Kind k) { TensorExp::TensorExp(TensorExp::Kind k, unsigned x, ExprId y, Value v, Operation *o, Attribute a) - : kind(k), val(v), op(o) { + : kind(k), val(v), op(o), attr(a) { switch (kind) { // Leaf. case TensorExp::Kind::kTensor: @@ -133,6 +134,7 @@ TensorExp::TensorExp(TensorExp::Kind k, unsigned x, ExprId y, Value v, case TensorExp::Kind::kExpm1C: case TensorExp::Kind::kLog1pF: case TensorExp::Kind::kLog1pC: + case TensorExp::Kind::kRelu: case TensorExp::Kind::kSinF: case TensorExp::Kind::kSinC: case TensorExp::Kind::kTanhF: @@ -201,7 +203,6 @@ TensorExp::TensorExp(TensorExp::Kind k, unsigned x, ExprId y, Value v, case TensorExp::Kind::kCmpF: case TensorExp::Kind::kCmpI: assert(x != detail::kInvalidId && y != detail::kInvalidId && !v && !o); - attr = a; children.e0 = x; children.e1 = y; return; @@ -337,7 +338,6 @@ LatSetId Merger::conjSet(ExprId e, LatSetId s0, LatSetId s1, Operation *op) { LatSetId Merger::disjSet(ExprId e, LatSetId s0, LatSetId s1, Operation *op) { const LatSetId sNew = conjSet(e, s0, s1, op); TensorExp::Kind kind = exp(e).kind; - // Followed by all in s0. latSets[sNew].append(latSets[s0]); // Map binary 0-y to unary -y. @@ -381,31 +381,32 @@ LatSetId Merger::combiSet(ExprId e, LatSetId s0, LatSetId s1, Operation *orig, bool includeLeft, TensorExp::Kind ltrans, Operation *opleft, bool includeRight, TensorExp::Kind rtrans, Operation *opright) { + Attribute a = exp(e).attr; const LatSetId sNew = conjSet(e, s0, s1, orig); // Left Region. if (includeLeft) { if (opleft) - s0 = mapSet(ltrans, s0, Value(), opleft); + s0 = mapSet(ltrans, s0, Value(), opleft, a); latSets[sNew].append(latSets[s0]); } // Right Region. if (includeRight) { if (opright) - s1 = mapSet(rtrans, s1, Value(), opright); + s1 = mapSet(rtrans, s1, Value(), opright, a); latSets[sNew].append(latSets[s1]); } return sNew; } LatSetId Merger::mapSet(TensorExp::Kind kind, LatSetId s0, Value v, - Operation *op) { + Operation *op, Attribute a) { assert((TensorExp::Kind::kAbsF <= kind && kind <= TensorExp::Kind::kSelect) || TensorExp::Kind::kDenseOp == kind); const LatSetId sNew = addSet(); auto &setNew = latSets[sNew]; for (const LatPointId p : set(s0)) { const auto &point = latPoints[p]; - setNew.push_back(addLat(point.bits, addExp(kind, point.exp, v, op))); + setNew.push_back(addLat(point.bits, addExp(kind, point.exp, v, op, a))); } return sNew; } @@ -596,6 +597,7 @@ bool Merger::isSingleCondition(TensorId t, ExprId e) const { case TensorExp::Kind::kExpm1C: case TensorExp::Kind::kLog1pF: case TensorExp::Kind::kLog1pC: + case TensorExp::Kind::kRelu: case TensorExp::Kind::kSinF: case TensorExp::Kind::kSinC: case TensorExp::Kind::kTanhF: @@ -717,6 +719,8 @@ static const char *kindToOpSymbol(TensorExp::Kind kind) { case TensorExp::Kind::kLog1pF: case TensorExp::Kind::kLog1pC: return "log1p"; + case TensorExp::Kind::kRelu: + return "relu"; case TensorExp::Kind::kSinF: case TensorExp::Kind::kSinC: return "sin"; @@ -824,6 +828,7 @@ void Merger::dumpExp(ExprId e) const { case TensorExp::Kind::kExpm1C: case TensorExp::Kind::kLog1pF: case TensorExp::Kind::kLog1pC: + case TensorExp::Kind::kRelu: case TensorExp::Kind::kSinF: case TensorExp::Kind::kSinC: case TensorExp::Kind::kTanhF: @@ -972,6 +977,7 @@ LatSetId Merger::buildLattices(ExprId e, LoopId i) { case TensorExp::Kind::kExpm1C: case TensorExp::Kind::kLog1pF: case TensorExp::Kind::kLog1pC: + case TensorExp::Kind::kRelu: case TensorExp::Kind::kSinF: case TensorExp::Kind::kSinC: case TensorExp::Kind::kTanhF: @@ -1001,7 +1007,8 @@ LatSetId Merger::buildLattices(ExprId e, LoopId i) { { const ExprId e0 = expr.children.e0; const Value v = expr.val; - return mapSet(kind, buildLattices(e0, i), v); + Attribute a = expr.attr; + return mapSet(kind, buildLattices(e0, i), v, nullptr, a); } case TensorExp::Kind::kBinaryBranch: case TensorExp::Kind::kSelect: @@ -1190,10 +1197,26 @@ std::optional Merger::buildTensorExpFromLinalg(linalg::GenericOp op) { return buildTensorExp(op, yield->getOperand(0)).first; } +/// Only returns true if we are certain this is a zero. +static bool isCertainZero(Value val) { + if (auto c = val.getDefiningOp()) { + ArrayAttr arrayAttr = c.getValue(); + return cast(arrayAttr[0]).getValue().isZero() && + cast(arrayAttr[1]).getValue().isZero(); + } + if (auto c = val.getDefiningOp()) + return c.value() == 0; + if (auto c = val.getDefiningOp()) + return c.value().isZero(); + return false; +} + /// Only returns false if we are certain this is a nonzero. bool Merger::maybeZero(ExprId e) const { const auto &expr = exp(e); if (expr.kind == TensorExp::Kind::kInvariant) { + // Note that this is different from isCertainZero() in a subtle + // way by always returning true for non-constants. if (auto c = expr.val.getDefiningOp()) { ArrayAttr arrayAttr = c.getValue(); return cast(arrayAttr[0]).getValue().isZero() && @@ -1247,6 +1270,21 @@ static bool isAdmissibleBranch(Operation *op, Region ®ion) { return isAdmissibleBranchExp(op, ®ion.front(), yield->getOperand(0)); } +// Recognizes a direct GT comparison. +static bool isGreater(TensorExp::Kind kind, Attribute attr) { + if (kind == TensorExp::Kind::kCmpI) { + auto pred = llvm::cast(attr).getValue(); + return pred == arith::CmpIPredicate::ugt || + pred == arith::CmpIPredicate::sgt; + } + if (kind == TensorExp::Kind::kCmpF) { + auto pred = llvm::cast(attr).getValue(); + return pred == arith::CmpFPredicate::UGT || + pred == arith::CmpFPredicate::OGT; + } + return false; +} + std::pair, bool> Merger::buildTensorExp(linalg::GenericOp op, Value v) { // Recursion leaves. @@ -1266,6 +1304,7 @@ Merger::buildTensorExp(linalg::GenericOp op, Value v) { // or belonging to an enveloping op) is considered invariant. return {addInvariantExp(v), /*hasSpDep=*/false}; } + // Something defined outside is invariant. Operation *def = v.getDefiningOp(); if (def->getBlock() != &op.getRegion().front()) @@ -1352,6 +1391,7 @@ Merger::buildTensorExp(linalg::GenericOp op, Value v) { } } } + // Construct binary operations if subexpressions can be built. // See buildLattices() for an explanation of rejecting certain // division and shift operations. @@ -1447,6 +1487,7 @@ Merger::buildTensorExp(linalg::GenericOp op, Value v) { } } } + // Construct ternary operations if subexpressions can be built. if (def->getNumOperands() == 3) { const auto [x, xDepSp] = buildTensorExp(op, def->getOperand(0)); @@ -1460,6 +1501,26 @@ Merger::buildTensorExp(linalg::GenericOp op, Value v) { if (isAdmissibleBranch(redop, redop.getRegion())) return {addExp(TensorExp::Kind::kReduce, e0, e1, def), hasSpDep}; } + if (auto selop = dyn_cast(def)) { + // Recognize an integral or floating-point ReLu(x) = Max(x, 0) + // operation inside a very specific ternary select operation. + // TODO: capture MIN/MAX/ABS/RELU structure in a more generic way + const auto &cnd = exp(*x); + if (isGreater(cnd.kind, cnd.attr) && + exp(*y).kind == TensorExp::Kind::kTensor && + exp(*z).kind == TensorExp::Kind::kInvariant && + isCertainZero(exp(*z).val)) { + const auto &a = exp(cnd.children.e0); + const auto &b = exp(cnd.children.e1); + if (a.kind == TensorExp::Kind::kTensor && + a.tensor == exp(*y).tensor && + b.kind == TensorExp::Kind::kInvariant && isCertainZero(b.val)) { + return {addExp(TensorExp::Kind::kRelu, *y, detail::kInvalidId, + nullptr, cnd.attr), + yDepSp}; + } + } + } } } @@ -1469,7 +1530,6 @@ Merger::buildTensorExp(linalg::GenericOp op, Value v) { // tensors). if (def->getNumResults() != 1) // only handle single result operation. return {std::nullopt, false}; - SmallVector, bool>, 2> subExp; // Builds all the sub-expressions for (Value operand : def->getOperands()) @@ -1489,6 +1549,7 @@ Merger::buildTensorExp(linalg::GenericOp op, Value v) { return {e, false}; } } + // Cannot build. return {std::nullopt, false}; } @@ -1538,6 +1599,22 @@ static Value buildBinaryOverlap(RewriterBase &rewriter, Location loc, return insertYieldOp(rewriter, loc, overlapRegion, {v0, v1}); } +static Value buildRelu(RewriterBase &rewriter, Location loc, Value v0, + Attribute attr) { + Type tp = v0.getType(); + auto zero = + rewriter.create(loc, tp, rewriter.getZeroAttr(tp)); + Value cmp; + if (isa(tp)) { + auto pred = llvm::cast(attr); + cmp = rewriter.create(loc, pred, v0, zero); + } else { + auto pred = llvm::cast(attr); + cmp = rewriter.create(loc, pred, v0, zero); + } + return rewriter.create(loc, cmp, v0, zero); +} + Value Merger::buildExp(RewriterBase &rewriter, Location loc, ExprId e, Value v0, Value v1) const { const auto &expr = exp(e); @@ -1574,6 +1651,8 @@ Value Merger::buildExp(RewriterBase &rewriter, Location loc, ExprId e, Value v0, return rewriter.create(loc, v0); case TensorExp::Kind::kLog1pC: return rewriter.create(loc, v0); + case TensorExp::Kind::kRelu: + return buildRelu(rewriter, loc, v0, expr.attr); case TensorExp::Kind::kSinF: return rewriter.create(loc, v0); case TensorExp::Kind::kSinC: @@ -1677,7 +1756,8 @@ Value Merger::buildExp(RewriterBase &rewriter, Location loc, ExprId e, Value v0, case TensorExp::Kind::kUnary: return buildUnaryPresent(rewriter, loc, expr.op, v0); case TensorExp::Kind::kSelect: - return insertYieldOp(rewriter, loc, cast(expr.op).getRegion(), + return insertYieldOp(rewriter, loc, + cast(expr.op).getRegion(), {v0}); case TensorExp::Kind::kBinary: return buildBinaryOverlap(rewriter, loc, expr.op, v0, v1); diff --git a/mlir/test/Dialect/SparseTensor/sparse_relu.mlir b/mlir/test/Dialect/SparseTensor/sparse_relu.mlir new file mode 100644 index 000000000000..25f0c790b43d --- /dev/null +++ b/mlir/test/Dialect/SparseTensor/sparse_relu.mlir @@ -0,0 +1,34 @@ +// RUN: mlir-opt %s --sparsification-and-bufferization | FileCheck %s + +#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)> + +#sparse = #sparse_tensor.encoding<{ + map = (d0, d1, d2) -> (d0 : dense, d1 : dense, d2 : compressed) +}> + +// +// Make sure a simple ReLU passes the sparsifier +// +// CHECK-LABEL: func.func @relu +// CHECK: scf.for +// CHECK: scf.for +// CHECK: scf.for +// CHECK: arith.cmpf ugt +// CHECK: arith.select +// +func.func @relu(%arg0: tensor<10x20x30xf64, #sparse>) -> tensor<10x20x30xf64, #sparse> { + %cst = arith.constant 0.000000e+00 : f64 + %0 = tensor.empty() : tensor<10x20x30xf64> + %1 = linalg.generic { + indexing_maps = [#map, #map], + iterator_types = ["parallel", "parallel", "parallel"]} + ins(%arg0 : tensor<10x20x30xf64, #sparse>) + outs(%0 : tensor<10x20x30xf64>) { + ^bb0(%in: f64, %out: f64): + %2 = arith.cmpf ugt, %in, %cst : f64 + %3 = arith.select %2, %in, %cst : f64 + linalg.yield %3 : f64 + } -> tensor<10x20x30xf64> + %cast = tensor.cast %1 : tensor<10x20x30xf64> to tensor<10x20x30xf64, #sparse> + return %cast : tensor<10x20x30xf64, #sparse> +} diff --git a/mlir/unittests/Dialect/SparseTensor/MergerTest.cpp b/mlir/unittests/Dialect/SparseTensor/MergerTest.cpp index 943e7d5c120b..abc6c7076694 100644 --- a/mlir/unittests/Dialect/SparseTensor/MergerTest.cpp +++ b/mlir/unittests/Dialect/SparseTensor/MergerTest.cpp @@ -236,6 +236,7 @@ protected: case TensorExp::Kind::kExpm1C: case TensorExp::Kind::kLog1pF: case TensorExp::Kind::kLog1pC: + case TensorExp::Kind::kRelu: case TensorExp::Kind::kSinF: case TensorExp::Kind::kSinC: case TensorExp::Kind::kTanhF: -- GitLab From 4ecf2caf687014a63f0434a63fe9a522ec9be445 Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Mon, 13 May 2024 14:23:32 -0700 Subject: [PATCH 135/578] [BOLT] Use aggregated FuncBranchData in writeBATYAML Switch from FuncBranchData intermediate maps (Intra/InterIndex) to aggregated Data, same as one used by DataReader: https://github.com/llvm/llvm-project/blob/e62ce1f8842cca36eb14126d79dcca0a85bf6d36/bolt/lib/Profile/DataReader.cpp#L385-L389 This aligns the order of the output between YAMLProfileWriter and writeBATYAML. Test Plan: updated bolt-address-translation-yaml.test Reviewers: rafaelauler, dcci, ayermolo, maksfb Reviewed By: ayermolo, maksfb Pull Request: https://github.com/llvm/llvm-project/pull/91289 --- bolt/lib/Profile/DataAggregator.cpp | 63 ++++++------------- .../Inputs/blarge_new_bat_order.preagg.txt | 2 + .../X86/bolt-address-translation-yaml.test | 11 ++++ 3 files changed, 33 insertions(+), 43 deletions(-) create mode 100644 bolt/test/X86/Inputs/blarge_new_bat_order.preagg.txt diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index 302bcf1f2d87..167899ccba12 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -2355,30 +2355,6 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC, for (auto BI = BlockMap.begin(), BE = BlockMap.end(); BI != BE; ++BI) YamlBF.Blocks[BI->second.getBBIndex()].Hash = BI->second.getBBHash(); - auto getSuccessorInfo = [&](uint32_t SuccOffset, unsigned SuccDataIdx) { - const llvm::bolt::BranchInfo &BI = Branches.Data.at(SuccDataIdx); - yaml::bolt::SuccessorInfo SI; - SI.Index = BlockMap.getBBIndex(SuccOffset); - SI.Count = BI.Branches; - SI.Mispreds = BI.Mispreds; - return SI; - }; - - auto getCallSiteInfo = [&](Location CallToLoc, unsigned CallToIdx, - uint32_t Offset) { - const llvm::bolt::BranchInfo &BI = Branches.Data.at(CallToIdx); - yaml::bolt::CallSiteInfo CSI; - CSI.DestId = 0; // designated for unknown functions - CSI.EntryDiscriminator = 0; - CSI.Count = BI.Branches; - CSI.Mispreds = BI.Mispreds; - CSI.Offset = Offset; - if (BinaryData *BD = BC.getBinaryDataByName(CallToLoc.Name)) - YAMLProfileWriter::setCSIDestination(BC, CSI, BD->getSymbol(), BAT, - CallToLoc.Offset); - return CSI; - }; - // Lookup containing basic block offset and index auto getBlock = [&BlockMap](uint32_t Offset) { auto BlockIt = BlockMap.upper_bound(Offset); @@ -2390,25 +2366,26 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC, return std::pair(BlockIt->first, BlockIt->second.getBBIndex()); }; - for (const auto &[FromOffset, SuccKV] : Branches.IntraIndex) { - const auto &[_, Index] = getBlock(FromOffset); - yaml::bolt::BinaryBasicBlockProfile &YamlBB = YamlBF.Blocks[Index]; - for (const auto &[SuccOffset, SuccDataIdx] : SuccKV) - if (BlockMap.isInputBlock(SuccOffset)) - YamlBB.Successors.emplace_back( - getSuccessorInfo(SuccOffset, SuccDataIdx)); - } - for (const auto &[FromOffset, CallTo] : Branches.InterIndex) { - const auto &[BlockOffset, BlockIndex] = getBlock(FromOffset); - yaml::bolt::BinaryBasicBlockProfile &YamlBB = YamlBF.Blocks[BlockIndex]; - const uint32_t Offset = FromOffset - BlockOffset; - for (const auto &[CallToLoc, CallToIdx] : CallTo) - YamlBB.CallSites.emplace_back( - getCallSiteInfo(CallToLoc, CallToIdx, Offset)); - llvm::sort(YamlBB.CallSites, [](yaml::bolt::CallSiteInfo &A, - yaml::bolt::CallSiteInfo &B) { - return A.Offset < B.Offset; - }); + for (const llvm::bolt::BranchInfo &BI : Branches.Data) { + using namespace yaml::bolt; + const auto &[BlockOffset, BlockIndex] = getBlock(BI.From.Offset); + BinaryBasicBlockProfile &YamlBB = YamlBF.Blocks[BlockIndex]; + if (BI.To.IsSymbol && BI.To.Name == BI.From.Name && BI.To.Offset != 0) { + // Internal branch + const unsigned SuccIndex = getBlock(BI.To.Offset).second; + auto &SI = YamlBB.Successors.emplace_back(SuccessorInfo{SuccIndex}); + SI.Count = BI.Branches; + SI.Mispreds = BI.Mispreds; + } else { + // Call + const uint32_t Offset = BI.From.Offset - BlockOffset; + auto &CSI = YamlBB.CallSites.emplace_back(CallSiteInfo{Offset}); + CSI.Count = BI.Branches; + CSI.Mispreds = BI.Mispreds; + if (const BinaryData *BD = BC.getBinaryDataByName(BI.To.Name)) + YAMLProfileWriter::setCSIDestination(BC, CSI, BD->getSymbol(), BAT, + BI.To.Offset); + } } // Set entry counts, similar to DataReader::readProfile. for (const llvm::bolt::BranchInfo &BI : Branches.EntryData) { diff --git a/bolt/test/X86/Inputs/blarge_new_bat_order.preagg.txt b/bolt/test/X86/Inputs/blarge_new_bat_order.preagg.txt new file mode 100644 index 000000000000..e4e1f170343c --- /dev/null +++ b/bolt/test/X86/Inputs/blarge_new_bat_order.preagg.txt @@ -0,0 +1,2 @@ +B 800154 401050 20 0 +F 800159 800193 7 diff --git a/bolt/test/X86/bolt-address-translation-yaml.test b/bolt/test/X86/bolt-address-translation-yaml.test index c15d6ce15ed0..e21513b7dfe5 100644 --- a/bolt/test/X86/bolt-address-translation-yaml.test +++ b/bolt/test/X86/bolt-address-translation-yaml.test @@ -15,6 +15,17 @@ BRANCHENTRY-YAML-CHECK: - name: SolveCubic BRANCHENTRY-YAML-CHECK: bid: 0 BRANCHENTRY-YAML-CHECK: hash: 0x700F19D24600000 BRANCHENTRY-YAML-CHECK-NEXT: succ: [ { bid: 7, cnt: 1 } +# Check that the order is correct between BAT YAML and FDATA->YAML. +RUN: perf2bolt %t.out --pa -p %p/Inputs/blarge_new_bat_order.preagg.txt \ +RUN: -w %t.yaml -o %t.fdata +RUN: llvm-bolt %t.exe -data %t.fdata -w %t.yaml-fdata -o %t.null +RUN: FileCheck --input-file %t.yaml --check-prefix ORDER-YAML-CHECK %s +RUN: FileCheck --input-file %t.yaml-fdata --check-prefix ORDER-YAML-CHECK %s +ORDER-YAML-CHECK: - name: SolveCubic +ORDER-YAML-CHECK: bid: 3 +ORDER-YAML-CHECK: hash: 0xDDA1DC5F69F900AC +ORDER-YAML-CHECK-NEXT: calls: [ { off: 0x26, fid: [[#]], cnt: 20 } ] +ORDER-YAML-CHECK-NEXT: succ: [ { bid: 5, cnt: 7 } # Large profile test RUN: perf2bolt %t.out --pa -p %p/Inputs/blarge_new_bat.preagg.txt -w %t.yaml -o %t.fdata \ RUN: 2>&1 | FileCheck --check-prefix READ-BAT-CHECK %s -- GitLab From efc7bbb917428393f543b09eecddf6e4bb5fce08 Mon Sep 17 00:00:00 2001 From: Stanislav Mekhanoshin Date: Mon, 13 May 2024 14:53:26 -0700 Subject: [PATCH 136/578] [AMDGPU] Make v2bf16 BUILD_VECTOR legal (#92022) There is nothing specific here and it is not different from i16 or f16. --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 8 +- llvm/lib/Target/AMDGPU/SIInstructions.td | 4 +- llvm/test/CodeGen/AMDGPU/bf16-conversions.ll | 6 +- .../AMDGPU/insert_vector_elt.v2bf16.ll | 1690 +++++++++++++++++ 4 files changed, 1698 insertions(+), 10 deletions(-) create mode 100644 llvm/test/CodeGen/AMDGPU/insert_vector_elt.v2bf16.ll diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 0a3a56e9b3a0..8645f560d997 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -233,9 +233,6 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM, // sources. setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); - - setOperationAction(ISD::BUILD_VECTOR, MVT::v2bf16, Promote); - AddPromotedToType(ISD::BUILD_VECTOR, MVT::v2bf16, MVT::v2i16); } setTruncStoreAction(MVT::v2i32, MVT::v2i16, Expand); @@ -744,9 +741,8 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM, setOperationAction({ISD::ANY_EXTEND, ISD::ZERO_EXTEND, ISD::SIGN_EXTEND}, MVT::v8i32, Expand); - if (!Subtarget->hasVOP3PInsts()) - setOperationAction(ISD::BUILD_VECTOR, - {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Custom); + setOperationAction(ISD::BUILD_VECTOR, {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, + Subtarget->hasVOP3PInsts() ? Legal : Custom); setOperationAction(ISD::FNEG, MVT::v2f16, Legal); // This isn't really legal, but this avoids the legalizer unrolling it (and diff --git a/llvm/lib/Target/AMDGPU/SIInstructions.td b/llvm/lib/Target/AMDGPU/SIInstructions.td index f9e811f54d05..e7aeaa017306 100644 --- a/llvm/lib/Target/AMDGPU/SIInstructions.td +++ b/llvm/lib/Target/AMDGPU/SIInstructions.td @@ -3166,7 +3166,7 @@ def : GCNPat < (v2f16 (V_AND_B32_e64 (i32 (V_MOV_B32_e32 (i32 0xffff))), VGPR_32:$src1)) >; -foreach vecTy = [v2i16, v2f16] in { +foreach vecTy = [v2i16, v2f16, v2bf16] in { defvar Ty = vecTy.ElementType; @@ -3212,7 +3212,7 @@ def : GCNPat < >; -foreach vecTy = [v2i16, v2f16] in { +foreach vecTy = [v2i16, v2f16, v2bf16] in { defvar Ty = vecTy.ElementType; defvar immzeroTy = !if(!eq(Ty, i16), immzero, fpimmzero); diff --git a/llvm/test/CodeGen/AMDGPU/bf16-conversions.ll b/llvm/test/CodeGen/AMDGPU/bf16-conversions.ll index 7108f3d65768..1c9f35dd45fe 100644 --- a/llvm/test/CodeGen/AMDGPU/bf16-conversions.ll +++ b/llvm/test/CodeGen/AMDGPU/bf16-conversions.ll @@ -55,7 +55,8 @@ define amdgpu_ps float @v_test_cvt_v2f32_v2bf16_s(<2 x float> inreg %src) { ; GCN-NEXT: s_add_i32 s5, s2, 0x7fff ; GCN-NEXT: v_cmp_u_f32_e64 s[2:3], s1, s1 ; GCN-NEXT: s_and_b64 s[2:3], s[2:3], exec -; GCN-NEXT: s_cselect_b32 s2, s4, s5 +; GCN-NEXT: s_cselect_b32 s1, s4, s5 +; GCN-NEXT: s_lshr_b32 s2, s1, 16 ; GCN-NEXT: s_bfe_u32 s1, s0, 0x10010 ; GCN-NEXT: s_add_i32 s1, s1, s0 ; GCN-NEXT: s_or_b32 s3, s0, 0x400000 @@ -63,7 +64,8 @@ define amdgpu_ps float @v_test_cvt_v2f32_v2bf16_s(<2 x float> inreg %src) { ; GCN-NEXT: v_cmp_u_f32_e64 s[0:1], s0, s0 ; GCN-NEXT: s_and_b64 s[0:1], s[0:1], exec ; GCN-NEXT: s_cselect_b32 s0, s3, s4 -; GCN-NEXT: s_pack_hh_b32_b16 s0, s0, s2 +; GCN-NEXT: s_lshr_b32 s0, s0, 16 +; GCN-NEXT: s_pack_ll_b32_b16 s0, s0, s2 ; GCN-NEXT: v_mov_b32_e32 v0, s0 ; GCN-NEXT: ; return to shader part epilog %res = fptrunc <2 x float> %src to <2 x bfloat> diff --git a/llvm/test/CodeGen/AMDGPU/insert_vector_elt.v2bf16.ll b/llvm/test/CodeGen/AMDGPU/insert_vector_elt.v2bf16.ll new file mode 100644 index 000000000000..c9b01eb5a972 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/insert_vector_elt.v2bf16.ll @@ -0,0 +1,1690 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=tahiti < %s | FileCheck -check-prefix=SI %s +; RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=tonga < %s | FileCheck -check-prefix=VI %s +; RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s | FileCheck -check-prefix=GFX900 %s +; RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 < %s | FileCheck -check-prefix=GFX940 %s + +define amdgpu_kernel void @s_insertelement_v2bf16_0(ptr addrspace(1) %out, ptr addrspace(4) %vec.ptr) #0 { +; SI-LABEL: s_insertelement_v2bf16_0: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_load_dword s4, s[2:3], 0x0 +; SI-NEXT: s_mov_b32 s3, 0x100f000 +; SI-NEXT: s_mov_b32 s2, -1 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_and_b32 s4, s4, 0xffff0000 +; SI-NEXT: s_or_b32 s4, s4, 0x40a0 +; SI-NEXT: v_mov_b32_e32 v0, s4 +; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 +; SI-NEXT: s_endpgm +; +; VI-LABEL: s_insertelement_v2bf16_0: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: s_load_dword s2, s[2:3], 0x0 +; VI-NEXT: v_mov_b32_e32 v0, s0 +; VI-NEXT: v_mov_b32_e32 v1, s1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: s_and_b32 s0, s2, 0xffff0000 +; VI-NEXT: s_or_b32 s0, s0, 0x40a0 +; VI-NEXT: v_mov_b32_e32 v2, s0 +; VI-NEXT: flat_store_dword v[0:1], v2 +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: s_insertelement_v2bf16_0: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: v_mov_b32_e32 v0, 0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: s_load_dword s2, s[2:3], 0x0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: s_lshr_b32 s2, s2, 16 +; GFX900-NEXT: s_pack_ll_b32_b16 s2, 0x40a0, s2 +; GFX900-NEXT: v_mov_b32_e32 v1, s2 +; GFX900-NEXT: global_store_dword v0, v1, s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: s_insertelement_v2bf16_0: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX940-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: s_load_dword s2, s[2:3], 0x0 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: s_lshr_b32 s2, s2, 16 +; GFX940-NEXT: s_pack_ll_b32_b16 s2, 0x40a0, s2 +; GFX940-NEXT: v_mov_b32_e32 v1, s2 +; GFX940-NEXT: global_store_dword v0, v1, s[0:1] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %vec = load <2 x bfloat>, ptr addrspace(4) %vec.ptr + %vecins = insertelement <2 x bfloat> %vec, bfloat 5.000000e+00, i32 0 + store <2 x bfloat> %vecins, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @s_insertelement_v2bf16_1(ptr addrspace(1) %out, ptr addrspace(4) %vec.ptr) #0 { +; SI-LABEL: s_insertelement_v2bf16_1: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_load_dword s4, s[2:3], 0x0 +; SI-NEXT: s_mov_b32 s3, 0x100f000 +; SI-NEXT: s_mov_b32 s2, -1 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_and_b32 s4, s4, 0xffff +; SI-NEXT: s_or_b32 s4, s4, 0x40a00000 +; SI-NEXT: v_mov_b32_e32 v0, s4 +; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 +; SI-NEXT: s_endpgm +; +; VI-LABEL: s_insertelement_v2bf16_1: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: s_load_dword s2, s[2:3], 0x0 +; VI-NEXT: v_mov_b32_e32 v0, s0 +; VI-NEXT: v_mov_b32_e32 v1, s1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: s_and_b32 s0, s2, 0xffff +; VI-NEXT: s_or_b32 s0, s0, 0x40a00000 +; VI-NEXT: v_mov_b32_e32 v2, s0 +; VI-NEXT: flat_store_dword v[0:1], v2 +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: s_insertelement_v2bf16_1: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: v_mov_b32_e32 v0, 0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: s_load_dword s2, s[2:3], 0x0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: s_pack_ll_b32_b16 s2, s2, 0x40a0 +; GFX900-NEXT: v_mov_b32_e32 v1, s2 +; GFX900-NEXT: global_store_dword v0, v1, s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: s_insertelement_v2bf16_1: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX940-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: s_load_dword s2, s[2:3], 0x0 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: s_pack_ll_b32_b16 s2, s2, 0x40a0 +; GFX940-NEXT: v_mov_b32_e32 v1, s2 +; GFX940-NEXT: global_store_dword v0, v1, s[0:1] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %vec = load <2 x bfloat>, ptr addrspace(4) %vec.ptr + %vecins = insertelement <2 x bfloat> %vec, bfloat 5.000000e+00, i32 1 + store <2 x bfloat> %vecins, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @v_insertelement_v2bf16_0(ptr addrspace(1) %out, ptr addrspace(1) %in) #0 { +; SI-LABEL: v_insertelement_v2bf16_0: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; SI-NEXT: v_mov_b32_e32 v1, 0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: buffer_load_dword v2, v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 +; SI-NEXT: v_or_b32_e32 v2, 0x40a0, v2 +; SI-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v2bf16_0: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v3, v[0:1] +; VI-NEXT: v_mov_b32_e32 v1, s1 +; VI-NEXT: v_add_u32_e32 v0, vcc, s0, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_and_b32_e32 v2, 0xffff0000, v3 +; VI-NEXT: v_or_b32_e32 v2, 0x40a0, v2 +; VI-NEXT: flat_store_dword v[0:1], v2 +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v2bf16_0: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX900-NEXT: v_mov_b32_e32 v2, 0x40a0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dword v1, v0, s[2:3] +; GFX900-NEXT: s_mov_b32 s2, 0xffff +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_bfi_b32 v1, s2, v2, v1 +; GFX900-NEXT: global_store_dword v0, v1, s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v2bf16_0: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX940-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX940-NEXT: v_mov_b32_e32 v2, 0x40a0 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dword v1, v0, s[2:3] +; GFX940-NEXT: s_mov_b32 s2, 0xffff +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_bfi_b32 v1, s2, v2, v1 +; GFX940-NEXT: global_store_dword v0, v1, s[0:1] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <2 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <2 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <2 x bfloat>, ptr addrspace(1) %in.gep + %vecins = insertelement <2 x bfloat> %vec, bfloat 5.000000e+00, i32 0 + store <2 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v2bf16_0_inlineimm(ptr addrspace(1) %out, ptr addrspace(1) %in) #0 { +; SI-LABEL: v_insertelement_v2bf16_0_inlineimm: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; SI-NEXT: v_mov_b32_e32 v1, 0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: buffer_load_dword v2, v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 +; SI-NEXT: v_or_b32_e32 v2, 53, v2 +; SI-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v2bf16_0_inlineimm: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v3, v[0:1] +; VI-NEXT: v_mov_b32_e32 v1, s1 +; VI-NEXT: v_add_u32_e32 v0, vcc, s0, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_and_b32_e32 v2, 0xffff0000, v3 +; VI-NEXT: v_or_b32_e32 v2, 53, v2 +; VI-NEXT: flat_store_dword v[0:1], v2 +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v2bf16_0_inlineimm: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dword v1, v0, s[2:3] +; GFX900-NEXT: s_mov_b32 s2, 0xffff +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_bfi_b32 v1, s2, 53, v1 +; GFX900-NEXT: global_store_dword v0, v1, s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v2bf16_0_inlineimm: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX940-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dword v1, v0, s[2:3] +; GFX940-NEXT: s_mov_b32 s2, 0xffff +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_bfi_b32 v1, s2, 53, v1 +; GFX940-NEXT: global_store_dword v0, v1, s[0:1] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <2 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <2 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <2 x bfloat>, ptr addrspace(1) %in.gep + %vecins = insertelement <2 x bfloat> %vec, bfloat 0xR0035, i32 0 + store <2 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v2bf16_1(ptr addrspace(1) %out, ptr addrspace(1) %in) #0 { +; SI-LABEL: v_insertelement_v2bf16_1: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; SI-NEXT: v_mov_b32_e32 v1, 0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: buffer_load_dword v2, v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_and_b32_e32 v2, 0xffff, v2 +; SI-NEXT: v_or_b32_e32 v2, 0x40a00000, v2 +; SI-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v2bf16_1: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v3, v[0:1] +; VI-NEXT: v_mov_b32_e32 v1, s1 +; VI-NEXT: v_add_u32_e32 v0, vcc, s0, v2 +; VI-NEXT: v_mov_b32_e32 v2, 0x40a00000 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_or_b32_sdwa v2, v3, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: flat_store_dword v[0:1], v2 +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v2bf16_1: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX900-NEXT: v_mov_b32_e32 v2, 0x5040100 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dword v1, v0, s[2:3] +; GFX900-NEXT: s_movk_i32 s2, 0x40a0 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_perm_b32 v1, s2, v1, v2 +; GFX900-NEXT: global_store_dword v0, v1, s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v2bf16_1: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX940-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX940-NEXT: v_mov_b32_e32 v2, 0x5040100 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dword v1, v0, s[2:3] +; GFX940-NEXT: s_movk_i32 s2, 0x40a0 +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_perm_b32 v1, s2, v1, v2 +; GFX940-NEXT: global_store_dword v0, v1, s[0:1] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <2 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <2 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <2 x bfloat>, ptr addrspace(1) %in.gep + %vecins = insertelement <2 x bfloat> %vec, bfloat 5.000000e+00, i32 1 + store <2 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v2bf16_1_inlineimm(ptr addrspace(1) %out, ptr addrspace(1) %in) #0 { +; SI-LABEL: v_insertelement_v2bf16_1_inlineimm: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; SI-NEXT: v_mov_b32_e32 v1, 0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: buffer_load_dword v2, v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_and_b32_e32 v2, 0xffff, v2 +; SI-NEXT: v_or_b32_e32 v2, 0x230000, v2 +; SI-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v2bf16_1_inlineimm: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v3, v[0:1] +; VI-NEXT: v_mov_b32_e32 v1, s1 +; VI-NEXT: v_add_u32_e32 v0, vcc, s0, v2 +; VI-NEXT: v_mov_b32_e32 v2, 0x230000 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_or_b32_sdwa v2, v3, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: flat_store_dword v[0:1], v2 +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v2bf16_1_inlineimm: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX900-NEXT: v_mov_b32_e32 v2, 0x5040100 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dword v1, v0, s[2:3] +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_perm_b32 v1, 35, v1, v2 +; GFX900-NEXT: global_store_dword v0, v1, s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v2bf16_1_inlineimm: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX940-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX940-NEXT: v_mov_b32_e32 v2, 0x5040100 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dword v1, v0, s[2:3] +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_perm_b32 v1, 35, v1, v2 +; GFX940-NEXT: global_store_dword v0, v1, s[0:1] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <2 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <2 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <2 x bfloat>, ptr addrspace(1) %in.gep + %vecins = insertelement <2 x bfloat> %vec, bfloat 0xR0023, i32 1 + store <2 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v2bf16_dynamic_vgpr(ptr addrspace(1) %out, ptr addrspace(1) %in, ptr addrspace(1) %idx.ptr) #0 { +; SI-LABEL: v_insertelement_v2bf16_dynamic_vgpr: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x4 +; SI-NEXT: s_mov_b32 s11, 0x100f000 +; SI-NEXT: s_mov_b32 s10, 0 +; SI-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; SI-NEXT: v_mov_b32_e32 v1, 0 +; SI-NEXT: s_mov_b64 s[6:7], s[10:11] +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: buffer_load_dword v2, v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b64 s[8:9], s[2:3] +; SI-NEXT: buffer_load_dword v3, v[0:1], s[8:11], 0 addr64 +; SI-NEXT: s_mov_b32 s4, 0x12341234 +; SI-NEXT: s_mov_b64 s[2:3], s[10:11] +; SI-NEXT: s_waitcnt vmcnt(1) +; SI-NEXT: v_lshlrev_b32_e32 v2, 4, v2 +; SI-NEXT: v_lshl_b32_e32 v2, 0xffff, v2 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_bfi_b32 v2, v2, s4, v3 +; SI-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v2bf16_dynamic_vgpr: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x10 +; VI-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v3, s3 +; VI-NEXT: v_mov_b32_e32 v1, s5 +; VI-NEXT: v_add_u32_e32 v0, vcc, s4, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v4, v[0:1] +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v3, vcc +; VI-NEXT: flat_load_dword v3, v[0:1] +; VI-NEXT: s_mov_b32 s2, 0xffff +; VI-NEXT: v_add_u32_e32 v0, vcc, s0, v2 +; VI-NEXT: v_mov_b32_e32 v1, s1 +; VI-NEXT: s_mov_b32 s0, 0x12341234 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_lshlrev_b32_e32 v2, 4, v4 +; VI-NEXT: v_lshlrev_b32_e64 v2, v2, s2 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_bfi_b32 v2, v2, s0, v3 +; VI-NEXT: flat_store_dword v[0:1], v2 +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v2bf16_dynamic_vgpr: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x10 +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dword v1, v0, s[6:7] +; GFX900-NEXT: global_load_dword v2, v0, s[2:3] +; GFX900-NEXT: s_mov_b32 s2, 0xffff +; GFX900-NEXT: s_waitcnt vmcnt(1) +; GFX900-NEXT: v_lshlrev_b32_e32 v1, 4, v1 +; GFX900-NEXT: v_lshlrev_b32_e64 v1, v1, s2 +; GFX900-NEXT: s_mov_b32 s2, 0x12341234 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_bfi_b32 v1, v1, s2, v2 +; GFX900-NEXT: global_store_dword v0, v1, s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v2bf16_dynamic_vgpr: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x10 +; GFX940-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 +; GFX940-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX940-NEXT: s_mov_b32 s0, 0xffff +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dword v1, v0, s[2:3] +; GFX940-NEXT: global_load_dword v2, v0, s[6:7] +; GFX940-NEXT: s_waitcnt vmcnt(1) +; GFX940-NEXT: v_lshlrev_b32_e32 v1, 4, v1 +; GFX940-NEXT: v_lshlrev_b32_e64 v1, v1, s0 +; GFX940-NEXT: s_mov_b32 s0, 0x12341234 +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_bfi_b32 v1, v1, s0, v2 +; GFX940-NEXT: global_store_dword v0, v1, s[4:5] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <2 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %idx.gep = getelementptr inbounds i32, ptr addrspace(1) %idx.ptr, i64 %tid.ext + %out.gep = getelementptr inbounds <2 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %idx = load i32, ptr addrspace(1) %idx.gep + %vec = load <2 x bfloat>, ptr addrspace(1) %in.gep + %vecins = insertelement <2 x bfloat> %vec, bfloat 0xR1234, i32 %idx + store <2 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v4bf16_0(ptr addrspace(1) %out, ptr addrspace(1) %in, [8 x i32], i32 %val) #0 { +; SI-LABEL: v_insertelement_v4bf16_0: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_load_dword s8, s[4:5], 0xc +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v0, 3, v0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: v_mov_b32_e32 v1, 0 +; SI-NEXT: buffer_load_dwordx2 v[2:3], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b32 s4, 0xffff +; SI-NEXT: v_mov_b32_e32 v4, s8 +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_bfi_b32 v2, s4, v4, v2 +; SI-NEXT: buffer_store_dwordx2 v[2:3], v[0:1], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v4bf16_0: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_load_dword s4, s[4:5], 0x30 +; VI-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; VI-NEXT: v_mov_b32_e32 v4, 0x3020504 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[0:1], v[0:1] +; VI-NEXT: v_mov_b32_e32 v3, s1 +; VI-NEXT: v_add_u32_e32 v2, vcc, s0, v2 +; VI-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v0, s4, v0, v4 +; VI-NEXT: flat_store_dwordx2 v[2:3], v[0:1] +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v4bf16_0: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: s_load_dword s6, s[4:5], 0x30 +; GFX900-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dwordx2 v[0:1], v2, s[2:3] +; GFX900-NEXT: s_mov_b32 s2, 0xffff +; GFX900-NEXT: v_mov_b32_e32 v3, s6 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_bfi_b32 v0, s2, v3, v0 +; GFX900-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v4bf16_0: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 +; GFX940-NEXT: s_load_dword s2, s[0:1], 0x30 +; GFX940-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX940-NEXT: s_mov_b32 s0, 0xffff +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dwordx2 v[0:1], v2, s[6:7] +; GFX940-NEXT: v_mov_b32_e32 v3, s2 +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_bfi_b32 v0, s0, v3, v0 +; GFX940-NEXT: global_store_dwordx2 v2, v[0:1], s[4:5] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <4 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <4 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <4 x bfloat>, ptr addrspace(1) %in.gep + %val.trunc = trunc i32 %val to i16 + %val.cvt = bitcast i16 %val.trunc to bfloat + %vecins = insertelement <4 x bfloat> %vec, bfloat %val.cvt, i32 0 + store <4 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v4bf16_1(ptr addrspace(1) %out, ptr addrspace(1) %in, i32 %val) #0 { +; SI-LABEL: v_insertelement_v4bf16_1: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_load_dword s8, s[4:5], 0x4 +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v0, 3, v0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: v_mov_b32_e32 v1, 0 +; SI-NEXT: buffer_load_dwordx2 v[2:3], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_lshl_b32 s4, s8, 16 +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_and_b32_e32 v2, 0xffff, v2 +; SI-NEXT: v_or_b32_e32 v2, s4, v2 +; SI-NEXT: buffer_store_dwordx2 v[2:3], v[0:1], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v4bf16_1: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_load_dword s4, s[4:5], 0x10 +; VI-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; VI-NEXT: v_mov_b32_e32 v4, 0x1000504 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[0:1], v[0:1] +; VI-NEXT: v_mov_b32_e32 v3, s1 +; VI-NEXT: v_add_u32_e32 v2, vcc, s0, v2 +; VI-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v0, v0, s4, v4 +; VI-NEXT: flat_store_dwordx2 v[2:3], v[0:1] +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v4bf16_1: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: s_load_dword s6, s[4:5], 0x10 +; GFX900-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX900-NEXT: v_mov_b32_e32 v3, 0x5040100 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dwordx2 v[0:1], v2, s[2:3] +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_perm_b32 v0, s6, v0, v3 +; GFX900-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v4bf16_1: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 +; GFX940-NEXT: s_load_dword s2, s[0:1], 0x10 +; GFX940-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX940-NEXT: v_mov_b32_e32 v3, 0x5040100 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dwordx2 v[0:1], v2, s[6:7] +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_perm_b32 v0, s2, v0, v3 +; GFX940-NEXT: global_store_dwordx2 v2, v[0:1], s[4:5] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <4 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <4 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <4 x bfloat>, ptr addrspace(1) %in.gep + %val.trunc = trunc i32 %val to i16 + %val.cvt = bitcast i16 %val.trunc to bfloat + %vecins = insertelement <4 x bfloat> %vec, bfloat %val.cvt, i32 1 + store <4 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v4bf16_2(ptr addrspace(1) %out, ptr addrspace(1) %in, [8 x i32], i32 %val) #0 { +; SI-LABEL: v_insertelement_v4bf16_2: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_load_dword s8, s[4:5], 0xc +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v0, 3, v0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: v_mov_b32_e32 v1, 0 +; SI-NEXT: buffer_load_dwordx2 v[2:3], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b32 s4, 0xffff +; SI-NEXT: v_mov_b32_e32 v4, s8 +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_bfi_b32 v3, s4, v4, v3 +; SI-NEXT: buffer_store_dwordx2 v[2:3], v[0:1], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v4bf16_2: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_load_dword s4, s[4:5], 0x30 +; VI-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; VI-NEXT: v_mov_b32_e32 v4, 0x3020504 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[0:1], v[0:1] +; VI-NEXT: v_mov_b32_e32 v3, s1 +; VI-NEXT: v_add_u32_e32 v2, vcc, s0, v2 +; VI-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v1, s4, v1, v4 +; VI-NEXT: flat_store_dwordx2 v[2:3], v[0:1] +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v4bf16_2: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: s_load_dword s6, s[4:5], 0x30 +; GFX900-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dwordx2 v[0:1], v2, s[2:3] +; GFX900-NEXT: s_mov_b32 s2, 0xffff +; GFX900-NEXT: v_mov_b32_e32 v3, s6 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_bfi_b32 v1, s2, v3, v1 +; GFX900-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v4bf16_2: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 +; GFX940-NEXT: s_load_dword s2, s[0:1], 0x30 +; GFX940-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX940-NEXT: s_mov_b32 s0, 0xffff +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dwordx2 v[0:1], v2, s[6:7] +; GFX940-NEXT: v_mov_b32_e32 v3, s2 +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_bfi_b32 v1, s0, v3, v1 +; GFX940-NEXT: global_store_dwordx2 v2, v[0:1], s[4:5] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <4 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <4 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <4 x bfloat>, ptr addrspace(1) %in.gep + %val.trunc = trunc i32 %val to i16 + %val.cvt = bitcast i16 %val.trunc to bfloat + %vecins = insertelement <4 x bfloat> %vec, bfloat %val.cvt, i32 2 + store <4 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v4bf16_3(ptr addrspace(1) %out, ptr addrspace(1) %in, i32 %val) #0 { +; SI-LABEL: v_insertelement_v4bf16_3: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_load_dword s8, s[4:5], 0x4 +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v0, 3, v0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: v_mov_b32_e32 v1, 0 +; SI-NEXT: buffer_load_dwordx2 v[2:3], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_lshl_b32 s4, s8, 16 +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_and_b32_e32 v3, 0xffff, v3 +; SI-NEXT: v_or_b32_e32 v3, s4, v3 +; SI-NEXT: buffer_store_dwordx2 v[2:3], v[0:1], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v4bf16_3: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_load_dword s4, s[4:5], 0x10 +; VI-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; VI-NEXT: v_mov_b32_e32 v4, 0x1000504 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[0:1], v[0:1] +; VI-NEXT: v_mov_b32_e32 v3, s1 +; VI-NEXT: v_add_u32_e32 v2, vcc, s0, v2 +; VI-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v1, v1, s4, v4 +; VI-NEXT: flat_store_dwordx2 v[2:3], v[0:1] +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v4bf16_3: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: s_load_dword s6, s[4:5], 0x10 +; GFX900-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX900-NEXT: v_mov_b32_e32 v3, 0x5040100 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dwordx2 v[0:1], v2, s[2:3] +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_perm_b32 v1, s6, v1, v3 +; GFX900-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v4bf16_3: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 +; GFX940-NEXT: s_load_dword s2, s[0:1], 0x10 +; GFX940-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX940-NEXT: v_mov_b32_e32 v3, 0x5040100 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dwordx2 v[0:1], v2, s[6:7] +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_perm_b32 v1, s2, v1, v3 +; GFX940-NEXT: global_store_dwordx2 v2, v[0:1], s[4:5] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <4 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <4 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <4 x bfloat>, ptr addrspace(1) %in.gep + %val.trunc = trunc i32 %val to i16 + %val.cvt = bitcast i16 %val.trunc to bfloat + %vecins = insertelement <4 x bfloat> %vec, bfloat %val.cvt, i32 3 + store <4 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v4bf16_dynamic_sgpr(ptr addrspace(1) %out, ptr addrspace(1) %in, i32 %val, i32 %idxval) #0 { +; SI-LABEL: v_insertelement_v4bf16_dynamic_sgpr: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_load_dwordx2 s[8:9], s[4:5], 0x4 +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v0, 3, v0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: v_mov_b32_e32 v1, 0 +; SI-NEXT: buffer_load_dwordx2 v[2:3], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_lshl_b32 s4, s8, 16 +; SI-NEXT: s_and_b32 s5, s8, 0xffff +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_lshl_b32 s6, s9, 4 +; SI-NEXT: s_or_b32 s7, s5, s4 +; SI-NEXT: s_lshl_b64 s[4:5], 0xffff, s6 +; SI-NEXT: v_mov_b32_e32 v4, s7 +; SI-NEXT: v_mov_b32_e32 v5, s7 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_bfi_b32 v3, s5, v4, v3 +; SI-NEXT: v_bfi_b32 v2, s4, v5, v2 +; SI-NEXT: buffer_store_dwordx2 v[2:3], v[0:1], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v4bf16_dynamic_sgpr: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x10 +; VI-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[0:1], v[0:1] +; VI-NEXT: v_mov_b32_e32 v3, s1 +; VI-NEXT: s_lshl_b32 s1, s4, 16 +; VI-NEXT: s_and_b32 s2, s4, 0xffff +; VI-NEXT: s_lshl_b32 s3, s5, 4 +; VI-NEXT: s_or_b32 s2, s2, s1 +; VI-NEXT: v_add_u32_e32 v2, vcc, s0, v2 +; VI-NEXT: s_lshl_b64 s[0:1], 0xffff, s3 +; VI-NEXT: v_mov_b32_e32 v4, s2 +; VI-NEXT: v_mov_b32_e32 v5, s2 +; VI-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_bfi_b32 v1, s1, v4, v1 +; VI-NEXT: v_bfi_b32 v0, s0, v5, v0 +; VI-NEXT: flat_store_dwordx2 v[2:3], v[0:1] +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v4bf16_dynamic_sgpr: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x10 +; GFX900-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dwordx2 v[0:1], v2, s[2:3] +; GFX900-NEXT: s_lshl_b32 s2, s7, 4 +; GFX900-NEXT: s_pack_ll_b32_b16 s4, s6, s6 +; GFX900-NEXT: s_lshl_b64 s[2:3], 0xffff, s2 +; GFX900-NEXT: v_mov_b32_e32 v3, s4 +; GFX900-NEXT: v_mov_b32_e32 v4, s4 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_bfi_b32 v1, s3, v3, v1 +; GFX900-NEXT: v_bfi_b32 v0, s2, v4, v0 +; GFX900-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v4bf16_dynamic_sgpr: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 +; GFX940-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x10 +; GFX940-NEXT: v_lshlrev_b32_e32 v2, 3, v0 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dwordx2 v[0:1], v2, s[6:7] +; GFX940-NEXT: s_lshl_b32 s0, s3, 4 +; GFX940-NEXT: s_pack_ll_b32_b16 s2, s2, s2 +; GFX940-NEXT: s_lshl_b64 s[0:1], 0xffff, s0 +; GFX940-NEXT: v_mov_b32_e32 v3, s2 +; GFX940-NEXT: v_mov_b32_e32 v4, s2 +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_bfi_b32 v1, s1, v3, v1 +; GFX940-NEXT: v_bfi_b32 v0, s0, v4, v0 +; GFX940-NEXT: global_store_dwordx2 v2, v[0:1], s[4:5] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <4 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <4 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <4 x bfloat>, ptr addrspace(1) %in.gep + %val.trunc = trunc i32 %val to i16 + %val.cvt = bitcast i16 %val.trunc to bfloat + %vecins = insertelement <4 x bfloat> %vec, bfloat %val.cvt, i32 %idxval + store <4 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v8bf16_3(ptr addrspace(1) %out, ptr addrspace(1) %in, i32 %val) { +; SI-LABEL: v_insertelement_v8bf16_3: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_load_dword s8, s[4:5], 0x4 +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v4, 4, v0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: v_mov_b32_e32 v5, 0 +; SI-NEXT: buffer_load_dwordx4 v[0:3], v[4:5], s[4:7], 0 addr64 +; SI-NEXT: s_lshl_b32 s4, s8, 16 +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_and_b32_e32 v1, 0xffff, v1 +; SI-NEXT: v_or_b32_e32 v1, s4, v1 +; SI-NEXT: buffer_store_dwordx4 v[0:3], v[4:5], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v8bf16_3: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_load_dword s4, s[4:5], 0x10 +; VI-NEXT: v_lshlrev_b32_e32 v4, 4, v0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v4 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx4 v[0:3], v[0:1] +; VI-NEXT: v_add_u32_e32 v4, vcc, s0, v4 +; VI-NEXT: s_lshl_b32 s0, s4, 16 +; VI-NEXT: v_mov_b32_e32 v5, s1 +; VI-NEXT: v_mov_b32_e32 v6, s0 +; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v5, vcc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_or_b32_sdwa v1, v1, v6 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: flat_store_dwordx4 v[4:5], v[0:3] +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v8bf16_3: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: s_load_dword s6, s[4:5], 0x10 +; GFX900-NEXT: v_lshlrev_b32_e32 v4, 4, v0 +; GFX900-NEXT: v_mov_b32_e32 v5, 0x5040100 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dwordx4 v[0:3], v4, s[2:3] +; GFX900-NEXT: s_mov_b32 s2, 0xffff +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_bfi_b32 v3, s2, v3, v3 +; GFX900-NEXT: v_bfi_b32 v2, s2, v2, v2 +; GFX900-NEXT: v_bfi_b32 v0, s2, v0, v0 +; GFX900-NEXT: v_perm_b32 v1, s6, v1, v5 +; GFX900-NEXT: global_store_dwordx4 v4, v[0:3], s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v8bf16_3: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 +; GFX940-NEXT: s_load_dword s2, s[0:1], 0x10 +; GFX940-NEXT: v_lshlrev_b32_e32 v4, 4, v0 +; GFX940-NEXT: s_mov_b32 s0, 0xffff +; GFX940-NEXT: v_mov_b32_e32 v5, 0x5040100 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dwordx4 v[0:3], v4, s[6:7] +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_bfi_b32 v3, s0, v3, v3 +; GFX940-NEXT: v_bfi_b32 v2, s0, v2, v2 +; GFX940-NEXT: v_bfi_b32 v0, s0, v0, v0 +; GFX940-NEXT: v_perm_b32 v1, s2, v1, v5 +; GFX940-NEXT: global_store_dwordx4 v4, v[0:3], s[4:5] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <8 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <8 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <8 x bfloat>, ptr addrspace(1) %in.gep + %val.trunc = trunc i32 %val to i16 + %val.cvt = bitcast i16 %val.trunc to bfloat + %vecins = insertelement <8 x bfloat> %vec, bfloat %val.cvt, i32 3 + store <8 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v8bf16_dynamic(ptr addrspace(1) %out, ptr addrspace(1) %in, i32 %val, i32 %n) { +; SI-LABEL: v_insertelement_v8bf16_dynamic: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_load_dwordx2 s[8:9], s[4:5], 0x4 +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v4, 4, v0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: v_mov_b32_e32 v5, 0 +; SI-NEXT: buffer_load_dwordx4 v[0:3], v[4:5], s[4:7], 0 addr64 +; SI-NEXT: s_cmp_eq_u32 s9, 6 +; SI-NEXT: v_mov_b32_e32 v6, s8 +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s9, 7 +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_cndmask_b32_e32 v7, v3, v6, vcc +; SI-NEXT: v_lshrrev_b32_e32 v3, 16, v3 +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s9, 4 +; SI-NEXT: v_cndmask_b32_e32 v3, v3, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s9, 5 +; SI-NEXT: v_lshrrev_b32_e32 v8, 16, v2 +; SI-NEXT: v_cndmask_b32_e32 v2, v2, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s9, 2 +; SI-NEXT: v_and_b32_e32 v7, 0xffff, v7 +; SI-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; SI-NEXT: v_cndmask_b32_e32 v8, v8, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s9, 3 +; SI-NEXT: v_lshrrev_b32_e32 v9, 16, v1 +; SI-NEXT: v_and_b32_e32 v2, 0xffff, v2 +; SI-NEXT: v_or_b32_e32 v3, v7, v3 +; SI-NEXT: v_lshlrev_b32_e32 v7, 16, v8 +; SI-NEXT: v_cndmask_b32_e32 v1, v1, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s9, 0 +; SI-NEXT: v_or_b32_e32 v2, v2, v7 +; SI-NEXT: v_cndmask_b32_e32 v7, v9, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s9, 1 +; SI-NEXT: v_lshrrev_b32_e32 v10, 16, v0 +; SI-NEXT: v_cndmask_b32_e32 v0, v0, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: v_cndmask_b32_e32 v6, v10, v6, vcc +; SI-NEXT: v_and_b32_e32 v1, 0xffff, v1 +; SI-NEXT: v_lshlrev_b32_e32 v7, 16, v7 +; SI-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; SI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 +; SI-NEXT: v_or_b32_e32 v1, v1, v7 +; SI-NEXT: v_or_b32_e32 v0, v0, v6 +; SI-NEXT: buffer_store_dwordx4 v[0:3], v[4:5], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v8bf16_dynamic: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x10 +; VI-NEXT: v_lshlrev_b32_e32 v4, 4, v0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v4 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx4 v[0:3], v[0:1] +; VI-NEXT: v_mov_b32_e32 v5, s1 +; VI-NEXT: v_add_u32_e32 v4, vcc, s0, v4 +; VI-NEXT: s_cmp_eq_u32 s5, 6 +; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v5, vcc +; VI-NEXT: v_mov_b32_e32 v6, s4 +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 7 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_cndmask_b32_e32 v7, v3, v6, vcc +; VI-NEXT: v_lshrrev_b32_e32 v3, 16, v3 +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 4 +; VI-NEXT: v_cndmask_b32_e32 v3, v3, v6, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 5 +; VI-NEXT: v_lshrrev_b32_e32 v8, 16, v2 +; VI-NEXT: v_cndmask_b32_e32 v2, v2, v6, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 2 +; VI-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; VI-NEXT: v_cndmask_b32_e32 v8, v8, v6, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 3 +; VI-NEXT: v_lshrrev_b32_e32 v9, 16, v1 +; VI-NEXT: v_or_b32_sdwa v3, v7, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: v_lshlrev_b32_e32 v7, 16, v8 +; VI-NEXT: v_cndmask_b32_e32 v1, v1, v6, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 0 +; VI-NEXT: v_or_b32_sdwa v2, v2, v7 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: v_cndmask_b32_e32 v7, v9, v6, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 1 +; VI-NEXT: v_lshrrev_b32_e32 v10, 16, v0 +; VI-NEXT: v_cndmask_b32_e32 v0, v0, v6, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: v_cndmask_b32_e32 v6, v10, v6, vcc +; VI-NEXT: v_lshlrev_b32_e32 v7, 16, v7 +; VI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 +; VI-NEXT: v_or_b32_sdwa v1, v1, v7 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: v_or_b32_sdwa v0, v0, v6 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: flat_store_dwordx4 v[4:5], v[0:3] +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v8bf16_dynamic: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x10 +; GFX900-NEXT: v_lshlrev_b32_e32 v4, 4, v0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dwordx4 v[0:3], v4, s[2:3] +; GFX900-NEXT: s_cmp_eq_u32 s7, 6 +; GFX900-NEXT: v_mov_b32_e32 v5, s6 +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 7 +; GFX900-NEXT: s_mov_b32 s2, 0x5040100 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_cndmask_b32_e32 v6, v3, v5, vcc +; GFX900-NEXT: v_lshrrev_b32_e32 v3, 16, v3 +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 4 +; GFX900-NEXT: v_cndmask_b32_e32 v3, v3, v5, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 5 +; GFX900-NEXT: v_lshrrev_b32_e32 v7, 16, v2 +; GFX900-NEXT: v_cndmask_b32_e32 v2, v2, v5, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 2 +; GFX900-NEXT: v_perm_b32 v3, v3, v6, s2 +; GFX900-NEXT: v_cndmask_b32_e32 v6, v7, v5, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 3 +; GFX900-NEXT: v_lshrrev_b32_e32 v8, 16, v1 +; GFX900-NEXT: v_cndmask_b32_e32 v1, v1, v5, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 0 +; GFX900-NEXT: v_perm_b32 v2, v6, v2, s2 +; GFX900-NEXT: v_cndmask_b32_e32 v6, v8, v5, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 1 +; GFX900-NEXT: v_lshrrev_b32_e32 v9, 16, v0 +; GFX900-NEXT: v_cndmask_b32_e32 v0, v0, v5, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: v_cndmask_b32_e32 v5, v9, v5, vcc +; GFX900-NEXT: v_perm_b32 v1, v6, v1, s2 +; GFX900-NEXT: v_perm_b32 v0, v5, v0, s2 +; GFX900-NEXT: global_store_dwordx4 v4, v[0:3], s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v8bf16_dynamic: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 +; GFX940-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x10 +; GFX940-NEXT: v_lshlrev_b32_e32 v4, 4, v0 +; GFX940-NEXT: s_mov_b32 s0, 0x5040100 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dwordx4 v[0:3], v4, s[6:7] +; GFX940-NEXT: s_cmp_eq_u32 s3, 6 +; GFX940-NEXT: v_mov_b32_e32 v5, s2 +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 7 +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_cndmask_b32_e32 v6, v3, v5, vcc +; GFX940-NEXT: v_lshrrev_b32_e32 v3, 16, v3 +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 4 +; GFX940-NEXT: v_cndmask_b32_e32 v3, v3, v5, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 5 +; GFX940-NEXT: v_lshrrev_b32_e32 v7, 16, v2 +; GFX940-NEXT: v_cndmask_b32_e32 v2, v2, v5, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 2 +; GFX940-NEXT: v_perm_b32 v3, v3, v6, s0 +; GFX940-NEXT: v_cndmask_b32_e32 v6, v7, v5, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 3 +; GFX940-NEXT: v_lshrrev_b32_e32 v8, 16, v1 +; GFX940-NEXT: v_cndmask_b32_e32 v1, v1, v5, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 0 +; GFX940-NEXT: v_perm_b32 v2, v6, v2, s0 +; GFX940-NEXT: v_cndmask_b32_e32 v6, v8, v5, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 1 +; GFX940-NEXT: v_lshrrev_b32_e32 v9, 16, v0 +; GFX940-NEXT: v_cndmask_b32_e32 v0, v0, v5, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: v_cndmask_b32_e32 v5, v9, v5, vcc +; GFX940-NEXT: v_perm_b32 v1, v6, v1, s0 +; GFX940-NEXT: v_perm_b32 v0, v5, v0, s0 +; GFX940-NEXT: global_store_dwordx4 v4, v[0:3], s[4:5] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <8 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <8 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <8 x bfloat>, ptr addrspace(1) %in.gep + %val.trunc = trunc i32 %val to i16 + %val.cvt = bitcast i16 %val.trunc to bfloat + %vecins = insertelement <8 x bfloat> %vec, bfloat %val.cvt, i32 %n + store <8 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v16bf16_3(ptr addrspace(1) %out, ptr addrspace(1) %in, i32 %val) { +; SI-LABEL: v_insertelement_v16bf16_3: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_load_dword s8, s[4:5], 0x4 +; SI-NEXT: s_mov_b32 s7, 0x100f000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_lshlrev_b32_e32 v8, 5, v0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[4:5], s[2:3] +; SI-NEXT: v_mov_b32_e32 v9, 0 +; SI-NEXT: buffer_load_dwordx4 v[0:3], v[8:9], s[4:7], 0 addr64 +; SI-NEXT: buffer_load_dwordx4 v[4:7], v[8:9], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_mov_b64 s[2:3], s[6:7] +; SI-NEXT: s_lshl_b32 s4, s8, 16 +; SI-NEXT: s_waitcnt vmcnt(1) +; SI-NEXT: v_and_b32_e32 v1, 0xffff, v1 +; SI-NEXT: v_or_b32_e32 v1, s4, v1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_store_dwordx4 v[4:7], v[8:9], s[0:3], 0 addr64 offset:16 +; SI-NEXT: buffer_store_dwordx4 v[0:3], v[8:9], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v16bf16_3: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_load_dword s4, s[4:5], 0x10 +; VI-NEXT: v_lshlrev_b32_e32 v8, 5, v0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v8 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: v_add_u32_e32 v4, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx4 v[0:3], v[0:1] +; VI-NEXT: flat_load_dwordx4 v[4:7], v[4:5] +; VI-NEXT: v_mov_b32_e32 v9, s1 +; VI-NEXT: v_add_u32_e32 v8, vcc, s0, v8 +; VI-NEXT: v_addc_u32_e32 v9, vcc, 0, v9, vcc +; VI-NEXT: s_lshl_b32 s1, s4, 16 +; VI-NEXT: v_add_u32_e32 v10, vcc, 16, v8 +; VI-NEXT: v_mov_b32_e32 v12, s1 +; VI-NEXT: v_addc_u32_e32 v11, vcc, 0, v9, vcc +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_or_b32_sdwa v1, v1, v12 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: flat_store_dwordx4 v[10:11], v[4:7] +; VI-NEXT: flat_store_dwordx4 v[8:9], v[0:3] +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v16bf16_3: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: s_load_dword s6, s[4:5], 0x10 +; GFX900-NEXT: v_lshlrev_b32_e32 v8, 5, v0 +; GFX900-NEXT: v_mov_b32_e32 v9, 0x5040100 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dwordx4 v[0:3], v8, s[2:3] +; GFX900-NEXT: global_load_dwordx4 v[4:7], v8, s[2:3] offset:16 +; GFX900-NEXT: s_waitcnt vmcnt(1) +; GFX900-NEXT: v_perm_b32 v1, s6, v1, v9 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: global_store_dwordx4 v8, v[4:7], s[0:1] offset:16 +; GFX900-NEXT: global_store_dwordx4 v8, v[0:3], s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v16bf16_3: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 +; GFX940-NEXT: s_load_dword s2, s[0:1], 0x10 +; GFX940-NEXT: v_lshlrev_b32_e32 v8, 5, v0 +; GFX940-NEXT: v_mov_b32_e32 v9, 0x5040100 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dwordx4 v[0:3], v8, s[6:7] +; GFX940-NEXT: global_load_dwordx4 v[4:7], v8, s[6:7] offset:16 +; GFX940-NEXT: s_waitcnt vmcnt(1) +; GFX940-NEXT: v_perm_b32 v1, s2, v1, v9 +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: global_store_dwordx4 v8, v[4:7], s[4:5] offset:16 sc0 sc1 +; GFX940-NEXT: global_store_dwordx4 v8, v[0:3], s[4:5] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <16 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <16 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <16 x bfloat>, ptr addrspace(1) %in.gep + %val.trunc = trunc i32 %val to i16 + %val.cvt = bitcast i16 %val.trunc to bfloat + %vecins = insertelement <16 x bfloat> %vec, bfloat %val.cvt, i32 3 + store <16 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +define amdgpu_kernel void @v_insertelement_v16bf16_dynamic(ptr addrspace(1) %out, ptr addrspace(1) %in, i32 %val, i32 %n) { +; SI-LABEL: v_insertelement_v16bf16_dynamic: +; SI: ; %bb.0: +; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; SI-NEXT: s_mov_b32 s11, 0x100f000 +; SI-NEXT: s_mov_b32 s10, 0 +; SI-NEXT: v_lshlrev_b32_e32 v4, 5, v0 +; SI-NEXT: v_mov_b32_e32 v5, 0 +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_mov_b64 s[8:9], s[2:3] +; SI-NEXT: buffer_load_dwordx4 v[7:10], v[4:5], s[8:11], 0 addr64 +; SI-NEXT: buffer_load_dwordx4 v[0:3], v[4:5], s[8:11], 0 addr64 offset:16 +; SI-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x4 +; SI-NEXT: s_mov_b64 s[2:3], s[10:11] +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: s_cmp_eq_u32 s5, 6 +; SI-NEXT: v_mov_b32_e32 v6, s4 +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 7 +; SI-NEXT: s_waitcnt vmcnt(1) +; SI-NEXT: v_cndmask_b32_e32 v11, v10, v6, vcc +; SI-NEXT: v_lshrrev_b32_e32 v10, 16, v10 +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 4 +; SI-NEXT: v_cndmask_b32_e32 v10, v10, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 5 +; SI-NEXT: v_lshrrev_b32_e32 v12, 16, v9 +; SI-NEXT: v_cndmask_b32_e32 v9, v9, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 2 +; SI-NEXT: v_and_b32_e32 v11, 0xffff, v11 +; SI-NEXT: v_lshlrev_b32_e32 v10, 16, v10 +; SI-NEXT: v_cndmask_b32_e32 v12, v12, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 3 +; SI-NEXT: v_lshrrev_b32_e32 v13, 16, v8 +; SI-NEXT: v_and_b32_e32 v9, 0xffff, v9 +; SI-NEXT: v_or_b32_e32 v10, v11, v10 +; SI-NEXT: v_lshlrev_b32_e32 v11, 16, v12 +; SI-NEXT: v_cndmask_b32_e32 v8, v8, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 0 +; SI-NEXT: v_or_b32_e32 v9, v9, v11 +; SI-NEXT: v_cndmask_b32_e32 v11, v13, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 1 +; SI-NEXT: v_lshrrev_b32_e32 v14, 16, v7 +; SI-NEXT: v_and_b32_e32 v8, 0xffff, v8 +; SI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 +; SI-NEXT: v_cndmask_b32_e32 v7, v7, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 14 +; SI-NEXT: v_or_b32_e32 v8, v8, v11 +; SI-NEXT: v_cndmask_b32_e32 v11, v14, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 15 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_lshrrev_b32_e32 v15, 16, v3 +; SI-NEXT: v_and_b32_e32 v7, 0xffff, v7 +; SI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 +; SI-NEXT: v_cndmask_b32_e32 v3, v3, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 12 +; SI-NEXT: v_or_b32_e32 v7, v7, v11 +; SI-NEXT: v_cndmask_b32_e32 v11, v15, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 13 +; SI-NEXT: v_lshrrev_b32_e32 v16, 16, v2 +; SI-NEXT: v_and_b32_e32 v3, 0xffff, v3 +; SI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 +; SI-NEXT: v_cndmask_b32_e32 v2, v2, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 10 +; SI-NEXT: v_or_b32_e32 v3, v3, v11 +; SI-NEXT: v_cndmask_b32_e32 v11, v16, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 11 +; SI-NEXT: v_lshrrev_b32_e32 v17, 16, v1 +; SI-NEXT: v_and_b32_e32 v2, 0xffff, v2 +; SI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 +; SI-NEXT: v_cndmask_b32_e32 v1, v1, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 8 +; SI-NEXT: v_or_b32_e32 v2, v2, v11 +; SI-NEXT: v_cndmask_b32_e32 v11, v17, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: s_cmp_eq_u32 s5, 9 +; SI-NEXT: v_lshrrev_b32_e32 v18, 16, v0 +; SI-NEXT: v_cndmask_b32_e32 v0, v0, v6, vcc +; SI-NEXT: s_cselect_b64 vcc, -1, 0 +; SI-NEXT: v_cndmask_b32_e32 v6, v18, v6, vcc +; SI-NEXT: v_and_b32_e32 v1, 0xffff, v1 +; SI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 +; SI-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; SI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 +; SI-NEXT: v_or_b32_e32 v1, v1, v11 +; SI-NEXT: v_or_b32_e32 v0, v0, v6 +; SI-NEXT: buffer_store_dwordx4 v[0:3], v[4:5], s[0:3], 0 addr64 offset:16 +; SI-NEXT: buffer_store_dwordx4 v[7:10], v[4:5], s[0:3], 0 addr64 +; SI-NEXT: s_endpgm +; +; VI-LABEL: v_insertelement_v16bf16_dynamic: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; VI-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x10 +; VI-NEXT: v_lshlrev_b32_e32 v8, 5, v0 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v0, s3 +; VI-NEXT: v_add_u32_e32 v4, vcc, s2, v8 +; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v0, vcc +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v4 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v5, vcc +; VI-NEXT: flat_load_dwordx4 v[0:3], v[0:1] +; VI-NEXT: flat_load_dwordx4 v[4:7], v[4:5] +; VI-NEXT: v_mov_b32_e32 v9, s1 +; VI-NEXT: v_add_u32_e32 v8, vcc, s0, v8 +; VI-NEXT: v_addc_u32_e32 v9, vcc, 0, v9, vcc +; VI-NEXT: v_add_u32_e32 v10, vcc, 16, v8 +; VI-NEXT: s_cmp_eq_u32 s5, 14 +; VI-NEXT: v_addc_u32_e32 v11, vcc, 0, v9, vcc +; VI-NEXT: v_mov_b32_e32 v12, s4 +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 15 +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_cndmask_b32_e32 v13, v3, v12, vcc +; VI-NEXT: v_lshrrev_b32_e32 v3, 16, v3 +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 12 +; VI-NEXT: v_cndmask_b32_e32 v3, v3, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 13 +; VI-NEXT: v_lshrrev_b32_e32 v14, 16, v2 +; VI-NEXT: v_cndmask_b32_e32 v2, v2, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 10 +; VI-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; VI-NEXT: v_cndmask_b32_e32 v14, v14, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 11 +; VI-NEXT: v_lshrrev_b32_e32 v15, 16, v1 +; VI-NEXT: v_or_b32_sdwa v3, v13, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: v_lshlrev_b32_e32 v13, 16, v14 +; VI-NEXT: v_cndmask_b32_e32 v1, v1, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 8 +; VI-NEXT: v_or_b32_sdwa v2, v2, v13 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: v_cndmask_b32_e32 v13, v15, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 9 +; VI-NEXT: v_lshrrev_b32_e32 v16, 16, v0 +; VI-NEXT: v_lshlrev_b32_e32 v13, 16, v13 +; VI-NEXT: v_cndmask_b32_e32 v0, v0, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 6 +; VI-NEXT: v_or_b32_sdwa v1, v1, v13 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: v_cndmask_b32_e32 v13, v16, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 7 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_lshrrev_b32_e32 v17, 16, v7 +; VI-NEXT: v_lshlrev_b32_e32 v13, 16, v13 +; VI-NEXT: v_cndmask_b32_e32 v7, v7, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 4 +; VI-NEXT: v_or_b32_sdwa v0, v0, v13 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: v_cndmask_b32_e32 v13, v17, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 5 +; VI-NEXT: v_lshrrev_b32_e32 v18, 16, v6 +; VI-NEXT: v_lshlrev_b32_e32 v13, 16, v13 +; VI-NEXT: v_cndmask_b32_e32 v6, v6, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 2 +; VI-NEXT: v_or_b32_sdwa v7, v7, v13 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: v_cndmask_b32_e32 v13, v18, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 3 +; VI-NEXT: v_lshrrev_b32_e32 v19, 16, v5 +; VI-NEXT: v_lshlrev_b32_e32 v13, 16, v13 +; VI-NEXT: v_cndmask_b32_e32 v5, v5, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 0 +; VI-NEXT: v_or_b32_sdwa v6, v6, v13 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: v_cndmask_b32_e32 v13, v19, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: s_cmp_eq_u32 s5, 1 +; VI-NEXT: v_lshrrev_b32_e32 v20, 16, v4 +; VI-NEXT: v_cndmask_b32_e32 v4, v4, v12, vcc +; VI-NEXT: s_cselect_b64 vcc, -1, 0 +; VI-NEXT: v_cndmask_b32_e32 v12, v20, v12, vcc +; VI-NEXT: v_lshlrev_b32_e32 v13, 16, v13 +; VI-NEXT: v_lshlrev_b32_e32 v12, 16, v12 +; VI-NEXT: v_or_b32_sdwa v5, v5, v13 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: v_or_b32_sdwa v4, v4, v12 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: flat_store_dwordx4 v[8:9], v[4:7] +; VI-NEXT: flat_store_dwordx4 v[10:11], v[0:3] +; VI-NEXT: s_endpgm +; +; GFX900-LABEL: v_insertelement_v16bf16_dynamic: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX900-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x10 +; GFX900-NEXT: v_lshlrev_b32_e32 v0, 5, v0 +; GFX900-NEXT: s_waitcnt lgkmcnt(0) +; GFX900-NEXT: global_load_dwordx4 v[1:4], v0, s[2:3] +; GFX900-NEXT: global_load_dwordx4 v[5:8], v0, s[2:3] offset:16 +; GFX900-NEXT: s_cmp_eq_u32 s7, 6 +; GFX900-NEXT: v_mov_b32_e32 v9, s6 +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 7 +; GFX900-NEXT: s_mov_b32 s2, 0x5040100 +; GFX900-NEXT: s_waitcnt vmcnt(1) +; GFX900-NEXT: v_cndmask_b32_e32 v10, v4, v9, vcc +; GFX900-NEXT: v_lshrrev_b32_e32 v4, 16, v4 +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 4 +; GFX900-NEXT: v_cndmask_b32_e32 v4, v4, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 5 +; GFX900-NEXT: v_lshrrev_b32_e32 v11, 16, v3 +; GFX900-NEXT: v_cndmask_b32_e32 v3, v3, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 2 +; GFX900-NEXT: v_perm_b32 v4, v4, v10, s2 +; GFX900-NEXT: v_cndmask_b32_e32 v10, v11, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 3 +; GFX900-NEXT: v_lshrrev_b32_e32 v12, 16, v2 +; GFX900-NEXT: v_cndmask_b32_e32 v2, v2, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 0 +; GFX900-NEXT: v_perm_b32 v3, v10, v3, s2 +; GFX900-NEXT: v_cndmask_b32_e32 v10, v12, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 1 +; GFX900-NEXT: v_lshrrev_b32_e32 v13, 16, v1 +; GFX900-NEXT: v_cndmask_b32_e32 v1, v1, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 14 +; GFX900-NEXT: v_perm_b32 v2, v10, v2, s2 +; GFX900-NEXT: v_cndmask_b32_e32 v10, v13, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 15 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_lshrrev_b32_e32 v14, 16, v8 +; GFX900-NEXT: v_cndmask_b32_e32 v8, v8, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 12 +; GFX900-NEXT: v_perm_b32 v1, v10, v1, s2 +; GFX900-NEXT: v_cndmask_b32_e32 v10, v14, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 13 +; GFX900-NEXT: v_lshrrev_b32_e32 v15, 16, v7 +; GFX900-NEXT: v_cndmask_b32_e32 v7, v7, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 10 +; GFX900-NEXT: v_perm_b32 v8, v10, v8, s2 +; GFX900-NEXT: v_cndmask_b32_e32 v10, v15, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 11 +; GFX900-NEXT: v_lshrrev_b32_e32 v16, 16, v6 +; GFX900-NEXT: v_cndmask_b32_e32 v6, v6, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 8 +; GFX900-NEXT: v_perm_b32 v7, v10, v7, s2 +; GFX900-NEXT: v_cndmask_b32_e32 v10, v16, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: s_cmp_eq_u32 s7, 9 +; GFX900-NEXT: v_lshrrev_b32_e32 v17, 16, v5 +; GFX900-NEXT: v_cndmask_b32_e32 v5, v5, v9, vcc +; GFX900-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX900-NEXT: v_cndmask_b32_e32 v9, v17, v9, vcc +; GFX900-NEXT: v_perm_b32 v6, v10, v6, s2 +; GFX900-NEXT: v_perm_b32 v5, v9, v5, s2 +; GFX900-NEXT: global_store_dwordx4 v0, v[5:8], s[0:1] offset:16 +; GFX900-NEXT: global_store_dwordx4 v0, v[1:4], s[0:1] +; GFX900-NEXT: s_endpgm +; +; GFX940-LABEL: v_insertelement_v16bf16_dynamic: +; GFX940: ; %bb.0: +; GFX940-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 +; GFX940-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x10 +; GFX940-NEXT: v_lshlrev_b32_e32 v8, 5, v0 +; GFX940-NEXT: s_mov_b32 s0, 0x5040100 +; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: global_load_dwordx4 v[0:3], v8, s[6:7] +; GFX940-NEXT: global_load_dwordx4 v[4:7], v8, s[6:7] offset:16 +; GFX940-NEXT: s_cmp_eq_u32 s3, 6 +; GFX940-NEXT: v_mov_b32_e32 v9, s2 +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 7 +; GFX940-NEXT: s_waitcnt vmcnt(1) +; GFX940-NEXT: v_cndmask_b32_e32 v10, v3, v9, vcc +; GFX940-NEXT: v_lshrrev_b32_e32 v3, 16, v3 +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 4 +; GFX940-NEXT: v_cndmask_b32_e32 v3, v3, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 5 +; GFX940-NEXT: v_lshrrev_b32_e32 v11, 16, v2 +; GFX940-NEXT: v_cndmask_b32_e32 v2, v2, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 2 +; GFX940-NEXT: v_perm_b32 v3, v3, v10, s0 +; GFX940-NEXT: v_cndmask_b32_e32 v10, v11, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 3 +; GFX940-NEXT: v_lshrrev_b32_e32 v12, 16, v1 +; GFX940-NEXT: v_cndmask_b32_e32 v1, v1, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 0 +; GFX940-NEXT: v_perm_b32 v2, v10, v2, s0 +; GFX940-NEXT: v_cndmask_b32_e32 v10, v12, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 1 +; GFX940-NEXT: v_lshrrev_b32_e32 v13, 16, v0 +; GFX940-NEXT: v_cndmask_b32_e32 v0, v0, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 14 +; GFX940-NEXT: v_perm_b32 v1, v10, v1, s0 +; GFX940-NEXT: v_cndmask_b32_e32 v10, v13, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 15 +; GFX940-NEXT: s_waitcnt vmcnt(0) +; GFX940-NEXT: v_lshrrev_b32_e32 v14, 16, v7 +; GFX940-NEXT: v_cndmask_b32_e32 v7, v7, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 12 +; GFX940-NEXT: v_perm_b32 v0, v10, v0, s0 +; GFX940-NEXT: v_cndmask_b32_e32 v10, v14, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 13 +; GFX940-NEXT: v_lshrrev_b32_e32 v15, 16, v6 +; GFX940-NEXT: v_cndmask_b32_e32 v6, v6, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 10 +; GFX940-NEXT: v_perm_b32 v7, v10, v7, s0 +; GFX940-NEXT: v_cndmask_b32_e32 v10, v15, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 11 +; GFX940-NEXT: v_lshrrev_b32_e32 v16, 16, v5 +; GFX940-NEXT: v_cndmask_b32_e32 v5, v5, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 8 +; GFX940-NEXT: v_perm_b32 v6, v10, v6, s0 +; GFX940-NEXT: v_cndmask_b32_e32 v10, v16, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: s_cmp_eq_u32 s3, 9 +; GFX940-NEXT: v_lshrrev_b32_e32 v17, 16, v4 +; GFX940-NEXT: v_cndmask_b32_e32 v4, v4, v9, vcc +; GFX940-NEXT: s_cselect_b64 vcc, -1, 0 +; GFX940-NEXT: v_cndmask_b32_e32 v9, v17, v9, vcc +; GFX940-NEXT: v_perm_b32 v5, v10, v5, s0 +; GFX940-NEXT: v_perm_b32 v4, v9, v4, s0 +; GFX940-NEXT: global_store_dwordx4 v8, v[4:7], s[4:5] offset:16 sc0 sc1 +; GFX940-NEXT: global_store_dwordx4 v8, v[0:3], s[4:5] sc0 sc1 +; GFX940-NEXT: s_endpgm +; + %tid = call i32 @llvm.amdgcn.workitem.id.x() #1 + %tid.ext = sext i32 %tid to i64 + %in.gep = getelementptr inbounds <16 x bfloat>, ptr addrspace(1) %in, i64 %tid.ext + %out.gep = getelementptr inbounds <16 x bfloat>, ptr addrspace(1) %out, i64 %tid.ext + %vec = load <16 x bfloat>, ptr addrspace(1) %in.gep + %val.trunc = trunc i32 %val to i16 + %val.cvt = bitcast i16 %val.trunc to bfloat + %vecins = insertelement <16 x bfloat> %vec, bfloat %val.cvt, i32 %n + store <16 x bfloat> %vecins, ptr addrspace(1) %out.gep + ret void +} + +declare i32 @llvm.amdgcn.workitem.id.x() #1 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } -- GitLab From 561c42df5712c346d4de2e6499b06712403d3164 Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Mon, 13 May 2024 23:56:01 +0200 Subject: [PATCH 137/578] [libc][errno] Use macro instead of system header (#91150) ## Why Currently, the system header `errno.h` is included in `libc_errno.h`, which is supposed to be consumed by internal implementations only. As unit and hermetic tests should never use `#include ` but instead use `#include "src/errno/libc_errno.h"`, we do not want to implicitly include `errno.h`. In order to have a clear seperation between those two, we want to pull out the definitions of errno numbers from `errno.h`. ## What * Extract the definitions of errno numbers from [include/errno.h.def](https://github.com/llvm/llvm-project/pull/91150/files#diff-ed38ed463ed50571b498a5b69039cab58dc9d145da7f751a24da9d77f07781cd) and place it under [include/llvm-libc-macros/linux/error-number-macros.h](https://github.com/llvm/llvm-project/pull/91150/files#diff-d6192866629690ebb7cefa1f0a90b6675073e9642f3279df08a04dcdb05fd892) * Provide mips-specific errno numbers in [include/llvm-libc-macros/linux/mips/error-number-macros.h](https://github.com/llvm/llvm-project/pull/91150/files#diff-3fd35a4c94e0cc359933e497b10311d857857b2e173e8afebc421b04b7527743) * Find definition of mips errno numbers in glibc [here](https://github.com/bminor/glibc/blob/ea73eb5f581ef5931fd67005aa0c526ba43366c9/sysdeps/unix/sysv/linux/mips/bits/errno.h#L32-L50) (equally defined in the Linux kernel) * Provide sparc-specific errno numbers in [include/llvm-libc-macros/linux/sparc/error-number-macros.h](https://github.com/llvm/llvm-project/pull/91150/files#diff-5f16ffb2a51a6f72ebd4403aca7e1edea48289c99dd5978a1c84385bec4f226b) * Find definition of sparc errno numbers in glibc [here](https://github.com/bminor/glibc/blob/ea73eb5f581ef5931fd67005aa0c526ba43366c9/sysdeps/unix/sysv/linux/sparc/bits/errno.h#L33-L51) (equally defined in the Linux kernel) * Include proxy header `errno_macros.h` instead of the system header `errno.h` in `libc_errno.h`/`libc_errno.cpp` Closes https://github.com/llvm/llvm-project/issues/80172 --- libc/hdr/CMakeLists.txt | 10 ++++++ libc/hdr/errno_macros.h | 26 +++++++++++++++ libc/include/errno.h.def | 20 +----------- libc/include/llvm-libc-macros/CMakeLists.txt | 6 ++++ .../llvm-libc-macros/error-number-macros.h | 8 +++++ .../generic-error-number-macros.h | 2 ++ .../llvm-libc-macros/linux/CMakeLists.txt | 12 +++++++ .../linux/error-number-macros.h | 32 +++++++++++++++++++ .../linux/mips/CMakeLists.txt | 5 +++ .../linux/mips/error-number-macros.h | 24 ++++++++++++++ .../linux/sparc/CMakeLists.txt | 5 +++ .../linux/sparc/error-number-macros.h | 24 ++++++++++++++ libc/src/errno/CMakeLists.txt | 2 +- libc/src/errno/libc_errno.cpp | 2 +- libc/src/errno/libc_errno.h | 6 +--- 15 files changed, 158 insertions(+), 26 deletions(-) create mode 100644 libc/hdr/errno_macros.h create mode 100644 libc/include/llvm-libc-macros/error-number-macros.h create mode 100644 libc/include/llvm-libc-macros/linux/error-number-macros.h create mode 100644 libc/include/llvm-libc-macros/linux/mips/CMakeLists.txt create mode 100644 libc/include/llvm-libc-macros/linux/mips/error-number-macros.h create mode 100644 libc/include/llvm-libc-macros/linux/sparc/CMakeLists.txt create mode 100644 libc/include/llvm-libc-macros/linux/sparc/error-number-macros.h diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt index 754934251430..91b8cb71552a 100644 --- a/libc/hdr/CMakeLists.txt +++ b/libc/hdr/CMakeLists.txt @@ -32,6 +32,16 @@ add_proxy_header_library( libc.include.math ) +add_proxy_header_library( + errno_macros + HDRS + errno_macros.h + FULL_BUILD_DEPENDS + libc.include.errno + libc.include.llvm-libc-macros.error_number_macros + libc.include.llvm-libc-macros.generic_error_number_macros +) + add_proxy_header_library( fcntl_macros HDRS diff --git a/libc/hdr/errno_macros.h b/libc/hdr/errno_macros.h new file mode 100644 index 000000000000..b5ef7dc2a207 --- /dev/null +++ b/libc/hdr/errno_macros.h @@ -0,0 +1,26 @@ +//===-- Definition of macros from errno.h ---------------------------------===// +// +// 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_HDR_ERRNO_MACROS_H +#define LLVM_LIBC_HDR_ERRNO_MACROS_H + +#ifdef LIBC_FULL_BUILD + +#ifdef __linux__ +#include "llvm-libc-macros/error-number-macros.h" +#else // __linux__ +#include "llvm-libc-macros/generic-error-number-macros.h" +#endif + +#else // Overlay mode + +#include + +#endif // LLVM_LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_ERRNO_MACROS_H diff --git a/libc/include/errno.h.def b/libc/include/errno.h.def index d7ae90ad4524..3ffcd3fe4c72 100644 --- a/libc/include/errno.h.def +++ b/libc/include/errno.h.def @@ -15,29 +15,11 @@ #include -#ifndef ERFKILL -#define ERFKILL 132 -#endif // ERFKILL - -#ifndef EOWNERDEAD -#define EOWNERDEAD 130 -#endif // EOWNERDEAD - -#ifndef EHWPOISON -#define EHWPOISON 133 -#endif // EHWPOISON - -#ifndef ECANCELED -#define ECANCELED 125 -#endif // ECANCELED - #ifndef ENOTSUP #define ENOTSUP EOPNOTSUPP #endif // ENOTSUP -#ifndef ENOTRECOVERABLE -#define ENOTRECOVERABLE 131 -#endif // ENOTRECOVERABLE +#include "llvm-libc-macros/linux/error-number-macros.h" #else // __linux__ #include "llvm-libc-macros/generic-error-number-macros.h" diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt index 68ba110aec80..961830ef9766 100644 --- a/libc/include/llvm-libc-macros/CMakeLists.txt +++ b/libc/include/llvm-libc-macros/CMakeLists.txt @@ -37,6 +37,12 @@ add_macro_header( assert-macros.h ) +add_macro_header( + error_number_macros + HDR + error-number-macros.h +) + add_macro_header( generic_error_number_macros HDR diff --git a/libc/include/llvm-libc-macros/error-number-macros.h b/libc/include/llvm-libc-macros/error-number-macros.h new file mode 100644 index 000000000000..29bd54d07f2e --- /dev/null +++ b/libc/include/llvm-libc-macros/error-number-macros.h @@ -0,0 +1,8 @@ +#ifndef LLVM_LIBC_MACROS_ERROR_NUMBER_MACROS_H +#define LLVM_LIBC_MACROS_ERROR_NUMBER_MACROS_H + +#ifdef __linux__ +#include "linux/error-number-macros.h" +#endif + +#endif // LLVM_LIBC_MACROS_ERROR_NUMBER_MACROS_H diff --git a/libc/include/llvm-libc-macros/generic-error-number-macros.h b/libc/include/llvm-libc-macros/generic-error-number-macros.h index 7ee0352669b8..b5b1b676dacc 100644 --- a/libc/include/llvm-libc-macros/generic-error-number-macros.h +++ b/libc/include/llvm-libc-macros/generic-error-number-macros.h @@ -44,5 +44,7 @@ #define EDOM 33 #define ERANGE 34 #define EILSEQ 35 +#define ENAMETOOLONG 36 +#define EOVERFLOW 75 #endif // LLVM_LIBC_MACROS_GENERIC_ERROR_NUMBER_MACROS_H diff --git a/libc/include/llvm-libc-macros/linux/CMakeLists.txt b/libc/include/llvm-libc-macros/linux/CMakeLists.txt index 4ee429d1db16..a07803103eef 100644 --- a/libc/include/llvm-libc-macros/linux/CMakeLists.txt +++ b/libc/include/llvm-libc-macros/linux/CMakeLists.txt @@ -1,3 +1,15 @@ +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/mips) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sparc) + +add_header( + error_number_macros + HDR + error-number-macros.h + DEPENDS + .mips.error_number_macros + .sparc.error_number_macros +) + add_header( fcntl_macros HDR diff --git a/libc/include/llvm-libc-macros/linux/error-number-macros.h b/libc/include/llvm-libc-macros/linux/error-number-macros.h new file mode 100644 index 000000000000..4c8b3feb3dc3 --- /dev/null +++ b/libc/include/llvm-libc-macros/linux/error-number-macros.h @@ -0,0 +1,32 @@ +#ifndef LLVM_LIBC_MACROS_LINUX_ERROR_NUMBER_MACROS_H +#define LLVM_LIBC_MACROS_LINUX_ERROR_NUMBER_MACROS_H + +#if defined(__mips__) +#include "mips/error-number-macros.h" + +#elif defined(__sparc__) +#include "sparc/error-number-macros.h" + +#else +#ifndef ECANCELED +#define ECANCELED 125 +#endif // ECANCELED + +#ifndef EOWNERDEAD +#define EOWNERDEAD 130 +#endif // EOWNERDEAD + +#ifndef ENOTRECOVERABLE +#define ENOTRECOVERABLE 131 +#endif // ENOTRECOVERABLE + +#ifndef ERFKILL +#define ERFKILL 132 +#endif // ERFKILL + +#ifndef EHWPOISON +#define EHWPOISON 133 +#endif // EHWPOISON +#endif + +#endif // LLVM_LIBC_MACROS_LINUX_ERROR_NUMBER_MACROS_H diff --git a/libc/include/llvm-libc-macros/linux/mips/CMakeLists.txt b/libc/include/llvm-libc-macros/linux/mips/CMakeLists.txt new file mode 100644 index 000000000000..eee4cfd19396 --- /dev/null +++ b/libc/include/llvm-libc-macros/linux/mips/CMakeLists.txt @@ -0,0 +1,5 @@ +add_header( + error_number_macros + HDR + error-number-macros.h +) diff --git a/libc/include/llvm-libc-macros/linux/mips/error-number-macros.h b/libc/include/llvm-libc-macros/linux/mips/error-number-macros.h new file mode 100644 index 000000000000..af2a4243e3ce --- /dev/null +++ b/libc/include/llvm-libc-macros/linux/mips/error-number-macros.h @@ -0,0 +1,24 @@ +#ifndef LLVM_LIBC_MACROS_LINUX_MIPS_ERROR_NUMBER_MACROS_H +#define LLVM_LIBC_MACROS_LINUX_MIPS_ERROR_NUMBER_MACROS_H + +#ifndef ECANCELED +#define ECANCELED 158 +#endif // ECANCELED + +#ifndef EOWNERDEAD +#define EOWNERDEAD 165 +#endif // EOWNERDEAD + +#ifndef ENOTRECOVERABLE +#define ENOTRECOVERABLE 166 +#endif // ENOTRECOVERABLE + +#ifndef ERFKILL +#define ERFKILL 167 +#endif // ERFKILL + +#ifndef EHWPOISON +#define EHWPOISON 168 +#endif // EHWPOISON + +#endif // LLVM_LIBC_MACROS_LINUX_MIPS_ERROR_NUMBER_MACROS_H diff --git a/libc/include/llvm-libc-macros/linux/sparc/CMakeLists.txt b/libc/include/llvm-libc-macros/linux/sparc/CMakeLists.txt new file mode 100644 index 000000000000..eee4cfd19396 --- /dev/null +++ b/libc/include/llvm-libc-macros/linux/sparc/CMakeLists.txt @@ -0,0 +1,5 @@ +add_header( + error_number_macros + HDR + error-number-macros.h +) diff --git a/libc/include/llvm-libc-macros/linux/sparc/error-number-macros.h b/libc/include/llvm-libc-macros/linux/sparc/error-number-macros.h new file mode 100644 index 000000000000..76a1408bf760 --- /dev/null +++ b/libc/include/llvm-libc-macros/linux/sparc/error-number-macros.h @@ -0,0 +1,24 @@ +#ifndef LLVM_LIBC_MACROS_LINUX_SPARC_ERROR_NUMBER_MACROS_H +#define LLVM_LIBC_MACROS_LINUX_SPARC_ERROR_NUMBER_MACROS_H + +#ifndef ECANCELED +#define ECANCELED 127 +#endif // ECANCELED + +#ifndef EOWNERDEAD +#define EOWNERDEAD 132 +#endif // EOWNERDEAD + +#ifndef ENOTRECOVERABLE +#define ENOTRECOVERABLE 133 +#endif // ENOTRECOVERABLE + +#ifndef ERFKILL +#define ERFKILL 134 +#endif // ERFKILL + +#ifndef EHWPOISON +#define EHWPOISON 135 +#endif // EHWPOISON + +#endif // LLVM_LIBC_MACROS_LINUX_SPARC_ERROR_NUMBER_MACROS_H diff --git a/libc/src/errno/CMakeLists.txt b/libc/src/errno/CMakeLists.txt index d9b8d9957c17..2622e51261cc 100644 --- a/libc/src/errno/CMakeLists.txt +++ b/libc/src/errno/CMakeLists.txt @@ -18,6 +18,6 @@ add_entrypoint_object( COMPILE_OPTIONS ${full_build_flag} DEPENDS - libc.include.errno + libc.hdr.errno_macros libc.src.__support.common ) diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp index 30b0a67a3241..a59e6c34029d 100644 --- a/libc/src/errno/libc_errno.cpp +++ b/libc/src/errno/libc_errno.cpp @@ -37,7 +37,7 @@ LIBC_NAMESPACE::Errno::operator int() { return __llvmlibc_errno; } #else // In overlay mode, we simply use the system errno. -#include +#include "hdr/errno_macros.h" void LIBC_NAMESPACE::Errno::operator=(int a) { errno = a; } LIBC_NAMESPACE::Errno::operator int() { return errno; } diff --git a/libc/src/errno/libc_errno.h b/libc/src/errno/libc_errno.h index 5afc0a41d348..df67ea3b42fa 100644 --- a/libc/src/errno/libc_errno.h +++ b/libc/src/errno/libc_errno.h @@ -12,11 +12,7 @@ #include "src/__support/macros/attributes.h" #include "src/__support/macros/properties/architectures.h" -// TODO: https://github.com/llvm/llvm-project/issues/80172 -// Separate just the definition of errno numbers in -// include/llvm-libc-macros/* and only include that instead of the system -// . -#include +#include "hdr/errno_macros.h" // This header is to be consumed by internal implementations, in which all of // them should refer to `libc_errno` instead of using `errno` directly from -- GitLab From c5e67b86ef6718585120e3cabb04c1fc2d292cfb Mon Sep 17 00:00:00 2001 From: Sayan Saha Date: Mon, 13 May 2024 18:18:20 -0400 Subject: [PATCH 138/578] [mlir] [tensor] Crash in getPackOpResultTypeShape for tensor.pack/unpack ops. (#90641) Windows build of `mlir` with Visual Studio (19.36.32538 for x64) using with the following command: `cmake.exe -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=mlir -DLLVM_ENABLE_EH=ON -DLLVM_ENABLE_RTTI=1 -DLLVM_TARGETS_TO_BUILD=host ../llvm` is leading to a crash when calling canonicalization on `tensor.pack`/`tensor.unpack` ops `mlir-opt --canonicalize input.mlir` where the `input.mlir` is as follows (this is taken from one of the filecheck tests for `tensor.pack`): ``` func.func @pack_unpack(%arg0: tensor<128x256xf32>) -> tensor<128x256xf32> { %pack_dest = tensor.empty() : tensor<8x16x8x32xf32> %unpack_dest = tensor.empty() : tensor<128x256xf32> %tp = tensor.pack %arg0 outer_dims_perm = [1, 0] inner_dims_pos = [0, 1] inner_tiles = [8, 32] into %pack_dest : tensor<128x256xf32> -> tensor<8x16x8x32xf32> %tup = tensor.unpack %tp outer_dims_perm = [1, 0] inner_dims_pos = [0, 1] inner_tiles = [8, 32] into %unpack_dest : tensor<8x16x8x32xf32> -> tensor<128x256xf32> return %tup : tensor<128x256xf32> } ``` The crash is seemingly coming from invalid memory access during iterating over `innerDimsPos` within `getPackOpResultTypeShape`. This crash is also causing the following tests to fail: ``` MLIR :: Dialect/Linalg/canonicalize.mlir MLIR :: Dialect/Linalg/data-layout-propagation.mlir MLIR :: Dialect/Linalg/generalize-tensor-pack-tile.mlir MLIR :: Dialect/Linalg/generalize-tensor-pack.mlir MLIR :: Dialect/Linalg/generalize-tensor-unpack-tile.mlir MLIR :: Dialect/Linalg/generalize-tensor-unpack.mlir MLIR :: Dialect/Linalg/transform-lower-pack.mlir MLIR :: Dialect/Linalg/transform-op-fuse.mlir MLIR :: Dialect/Linalg/transform-op-pack.mlir MLIR :: Dialect/Linalg/transform-pack-greedily.mlir MLIR :: Dialect/Tensor/canonicalize.mlir MLIR :: Dialect/Tensor/fold-into-pack-and-unpack.mlir MLIR :: Dialect/Tensor/invalid.mlir MLIR :: Dialect/Tensor/ops.mlir MLIR :: Dialect/Tensor/simplify-pack-unpack.mlir MLIR :: Dialect/Tensor/tiling.mlir ``` --- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index e41d59a0e0b9..414bd7459af8 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -3963,7 +3963,7 @@ static SmallVector getPackOpResultTypeShape( ArrayRef sourceShape, ArrayRef innerTileSizes, ArrayRef innerDimsPos, ArrayRef outerDimsPerm) { SmallVector resultShape = llvm::to_vector(sourceShape); - for (auto tiledDim : llvm::enumerate(innerDimsPos)) { + for (auto tiledDim : llvm::enumerate(llvm::to_vector(innerDimsPos))) { if (ShapedType::isDynamic(resultShape[tiledDim.value()])) continue; if (ShapedType::isDynamic(innerTileSizes[tiledDim.index()])) { @@ -3992,7 +3992,7 @@ SmallVector PackOp::getResultShape( AffineExpr s0, s1; bindSymbols(builder.getContext(), s0, s1); AffineExpr ceilDivExpr = s0.ceilDiv(s1); - for (auto tiledDim : llvm::enumerate(innerDimsPos)) { + for (auto tiledDim : llvm::enumerate(llvm::to_vector(innerDimsPos))) { resultDims[tiledDim.value()] = affine::makeComposedFoldedAffineApply( builder, loc, ceilDivExpr, {resultDims[tiledDim.value()], innerTileSizes[tiledDim.index()]}); -- GitLab From 8960078765f141c770f70629a205b3ea88cd9781 Mon Sep 17 00:00:00 2001 From: lntue <35648136+lntue@users.noreply.github.com> Date: Mon, 13 May 2024 18:31:35 -0400 Subject: [PATCH 139/578] [libc][errno] Include for Linux in full build mode. (#92041) --- libc/hdr/errno_macros.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libc/hdr/errno_macros.h b/libc/hdr/errno_macros.h index b5ef7dc2a207..198b5233d440 100644 --- a/libc/hdr/errno_macros.h +++ b/libc/hdr/errno_macros.h @@ -12,6 +12,8 @@ #ifdef LIBC_FULL_BUILD #ifdef __linux__ +#include + #include "llvm-libc-macros/error-number-macros.h" #else // __linux__ #include "llvm-libc-macros/generic-error-number-macros.h" -- GitLab From 943baf327409fdcb01c9d02aa3c3368f2fca114b Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 13 May 2024 15:47:35 -0700 Subject: [PATCH 140/578] [ELF] Make compareByFilePosition a strict weak order This fixes the new test linkerscript/enable-non-contiguous-regions.test from #90007 in -stdlib=libc++ -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG builds. adjustOutputSections does not discard the output section .potential_a because it contained .a (which would be spilled to .actual_a). .potential_a and .bc have the same address and will cause an assertion failure. --- lld/ELF/Writer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 8d529f2bdb9f..e8a7b19a95ee 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1338,9 +1338,11 @@ static bool compareByFilePosition(InputSection *a, InputSection *b) { OutputSection *aOut = la->getParent(); OutputSection *bOut = lb->getParent(); - if (aOut != bOut) - return aOut->addr < bOut->addr; - return la->outSecOff < lb->outSecOff; + if (aOut == bOut) + return la->outSecOff < lb->outSecOff; + if (aOut->addr == bOut->addr) + return aOut->sectionIndex < bOut->sectionIndex; + return aOut->addr < bOut->addr; } template void Writer::resolveShfLinkOrder() { -- GitLab From 531a0b67ea1ad65ea4d1a99c67fee280beeb8fbb Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Mon, 13 May 2024 15:50:16 -0700 Subject: [PATCH 141/578] [DirectX] Reapply Fix DXIL part header version encoding (#91956) This reapplies https://github.com/llvm/llvm-project/commit/195d8ac26d91ca798733c3a5f58d67992d43503d [DirectX] Fix DXIL part header version encoding. The endian issue was fixed by https://github.com/llvm/llvm-project/commit/f42117c8517cc928c6373bad35ebf75d94fe865b. Move MinorVersion be the lower 8 bit. Set DXIL version in DXContainerObjectWriter::writeObject. Fixes #89952 --- llvm/include/llvm/BinaryFormat/DXContainer.h | 2 +- llvm/include/llvm/TargetParser/Triple.h | 2 +- llvm/lib/MC/MCDXContainerWriter.cpp | 3 +++ llvm/lib/TargetParser/Triple.cpp | 2 ++ llvm/test/CodeGen/DirectX/embed-dxil.ll | 4 ++-- llvm/unittests/Object/DXContainerTest.cpp | 16 +++++++++------- 6 files changed, 18 insertions(+), 11 deletions(-) diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index 847d8103e681..013431faff27 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -103,8 +103,8 @@ struct PartHeader { struct BitcodeHeader { uint8_t Magic[4]; // ACSII "DXIL". - uint8_t MajorVersion; // DXIL version. uint8_t MinorVersion; // DXIL version. + uint8_t MajorVersion; // DXIL version. uint16_t Unused; uint32_t Offset; // Offset to LLVM bitcode (from start of header). uint32_t Size; // Size of LLVM bitcode (in bytes). diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 8f9d99816931..b3bb354b38ff 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -429,7 +429,7 @@ public: /// (SubArch). This should only be called with Vulkan SPIR-V triples. VersionTuple getVulkanVersion() const; - /// Parse the DXIL version number from the DXIL version + /// Parse the DXIL version number from the OSVersion and DXIL version /// (SubArch). This should only be called with DXIL triples. VersionTuple getDXILVersion() const; diff --git a/llvm/lib/MC/MCDXContainerWriter.cpp b/llvm/lib/MC/MCDXContainerWriter.cpp index ff64c6e538ac..1d82a7ec849f 100644 --- a/llvm/lib/MC/MCDXContainerWriter.cpp +++ b/llvm/lib/MC/MCDXContainerWriter.cpp @@ -129,6 +129,9 @@ uint64_t DXContainerObjectWriter::writeObject(MCAssembler &Asm, // The program header's size field is in 32-bit words. Header.Size = (SectionSize + sizeof(dxbc::ProgramHeader) + 3) / 4; memcpy(Header.Bitcode.Magic, "DXIL", 4); + VersionTuple DXILVersion = TT.getDXILVersion(); + Header.Bitcode.MajorVersion = DXILVersion.getMajor(); + Header.Bitcode.MinorVersion = DXILVersion.getMinor().value_or(0); Header.Bitcode.Offset = sizeof(dxbc::BitcodeHeader); Header.Bitcode.Size = SectionSize; if (sys::IsBigEndianHost) diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index f8269a51dc0b..4fc1ff5aaa05 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -1510,6 +1510,8 @@ VersionTuple Triple::getDXILVersion() const { if (getArch() != dxil || getOS() != ShaderModel) llvm_unreachable("invalid DXIL triple"); StringRef Arch = getArchName(); + if (getSubArch() == NoSubArch) + Arch = getDXILArchNameFromShaderModel(getOSName()); Arch.consume_front("dxilv"); VersionTuple DXILVersion = parseVersionFromName(Arch); // FIXME: validate DXIL version against Shader Model version. diff --git a/llvm/test/CodeGen/DirectX/embed-dxil.ll b/llvm/test/CodeGen/DirectX/embed-dxil.ll index 306e5c385b5a..9f4fb19d86fa 100644 --- a/llvm/test/CodeGen/DirectX/embed-dxil.ll +++ b/llvm/test/CodeGen/DirectX/embed-dxil.ll @@ -42,8 +42,8 @@ define i32 @add(i32 %a, i32 %b) { ; DXC-NEXT: MinorVersion: 5 ; DXC-NEXT: ShaderKind: 6 ; DXC-NEXT: Size: [[#div(SIZE,4)]] -; DXC-NEXT: DXILMajorVersion: [[#]] -; DXC-NEXT: DXILMinorVersion: [[#]] +; DXC-NEXT: DXILMajorVersion: 1 +; DXC-NEXT: DXILMinorVersion: 5 ; DXC-NEXT: DXILSize: [[#SIZE - 24]] ; DXC-NEXT: DXIL: [ 0x42, 0x43, 0xC0, 0xDE, ; DXC: - Name: SFI0 diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp index 115de47a3cef..9da6543c520c 100644 --- a/llvm/unittests/Object/DXContainerTest.cpp +++ b/llvm/unittests/Object/DXContainerTest.cpp @@ -215,6 +215,8 @@ TEST(DXCFile, ParseDXILPart) { EXPECT_EQ(Header.getMinorVersion(), 5u); EXPECT_EQ(Header.ShaderKind, 5u); EXPECT_EQ(Header.Size, 8u); + EXPECT_EQ(Header.Bitcode.MajorVersion, 1u); + EXPECT_EQ(Header.Bitcode.MinorVersion, 5u); } static Expected @@ -283,8 +285,8 @@ Parts: MinorVersion: 0 ShaderKind: 14 Size: 6 - DXILMajorVersion: 0 - DXILMinorVersion: 1 + DXILMajorVersion: 1 + DXILMinorVersion: 0 DXILSize: 0 ... )"; @@ -404,8 +406,8 @@ Parts: // MinorVersion: 0 // ShaderKind: 14 // Size: 6 -// DXILMajorVersion: 0 -// DXILMinorVersion: 1 +// DXILMajorVersion: 1 +// DXILMinorVersion: 0 // DXILSize: 0 // - Name: PSV0 // Size: 36 @@ -520,7 +522,7 @@ TEST(DXCFile, MaliciousFiles) { // // --- !dxcontainer // Header: -// Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +// Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] // Version: // Major: 1 @@ -534,8 +536,8 @@ TEST(DXCFile, MaliciousFiles) { // MinorVersion: 0 // ShaderKind: 14 // Size: 6 -// DXILMajorVersion: 0 -// DXILMinorVersion: 1 +// DXILMajorVersion: 1 +// DXILMinorVersion: 0 // DXILSize: 0 // - Name: PSV0 // Size: 100 -- GitLab From 6cfac497e96978f2bfc50a00b51c198f2ed50f82 Mon Sep 17 00:00:00 2001 From: Muhammad Omair Javaid Date: Tue, 14 May 2024 03:52:30 +0500 Subject: [PATCH 142/578] [lldb][DWARF] Mark delayed-definition-die-searching.test unsupported on Windows This marks delayed-definition-die-searching.test as unsupported on Windows. Clang uses link.exe as default linker if not marked explicitly to use lld. When used with link.exe clang produces PDB format debug info even when -gdwarf is specified. This test will be unsupported until we make lldb-aarch64-windows buildbot to use lld. --- .../SymbolFile/DWARF/delayed-definition-die-searching.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test index 836fcd7b587b..d253981b498c 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test +++ b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test @@ -1,5 +1,7 @@ # Test definition DIE searching is delayed until complete type is required. +# UNSUPPORTED: system-windows + # RUN: split-file %s %t # RUN: %clangxx_host %t/main.cpp %t/t1_def.cpp -gdwarf -o %t.out # RUN: %lldb -b %t.out -s %t/lldb.cmd | FileCheck %s -- GitLab From ec3bc2fbbf73c834697283a7066a8efe88bd0058 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 13 May 2024 15:51:10 -0700 Subject: [PATCH 143/578] [RISCV] Use printRegName in RISCVInstPrinter::printRlist. NFC Instead of hardcoding all of the register name strings. --- .../RISCV/MCTargetDesc/RISCVInstPrinter.cpp | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp index 2f127238a97f..663d4bad767d 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp @@ -222,30 +222,30 @@ void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo, O << "{"; switch (Imm) { case RISCVZC::RLISTENCODE::RA: - markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra"); + printRegName(O, RISCV::X1); break; case RISCVZC::RLISTENCODE::RA_S0: - markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra"); + printRegName(O, RISCV::X1); O << ", "; - markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0"); + printRegName(O, RISCV::X8); break; case RISCVZC::RLISTENCODE::RA_S0_S1: - markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra"); + printRegName(O, RISCV::X1); O << ", "; - markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0"); + printRegName(O, RISCV::X8); O << '-'; - markup(O, Markup::Register) << (ArchRegNames ? "x9" : "s1"); + printRegName(O, RISCV::X9); break; case RISCVZC::RLISTENCODE::RA_S0_S2: - markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra"); + printRegName(O, RISCV::X1); O << ", "; - markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0"); + printRegName(O, RISCV::X8); O << '-'; - markup(O, Markup::Register) << (ArchRegNames ? "x9" : "s2"); if (ArchRegNames) { + printRegName(O, RISCV::X9); O << ", "; - markup(O, Markup::Register) << "x18"; } + printRegName(O, RISCV::X18); break; case RISCVZC::RLISTENCODE::RA_S0_S3: case RISCVZC::RLISTENCODE::RA_S0_S4: @@ -255,20 +255,19 @@ void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo, case RISCVZC::RLISTENCODE::RA_S0_S8: case RISCVZC::RLISTENCODE::RA_S0_S9: case RISCVZC::RLISTENCODE::RA_S0_S11: - markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra"); + printRegName(O, RISCV::X1); O << ", "; - markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0"); + printRegName(O, RISCV::X8); O << '-'; if (ArchRegNames) { - markup(O, Markup::Register) << "x9"; + printRegName(O, RISCV::X9); O << ", "; - markup(O, Markup::Register) << "x18"; + printRegName(O, RISCV::X18); O << '-'; } - markup(O, Markup::Register) << getRegisterName( - RISCV::X19 + (Imm == RISCVZC::RLISTENCODE::RA_S0_S11 - ? 8 - : Imm - RISCVZC::RLISTENCODE::RA_S0_S3)); + printRegName(O, RISCV::X19 + (Imm == RISCVZC::RLISTENCODE::RA_S0_S11 + ? 8 + : Imm - RISCVZC::RLISTENCODE::RA_S0_S3)); break; default: llvm_unreachable("invalid register list"); -- GitLab From b342d18a8f0240342ea5c461145e78c6e3af92cc Mon Sep 17 00:00:00 2001 From: Schrodinger ZHU Yifan Date: Mon, 13 May 2024 19:00:19 -0400 Subject: [PATCH 144/578] [libc] add timeout and clock conversion utilities (#91905) This PR: - Make `clock_gettime` a header-only library - Add `clock_conversion` header library to allow conversion between clocks relative to the time of call - Add `timeout` header library to manage the absolute timeout used in POSIX's timed locking/waiting APIs --- .../__support/threads/linux/CMakeLists.txt | 2 +- .../src/__support/threads/linux/futex_utils.h | 11 ++-- libc/src/__support/time/linux/CMakeLists.txt | 33 +++++++++- libc/src/__support/time/linux/abs_timeout.h | 49 +++++++++++++++ .../__support/time/linux/clock_conversion.h | 42 +++++++++++++ .../__support/time/linux/clock_gettime.cpp | 35 ----------- libc/src/__support/time/linux/clock_gettime.h | 25 +++++++- libc/src/__support/time/linux/monotonicity.h | 43 +++++++++++++ libc/test/src/__support/CMakeLists.txt | 1 + libc/test/src/__support/time/CMakeLists.txt | 5 ++ .../src/__support/time/linux/CMakeLists.txt | 9 +++ .../src/__support/time/linux/timeout_test.cpp | 60 +++++++++++++++++++ 12 files changed, 267 insertions(+), 48 deletions(-) create mode 100644 libc/src/__support/time/linux/abs_timeout.h create mode 100644 libc/src/__support/time/linux/clock_conversion.h delete mode 100644 libc/src/__support/time/linux/clock_gettime.cpp create mode 100644 libc/src/__support/time/linux/monotonicity.h create mode 100644 libc/test/src/__support/time/CMakeLists.txt create mode 100644 libc/test/src/__support/time/linux/CMakeLists.txt create mode 100644 libc/test/src/__support/time/linux/timeout_test.cpp diff --git a/libc/src/__support/threads/linux/CMakeLists.txt b/libc/src/__support/threads/linux/CMakeLists.txt index 9bee30206f1b..d3353f6b3ff8 100644 --- a/libc/src/__support/threads/linux/CMakeLists.txt +++ b/libc/src/__support/threads/linux/CMakeLists.txt @@ -19,7 +19,7 @@ add_header_library( libc.src.__support.CPP.atomic libc.src.__support.CPP.limits libc.src.__support.CPP.optional - libc.hdr.types.struct_timespec + libc.src.__support.time.linux.abs_timeout ) add_header_library( diff --git a/libc/src/__support/threads/linux/futex_utils.h b/libc/src/__support/threads/linux/futex_utils.h index 1fbce4f7bf43..e40ade8e709b 100644 --- a/libc/src/__support/threads/linux/futex_utils.h +++ b/libc/src/__support/threads/linux/futex_utils.h @@ -9,23 +9,20 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_FUTEX_UTILS_H #define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_FUTEX_UTILS_H -#include "hdr/types/struct_timespec.h" #include "src/__support/CPP/atomic.h" #include "src/__support/CPP/limits.h" #include "src/__support/CPP/optional.h" #include "src/__support/OSUtil/syscall.h" #include "src/__support/macros/attributes.h" #include "src/__support/threads/linux/futex_word.h" +#include "src/__support/time/linux/abs_timeout.h" #include #include namespace LIBC_NAMESPACE { class Futex : public cpp::Atomic { public: - struct Timeout { - timespec abs_time; - bool is_realtime; - }; + using Timeout = internal::AbsTimeout; LIBC_INLINE constexpr Futex(FutexWordType value) : cpp::Atomic(value) {} LIBC_INLINE Futex &operator=(FutexWordType value) { @@ -37,7 +34,7 @@ public: bool is_shared = false) { // use bitset variants to enforce abs_time uint32_t op = is_shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE; - if (timeout && timeout->is_realtime) { + if (timeout && timeout->is_realtime()) { op |= FUTEX_CLOCK_REALTIME; } for (;;) { @@ -49,7 +46,7 @@ public: /* futex address */ this, /* futex operation */ op, /* expected value */ expected, - /* timeout */ timeout ? &timeout->abs_time : nullptr, + /* timeout */ timeout ? &timeout->get_timespec() : nullptr, /* ignored */ nullptr, /* bitset */ FUTEX_BITSET_MATCH_ANY); diff --git a/libc/src/__support/time/linux/CMakeLists.txt b/libc/src/__support/time/linux/CMakeLists.txt index f04d550555e1..1b41c7cb0a98 100644 --- a/libc/src/__support/time/linux/CMakeLists.txt +++ b/libc/src/__support/time/linux/CMakeLists.txt @@ -1,9 +1,7 @@ -add_object_library( +add_header_library( clock_gettime HDRS clock_gettime.h - SRCS - clock_gettime.cpp DEPENDS libc.include.sys_syscall libc.hdr.types.struct_timespec @@ -12,3 +10,32 @@ add_object_library( libc.src.__support.error_or libc.src.__support.OSUtil.osutil ) + +add_header_library( + clock_conversion + HDRS + clock_conversion.h + DEPENDS + .clock_gettime + libc.src.__support.time.units +) + +add_header_library( + abs_timeout + HDRS + abs_timeout.h + DEPENDS + libc.hdr.types.struct_timespec + libc.src.__support.time.units + libc.src.__support.CPP.expected +) + +add_header_library( + monotonicity + HDRS + monotonicity.h + DEPENDS + .clock_conversion + .abs_timeout + libc.hdr.time_macros +) diff --git a/libc/src/__support/time/linux/abs_timeout.h b/libc/src/__support/time/linux/abs_timeout.h new file mode 100644 index 000000000000..6e5e59b32b7a --- /dev/null +++ b/libc/src/__support/time/linux/abs_timeout.h @@ -0,0 +1,49 @@ +//===--- Linux absolute timeout ---------------------------------*- 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___SUPPORT_TIME_LINUX_ABS_TIMEOUT_H +#define LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_ABS_TIMEOUT_H + +#include "hdr/time_macros.h" +#include "hdr/types/struct_timespec.h" +#include "src/__support/CPP/expected.h" +#include "src/__support/time/units.h" + +namespace LIBC_NAMESPACE { +namespace internal { +// We use AbsTimeout to remind ourselves that the timeout is an absolute time. +// This is a simple wrapper around the timespec struct that also keeps track of +// whether the time is in realtime or monotonic time. +class AbsTimeout { + timespec timeout; + bool realtime_flag; + LIBC_INLINE constexpr explicit AbsTimeout(timespec ts, bool realtime) + : timeout(ts), realtime_flag(realtime) {} + +public: + enum class Error { Invalid, BeforeEpoch }; + LIBC_INLINE const timespec &get_timespec() const { return timeout; } + LIBC_INLINE bool is_realtime() const { return realtime_flag; } + LIBC_INLINE static constexpr cpp::expected + from_timespec(timespec ts, bool realtime) { + using namespace time_units; + if (ts.tv_nsec < 0 || ts.tv_nsec >= 1_s_ns) + return cpp::unexpected(Error::Invalid); + + // POSIX allows tv_sec to be negative. We interpret this as an expired + // timeout. + if (ts.tv_sec < 0) + return cpp::unexpected(Error::BeforeEpoch); + + return AbsTimeout{ts, realtime}; + } +}; +} // namespace internal +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_ABS_TIMEOUT_H diff --git a/libc/src/__support/time/linux/clock_conversion.h b/libc/src/__support/time/linux/clock_conversion.h new file mode 100644 index 000000000000..4a7c8ff28484 --- /dev/null +++ b/libc/src/__support/time/linux/clock_conversion.h @@ -0,0 +1,42 @@ +//===--- clock conversion linux implementation ------------------*- 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___SUPPORT_TIME_LINUX_CLOCK_CONVERSION_H +#define LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_CLOCK_CONVERSION_H + +#include "src/__support/time/linux/clock_gettime.h" +#include "src/__support/time/units.h" + +namespace LIBC_NAMESPACE { +namespace internal { + +LIBC_INLINE timespec convert_clock(timespec input, clockid_t from, + clockid_t to) { + using namespace time_units; + timespec from_time; + timespec to_time; + timespec output; + internal::clock_gettime(from, &from_time); + internal::clock_gettime(to, &to_time); + output.tv_sec = input.tv_sec - from_time.tv_sec + to_time.tv_sec; + output.tv_nsec = input.tv_nsec - from_time.tv_nsec + to_time.tv_nsec; + + if (output.tv_nsec > 1_s_ns) { + output.tv_sec++; + output.tv_nsec -= 1_s_ns; + } else if (output.tv_nsec < 0) { + output.tv_sec--; + output.tv_nsec += 1_s_ns; + } + return output; +} + +} // namespace internal +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_CLOCK_CONVERSION_H diff --git a/libc/src/__support/time/linux/clock_gettime.cpp b/libc/src/__support/time/linux/clock_gettime.cpp deleted file mode 100644 index 7f266b282a39..000000000000 --- a/libc/src/__support/time/linux/clock_gettime.cpp +++ /dev/null @@ -1,35 +0,0 @@ -//===--- clock_gettime linux implementation ---------------------*- 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/time/linux/clock_gettime.h" -#include "src/__support/OSUtil/syscall.h" -#include -namespace LIBC_NAMESPACE { -namespace internal { -ErrorOr clock_gettime(clockid_t clockid, timespec *ts) { -#if SYS_clock_gettime - int ret = LIBC_NAMESPACE::syscall_impl(SYS_clock_gettime, - static_cast(clockid), - reinterpret_cast(ts)); -#elif defined(SYS_clock_gettime64) - static_assert( - sizeof(time_t) == sizeof(int64_t), - "SYS_clock_gettime64 requires struct timespec with 64-bit members."); - int ret = LIBC_NAMESPACE::syscall_impl(SYS_clock_gettime64, - static_cast(clockid), - reinterpret_cast(ts)); -#else -#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available." -#endif - if (ret < 0) - return Error(-ret); - return ret; -} - -} // namespace internal -} // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/time/linux/clock_gettime.h b/libc/src/__support/time/linux/clock_gettime.h index b1572726f630..bbdde98551ab 100644 --- a/libc/src/__support/time/linux/clock_gettime.h +++ b/libc/src/__support/time/linux/clock_gettime.h @@ -8,16 +8,37 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_CLOCK_GETTIME_H #define LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_CLOCK_GETTIME_H + #include "hdr/types/clockid_t.h" #include "hdr/types/struct_timespec.h" +#include "src/__support/OSUtil/syscall.h" #include "src/__support/common.h" - #include "src/__support/error_or.h" +#include namespace LIBC_NAMESPACE { namespace internal { -ErrorOr clock_gettime(clockid_t clockid, timespec *ts); +LIBC_INLINE ErrorOr clock_gettime(clockid_t clockid, timespec *ts) { +#if SYS_clock_gettime + int ret = LIBC_NAMESPACE::syscall_impl(SYS_clock_gettime, + static_cast(clockid), + reinterpret_cast(ts)); +#elif defined(SYS_clock_gettime64) + static_assert( + sizeof(time_t) == sizeof(int64_t), + "SYS_clock_gettime64 requires struct timespec with 64-bit members."); + int ret = LIBC_NAMESPACE::syscall_impl(SYS_clock_gettime64, + static_cast(clockid), + reinterpret_cast(ts)); +#else +#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available." +#endif + if (ret < 0) + return Error(-ret); + return ret; } + +} // namespace internal } // namespace LIBC_NAMESPACE #endif // LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_CLOCK_GETTIME_H diff --git a/libc/src/__support/time/linux/monotonicity.h b/libc/src/__support/time/linux/monotonicity.h new file mode 100644 index 000000000000..e413275430dd --- /dev/null +++ b/libc/src/__support/time/linux/monotonicity.h @@ -0,0 +1,43 @@ +//===--- timeout linux implementation ---------------------------*- 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___SUPPORT_TIME_LINUX_MONOTONICITY_H +#define LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_MONOTONICITY_H + +#include "hdr/time_macros.h" +#include "src/__support/libc_assert.h" +#include "src/__support/time/linux/abs_timeout.h" +#include "src/__support/time/linux/clock_conversion.h" +namespace LIBC_NAMESPACE { +namespace internal { +// This function is separated from abs_timeout. +// This function pulls in the dependency to clock_conversion.h, +// which may transitively depend on vDSO hence futex. However, this structure +// would be passed to futex, so we need to avoid cyclic dependencies. +// This function is going to be used in timed locks. Pthread generally uses +// realtime clocks for timeouts. However, due to non-monotoncity, realtime +// clocks reportedly lead to undesired behaviors. Therefore, we also provide a +// method to convert the timespec to a monotonic clock relative to the time of +// function call. +LIBC_INLINE void ensure_monotonicity(AbsTimeout &timeout) { + if (timeout.is_realtime()) { + auto res = AbsTimeout::from_timespec( + convert_clock(timeout.get_timespec(), CLOCK_REALTIME, CLOCK_MONOTONIC), + false); + + LIBC_ASSERT(res.has_value()); + if (!res.has_value()) + __builtin_unreachable(); + + timeout = *res; + } +} +} // namespace internal +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_MONOTONICITY_H diff --git a/libc/test/src/__support/CMakeLists.txt b/libc/test/src/__support/CMakeLists.txt index 5d1230f5f3a7..8bdc56ee59cc 100644 --- a/libc/test/src/__support/CMakeLists.txt +++ b/libc/test/src/__support/CMakeLists.txt @@ -206,3 +206,4 @@ add_subdirectory(OSUtil) add_subdirectory(FPUtil) add_subdirectory(fixed_point) add_subdirectory(HashTable) +add_subdirectory(time) diff --git a/libc/test/src/__support/time/CMakeLists.txt b/libc/test/src/__support/time/CMakeLists.txt new file mode 100644 index 000000000000..37062e131acf --- /dev/null +++ b/libc/test/src/__support/time/CMakeLists.txt @@ -0,0 +1,5 @@ +add_custom_target(libc-support-time-tests) + +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) + add_subdirectory(${LIBC_TARGET_OS}) +endif() diff --git a/libc/test/src/__support/time/linux/CMakeLists.txt b/libc/test/src/__support/time/linux/CMakeLists.txt new file mode 100644 index 000000000000..3174986283dd --- /dev/null +++ b/libc/test/src/__support/time/linux/CMakeLists.txt @@ -0,0 +1,9 @@ +add_libc_test( + timeout_test + SUITE libc-support-time-tests + SRCS timeout_test.cpp + DEPENDS + libc.src.__support.time.linux.abs_timeout + libc.src.__support.time.linux.monotonicity + libc.src.__support.CPP.expected +) diff --git a/libc/test/src/__support/time/linux/timeout_test.cpp b/libc/test/src/__support/time/linux/timeout_test.cpp new file mode 100644 index 000000000000..886d4389709e --- /dev/null +++ b/libc/test/src/__support/time/linux/timeout_test.cpp @@ -0,0 +1,60 @@ +//===-- unit tests for linux's timeout utilities --------------------------===// +// +// 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/CPP/expected.h" +#include "src/__support/time/linux/abs_timeout.h" +#include "src/__support/time/linux/monotonicity.h" +#include "test/UnitTest/Test.h" + +template +using expected = LIBC_NAMESPACE::cpp::expected; +using AbsTimeout = LIBC_NAMESPACE::internal::AbsTimeout; + +TEST(LlvmLibcSupportLinuxTimeoutTest, NegativeSecond) { + timespec ts = {-1, 0}; + expected result = + AbsTimeout::from_timespec(ts, false); + ASSERT_FALSE(result.has_value()); + ASSERT_EQ(result.error(), AbsTimeout::Error::BeforeEpoch); +} +TEST(LlvmLibcSupportLinuxTimeoutTest, OverflowNano) { + using namespace LIBC_NAMESPACE::time_units; + timespec ts = {0, 2_s_ns}; + expected result = + AbsTimeout::from_timespec(ts, false); + ASSERT_FALSE(result.has_value()); + ASSERT_EQ(result.error(), AbsTimeout::Error::Invalid); +} +TEST(LlvmLibcSupportLinuxTimeoutTest, UnderflowNano) { + timespec ts = {0, -1}; + expected result = + AbsTimeout::from_timespec(ts, false); + ASSERT_FALSE(result.has_value()); + ASSERT_EQ(result.error(), AbsTimeout::Error::Invalid); +} +TEST(LlvmLibcSupportLinuxTimeoutTest, NoChangeIfClockIsMonotonic) { + timespec ts = {10000, 0}; + expected result = + AbsTimeout::from_timespec(ts, false); + ASSERT_TRUE(result.has_value()); + ensure_monotonicity(*result); + ASSERT_FALSE(result->is_realtime()); + ASSERT_EQ(result->get_timespec().tv_sec, static_cast(10000)); + ASSERT_EQ(result->get_timespec().tv_nsec, static_cast(0)); +} +TEST(LlvmLibcSupportLinuxTimeoutTest, ValidAfterConversion) { + timespec ts; + LIBC_NAMESPACE::internal::clock_gettime(CLOCK_REALTIME, &ts); + expected result = + AbsTimeout::from_timespec(ts, true); + ASSERT_TRUE(result.has_value()); + ensure_monotonicity(*result); + ASSERT_FALSE(result->is_realtime()); + ASSERT_TRUE( + AbsTimeout::from_timespec(result->get_timespec(), false).has_value()); +} -- GitLab From 5b6f15110422f4955212bd26a96057972e3304ad Mon Sep 17 00:00:00 2001 From: Lei Wang Date: Mon, 13 May 2024 16:01:29 -0700 Subject: [PATCH 145/578] [SampleFDO] Improve stale profile matching by diff algorithm (#87375) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change improves the matching algorithm by using the diff algorithm, the current matching algorithm only processes the callsites grouped by the same name functions, it doesn't consider the order relationships between different name functions, this sometimes fails to handle this ambiguous anchor case. For example. (`Foo:1` means a calliste[callee_name: callsite_location]) ``` IR : foo:1 bar:2 foo:4 bar:5 Profile : bar:3 foo:5 bar:6 ``` The `foo:1` is matched to the 2nd `foo:5` and using the diff algorithm(finding longest common subsequence ) can help on this issue. One well-known diff algorithm is the Myers diff algorithm(paper "An O(ND) Difference Algorithm and Its Variations∗" Eugene W. Myers), its variations have been implemented and used in many famous tools, like the GNU diff or git diff. It provides an efficient way to find the longest common subsequence or the shortest edit script through graph searching. There are several variations/refinements for the algorithm, but as in our case, the num of function callsites is usually very small, so we implemented the basic greedy version in this change which should be good enough. We observed better matchings and positive perf improvement on our internal services. --- .../Transforms/IPO/SampleProfileMatcher.h | 46 ++- .../Transforms/IPO/SampleProfileMatcher.cpp | 290 +++++++++++------- ...eudo-probe-stale-profile-matching-LCS.prof | 26 ++ ...pseudo-probe-stale-profile-matching-LCS.ll | 219 +++++++++++++ .../pseudo-probe-stale-profile-matching.ll | 2 +- 5 files changed, 457 insertions(+), 126 deletions(-) create mode 100644 llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-stale-profile-matching-LCS.prof create mode 100644 llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-LCS.ll diff --git a/llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h b/llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h index 7ae6194da7c9..b6feca5d4703 100644 --- a/llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h +++ b/llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h @@ -19,6 +19,9 @@ namespace llvm { +using AnchorList = std::vector>; +using AnchorMap = std::map; + // Sample profile matching - fuzzy match. class SampleProfileMatcher { Module &M; @@ -27,8 +30,8 @@ class SampleProfileMatcher { const ThinOrFullLTOPhase LTOPhase; SampleProfileMap FlattenedProfiles; // For each function, the matcher generates a map, of which each entry is a - // mapping from the source location of current build to the source location in - // the profile. + // mapping from the source location of current build to the source location + // in the profile. StringMap FuncMappings; // Match state for an anchor/callsite. @@ -95,18 +98,13 @@ private: return nullptr; } void runOnFunction(Function &F); - void findIRAnchors(const Function &F, - std::map &IRAnchors); - void findProfileAnchors( - const FunctionSamples &FS, - std::map> &ProfileAnchors); + void findIRAnchors(const Function &F, AnchorMap &IRAnchors); + void findProfileAnchors(const FunctionSamples &FS, AnchorMap &ProfileAnchors); // Record the callsite match states for profile staleness report, the result // is saved in FuncCallsiteMatchStates. - void recordCallsiteMatchStates( - const Function &F, const std::map &IRAnchors, - const std::map> - &ProfileAnchors, - const LocToLocMap *IRToProfileLocationMap); + void recordCallsiteMatchStates(const Function &F, const AnchorMap &IRAnchors, + const AnchorMap &ProfileAnchors, + const LocToLocMap *IRToProfileLocationMap); bool isMismatchState(const enum MatchState &State) { return State == MatchState::InitialMismatch || @@ -143,11 +141,25 @@ private: } void distributeIRToProfileLocationMap(); void distributeIRToProfileLocationMap(FunctionSamples &FS); - void runStaleProfileMatching( - const Function &F, const std::map &IRAnchors, - const std::map> - &ProfileAnchors, - LocToLocMap &IRToProfileLocationMap); + // This function implements the Myers diff algorithm used for stale profile + // matching. The algorithm provides a simple and efficient way to find the + // Longest Common Subsequence(LCS) or the Shortest Edit Script(SES) of two + // sequences. For more details, refer to the paper 'An O(ND) Difference + // Algorithm and Its Variations' by Eugene W. Myers. + // In the scenario of profile fuzzy matching, the two sequences are the IR + // callsite anchors and profile callsite anchors. The subsequence equivalent + // parts from the resulting SES are used to remap the IR locations to the + // profile locations. As the number of function callsite is usually not big, + // we currently just implements the basic greedy version(page 6 of the paper). + LocToLocMap + longestCommonSequence(const AnchorList &IRCallsiteAnchors, + const AnchorList &ProfileCallsiteAnchors) const; + void matchNonCallsiteLocs(const LocToLocMap &AnchorMatchings, + const AnchorMap &IRAnchors, + LocToLocMap &IRToProfileLocationMap); + void runStaleProfileMatching(const Function &F, const AnchorMap &IRAnchors, + const AnchorMap &ProfileAnchors, + LocToLocMap &IRToProfileLocationMap); void reportOrPersistProfileStats(); }; } // end namespace llvm diff --git a/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp b/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp index 142660bcc58e..d7613bce4c52 100644 --- a/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp @@ -24,8 +24,8 @@ extern cl::opt SalvageStaleProfile; extern cl::opt PersistProfileStaleness; extern cl::opt ReportProfileStaleness; -void SampleProfileMatcher::findIRAnchors( - const Function &F, std::map &IRAnchors) { +void SampleProfileMatcher::findIRAnchors(const Function &F, + AnchorMap &IRAnchors) { // For inlined code, recover the original callsite and callee by finding the // top-level inline frame. e.g. For frame stack "main:1 @ foo:2 @ bar:3", the // top-level frame is "main:1", the callsite is "1" and the callee is "foo". @@ -40,7 +40,7 @@ void SampleProfileMatcher::findIRAnchors( LineLocation Callsite = FunctionSamples::getCallSiteIdentifier( DIL, FunctionSamples::ProfileIsFS); StringRef CalleeName = PrevDIL->getSubprogramLinkageName(); - return std::make_pair(Callsite, CalleeName); + return std::make_pair(Callsite, FunctionId(CalleeName)); }; auto GetCanonicalCalleeName = [](const CallBase *CB) { @@ -70,7 +70,8 @@ void SampleProfileMatcher::findIRAnchors( if (!isa(&I)) CalleeName = GetCanonicalCalleeName(CB); } - IRAnchors.emplace(LineLocation(Probe->Id, 0), CalleeName); + LineLocation Loc = LineLocation(Probe->Id, 0); + IRAnchors.emplace(Loc, FunctionId(CalleeName)); } } } else { @@ -86,84 +87,127 @@ void SampleProfileMatcher::findIRAnchors( LineLocation Callsite = FunctionSamples::getCallSiteIdentifier( DIL, FunctionSamples::ProfileIsFS); StringRef CalleeName = GetCanonicalCalleeName(dyn_cast(&I)); - IRAnchors.emplace(Callsite, CalleeName); + IRAnchors.emplace(Callsite, FunctionId(CalleeName)); } } } } } -void SampleProfileMatcher::findProfileAnchors( - const FunctionSamples &FS, - std::map> &ProfileAnchors) { +void SampleProfileMatcher::findProfileAnchors(const FunctionSamples &FS, + AnchorMap &ProfileAnchors) { auto isInvalidLineOffset = [](uint32_t LineOffset) { return LineOffset & 0x8000; }; + auto InsertAnchor = [](const LineLocation &Loc, const FunctionId &CalleeName, + AnchorMap &ProfileAnchors) { + auto Ret = ProfileAnchors.try_emplace(Loc, CalleeName); + if (!Ret.second) { + // For multiple callees, which indicates it's an indirect call, we use a + // dummy name(UnknownIndirectCallee) as the indrect callee name. + Ret.first->second = FunctionId(UnknownIndirectCallee); + } + }; + for (const auto &I : FS.getBodySamples()) { const LineLocation &Loc = I.first; if (isInvalidLineOffset(Loc.LineOffset)) continue; - for (const auto &I : I.second.getCallTargets()) { - auto Ret = - ProfileAnchors.try_emplace(Loc, std::unordered_set()); - Ret.first->second.insert(I.first); - } + for (const auto &C : I.second.getCallTargets()) + InsertAnchor(Loc, C.first, ProfileAnchors); } for (const auto &I : FS.getCallsiteSamples()) { const LineLocation &Loc = I.first; if (isInvalidLineOffset(Loc.LineOffset)) continue; - const auto &CalleeMap = I.second; - for (const auto &I : CalleeMap) { - auto Ret = - ProfileAnchors.try_emplace(Loc, std::unordered_set()); - Ret.first->second.insert(I.first); - } + for (const auto &C : I.second) + InsertAnchor(Loc, C.first, ProfileAnchors); } } -// Call target name anchor based profile fuzzy matching. -// Input: -// For IR locations, the anchor is the callee name of direct callsite; For -// profile locations, it's the call target name for BodySamples or inlinee's -// profile name for CallsiteSamples. -// Matching heuristic: -// First match all the anchors in lexical order, then split the non-anchor -// locations between the two anchors evenly, first half are matched based on the -// start anchor, second half are matched based on the end anchor. -// For example, given: -// IR locations: [1, 2(foo), 3, 5, 6(bar), 7] -// Profile locations: [1, 2, 3(foo), 4, 7, 8(bar), 9] -// The matching gives: -// [1, 2(foo), 3, 5, 6(bar), 7] -// | | | | | | -// [1, 2, 3(foo), 4, 7, 8(bar), 9] -// The output mapping: [2->3, 3->4, 5->7, 6->8, 7->9]. -void SampleProfileMatcher::runStaleProfileMatching( - const Function &F, const std::map &IRAnchors, - const std::map> - &ProfileAnchors, - LocToLocMap &IRToProfileLocationMap) { - LLVM_DEBUG(dbgs() << "Run stale profile matching for " << F.getName() - << "\n"); - assert(IRToProfileLocationMap.empty() && - "Run stale profile matching only once per function"); +LocToLocMap SampleProfileMatcher::longestCommonSequence( + const AnchorList &AnchorList1, const AnchorList &AnchorList2) const { + int32_t Size1 = AnchorList1.size(), Size2 = AnchorList2.size(), + MaxDepth = Size1 + Size2; + auto Index = [&](int32_t I) { return I + MaxDepth; }; + + LocToLocMap EqualLocations; + if (MaxDepth == 0) + return EqualLocations; + + // Backtrack the SES result. + auto Backtrack = [&](const std::vector> &Trace, + const AnchorList &AnchorList1, + const AnchorList &AnchorList2, + LocToLocMap &EqualLocations) { + int32_t X = Size1, Y = Size2; + for (int32_t Depth = Trace.size() - 1; X > 0 || Y > 0; Depth--) { + const auto &P = Trace[Depth]; + int32_t K = X - Y; + int32_t PrevK = K; + if (K == -Depth || (K != Depth && P[Index(K - 1)] < P[Index(K + 1)])) + PrevK = K + 1; + else + PrevK = K - 1; + + int32_t PrevX = P[Index(PrevK)]; + int32_t PrevY = PrevX - PrevK; + while (X > PrevX && Y > PrevY) { + X--; + Y--; + EqualLocations.insert({AnchorList1[X].first, AnchorList2[Y].first}); + } - std::unordered_map> CalleeToCallsitesMap; - for (const auto &I : ProfileAnchors) { - const auto &Loc = I.first; - const auto &Callees = I.second; - // Filter out possible indirect calls, use direct callee name as anchor. - if (Callees.size() == 1) { - FunctionId CalleeName = *Callees.begin(); - const auto &Candidates = CalleeToCallsitesMap.try_emplace( - CalleeName, std::set()); - Candidates.first->second.insert(Loc); + if (Depth == 0) + break; + + if (Y == PrevY) + X--; + else if (X == PrevX) + Y--; + X = PrevX; + Y = PrevY; + } + }; + + // The greedy LCS/SES algorithm. + + // An array contains the endpoints of the furthest reaching D-paths. + std::vector V(2 * MaxDepth + 1, -1); + V[Index(1)] = 0; + // Trace is used to backtrack the SES result. + std::vector> Trace; + for (int32_t Depth = 0; Depth <= MaxDepth; Depth++) { + Trace.push_back(V); + for (int32_t K = -Depth; K <= Depth; K += 2) { + int32_t X = 0, Y = 0; + if (K == -Depth || (K != Depth && V[Index(K - 1)] < V[Index(K + 1)])) + X = V[Index(K + 1)]; + else + X = V[Index(K - 1)] + 1; + Y = X - K; + while (X < Size1 && Y < Size2 && + AnchorList1[X].second == AnchorList2[Y].second) + X++, Y++; + + V[Index(K)] = X; + + if (X >= Size1 && Y >= Size2) { + // Length of an SES is D. + Backtrack(Trace, AnchorList1, AnchorList2, EqualLocations); + return EqualLocations; + } } } + // Length of an SES is greater than MaxDepth. + return EqualLocations; +} +void SampleProfileMatcher::matchNonCallsiteLocs( + const LocToLocMap &MatchedAnchors, const AnchorMap &IRAnchors, + LocToLocMap &IRToProfileLocationMap) { auto InsertMatching = [&](const LineLocation &From, const LineLocation &To) { // Skip the unchanged location mapping to save memory. if (From != To) @@ -173,43 +217,35 @@ void SampleProfileMatcher::runStaleProfileMatching( // Use function's beginning location as the initial anchor. int32_t LocationDelta = 0; SmallVector LastMatchedNonAnchors; - for (const auto &IR : IRAnchors) { const auto &Loc = IR.first; - auto CalleeName = IR.second; bool IsMatchedAnchor = false; // Match the anchor location in lexical order. - if (!CalleeName.empty()) { - auto CandidateAnchors = - CalleeToCallsitesMap.find(getRepInFormat(CalleeName)); - if (CandidateAnchors != CalleeToCallsitesMap.end() && - !CandidateAnchors->second.empty()) { - auto CI = CandidateAnchors->second.begin(); - const auto Candidate = *CI; - CandidateAnchors->second.erase(CI); - InsertMatching(Loc, Candidate); - LLVM_DEBUG(dbgs() << "Callsite with callee:" << CalleeName - << " is matched from " << Loc << " to " << Candidate - << "\n"); - LocationDelta = Candidate.LineOffset - Loc.LineOffset; - - // Match backwards for non-anchor locations. - // The locations in LastMatchedNonAnchors have been matched forwards - // based on the previous anchor, spilt it evenly and overwrite the - // second half based on the current anchor. - for (size_t I = (LastMatchedNonAnchors.size() + 1) / 2; - I < LastMatchedNonAnchors.size(); I++) { - const auto &L = LastMatchedNonAnchors[I]; - uint32_t CandidateLineOffset = L.LineOffset + LocationDelta; - LineLocation Candidate(CandidateLineOffset, L.Discriminator); - InsertMatching(L, Candidate); - LLVM_DEBUG(dbgs() << "Location is rematched backwards from " << L - << " to " << Candidate << "\n"); - } - - IsMatchedAnchor = true; - LastMatchedNonAnchors.clear(); + auto R = MatchedAnchors.find(Loc); + if (R != MatchedAnchors.end()) { + const auto &Candidate = R->second; + InsertMatching(Loc, Candidate); + LLVM_DEBUG(dbgs() << "Callsite with callee:" << IR.second.stringRef() + << " is matched from " << Loc << " to " << Candidate + << "\n"); + LocationDelta = Candidate.LineOffset - Loc.LineOffset; + + // Match backwards for non-anchor locations. + // The locations in LastMatchedNonAnchors have been matched forwards + // based on the previous anchor, spilt it evenly and overwrite the + // second half based on the current anchor. + for (size_t I = (LastMatchedNonAnchors.size() + 1) / 2; + I < LastMatchedNonAnchors.size(); I++) { + const auto &L = LastMatchedNonAnchors[I]; + uint32_t CandidateLineOffset = L.LineOffset + LocationDelta; + LineLocation Candidate(CandidateLineOffset, L.Discriminator); + InsertMatching(L, Candidate); + LLVM_DEBUG(dbgs() << "Location is rematched backwards from " << L + << " to " << Candidate << "\n"); } + + IsMatchedAnchor = true; + LastMatchedNonAnchors.clear(); } // Match forwards for non-anchor locations. @@ -224,6 +260,57 @@ void SampleProfileMatcher::runStaleProfileMatching( } } +// Call target name anchor based profile fuzzy matching. +// Input: +// For IR locations, the anchor is the callee name of direct callsite; For +// profile locations, it's the call target name for BodySamples or inlinee's +// profile name for CallsiteSamples. +// Matching heuristic: +// First match all the anchors using the diff algorithm, then split the +// non-anchor locations between the two anchors evenly, first half are matched +// based on the start anchor, second half are matched based on the end anchor. +// For example, given: +// IR locations: [1, 2(foo), 3, 5, 6(bar), 7] +// Profile locations: [1, 2, 3(foo), 4, 7, 8(bar), 9] +// The matching gives: +// [1, 2(foo), 3, 5, 6(bar), 7] +// | | | | | | +// [1, 2, 3(foo), 4, 7, 8(bar), 9] +// The output mapping: [2->3, 3->4, 5->7, 6->8, 7->9]. +void SampleProfileMatcher::runStaleProfileMatching( + const Function &F, const AnchorMap &IRAnchors, + const AnchorMap &ProfileAnchors, LocToLocMap &IRToProfileLocationMap) { + LLVM_DEBUG(dbgs() << "Run stale profile matching for " << F.getName() + << "\n"); + assert(IRToProfileLocationMap.empty() && + "Run stale profile matching only once per function"); + + AnchorList FilteredProfileAnchorList; + for (const auto &I : ProfileAnchors) + FilteredProfileAnchorList.emplace_back(I); + + AnchorList FilteredIRAnchorsList; + // Filter the non-callsite from IRAnchors. + for (const auto &I : IRAnchors) { + if (I.second.stringRef().empty()) + continue; + FilteredIRAnchorsList.emplace_back(I); + } + + if (FilteredIRAnchorsList.empty() || FilteredProfileAnchorList.empty()) + return; + + // Match the callsite anchors by finding the longest common subsequence + // between IR and profile. Note that we need to use IR anchor as base(A side) + // to align with the order of IRToProfileLocationMap. + LocToLocMap MatchedAnchors = + longestCommonSequence(FilteredIRAnchorsList, FilteredProfileAnchorList); + + // Match the non-callsite locations and write the result to + // IRToProfileLocationMap. + matchNonCallsiteLocs(MatchedAnchors, IRAnchors, IRToProfileLocationMap); +} + void SampleProfileMatcher::runOnFunction(Function &F) { // We need to use flattened function samples for matching. // Unlike IR, which includes all callsites from the source code, the callsites @@ -238,11 +325,11 @@ void SampleProfileMatcher::runOnFunction(Function &F) { // Anchors for IR. It's a map from IR location to callee name, callee name is // empty for non-call instruction and use a dummy name(UnknownIndirectCallee) // for unknown indrect callee name. - std::map IRAnchors; + AnchorMap IRAnchors; findIRAnchors(F, IRAnchors); // Anchors for profile. It's a map from callsite location to a set of callee // name. - std::map> ProfileAnchors; + AnchorMap ProfileAnchors; findProfileAnchors(*FSFlattened, ProfileAnchors); // Compute the callsite match states for profile staleness report. @@ -274,9 +361,8 @@ void SampleProfileMatcher::runOnFunction(Function &F) { } void SampleProfileMatcher::recordCallsiteMatchStates( - const Function &F, const std::map &IRAnchors, - const std::map> - &ProfileAnchors, + const Function &F, const AnchorMap &IRAnchors, + const AnchorMap &ProfileAnchors, const LocToLocMap *IRToProfileLocationMap) { bool IsPostMatch = IRToProfileLocationMap != nullptr; auto &CallsiteMatchStates = @@ -297,23 +383,12 @@ void SampleProfileMatcher::recordCallsiteMatchStates( // After fuzzy profile matching, use the matching result to remap the // current IR callsite. const auto &ProfileLoc = MapIRLocToProfileLoc(I.first); - const auto &IRCalleeName = I.second; + const auto &IRCalleeId = I.second; const auto &It = ProfileAnchors.find(ProfileLoc); if (It == ProfileAnchors.end()) continue; - const auto &Callees = It->second; - - bool IsCallsiteMatched = false; - // Since indirect call does not have CalleeName, check conservatively if - // callsite in the profile is a callsite location. This is to reduce num of - // false positive since otherwise all the indirect call samples will be - // reported as mismatching. - if (IRCalleeName == SampleProfileMatcher::UnknownIndirectCallee) - IsCallsiteMatched = true; - else if (Callees.size() == 1 && Callees.count(getRepInFormat(IRCalleeName))) - IsCallsiteMatched = true; - - if (IsCallsiteMatched) { + const auto &ProfCalleeId = It->second; + if (IRCalleeId == ProfCalleeId) { auto It = CallsiteMatchStates.find(ProfileLoc); if (It == CallsiteMatchStates.end()) CallsiteMatchStates.emplace(ProfileLoc, MatchState::InitialMatch); @@ -330,8 +405,7 @@ void SampleProfileMatcher::recordCallsiteMatchStates( // IR callsites. for (const auto &I : ProfileAnchors) { const auto &Loc = I.first; - [[maybe_unused]] const auto &Callees = I.second; - assert(!Callees.empty() && "Callees should not be empty"); + assert(!I.second.stringRef().empty() && "Callees should not be empty"); auto It = CallsiteMatchStates.find(Loc); if (It == CallsiteMatchStates.end()) CallsiteMatchStates.emplace(Loc, MatchState::InitialMismatch); diff --git a/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-stale-profile-matching-LCS.prof b/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-stale-profile-matching-LCS.prof new file mode 100644 index 000000000000..e56c7c01865d --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-stale-profile-matching-LCS.prof @@ -0,0 +1,26 @@ +test_direct_call:606:83 + 1: 83 + 2: 83 C:83 + 3: 90 B:90 + 4: 83 A:83 + 5: 92 B:92 + 6: 83 A:83 + 7: 97 C:97 + !CFGChecksum: 123456 +test_indirect_call:589:86 + 1: 86 + 2: 86 C:86 + 3: 83 A:43 B:40 + 4: 84 B:84 + 6: 82 B:62 A:20 + 7: 91 C:91 + !CFGChecksum: 123456 +main:403:0 + 1: 0 + 2: 80 + 3: 80 + 4: 86 test_indirect_call:86 + 5: 83 test_direct_call:83 + 6: 83 + 7: 0 + !CFGChecksum: 563036051115663 diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-LCS.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-LCS.ll new file mode 100644 index 000000000000..ecf8484d98e5 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-LCS.ll @@ -0,0 +1,219 @@ +; REQUIRES: x86_64-linux +; REQUIRES: asserts +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-stale-profile-matching-LCS.prof --salvage-stale-profile -S --debug-only=sample-profile,sample-profile-matcher,sample-profile-impl 2>&1 | FileCheck %s + +; CHECK: Run stale profile matching for test_direct_call +; CHECK: Location is matched from 1 to 1 +; CHECK: Location is matched from 2 to 2 +; CHECK: Location is matched from 3 to 3 +; CHECK: Callsite with callee:C is matched from 4 to 2 +; CHECK: Location is rematched backwards from 3 to 1 +; CHECK: Callsite with callee:A is matched from 5 to 4 +; CHECK: Callsite with callee:B is matched from 6 to 5 +; CHECK: Location is matched from 7 to 6 +; CHECK: Callsite with callee:A is matched from 8 to 6 + +; CHECK: Run stale profile matching for test_indirect_call +; CHECK: Location is matched from 1 to 1 +; CHECK: Location is matched from 2 to 2 +; CHECK: Location is matched from 3 to 3 +; CHECK: Location is matched from 4 to 4 +; CHECK: Callsite with callee:C is matched from 5 to 2 +; CHECK: Location is rematched backwards from 3 to 0 +; CHECK: Location is rematched backwards from 4 to 1 +; CHECK: Callsite with callee:unknown.indirect.callee is matched from 6 to 3 +; CHECK:Callsite with callee:B is matched from 7 to 4 +; CHECK: Location is matched from 8 to 5 +; CHECK: Callsite with callee:unknown.indirect.callee is matched from 9 to 6 +; CHECK: Callsite with callee:C is matched from 10 to 7 + + +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" + +@c = external global i32, align 4 + +; Function Attrs: nounwind uwtable +define dso_local i32 @test_direct_call(i32 noundef %x) #0 !dbg !12 { +entry: + #dbg_value(i32 %x, !17, !DIExpression(), !18) + call void @llvm.pseudoprobe(i64 -4364451034228175269, i64 1, i32 0, i64 -1), !dbg !19 + %call = call i32 @A(i32 noundef %x), !dbg !20 + %add = add nsw i32 %x, %call, !dbg !22 + #dbg_value(i32 %add, !17, !DIExpression(), !18) + %call1 = call i32 @B(i32 noundef %add), !dbg !23 + %add2 = add nsw i32 %add, %call1, !dbg !25 + #dbg_value(i32 %add2, !17, !DIExpression(), !18) + %call3 = call i32 @C(i32 noundef %add2), !dbg !26 + %add4 = add nsw i32 %add2, %call3, !dbg !28 + #dbg_value(i32 %add4, !17, !DIExpression(), !18) + %call5 = call i32 @A(i32 noundef %add4), !dbg !29 + %add6 = add nsw i32 %add4, %call5, !dbg !31 + #dbg_value(i32 %add6, !17, !DIExpression(), !18) + %call7 = call i32 @B(i32 noundef %add6), !dbg !32 + %add8 = add nsw i32 %add6, %call7, !dbg !34 + #dbg_value(i32 %add8, !17, !DIExpression(), !18) + %call9 = call i32 @B(i32 noundef %add8), !dbg !35 + %add10 = add nsw i32 %add8, %call9, !dbg !37 + #dbg_value(i32 %add10, !17, !DIExpression(), !18) + %call11 = call i32 @A(i32 noundef %add10), !dbg !38 + %add12 = add nsw i32 %add10, %call11, !dbg !40 + #dbg_value(i32 %add12, !17, !DIExpression(), !18) + ret i32 %add12, !dbg !41 +} + +; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +declare !dbg !42 i32 @A(i32 noundef) #2 + +declare !dbg !43 i32 @B(i32 noundef) #2 + +declare !dbg !44 i32 @C(i32 noundef) #2 + +; Function Attrs: nounwind uwtable +define dso_local i32 @test_indirect_call(i32 noundef %x) #0 !dbg !45 { +entry: + #dbg_value(i32 %x, !47, !DIExpression(), !50) + call void @llvm.pseudoprobe(i64 -8563147518712133441, i64 1, i32 0, i64 -1), !dbg !51 + %0 = load i32, ptr @c, align 4, !dbg !51, !tbaa !53 + %tobool = icmp ne i32 %0, 0, !dbg !51 + br i1 %tobool, label %if.then, label %if.else, !dbg !57 + +if.then: ; preds = %entry + call void @llvm.pseudoprobe(i64 -8563147518712133441, i64 2, i32 0, i64 -1), !dbg !58 + #dbg_value(ptr @A, !48, !DIExpression(), !50) + br label %if.end, !dbg !59 + +if.else: ; preds = %entry + call void @llvm.pseudoprobe(i64 -8563147518712133441, i64 3, i32 0, i64 -1), !dbg !60 + #dbg_value(ptr @B, !48, !DIExpression(), !50) + br label %if.end + +if.end: ; preds = %if.else, %if.then + %fp.0 = phi ptr [ @A, %if.then ], [ @B, %if.else ], !dbg !61 + #dbg_value(ptr %fp.0, !48, !DIExpression(), !50) + call void @llvm.pseudoprobe(i64 -8563147518712133441, i64 4, i32 0, i64 -1), !dbg !62 + %call = call i32 @C(i32 noundef %x), !dbg !63 + %add = add nsw i32 %x, %call, !dbg !65 + #dbg_value(i32 %add, !47, !DIExpression(), !50) + %call1 = call i32 %fp.0(i32 noundef %add), !dbg !66 + %add2 = add nsw i32 %add, %call1, !dbg !68 + #dbg_value(i32 %add2, !47, !DIExpression(), !50) + %call3 = call i32 @B(i32 noundef %add2), !dbg !69 + %add4 = add nsw i32 %add2, %call3, !dbg !71 + #dbg_value(i32 %add4, !47, !DIExpression(), !50) + %call5 = call i32 @C(i32 noundef %add4), !dbg !72 + %add6 = add nsw i32 %add4, %call5, !dbg !74 + #dbg_value(i32 %add6, !47, !DIExpression(), !50) + %call7 = call i32 %fp.0(i32 noundef %add6), !dbg !75 + %add8 = add nsw i32 %add6, %call7, !dbg !77 + #dbg_value(i32 %add8, !47, !DIExpression(), !50) + %call9 = call i32 @C(i32 noundef %add8), !dbg !78 + %add10 = add nsw i32 %add8, %call9, !dbg !80 + #dbg_value(i32 %add10, !47, !DIExpression(), !50) + ret i32 %add10, !dbg !81 +} + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #3 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) +declare void @llvm.pseudoprobe(i64, i64, i32, i64) #4 + +attributes #0 = { nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "use-sample-profile" } +attributes #1 = { mustprogress nocallback nofree nosync nounwind speculatable willreturn } +attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { mustprogress nocallback nofree nosync nounwind willreturn } +attributes #4 = { mustprogress nocallback nofree nosync nounwind willreturn } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} +!llvm.pseudo_probe_desc = !{!10, !11} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, debugInfoForProfiling: true, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/home/", checksumkind: CSK_MD5, checksum: "be98aa946f37f0ad8d307c9121efe101") +!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, !"debug-info-assignment-tracking", i1 true} +!9 = !{!"clang version 19.0.0"} +!10 = !{i64 -4364451034228175269, i64 1970329131941887, !"test_direct_call"} +!11 = !{i64 -8563147518712133441, i64 1688922477484692, !"test_indirect_call"} +!12 = distinct !DISubprogram(name: "test_direct_call", scope: !1, file: !1, line: 10, type: !13, scopeLine: 10, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !16) +!13 = !DISubroutineType(types: !14) +!14 = !{!15, !15} +!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!16 = !{!17} +!17 = !DILocalVariable(name: "x", arg: 1, scope: !12, file: !1, line: 10, type: !15) +!18 = !DILocation(line: 0, scope: !12) +!19 = !DILocation(line: 11, column: 10, scope: !12) +!20 = !DILocation(line: 11, column: 8, scope: !21) +!21 = !DILexicalBlockFile(scope: !12, file: !1, discriminator: 186646551) +!22 = !DILocation(line: 11, column: 5, scope: !12) +!23 = !DILocation(line: 12, column: 8, scope: !24) +!24 = !DILexicalBlockFile(scope: !12, file: !1, discriminator: 186646559) +!25 = !DILocation(line: 12, column: 5, scope: !12) +!26 = !DILocation(line: 13, column: 8, scope: !27) +!27 = !DILexicalBlockFile(scope: !12, file: !1, discriminator: 186646567) +!28 = !DILocation(line: 13, column: 5, scope: !12) +!29 = !DILocation(line: 14, column: 8, scope: !30) +!30 = !DILexicalBlockFile(scope: !12, file: !1, discriminator: 186646575) +!31 = !DILocation(line: 14, column: 5, scope: !12) +!32 = !DILocation(line: 15, column: 8, scope: !33) +!33 = !DILexicalBlockFile(scope: !12, file: !1, discriminator: 186646583) +!34 = !DILocation(line: 15, column: 5, scope: !12) +!35 = !DILocation(line: 16, column: 8, scope: !36) +!36 = !DILexicalBlockFile(scope: !12, file: !1, discriminator: 186646591) +!37 = !DILocation(line: 16, column: 5, scope: !12) +!38 = !DILocation(line: 17, column: 8, scope: !39) +!39 = !DILexicalBlockFile(scope: !12, file: !1, discriminator: 186646599) +!40 = !DILocation(line: 17, column: 5, scope: !12) +!41 = !DILocation(line: 18, column: 3, scope: !12) +!42 = !DISubprogram(name: "A", scope: !1, file: !1, line: 2, type: !13, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +!43 = !DISubprogram(name: "B", scope: !1, file: !1, line: 3, type: !13, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +!44 = !DISubprogram(name: "C", scope: !1, file: !1, line: 4, type: !13, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +!45 = distinct !DISubprogram(name: "test_indirect_call", scope: !1, file: !1, line: 21, type: !13, scopeLine: 21, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !46) +!46 = !{!47, !48} +!47 = !DILocalVariable(name: "x", arg: 1, scope: !45, file: !1, line: 21, type: !15) +!48 = !DILocalVariable(name: "fp", scope: !45, file: !1, line: 22, type: !49) +!49 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64) +!50 = !DILocation(line: 0, scope: !45) +!51 = !DILocation(line: 23, column: 6, scope: !52) +!52 = distinct !DILexicalBlock(scope: !45, file: !1, line: 23, column: 6) +!53 = !{!54, !54, i64 0} +!54 = !{!"int", !55, i64 0} +!55 = !{!"omnipotent char", !56, i64 0} +!56 = !{!"Simple C/C++ TBAA"} +!57 = !DILocation(line: 23, column: 6, scope: !45) +!58 = !DILocation(line: 24, column: 8, scope: !52) +!59 = !DILocation(line: 24, column: 5, scope: !52) +!60 = !DILocation(line: 26, column: 8, scope: !52) +!61 = !DILocation(line: 0, scope: !52) +!62 = !DILocation(line: 27, column: 10, scope: !45) +!63 = !DILocation(line: 27, column: 8, scope: !64) +!64 = !DILexicalBlockFile(scope: !45, file: !1, discriminator: 186646575) +!65 = !DILocation(line: 27, column: 5, scope: !45) +!66 = !DILocation(line: 28, column: 8, scope: !67) +!67 = !DILexicalBlockFile(scope: !45, file: !1, discriminator: 119537719) +!68 = !DILocation(line: 28, column: 5, scope: !45) +!69 = !DILocation(line: 29, column: 8, scope: !70) +!70 = !DILexicalBlockFile(scope: !45, file: !1, discriminator: 186646591) +!71 = !DILocation(line: 29, column: 5, scope: !45) +!72 = !DILocation(line: 30, column: 8, scope: !73) +!73 = !DILexicalBlockFile(scope: !45, file: !1, discriminator: 186646599) +!74 = !DILocation(line: 30, column: 5, scope: !45) +!75 = !DILocation(line: 31, column: 8, scope: !76) +!76 = !DILexicalBlockFile(scope: !45, file: !1, discriminator: 119537743) +!77 = !DILocation(line: 31, column: 5, scope: !45) +!78 = !DILocation(line: 32, column: 8, scope: !79) +!79 = !DILexicalBlockFile(scope: !45, file: !1, discriminator: 186646615) +!80 = !DILocation(line: 32, column: 5, scope: !45) +!81 = !DILocation(line: 33, column: 3, scope: !45) diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll index 0d471e43d2a7..20be0c2fec7f 100644 --- a/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll @@ -86,7 +86,7 @@ ; CHECK: 3: call void @llvm.pseudoprobe(i64 6699318081062747564, i64 3, i32 0, i64 -1), !dbg ![[#]] - weight: 13 - factor: 1.00) ; CHECK: 6: %call1.i5 = call i32 @bar(i32 noundef %add.i4), !dbg ![[#]] - weight: 13 - factor: 1.00) ; CHECK: 4: call void @llvm.pseudoprobe(i64 6699318081062747564, i64 4, i32 0, i64 -1), !dbg ![[#]] - weight: 112 - factor: 1.00) -; CHECK: 14: %call2 = call i32 @bar(i32 noundef %3), !dbg ![[#]] - weight: 124 - factor: 1.00) +; CHECK: 14: %call2 = call i32 @bar(i32 noundef %3), !dbg ![[#]] - weight: 124 - factor: 1.00) ; CHECK: 8: call void @llvm.pseudoprobe(i64 -2624081020897602054, i64 8, i32 0, i64 -1), !dbg ![[#]] - weight: 0 - factor: 1.00) ; CHECK: 1: call void @llvm.pseudoprobe(i64 6699318081062747564, i64 1, i32 0, i64 -1), !dbg ![[#]] - weight: 117 - factor: 1.00) ; CHECK: 2: call void @llvm.pseudoprobe(i64 6699318081062747564, i64 2, i32 0, i64 -1), !dbg ![[#]] - weight: 104 - factor: 1.00) -- GitLab From 435771228caf77cce35406ecf57a49a06e227fe4 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 13 May 2024 16:03:26 -0700 Subject: [PATCH 146/578] [RISCV] Inogre CallingConv::RISCV_VectorCall in getCalleeSavedRegs if V/Zve is not enabled. We can't save vector registers without V/Zve. --- llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index 129b4cb4e8cb..caa5dbc15f8b 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -72,7 +72,8 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { } bool HasVectorCSR = - MF->getFunction().getCallingConv() == CallingConv::RISCV_VectorCall; + MF->getFunction().getCallingConv() == CallingConv::RISCV_VectorCall && + Subtarget.hasVInstructions(); switch (Subtarget.getTargetABI()) { default: -- GitLab From 4c79d38f82e1f6fe8575d88d8c74f2f1806b19ce Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Mon, 13 May 2024 16:05:09 -0700 Subject: [PATCH 147/578] [libc] add errno_macro header to bazel build (#92044) Patch #91150 added a proxy header for errno macros. This patch fixes the bazel build since it needs to be added as a dependency. --- utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 6255ac998db1..ce61c432c2ed 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -117,6 +117,11 @@ libc_support_library( hdrs = ["hdr/sys_epoll_macros.h"], ) +libc_support_library( + name = "hdr_errno_macros", + hdrs = ["hdr/errno_macros.h"], +) + ############################ Type Proxy Header Files ########################### libc_support_library( @@ -1144,6 +1149,7 @@ libc_function( ":__support_common", ":__support_macros_attributes", ":__support_macros_properties_architectures", + ":hdr_errno_macros", ], ) -- GitLab From c99d1156c28dfed67a8479dd97608d1f0d6cd593 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Mon, 13 May 2024 16:31:21 -0700 Subject: [PATCH 148/578] [workflows] Add a job for requesting a release note on release branch PRs (#91826) We have been collecting release notes from the PRs for most of the 18.1.x releases and this just helps automate the process. --- .github/workflows/pr-request-release-note.yml | 43 +++++++++++++++++++ llvm/utils/git/github-automation.py | 33 ++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 .github/workflows/pr-request-release-note.yml diff --git a/.github/workflows/pr-request-release-note.yml b/.github/workflows/pr-request-release-note.yml new file mode 100644 index 000000000000..0fcb95f1fe29 --- /dev/null +++ b/.github/workflows/pr-request-release-note.yml @@ -0,0 +1,43 @@ +name: PR Request Release Note + +permissions: + contents: read + pull-requests: write + +on: + pull_request: + types: + - closed + +jobs: + request-release-note: + if: >- + github.repository_owner == 'llvm' && + startsWith(github.ref, 'refs/heads/release') + + runs-on: ubuntu-latest + steps: + # We need to pull the script from the main branch, so that we ensure + # we get the latest version of this script. + - name: Checkout Scripts + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + sparse-checkout: | + llvm/utils/git/requirements.txt + llvm/utils/git/github-automation.py + sparse-checkout-cone-mode: false + + - name: Install Dependencies + run: | + pip install -r llvm/utils/git/requirements.txt + + - name: Request Release Note + env: + # We need to use an llvmbot token here, because we are mentioning a user. + GITHUB_TOKEN: ${{ github.token }} + run: | + python3 llvm/utils/git/github-automation.py \ + --repo "$GITHUB_REPOSITORY" \ + --token "$GITHUB_TOKEN" \ + request-release-note \ + --pr-number ${{ github.event.pull_request.number}} diff --git a/llvm/utils/git/github-automation.py b/llvm/utils/git/github-automation.py index 1b5141e42594..1766ccb38ba2 100755 --- a/llvm/utils/git/github-automation.py +++ b/llvm/utils/git/github-automation.py @@ -637,6 +637,25 @@ class ReleaseWorkflow: return False +def request_release_note(token: str, repo_name: str, pr_number: int): + repo = github.Github(token).get_repo(repo_name) + pr = repo.get_issue(pr_number).as_pull_request() + submitter = pr.user.login + if submitter == "llvmbot": + m = re.search("Requested by: @(.+)$", pr.body) + if not m: + submitter = None + print("Warning could not determine user who requested backport.") + submitter = m.group(1) + + mention = "" + if submitter: + mention = f"@{submitter}" + + comment = f"{mention} (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR. " + pr.as_issue().create_comment(comment) + + parser = argparse.ArgumentParser() parser.add_argument( "--token", type=str, required=True, help="GitHub authentication token" @@ -703,6 +722,18 @@ release_workflow_parser.add_argument( help="The user that requested this backport", ) +request_release_note_parser = subparsers.add_parser( + "request-release-note", + help="Request a release note for a pull request", +) +request_release_note_parser.add_argument( + "--pr-number", + type=int, + required=True, + help="The pull request to request the release note", +) + + args = parser.parse_args() if args.command == "issue-subscriber": @@ -743,3 +774,5 @@ elif args.command == "release-workflow": sys.exit(1) elif args.command == "setup-llvmbot-git": setup_llvmbot_git() +elif args.command == "request-release-note": + request_release_note(args.token, args.repo, args.pr_number) -- GitLab From 23f8fac745bdde70ed4f9c585d19c4913734f1b8 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 13 May 2024 16:37:39 -0700 Subject: [PATCH 149/578] Revert "Repply#2 "[RemoveDIs] Load into new debug info format by default in LLVM (#89799)"" This reverts commit 91446e2aa687ec57ad88dc0df793d0c6e694a7c9 and a unittest followup 1530f319311908b06fe935c89fca692d3e53184f (#90476). In a stage-2 -flto=thin -gsplit-dwarf -g -fdebug-info-for-profiling -fprofile-sample-use= build of clang, a ThinLTO backend compile has assertion failures: Global is external, but doesn't have external or weak linkage! ptr @_ZN5clang12ast_matchers8internal18makeAllOfCompositeINS_8QualTypeEEENS1_15BindableMatcherIT_EEN4llvm8ArrayRefIPKNS1_7MatcherIS5_EEEE function declaration may only have a unique !dbg attachment ptr @_ZN5clang12ast_matchers8internal18makeAllOfCompositeINS_8QualTypeEEENS1_15BindableMatcherIT_EEN4llvm8ArrayRefIPKNS1_7MatcherIS5_EEEE The failures somehow go away if -fprofile-sample-use= is removed. --- llvm/docs/ReleaseNotes.rst | 7 - llvm/include/llvm/AsmParser/LLParser.h | 1 + llvm/lib/AsmParser/LLParser.cpp | 34 +-- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 2 +- llvm/lib/IR/BasicBlock.cpp | 2 +- llvm/lib/IR/DebugProgramInstruction.cpp | 4 +- llvm/lib/IR/Function.cpp | 4 +- llvm/lib/IR/Module.cpp | 4 +- llvm/tools/llvm-as/llvm-as.cpp | 7 +- llvm/tools/llvm-dis/llvm-dis.cpp | 2 +- llvm/tools/llvm-link/llvm-link.cpp | 8 +- .../Analysis/IRSimilarityIdentifierTest.cpp | 22 +- llvm/unittests/IR/BasicBlockDbgInfoTest.cpp | 68 ++++++ llvm/unittests/IR/DebugInfoTest.cpp | 73 +++--- llvm/unittests/IR/IRBuilderTest.cpp | 12 +- llvm/unittests/IR/InstructionsTest.cpp | 6 - llvm/unittests/IR/ValueTest.cpp | 9 +- .../Transforms/Utils/CloningTest.cpp | 5 +- llvm/unittests/Transforms/Utils/LocalTest.cpp | 211 ++++++++---------- 19 files changed, 248 insertions(+), 233 deletions(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index f2577e1684f5..84320461fa9e 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -189,13 +189,6 @@ Changes to the Metadata Info Changes to the Debug Info --------------------------------- -* LLVM has switched from using debug intrinsics internally to using debug - records by default. This should happen transparently when using the DIBuilder - to construct debug variable information, but will require changes for any code - that interacts with debug intrinsics directly. Debug intrinsics will only be - supported on a best-effort basis from here onwards; for more information, see - the `migration docs `_. - Changes to the LLVM tools --------------------------------- * llvm-nm and llvm-objdump can now print symbol information from linked diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index e687254f6c4c..b2dcdfad0a04 100644 --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -337,6 +337,7 @@ namespace llvm { // Top-Level Entities bool parseTopLevelEntities(); + bool finalizeDebugInfoFormat(Module *M); void dropUnknownMetadataReferences(); bool validateEndOfModule(bool UpgradeDebugInfo); bool validateEndOfIndex(); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 34053a5ca9c8..2902bd9fe17c 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -74,6 +74,23 @@ static std::string getTypeString(Type *T) { return Tmp.str(); } +// Whatever debug info format we parsed, we should convert to the expected debug +// info format immediately afterwards. +bool LLParser::finalizeDebugInfoFormat(Module *M) { + // We should have already returned an error if we observed both intrinsics and + // records in this IR. + assert(!(SeenNewDbgInfoFormat && SeenOldDbgInfoFormat) && + "Mixed debug intrinsics/records seen without a parsing error?"); + if (PreserveInputDbgFormat == cl::boolOrDefault::BOU_TRUE) { + UseNewDbgInfoFormat = SeenNewDbgInfoFormat; + WriteNewDbgInfoFormatToBitcode = SeenNewDbgInfoFormat; + WriteNewDbgInfoFormat = SeenNewDbgInfoFormat; + } else if (M) { + M->setIsNewDbgInfoFormat(false); + } + return false; +} + /// Run: module ::= toplevelentity* bool LLParser::Run(bool UpgradeDebugInfo, DataLayoutCallbackTy DataLayoutCallback) { @@ -91,7 +108,7 @@ bool LLParser::Run(bool UpgradeDebugInfo, } return parseTopLevelEntities() || validateEndOfModule(UpgradeDebugInfo) || - validateEndOfIndex(); + validateEndOfIndex() || finalizeDebugInfoFormat(M); } bool LLParser::parseStandaloneConstantValue(Constant *&C, @@ -190,18 +207,6 @@ void LLParser::dropUnknownMetadataReferences() { bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) { if (!M) return false; - - // We should have already returned an error if we observed both intrinsics and - // records in this IR. - assert(!(SeenNewDbgInfoFormat && SeenOldDbgInfoFormat) && - "Mixed debug intrinsics/records seen without a parsing error?"); - if (PreserveInputDbgFormat == cl::boolOrDefault::BOU_TRUE) { - UseNewDbgInfoFormat = SeenNewDbgInfoFormat; - WriteNewDbgInfoFormatToBitcode = SeenNewDbgInfoFormat; - WriteNewDbgInfoFormat = SeenNewDbgInfoFormat; - M->setNewDbgInfoFormatFlag(SeenNewDbgInfoFormat); - } - // Handle any function attribute group forward references. for (const auto &RAG : ForwardRefAttrGroups) { Value *V = RAG.first; @@ -434,9 +439,6 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) { UpgradeModuleFlags(*M); UpgradeSectionAttributes(*M); - if (PreserveInputDbgFormat != cl::boolOrDefault::BOU_TRUE) - M->setIsNewDbgInfoFormat(UseNewDbgInfoFormat); - if (!Slots) return false; // Initialize the slot mapping. diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index be2381cd7d77..19a15209f8b6 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -4319,7 +4319,7 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit, if (PreserveInputDbgFormat != cl::boolOrDefault::BOU_TRUE) { TheModule->IsNewDbgInfoFormat = UseNewDbgInfoFormat && - LoadBitcodeIntoNewDbgInfoFormat != cl::boolOrDefault::BOU_FALSE; + LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_TRUE; } this->ValueTypeCallback = std::move(Callbacks.ValueType); diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp index aea9425ebeba..29f2cbf611fa 100644 --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -181,7 +181,7 @@ template class llvm::SymbolTableListTraits(getRawLocation())) || - (getNumVariableLocationOps() == 0 && !getExpression()->isComplex()) || + return (getNumVariableLocationOps() == 0 && + !getExpression()->isComplex()) || any_of(location_ops(), [](Value *V) { return isa(V); }); } diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 7f1e832f8597..bd06ff82a15a 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -83,8 +83,6 @@ static cl::opt NonGlobalValueMaxNameSize( "non-global-value-max-name-size", cl::Hidden, cl::init(1024), cl::desc("Maximum size for the name of non-global values.")); -extern cl::opt UseNewDbgInfoFormat; - void Function::convertToNewDbgValues() { IsNewDbgInfoFormat = true; for (auto &BB : *this) { @@ -440,7 +438,7 @@ Function::Function(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, : GlobalObject(Ty, Value::FunctionVal, OperandTraits::op_begin(this), 0, Linkage, name, computeAddrSpace(AddrSpace, ParentModule)), - NumArgs(Ty->getNumParams()), IsNewDbgInfoFormat(UseNewDbgInfoFormat) { + NumArgs(Ty->getNumParams()), IsNewDbgInfoFormat(false) { assert(FunctionType::isValidReturnType(getReturnType()) && "invalid return type"); setGlobalObjectSubClassData(0); diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index 915fa5097383..a8696ed9e3ce 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -54,8 +54,6 @@ using namespace llvm; -extern cl::opt UseNewDbgInfoFormat; - //===----------------------------------------------------------------------===// // Methods to implement the globals and functions lists. // @@ -74,7 +72,7 @@ template class llvm::SymbolTableListTraits; Module::Module(StringRef MID, LLVMContext &C) : Context(C), ValSymTab(std::make_unique(-1)), ModuleID(std::string(MID)), SourceFileName(std::string(MID)), DL(""), - IsNewDbgInfoFormat(UseNewDbgInfoFormat) { + IsNewDbgInfoFormat(false) { Context.addModule(this); } diff --git a/llvm/tools/llvm-as/llvm-as.cpp b/llvm/tools/llvm-as/llvm-as.cpp index 0958e16c2197..e48e3f4d22c1 100644 --- a/llvm/tools/llvm-as/llvm-as.cpp +++ b/llvm/tools/llvm-as/llvm-as.cpp @@ -142,10 +142,11 @@ int main(int argc, char **argv) { } // Convert to new debug format if requested. - M->setIsNewDbgInfoFormat(UseNewDbgInfoFormat && - WriteNewDbgInfoFormatToBitcode); - if (M->IsNewDbgInfoFormat) + assert(!M->IsNewDbgInfoFormat && "Unexpectedly in new debug mode"); + if (UseNewDbgInfoFormat && WriteNewDbgInfoFormatToBitcode) { + M->convertToNewDbgValues(); M->removeDebugIntrinsicDeclarations(); + } std::unique_ptr Index = std::move(ModuleAndIndex.Index); diff --git a/llvm/tools/llvm-dis/llvm-dis.cpp b/llvm/tools/llvm-dis/llvm-dis.cpp index d28af85bc739..fbbb5506e43e 100644 --- a/llvm/tools/llvm-dis/llvm-dis.cpp +++ b/llvm/tools/llvm-dis/llvm-dis.cpp @@ -258,7 +258,7 @@ int main(int argc, char **argv) { // All that llvm-dis does is write the assembly to a file. if (!DontPrint) { if (M) { - M->setIsNewDbgInfoFormat(WriteNewDbgInfoFormat); + ScopedDbgInfoFormatSetter FormatSetter(*M, WriteNewDbgInfoFormat); if (WriteNewDbgInfoFormat) M->removeDebugIntrinsicDeclarations(); M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder); diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp index b84469d1c757..7794f2d81ed0 100644 --- a/llvm/tools/llvm-link/llvm-link.cpp +++ b/llvm/tools/llvm-link/llvm-link.cpp @@ -489,6 +489,12 @@ int main(int argc, char **argv) { if (LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_UNSET) LoadBitcodeIntoNewDbgInfoFormat = cl::boolOrDefault::BOU_TRUE; + // RemoveDIs debug-info transition: tests may request that we /try/ to use the + // new debug-info format. + if (TryUseNewDbgInfoFormat) { + // Turn the new debug-info format on. + UseNewDbgInfoFormat = true; + } // Since llvm-link collects multiple IR modules together, for simplicity's // sake we disable the "PreserveInputDbgFormat" flag to enforce a single // debug info format. @@ -550,7 +556,7 @@ int main(int argc, char **argv) { SetFormat(WriteNewDbgInfoFormat); Composite->print(Out.os(), nullptr, PreserveAssemblyUseListOrder); } else if (Force || !CheckBitcodeOutputToConsole(Out.os())) { - SetFormat(UseNewDbgInfoFormat && WriteNewDbgInfoFormatToBitcode); + SetFormat(WriteNewDbgInfoFormatToBitcode); WriteBitcodeToFile(*Composite, Out.os(), PreserveBitcodeUseListOrder); } diff --git a/llvm/unittests/Analysis/IRSimilarityIdentifierTest.cpp b/llvm/unittests/Analysis/IRSimilarityIdentifierTest.cpp index 24f4f11db9a8..f6a053792f85 100644 --- a/llvm/unittests/Analysis/IRSimilarityIdentifierTest.cpp +++ b/llvm/unittests/Analysis/IRSimilarityIdentifierTest.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/IRSimilarityIdentifier.h" -#include "llvm/ADT/ScopeExit.h" #include "llvm/AsmParser/Parser.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -23,11 +22,6 @@ using namespace llvm; using namespace IRSimilarity; -extern llvm::cl::opt UseNewDbgInfoFormat; -extern cl::opt PreserveInputDbgFormat; -extern bool WriteNewDbgInfoFormatToBitcode; -extern cl::opt WriteNewDbgInfoFormat; - static std::unique_ptr makeLLVMModule(LLVMContext &Context, StringRef ModuleStr) { SMDiagnostic Err; @@ -1312,18 +1306,19 @@ TEST(IRInstructionMapper, CallBrInstIllegal) { ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber); } -// Checks that an debuginfo records are mapped to be invisible. Since they +// Checks that an debuginfo intrinsics are mapped to be invisible. Since they // do not semantically change the program, they can be recognized as similar. TEST(IRInstructionMapper, DebugInfoInvisible) { StringRef ModuleString = R"( define i32 @f(i32 %a, i32 %b) { then: - %0 = add i32 %a, %b - #dbg_value(i32 0, !0, !0, !0) - %1 = add i32 %a, %b + %0 = add i32 %a, %b + call void @llvm.dbg.value(metadata !0) + %1 = add i32 %a, %b ret i32 0 } + declare void @llvm.dbg.value(metadata) !0 = distinct !{!"test\00", i32 10})"; LLVMContext Context; std::unique_ptr M = makeLLVMModule(Context, ModuleString); @@ -1919,19 +1914,19 @@ TEST(IRSimilarityCandidate, CheckRegionsDifferentTypes) { ASSERT_FALSE(longSimCandCompare(InstrList)); } -// Check that debug records do not impact similarity. They are marked as +// Check that debug instructions do not impact similarity. They are marked as // invisible. TEST(IRSimilarityCandidate, IdenticalWithDebug) { StringRef ModuleString = R"( define i32 @f(i32 %a, i32 %b) { bb0: %0 = add i32 %a, %b - #dbg_value(i32 0, !0, !0, !0) + call void @llvm.dbg.value(metadata !0) %1 = add i32 %b, %a ret i32 0 bb1: %2 = add i32 %a, %b - #dbg_value(i32 1, !1, !1, !1) + call void @llvm.dbg.value(metadata !1) %3 = add i32 %b, %a ret i32 0 bb2: @@ -1940,6 +1935,7 @@ TEST(IRSimilarityCandidate, IdenticalWithDebug) { ret i32 0 } + declare void @llvm.dbg.value(metadata) !0 = distinct !{!"test\00", i32 10} !1 = distinct !{!"test\00", i32 11})"; LLVMContext Context; diff --git a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp index 91a0745a0cc7..f873bbd4293a 100644 --- a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp +++ b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp @@ -25,6 +25,8 @@ using namespace llvm; +extern cl::opt UseNewDbgInfoFormat; + static std::unique_ptr parseIR(LLVMContext &C, const char *IR) { SMDiagnostic Err; std::unique_ptr Mod = parseAssemblyString(IR, Err, C); @@ -42,6 +44,8 @@ namespace { // by DbgVariableRecords, the dbg.value replacement. TEST(BasicBlockDbgInfoTest, InsertAfterSelf) { LLVMContext C; + UseNewDbgInfoFormat = true; + std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 @@ -68,6 +72,8 @@ TEST(BasicBlockDbgInfoTest, InsertAfterSelf) { !11 = !DILocation(line: 1, column: 1, scope: !6) )"); + // Convert the module to "new" form debug-info. + M->convertToNewDbgValues(); // Fetch the entry block. BasicBlock &BB = M->getFunction("f")->getEntryBlock(); @@ -97,10 +103,16 @@ TEST(BasicBlockDbgInfoTest, InsertAfterSelf) { EXPECT_TRUE(RetInst->hasDbgRecords()); auto Range2 = RetInst->getDbgRecordRange(); EXPECT_EQ(std::distance(Range2.begin(), Range2.end()), 1u); + + M->convertFromNewDbgValues(); + + UseNewDbgInfoFormat = false; } TEST(BasicBlockDbgInfoTest, SplitBasicBlockBefore) { LLVMContext C; + UseNewDbgInfoFormat = true; + std::unique_ptr M = parseIR(C, R"---( define dso_local void @func() #0 !dbg !10 { %1 = alloca i32, align 4 @@ -138,6 +150,8 @@ TEST(BasicBlockDbgInfoTest, SplitBasicBlockBefore) { )---"); ASSERT_TRUE(M); + M->convertToNewDbgValues(); + Function *F = M->getFunction("func"); BasicBlock &BB = F->getEntryBlock(); @@ -147,10 +161,14 @@ TEST(BasicBlockDbgInfoTest, SplitBasicBlockBefore) { BasicBlock &BBBefore = F->getEntryBlock(); auto I2 = std::prev(BBBefore.end(), 2); ASSERT_TRUE(I2->hasDbgRecords()); + + UseNewDbgInfoFormat = false; } TEST(BasicBlockDbgInfoTest, MarkerOperations) { LLVMContext C; + UseNewDbgInfoFormat = true; + std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 @@ -178,6 +196,8 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { // Fetch the entry block, BasicBlock &BB = M->getFunction("f")->getEntryBlock(); + // Convert the module to "new" form debug-info. + M->convertToNewDbgValues(); EXPECT_EQ(BB.size(), 2u); // Fetch out our two markers, @@ -275,10 +295,14 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { // Teardown, Instr1->insertBefore(BB, BB.begin()); + + UseNewDbgInfoFormat = false; } TEST(BasicBlockDbgInfoTest, HeadBitOperations) { LLVMContext C; + UseNewDbgInfoFormat = true; + std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { %b = add i16 %a, 1, !dbg !11 @@ -308,6 +332,8 @@ TEST(BasicBlockDbgInfoTest, HeadBitOperations) { // Test that the movement of debug-data when using moveBefore etc and // insertBefore etc are governed by the "head" bit of iterators. BasicBlock &BB = M->getFunction("f")->getEntryBlock(); + // Convert the module to "new" form debug-info. + M->convertToNewDbgValues(); // Test that the head bit behaves as expected: it should be set when the // code wants the _start_ of the block, but not otherwise. @@ -378,10 +404,14 @@ TEST(BasicBlockDbgInfoTest, HeadBitOperations) { DInst->DebugMarker->StoredDbgRecords.empty()); EXPECT_FALSE(CInst->DebugMarker->StoredDbgRecords.empty()); EXPECT_EQ(&*BB.begin(), CInst); + + UseNewDbgInfoFormat = false; } TEST(BasicBlockDbgInfoTest, InstrDbgAccess) { LLVMContext C; + UseNewDbgInfoFormat = true; + std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { %b = add i16 %a, 1, !dbg !11 @@ -411,6 +441,8 @@ TEST(BasicBlockDbgInfoTest, InstrDbgAccess) { // Check that DbgVariableRecords can be accessed from Instructions without // digging into the depths of DbgMarkers. BasicBlock &BB = M->getFunction("f")->getEntryBlock(); + // Convert the module to "new" form debug-info. + M->convertToNewDbgValues(); Instruction *BInst = &*BB.begin(); Instruction *CInst = BInst->getNextNode(); @@ -451,6 +483,8 @@ TEST(BasicBlockDbgInfoTest, InstrDbgAccess) { CInst->dropOneDbgRecord(DVR1); EXPECT_FALSE(CInst->hasDbgRecords()); EXPECT_EQ(CInst->DebugMarker->StoredDbgRecords.size(), 0u); + + UseNewDbgInfoFormat = false; } /* Let's recall the big illustration from BasicBlock::spliceDebugInfo: @@ -543,7 +577,9 @@ protected: DbgVariableRecord *DVRA, *DVRB, *DVRConst; void SetUp() override { + UseNewDbgInfoFormat = true; M = parseIR(C, SpliceTestIR.c_str()); + M->convertToNewDbgValues(); BBEntry = &M->getFunction("f")->getEntryBlock(); BBExit = BBEntry->getNextNode(); @@ -563,6 +599,8 @@ protected: cast(&*CInst->DebugMarker->StoredDbgRecords.begin()); } + void TearDown() override { UseNewDbgInfoFormat = false; } + bool InstContainsDbgVariableRecord(Instruction *I, DbgVariableRecord *DVR) { for (DbgRecord &D : I->getDbgRecordRange()) { if (&D == DVR) { @@ -1149,6 +1187,8 @@ metadata !9, metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, // then the trailing DbgVariableRecords should get flushed back out. TEST(BasicBlockDbgInfoTest, DbgSpliceTrailing) { LLVMContext C; + UseNewDbgInfoFormat = true; + std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { entry: @@ -1179,6 +1219,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceTrailing) { BasicBlock &Entry = M->getFunction("f")->getEntryBlock(); BasicBlock &Exit = *Entry.getNextNode(); + M->convertToNewDbgValues(); // Begin by forcing entry block to have dangling DbgVariableRecord. Entry.getTerminator()->eraseFromParent(); @@ -1193,6 +1234,8 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceTrailing) { Instruction *BInst = &*Entry.begin(); ASSERT_TRUE(BInst->DebugMarker); EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 1u); + + UseNewDbgInfoFormat = false; } // When we remove instructions from the program, adjacent DbgVariableRecords @@ -1201,6 +1244,8 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceTrailing) { // dbg.values. Test that this can be replicated correctly by DbgVariableRecords TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsert) { LLVMContext C; + UseNewDbgInfoFormat = true; + std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { entry: @@ -1228,6 +1273,7 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsert) { )"); BasicBlock &Entry = M->getFunction("f")->getEntryBlock(); + M->convertToNewDbgValues(); // Fetch the relevant instructions from the converted function. Instruction *SubInst = &*Entry.begin(); @@ -1270,12 +1316,16 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsert) { EXPECT_EQ(std::distance(R4.begin(), R4.end()), 1u); auto R5 = RetInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R5.begin(), R5.end()), 1u); + + UseNewDbgInfoFormat = false; } // Test instruction removal and re-insertion, this time with one // DbgVariableRecord that should hop up one instruction. TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDbgVariableRecord) { LLVMContext C; + UseNewDbgInfoFormat = true; + std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { entry: @@ -1302,6 +1352,7 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDbgVariableRecord) { )"); BasicBlock &Entry = M->getFunction("f")->getEntryBlock(); + M->convertToNewDbgValues(); // Fetch the relevant instructions from the converted function. Instruction *SubInst = &*Entry.begin(); @@ -1340,6 +1391,8 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDbgVariableRecord) { EXPECT_FALSE(RetInst->hasDbgRecords()); auto R3 = AddInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R3.begin(), R3.end()), 1u); + + UseNewDbgInfoFormat = false; } // Similar to the above, what if we splice into an empty block with debug-info, @@ -1348,6 +1401,8 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDbgVariableRecord) { // of the i16 0 dbg.value. TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty1) { LLVMContext C; + UseNewDbgInfoFormat = true; + std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { entry: @@ -1381,6 +1436,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty1) { Function &F = *M->getFunction("f"); BasicBlock &Entry = F.getEntryBlock(); BasicBlock &Exit = *Entry.getNextNode(); + M->convertToNewDbgValues(); // Begin by forcing entry block to have dangling DbgVariableRecord. Entry.getTerminator()->eraseFromParent(); @@ -1407,12 +1463,16 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty1) { // No trailing DbgVariableRecords in the entry block now. EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr); + + UseNewDbgInfoFormat = false; } // Similar test again, but this time: splice the contents of exit into entry, // with the intention of leaving the first dbg.value (i16 0) behind. TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty2) { LLVMContext C; + UseNewDbgInfoFormat = true; + std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { entry: @@ -1446,6 +1506,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty2) { Function &F = *M->getFunction("f"); BasicBlock &Entry = F.getEntryBlock(); BasicBlock &Exit = *Entry.getNextNode(); + M->convertToNewDbgValues(); // Begin by forcing entry block to have dangling DbgVariableRecord. Entry.getTerminator()->eraseFromParent(); @@ -1476,12 +1537,16 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty2) { EXPECT_FALSE(Exit.getTrailingDbgRecords()->empty()); Exit.getTrailingDbgRecords()->eraseFromParent(); Exit.deleteTrailingDbgRecords(); + + UseNewDbgInfoFormat = false; } // What if we moveBefore end() -- there might be no debug-info there, in which // case we shouldn't crash. TEST(BasicBlockDbgInfoTest, DbgMoveToEnd) { LLVMContext C; + UseNewDbgInfoFormat = true; + std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { entry: @@ -1511,6 +1576,7 @@ TEST(BasicBlockDbgInfoTest, DbgMoveToEnd) { Function &F = *M->getFunction("f"); BasicBlock &Entry = F.getEntryBlock(); BasicBlock &Exit = *Entry.getNextNode(); + M->convertToNewDbgValues(); // Move the return to the end of the entry block. Instruction *Br = Entry.getTerminator(); @@ -1523,6 +1589,8 @@ TEST(BasicBlockDbgInfoTest, DbgMoveToEnd) { EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr); EXPECT_EQ(Exit.getTrailingDbgRecords(), nullptr); EXPECT_FALSE(Ret->hasDbgRecords()); + + UseNewDbgInfoFormat = false; } } // End anonymous namespace. diff --git a/llvm/unittests/IR/DebugInfoTest.cpp b/llvm/unittests/IR/DebugInfoTest.cpp index cac8acbe15a7..ec3f33318f8c 100644 --- a/llvm/unittests/IR/DebugInfoTest.cpp +++ b/llvm/unittests/IR/DebugInfoTest.cpp @@ -156,7 +156,7 @@ TEST(StripTest, LoopMetadata) { EXPECT_FALSE(BrokenDebugInfo); } -TEST(MetadataTest, DeleteInstUsedByDbgRecord) { +TEST(MetadataTest, DeleteInstUsedByDbgValue) { LLVMContext C; std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { @@ -187,13 +187,12 @@ TEST(MetadataTest, DeleteInstUsedByDbgRecord) { // Find the dbg.value using %b. SmallVector DVIs; - SmallVector DVRs; - findDbgValues(DVIs, &I, &DVRs); + findDbgValues(DVIs, &I); // Delete %b. The dbg.value should now point to undef. I.eraseFromParent(); - EXPECT_EQ(DVRs[0]->getNumVariableLocationOps(), 1u); - EXPECT_TRUE(isa(DVRs[0]->getValue(0))); + EXPECT_EQ(DVIs[0]->getNumVariableLocationOps(), 1u); + EXPECT_TRUE(isa(DVIs[0]->getValue(0))); } TEST(DbgVariableIntrinsic, EmptyMDIsKillLocation) { @@ -231,8 +230,8 @@ TEST(DbgVariableIntrinsic, EmptyMDIsKillLocation) { // Get the dbg.declare. Function &F = *cast(M->getNamedValue("fun")); - DbgVariableRecord *DbgDeclare = - cast(&*F.front().front().getDbgRecordRange().begin()); + DbgVariableIntrinsic *DbgDeclare = + cast(&F.front().front()); // Check that this form counts as a "no location" marker. EXPECT_TRUE(DbgDeclare->isKillLocation()); } @@ -240,9 +239,6 @@ TEST(DbgVariableIntrinsic, EmptyMDIsKillLocation) { // Duplicate of above test, but in DbgVariableRecord representation. TEST(MetadataTest, DeleteInstUsedByDbgVariableRecord) { LLVMContext C; - bool OldDbgValueMode = UseNewDbgInfoFormat; - UseNewDbgInfoFormat = true; - std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { %b = add i16 %a, 1, !dbg !11 @@ -268,7 +264,10 @@ TEST(MetadataTest, DeleteInstUsedByDbgVariableRecord) { !11 = !DILocation(line: 1, column: 1, scope: !6) )"); + bool OldDbgValueMode = UseNewDbgInfoFormat; + UseNewDbgInfoFormat = true; Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI(); + M->convertToNewDbgValues(); // Find the DbgVariableRecords using %b. SmallVector DVIs; @@ -290,8 +289,6 @@ TEST(MetadataTest, DeleteInstUsedByDbgVariableRecord) { // Ensure that the order of dbg.value intrinsics returned by findDbgValues, and // their corresponding DbgVariableRecord representation, are consistent. TEST(MetadataTest, OrderingOfDbgVariableRecords) { - bool OldDbgValueMode = UseNewDbgInfoFormat; - UseNewDbgInfoFormat = false; LLVMContext C; std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { @@ -319,6 +316,8 @@ TEST(MetadataTest, OrderingOfDbgVariableRecords) { !12 = !DILocalVariable(name: "bar", scope: !6, file: !1, line: 1, type: !10) )"); + bool OldDbgValueMode = UseNewDbgInfoFormat; + UseNewDbgInfoFormat = true; Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI(); SmallVector DVIs; @@ -516,15 +515,14 @@ TEST(DbgAssignIntrinsicTest, replaceVariableLocationOp) { Value *V1 = Fun.getArg(0); Value *P1 = Fun.getArg(1); Value *P2 = Fun.getArg(2); - DbgVariableRecord *DbgAssign = cast( - &*Fun.front().front().getDbgRecordRange().begin()); - ASSERT_TRUE(V1 == DbgAssign->getVariableLocationOp(0)); - ASSERT_TRUE(P1 == DbgAssign->getAddress()); + DbgAssignIntrinsic *DAI = cast(Fun.begin()->begin()); + ASSERT_TRUE(V1 == DAI->getVariableLocationOp(0)); + ASSERT_TRUE(P1 == DAI->getAddress()); #define TEST_REPLACE(Old, New, ExpectedValue, ExpectedAddr) \ - DbgAssign->replaceVariableLocationOp(Old, New); \ - EXPECT_EQ(DbgAssign->getVariableLocationOp(0), ExpectedValue); \ - EXPECT_EQ(DbgAssign->getAddress(), ExpectedAddr); + DAI->replaceVariableLocationOp(Old, New); \ + EXPECT_EQ(DAI->getVariableLocationOp(0), ExpectedValue); \ + EXPECT_EQ(DAI->getAddress(), ExpectedAddr); // Replace address only. TEST_REPLACE(/*Old*/ P1, /*New*/ P2, /*Value*/ V1, /*Address*/ P2); @@ -535,8 +533,8 @@ TEST(DbgAssignIntrinsicTest, replaceVariableLocationOp) { // Replace address only, value uses a DIArgList. // Value = {DIArgList(V1)}, Addr = P1. - DbgAssign->setRawLocation(DIArgList::get(C, ValueAsMetadata::get(V1))); - DbgAssign->setExpression(DIExpression::get( + DAI->setRawLocation(DIArgList::get(C, ValueAsMetadata::get(V1))); + DAI->setExpression(DIExpression::get( C, {dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_stack_value})); TEST_REPLACE(/*Old*/ P1, /*New*/ P2, /*Value*/ V1, /*Address*/ P2); #undef TEST_REPLACE @@ -622,11 +620,11 @@ TEST(AssignmentTrackingTest, Utils) { // // Check there are two llvm.dbg.assign intrinsics linked to Alloca. auto CheckFun1Mapping = [&Alloca]() { - auto Markers = at::getDVRAssignmentMarkers(&Alloca); + auto Markers = at::getAssignmentMarkers(&Alloca); EXPECT_TRUE(std::distance(Markers.begin(), Markers.end()) == 2); // Check those two entries are distinct. - DbgVariableRecord *First = *Markers.begin(); - DbgVariableRecord *Second = *std::next(Markers.begin()); + DbgAssignIntrinsic *First = *Markers.begin(); + DbgAssignIntrinsic *Second = *std::next(Markers.begin()); EXPECT_NE(First, Second); // Check that we can get back to Alloca from each llvm.dbg.assign. @@ -662,7 +660,7 @@ TEST(AssignmentTrackingTest, Utils) { DIAssignID *Fun2ID = cast_or_null( Fun2Alloca.getMetadata(LLVMContext::MD_DIAssignID)); EXPECT_NE(New, Fun2ID); - auto Fun2Markers = at::getDVRAssignmentMarkers(&Fun2Alloca); + auto Fun2Markers = at::getAssignmentMarkers(&Fun2Alloca); ASSERT_TRUE(std::distance(Fun2Markers.begin(), Fun2Markers.end()) == 1); auto Fun2Insts = at::getAssignmentInsts(*Fun2Markers.begin()); ASSERT_TRUE(std::distance(Fun2Insts.begin(), Fun2Insts.end()) == 1); @@ -671,10 +669,10 @@ TEST(AssignmentTrackingTest, Utils) { // 3. Check that deleting dbg.assigns from a specific instruction works. Instruction &Fun3Alloca = *M->getFunction("fun3")->getEntryBlock().getFirstNonPHIOrDbg(); - auto Fun3Markers = at::getDVRAssignmentMarkers(&Fun3Alloca); + auto Fun3Markers = at::getAssignmentMarkers(&Fun3Alloca); ASSERT_TRUE(std::distance(Fun3Markers.begin(), Fun3Markers.end()) == 1); at::deleteAssignmentMarkers(&Fun3Alloca); - Fun3Markers = at::getDVRAssignmentMarkers(&Fun3Alloca); + Fun3Markers = at::getAssignmentMarkers(&Fun3Alloca); EXPECT_EQ(Fun3Markers.empty(), true); // 4. Check that deleting works and applies only to the target function. @@ -685,7 +683,7 @@ TEST(AssignmentTrackingTest, Utils) { // llvm.dbg.assign. EXPECT_EQ(Fun2ID, cast_or_null( Fun2Alloca.getMetadata(LLVMContext::MD_DIAssignID))); - EXPECT_FALSE(at::getDVRAssignmentMarkers(&Fun2Alloca).empty()); + EXPECT_FALSE(at::getAssignmentMarkers(&Fun2Alloca).empty()); } TEST(IRBuilder, GetSetInsertionPointWithEmptyBasicBlock) { @@ -771,12 +769,12 @@ TEST(AssignmentTrackingTest, InstrMethods) { // Use SetVectors to check that the attachments and markers are unique // (another test requirement). SetVector OrigIDs; - SetVector Markers; + SetVector Markers; for (const Instruction *SI : Stores) { Metadata *ID = SI->getMetadata(LLVMContext::MD_DIAssignID); ASSERT_TRUE(OrigIDs.insert(ID)); ASSERT_TRUE(ID != nullptr); - auto Range = at::getDVRAssignmentMarkers(SI); + auto Range = at::getAssignmentMarkers(SI); ASSERT_TRUE(std::distance(Range.begin(), Range.end()) == 1); ASSERT_TRUE(Markers.insert(*Range.begin())); } @@ -869,8 +867,6 @@ TEST(AssignmentTrackingTest, InstrMethods) { // dbg.values that have been converted to a non-instruction format. TEST(MetadataTest, ConvertDbgToDbgVariableRecord) { LLVMContext C; - bool OldDbgValueMode = UseNewDbgInfoFormat; - UseNewDbgInfoFormat = false; std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 @@ -1045,14 +1041,14 @@ TEST(MetadataTest, ConvertDbgToDbgVariableRecord) { // The record of those trailing DbgVariableRecords would dangle and cause an // assertion failure if it lived until the end of the LLVMContext. ExitBlock->deleteTrailingDbgRecords(); - UseNewDbgInfoFormat = OldDbgValueMode; } TEST(MetadataTest, DbgVariableRecordConversionRoutines) { LLVMContext C; - bool OldDbgValueMode = UseNewDbgInfoFormat; - UseNewDbgInfoFormat = false; + // For the purpose of this test, set and un-set the command line option + // corresponding to UseNewDbgInfoFormat. + UseNewDbgInfoFormat = true; std::unique_ptr M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { @@ -1083,11 +1079,6 @@ TEST(MetadataTest, DbgVariableRecordConversionRoutines) { !11 = !DILocation(line: 1, column: 1, scope: !6) )"); - // For the purpose of this test, set and un-set the command line option - // corresponding to UseNewDbgInfoFormat, but only after parsing, to ensure - // that the IR starts off in the old format. - UseNewDbgInfoFormat = true; - // Check that the conversion routines and utilities between dbg.value // debug-info format and DbgVariableRecords works. Function *F = M->getFunction("f"); @@ -1192,7 +1183,7 @@ TEST(MetadataTest, DbgVariableRecordConversionRoutines) { EXPECT_EQ(DVI2->getVariable(), DLV2); EXPECT_EQ(DVI2->getExpression(), Expr2); - UseNewDbgInfoFormat = OldDbgValueMode; + UseNewDbgInfoFormat = false; } // Test that the hashing function for DISubprograms representing methods produce diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp index ff96df858120..2001df090aed 100644 --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -994,17 +994,17 @@ TEST_F(IRBuilderTest, DIBuilder) { EXPECT_TRUE(verifyModule(*M)); }; - // Test in new-debug mode. - EXPECT_TRUE(M->IsNewDbgInfoFormat); + // Test in old-debug mode. + EXPECT_FALSE(M->IsNewDbgInfoFormat); RunTest(); - // Test in old-debug mode. - // Reset the test then call convertFromNewDbgValues to flip the flag + // Test in new-debug mode. + // Reset the test then call convertToNewDbgValues to flip the flag // on the test's Module, Function and BasicBlock. TearDown(); SetUp(); - M->convertFromNewDbgValues(); - EXPECT_FALSE(M->IsNewDbgInfoFormat); + M->convertToNewDbgValues(); + EXPECT_TRUE(M->IsNewDbgInfoFormat); RunTest(); } diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp index b6044b286292..b47c73f0b329 100644 --- a/llvm/unittests/IR/InstructionsTest.cpp +++ b/llvm/unittests/IR/InstructionsTest.cpp @@ -25,15 +25,12 @@ #include "llvm/IR/Module.h" #include "llvm/IR/NoFolder.h" #include "llvm/IR/Operator.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/SourceMgr.h" #include "llvm-c/Core.h" #include "gmock/gmock-matchers.h" #include "gtest/gtest.h" #include -extern llvm::cl::opt UseNewDbgInfoFormat; - namespace llvm { namespace { @@ -1463,8 +1460,6 @@ TEST(InstructionsTest, GetSplat) { TEST(InstructionsTest, SkipDebug) { LLVMContext C; - bool OldDbgValueMode = UseNewDbgInfoFormat; - UseNewDbgInfoFormat = false; std::unique_ptr M = parseIR(C, R"( declare void @llvm.dbg.value(metadata, metadata, metadata) @@ -1500,7 +1495,6 @@ TEST(InstructionsTest, SkipDebug) { // After the terminator, there are no non-debug instructions. EXPECT_EQ(nullptr, Term->getNextNonDebugInstruction()); - UseNewDbgInfoFormat = OldDbgValueMode; } TEST(InstructionsTest, PhiMightNotBeFPMathOperator) { diff --git a/llvm/unittests/IR/ValueTest.cpp b/llvm/unittests/IR/ValueTest.cpp index 33a86d510d45..246c2fc7fe40 100644 --- a/llvm/unittests/IR/ValueTest.cpp +++ b/llvm/unittests/IR/ValueTest.cpp @@ -13,7 +13,6 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/ModuleSlotTracker.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" using namespace llvm; @@ -256,8 +255,6 @@ TEST(ValueTest, getLocalSlotDeath) { TEST(ValueTest, replaceUsesOutsideBlock) { // Check that Value::replaceUsesOutsideBlock(New, BB) replaces uses outside // BB, including dbg.* uses of MetadataAsValue(ValueAsMetadata(this)). - bool OldDbgValueMode = UseNewDbgInfoFormat; - UseNewDbgInfoFormat = false; const auto *IR = R"( define i32 @f() !dbg !6 { entry: @@ -318,7 +315,6 @@ TEST(ValueTest, replaceUsesOutsideBlock) { // These users are outside Entry so should be changed. ASSERT_TRUE(ExitDbg->getValue(0) == cast(B)); ASSERT_TRUE(Ret->getOperand(0) == cast(B)); - UseNewDbgInfoFormat = OldDbgValueMode; } TEST(ValueTest, replaceUsesOutsideBlockDbgVariableRecord) { @@ -363,6 +359,10 @@ TEST(ValueTest, replaceUsesOutsideBlockDbgVariableRecord) { if (!M) Err.print("ValueTest", errs()); + bool OldDbgValueMode = UseNewDbgInfoFormat; + UseNewDbgInfoFormat = true; + M->convertToNewDbgValues(); + auto GetNext = [](auto *I) { return &*++I->getIterator(); }; Function *F = M->getFunction("f"); @@ -389,6 +389,7 @@ TEST(ValueTest, replaceUsesOutsideBlockDbgVariableRecord) { EXPECT_TRUE(DVR1->getVariableLocationOp(0) == cast(A)); // These users are outside Entry so should be changed. EXPECT_TRUE(DVR2->getVariableLocationOp(0) == cast(B)); + UseNewDbgInfoFormat = OldDbgValueMode; } } // end anonymous namespace diff --git a/llvm/unittests/Transforms/Utils/CloningTest.cpp b/llvm/unittests/Transforms/Utils/CloningTest.cpp index 1d0d56a2099c..5e302d9c0a0d 100644 --- a/llvm/unittests/Transforms/Utils/CloningTest.cpp +++ b/llvm/unittests/Transforms/Utils/CloningTest.cpp @@ -844,9 +844,8 @@ TEST(CloneFunction, CloneFunctionWithInlinedSubprograms) { EXPECT_FALSE(verifyModule(*ImplModule, &errs())); // Check that DILexicalBlock of inlined function was not cloned. - auto DbgDeclareI = Func->begin()->begin()->getDbgRecordRange().begin(); - auto ClonedDbgDeclareI = - ClonedFunc->begin()->begin()->getDbgRecordRange().begin(); + auto DbgDeclareI = Func->begin()->begin(); + auto ClonedDbgDeclareI = ClonedFunc->begin()->begin(); const DebugLoc &DbgLoc = DbgDeclareI->getDebugLoc(); const DebugLoc &ClonedDbgLoc = ClonedDbgDeclareI->getDebugLoc(); EXPECT_NE(DbgLoc.get(), ClonedDbgLoc.get()); diff --git a/llvm/unittests/Transforms/Utils/LocalTest.cpp b/llvm/unittests/Transforms/Utils/LocalTest.cpp index 6052e58b697d..32c5244d3ff5 100644 --- a/llvm/unittests/Transforms/Utils/LocalTest.cpp +++ b/llvm/unittests/Transforms/Utils/LocalTest.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/Local.h" -#include "llvm/ADT/ScopeExit.h" #include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/PostDominators.h" @@ -27,27 +26,6 @@ using namespace llvm; -extern llvm::cl::opt UseNewDbgInfoFormat; -extern cl::opt PreserveInputDbgFormat; -extern bool WriteNewDbgInfoFormatToBitcode; -extern cl::opt WriteNewDbgInfoFormat; - -// Backup all of the existing settings that may be modified when -// PreserveInputDbgFormat=true, so that when the test is finished we return them -// (and the "preserve" setting) to their original values. -static auto SaveDbgInfoFormat() { - return make_scope_exit( - [OldPreserveInputDbgFormat = PreserveInputDbgFormat.getValue(), - OldUseNewDbgInfoFormat = UseNewDbgInfoFormat.getValue(), - OldWriteNewDbgInfoFormatToBitcode = WriteNewDbgInfoFormatToBitcode, - OldWriteNewDbgInfoFormat = WriteNewDbgInfoFormat.getValue()] { - PreserveInputDbgFormat = OldPreserveInputDbgFormat; - UseNewDbgInfoFormat = OldUseNewDbgInfoFormat; - WriteNewDbgInfoFormatToBitcode = OldWriteNewDbgInfoFormatToBitcode; - WriteNewDbgInfoFormat = OldWriteNewDbgInfoFormat; - }); -} - TEST(Local, RecursivelyDeleteDeadPHINodes) { LLVMContext C; @@ -138,6 +116,7 @@ static std::unique_ptr parseIR(LLVMContext &C, const char *IR) { TEST(Local, ReplaceDbgDeclare) { LLVMContext C; + // Original C source to get debug info for a local variable: // void f() { int x; } std::unique_ptr M = parseIR(C, @@ -145,11 +124,11 @@ TEST(Local, ReplaceDbgDeclare) { define void @f() !dbg !8 { entry: %x = alloca i32, align 4 - #dbg_declare(ptr %x, !11, !DIExpression(), !13) - #dbg_declare(ptr %x, !11, !DIExpression(), !13) + call void @llvm.dbg.declare(metadata i32* %x, metadata !11, metadata !DIExpression()), !dbg !13 + call void @llvm.dbg.declare(metadata i32* %x, metadata !11, metadata !DIExpression()), !dbg !13 ret void, !dbg !14 } - + declare void @llvm.dbg.declare(metadata, metadata, metadata) !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) @@ -172,18 +151,20 @@ TEST(Local, ReplaceDbgDeclare) { Instruction *Inst = &F->front().front(); auto *AI = dyn_cast(Inst); ASSERT_TRUE(AI); - + Inst = Inst->getNextNode()->getNextNode(); + ASSERT_TRUE(Inst); + auto *DII = dyn_cast(Inst); + ASSERT_TRUE(DII); Value *NewBase = Constant::getNullValue(PointerType::getUnqual(C)); DIBuilder DIB(*M); replaceDbgDeclare(AI, NewBase, DIB, DIExpression::ApplyOffset, 0); - // There should be exactly two dbg.declares, attached to the terminator. - Inst = F->front().getTerminator(); - ASSERT_TRUE(Inst); - EXPECT_TRUE(Inst->hasDbgRecords()); - EXPECT_EQ(range_size(Inst->getDbgRecordRange()), 2u); - for (DbgVariableRecord &DVR : filterDbgVars(Inst->getDbgRecordRange())) - EXPECT_EQ(DVR.getAddress(), NewBase); + // There should be exactly two dbg.declares. + int Declares = 0; + for (const Instruction &I : F->front()) + if (isa(I)) + Declares++; + EXPECT_EQ(2, Declares); } /// Build the dominator tree for the function and run the Test. @@ -518,10 +499,11 @@ struct SalvageDebugInfoTest : ::testing::Test { entry: %x = add i32 0, 1 %y = add i32 %x, 2 - #dbg_value(i32 %x, !11, !DIExpression(), !13) - #dbg_value(i32 %y, !11, !DIExpression(), !13) + call void @llvm.dbg.value(metadata i32 %x, metadata !11, metadata !DIExpression()), !dbg !13 + call void @llvm.dbg.value(metadata i32 %y, metadata !11, metadata !DIExpression()), !dbg !13 ret void, !dbg !14 } + declare void @llvm.dbg.value(metadata, metadata, metadata) !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) @@ -544,48 +526,49 @@ struct SalvageDebugInfoTest : ::testing::Test { ASSERT_TRUE(F); } - bool doesDebugValueDescribeX(const DbgVariableRecord &DVR) { - if (DVR.getNumVariableLocationOps() != 1u) + bool doesDebugValueDescribeX(const DbgValueInst &DI) { + if (DI.getNumVariableLocationOps() != 1u) return false; - const auto &CI = *cast(DVR.getValue(0)); + const auto &CI = *cast(DI.getValue(0)); if (CI.isZero()) - return DVR.getExpression()->getElements().equals( + return DI.getExpression()->getElements().equals( {dwarf::DW_OP_plus_uconst, 1, dwarf::DW_OP_stack_value}); else if (CI.isOneValue()) - return DVR.getExpression()->getElements().empty(); + return DI.getExpression()->getElements().empty(); return false; } - bool doesDebugValueDescribeY(const DbgVariableRecord &DVR) { - if (DVR.getNumVariableLocationOps() != 1u) + bool doesDebugValueDescribeY(const DbgValueInst &DI) { + if (DI.getNumVariableLocationOps() != 1u) return false; - const auto &CI = *cast(DVR.getVariableLocationOp(0)); + const auto &CI = *cast(DI.getVariableLocationOp(0)); if (CI.isZero()) - return DVR.getExpression()->getElements().equals( + return DI.getExpression()->getElements().equals( {dwarf::DW_OP_plus_uconst, 1, dwarf::DW_OP_plus_uconst, 2, dwarf::DW_OP_stack_value}); else if (CI.isOneValue()) - return DVR.getExpression()->getElements().equals( + return DI.getExpression()->getElements().equals( {dwarf::DW_OP_plus_uconst, 2, dwarf::DW_OP_stack_value}); return false; } void verifyDebugValuesAreSalvaged() { - // The function should only contain debug values and a terminator. - EXPECT_EQ(F->size(), 1u); - EXPECT_TRUE(F->begin()->begin()->isTerminator()); - // Check that the debug values for %x and %y are preserved. bool FoundX = false; bool FoundY = false; - for (DbgVariableRecord &DVR : - filterDbgVars(F->begin()->begin()->getDbgRecordRange())) { - EXPECT_EQ(DVR.getVariable()->getName(), "x"); - FoundX |= doesDebugValueDescribeX(DVR); - FoundY |= doesDebugValueDescribeY(DVR); + for (const Instruction &I : F->front()) { + auto DI = dyn_cast(&I); + if (!DI) { + // The function should only contain debug values and a terminator. + ASSERT_TRUE(I.isTerminator()); + continue; + } + EXPECT_EQ(DI->getVariable()->getName(), "x"); + FoundX |= doesDebugValueDescribeX(*DI); + FoundY |= doesDebugValueDescribeY(*DI); } - EXPECT_TRUE(FoundX); - EXPECT_TRUE(FoundY); + ASSERT_TRUE(FoundX); + ASSERT_TRUE(FoundY); } }; @@ -608,12 +591,6 @@ TEST_F(SalvageDebugInfoTest, RecursiveBlockSimplification) { TEST(Local, wouldInstructionBeTriviallyDead) { LLVMContext Ctx; - // FIXME: PreserveInputDbgFormat is set to true because this test has - // been written to expect debug intrinsics rather than debug records. - // TODO: This test doesn't have a DbgRecord equivalent form so delete - // it when debug intrinsics are removed. - auto SettingGuard = SaveDbgInfoFormat(); - PreserveInputDbgFormat = cl::boolOrDefault::BOU_TRUE; std::unique_ptr M = parseIR(Ctx, R"( define dso_local void @fun() local_unnamed_addr #0 !dbg !9 { @@ -707,10 +684,12 @@ TEST(Local, FindDbgUsers) { R"( define dso_local void @fun(ptr %a) #0 !dbg !11 { entry: - #dbg_assign(ptr %a, !16, !DIExpression(), !15, ptr %a, !DIExpression(), !19) + call void @llvm.dbg.assign(metadata ptr %a, metadata !16, metadata !DIExpression(), metadata !15, metadata ptr %a, metadata !DIExpression()), !dbg !19 ret void } + declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) + !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!2, !3, !9} !llvm.ident = !{!10} @@ -737,13 +716,9 @@ TEST(Local, FindDbgUsers) { verifyModule(*M, &errs(), &BrokenDebugInfo); ASSERT_FALSE(BrokenDebugInfo); - // Convert to debug intrinsics as we want to test findDbgUsers and - // findDbgValue's debug-intrinsic-finding code here. - // TODO: Remove this test when debug intrinsics are removed. - M->convertFromNewDbgValues(); - Function &Fun = *cast(M->getNamedValue("fun")); Value *Arg = Fun.getArg(0); + SmallVector Users; // Arg (%a) is used twice by a single dbg.assign. Check findDbgUsers returns // only 1 pointer to it rather than 2. @@ -764,7 +739,7 @@ TEST(Local, FindDbgRecords) { R"( define dso_local void @fun(ptr %a) #0 !dbg !11 { entry: - #dbg_assign(ptr %a, !16, !DIExpression(), !15, ptr %a, !DIExpression(), !19) + call void @llvm.dbg.assign(metadata ptr %a, metadata !16, metadata !DIExpression(), metadata !15, metadata ptr %a, metadata !DIExpression()), !dbg !19 ret void } @@ -793,6 +768,9 @@ TEST(Local, FindDbgRecords) { bool BrokenDebugInfo = true; verifyModule(*M, &errs(), &BrokenDebugInfo); ASSERT_FALSE(BrokenDebugInfo); + bool NewDbgInfoFormat = UseNewDbgInfoFormat; + UseNewDbgInfoFormat = true; + M->convertToNewDbgValues(); Function &Fun = *cast(M->getNamedValue("fun")); Value *Arg = Fun.getArg(0); @@ -812,10 +790,12 @@ TEST(Local, FindDbgRecords) { findDbgValues(Vals, Arg, &Records); EXPECT_EQ(Vals.size(), 0u); EXPECT_EQ(Records.size(), 1u); + UseNewDbgInfoFormat = NewDbgInfoFormat; } TEST(Local, ReplaceAllDbgUsesWith) { using namespace llvm::dwarf; + LLVMContext Ctx; // Note: The datalayout simulates Darwin/x86_64. @@ -828,36 +808,39 @@ TEST(Local, ReplaceAllDbgUsesWith) { define void @f() !dbg !6 { entry: %a = add i32 0, 1, !dbg !15 + call void @llvm.dbg.value(metadata i32 %a, metadata !9, metadata !DIExpression()), !dbg !15 - #dbg_value(i32 %a, !9, !DIExpression(), !15) %b = add i64 0, 1, !dbg !16 + call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression()), !dbg !16 + call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression(DW_OP_lit0, DW_OP_mul)), !dbg !16 + call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_stack_value)), !dbg !16 + call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 8)), !dbg !16 + call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_fragment, 0, 8)), !dbg !16 + call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8)), !dbg !16 - #dbg_value(i64 %b, !11, !DIExpression(), !16) - #dbg_value(i64 %b, !11, !DIExpression(DW_OP_lit0, DW_OP_mul), !16) - #dbg_value(i64 %b, !11, !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_stack_value), !16) - #dbg_value(i64 %b, !11, !DIExpression(DW_OP_LLVM_fragment, 0, 8), !16) - #dbg_value(i64 %b, !11, !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_fragment, 0, 8), !16) - #dbg_value(i64 %b, !11, !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8), !16) - %c = inttoptr i64 0 to ptr, !dbg !17 + %c = inttoptr i64 0 to i64*, !dbg !17 + call void @llvm.dbg.declare(metadata i64* %c, metadata !13, metadata !DIExpression()), !dbg !17 - #dbg_declare(ptr %c, !13, !DIExpression(), !17) - %d = inttoptr i64 0 to ptr, !dbg !18 + %d = inttoptr i64 0 to i32*, !dbg !18 + call void @llvm.dbg.declare(metadata i32* %d, metadata !20, metadata !DIExpression()), !dbg !18 - #dbg_declare(ptr %d, !20, !DIExpression(), !18) %e = add <2 x i16> zeroinitializer, zeroinitializer + call void @llvm.dbg.value(metadata <2 x i16> %e, metadata !14, metadata !DIExpression()), !dbg !18 - #dbg_value(<2 x i16> %e, !14, !DIExpression(), !18) %f = call i32 @escape(i32 0) + call void @llvm.dbg.value(metadata i32 %f, metadata !9, metadata !DIExpression()), !dbg !15 - #dbg_value(i32 %f, !9, !DIExpression(), !15) %barrier = call i32 @escape(i32 0) %g = call i32 @escape(i32 %f) + call void @llvm.dbg.value(metadata i32 %g, metadata !9, metadata !DIExpression()), !dbg !15 - #dbg_value(i32 %g, !9, !DIExpression(), !15) ret void, !dbg !19 } + declare void @llvm.dbg.declare(metadata, metadata, metadata) + declare void @llvm.dbg.value(metadata, metadata, metadata) + !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!5} @@ -912,47 +895,38 @@ TEST(Local, ReplaceAllDbgUsesWith) { EXPECT_TRUE(replaceAllDbgUsesWith(D, C, C, DT)); SmallVector CDbgVals; - SmallVector CDbgRecords; - findDbgUsers(CDbgVals, &C, &CDbgRecords); - EXPECT_EQ(0U, CDbgVals.size()); - EXPECT_EQ(2U, CDbgRecords.size()); - EXPECT_TRUE(all_of( - CDbgRecords, [](DbgVariableRecord *DVR) { return DVR->isDbgDeclare(); })); + findDbgUsers(CDbgVals, &C); + EXPECT_EQ(2U, CDbgVals.size()); + EXPECT_TRUE(all_of(CDbgVals, [](DbgVariableIntrinsic *DII) { + return isa(DII); + })); EXPECT_TRUE(replaceAllDbgUsesWith(C, D, D, DT)); SmallVector DDbgVals; - SmallVector DDbgRecords; - findDbgUsers(DDbgVals, &D, &DDbgRecords); - EXPECT_EQ(0U, DDbgVals.size()); - EXPECT_EQ(2U, DDbgRecords.size()); - EXPECT_TRUE(all_of( - DDbgRecords, [](DbgVariableRecord *DVR) { return DVR->isDbgDeclare(); })); + findDbgUsers(DDbgVals, &D); + EXPECT_EQ(2U, DDbgVals.size()); + EXPECT_TRUE(all_of(DDbgVals, [](DbgVariableIntrinsic *DII) { + return isa(DII); + })); // Introduce a use-before-def. Check that the dbg.value for %a is salvaged. EXPECT_TRUE(replaceAllDbgUsesWith(A, F_, F_, DT)); - EXPECT_FALSE(A.hasDbgRecords()); - EXPECT_TRUE(B.hasDbgRecords()); - DbgVariableRecord *BDbgVal = - cast(&*B.getDbgRecordRange().begin()); - EXPECT_EQ(BDbgVal->getNumVariableLocationOps(), 1u); - EXPECT_EQ(ConstantInt::get(A.getType(), 0), - BDbgVal->getVariableLocationOp(0)); + auto *ADbgVal = cast(A.getNextNode()); + EXPECT_EQ(ADbgVal->getNumVariableLocationOps(), 1u); + EXPECT_EQ(ConstantInt::get(A.getType(), 0), ADbgVal->getVariableLocationOp(0)); // Introduce a use-before-def. Check that the dbg.values for %f become undef. EXPECT_TRUE(replaceAllDbgUsesWith(F_, G, G, DT)); - DbgVariableRecord *BarrierDbgVal = - cast(&*Barrier.getDbgRecordRange().begin()); - EXPECT_EQ(BarrierDbgVal->getNumVariableLocationOps(), 1u); - EXPECT_TRUE(BarrierDbgVal->isKillLocation()); + auto *FDbgVal = cast(F_.getNextNode()); + EXPECT_EQ(FDbgVal->getNumVariableLocationOps(), 1u); + EXPECT_TRUE(FDbgVal->isKillLocation()); - SmallVector BarrierDbgVals; - SmallVector BarrierDbgRecs; - findDbgValues(BarrierDbgVals, &F_, &BarrierDbgRecs); - EXPECT_EQ(0U, BarrierDbgVals.size()); - EXPECT_EQ(0U, BarrierDbgRecs.size()); + SmallVector FDbgVals; + findDbgValues(FDbgVals, &F_); + EXPECT_EQ(0U, FDbgVals.size()); // Simulate i32 -> i64 conversion to test sign-extension. Here are some // interesting cases to handle: @@ -962,15 +936,13 @@ TEST(Local, ReplaceAllDbgUsesWith) { // 4-6) like (1-3), but with a fragment EXPECT_TRUE(replaceAllDbgUsesWith(B, A, A, DT)); - SmallVector BDbgVals; - SmallVector BDbgRecs; - findDbgValues(BDbgVals, &A, &BDbgRecs); - EXPECT_EQ(0U, BDbgVals.size()); - EXPECT_EQ(6U, BDbgRecs.size()); + SmallVector ADbgVals; + findDbgValues(ADbgVals, &A); + EXPECT_EQ(6U, ADbgVals.size()); // Check that %a has a dbg.value with a DIExpression matching \p Ops. auto hasADbgVal = [&](ArrayRef Ops) { - return any_of(BDbgRecs, [&](DbgVariableRecord *DVI) { + return any_of(ADbgVals, [&](DbgValueInst *DVI) { assert(DVI->getVariable()->getName() == "2"); return DVI->getExpression()->getElements() == Ops; }); @@ -1373,11 +1345,6 @@ TEST(Local, ExpressionForConstant) { TEST(Local, ReplaceDbgVariableRecord) { LLVMContext C; - // FIXME: PreserveInputDbgFormat is set to true because this test has - // been written to expect debug intrinsics rather than debug records; use the - // intrinsic format until we update the test checks. - auto SettingGuard = SaveDbgInfoFormat(); - PreserveInputDbgFormat = cl::boolOrDefault::BOU_TRUE; // Test that RAUW also replaces the operands of DbgVariableRecord objects, // i.e. non-instruction stored debugging information. -- GitLab From ad1083dce4f664265c5489ecd2e46649cd978683 Mon Sep 17 00:00:00 2001 From: Peiming Liu Date: Mon, 13 May 2024 17:29:01 -0700 Subject: [PATCH 150/578] [mlir][sparse] introduce new pass to propagate sparse encodings. (#92052) --- .../Dialect/SparseTensor/Transforms/Passes.h | 6 ++++ .../Dialect/SparseTensor/Transforms/Passes.td | 36 +++++++++++++++++++ .../Transforms/SparseTensorPasses.cpp | 13 +++++++ 3 files changed, 55 insertions(+) diff --git a/mlir/include/mlir/Dialect/SparseTensor/Transforms/Passes.h b/mlir/include/mlir/Dialect/SparseTensor/Transforms/Passes.h index d6d038ef65bd..bb49d6c256f2 100644 --- a/mlir/include/mlir/Dialect/SparseTensor/Transforms/Passes.h +++ b/mlir/include/mlir/Dialect/SparseTensor/Transforms/Passes.h @@ -65,6 +65,12 @@ void populateSparseAssembler(RewritePatternSet &patterns, bool directOut); std::unique_ptr createSparseAssembler(); std::unique_ptr createSparseAssembler(bool directOut); +//===----------------------------------------------------------------------===// +// The SparseEncodingPropagation pass. +//===----------------------------------------------------------------------===// + +std::unique_ptr createSparseEncodingPropagationPass(); + //===----------------------------------------------------------------------===// // The SparseReinterpretMap pass. //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Dialect/SparseTensor/Transforms/Passes.td b/mlir/include/mlir/Dialect/SparseTensor/Transforms/Passes.td index 2f844cee5ff5..94c3ca60030e 100644 --- a/mlir/include/mlir/Dialect/SparseTensor/Transforms/Passes.td +++ b/mlir/include/mlir/Dialect/SparseTensor/Transforms/Passes.td @@ -40,6 +40,42 @@ def SparseAssembler : Pass<"sparse-assembler", "ModuleOp"> { ]; } +def SparseEncodingPropagation : Pass<"sparse-encoding-propagation", "func::FuncOp"> { + let summary = "Propagate sparse tensor encodings"; + let description = [{ + A pass that propagates sparse tensor encodings. + + Background: To avoid introducing repetitive operations, sparse tensors + in MLIR try to reuse tensor operations whenever available. However, most + tensor operations are canonicalized/transformed without the knowledge + of sparsity. The pass tries to propagate missing sparse encodings. + + For example: + ```mlir + %s = tensor.extract_slice %input[0, 0,] [2, 1] [1, 1] + : tensor<2x3xf32, #sparse> to tensor<2x1xf32, #sparse> + + // After rank reducing (by tensor dialect transformation) + %t = tensor.extract_slice %input[0, 0,] [2, 1] [1, 1] + : tensor<2x3xf32, #sparse> to tensor<2xf32> + %s = tensor.expand_shape [[0, 1]] %t + : tensor<2xf32> to tensor<2x1xf32, #sparse> + + // After sparsity propagation + %t = tensor.extract_slice %input[0, 0,] [2, 1] [1, 1] + : tensor<2x3xf32, #sparse> to tensor<2xf32, #sparse1> + %s = tensor.expand_shape [[0, 1]] %t + : tensor<2xf32, #sparse1> to tensor<2x1xf32, #sparse> + ``` + }]; + + let constructor = "mlir::createSparseEncodingPropagationPass()"; + let dependentDialects = [ + "sparse_tensor::SparseTensorDialect", + "tensor::TensorDialect", + ]; +} + def SparseReinterpretMap : Pass<"sparse-reinterpret-map", "ModuleOp"> { let summary = "Reinterprets sparse tensor type mappings"; let description = [{ diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorPasses.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorPasses.cpp index b42d58634a36..f57353b5892b 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorPasses.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorPasses.cpp @@ -23,6 +23,7 @@ namespace mlir { #define GEN_PASS_DEF_SPARSEASSEMBLER +#define GEN_PASS_DEF_SPARSEENCODINGPROPAGATION #define GEN_PASS_DEF_SPARSEREINTERPRETMAP #define GEN_PASS_DEF_PRESPARSIFICATIONREWRITE #define GEN_PASS_DEF_SPARSIFICATIONPASS @@ -60,6 +61,14 @@ struct SparseAssembler : public impl::SparseAssemblerBase { } }; +struct SparseEncodingPropagation + : public impl::SparseEncodingPropagationBase { + SparseEncodingPropagation() = default; + SparseEncodingPropagation(const SparseEncodingPropagation &pass) = default; + + void runOnOperation() override {} +}; + struct SparseReinterpretMap : public impl::SparseReinterpretMapBase { SparseReinterpretMap() = default; @@ -398,6 +407,10 @@ std::unique_ptr mlir::createSparseAssembler() { return std::make_unique(); } +std::unique_ptr mlir::createSparseEncodingPropagationPass() { + return std::make_unique(); +} + std::unique_ptr mlir::createSparseReinterpretMapPass() { return std::make_unique(); } -- GitLab From 595de12ff307f3f06f4ccd2acafc400cc1262bc6 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 14 May 2024 09:44:49 +0900 Subject: [PATCH 151/578] [APFloat] Replace partsCount array with single variable (NFC) (#91910) We only ever use the last element of this array, so there shouldn't be a need to store the preceding elements as well. --- llvm/lib/Support/APFloat.cpp | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 64a7e0c7223f..2a9b3903720b 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -732,7 +732,7 @@ powerOf5(APFloatBase::integerPart *dst, unsigned int power) { APFloatBase::integerPart pow5s[maxPowerOfFiveParts * 2 + 5]; pow5s[0] = 78125 * 5; - unsigned int partsCount[16] = { 1 }; + unsigned int partsCount = 1; APFloatBase::integerPart scratch[maxPowerOfFiveParts], *p1, *p2, *pow5; unsigned int result; assert(power <= maxExponent); @@ -747,25 +747,20 @@ powerOf5(APFloatBase::integerPart *dst, unsigned int power) { pow5 = pow5s; for (unsigned int n = 0; power; power >>= 1, n++) { - unsigned int pc; - - pc = partsCount[n]; - /* Calculate pow(5,pow(2,n+3)) if we haven't yet. */ - if (pc == 0) { - pc = partsCount[n - 1]; - APInt::tcFullMultiply(pow5, pow5 - pc, pow5 - pc, pc, pc); - pc *= 2; - if (pow5[pc - 1] == 0) - pc--; - partsCount[n] = pc; + if (n != 0) { + APInt::tcFullMultiply(pow5, pow5 - partsCount, pow5 - partsCount, + partsCount, partsCount); + partsCount *= 2; + if (pow5[partsCount - 1] == 0) + partsCount--; } if (power & 1) { APFloatBase::integerPart *tmp; - APInt::tcFullMultiply(p2, p1, pow5, result, pc); - result += pc; + APInt::tcFullMultiply(p2, p1, pow5, result, partsCount); + result += partsCount; if (p2[result - 1] == 0) result--; @@ -776,7 +771,7 @@ powerOf5(APFloatBase::integerPart *dst, unsigned int power) { p2 = tmp; } - pow5 += pc; + pow5 += partsCount; } if (p1 != dst) -- GitLab From 37b8e5feb1d065a7c474e6595bac6d2f65faeb51 Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Mon, 13 May 2024 17:12:58 -0700 Subject: [PATCH 152/578] Revert "[lldb][DWARF] Delay struct/class/union definition DIE searching when parsing declaration DIEs. (#90663)" This reverts commit 9a7262c2601874e5aa64c5db19746770212d4b44. --- .../Plugins/SymbolFile/DWARF/DWARFASTParser.h | 2 - .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 397 ++++++++---------- .../SymbolFile/DWARF/DWARFASTParserClang.h | 197 +++++---- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 44 +- .../SymbolFile/DWARF/SymbolFileDWARF.h | 4 - .../SymbolFile/DWARF/UniqueDWARFASTType.cpp | 107 +++-- .../SymbolFile/DWARF/UniqueDWARFASTType.h | 36 +- 7 files changed, 383 insertions(+), 404 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index e144cf0f9bd9..66db396279e0 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -60,8 +60,6 @@ public: virtual ConstString GetDIEClassTemplateParams(const DWARFDIE &die) = 0; - virtual lldb_private::Type *FindDefinitionTypeForDIE(const DWARFDIE &die) = 0; - static std::optional ParseChildArrayInfo(const DWARFDIE &parent_die, const ExecutionContext *exe_ctx = nullptr); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 2a46be921612..034817c3b4fa 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -154,26 +154,6 @@ static bool TagIsRecordType(dw_tag_t tag) { } } -static bool IsForwardDeclaration(const DWARFDIE &die, - const ParsedDWARFTypeAttributes &attrs, - LanguageType cu_language) { - if (attrs.is_forward_declaration) - return true; - - // Work around an issue with clang at the moment where forward - // declarations for objective C classes are emitted as: - // DW_TAG_structure_type [2] - // DW_AT_name( "ForwardObjcClass" ) - // DW_AT_byte_size( 0x00 ) - // DW_AT_decl_file( "..." ) - // DW_AT_decl_line( 1 ) - // - // Note that there is no DW_AT_declaration and there are no children, - // and the byte size is zero. - return attrs.byte_size && *attrs.byte_size == 0 && attrs.name && - !die.HasChildren() && cu_language == eLanguageTypeObjC; -} - TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, const DWARFDIE &die, Log *log) { @@ -269,9 +249,11 @@ static void ForcefullyCompleteType(CompilerType type) { /// This function serves a similar purpose as RequireCompleteType above, but it /// avoids completing the type if it is not immediately necessary. It only /// ensures we _can_ complete the type later. -void DWARFASTParserClang::PrepareContextToReceiveMembers( - clang::DeclContext *decl_ctx, const DWARFDIE &decl_ctx_die, - const DWARFDIE &die, const char *type_name_cstr) { +static void PrepareContextToReceiveMembers(TypeSystemClang &ast, + ClangASTImporter &ast_importer, + clang::DeclContext *decl_ctx, + DWARFDIE die, + const char *type_name_cstr) { auto *tag_decl_ctx = clang::dyn_cast(decl_ctx); if (!tag_decl_ctx) return; // Non-tag context are always ready. @@ -286,8 +268,7 @@ void DWARFASTParserClang::PrepareContextToReceiveMembers( // gmodules case), we can complete the type by doing a full import. // If this type was not imported from an external AST, there's nothing to do. - CompilerType type = m_ast.GetTypeForDecl(tag_decl_ctx); - ClangASTImporter &ast_importer = GetClangASTImporter(); + CompilerType type = ast.GetTypeForDecl(tag_decl_ctx); if (type && ast_importer.CanImport(type)) { auto qual_type = ClangUtil::GetQualType(type); if (ast_importer.RequireCompleteType(qual_type)) @@ -298,13 +279,6 @@ void DWARFASTParserClang::PrepareContextToReceiveMembers( type_name_cstr ? type_name_cstr : "", die.GetOffset()); } - // By searching for the definition DIE of the decl_ctx type, we will either: - // 1. Found the the definition DIE and start its definition with - // TypeSystemClang::StartTagDeclarationDefinition. - // 2. Unable to find it, then need to forcefully complete it. - FindDefinitionTypeForDIE(decl_ctx_die); - if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined()) - return; // We don't have a type definition and/or the import failed. We must // forcefully complete the type to avoid crashes. ForcefullyCompleteType(type); @@ -646,11 +620,10 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, if (tag == DW_TAG_typedef) { // DeclContext will be populated when the clang type is materialized in // Type::ResolveCompilerType. - DWARFDIE decl_ctx_die; - clang::DeclContext *decl_ctx = - GetClangDeclContextContainingDIE(die, &decl_ctx_die); - PrepareContextToReceiveMembers(decl_ctx, decl_ctx_die, die, - attrs.name.GetCString()); + PrepareContextToReceiveMembers( + m_ast, GetClangASTImporter(), + GetClangDeclContextContainingDIE(die, nullptr), die, + attrs.name.GetCString()); if (attrs.type.IsValid()) { // Try to parse a typedef from the (DWARF embedded in the) Clang @@ -1130,6 +1103,32 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, // struct and see if this is actually a C++ method Type *class_type = dwarf->ResolveType(decl_ctx_die); if (class_type) { + if (class_type->GetID() != decl_ctx_die.GetID() || + IsClangModuleFwdDecl(decl_ctx_die)) { + + // We uniqued the parent class of this function to another + // class so we now need to associate all dies under + // "decl_ctx_die" to DIEs in the DIE for "class_type"... + DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID()); + + if (class_type_die) { + std::vector failures; + + CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die, + class_type, failures); + + // FIXME do something with these failures that's + // smarter than just dropping them on the ground. + // Unfortunately classes don't like having stuff added + // to them after their definitions are complete... + + Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { + return type_ptr->shared_from_this(); + } + } + } + if (attrs.specification.IsValid()) { // We have a specification which we are going to base our // function prototype off of, so we need this type to be @@ -1264,39 +1263,6 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, } } } - // By here, we should have already completed the c++ class_type - // because if either specification or abstract_origin is present, we - // call GetClangDeclContextForDIE to resolve the DW_TAG_subprogram - // refered by this one until we reached the DW_TAG_subprogram without - // specification or abstract_origin (the else branch above). Then the - // above GetFullCompilerType() will complete the class_type if it's - // not completed yet. After that, we will have the mapping from DIEs - // in class_type_die to DeclContexts in m_die_to_decl_ctx. - if (class_type->GetID() != decl_ctx_die.GetID() || - IsClangModuleFwdDecl(decl_ctx_die)) { - - // We uniqued the parent class of this function to another - // class so we now need to associate all dies under - // "decl_ctx_die" to DIEs in the DIE for "class_type"... - DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID()); - - if (class_type_die) { - std::vector failures; - - CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die, - class_type, failures); - - // FIXME do something with these failures that's - // smarter than just dropping them on the ground. - // Unfortunately classes don't like having stuff added - // to them after their definitions are complete... - - Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; - if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { - return type_ptr->shared_from_this(); - } - } - } } } } @@ -1669,93 +1635,6 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) { return qualified_name; } -lldb_private::Type * -DWARFASTParserClang::FindDefinitionTypeForDIE(const DWARFDIE &die) { - SymbolFileDWARF *dwarf = die.GetDWARF(); - ParsedDWARFTypeAttributes attrs(die); - bool is_forward_declaration = IsForwardDeclaration( - die, attrs, SymbolFileDWARF::GetLanguage(*die.GetCU())); - if (!is_forward_declaration) - return dwarf->GetDIEToType()[die.GetDIE()]; - - const dw_tag_t tag = die.Tag(); - TypeSP type_sp; - Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " - "forward declaration DIE, trying to find definition DIE", - static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), - attrs.name.GetCString()); - } - // We haven't parse definition die for this type, starting to search for it. - // After we found the definition die, the GetDeclarationDIEToDefinitionDIE() - // map will have the new mapping from this declaration die to definition die. - if (attrs.class_language == eLanguageTypeObjC || - attrs.class_language == eLanguageTypeObjC_plus_plus) { - if (!attrs.is_complete_objc_class && - die.Supports_DW_AT_APPLE_objc_complete_type()) { - // We have a valid eSymbolTypeObjCClass class symbol whose name - // matches the current objective C class that we are trying to find - // and this DIE isn't the complete definition (we checked - // is_complete_objc_class above and know it is false), so the real - // definition is in here somewhere - type_sp = - dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, - // see if we have a declaration anywhere else... - type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( - die, attrs.name, true); - } - } - - if (type_sp && log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is an " - "incomplete objc type, complete type is {5:x8}", - static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), tag, attrs.name.GetCString(), - type_sp->GetID()); - } - } - } - - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die); - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, see - // if we have a declaration anywhere else... - type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die); - } - if (type_sp && log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " - "forward declaration, complete type is {4:x8}", - static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), - attrs.name.GetCString(), type_sp->GetID()); - } - } - - if (!type_sp && log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " - "forward declaration, unable to find definition DIE for it", - static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), - attrs.name.GetCString()); - } - return type_sp.get(); -} - TypeSP DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, const DWARFDIE &die, @@ -1767,10 +1646,14 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, LanguageType cu_language = SymbolFileDWARF::GetLanguage(*die.GetCU()); Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); + // UniqueDWARFASTType is large, so don't create a local variables on the + // stack, put it on the heap. This function is often called recursively and + // clang isn't good at sharing the stack space for variables in different + // blocks. + auto unique_ast_entry_up = std::make_unique(); + ConstString unique_typename(attrs.name); Declaration unique_decl(attrs.decl); - uint64_t byte_size = attrs.byte_size.value_or(0); - attrs.is_forward_declaration = IsForwardDeclaration(die, attrs, cu_language); if (attrs.name) { if (Language::LanguageIsCPlusPlus(cu_language)) { @@ -1783,42 +1666,14 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, unique_decl.Clear(); } - if (UniqueDWARFASTType *unique_ast_entry_type = - dwarf->GetUniqueDWARFASTTypeMap().Find( - unique_typename, die, unique_decl, byte_size, - attrs.is_forward_declaration)) { - type_sp = unique_ast_entry_type->m_type_sp; + if (dwarf->GetUniqueDWARFASTTypeMap().Find( + unique_typename, die, unique_decl, attrs.byte_size.value_or(-1), + *unique_ast_entry_up)) { + type_sp = unique_ast_entry_up->m_type_sp; if (type_sp) { dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); LinkDeclContextToDIE( - GetCachedClangDeclContextForDIE(unique_ast_entry_type->m_die), die); - if (!attrs.is_forward_declaration) { - // If the DIE being parsed in this function is a definition and the - // entry in the map is a declaration, then we need to update the entry - // to point to the definition DIE. - if (unique_ast_entry_type->m_is_forward_declaration) { - unique_ast_entry_type->m_die = die; - unique_ast_entry_type->m_byte_size = byte_size; - unique_ast_entry_type->m_declaration = unique_decl; - unique_ast_entry_type->m_is_forward_declaration = false; - // Need to update Type ID to refer to the definition DIE. because - // it's used in ParseSubroutine to determine if we need to copy cxx - // method types from a declaration DIE to this definition DIE. - type_sp->SetID(die.GetID()); - clang_type = type_sp->GetForwardCompilerType(); - if (attrs.class_language != eLanguageTypeObjC && - attrs.class_language != eLanguageTypeObjC_plus_plus) - TypeSystemClang::StartTagDeclarationDefinition(clang_type); - - CompilerType compiler_type_no_qualifiers = - ClangUtil::RemoveFastQualifiers(clang_type); - auto result = dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace( - compiler_type_no_qualifiers.GetOpaqueQualType(), - *die.GetDIERef()); - if (!result.second) - result.first->second = *die.GetDIERef(); - } - } + GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die); return type_sp; } } @@ -1840,21 +1695,125 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, default_accessibility = eAccessPrivate; } + if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && + !die.HasChildren() && cu_language == eLanguageTypeObjC) { + // Work around an issue with clang at the moment where forward + // declarations for objective C classes are emitted as: + // DW_TAG_structure_type [2] + // DW_AT_name( "ForwardObjcClass" ) + // DW_AT_byte_size( 0x00 ) + // DW_AT_decl_file( "..." ) + // DW_AT_decl_line( 1 ) + // + // Note that there is no DW_AT_declaration and there are no children, + // and the byte size is zero. + attrs.is_forward_declaration = true; + } + + if (attrs.class_language == eLanguageTypeObjC || + attrs.class_language == eLanguageTypeObjC_plus_plus) { + if (!attrs.is_complete_objc_class && + die.Supports_DW_AT_APPLE_objc_complete_type()) { + // We have a valid eSymbolTypeObjCClass class symbol whose name + // matches the current objective C class that we are trying to find + // and this DIE isn't the complete definition (we checked + // is_complete_objc_class above and know it is false), so the real + // definition is in here somewhere + type_sp = + dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, + // see if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( + die, attrs.name, true); + } + } + + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is an " + "incomplete objc type, complete type is {5:x8}", + static_cast(this), die.GetOffset(), + DW_TAG_value_to_name(tag), tag, attrs.name.GetCString(), + type_sp->GetID()); + } + + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this + // die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } + } + if (attrs.is_forward_declaration) { + // We have a forward declaration to a type and we need to try and + // find a full declaration. We look in the current type index just in + // case we have a forward declaration followed by an actual + // declarations in the DWARF. If this fails, we need to look + // elsewhere... + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is a " + "forward declaration, trying to find complete type", + static_cast(this), die.GetOffset(), DW_TAG_value_to_name(tag), + tag, attrs.name.GetCString()); + } + // See if the type comes from a Clang module and if so, track down // that type. type_sp = ParseTypeFromClangModule(sc, die, log); if (type_sp) return type_sp; - } + // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, + // type_name_const_str); + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, see + // if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die); + } + } + + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} ({3}) type \"{4}\" is a " + "forward declaration, complete type is {5:x8}", + static_cast(this), die.GetOffset(), + DW_TAG_value_to_name(tag), tag, attrs.name.GetCString(), + type_sp->GetID()); + } + + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::DeclContext *defn_decl_ctx = + GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + } assert(tag_decl_kind != -1); UNUSED_IF_ASSERT_DISABLED(tag_decl_kind); - DWARFDIE decl_ctx_die; - clang::DeclContext *decl_ctx = - GetClangDeclContextContainingDIE(die, &decl_ctx_die); + bool clang_type_was_created = false; + clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); - PrepareContextToReceiveMembers(decl_ctx, decl_ctx_die, die, + PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, die, attrs.name.GetCString()); if (attrs.accessibility == eAccessNone && decl_ctx) { @@ -1893,17 +1852,20 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, tag_decl_kind, template_param_infos); clang_type = m_ast.CreateClassTemplateSpecializationType(class_specialization_decl); + clang_type_was_created = true; m_ast.SetMetadata(class_template_decl, metadata); m_ast.SetMetadata(class_specialization_decl, metadata); } - if (!clang_type) { + if (!clang_type_was_created) { + clang_type_was_created = true; clang_type = m_ast.CreateRecordType( decl_ctx, GetOwningClangModule(die), attrs.accessibility, attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata, attrs.exports_symbols); } + // Store a forward declaration to this class type in case any // parameters in any class methods need it for the clang types for // function prototypes. @@ -1914,19 +1876,13 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, Type::ResolveState::Forward, TypePayloadClang(OptionalClangModuleID(), attrs.is_complete_objc_class)); - // UniqueDWARFASTType is large, so don't create a local variables on the - // stack, put it on the heap. This function is often called recursively and - // clang isn't good at sharing the stack space for variables in different - // blocks. - auto unique_ast_entry_up = std::make_unique(); // Add our type to the unique type map so we don't end up creating many // copies of the same type over and over in the ASTContext for our // module unique_ast_entry_up->m_type_sp = type_sp; unique_ast_entry_up->m_die = die; unique_ast_entry_up->m_declaration = unique_decl; - unique_ast_entry_up->m_byte_size = byte_size; - unique_ast_entry_up->m_is_forward_declaration = attrs.is_forward_declaration; + unique_ast_entry_up->m_byte_size = attrs.byte_size.value_or(0); dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, *unique_ast_entry_up); @@ -1967,7 +1923,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, GetClangASTImporter().SetRecordLayout(record_decl, layout); } } - } else { + } else if (clang_type_was_created) { // Start the definition if the class is not objective C since the // underlying decls respond to isCompleteDefinition(). Objective // C decls don't respond to isCompleteDefinition() so we can't @@ -1979,21 +1935,26 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, if (attrs.class_language != eLanguageTypeObjC && attrs.class_language != eLanguageTypeObjC_plus_plus) TypeSystemClang::StartTagDeclarationDefinition(clang_type); + + // Leave this as a forward declaration until we need to know the + // details of the type. lldb_private::Type will automatically call + // the SymbolFile virtual function + // "SymbolFileDWARF::CompleteType(Type *)" When the definition + // needs to be defined. + assert(!dwarf->GetForwardDeclCompilerTypeToDIE().count( + ClangUtil::RemoveFastQualifiers(clang_type) + .GetOpaqueQualType()) && + "Type already in the forward declaration map!"); + // Can't assume m_ast.GetSymbolFile() is actually a + // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple + // binaries. + dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace( + ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(), + *die.GetDIERef()); + m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); } } - // If this is a declaration DIE, leave this as a forward declaration until we - // need to know the details of the type. lldb_private::Type will automatically - // call the SymbolFile virtual function "SymbolFileDWARF::CompleteType(Type - // *)" When the definition needs to be defined. - assert(!dwarf->GetForwardDeclCompilerTypeToDIE().count( - ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()) && - "Type already in the forward declaration map!"); - dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace( - ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(), - *die.GetDIERef()); - m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); - // If we made a clang type, set the trivial abi if applicable: We only // do this for pass by value - which implies the Trivial ABI. There // isn't a way to assert that something that would normally be pass by diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 853b8ccc3036..8d4af203bb28 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -42,40 +42,40 @@ struct ParsedDWARFTypeAttributes; class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { public: - typedef lldb_private::plugin::dwarf::DWARFDIE DWARFDIE; - DWARFASTParserClang(lldb_private::TypeSystemClang &ast); ~DWARFASTParserClang() override; // DWARFASTParser interface. - lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, - bool *type_is_new_ptr) override; + lldb::TypeSP + ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, + const lldb_private::plugin::dwarf::DWARFDIE &die, + bool *type_is_new_ptr) override; - lldb_private::ConstString - ConstructDemangledNameFromDWARF(const DWARFDIE &die) override; + lldb_private::ConstString ConstructDemangledNameFromDWARF( + const lldb_private::plugin::dwarf::DWARFDIE &die) override; lldb_private::Function * ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit, - const DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &die, const lldb_private::AddressRange &func_range) override; bool - CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, + CompleteTypeFromDWARF(const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::Type *type, lldb_private::CompilerType &compiler_type) override; - lldb_private::CompilerDecl - GetDeclForUIDFromDWARF(const DWARFDIE &die) override; + lldb_private::CompilerDecl GetDeclForUIDFromDWARF( + const lldb_private::plugin::dwarf::DWARFDIE &die) override; void EnsureAllDIEsInDeclContextHaveBeenParsed( lldb_private::CompilerDeclContext decl_context) override; - lldb_private::CompilerDeclContext - GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override; + lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF( + const lldb_private::plugin::dwarf::DWARFDIE &die) override; - lldb_private::CompilerDeclContext - GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override; + lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF( + const lldb_private::plugin::dwarf::DWARFDIE &die) override; lldb_private::ClangASTImporter &GetClangASTImporter(); @@ -105,13 +105,8 @@ public: /// \return A string, including surrounding '<>', of the template parameters. /// If the DIE's name already has '<>', returns an empty ConstString because /// it's assumed that the caller is using the DIE name anyway. - lldb_private::ConstString - GetDIEClassTemplateParams(const DWARFDIE &die) override; - - // Searching for definition DIE for the given DIE and return the type - // associated with the definition DIE, or nullptr if definition DIE is not - // found. - lldb_private::Type *FindDefinitionTypeForDIE(const DWARFDIE &die) override; + lldb_private::ConstString GetDIEClassTemplateParams( + const lldb_private::plugin::dwarf::DWARFDIE &die) override; protected: /// Protected typedefs and members. @@ -123,7 +118,8 @@ protected: const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap; - typedef std::multimap + typedef std::multimap DeclContextToDIEMap; typedef llvm::DenseMap< const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *, @@ -141,11 +137,14 @@ protected: std::unique_ptr m_clang_ast_importer_up; /// @} - clang::DeclContext *GetDeclContextForBlock(const DWARFDIE &die); + clang::DeclContext * + GetDeclContextForBlock(const lldb_private::plugin::dwarf::DWARFDIE &die); - clang::BlockDecl *ResolveBlockDIE(const DWARFDIE &die); + clang::BlockDecl * + ResolveBlockDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); - clang::NamespaceDecl *ResolveNamespaceDIE(const DWARFDIE &die); + clang::NamespaceDecl * + ResolveNamespaceDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); /// Returns the namespace decl that a DW_TAG_imported_declaration imports. /// @@ -156,86 +155,96 @@ protected: /// 'die' imports. If the imported entity is not a namespace /// or another import declaration, returns nullptr. If an error /// occurs, returns nullptr. - clang::NamespaceDecl *ResolveImportedDeclarationDIE(const DWARFDIE &die); + clang::NamespaceDecl *ResolveImportedDeclarationDIE( + const lldb_private::plugin::dwarf::DWARFDIE &die); - bool ParseTemplateDIE(const DWARFDIE &die, + bool ParseTemplateDIE(const lldb_private::plugin::dwarf::DWARFDIE &die, lldb_private::TypeSystemClang::TemplateParameterInfos &template_param_infos); bool ParseTemplateParameterInfos( - const DWARFDIE &parent_die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, lldb_private::TypeSystemClang::TemplateParameterInfos &template_param_infos); - std::string GetCPlusPlusQualifiedName(const DWARFDIE &die); + std::string + GetCPlusPlusQualifiedName(const lldb_private::plugin::dwarf::DWARFDIE &die); bool ParseChildMembers( - const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type, + const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::CompilerType &class_compiler_type, std::vector> &base_classes, - std::vector &member_function_dies, - std::vector &contained_type_dies, + std::vector &member_function_dies, + std::vector &contained_type_dies, DelayedPropertyList &delayed_properties, const lldb::AccessType default_accessibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info); size_t ParseChildParameters(clang::DeclContext *containing_decl_ctx, - const DWARFDIE &parent_die, bool skip_artificial, - bool &is_static, bool &is_variadic, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, + bool skip_artificial, bool &is_static, bool &is_variadic, bool &has_template_params, std::vector &function_args, std::vector &function_param_decls, unsigned &type_quals); - size_t ParseChildEnumerators(lldb_private::CompilerType &compiler_type, - bool is_signed, uint32_t enumerator_byte_size, - const DWARFDIE &parent_die); + size_t ParseChildEnumerators( + lldb_private::CompilerType &compiler_type, bool is_signed, + uint32_t enumerator_byte_size, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die); /// Parse a structure, class, or union type DIE. - lldb::TypeSP ParseStructureLikeDIE(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, - ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP + ParseStructureLikeDIE(const lldb_private::SymbolContext &sc, + const lldb_private::plugin::dwarf::DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); - clang::Decl *GetClangDeclForDIE(const DWARFDIE &die); + clang::Decl * + GetClangDeclForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); - clang::DeclContext *GetClangDeclContextForDIE(const DWARFDIE &die); + clang::DeclContext * + GetClangDeclContextForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); - clang::DeclContext *GetClangDeclContextContainingDIE(const DWARFDIE &die, - DWARFDIE *decl_ctx_die); - lldb_private::OptionalClangModuleID GetOwningClangModule(const DWARFDIE &die); + clang::DeclContext *GetClangDeclContextContainingDIE( + const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::plugin::dwarf::DWARFDIE *decl_ctx_die); + lldb_private::OptionalClangModuleID + GetOwningClangModule(const lldb_private::plugin::dwarf::DWARFDIE &die); - bool CopyUniqueClassMethodTypes(const DWARFDIE &src_class_die, - const DWARFDIE &dst_class_die, - lldb_private::Type *class_type, - std::vector &failures); + bool CopyUniqueClassMethodTypes( + const lldb_private::plugin::dwarf::DWARFDIE &src_class_die, + const lldb_private::plugin::dwarf::DWARFDIE &dst_class_die, + lldb_private::Type *class_type, + std::vector &failures); - clang::DeclContext *GetCachedClangDeclContextForDIE(const DWARFDIE &die); + clang::DeclContext *GetCachedClangDeclContextForDIE( + const lldb_private::plugin::dwarf::DWARFDIE &die); - void LinkDeclContextToDIE(clang::DeclContext *decl_ctx, const DWARFDIE &die); + void LinkDeclContextToDIE(clang::DeclContext *decl_ctx, + const lldb_private::plugin::dwarf::DWARFDIE &die); - void LinkDeclToDIE(clang::Decl *decl, const DWARFDIE &die); + void LinkDeclToDIE(clang::Decl *decl, + const lldb_private::plugin::dwarf::DWARFDIE &die); /// If \p type_sp is valid, calculate and set its symbol context scope, and /// update the type list for its backing symbol file. /// /// Returns \p type_sp. - lldb::TypeSP - UpdateSymbolContextScopeForType(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, lldb::TypeSP type_sp); + lldb::TypeSP UpdateSymbolContextScopeForType( + const lldb_private::SymbolContext &sc, + const lldb_private::plugin::dwarf::DWARFDIE &die, lldb::TypeSP type_sp); /// Follow Clang Module Skeleton CU references to find a type definition. - lldb::TypeSP ParseTypeFromClangModule(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, - lldb_private::Log *log); + lldb::TypeSP + ParseTypeFromClangModule(const lldb_private::SymbolContext &sc, + const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::Log *log); // Return true if this type is a declaration to a type in an external // module. - lldb::ModuleSP GetModuleForType(const DWARFDIE &die); - - void PrepareContextToReceiveMembers(clang::DeclContext *decl_ctx, - const DWARFDIE &decl_ctx_die, - const DWARFDIE &die, - const char *type_name_cstr); + lldb::ModuleSP + GetModuleForType(const lldb_private::plugin::dwarf::DWARFDIE &die); static bool classof(const DWARFASTParser *Parser) { return Parser->GetKind() == Kind::DWARFASTParserClang; @@ -265,8 +274,10 @@ private: /// Parsed form of all attributes that are relevant for parsing type members. struct MemberAttributes { - explicit MemberAttributes(const DWARFDIE &die, const DWARFDIE &parent_die, - lldb::ModuleSP module_sp); + explicit MemberAttributes( + const lldb_private::plugin::dwarf::DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, + lldb::ModuleSP module_sp); const char *name = nullptr; /// Indicates how many bits into the word (according to the host endianness) /// the low-order bit of the field starts. Can be negative. @@ -313,12 +324,15 @@ private: /// created property. /// \param delayed_properties The list of delayed properties that the result /// will be appended to. - void ParseObjCProperty(const DWARFDIE &die, const DWARFDIE &parent_die, - const lldb_private::CompilerType &class_clang_type, - DelayedPropertyList &delayed_properties); + void + ParseObjCProperty(const lldb_private::plugin::dwarf::DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, + const lldb_private::CompilerType &class_clang_type, + DelayedPropertyList &delayed_properties); void - ParseSingleMember(const DWARFDIE &die, const DWARFDIE &parent_die, + ParseSingleMember(const lldb_private::plugin::dwarf::DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, const lldb_private::CompilerType &class_clang_type, lldb::AccessType default_accessibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info, @@ -336,25 +350,31 @@ private: /// \param[in] class_clang_type The parent RecordType of the static /// member this function will create. void CreateStaticMemberVariable( - const DWARFDIE &die, const MemberAttributes &attrs, + const lldb_private::plugin::dwarf::DWARFDIE &die, + const MemberAttributes &attrs, const lldb_private::CompilerType &class_clang_type); - bool CompleteRecordType(const DWARFDIE &die, lldb_private::Type *type, + bool CompleteRecordType(const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::Type *type, lldb_private::CompilerType &clang_type); - bool CompleteEnumType(const DWARFDIE &die, lldb_private::Type *type, + bool CompleteEnumType(const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::Type *type, lldb_private::CompilerType &clang_type); - lldb::TypeSP ParseTypeModifier(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, - ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP + ParseTypeModifier(const lldb_private::SymbolContext &sc, + const lldb_private::plugin::dwarf::DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); lldb::TypeSP ParseEnum(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs); - lldb::TypeSP ParseSubroutine(const DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP ParseSubroutine(const lldb_private::plugin::dwarf::DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs); - lldb::TypeSP ParseArrayType(const DWARFDIE &die, + lldb::TypeSP ParseArrayType(const lldb_private::plugin::dwarf::DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs); - lldb::TypeSP ParsePointerToMemberType(const DWARFDIE &die, - const ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP + ParsePointerToMemberType(const lldb_private::plugin::dwarf::DWARFDIE &die, + const ParsedDWARFTypeAttributes &attrs); /// Parses a DW_TAG_inheritance DIE into a base/super class. /// @@ -371,7 +391,8 @@ private: /// \param layout_info The layout information that will be updated for C++ /// base classes with the base offset. void ParseInheritance( - const DWARFDIE &die, const DWARFDIE &parent_die, + const lldb_private::plugin::dwarf::DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, const lldb_private::CompilerType class_clang_type, const lldb::AccessType default_accessibility, const lldb::ModuleSP &module_sp, @@ -388,7 +409,8 @@ private: /// \param layout_info The layout information that will be updated for // base classes with the base offset void - ParseRustVariantPart(DWARFDIE &die, const DWARFDIE &parent_die, + ParseRustVariantPart(lldb_private::plugin::dwarf::DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, lldb_private::CompilerType &class_clang_type, const lldb::AccessType default_accesibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info); @@ -398,9 +420,8 @@ private: /// Some attributes are relevant for all kinds of types (declaration), while /// others are only meaningful to a specific type (is_virtual) struct ParsedDWARFTypeAttributes { - typedef lldb_private::plugin::dwarf::DWARFDIE DWARFDIE; - - explicit ParsedDWARFTypeAttributes(const DWARFDIE &die); + explicit ParsedDWARFTypeAttributes( + const lldb_private::plugin::dwarf::DWARFDIE &die); lldb::AccessType accessibility = lldb::eAccessNone; bool is_artificial = false; @@ -417,7 +438,7 @@ struct ParsedDWARFTypeAttributes { const char *mangled_name = nullptr; lldb_private::ConstString name; lldb_private::Declaration decl; - DWARFDIE object_pointer; + lldb_private::plugin::dwarf::DWARFDIE object_pointer; lldb_private::plugin::dwarf::DWARFFormValue abstract_origin; lldb_private::plugin::dwarf::DWARFFormValue containing_type; lldb_private::plugin::dwarf::DWARFFormValue signature; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 5a07fd30fbf7..f6f152726bf7 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1632,33 +1632,27 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { return true; } - // Once we start resolving this type, remove it from the forward - // declaration map in case anyone's child members or other types require this - // type to get resolved. - DWARFDIE dwarf_die = GetDIE(die_it->second); - GetForwardDeclCompilerTypeToDIE().erase(die_it); - Type *type = nullptr; - if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU())) - type = dwarf_ast->FindDefinitionTypeForDIE(dwarf_die); - if (!type) - return false; - - die_it = GetForwardDeclCompilerTypeToDIE().find( - compiler_type_no_qualifiers.GetOpaqueQualType()); - if (die_it != GetForwardDeclCompilerTypeToDIE().end()) { - dwarf_die = GetDIE(die_it->getSecond()); + DWARFDIE dwarf_die = GetDIE(die_it->getSecond()); + if (dwarf_die) { + // Once we start resolving this type, remove it from the forward + // declaration map in case anyone child members or other types require this + // type to get resolved. The type will get resolved when all of the calls + // to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done. GetForwardDeclCompilerTypeToDIE().erase(die_it); - } - if (Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion)) - GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( - log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...", - dwarf_die.GetID(), DW_TAG_value_to_name(dwarf_die.Tag()), - dwarf_die.Tag(), type->GetName().AsCString()); - assert(compiler_type); - if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU())) - return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type); - return true; + Type *type = GetDIEToType().lookup(dwarf_die.GetDIE()); + + Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion); + if (log) + GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( + log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...", + dwarf_die.GetID(), DW_TAG_value_to_name(dwarf_die.Tag()), + dwarf_die.Tag(), type->GetName().AsCString()); + assert(compiler_type); + if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU())) + return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type); + } + return false; } Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 94aa810680c5..7282c08c6857 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -533,12 +533,8 @@ protected: NameToOffsetMap m_function_scope_qualified_name_map; std::unique_ptr m_ranges; UniqueDWARFASTTypeMap m_unique_ast_type_map; - // A map from DIE to lldb_private::Type. For record type, the key might be - // either declaration DIE or definition DIE. DIEToTypePtr m_die_to_type; DIEToVariableSP m_die_to_variable_sp; - // A map from CompilerType to the struct/class/union/enum DIE (might be a - // declaration or a definition) that is used to construct it. CompilerTypeToDIE m_forward_decl_compiler_type_to_die; llvm::DenseMap> m_type_unit_support_files; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index 4762356034ca..223518f0ae82 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -13,67 +13,66 @@ using namespace lldb_private::dwarf; using namespace lldb_private::plugin::dwarf; -UniqueDWARFASTType *UniqueDWARFASTTypeList::Find( - const DWARFDIE &die, const lldb_private::Declaration &decl, - const int32_t byte_size, bool is_forward_declaration) { - for (UniqueDWARFASTType &udt : m_collection) { +bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, + const lldb_private::Declaration &decl, + const int32_t byte_size, + UniqueDWARFASTType &entry) const { + for (const UniqueDWARFASTType &udt : m_collection) { // Make sure the tags match if (udt.m_die.Tag() == die.Tag()) { - // If they are not both definition DIEs or both declaration DIEs, then - // don't check for byte size and declaration location, because declaration - // DIEs usually don't have those info. - bool matching_size_declaration = - udt.m_is_forward_declaration != is_forward_declaration - ? true - : (udt.m_byte_size < 0 || byte_size < 0 || - udt.m_byte_size == byte_size) && - udt.m_declaration == decl; - if (!matching_size_declaration) - continue; - // The type has the same name, and was defined on the same file and - // line. Now verify all of the parent DIEs match. - DWARFDIE parent_arg_die = die.GetParent(); - DWARFDIE parent_pos_die = udt.m_die.GetParent(); - bool match = true; - bool done = false; - while (!done && match && parent_arg_die && parent_pos_die) { - const dw_tag_t parent_arg_tag = parent_arg_die.Tag(); - const dw_tag_t parent_pos_tag = parent_pos_die.Tag(); - if (parent_arg_tag == parent_pos_tag) { - switch (parent_arg_tag) { - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_namespace: { - const char *parent_arg_die_name = parent_arg_die.GetName(); - if (parent_arg_die_name == nullptr) { - // Anonymous (i.e. no-name) struct - match = false; - } else { - const char *parent_pos_die_name = parent_pos_die.GetName(); - if (parent_pos_die_name == nullptr || - ((parent_arg_die_name != parent_pos_die_name) && - strcmp(parent_arg_die_name, parent_pos_die_name))) - match = false; + // Validate byte sizes of both types only if both are valid. + if (udt.m_byte_size < 0 || byte_size < 0 || + udt.m_byte_size == byte_size) { + // Make sure the file and line match + if (udt.m_declaration == decl) { + // The type has the same name, and was defined on the same file and + // line. Now verify all of the parent DIEs match. + DWARFDIE parent_arg_die = die.GetParent(); + DWARFDIE parent_pos_die = udt.m_die.GetParent(); + bool match = true; + bool done = false; + while (!done && match && parent_arg_die && parent_pos_die) { + const dw_tag_t parent_arg_tag = parent_arg_die.Tag(); + const dw_tag_t parent_pos_tag = parent_pos_die.Tag(); + if (parent_arg_tag == parent_pos_tag) { + switch (parent_arg_tag) { + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_namespace: { + const char *parent_arg_die_name = parent_arg_die.GetName(); + if (parent_arg_die_name == + nullptr) // Anonymous (i.e. no-name) struct + { + match = false; + } else { + const char *parent_pos_die_name = parent_pos_die.GetName(); + if (parent_pos_die_name == nullptr || + ((parent_arg_die_name != parent_pos_die_name) && + strcmp(parent_arg_die_name, parent_pos_die_name))) + match = false; + } + } break; + + case DW_TAG_compile_unit: + case DW_TAG_partial_unit: + done = true; + break; + default: + break; + } } - } break; + parent_arg_die = parent_arg_die.GetParent(); + parent_pos_die = parent_pos_die.GetParent(); + } - case DW_TAG_compile_unit: - case DW_TAG_partial_unit: - done = true; - break; - default: - break; + if (match) { + entry = udt; + return true; } } - parent_arg_die = parent_arg_die.GetParent(); - parent_pos_die = parent_pos_die.GetParent(); - } - - if (match) { - return &udt; } } } - return nullptr; + return false; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h index 29e5c02dcbe1..bf3cbae55e5c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h @@ -23,19 +23,31 @@ public: // Constructors and Destructors UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {} + UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die, + const Declaration &decl, int32_t byte_size) + : m_type_sp(type_sp), m_die(die), m_declaration(decl), + m_byte_size(byte_size) {} + UniqueDWARFASTType(const UniqueDWARFASTType &rhs) : m_type_sp(rhs.m_type_sp), m_die(rhs.m_die), - m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size), - m_is_forward_declaration(rhs.m_is_forward_declaration) {} + m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size) {} ~UniqueDWARFASTType() = default; + UniqueDWARFASTType &operator=(const UniqueDWARFASTType &rhs) { + if (this != &rhs) { + m_type_sp = rhs.m_type_sp; + m_die = rhs.m_die; + m_declaration = rhs.m_declaration; + m_byte_size = rhs.m_byte_size; + } + return *this; + } + lldb::TypeSP m_type_sp; DWARFDIE m_die; Declaration m_declaration; int32_t m_byte_size = -1; - // True if the m_die is a forward declaration DIE. - bool m_is_forward_declaration = true; }; class UniqueDWARFASTTypeList { @@ -50,9 +62,8 @@ public: m_collection.push_back(entry); } - UniqueDWARFASTType *Find(const DWARFDIE &die, const Declaration &decl, - const int32_t byte_size, - bool is_forward_declaration); + bool Find(const DWARFDIE &die, const Declaration &decl, + const int32_t byte_size, UniqueDWARFASTType &entry) const; protected: typedef std::vector collection; @@ -69,15 +80,14 @@ public: m_collection[name.GetCString()].Append(entry); } - UniqueDWARFASTType *Find(ConstString name, const DWARFDIE &die, - const Declaration &decl, const int32_t byte_size, - bool is_forward_declaration) { + bool Find(ConstString name, const DWARFDIE &die, const Declaration &decl, + const int32_t byte_size, UniqueDWARFASTType &entry) const { const char *unique_name_cstr = name.GetCString(); - collection::iterator pos = m_collection.find(unique_name_cstr); + collection::const_iterator pos = m_collection.find(unique_name_cstr); if (pos != m_collection.end()) { - return pos->second.Find(die, decl, byte_size, is_forward_declaration); + return pos->second.Find(die, decl, byte_size, entry); } - return nullptr; + return false; } protected: -- GitLab From 70de9b21cbdeb1297108c4ee520b8f6dbd6496a7 Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Mon, 13 May 2024 17:13:12 -0700 Subject: [PATCH 153/578] Revert "[lldb][DWARF] Do not complete type from declaration die. (#91799)" This reverts commit a7eff59f78f08f8ef0487dfe2a136fb311af4fd0. --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 034817c3b4fa..f8101aba5c62 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2306,11 +2306,6 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, if (!die) return false; - ParsedDWARFTypeAttributes attrs(die); - bool is_forward_declaration = IsForwardDeclaration( - die, attrs, SymbolFileDWARF::GetLanguage(*die.GetCU())); - if (is_forward_declaration) - return false; const dw_tag_t tag = die.Tag(); -- GitLab From b06f97b039b3a4f2397281609069b2aaad86dd59 Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Mon, 13 May 2024 18:02:38 -0700 Subject: [PATCH 154/578] [BOLT] Allow pass-through blocks in YAMLProfileReader (#91828) --- bolt/lib/Profile/DataReader.cpp | 1 + bolt/lib/Profile/YAMLProfileReader.cpp | 29 ++++++--- bolt/test/X86/profile-passthrough-block.test | 67 ++++++++++++++++++++ 3 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 bolt/test/X86/profile-passthrough-block.test diff --git a/bolt/lib/Profile/DataReader.cpp b/bolt/lib/Profile/DataReader.cpp index b2511ba10399..06c5e96b7806 100644 --- a/bolt/lib/Profile/DataReader.cpp +++ b/bolt/lib/Profile/DataReader.cpp @@ -775,6 +775,7 @@ bool DataReader::recordBranch(BinaryFunction &BF, uint64_t From, uint64_t To, if (collectedInBoltedBinary() && FromBB == ToBB) return true; + // Allow passthrough blocks. BinaryBasicBlock *FTSuccessor = FromBB->getConditionalSuccessor(false); if (FTSuccessor && FTSuccessor->succ_size() == 1 && FTSuccessor->getSuccessor(ToBB->getLabel())) { diff --git a/bolt/lib/Profile/YAMLProfileReader.cpp b/bolt/lib/Profile/YAMLProfileReader.cpp index e4673f6e3c30..978a7cadfe79 100644 --- a/bolt/lib/Profile/YAMLProfileReader.cpp +++ b/bolt/lib/Profile/YAMLProfileReader.cpp @@ -218,17 +218,28 @@ bool YAMLProfileReader::parseFunctionProfile( continue; } - BinaryBasicBlock &SuccessorBB = *Order[YamlSI.Index]; - if (!BB.getSuccessor(SuccessorBB.getLabel())) { - if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: no successor for block " << BB.getName() - << " that matches index " << YamlSI.Index << " or block " - << SuccessorBB.getName() << '\n'; - ++MismatchedEdges; - continue; + BinaryBasicBlock *ToBB = Order[YamlSI.Index]; + if (!BB.getSuccessor(ToBB->getLabel())) { + // Allow passthrough blocks. + BinaryBasicBlock *FTSuccessor = BB.getConditionalSuccessor(false); + if (FTSuccessor && FTSuccessor->succ_size() == 1 && + FTSuccessor->getSuccessor(ToBB->getLabel())) { + BinaryBasicBlock::BinaryBranchInfo &FTBI = + FTSuccessor->getBranchInfo(*ToBB); + FTBI.Count += YamlSI.Count; + FTBI.MispredictedCount += YamlSI.Mispreds; + ToBB = FTSuccessor; + } else { + if (opts::Verbosity >= 1) + errs() << "BOLT-WARNING: no successor for block " << BB.getName() + << " that matches index " << YamlSI.Index << " or block " + << ToBB->getName() << '\n'; + ++MismatchedEdges; + continue; + } } - BinaryBasicBlock::BinaryBranchInfo &BI = BB.getBranchInfo(SuccessorBB); + BinaryBasicBlock::BinaryBranchInfo &BI = BB.getBranchInfo(*ToBB); BI.Count += YamlSI.Count; BI.MispredictedCount += YamlSI.Mispreds; } diff --git a/bolt/test/X86/profile-passthrough-block.test b/bolt/test/X86/profile-passthrough-block.test new file mode 100644 index 000000000000..1b875885260d --- /dev/null +++ b/bolt/test/X86/profile-passthrough-block.test @@ -0,0 +1,67 @@ +## Test YAMLProfileReader support for pass-through blocks in non-matching edges: +## match the profile edge A -> C to the CFG with blocks A -> B -> C. + +# REQUIRES: system-linux +# RUN: split-file %s %t +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o +# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib +# RUN: llvm-bolt %t.exe -o %t.out --data %t/yaml --profile-ignore-hash -v=1 \ +# RUN: --print-cfg 2>&1 | FileCheck %s + +# CHECK: Binary Function "main" after building cfg +# CHECK: Profile Acc : 100.0% +# CHECK-NOT: BOLT-WARNING: no successor for block .LFT0 that matches index 3 or block .Ltmp0 + +#--- main.s +.globl main +.type main, @function +main: + .cfi_startproc +.LBB00: + pushq %rbp + movq %rsp, %rbp + subq $16, %rsp + testq %rax, %rax + js .LBB03 +.LBB01: + jne .LBB04 +.LBB02: + nop +.LBB03: + xorl %eax, %eax + addq $16, %rsp + popq %rbp + retq +.LBB04: + xorl %eax, %eax + addq $16, %rsp + popq %rbp + retq +## For relocations against .text +.LBB05: + call exit + .cfi_endproc + .size main, .-main + +#--- yaml +--- +header: + profile-version: 1 + binary-name: 'profile-passthrough-block.s.tmp.exe' + binary-build-id: '' + profile-flags: [ lbr ] + profile-origin: branch profile reader + profile-events: '' + dfs-order: false + hash-func: xxh3 +functions: + - name: main + fid: 0 + hash: 0x0000000000000000 + exec: 1 + nblocks: 6 + blocks: + - bid: 1 + insns: 1 + succ: [ { bid: 3, cnt: 1} ] +... -- GitLab From b1c958e50e5d58040c53e2aa822f4dfbcbf9c273 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 14 May 2024 10:06:10 +0900 Subject: [PATCH 155/578] [AArch64] Clarify atomic load/store size condition (NFCI) (#91907) This is currently bailing out on MemSizeInBytes larger than 64 bytes. However, the following code can only handle sizes up to 8 bytes. Possibly there was confusion here between MemSizeInBytes and MemSizeInBits. I *think* that this can't actually result in an out of bounds read of the opcode table because we'll only ever mark loads/stores of up to 8 bytes as legal (16 byte atomics are custom-legalized earlier). As such, I've changed this condition to an assert. --- llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index 1b65ae7b4782..3b3c1fc8b27b 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -2861,8 +2861,8 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { Order != AtomicOrdering::Unordered && Order != AtomicOrdering::Monotonic) { assert(!isa(LdSt)); - if (MemSizeInBytes > 64) - return false; + assert(MemSizeInBytes <= 8 && + "128-bit atomics should already be custom-legalized"); if (isa(LdSt)) { static constexpr unsigned LDAPROpcodes[] = { -- GitLab From 4420ea7a4971eadad528c0cd609da471a7614422 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 14 May 2024 10:06:41 +0900 Subject: [PATCH 156/578] [StringMap] Move free into StringMapImpl dtor (NFC) (#91908) StringMapImpl allocates the memory for the table, but does not have a dtor that free it. Instead, StringMap (which inherits from StringMapImpl) contains the free call. I don't really see a good reason why this free is performed in the "wrong" class, so move it into StringMapImpl. --- llvm/include/llvm/ADT/StringMap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/StringMap.h b/llvm/include/llvm/ADT/StringMap.h index daaf82654e09..9b58af732739 100644 --- a/llvm/include/llvm/ADT/StringMap.h +++ b/llvm/include/llvm/ADT/StringMap.h @@ -53,6 +53,7 @@ protected: } StringMapImpl(unsigned InitSize, unsigned ItemSize); + ~StringMapImpl() { free(TheTable); } unsigned RehashTable(unsigned BucketNo = 0); /// LookupBucketFor - Look up the bucket that the specified string should end @@ -203,7 +204,6 @@ public: } } } - free(TheTable); } using AllocTy::getAllocator; -- GitLab From 22cc4488c9dde0f0d27c0cfc58f6e82517c83f7f Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 13 May 2024 18:18:30 -0700 Subject: [PATCH 157/578] [bazel] Port libc #91905 --- .../llvm-project-overlay/libc/BUILD.bazel | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index ce61c432c2ed..9cdcc7577b46 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -122,6 +122,11 @@ libc_support_library( hdrs = ["hdr/errno_macros.h"], ) +libc_support_library( + name = "hdr_time_macros", + hdrs = ["hdr/time_macros.h"], +) + ############################ Type Proxy Header Files ########################### libc_support_library( @@ -149,6 +154,11 @@ libc_support_library( hdrs = ["hdr/types/struct_timespec.h"], ) +libc_support_library( + name = "types_time_t", + hdrs = ["hdr/types/time_t.h"], +) + ############################### Support libraries ############################## libc_support_library( @@ -1115,6 +1125,7 @@ libc_support_library( ":__support_cpp_optional", ":__support_osutil_syscall", ":__support_threads_linux_futex_word_type", + ":__support_time_linux", ":types_struct_timespec", ], ) @@ -1139,6 +1150,28 @@ libc_support_library( ], ) +libc_support_library( + name = "__support_time", + hdrs = glob(["src/__support/time/*.h"]), + deps = [ + ":hdr_time_macros", + ":types_time_t", + ], +) + +libc_support_library( + name = "__support_time_linux", + hdrs = glob(["src/__support/time/linux/**/*.h"]), + target_compatible_with = select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + deps = [ + ":__support_time", + ":hdr_time_macros", + ], +) + ############################### errno targets ################################ libc_function( -- GitLab From e6b2197a89f5d6d0f56a03c03b8afda561eee899 Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Mon, 13 May 2024 18:16:47 -0700 Subject: [PATCH 158/578] Revert a test that was failing after a previous reversion. This test was modified as part of the commit: 9a7262c2601874e5aa64c5db19746770212d4b44 but without that patch this test is failing. Remove the test for now till the issue with the original patch can be sorted out. --- .../delayed-definition-die-searching.test | 36 ------------------- 1 file changed, 36 deletions(-) delete mode 100644 lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test diff --git a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test deleted file mode 100644 index d253981b498c..000000000000 --- a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test +++ /dev/null @@ -1,36 +0,0 @@ -# Test definition DIE searching is delayed until complete type is required. - -# UNSUPPORTED: system-windows - -# RUN: split-file %s %t -# RUN: %clangxx_host %t/main.cpp %t/t1_def.cpp -gdwarf -o %t.out -# RUN: %lldb -b %t.out -s %t/lldb.cmd | FileCheck %s - -# CHECK: (lldb) p v1 -# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't2' -# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1' -# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't2' resolving forward declaration... -# CHECK: (t2) {} -# CHECK: (lldb) p v2 -# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1' -# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't1' resolving forward declaration... - -#--- lldb.cmd -log enable dwarf comp -p v1 -p v2 - -#--- main.cpp -template -struct t2 { -}; -struct t1; -t2 v1; // this CU doesn't have definition DIE for t1, but only declaration DIE for it. -int main() { -} - -#--- t1_def.cpp -struct t1 { // this CU contains definition DIE for t1. - int x; -}; -t1 v2; -- GitLab From f12018eba11f8d4b74cf67dbc416c429c870a5f4 Mon Sep 17 00:00:00 2001 From: Congcong Cai Date: Tue, 14 May 2024 09:48:57 +0800 Subject: [PATCH 159/578] [clang-tidy] support expect no diagnosis test (#91293) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When someone wants to declare a test case without any diagnosis. check-clang-tidy will failed with error message ``` CHECK-FIXES, CHECK-MESSAGES or CHECK-NOTES not found in the input ``` This PR want to check there are no diagnosis from clang-tidy when CHECK-FIXES, CHECK-MESSAGES or CHECK-NOTES are not found. It also changes the extension of a test case. `hxx` is not a valid test case extension and won't be tested. --------- Co-authored-by: Danny Mösch --- .../test/clang-tidy/check_clang_tidy.py | 28 +++++++++++++++---- .../checkers/misc/unused-using-decls.hpp | 6 ++++ .../checkers/misc/unused-using-decls.hxx | 6 ---- 3 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.hpp delete mode 100644 clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.hxx diff --git a/clang-tools-extra/test/clang-tidy/check_clang_tidy.py b/clang-tools-extra/test/clang-tidy/check_clang_tidy.py index 6d4b466afa69..e92179ac82c6 100755 --- a/clang-tools-extra/test/clang-tidy/check_clang_tidy.py +++ b/clang-tools-extra/test/clang-tidy/check_clang_tidy.py @@ -99,6 +99,7 @@ class CheckRunner: self.has_check_fixes = False self.has_check_messages = False self.has_check_notes = False + self.expect_no_diagnosis = False self.export_fixes = args.export_fixes self.fixes = MessagePrefix("CHECK-FIXES") self.messages = MessagePrefix("CHECK-MESSAGES") @@ -172,12 +173,21 @@ class CheckRunner: ) if not has_check_fix and not has_check_message and not has_check_note: - sys.exit( - "%s, %s or %s not found in the input" - % (self.fixes.prefix, self.messages.prefix, self.notes.prefix) - ) + self.expect_no_diagnosis = True - assert self.has_check_fixes or self.has_check_messages or self.has_check_notes + expect_diagnosis = ( + self.has_check_fixes or self.has_check_messages or self.has_check_notes + ) + if self.expect_no_diagnosis and expect_diagnosis: + sys.exit( + "%s, %s or %s not found in the input" + % ( + self.fixes.prefix, + self.messages.prefix, + self.notes.prefix, + ) + ) + assert expect_diagnosis or self.expect_no_diagnosis def prepare_test_inputs(self): # Remove the contents of the CHECK lines to avoid CHECKs matching on @@ -226,6 +236,10 @@ class CheckRunner: print("------------------------------------------------------------------") return clang_tidy_output + def check_no_diagnosis(self, clang_tidy_output): + if clang_tidy_output != "": + sys.exit("No diagnostics were expected, but found the ones above") + def check_fixes(self): if self.has_check_fixes: try_run( @@ -277,7 +291,9 @@ class CheckRunner: self.get_prefixes() self.prepare_test_inputs() clang_tidy_output = self.run_clang_tidy() - if self.export_fixes is None: + if self.expect_no_diagnosis: + self.check_no_diagnosis(clang_tidy_output) + elif self.export_fixes is None: self.check_fixes() self.check_messages(clang_tidy_output) self.check_notes(clang_tidy_output) diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.hpp b/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.hpp new file mode 100644 index 000000000000..4918aae16cb9 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.hpp @@ -0,0 +1,6 @@ +// RUN: %check_clang_tidy %s misc-unused-using-decls %t + +// Verify that we don't generate the warnings on header files. +namespace foo { class Foo {}; } + +using foo::Foo; diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.hxx b/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.hxx deleted file mode 100644 index f15e4fae80c0..000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.hxx +++ /dev/null @@ -1,6 +0,0 @@ -// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- --fix-notes -- -fno-delayed-template-parsing -isystem %S/Inputs - -// Verify that we don't generate the warnings on header files. -namespace foo { class Foo {}; } - -using foo::Foo; -- GitLab From 881d45cd7d3c5ea97f0d409bab5c57ae7bd43ab2 Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Tue, 14 May 2024 10:18:10 +0800 Subject: [PATCH 160/578] [X86][BF16] Do not combine FP_TRUNC + FP_EXTEND if they come from user (#91420) As discussed in https://github.com/llvm/llvm-project/commit/3cf8535dbf0bf5fafa99ea1f300e2384a7254fba We are not allowed to combine explicit fptrunc/fpext from user. --- llvm/lib/Target/X86/X86ISelLowering.cpp | 7 ++-- llvm/test/CodeGen/X86/bfloat.ll | 44 +++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index ecc5b3b3bf84..a57c10e784d9 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -56741,6 +56741,7 @@ static SDValue combineFP16_TO_FP(SDNode *N, SelectionDAG &DAG, } static SDValue combineFP_EXTEND(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, const X86Subtarget &Subtarget) { EVT VT = N->getValueType(0); bool IsStrict = N->isStrictFPOpcode(); @@ -56749,8 +56750,8 @@ static SDValue combineFP_EXTEND(SDNode *N, SelectionDAG &DAG, SDLoc dl(N); if (SrcVT.getScalarType() == MVT::bf16) { - if (!IsStrict && Src.getOpcode() == ISD::FP_ROUND && - Src.getOperand(0).getValueType() == VT) + if (DCI.isAfterLegalizeDAG() && Src.getOpcode() == ISD::FP_ROUND && + !IsStrict && Src.getOperand(0).getValueType() == VT) return Src.getOperand(0); if (!SrcVT.isVector()) @@ -57168,7 +57169,7 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N, case X86ISD::KSHIFTR: return combineKSHIFT(N, DAG, DCI); case ISD::FP16_TO_FP: return combineFP16_TO_FP(N, DAG, Subtarget); case ISD::STRICT_FP_EXTEND: - case ISD::FP_EXTEND: return combineFP_EXTEND(N, DAG, Subtarget); + case ISD::FP_EXTEND: return combineFP_EXTEND(N, DAG, DCI, Subtarget); case ISD::STRICT_FP_ROUND: case ISD::FP_ROUND: return combineFP_ROUND(N, DAG, Subtarget); case X86ISD::VBROADCAST_LOAD: diff --git a/llvm/test/CodeGen/X86/bfloat.ll b/llvm/test/CodeGen/X86/bfloat.ll index 39d8e2d50c91..b3e04590075f 100644 --- a/llvm/test/CodeGen/X86/bfloat.ll +++ b/llvm/test/CodeGen/X86/bfloat.ll @@ -2420,3 +2420,47 @@ define <16 x bfloat> @concat_dup_v8bf16(<8 x bfloat> %x, <8 x bfloat> %y) { %a = shufflevector <8 x bfloat> %x, <8 x bfloat> %y, <16 x i32> ret <16 x bfloat> %a } + +define float @trunc_ext(float %a) nounwind { +; X86-LABEL: trunc_ext: +; X86: # %bb.0: +; X86-NEXT: pushl %eax +; X86-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero +; X86-NEXT: vcvtneps2bf16 %xmm0, %xmm0 +; X86-NEXT: vmovw %xmm0, %eax +; X86-NEXT: shll $16, %eax +; X86-NEXT: vmovd %eax, %xmm0 +; X86-NEXT: vmovd %xmm0, (%esp) +; X86-NEXT: flds (%esp) +; X86-NEXT: popl %eax +; X86-NEXT: retl +; +; SSE2-LABEL: trunc_ext: +; SSE2: # %bb.0: +; SSE2-NEXT: pushq %rax +; SSE2-NEXT: callq __truncsfbf2@PLT +; SSE2-NEXT: pextrw $0, %xmm0, %eax +; SSE2-NEXT: shll $16, %eax +; SSE2-NEXT: movd %eax, %xmm0 +; SSE2-NEXT: popq %rax +; SSE2-NEXT: retq +; +; FP16-LABEL: trunc_ext: +; FP16: # %bb.0: +; FP16-NEXT: vcvtneps2bf16 %xmm0, %xmm0 +; FP16-NEXT: vmovw %xmm0, %eax +; FP16-NEXT: shll $16, %eax +; FP16-NEXT: vmovd %eax, %xmm0 +; FP16-NEXT: retq +; +; AVXNC-LABEL: trunc_ext: +; AVXNC: # %bb.0: +; AVXNC-NEXT: {vex} vcvtneps2bf16 %xmm0, %xmm0 +; AVXNC-NEXT: vmovd %xmm0, %eax +; AVXNC-NEXT: shll $16, %eax +; AVXNC-NEXT: vmovd %eax, %xmm0 +; AVXNC-NEXT: retq + %b = fptrunc float %a to bfloat + %c = fpext bfloat %b to float + ret float %c +} -- GitLab From c72e94382c21db2f5ff066d72103ac55eb8d2874 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Mon, 13 May 2024 19:19:15 -0700 Subject: [PATCH 161/578] [clang-format][NFC] Move LeftRightQualifierAlignmentFixer::is...() (#91930) Move static member functions LeftRightQualifierAlignmentFixer::is...() out of the class so that #91712 can reland. --- clang/lib/Format/QualifierAlignmentFixer.cpp | 11 +-- clang/lib/Format/QualifierAlignmentFixer.h | 19 ++-- clang/unittests/Format/QualifierFixerTest.cpp | 98 +++++++------------ 3 files changed, 52 insertions(+), 76 deletions(-) diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp index c26353045672..36d0639041c6 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.cpp +++ b/clang/lib/Format/QualifierAlignmentFixer.cpp @@ -614,22 +614,21 @@ void prepareLeftRightOrderingForQualifierAlignmentFixer( } } -bool LeftRightQualifierAlignmentFixer::isQualifierOrType(const FormatToken *Tok, - bool IsCpp) { +bool isQualifierOrType(const FormatToken *Tok, bool IsCpp) { return Tok && (Tok->isTypeName(IsCpp) || Tok->is(tok::kw_auto) || isQualifier(Tok)); } -bool LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - const FormatToken *Tok, const std::vector &Qualifiers, - bool IsCpp) { +bool isConfiguredQualifierOrType(const FormatToken *Tok, + const std::vector &Qualifiers, + bool IsCpp) { return Tok && (Tok->isTypeName(IsCpp) || Tok->is(tok::kw_auto) || isConfiguredQualifier(Tok, Qualifiers)); } // If a token is an identifier and it's upper case, it could // be a macro and hence we need to be able to ignore it. -bool LeftRightQualifierAlignmentFixer::isPossibleMacro(const FormatToken *Tok) { +bool isPossibleMacro(const FormatToken *Tok) { if (!Tok) return false; if (Tok->isNot(tok::identifier)) diff --git a/clang/lib/Format/QualifierAlignmentFixer.h b/clang/lib/Format/QualifierAlignmentFixer.h index e1cc27e62b13..e31d525da164 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.h +++ b/clang/lib/Format/QualifierAlignmentFixer.h @@ -32,6 +32,15 @@ void prepareLeftRightOrderingForQualifierAlignmentFixer( std::vector &RightOrder, std::vector &Qualifiers); +// Is the Token a simple or qualifier type +bool isQualifierOrType(const FormatToken *Tok, bool IsCpp = true); +bool isConfiguredQualifierOrType(const FormatToken *Tok, + const std::vector &Qualifiers, + bool IsCpp = true); + +// Is the Token likely a Macro +bool isPossibleMacro(const FormatToken *Tok); + class LeftRightQualifierAlignmentFixer : public TokenAnalyzer { std::string Qualifier; bool RightAlign; @@ -69,16 +78,6 @@ public: const FormatToken *Tok, const std::string &Qualifier, tok::TokenKind QualifierType); - - // Is the Token a simple or qualifier type - static bool isQualifierOrType(const FormatToken *Tok, bool IsCpp = true); - static bool - isConfiguredQualifierOrType(const FormatToken *Tok, - const std::vector &Qualifiers, - bool IsCpp = true); - - // Is the Token likely a Macro - static bool isPossibleMacro(const FormatToken *Tok); }; } // end namespace format diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index 792d8f3c3a98..1e997bb06b86 100644 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -1059,66 +1059,44 @@ TEST_F(QualifierFixerTest, IsQualifierType) { "const static inline auto restrict int double long constexpr friend"); ASSERT_EQ(Tokens.size(), 11u) << Tokens; - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[0], ConfiguredTokens)); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[1], ConfiguredTokens)); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[2], ConfiguredTokens)); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[3], ConfiguredTokens)); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[4], ConfiguredTokens)); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[5], ConfiguredTokens)); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[6], ConfiguredTokens)); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[7], ConfiguredTokens)); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[8], ConfiguredTokens)); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - Tokens[9], ConfiguredTokens)); - - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[0])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[1])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[2])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[3])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[4])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[5])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[6])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[7])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[8])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[9])); + EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[0], ConfiguredTokens)); + EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[1], ConfiguredTokens)); + EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[2], ConfiguredTokens)); + EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[3], ConfiguredTokens)); + EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[4], ConfiguredTokens)); + EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[5], ConfiguredTokens)); + EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[6], ConfiguredTokens)); + EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[7], ConfiguredTokens)); + EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[8], ConfiguredTokens)); + EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[9], ConfiguredTokens)); + + EXPECT_TRUE(isQualifierOrType(Tokens[0])); + EXPECT_TRUE(isQualifierOrType(Tokens[1])); + EXPECT_TRUE(isQualifierOrType(Tokens[2])); + EXPECT_TRUE(isQualifierOrType(Tokens[3])); + EXPECT_TRUE(isQualifierOrType(Tokens[4])); + EXPECT_TRUE(isQualifierOrType(Tokens[5])); + EXPECT_TRUE(isQualifierOrType(Tokens[6])); + EXPECT_TRUE(isQualifierOrType(Tokens[7])); + EXPECT_TRUE(isQualifierOrType(Tokens[8])); + EXPECT_TRUE(isQualifierOrType(Tokens[9])); auto NotTokens = annotate("for while do Foo Bar "); ASSERT_EQ(NotTokens.size(), 6u) << Tokens; - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[0], ConfiguredTokens)); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[1], ConfiguredTokens)); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[2], ConfiguredTokens)); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[3], ConfiguredTokens)); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[4], ConfiguredTokens)); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( - NotTokens[5], ConfiguredTokens)); - - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[0])); - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[1])); - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[2])); - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[3])); - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[4])); - EXPECT_FALSE( - LeftRightQualifierAlignmentFixer::isQualifierOrType(NotTokens[5])); + EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[0], ConfiguredTokens)); + EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[1], ConfiguredTokens)); + EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[2], ConfiguredTokens)); + EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[3], ConfiguredTokens)); + EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[4], ConfiguredTokens)); + EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[5], ConfiguredTokens)); + + EXPECT_FALSE(isQualifierOrType(NotTokens[0])); + EXPECT_FALSE(isQualifierOrType(NotTokens[1])); + EXPECT_FALSE(isQualifierOrType(NotTokens[2])); + EXPECT_FALSE(isQualifierOrType(NotTokens[3])); + EXPECT_FALSE(isQualifierOrType(NotTokens[4])); + EXPECT_FALSE(isQualifierOrType(NotTokens[5])); } TEST_F(QualifierFixerTest, IsMacro) { @@ -1126,10 +1104,10 @@ TEST_F(QualifierFixerTest, IsMacro) { auto Tokens = annotate("INT INTPR Foo int"); ASSERT_EQ(Tokens.size(), 5u) << Tokens; - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isPossibleMacro(Tokens[0])); - EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isPossibleMacro(Tokens[1])); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isPossibleMacro(Tokens[2])); - EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isPossibleMacro(Tokens[3])); + EXPECT_TRUE(isPossibleMacro(Tokens[0])); + EXPECT_TRUE(isPossibleMacro(Tokens[1])); + EXPECT_FALSE(isPossibleMacro(Tokens[2])); + EXPECT_FALSE(isPossibleMacro(Tokens[3])); } TEST_F(QualifierFixerTest, OverlappingQualifier) { -- GitLab From e20800c16f0570562fea31e9a02d65ba56e6858a Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Mon, 13 May 2024 19:45:11 -0700 Subject: [PATCH 162/578] [clang-format][NFC] Test IsQualifier only needs to call the lexer --- clang/unittests/Format/QualifierFixerTest.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index 1e997bb06b86..4ddeef50f5f7 100644 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -1055,7 +1055,9 @@ TEST_F(QualifierFixerTest, IsQualifierType) { ConfiguredTokens.push_back(tok::kw_constexpr); ConfiguredTokens.push_back(tok::kw_friend); - auto Tokens = annotate( + TestLexer lexer{Allocator, Buffers}; + + auto Tokens = lexer.lex( "const static inline auto restrict int double long constexpr friend"); ASSERT_EQ(Tokens.size(), 11u) << Tokens; @@ -1081,7 +1083,7 @@ TEST_F(QualifierFixerTest, IsQualifierType) { EXPECT_TRUE(isQualifierOrType(Tokens[8])); EXPECT_TRUE(isQualifierOrType(Tokens[9])); - auto NotTokens = annotate("for while do Foo Bar "); + auto NotTokens = lexer.lex("for while do Foo Bar "); ASSERT_EQ(NotTokens.size(), 6u) << Tokens; EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[0], ConfiguredTokens)); -- GitLab From 05a97a1a5143d0af60f2dc1e452c3f4ab7409b4c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 14 May 2024 12:21:55 +0900 Subject: [PATCH 163/578] [MustExec] Drop duplicate RUN line (NFC) --- llvm/test/Analysis/MustExecute/const-cond.ll | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/test/Analysis/MustExecute/const-cond.ll b/llvm/test/Analysis/MustExecute/const-cond.ll index e829db349ca6..97358f670b88 100644 --- a/llvm/test/Analysis/MustExecute/const-cond.ll +++ b/llvm/test/Analysis/MustExecute/const-cond.ll @@ -1,6 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -disable-output -passes=print-mustexecute %s 2>&1 | FileCheck %s -; RUN: opt -disable-output -passes=print-mustexecute %s 2>&1 | FileCheck %s ; In general the CFG below is easily simplified but this is useful for ; pass ordering issue elimination. -- GitLab From 3a25e358e2957cce912e701a544fb6163f572575 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 14 May 2024 12:26:15 +0900 Subject: [PATCH 164/578] [LICM] Generate test checks (NFC) --- llvm/test/Transforms/LICM/hoist-mustexec.ll | 480 +++++++++++++++++--- 1 file changed, 411 insertions(+), 69 deletions(-) diff --git a/llvm/test/Transforms/LICM/hoist-mustexec.ll b/llvm/test/Transforms/LICM/hoist-mustexec.ll index d47209941298..9f3c2f9b4e8c 100644 --- a/llvm/test/Transforms/LICM/hoist-mustexec.ll +++ b/llvm/test/Transforms/LICM/hoist-mustexec.ll @@ -1,18 +1,37 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; REQUIRES: asserts ; RUN: opt -S -passes=licm -ipt-expensive-asserts=true < %s | FileCheck %s -; RUN: opt -aa-pipeline=basic-aa -passes='require,loop-mssa(licm)' -ipt-expensive-asserts=true -S %s | FileCheck %s + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" declare void @f() nounwind declare void @llvm.experimental.guard(i1,...) ; constant fold on first ieration define i32 @test1(ptr noalias nocapture readonly %a) nounwind uwtable { -; CHECK-LABEL: @test1( +; CHECK-LABEL: define i32 @test1( +; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ] +; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ] +; CHECK-NEXT: [[R_CHK:%.*]] = icmp ult i32 [[IV]], 2000 +; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL:%.*]] +; CHECK: continue: +; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ] +; CHECK-NEXT: ret i32 [[ADD_LCSSA]] +; CHECK: fail: +; CHECK-NEXT: call void @f() +; CHECK-NEXT: ret i32 -1 +; entry: -; CHECK: %i1 = load i32, ptr %a, align 4 -; CHECK-NEXT: br label %for.body br label %for.body for.body: @@ -37,10 +56,29 @@ fail: ; Same as test1, but with a floating point IR and fcmp define i32 @test_fcmp(ptr noalias nocapture readonly %a) nounwind uwtable { -; CHECK-LABEL: @test_fcmp( +; CHECK-LABEL: define i32 @test_fcmp( +; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ] +; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ] +; CHECK-NEXT: [[R_CHK:%.*]] = fcmp olt float [[IV]], 2.000000e+03 +; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL:%.*]] +; CHECK: continue: +; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] +; CHECK-NEXT: [[INC]] = fadd float [[IV]], 1.000000e+00 +; CHECK-NEXT: [[EXITCOND:%.*]] = fcmp ogt float [[INC]], 1.000000e+03 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ] +; CHECK-NEXT: ret i32 [[ADD_LCSSA]] +; CHECK: fail: +; CHECK-NEXT: call void @f() +; CHECK-NEXT: ret i32 -1 +; entry: -; CHECK: %i1 = load i32, ptr %a, align 4 -; CHECK-NEXT: br label %for.body br label %for.body for.body: @@ -67,7 +105,35 @@ fail: ; TODO: currently unable to prove the following: ; ule i32 (add nsw i32 %len, -1), %len where len is [0, 512] define i32 @test2(ptr noalias nocapture readonly %a) nounwind uwtable { -; CHECK-LABEL: @test2( +; CHECK-LABEL: define i32 @test2( +; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0:![0-9]+]] +; CHECK-NEXT: [[IS_NON_POS:%.*]] = icmp eq i32 [[LEN]], 0 +; CHECK-NEXT: br i1 [[IS_NON_POS]], label [[FAIL:%.*]], label [[PREHEADER:%.*]] +; CHECK: preheader: +; CHECK-NEXT: [[LENMINUSONE:%.*]] = add nsw i32 [[LEN]], -1 +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LENMINUSONE]], [[PREHEADER]] ], [ [[DEC:%.*]], [[CONTINUE:%.*]] ] +; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ] +; CHECK-NEXT: [[R_CHK:%.*]] = icmp ule i32 [[IV]], [[LEN]] +; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]] +; CHECK: continue: +; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] +; CHECK-NEXT: [[DEC]] = add nsw i32 [[IV]], -1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[DEC]], 0 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ] +; CHECK-NEXT: ret i32 [[ADD_LCSSA]] +; CHECK: fail.loopexit: +; CHECK-NEXT: br label [[FAIL]] +; CHECK: fail: +; CHECK-NEXT: call void @f() +; CHECK-NEXT: ret i32 -1 +; entry: %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512} %is.non.pos = icmp eq i32 %len, 0 @@ -81,8 +147,6 @@ for.body: %r.chk = icmp ule i32 %iv, %len br i1 %r.chk, label %continue, label %fail continue: -; CHECK-LABEL: continue -; CHECK: %i1 = load i32, ptr %a, align 4 %i1 = load i32, ptr %a, align 4 %add = add nsw i32 %i1, %acc %dec = add nsw i32 %iv, -1 @@ -99,14 +163,39 @@ fail: ; trivially true for zero define i32 @test3(ptr noalias nocapture readonly %a) nounwind uwtable { -; CHECK-LABEL: @test3( +; CHECK-LABEL: define i32 @test3( +; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0]] +; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0 +; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]] +; CHECK: preheader: +; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ] +; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ] +; CHECK-NEXT: [[R_CHK:%.*]] = icmp ule i32 [[IV]], [[LEN]] +; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]] +; CHECK: continue: +; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ] +; CHECK-NEXT: ret i32 [[ADD_LCSSA]] +; CHECK: fail.loopexit: +; CHECK-NEXT: br label [[FAIL]] +; CHECK: fail: +; CHECK-NEXT: call void @f() +; CHECK-NEXT: ret i32 -1 +; entry: %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512} %is.zero = icmp eq i32 %len, 0 br i1 %is.zero, label %fail, label %preheader preheader: -; CHECK: %i1 = load i32, ptr %a, align 4 -; CHECK-NEXT: br label %for.body br label %for.body for.body: %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ] @@ -130,9 +219,10 @@ fail: ; requires fact length is non-zero define i32 @test4(ptr noalias nocapture readonly %a) nounwind uwtable { -; CHECK-LABEL: @test4( +; CHECK-LABEL: define i32 @test4( +; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A:%.*]], align 4, !range !0 +; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0]] ; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0 ; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]] ; CHECK: preheader: @@ -185,10 +275,29 @@ fail: ; variation on test1 with branch swapped define i32 @test-brswap(ptr noalias nocapture readonly %a) nounwind uwtable { -; CHECK-LABEL: @test-brswap( +; CHECK-LABEL: define i32 @test-brswap( +; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ] +; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ] +; CHECK-NEXT: [[R_CHK:%.*]] = icmp ugt i32 [[IV]], 2000 +; CHECK-NEXT: br i1 [[R_CHK]], label [[FAIL:%.*]], label [[CONTINUE]] +; CHECK: continue: +; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ] +; CHECK-NEXT: ret i32 [[ADD_LCSSA]] +; CHECK: fail: +; CHECK-NEXT: call void @f() +; CHECK-NEXT: ret i32 -1 +; entry: -; CHECK: %i1 = load i32, ptr %a, align 4 -; CHECK-NEXT: br label %for.body br label %for.body for.body: @@ -212,13 +321,33 @@ fail: } define i32 @test-nonphi(ptr noalias nocapture readonly %a) nounwind uwtable { -; CHECK-LABEL: @test-nonphi( +; CHECK-LABEL: define i32 @test-nonphi( +; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ] +; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ] +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[IV]], 72 +; CHECK-NEXT: [[R_CHK:%.*]] = icmp ugt i32 [[XOR]], 2000 +; CHECK-NEXT: br i1 [[R_CHK]], label [[FAIL:%.*]], label [[CONTINUE]] +; CHECK: continue: +; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ] +; CHECK-NEXT: ret i32 [[ADD_LCSSA]] +; CHECK: fail: +; CHECK-NEXT: call void @f() +; CHECK-NEXT: ret i32 -1 +; entry: br label %for.body for.body: -; CHECK-LABEL: continue -; CHECK: %i1 = load i32, ptr %a, align 4 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ] %acc = phi i32 [ 0, %entry ], [ %add, %continue ] %xor = xor i32 %iv, 72 @@ -240,7 +369,34 @@ fail: } define i32 @test-wrongphi(ptr noalias nocapture readonly %a) nounwind uwtable { -; CHECK-LABEL: @test-wrongphi( +; CHECK-LABEL: define i32 @test-wrongphi( +; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ] +; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ] +; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[IV]], 500 +; CHECK-NEXT: br i1 [[COND]], label [[DUMMY_BLOCK1:%.*]], label [[DUMMY_BLOCK2:%.*]] +; CHECK: dummy_block1: +; CHECK-NEXT: br label [[DUMMY_BLOCK2]] +; CHECK: dummy_block2: +; CHECK-NEXT: [[WRONGPHI:%.*]] = phi i32 [ 11, [[FOR_BODY]] ], [ 12, [[DUMMY_BLOCK1]] ] +; CHECK-NEXT: [[R_CHK:%.*]] = icmp ugt i32 [[WRONGPHI]], 2000 +; CHECK-NEXT: br i1 [[R_CHK]], label [[FAIL:%.*]], label [[CONTINUE]] +; CHECK: continue: +; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ] +; CHECK-NEXT: ret i32 [[ADD_LCSSA]] +; CHECK: fail: +; CHECK-NEXT: call void @f() +; CHECK-NEXT: ret i32 -1 +; entry: br label %for.body @@ -258,8 +414,6 @@ dummy_block2: %r.chk = icmp ugt i32 %wrongphi, 2000 br i1 %r.chk, label %fail, label %continue continue: -; CHECK-LABEL: continue -; CHECK: %i1 = load i32, ptr %a, align 4 %i1 = load i32, ptr %a, align 4 %add = add nsw i32 %i1, %acc %inc = add nuw nsw i32 %iv, 1 @@ -276,10 +430,34 @@ fail: ; This works because loop-simplify is run implicitly, but test for it anyways define i32 @test-multiple-latch(ptr noalias nocapture readonly %a) nounwind uwtable { -; CHECK-LABEL: @test-multiple-latch( +; CHECK-LABEL: define i32 @test-multiple-latch( +; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_BACKEDGE:%.*]] ] +; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY_BACKEDGE]] ] +; CHECK-NEXT: [[R_CHK:%.*]] = icmp ult i32 [[IV]], 2000 +; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE1:%.*]], label [[FAIL:%.*]] +; CHECK: continue1: +; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ADD]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[CONTINUE2:%.*]], label [[FOR_BODY_BACKEDGE]] +; CHECK: for.body.backedge: +; CHECK-NEXT: br label [[FOR_BODY]] +; CHECK: continue2: +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_BACKEDGE]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE2]] ] +; CHECK-NEXT: ret i32 [[ADD_LCSSA]] +; CHECK: fail: +; CHECK-NEXT: call void @f() +; CHECK-NEXT: ret i32 -1 +; entry: -; CHECK: %i1 = load i32, ptr %a, align 4 -; CHECK-NEXT: br label %for.body br label %for.body for.body: @@ -306,12 +484,21 @@ fail: } define void @test-hoisting-in-presence-of-guards(i1 %c, ptr %p) { - -; CHECK-LABEL: @test-hoisting-in-presence-of-guards -; CHECK: entry: -; CHECK: %a = load i32, ptr %p -; CHECK: %invariant_cond = icmp ne i32 %a, 100 +; CHECK-LABEL: define void @test-hoisting-in-presence-of-guards( +; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4 +; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100 +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ] +; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 +; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000 +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: br label %loop @@ -335,11 +522,30 @@ declare void @may_throw() inaccessiblememonly ; Test that we can sink a mustexecute load from loop header even in presence of ; throwing instructions after it. define void @test_hoist_from_header_01(ptr %p, i32 %n) { - -; CHECK-LABEL: @test_hoist_from_header_01( -; CHECK: entry: -; CHECK-NEXT: %load = load i32, ptr %p -; CHECK-NOT: load i32 +; CHECK-LABEL: define void @test_hoist_from_header_01( +; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: call void @may_throw() +; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; CHECK: if.true: +; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: if.false: +; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: backedge: +; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ] +; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]] +; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: br label %loop @@ -371,11 +577,30 @@ exit: } define void @test_hoist_from_header_02(ptr %p, i32 %n) { - -; CHECK-LABEL: @test_hoist_from_header_02( -; CHECK: entry: -; CHECK-NEXT: %load = load i32, ptr %p -; CHECK-NOT: load i32 +; CHECK-LABEL: define void @test_hoist_from_header_02( +; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; CHECK: if.true: +; CHECK-NEXT: call void @may_throw() +; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: if.false: +; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: backedge: +; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ] +; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]] +; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: br label %loop @@ -407,11 +632,30 @@ exit: } define void @test_hoist_from_header_03(ptr %p, i32 %n) { - -; CHECK-LABEL: @test_hoist_from_header_03( -; CHECK: entry: -; CHECK-NEXT: %load = load i32, ptr %p -; CHECK-NOT: load i32 +; CHECK-LABEL: define void @test_hoist_from_header_03( +; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; CHECK: if.true: +; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: if.false: +; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: backedge: +; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ] +; CHECK-NEXT: call void @may_throw() +; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]] +; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: br label %loop @@ -444,11 +688,30 @@ exit: ; Check that a throwing instruction prohibits hoisting across it. define void @test_hoist_from_header_04(ptr %p, i32 %n) { - -; CHECK-LABEL: @test_hoist_from_header_04( -; CHECK: entry: +; CHECK-LABEL: define void @test_hoist_from_header_04( +; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK: %load = load i32, ptr %p +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: call void @may_throw() +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4 +; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; CHECK: if.true: +; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: if.false: +; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: backedge: +; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ] +; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]] +; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: br label %loop @@ -482,11 +745,30 @@ exit: ; Check that we can hoist a mustexecute load from backedge even if something ; throws after it. define void @test_hoist_from_backedge_01(ptr %p, i32 %n) { - -; CHECK-LABEL: @test_hoist_from_backedge_01( -; CHECK: entry: -; CHECK-NEXT: %load = load i32, ptr %p -; CHECK-NOT: load i32 +; CHECK-LABEL: define void @test_hoist_from_backedge_01( +; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; CHECK: if.true: +; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: if.false: +; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: backedge: +; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ] +; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]] +; CHECK-NEXT: call void @may_throw() +; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: br label %loop @@ -519,11 +801,30 @@ exit: ; Check that we don't hoist the load if something before it can throw. define void @test_hoist_from_backedge_02(ptr %p, i32 %n) { - -; CHECK-LABEL: @test_hoist_from_backedge_02( -; CHECK: entry: +; CHECK-LABEL: define void @test_hoist_from_backedge_02( +; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK: %load = load i32, ptr %p +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; CHECK: if.true: +; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: if.false: +; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: backedge: +; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ] +; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]] +; CHECK-NEXT: call void @may_throw() +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4 +; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: br label %loop @@ -555,11 +856,30 @@ exit: } define void @test_hoist_from_backedge_03(ptr %p, i32 %n) { - -; CHECK-LABEL: @test_hoist_from_backedge_03( -; CHECK: entry: +; CHECK-LABEL: define void @test_hoist_from_backedge_03( +; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK: %load = load i32, ptr %p +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; CHECK: if.true: +; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: if.false: +; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]] +; CHECK-NEXT: call void @may_throw() +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: backedge: +; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ] +; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]] +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4 +; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: br label %loop @@ -591,11 +911,30 @@ exit: } define void @test_hoist_from_backedge_04(ptr %p, i32 %n) { - -; CHECK-LABEL: @test_hoist_from_backedge_04( -; CHECK: entry: +; CHECK-LABEL: define void @test_hoist_from_backedge_04( +; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK: %load = load i32, ptr %p +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: call void @may_throw() +; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; CHECK: if.true: +; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: if.false: +; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]] +; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK: backedge: +; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ] +; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]] +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4 +; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: br label %loop @@ -625,3 +964,6 @@ backedge: exit: ret void } +;. +; CHECK: [[RNG0]] = !{i32 0, i32 512} +;. -- GitLab From b7adba8e78662b901099dac5e06fd9f4beda22b4 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 14 May 2024 12:28:01 +0900 Subject: [PATCH 165/578] [LICM] Add must exec hoisting test with commuted operands (NFC) --- llvm/test/Transforms/LICM/hoist-mustexec.ll | 57 +++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/llvm/test/Transforms/LICM/hoist-mustexec.ll b/llvm/test/Transforms/LICM/hoist-mustexec.ll index 9f3c2f9b4e8c..81e0815053ff 100644 --- a/llvm/test/Transforms/LICM/hoist-mustexec.ll +++ b/llvm/test/Transforms/LICM/hoist-mustexec.ll @@ -217,6 +217,63 @@ fail: ret i32 -1 } +; Same as previous case, with commuted icmp. +; FIXME: The load should get hoisted here as well. +define i32 @test3_commuted(ptr noalias nocapture readonly %a) nounwind uwtable { +; CHECK-LABEL: define i32 @test3_commuted( +; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0]] +; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0 +; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]] +; CHECK: preheader: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ] +; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ] +; CHECK-NEXT: [[R_CHK:%.*]] = icmp uge i32 [[LEN]], [[IV]] +; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]] +; CHECK: continue: +; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 +; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ] +; CHECK-NEXT: ret i32 [[ADD_LCSSA]] +; CHECK: fail.loopexit: +; CHECK-NEXT: br label [[FAIL]] +; CHECK: fail: +; CHECK-NEXT: call void @f() +; CHECK-NEXT: ret i32 -1 +; +entry: + %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512} + %is.zero = icmp eq i32 %len, 0 + br i1 %is.zero, label %fail, label %preheader +preheader: + br label %for.body +for.body: + %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ] + %acc = phi i32 [ 0, %preheader ], [ %add, %continue ] + %r.chk = icmp uge i32 %len, %iv + br i1 %r.chk, label %continue, label %fail +continue: + %i1 = load i32, ptr %a, align 4 + %add = add nsw i32 %i1, %acc + %inc = add nuw nsw i32 %iv, 1 + %exitcond = icmp eq i32 %inc, 1000 + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: + ret i32 %add + +fail: + call void @f() + ret i32 -1 +} + ; requires fact length is non-zero define i32 @test4(ptr noalias nocapture readonly %a) nounwind uwtable { ; CHECK-LABEL: define i32 @test4( -- GitLab From 7198c3d613f1087c78124928cbe2cbc4e03a0e5a Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 13 May 2024 20:33:09 -0700 Subject: [PATCH 166/578] [RISCV] Reduce the amount of similar code in RISCVInstPrinter::printRlist. NFC (#92053) Remove the switch statement and instead do range checks to know which pieces we need to print. --- .../RISCV/MCTargetDesc/RISCVInstPrinter.cpp | 70 +++++++------------ 1 file changed, 26 insertions(+), 44 deletions(-) diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp index 663d4bad767d..48b669c78cad 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp @@ -216,62 +216,44 @@ void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo, RISCVVType::printVType(Imm, O); } +// Print a Zcmp RList. If we are printing architectural register names rather +// than ABI register names, we need to print "{x1, x8-x9, x18-x27}" for all +// registers. Otherwise, we print "{ra, s0-s11}". void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O) { unsigned Imm = MI->getOperand(OpNo).getImm(); O << "{"; - switch (Imm) { - case RISCVZC::RLISTENCODE::RA: - printRegName(O, RISCV::X1); - break; - case RISCVZC::RLISTENCODE::RA_S0: - printRegName(O, RISCV::X1); - O << ", "; - printRegName(O, RISCV::X8); - break; - case RISCVZC::RLISTENCODE::RA_S0_S1: - printRegName(O, RISCV::X1); - O << ", "; - printRegName(O, RISCV::X8); - O << '-'; - printRegName(O, RISCV::X9); - break; - case RISCVZC::RLISTENCODE::RA_S0_S2: - printRegName(O, RISCV::X1); - O << ", "; - printRegName(O, RISCV::X8); - O << '-'; - if (ArchRegNames) { - printRegName(O, RISCV::X9); - O << ", "; - } - printRegName(O, RISCV::X18); - break; - case RISCVZC::RLISTENCODE::RA_S0_S3: - case RISCVZC::RLISTENCODE::RA_S0_S4: - case RISCVZC::RLISTENCODE::RA_S0_S5: - case RISCVZC::RLISTENCODE::RA_S0_S6: - case RISCVZC::RLISTENCODE::RA_S0_S7: - case RISCVZC::RLISTENCODE::RA_S0_S8: - case RISCVZC::RLISTENCODE::RA_S0_S9: - case RISCVZC::RLISTENCODE::RA_S0_S11: - printRegName(O, RISCV::X1); + printRegName(O, RISCV::X1); + + if (Imm >= RISCVZC::RLISTENCODE::RA_S0) { O << ", "; printRegName(O, RISCV::X8); + } + + if (Imm >= RISCVZC::RLISTENCODE::RA_S0_S1) { O << '-'; - if (ArchRegNames) { + if (Imm == RISCVZC::RLISTENCODE::RA_S0_S1 || ArchRegNames) printRegName(O, RISCV::X9); + } + + if (Imm >= RISCVZC::RLISTENCODE::RA_S0_S2) { + if (ArchRegNames) O << ", "; + if (Imm == RISCVZC::RLISTENCODE::RA_S0_S2 || ArchRegNames) printRegName(O, RISCV::X18); + } + + if (Imm >= RISCVZC::RLISTENCODE::RA_S0_S3) { + if (ArchRegNames) O << '-'; - } - printRegName(O, RISCV::X19 + (Imm == RISCVZC::RLISTENCODE::RA_S0_S11 - ? 8 - : Imm - RISCVZC::RLISTENCODE::RA_S0_S3)); - break; - default: - llvm_unreachable("invalid register list"); + unsigned Offset = (Imm - RISCVZC::RLISTENCODE::RA_S0_S3); + // Encodings for S3-S9 are contiguous. There is no encoding for S10, so we + // must skip to S11(X27). + if (Imm == RISCVZC::RLISTENCODE::RA_S0_S11) + ++Offset; + printRegName(O, RISCV::X19 + Offset); } + O << "}"; } -- GitLab From f608ac261781b7707b2721563765e07c57366619 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 14 May 2024 03:54:24 +0000 Subject: [PATCH 167/578] [bazel] Actually port libc #91905 --- utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 9cdcc7577b46..446499cf15d7 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -129,6 +129,11 @@ libc_support_library( ############################ Type Proxy Header Files ########################### +libc_support_library( + name = "types_clockid_t", + hdrs = ["hdr/types/clockid_t.h"], +) + libc_support_library( name = "types_fenv_t", hdrs = ["hdr/types/fenv_t.h"], @@ -1154,6 +1159,7 @@ libc_support_library( name = "__support_time", hdrs = glob(["src/__support/time/*.h"]), deps = [ + ":__support_common", ":hdr_time_macros", ":types_time_t", ], @@ -1167,8 +1173,14 @@ libc_support_library( "//conditions:default": ["@platforms//:incompatible"], }), deps = [ + ":__support_common", + ":__support_cpp_expected", + ":__support_error_or", + ":__support_libc_assert", ":__support_time", ":hdr_time_macros", + ":types_clockid_t", + ":types_struct_timespec", ], ) -- GitLab From cf8b93d8234c13b6a6baf7f8a1e5bdb8c1c8cca1 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Mon, 13 May 2024 21:05:41 -0700 Subject: [PATCH 168/578] [alpha.webkit.UncountedCallArgsChecker] Allow explicit instantiation of Ref/RefPtr on call arguments. (#91875) Co-authored-by: Ryosuke Niwa --- clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp | 7 +++++++ clang/test/Analysis/Checkers/WebKit/call-args.cpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp index f81db0e67d83..be07cf51eefb 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp @@ -28,6 +28,13 @@ bool tryToFindPtrOrigin( E = tempExpr->getSubExpr(); continue; } + if (auto *tempExpr = dyn_cast(E)) { + if (auto *C = tempExpr->getConstructor()) { + if (auto *Class = C->getParent(); Class && isRefCounted(Class)) + return callback(E, true); + break; + } + } if (auto *tempExpr = dyn_cast(E)) { E = tempExpr->getSubExpr(); continue; diff --git a/clang/test/Analysis/Checkers/WebKit/call-args.cpp b/clang/test/Analysis/Checkers/WebKit/call-args.cpp index e1bee8a23a25..94efddeaf66c 100644 --- a/clang/test/Analysis/Checkers/WebKit/call-args.cpp +++ b/clang/test/Analysis/Checkers/WebKit/call-args.cpp @@ -358,3 +358,10 @@ namespace call_with_ptr_on_ref { // expected-warning@-1{{Call argument for parameter 'bad' is uncounted and unsafe}} } } + +namespace call_with_explicit_temporary_obj { + void foo() { + Ref { *provide() }->method(); + RefPtr { provide() }->method(); + } +} -- GitLab From cff9e77783aceb52da705b7e2b2e45bfbc86c628 Mon Sep 17 00:00:00 2001 From: cor3ntin Date: Tue, 14 May 2024 06:15:01 +0200 Subject: [PATCH 169/578] [Clang][NFC] Mark P2552 as implemented. (#92007) wg21.link/P2552 suggest that __has_cpp_attribute should return a non-zero value for all attributes that the implementation does something interesting with. Clang does something meaninful with all attributes except for: - no_unique_address which we do not support for msvc target - carries_dependency which arguably does nothing interesting. P2552 shies away from specifying a behavior for that attribute (despite being the only one for which a recommandation would have been interesting, arguably) As such, we have nothing to change for this paper. This paper is a DR and clang always behaved reasonably. --- clang/test/SemaCXX/cxx2c-attributes.cpp | 20 ++++++++++++++++++++ clang/www/cxx_status.html | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/cxx2c-attributes.cpp diff --git a/clang/test/SemaCXX/cxx2c-attributes.cpp b/clang/test/SemaCXX/cxx2c-attributes.cpp new file mode 100644 index 000000000000..c20a1b606a0f --- /dev/null +++ b/clang/test/SemaCXX/cxx2c-attributes.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple x86_64-pc-linux -fsyntax-only -verify -Wno-c++17-extensions +// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple x86_64-windows-msvc -fsyntax-only -verify=msvc -Wno-c++17-extensions +// expected-no-diagnostics + +// Check we return non-zero values for supported attributes as per +// wg21.link/P2552 +static_assert(__has_cpp_attribute(assume)); + +// The standard does not prescribe a behavior for [[carries_dependency]] + +static_assert(__has_cpp_attribute(deprecated)); +static_assert(__has_cpp_attribute(fallthrough)); +static_assert(__has_cpp_attribute(likely)); +static_assert(__has_cpp_attribute(unlikely)); +static_assert(__has_cpp_attribute(maybe_unused)); +static_assert(__has_cpp_attribute(nodiscard)); +static_assert(__has_cpp_attribute(noreturn)); + +// We do not support [[no_unique_address]] in MSVC emulation mode +static_assert(__has_cpp_attribute(no_unique_address)); // msvc-error {{static assertion failed}} diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 1338f544ffcb..06777eaa6df6 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -130,7 +130,7 @@ C++23, informally referred to as C++26.

On the ignorability of standard attributes P2552R3 (DR) - No + Yes Static storage for braced initializers -- GitLab From e5a277b16755ad273d6c1caa5dd29b4a3ae29078 Mon Sep 17 00:00:00 2001 From: Alex Bradbury Date: Tue, 14 May 2024 05:34:39 +0100 Subject: [PATCH 170/578] [TableGen][RISCV] Add initial support for marking profiles as experimental (#91993) This is just the TableGen-side changes, split out as the minimal testable unit. It doesn't yet transition RVA23 and friends to be experimental (and add the necessary other changes for this to work). Although choosing not to emit the SupportedExperimentalProfiles array if no experimental profiles are present isn't consistent with what we do for experimental extensions, we need to do this in order to avoid adding a warning for the empty array when building LLVM for as long as we don't have any experimental profiles defined. --- llvm/lib/Target/RISCV/RISCVProfiles.td | 6 +++- llvm/test/TableGen/riscv-target-def.td | 13 ++++++- llvm/utils/TableGen/RISCVTargetDefEmitter.cpp | 35 ++++++++++++++----- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVProfiles.td b/llvm/lib/Target/RISCV/RISCVProfiles.td index 5c13710faf65..e56df33bd8cb 100644 --- a/llvm/lib/Target/RISCV/RISCVProfiles.td +++ b/llvm/lib/Target/RISCV/RISCVProfiles.td @@ -8,7 +8,11 @@ class RISCVProfile features> : SubtargetFeature; + "RISC-V " # name # " profile", features> { + // Indicates if the profile is not yet ratified, so should be treated as + // experimental. + bit Experimental = false; +} defvar RVI20U32Features = [Feature32Bit, FeatureStdExtI]; defvar RVI20U64Features = [Feature64Bit, FeatureStdExtI]; diff --git a/llvm/test/TableGen/riscv-target-def.td b/llvm/test/TableGen/riscv-target-def.td index 7f3d9bdb278c..e328a6e3b583 100644 --- a/llvm/test/TableGen/riscv-target-def.td +++ b/llvm/test/TableGen/riscv-target-def.td @@ -53,12 +53,19 @@ def FeatureDummy class RISCVProfile features> : SubtargetFeature; + "RISC-V " # name # " profile", features> { + bit Experimental = false; +} +class RISCVExperimentalProfile features> + : RISCVProfile<"experimental-"#name, features> { + let Experimental = true; +} def RVI20U32 : RISCVProfile<"rvi20u32", [Feature32Bit, FeatureStdExtI]>; def RVI20U64 : RISCVProfile<"rvi20u64", [Feature64Bit, FeatureStdExtI]>; def ProfileDummy : RISCVProfile<"dummy", [Feature64Bit, FeatureStdExtI, FeatureStdExtF, FeatureStdExtZidummy]>; +def RVI99U64 : RISCVExperimentalProfile<"rvi99u64", [Feature64Bit, FeatureStdExtI]>; class RISCVProcessorModel &Features) { OS << LS << Ext.first << Ext.second.Major << 'p' << Ext.second.Minor; } +static void printProfileTable(raw_ostream &OS, + const std::vector &Profiles, + bool Experimental) { + OS << "static constexpr RISCVProfile Supported"; + if (Experimental) + OS << "Experimental"; + OS << "Profiles[] = {\n"; + + for (const Record *Rec : Profiles) { + if (Rec->getValueAsBit("Experimental") != Experimental) + continue; + + OS.indent(4) << "{\"" << Rec->getValueAsString("Name") << "\",\""; + printMArch(OS, Rec->getValueAsListOfDefs("Implies")); + OS << "\"},\n"; + } + + OS << "};\n\n"; +} + static void emitRISCVProfiles(RecordKeeper &Records, raw_ostream &OS) { OS << "#ifdef GET_SUPPORTED_PROFILES\n"; OS << "#undef GET_SUPPORTED_PROFILES\n\n"; @@ -129,15 +149,12 @@ static void emitRISCVProfiles(RecordKeeper &Records, raw_ostream &OS) { auto Profiles = Records.getAllDerivedDefinitionsIfDefined("RISCVProfile"); if (!Profiles.empty()) { - llvm::sort(Profiles, LessRecordFieldName()); - OS << "static constexpr RISCVProfile SupportedProfiles[] = {\n"; - for (const Record *Rec : Profiles) { - OS.indent(4) << "{\"" << Rec->getValueAsString("Name") << "\",\""; - printMArch(OS, Rec->getValueAsListOfDefs("Implies")); - OS << "\"},\n"; - } - - OS << "};\n\n"; + printProfileTable(OS, Profiles, /*Experimental=*/false); + bool HasExperimentalProfiles = any_of(Profiles, [&](auto &Rec) { + return Rec->getValueAsBit("Experimental"); + }); + if (HasExperimentalProfiles) + printProfileTable(OS, Profiles, /*Experimental=*/true); } OS << "#endif // GET_SUPPORTED_PROFILES\n\n"; -- GitLab From f0a681640e012356974024dd2971d74fc18f5b48 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 13 May 2024 21:34:06 -0700 Subject: [PATCH 171/578] [RISCV] Remove AllPopRegs array from RISCVFrameLowering.cpp. NFC The same registers are listed in the same order in FixedCSRFIMap. --- llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 35 +++++++++----------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index cb41577c5d94..316f6a90893a 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -42,10 +42,16 @@ RISCVFrameLowering::RISCVFrameLowering(const RISCVSubtarget &STI) /*TransientStackAlignment=*/getABIStackAlignment(STI.getTargetABI())), STI(STI) {} -static const MCPhysReg AllPopRegs[] = { - RISCV::X1, RISCV::X8, RISCV::X9, RISCV::X18, RISCV::X19, - RISCV::X20, RISCV::X21, RISCV::X22, RISCV::X23, RISCV::X24, - RISCV::X25, RISCV::X26, RISCV::X27}; +// Offsets which need to be scale by XLen representing locations of CSRs which +// are given a fixed location by save/restore libcalls or Zcmp Push/Pop. +static const std::pair FixedCSRFIMap[] = { + {/*ra*/ RISCV::X1, -1}, {/*s0*/ RISCV::X8, -2}, + {/*s1*/ RISCV::X9, -3}, {/*s2*/ RISCV::X18, -4}, + {/*s3*/ RISCV::X19, -5}, {/*s4*/ RISCV::X20, -6}, + {/*s5*/ RISCV::X21, -7}, {/*s6*/ RISCV::X22, -8}, + {/*s7*/ RISCV::X23, -9}, {/*s8*/ RISCV::X24, -10}, + {/*s9*/ RISCV::X25, -11}, {/*s10*/ RISCV::X26, -12}, + {/*s11*/ RISCV::X27, -13}}; // For now we use x3, a.k.a gp, as pointer to shadow call stack. // User should not use x3 in their asm. @@ -170,7 +176,7 @@ static int getLibCallID(const MachineFunction &MF, Register MaxReg = RISCV::NoRegister; for (auto &CS : CSI) - // RISCVRegisterInfo::hasReservedSpillSlot assigns negative frame indexes to + // assignCalleeSavedSpillSlots assigns negative frame indexes to // registers which can be saved by libcall. if (CS.getFrameIdx() < 0) MaxReg = std::max(MaxReg.id(), CS.getReg().id()); @@ -291,7 +297,9 @@ static Register getMaxPushPopReg(const MachineFunction &MF, const std::vector &CSI) { Register MaxPushPopReg = RISCV::NoRegister; for (auto &CS : CSI) { - if (llvm::is_contained(AllPopRegs, CS.getReg().id())) + if (llvm::find_if(FixedCSRFIMap, [&](auto P) { + return P.first == CS.getReg(); + }) != std::end(FixedCSRFIMap)) MaxPushPopReg = std::max(MaxPushPopReg.id(), CS.getReg().id()); } // if rlist is {rs, s0-s10}, then s11 will also be included @@ -1385,17 +1393,6 @@ RISCVFrameLowering::getFirstSPAdjustAmount(const MachineFunction &MF) const { return 0; } -// Offsets which need to be scale by XLen representing locations of CSRs which -// are given a fixed location by save/restore libcalls or Zcmp Push/Pop. -static const std::pair FixedCSRFIMap[] = { - {/*ra*/ RISCV::X1, -1}, {/*s0*/ RISCV::X8, -2}, - {/*s1*/ RISCV::X9, -3}, {/*s2*/ RISCV::X18, -4}, - {/*s3*/ RISCV::X19, -5}, {/*s4*/ RISCV::X20, -6}, - {/*s5*/ RISCV::X21, -7}, {/*s6*/ RISCV::X22, -8}, - {/*s7*/ RISCV::X23, -9}, {/*s8*/ RISCV::X24, -10}, - {/*s9*/ RISCV::X25, -11}, {/*s10*/ RISCV::X26, -12}, - {/*s11*/ RISCV::X27, -13}}; - bool RISCVFrameLowering::assignCalleeSavedSpillSlots( MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector &CSI, unsigned &MinCSFrameIndex, @@ -1498,7 +1495,7 @@ bool RISCVFrameLowering::spillCalleeSavedRegisters( PushBuilder.addImm(0); for (unsigned i = 0; i < PushedRegNum; i++) - PushBuilder.addUse(AllPopRegs[i], RegState::Implicit); + PushBuilder.addUse(FixedCSRFIMap[i].first, RegState::Implicit); } } else if (const char *SpillLibCall = getSpillLibCallName(*MF, CSI)) { // Add spill libcall via non-callee-saved register t0. @@ -1611,7 +1608,7 @@ bool RISCVFrameLowering::restoreCalleeSavedRegisters( PopBuilder.addImm(0); for (unsigned i = 0; i < RVFI->getRVPushRegs(); i++) - PopBuilder.addDef(AllPopRegs[i], RegState::ImplicitDefine); + PopBuilder.addDef(FixedCSRFIMap[i].first, RegState::ImplicitDefine); } } else { const char *RestoreLibCall = getRestoreLibCallName(*MF, CSI); -- GitLab From 96c23af8b39a222ce1facd2ec621fbe661e072b7 Mon Sep 17 00:00:00 2001 From: Schrodinger ZHU Yifan Date: Tue, 14 May 2024 00:46:17 -0400 Subject: [PATCH 172/578] [libc] fix 32bit arm build (casting time_t) (#92065) --- libc/src/__support/time/units.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libc/src/__support/time/units.h b/libc/src/__support/time/units.h index f6bd19f9b139..ee74af70efdf 100644 --- a/libc/src/__support/time/units.h +++ b/libc/src/__support/time/units.h @@ -15,22 +15,22 @@ namespace LIBC_NAMESPACE { namespace time_units { LIBC_INLINE constexpr time_t operator""_s_ns(unsigned long long s) { - return s * 1'000'000'000; + return static_cast(s * 1'000'000'000); } LIBC_INLINE constexpr time_t operator""_s_us(unsigned long long s) { - return s * 1'000'000; + return static_cast(s * 1'000'000); } LIBC_INLINE constexpr time_t operator""_s_ms(unsigned long long s) { - return s * 1'000; + return static_cast(s * 1'000); } LIBC_INLINE constexpr time_t operator""_ms_ns(unsigned long long ms) { - return ms * 1'000'000; + return static_cast(ms * 1'000'000); } LIBC_INLINE constexpr time_t operator""_ms_us(unsigned long long ms) { - return ms * 1'000; + return static_cast(ms * 1'000); } LIBC_INLINE constexpr time_t operator""_us_ns(unsigned long long us) { - return us * 1'000; + return static_cast(us * 1'000); } } // namespace time_units } // namespace LIBC_NAMESPACE -- GitLab From 364f988d3feb46ead8fdb657c9eab78d93425a28 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Mon, 13 May 2024 21:52:50 -0700 Subject: [PATCH 173/578] Reland "[clang-format] Fix FormatToken::isSimpleTypeSpecifier() (#91712)" Remove FormatToken::isSimpleTypeSpecifier() and call Token::isSimpleTypeSpecifier(LangOpts) instead. --- clang/lib/Format/Format.cpp | 3 +- clang/lib/Format/FormatToken.cpp | 46 ++-------- clang/lib/Format/FormatToken.h | 8 +- clang/lib/Format/FormatTokenLexer.cpp | 1 - clang/lib/Format/QualifierAlignmentFixer.cpp | 22 +++-- clang/lib/Format/QualifierAlignmentFixer.h | 4 +- clang/lib/Format/TokenAnalyzer.cpp | 4 +- clang/lib/Format/TokenAnalyzer.h | 1 + clang/lib/Format/TokenAnnotator.cpp | 43 ++++++---- clang/lib/Format/TokenAnnotator.h | 6 +- clang/lib/Format/UnwrappedLineParser.cpp | 19 +++-- clang/lib/Format/UnwrappedLineParser.h | 1 + clang/unittests/Format/QualifierFixerTest.cpp | 85 +++++++++++-------- 13 files changed, 116 insertions(+), 127 deletions(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 8f027ffa20cc..52005a6c881f 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -3858,8 +3858,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) { LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11; LangOpts.LineComment = 1; - bool AlternativeOperators = Style.isCpp(); - LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; + LangOpts.CXXOperatorNames = Style.isCpp(); LangOpts.Bool = 1; LangOpts.ObjC = 1; LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp index 4fb70ffac706..85bec71ffbbc 100644 --- a/clang/lib/Format/FormatToken.cpp +++ b/clang/lib/Format/FormatToken.cpp @@ -34,43 +34,6 @@ const char *getTokenTypeName(TokenType Type) { return nullptr; } -// FIXME: This is copy&pasted from Sema. Put it in a common place and remove -// duplication. -bool FormatToken::isSimpleTypeSpecifier() const { - switch (Tok.getKind()) { - case tok::kw_short: - case tok::kw_long: - case tok::kw___int64: - case tok::kw___int128: - case tok::kw_signed: - case tok::kw_unsigned: - case tok::kw_void: - case tok::kw_char: - case tok::kw_int: - case tok::kw_half: - case tok::kw_float: - case tok::kw_double: - case tok::kw___bf16: - case tok::kw__Float16: - case tok::kw___float128: - case tok::kw___ibm128: - case tok::kw_wchar_t: - case tok::kw_bool: -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" - case tok::annot_typename: - case tok::kw_char8_t: - case tok::kw_char16_t: - case tok::kw_char32_t: - case tok::kw_typeof: - case tok::kw_decltype: - case tok::kw__Atomic: - return true; - default: - return false; - } -} - // Sorted common C++ non-keyword types. static SmallVector CppNonKeywordTypes = { "clock_t", "int16_t", "int32_t", "int64_t", "int8_t", @@ -78,15 +41,16 @@ static SmallVector CppNonKeywordTypes = { "uint32_t", "uint64_t", "uint8_t", "uintptr_t", }; -bool FormatToken::isTypeName(bool IsCpp) const { - return is(TT_TypeName) || isSimpleTypeSpecifier() || +bool FormatToken::isTypeName(const LangOptions &LangOpts) const { + const bool IsCpp = LangOpts.CXXOperatorNames; + return is(TT_TypeName) || Tok.isSimpleTypeSpecifier(LangOpts) || (IsCpp && is(tok::identifier) && std::binary_search(CppNonKeywordTypes.begin(), CppNonKeywordTypes.end(), TokenText)); } -bool FormatToken::isTypeOrIdentifier(bool IsCpp) const { - return isTypeName(IsCpp) || isOneOf(tok::kw_auto, tok::identifier); +bool FormatToken::isTypeOrIdentifier(const LangOptions &LangOpts) const { + return isTypeName(LangOpts) || isOneOf(tok::kw_auto, tok::identifier); } bool FormatToken::isBlockIndentedInitRBrace(const FormatStyle &Style) const { diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 95f16fde5005..8792f4c75074 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -684,12 +684,8 @@ public: isAttribute(); } - /// Determine whether the token is a simple-type-specifier. - [[nodiscard]] bool isSimpleTypeSpecifier() const; - - [[nodiscard]] bool isTypeName(bool IsCpp) const; - - [[nodiscard]] bool isTypeOrIdentifier(bool IsCpp) const; + [[nodiscard]] bool isTypeName(const LangOptions &LangOpts) const; + [[nodiscard]] bool isTypeOrIdentifier(const LangOptions &LangOpts) const; bool isObjCAccessSpecifier() const { return is(tok::at) && Next && diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index f430d3764bab..e21b5a882b77 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -1442,7 +1442,6 @@ void FormatTokenLexer::readRawToken(FormatToken &Tok) { void FormatTokenLexer::resetLexer(unsigned Offset) { StringRef Buffer = SourceMgr.getBufferData(ID); - LangOpts = getFormattingLangOpts(Style); Lex.reset(new Lexer(SourceMgr.getLocForStartOfFile(ID), LangOpts, Buffer.begin(), Buffer.begin() + Offset, Buffer.end())); Lex->SetKeepWhitespaceMode(true); diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp index 36d0639041c6..593f8efff25a 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.cpp +++ b/clang/lib/Format/QualifierAlignmentFixer.cpp @@ -268,13 +268,11 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( if (isPossibleMacro(TypeToken)) return Tok; - const bool IsCpp = Style.isCpp(); - // The case `const long long int volatile` -> `long long int const volatile` // The case `long const long int volatile` -> `long long int const volatile` // The case `long long volatile int const` -> `long long int const volatile` // The case `const long long volatile int` -> `long long int const volatile` - if (TypeToken->isTypeName(IsCpp)) { + if (TypeToken->isTypeName(LangOpts)) { // The case `const decltype(foo)` -> `const decltype(foo)` // The case `const typeof(foo)` -> `const typeof(foo)` // The case `const _Atomic(foo)` -> `const _Atomic(foo)` @@ -283,7 +281,7 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( const FormatToken *LastSimpleTypeSpecifier = TypeToken; while (isQualifierOrType(LastSimpleTypeSpecifier->getNextNonComment(), - IsCpp)) { + LangOpts)) { LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment(); } @@ -295,7 +293,7 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( // The case `unsigned short const` -> `unsigned short const` // The case: // `unsigned short volatile const` -> `unsigned short const volatile` - if (PreviousCheck && PreviousCheck->isTypeName(IsCpp)) { + if (PreviousCheck && PreviousCheck->isTypeName(LangOpts)) { if (LastQual != Tok) rotateTokens(SourceMgr, Fixes, Tok, LastQual, /*Left=*/false); return Tok; @@ -412,11 +410,11 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft( // The case `volatile long long const int` -> `const volatile long long int` // The case `const long long volatile int` -> `const volatile long long int` // The case `long volatile long int const` -> `const volatile long long int` - if (const bool IsCpp = Style.isCpp(); TypeToken->isTypeName(IsCpp)) { + if (TypeToken->isTypeName(LangOpts)) { const FormatToken *LastSimpleTypeSpecifier = TypeToken; while (isConfiguredQualifierOrType( LastSimpleTypeSpecifier->getPreviousNonComment(), - ConfiguredQualifierTokens, IsCpp)) { + ConfiguredQualifierTokens, LangOpts)) { LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getPreviousNonComment(); } @@ -614,15 +612,15 @@ void prepareLeftRightOrderingForQualifierAlignmentFixer( } } -bool isQualifierOrType(const FormatToken *Tok, bool IsCpp) { - return Tok && - (Tok->isTypeName(IsCpp) || Tok->is(tok::kw_auto) || isQualifier(Tok)); +bool isQualifierOrType(const FormatToken *Tok, const LangOptions &LangOpts) { + return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) || + isQualifier(Tok)); } bool isConfiguredQualifierOrType(const FormatToken *Tok, const std::vector &Qualifiers, - bool IsCpp) { - return Tok && (Tok->isTypeName(IsCpp) || Tok->is(tok::kw_auto) || + const LangOptions &LangOpts) { + return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) || isConfiguredQualifier(Tok, Qualifiers)); } diff --git a/clang/lib/Format/QualifierAlignmentFixer.h b/clang/lib/Format/QualifierAlignmentFixer.h index e31d525da164..a0a0d597ebf3 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.h +++ b/clang/lib/Format/QualifierAlignmentFixer.h @@ -33,10 +33,10 @@ void prepareLeftRightOrderingForQualifierAlignmentFixer( std::vector &Qualifiers); // Is the Token a simple or qualifier type -bool isQualifierOrType(const FormatToken *Tok, bool IsCpp = true); +bool isQualifierOrType(const FormatToken *Tok, const LangOptions &LangOpts); bool isConfiguredQualifierOrType(const FormatToken *Tok, const std::vector &Qualifiers, - bool IsCpp = true); + const LangOptions &LangOpts); // Is the Token likely a Macro bool isPossibleMacro(const FormatToken *Tok); diff --git a/clang/lib/Format/TokenAnalyzer.cpp b/clang/lib/Format/TokenAnalyzer.cpp index bd648c430f9b..804a2b0f5e8c 100644 --- a/clang/lib/Format/TokenAnalyzer.cpp +++ b/clang/lib/Format/TokenAnalyzer.cpp @@ -84,7 +84,7 @@ Environment::Environment(StringRef Code, StringRef FileName, NextStartColumn(NextStartColumn), LastStartColumn(LastStartColumn) {} TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style) - : Style(Style), Env(Env), + : Style(Style), LangOpts(getFormattingLangOpts(Style)), Env(Env), AffectedRangeMgr(Env.getSourceManager(), Env.getCharRanges()), UnwrappedLines(1), Encoding(encoding::detectEncoding( @@ -101,7 +101,7 @@ std::pair TokenAnalyzer::process(bool SkipAnnotation) { tooling::Replacements Result; llvm::SpecificBumpPtrAllocator Allocator; - IdentifierTable IdentTable(getFormattingLangOpts(Style)); + IdentifierTable IdentTable(LangOpts); FormatTokenLexer Lex(Env.getSourceManager(), Env.getFileID(), Env.getFirstStartColumn(), Style, Encoding, Allocator, IdentTable); diff --git a/clang/lib/Format/TokenAnalyzer.h b/clang/lib/Format/TokenAnalyzer.h index b7494c395c8a..ef559099d325 100644 --- a/clang/lib/Format/TokenAnalyzer.h +++ b/clang/lib/Format/TokenAnalyzer.h @@ -92,6 +92,7 @@ protected: void finishRun() override; FormatStyle Style; + LangOptions LangOpts; // Stores Style, FileID and SourceManager etc. const Environment &Env; // AffectedRangeMgr stores ranges to be fixed. diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index e935d3e2709c..478cae23d3c8 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -126,7 +126,9 @@ public: const AdditionalKeywords &Keywords, SmallVector &Scopes) : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false), - IsCpp(Style.isCpp()), Keywords(Keywords), Scopes(Scopes) { + IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)), + Keywords(Keywords), Scopes(Scopes) { + assert(IsCpp == LangOpts.CXXOperatorNames); Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false)); resetTokenMetadata(); } @@ -562,7 +564,7 @@ private: (CurrentToken->is(tok::l_paren) && CurrentToken->Next && CurrentToken->Next->isOneOf(tok::star, tok::amp, tok::caret)); if ((CurrentToken->Previous->isOneOf(tok::kw_const, tok::kw_auto) || - CurrentToken->Previous->isTypeName(IsCpp)) && + CurrentToken->Previous->isTypeName(LangOpts)) && !(CurrentToken->is(tok::l_brace) || (CurrentToken->is(tok::l_paren) && !ProbablyFunctionTypeLParen))) { Contexts.back().IsExpression = false; @@ -2624,7 +2626,7 @@ private: return true; // MyClass a; - if (PreviousNotConst->isTypeName(IsCpp)) + if (PreviousNotConst->isTypeName(LangOpts)) return true; // type[] a in Java @@ -2728,7 +2730,7 @@ private: } if (Tok.Next->is(tok::question) || - (Tok.Next->is(tok::ampamp) && !Tok.Previous->isTypeName(IsCpp))) { + (Tok.Next->is(tok::ampamp) && !Tok.Previous->isTypeName(LangOpts))) { return false; } @@ -2757,9 +2759,10 @@ private: } // Heuristically try to determine whether the parentheses contain a type. - auto IsQualifiedPointerOrReference = [](FormatToken *T, bool IsCpp) { + auto IsQualifiedPointerOrReference = [](FormatToken *T, + const LangOptions &LangOpts) { // This is used to handle cases such as x = (foo *const)&y; - assert(!T->isTypeName(IsCpp) && "Should have already been checked"); + assert(!T->isTypeName(LangOpts) && "Should have already been checked"); // Strip trailing qualifiers such as const or volatile when checking // whether the parens could be a cast to a pointer/reference type. while (T) { @@ -2791,8 +2794,8 @@ private: bool ParensAreType = !Tok.Previous || Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || - Tok.Previous->isTypeName(IsCpp) || - IsQualifiedPointerOrReference(Tok.Previous, IsCpp); + Tok.Previous->isTypeName(LangOpts) || + IsQualifiedPointerOrReference(Tok.Previous, LangOpts); bool ParensCouldEndDecl = Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater); if (ParensAreType && !ParensCouldEndDecl) @@ -3065,6 +3068,7 @@ private: FormatToken *CurrentToken; bool AutoFound; bool IsCpp; + LangOptions LangOpts; const AdditionalKeywords &Keywords; SmallVector &Scopes; @@ -3639,7 +3643,8 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) { // This function heuristically determines whether 'Current' starts the name of a // function declaration. -static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, +static bool isFunctionDeclarationName(const LangOptions &LangOpts, + const FormatToken &Current, const AnnotatedLine &Line, FormatToken *&ClosingParen) { assert(Current.Previous); @@ -3658,7 +3663,7 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, } auto skipOperatorName = - [IsCpp](const FormatToken *Next) -> const FormatToken * { + [&LangOpts](const FormatToken *Next) -> const FormatToken * { for (; Next; Next = Next->Next) { if (Next->is(TT_OverloadedOperatorLParen)) return Next; @@ -3677,7 +3682,7 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, Next = Next->Next; continue; } - if ((Next->isTypeName(IsCpp) || Next->is(tok::identifier)) && + if ((Next->isTypeName(LangOpts) || Next->is(tok::identifier)) && Next->Next && Next->Next->isPointerOrReference()) { // For operator void*(), operator char*(), operator Foo*(). Next = Next->Next; @@ -3693,8 +3698,10 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, return nullptr; }; + const auto *Next = Current.Next; + const bool IsCpp = LangOpts.CXXOperatorNames; + // Find parentheses of parameter list. - const FormatToken *Next = Current.Next; if (Current.is(tok::kw_operator)) { if (Previous.Tok.getIdentifierInfo() && !Previous.isOneOf(tok::kw_return, tok::kw_co_return)) { @@ -3774,7 +3781,7 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, Tok = Tok->MatchingParen; continue; } - if (Tok->is(tok::kw_const) || Tok->isTypeName(IsCpp) || + if (Tok->is(tok::kw_const) || Tok->isTypeName(LangOpts) || Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) { return true; } @@ -3837,7 +3844,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { AfterLastAttribute = Tok; if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName); IsCtorOrDtor || - isFunctionDeclarationName(IsCpp, *Tok, Line, ClosingParen)) { + isFunctionDeclarationName(LangOpts, *Tok, Line, ClosingParen)) { if (!IsCtorOrDtor) Tok->setFinalizedType(TT_FunctionDeclarationName); LineIsFunctionDeclaration = true; @@ -4447,7 +4454,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Left.Tok.isLiteral()) return true; // for (auto a = 0, b = 0; const auto & c : {1, 2, 3}) - if (Left.isTypeOrIdentifier(IsCpp) && Right.Next && Right.Next->Next && + if (Left.isTypeOrIdentifier(LangOpts) && Right.Next && Right.Next->Next && Right.Next->Next->is(TT_RangeBasedForLoopColon)) { return getTokenPointerOrReferenceAlignment(Right) != FormatStyle::PAS_Left; @@ -4490,7 +4497,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Right.is(tok::l_brace) && Right.is(BK_Block)) return true; // for (auto a = 0, b = 0; const auto& c : {1, 2, 3}) - if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(IsCpp) && Right.Next && + if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(LangOpts) && Right.Next && Right.Next->is(TT_RangeBasedForLoopColon)) { return getTokenPointerOrReferenceAlignment(Left) != FormatStyle::PAS_Right; @@ -4534,7 +4541,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Right.isPointerOrReference()) { const FormatToken *Previous = &Left; while (Previous && Previous->isNot(tok::kw_operator)) { - if (Previous->is(tok::identifier) || Previous->isTypeName(IsCpp)) { + if (Previous->is(tok::identifier) || Previous->isTypeName(LangOpts)) { Previous = Previous->getPreviousNonComment(); continue; } @@ -4723,7 +4730,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (!Style.isVerilog() && (Left.isOneOf(tok::identifier, tok::greater, tok::r_square, tok::r_paren) || - Left.isTypeName(IsCpp)) && + Left.isTypeName(LangOpts)) && Right.is(tok::l_brace) && Right.getNextNonComment() && Right.isNot(BK_Block)) { return false; diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 25a24dccb1b8..d19d3d061e40 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -211,7 +211,10 @@ private: class TokenAnnotator { public: TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords) - : Style(Style), IsCpp(Style.isCpp()), Keywords(Keywords) {} + : Style(Style), IsCpp(Style.isCpp()), + LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords) { + assert(IsCpp == LangOpts.CXXOperatorNames); + } /// Adapts the indent levels of comment lines to the indent of the /// subsequent line. @@ -260,6 +263,7 @@ private: const FormatStyle &Style; bool IsCpp; + LangOptions LangOpts; const AdditionalKeywords &Keywords; diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 310b75485e08..4f1c2c5114e9 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -160,13 +160,16 @@ UnwrappedLineParser::UnwrappedLineParser( IdentifierTable &IdentTable) : Line(new UnwrappedLine), MustBreakBeforeNextToken(false), CurrentLines(&Lines), Style(Style), IsCpp(Style.isCpp()), - Keywords(Keywords), CommentPragmasRegex(Style.CommentPragmas), - Tokens(nullptr), Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1), + LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords), + CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr), + Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1), IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None ? IG_Rejected : IG_Inited), IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn), - Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {} + Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) { + assert(IsCpp == LangOpts.CXXOperatorNames); +} void UnwrappedLineParser::reset() { PPBranchLevel = -1; @@ -1870,7 +1873,7 @@ void UnwrappedLineParser::parseStructuralElement( case tok::caret: nextToken(); // Block return type. - if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(IsCpp)) { + if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) { nextToken(); // Return types: pointers are ok too. while (FormatTok->is(tok::star)) @@ -2231,7 +2234,7 @@ bool UnwrappedLineParser::tryToParseLambda() { bool InTemplateParameterList = false; while (FormatTok->isNot(tok::l_brace)) { - if (FormatTok->isTypeName(IsCpp)) { + if (FormatTok->isTypeName(LangOpts)) { nextToken(); continue; } @@ -3448,7 +3451,7 @@ bool UnwrappedLineParser::parseRequires() { break; } default: - if (PreviousNonComment->isTypeOrIdentifier(IsCpp)) { + if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) { // This is a requires clause. parseRequiresClause(RequiresToken); return true; @@ -3511,7 +3514,7 @@ bool UnwrappedLineParser::parseRequires() { --OpenAngles; break; default: - if (NextToken->isTypeName(IsCpp)) { + if (NextToken->isTypeName(LangOpts)) { FormatTok = Tokens->setPosition(StoredPosition); parseRequiresExpression(RequiresToken); return false; @@ -4027,7 +4030,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { if (FormatTok->is(tok::l_square)) { FormatToken *Previous = FormatTok->Previous; if (!Previous || (Previous->isNot(tok::r_paren) && - !Previous->isTypeOrIdentifier(IsCpp))) { + !Previous->isTypeOrIdentifier(LangOpts))) { // Don't try parsing a lambda if we had a closing parenthesis before, // it was probably a pointer to an array: int (*)[]. if (!tryToParseLambda()) diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 2a0fe19d0957..d7963a4211bb 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -316,6 +316,7 @@ private: const FormatStyle &Style; bool IsCpp; + LangOptions LangOpts; const AdditionalKeywords &Keywords; llvm::Regex CommentPragmasRegex; diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index 4ddeef50f5f7..1f21fc0e0b42 100644 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -1056,49 +1056,66 @@ TEST_F(QualifierFixerTest, IsQualifierType) { ConfiguredTokens.push_back(tok::kw_friend); TestLexer lexer{Allocator, Buffers}; + const auto LangOpts = getFormattingLangOpts(); auto Tokens = lexer.lex( "const static inline auto restrict int double long constexpr friend"); ASSERT_EQ(Tokens.size(), 11u) << Tokens; - EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[0], ConfiguredTokens)); - EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[1], ConfiguredTokens)); - EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[2], ConfiguredTokens)); - EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[3], ConfiguredTokens)); - EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[4], ConfiguredTokens)); - EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[5], ConfiguredTokens)); - EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[6], ConfiguredTokens)); - EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[7], ConfiguredTokens)); - EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[8], ConfiguredTokens)); - EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[9], ConfiguredTokens)); - - EXPECT_TRUE(isQualifierOrType(Tokens[0])); - EXPECT_TRUE(isQualifierOrType(Tokens[1])); - EXPECT_TRUE(isQualifierOrType(Tokens[2])); - EXPECT_TRUE(isQualifierOrType(Tokens[3])); - EXPECT_TRUE(isQualifierOrType(Tokens[4])); - EXPECT_TRUE(isQualifierOrType(Tokens[5])); - EXPECT_TRUE(isQualifierOrType(Tokens[6])); - EXPECT_TRUE(isQualifierOrType(Tokens[7])); - EXPECT_TRUE(isQualifierOrType(Tokens[8])); - EXPECT_TRUE(isQualifierOrType(Tokens[9])); + EXPECT_TRUE( + isConfiguredQualifierOrType(Tokens[0], ConfiguredTokens, LangOpts)); + EXPECT_TRUE( + isConfiguredQualifierOrType(Tokens[1], ConfiguredTokens, LangOpts)); + EXPECT_TRUE( + isConfiguredQualifierOrType(Tokens[2], ConfiguredTokens, LangOpts)); + EXPECT_TRUE( + isConfiguredQualifierOrType(Tokens[3], ConfiguredTokens, LangOpts)); + EXPECT_TRUE( + isConfiguredQualifierOrType(Tokens[4], ConfiguredTokens, LangOpts)); + EXPECT_TRUE( + isConfiguredQualifierOrType(Tokens[5], ConfiguredTokens, LangOpts)); + EXPECT_TRUE( + isConfiguredQualifierOrType(Tokens[6], ConfiguredTokens, LangOpts)); + EXPECT_TRUE( + isConfiguredQualifierOrType(Tokens[7], ConfiguredTokens, LangOpts)); + EXPECT_TRUE( + isConfiguredQualifierOrType(Tokens[8], ConfiguredTokens, LangOpts)); + EXPECT_TRUE( + isConfiguredQualifierOrType(Tokens[9], ConfiguredTokens, LangOpts)); + + EXPECT_TRUE(isQualifierOrType(Tokens[0], LangOpts)); + EXPECT_TRUE(isQualifierOrType(Tokens[1], LangOpts)); + EXPECT_TRUE(isQualifierOrType(Tokens[2], LangOpts)); + EXPECT_TRUE(isQualifierOrType(Tokens[3], LangOpts)); + EXPECT_TRUE(isQualifierOrType(Tokens[4], LangOpts)); + EXPECT_TRUE(isQualifierOrType(Tokens[5], LangOpts)); + EXPECT_TRUE(isQualifierOrType(Tokens[6], LangOpts)); + EXPECT_TRUE(isQualifierOrType(Tokens[7], LangOpts)); + EXPECT_TRUE(isQualifierOrType(Tokens[8], LangOpts)); + EXPECT_TRUE(isQualifierOrType(Tokens[9], LangOpts)); auto NotTokens = lexer.lex("for while do Foo Bar "); ASSERT_EQ(NotTokens.size(), 6u) << Tokens; - EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[0], ConfiguredTokens)); - EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[1], ConfiguredTokens)); - EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[2], ConfiguredTokens)); - EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[3], ConfiguredTokens)); - EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[4], ConfiguredTokens)); - EXPECT_FALSE(isConfiguredQualifierOrType(NotTokens[5], ConfiguredTokens)); - - EXPECT_FALSE(isQualifierOrType(NotTokens[0])); - EXPECT_FALSE(isQualifierOrType(NotTokens[1])); - EXPECT_FALSE(isQualifierOrType(NotTokens[2])); - EXPECT_FALSE(isQualifierOrType(NotTokens[3])); - EXPECT_FALSE(isQualifierOrType(NotTokens[4])); - EXPECT_FALSE(isQualifierOrType(NotTokens[5])); + EXPECT_FALSE( + isConfiguredQualifierOrType(NotTokens[0], ConfiguredTokens, LangOpts)); + EXPECT_FALSE( + isConfiguredQualifierOrType(NotTokens[1], ConfiguredTokens, LangOpts)); + EXPECT_FALSE( + isConfiguredQualifierOrType(NotTokens[2], ConfiguredTokens, LangOpts)); + EXPECT_FALSE( + isConfiguredQualifierOrType(NotTokens[3], ConfiguredTokens, LangOpts)); + EXPECT_FALSE( + isConfiguredQualifierOrType(NotTokens[4], ConfiguredTokens, LangOpts)); + EXPECT_FALSE( + isConfiguredQualifierOrType(NotTokens[5], ConfiguredTokens, LangOpts)); + + EXPECT_FALSE(isQualifierOrType(NotTokens[0], LangOpts)); + EXPECT_FALSE(isQualifierOrType(NotTokens[1], LangOpts)); + EXPECT_FALSE(isQualifierOrType(NotTokens[2], LangOpts)); + EXPECT_FALSE(isQualifierOrType(NotTokens[3], LangOpts)); + EXPECT_FALSE(isQualifierOrType(NotTokens[4], LangOpts)); + EXPECT_FALSE(isQualifierOrType(NotTokens[5], LangOpts)); } TEST_F(QualifierFixerTest, IsMacro) { -- GitLab From cd45bb2e435b8e648ac528ed5f5fc1dc2bba48fe Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Tue, 14 May 2024 06:58:13 +0200 Subject: [PATCH 174/578] [libc][errno] Remove unnecessary include (#92063) Since https://github.com/llvm/llvm-project/pull/91150, a proxy header for the errno macros is available and gets included in `libc_errno.h` since then. As `libc_errno.cpp` includes `libc_errno.h`, which already includes the proxy header `hdr/errno_macros.h`, there's no need to include it in `libc_errno.cpp` if we are in overlay mode, because the proxy header takes care to either include our header from libc/include/ (fullbuild) or the corresponding underlying system header (overlay). --- libc/src/errno/libc_errno.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp index a59e6c34029d..64f9f522ca29 100644 --- a/libc/src/errno/libc_errno.cpp +++ b/libc/src/errno/libc_errno.cpp @@ -36,9 +36,6 @@ void LIBC_NAMESPACE::Errno::operator=(int a) { __llvmlibc_errno = a; } LIBC_NAMESPACE::Errno::operator int() { return __llvmlibc_errno; } #else -// In overlay mode, we simply use the system errno. -#include "hdr/errno_macros.h" - void LIBC_NAMESPACE::Errno::operator=(int a) { errno = a; } LIBC_NAMESPACE::Errno::operator int() { return errno; } -- GitLab From f3b8d91ca885744925ce775026df40660d9a4d4e Mon Sep 17 00:00:00 2001 From: appujee <124090381+appujee@users.noreply.github.com> Date: Mon, 13 May 2024 22:39:51 -0700 Subject: [PATCH 175/578] LLVM vectorizer working group (#92068) Recurring meeting at 3rd Thursday of every month. --- llvm/docs/GettingInvolved.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/docs/GettingInvolved.rst b/llvm/docs/GettingInvolved.rst index 89df6cbe31c4..3588ef14db15 100644 --- a/llvm/docs/GettingInvolved.rst +++ b/llvm/docs/GettingInvolved.rst @@ -209,6 +209,10 @@ what to add to your calendar invite. - `ics `__ `gcal `__ - `Meeting details/agenda: `__ + * - Vectorizer Improvement Working Group + - Every 3rd Thursday of the month + - `ics `__ + - `Meeting details/agenda: `__ Past online sync-ups ^^^^^^^^^^^^^^^^^^^^ -- GitLab From 12c0024d196189bd38a140512c0bfbda85d8d75e Mon Sep 17 00:00:00 2001 From: Tomas Matheson Date: Tue, 14 May 2024 07:04:29 +0100 Subject: [PATCH 176/578] [AArch64][TargetParser] Move extension aliases into tablegen (#91970) --- .../llvm/TargetParser/AArch64TargetParser.h | 14 ++++++-------- llvm/lib/Target/AArch64/AArch64Features.td | 5 +++++ llvm/lib/TargetParser/AArch64TargetParser.cpp | 16 +++------------- llvm/utils/TableGen/ARMTargetDefEmitter.cpp | 6 +++++- 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.h b/llvm/include/llvm/TargetParser/AArch64TargetParser.h index 20c3f95173c2..b662a74e5fc6 100644 --- a/llvm/include/llvm/TargetParser/AArch64TargetParser.h +++ b/llvm/include/llvm/TargetParser/AArch64TargetParser.h @@ -114,11 +114,12 @@ using ExtensionBitset = Bitset; // SubtargetFeature which may represent either an actual extension or some // internal LLVM property. struct ExtensionInfo { - StringRef Name; // Human readable name, e.g. "profile". - ArchExtKind ID; // Corresponding to the ArchExtKind, this - // extensions representation in the bitfield. - StringRef Feature; // -mattr enable string, e.g. "+spe" - StringRef NegFeature; // -mattr disable string, e.g. "-spe" + StringRef Name; // Human readable name, e.g. "profile". + std::optional Alias; // An alias for this extension, if one exists. + ArchExtKind ID; // Corresponding to the ArchExtKind, this + // extensions representation in the bitfield. + StringRef Feature; // -mattr enable string, e.g. "+spe" + StringRef NegFeature; // -mattr disable string, e.g. "-spe" CPUFeatures CPUFeature; // Function Multi Versioning (FMV) bitfield value // set in __aarch64_cpu_features StringRef DependentFeatures; // FMV enabled features string, @@ -674,8 +675,6 @@ struct Alias { inline constexpr Alias CpuAliases[] = {{"cobalt-100", "neoverse-n2"}, {"grace", "neoverse-v2"}}; -inline constexpr Alias ExtAliases[] = {{"rdma", "rdm"}}; - const ExtensionInfo &getExtensionByID(ArchExtKind(ExtID)); bool getExtensionFeatures( @@ -684,7 +683,6 @@ bool getExtensionFeatures( StringRef getArchExtFeature(StringRef ArchExt); StringRef resolveCPUAlias(StringRef CPU); -StringRef resolveExtAlias(StringRef ArchExt); // Information by Name const ArchInfo *getArchForCpu(StringRef CPU); diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td index 920ca7f4fbfc..b9c26e99ae03 100644 --- a/llvm/lib/Target/AArch64/AArch64Features.td +++ b/llvm/lib/Target/AArch64/AArch64Features.td @@ -39,6 +39,10 @@ class Extension< // not doing so. string MArchName = TargetFeatureName; + // An alias that can be used on the command line, if the extension has one. + // Used for correcting historical names while remaining backwards compatible. + string MArchAlias = ""; + // Function MultiVersioning (FMV) properties // A C++ expression giving the number of the bit in the FMV ABI. @@ -163,6 +167,7 @@ def FeatureOutlineAtomics : SubtargetFeature<"outline-atomics", "OutlineAtomics" def FeatureFMV : SubtargetFeature<"fmv", "HasFMV", "true", "Enable Function Multi Versioning support.">; +let MArchAlias = "rdma" in def FeatureRDM : Extension<"rdm", "RDM", "Enable ARMv8.1 Rounding Double Multiply Add/Subtract instructions (FEAT_RDM)", [FeatureNEON], diff --git a/llvm/lib/TargetParser/AArch64TargetParser.cpp b/llvm/lib/TargetParser/AArch64TargetParser.cpp index 026214e7e2ea..c10b4be4eded 100644 --- a/llvm/lib/TargetParser/AArch64TargetParser.cpp +++ b/llvm/lib/TargetParser/AArch64TargetParser.cpp @@ -74,13 +74,6 @@ StringRef AArch64::resolveCPUAlias(StringRef Name) { return Name; } -StringRef AArch64::resolveExtAlias(StringRef Name) { - for (const auto &A : ExtAliases) - if (A.AltName == Name) - return A.Name; - return Name; -} - StringRef AArch64::getArchExtFeature(StringRef ArchExt) { bool IsNegated = ArchExt.starts_with("no"); StringRef ArchExtBase = IsNegated ? ArchExt.drop_front(2) : ArchExt; @@ -120,13 +113,10 @@ const AArch64::ArchInfo *AArch64::parseArch(StringRef Arch) { return {}; } -std::optional AArch64::parseArchExtension(StringRef ArchExt) { - // Resolve aliases first. - ArchExt = resolveExtAlias(ArchExt); - - // Then find the Extension name. +std::optional +AArch64::parseArchExtension(StringRef ArchExt) { for (const auto &A : Extensions) { - if (ArchExt == A.Name) + if (ArchExt == A.Name || ArchExt == A.Alias) return A; } return {}; diff --git a/llvm/utils/TableGen/ARMTargetDefEmitter.cpp b/llvm/utils/TableGen/ARMTargetDefEmitter.cpp index 4a46f2ea9586..0e90f57af493 100644 --- a/llvm/utils/TableGen/ARMTargetDefEmitter.cpp +++ b/llvm/utils/TableGen/ARMTargetDefEmitter.cpp @@ -89,6 +89,10 @@ static void EmitARMTargetDef(RecordKeeper &RK, raw_ostream &OS) { auto AEK = Rec->getValueAsString("ArchExtKindSpelling").upper(); OS << " "; OS << "{\"" << Rec->getValueAsString("MArchName") << "\""; + if (auto Alias = Rec->getValueAsString("MArchAlias"); Alias.empty()) + OS << ", {}"; + else + OS << ", \"" << Alias << "\""; OS << ", AArch64::" << AEK; if (AEK == "AEK_NONE") { // HACK: don't emit posfeat/negfeat strings for FMVOnlyExtensions. @@ -102,7 +106,7 @@ static void EmitARMTargetDef(RecordKeeper &RK, raw_ostream &OS) { OS << ", " << (uint64_t)Rec->getValueAsInt("FMVPriority"); OS << "},\n"; }; - OS << " {\"none\", AArch64::AEK_NONE, {}, {}, FEAT_INIT, \"\", " + OS << " {\"none\", {}, AArch64::AEK_NONE, {}, {}, FEAT_INIT, \"\", " "ExtensionInfo::MaxFMVPriority},\n"; OS << "};\n" << "#undef EMIT_EXTENSIONS\n" -- GitLab From 922fafaff83319e33e8a890a692df073d3ce55c9 Mon Sep 17 00:00:00 2001 From: Pierre van Houtryve Date: Tue, 14 May 2024 08:26:00 +0200 Subject: [PATCH 177/578] [GlobalISel] Micro-optimize getConstantVRegValWithLookThrough (#91969) I was benchmarking the MatchTable when I found that `getConstantVRegValWithLookThrough` took a non-negligible amount of time, about 7.5% of all of `AArch64PreLegalizerCombinerImpl::tryCombineAll`. I decided to take a closer look to see if I could squeeze some performance out of it, and I landed on a few changes that: - Avoid copying APint unnecessarily, especially returning std::optional can be expensive when a out parameter also works. - Avoid indirect call by using templated function pointers instead of function_ref/std::function Both of those changes seem to speedup this function by about 50%, but my benchmarking (`perf record`) seems inconsistent (so take measurements with a grain of salt), I saw as high as 4.5% and as low as 2% for this function on the exact same input after the changes, but it never got close again to 7% in a few runs so this looks like a stable improvement. --- llvm/lib/CodeGen/GlobalISel/Utils.cpp | 76 ++++++++++++++++----------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp index 4e3781cb4e9d..cd5dc0e01ed0 100644 --- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -313,13 +313,22 @@ llvm::getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI) { namespace { -typedef std::function IsOpcodeFn; -typedef std::function(const MachineInstr *MI)> GetAPCstFn; - -std::optional getConstantVRegValWithLookThrough( - Register VReg, const MachineRegisterInfo &MRI, IsOpcodeFn IsConstantOpcode, - GetAPCstFn getAPCstValue, bool LookThroughInstrs = true, - bool LookThroughAnyExt = false) { +// This function is used in many places, and as such, it has some +// micro-optimizations to try and make it as fast as it can be. +// +// - We use template arguments to avoid an indirect call caused by passing a +// function_ref/std::function +// - GetAPCstValue does not return std::optional as that's expensive. +// Instead it returns true/false and places the result in a pre-constructed +// APInt. +// +// Please change this function carefully and benchmark your changes. +template +std::optional +getConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, + bool LookThroughInstrs = true, + bool LookThroughAnyExt = false) { SmallVector, 4> SeenOpcodes; MachineInstr *MI; @@ -353,26 +362,25 @@ std::optional getConstantVRegValWithLookThrough( if (!MI || !IsConstantOpcode(MI)) return std::nullopt; - std::optional MaybeVal = getAPCstValue(MI); - if (!MaybeVal) + APInt Val; + if (!GetAPCstValue(MI, Val)) return std::nullopt; - APInt &Val = *MaybeVal; - for (auto [Opcode, Size] : reverse(SeenOpcodes)) { - switch (Opcode) { + for (auto &Pair : reverse(SeenOpcodes)) { + switch (Pair.first) { case TargetOpcode::G_TRUNC: - Val = Val.trunc(Size); + Val = Val.trunc(Pair.second); break; case TargetOpcode::G_ANYEXT: case TargetOpcode::G_SEXT: - Val = Val.sext(Size); + Val = Val.sext(Pair.second); break; case TargetOpcode::G_ZEXT: - Val = Val.zext(Size); + Val = Val.zext(Pair.second); break; } } - return ValueAndVReg{Val, VReg}; + return ValueAndVReg{std::move(Val), VReg}; } bool isIConstant(const MachineInstr *MI) { @@ -394,42 +402,46 @@ bool isAnyConstant(const MachineInstr *MI) { return Opc == TargetOpcode::G_CONSTANT || Opc == TargetOpcode::G_FCONSTANT; } -std::optional getCImmAsAPInt(const MachineInstr *MI) { +bool getCImmAsAPInt(const MachineInstr *MI, APInt &Result) { const MachineOperand &CstVal = MI->getOperand(1); - if (CstVal.isCImm()) - return CstVal.getCImm()->getValue(); - return std::nullopt; + if (!CstVal.isCImm()) + return false; + Result = CstVal.getCImm()->getValue(); + return true; } -std::optional getCImmOrFPImmAsAPInt(const MachineInstr *MI) { +bool getCImmOrFPImmAsAPInt(const MachineInstr *MI, APInt &Result) { const MachineOperand &CstVal = MI->getOperand(1); if (CstVal.isCImm()) - return CstVal.getCImm()->getValue(); - if (CstVal.isFPImm()) - return CstVal.getFPImm()->getValueAPF().bitcastToAPInt(); - return std::nullopt; + Result = CstVal.getCImm()->getValue(); + else if (CstVal.isFPImm()) + Result = CstVal.getFPImm()->getValueAPF().bitcastToAPInt(); + else + return false; + return true; } } // end anonymous namespace std::optional llvm::getIConstantVRegValWithLookThrough( Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) { - return getConstantVRegValWithLookThrough(VReg, MRI, isIConstant, - getCImmAsAPInt, LookThroughInstrs); + return getConstantVRegValWithLookThrough( + VReg, MRI, LookThroughInstrs); } std::optional llvm::getAnyConstantVRegValWithLookThrough( Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs, bool LookThroughAnyExt) { - return getConstantVRegValWithLookThrough( - VReg, MRI, isAnyConstant, getCImmOrFPImmAsAPInt, LookThroughInstrs, - LookThroughAnyExt); + return getConstantVRegValWithLookThrough( + VReg, MRI, LookThroughInstrs, LookThroughAnyExt); } std::optional llvm::getFConstantVRegValWithLookThrough( Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) { - auto Reg = getConstantVRegValWithLookThrough( - VReg, MRI, isFConstant, getCImmOrFPImmAsAPInt, LookThroughInstrs); + auto Reg = + getConstantVRegValWithLookThrough( + VReg, MRI, LookThroughInstrs); if (!Reg) return std::nullopt; return FPValueAndVReg{getConstantFPVRegVal(Reg->VReg, MRI)->getValueAPF(), -- GitLab From ea238974e1b5f2243b6753c2d737c1f04dd1f17b Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Tue, 14 May 2024 08:28:27 +0200 Subject: [PATCH 178/578] [mlir] [TOSA] Allow any floating point type (#91745) After #86509 allowed all integer types in TOSA ops, this PR allows TOSA ops on all floating point types. This helps to experiment with `f64` and 8-bit float types when spec conformance is not required. --- mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td | 6 +++--- .../mlir/Dialect/Tosa/IR/TosaTypesBase.td | 21 ++++--------------- .../Tosa/Transforms/TosaValidation.cpp | 9 ++++---- mlir/test/Dialect/Tosa/invalid.mlir | 2 +- mlir/test/Dialect/Tosa/level_check.mlir | 8 +++++++ 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td index 97a36c49d01b..7871b46724a0 100644 --- a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td +++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td @@ -1857,11 +1857,11 @@ def Tosa_CastOp: Tosa_Op<"cast", [Pure, }]; let arguments = (ins - Tosa_Tensor_Plus_F64:$input + Tosa_Tensor:$input ); let results = (outs - Tosa_Tensor_Plus_F64:$output + Tosa_Tensor:$output ); let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)"; @@ -1944,7 +1944,7 @@ def Tosa_ConstOp : Tosa_Op<"const", [ConstantLike, Pure, ); let results = (outs - TensorOf<[AnyTypeOf<[Tosa_AnyNumber_Plus_F64]>]>:$output + TensorOf<[AnyTypeOf<[Tosa_AnyNumber]>]>:$output ); let hasFolder = 1; diff --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td index 3687891fe4b7..14fc9c7a6730 100644 --- a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td +++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td @@ -71,28 +71,16 @@ def Tosa_QuantizedInt : AnyTypeOf<[ Tosa_QuantizedType<"uint8", [8], 0>, Tosa_QuantizedType<"int16", [16, 0], 1>, Tosa_QuantizedType<"int32", [32, 0], 1>]>; -//===----------------------------------------------------------------------===// -// Floating-point types. -//===----------------------------------------------------------------------===// -def Tosa_Float : AnyTypeOf<[ - F32, - F16, - BF16]>; - //===----------------------------------------------------------------------===// // Multi-category types. //===----------------------------------------------------------------------===// -def Tosa_AnyNumber : AnyTypeOf<[Tosa_Int, Tosa_QuantizedInt, Tosa_Float], +def Tosa_AnyNumber : AnyTypeOf<[Tosa_Int, Tosa_QuantizedInt, AnyFloat], "number">; -// Add F64 type support just for tosa::CastOp and tosa::ConstOp -def Tosa_AnyNumber_Plus_F64 : AnyTypeOf<[Tosa_Int, Tosa_QuantizedInt, Tosa_Float, F64], - "number_plus_f64">; - // For weight tensors from tosa::Conv2DOp, tosa::Conv3DOp, // tosa::DepthwiseConv2DOp, tosa::TransposeConv2DOp, tosa::FullyConnectedOp def Tosa_Weight : AnyTypeOf<[Tosa_Int4, Tosa_Int8, - Tosa_QuantizedInt, Tosa_Float]>; + Tosa_QuantizedInt, AnyFloat]>; //===----------------------------------------------------------------------===// // Tensor types @@ -101,18 +89,17 @@ def Tosa_Weight : AnyTypeOf<[Tosa_Int4, Tosa_Int8, def Tosa_Int32Tensor : TensorOf<[Tosa_Int32]>; def Tosa_Int32Or64Tensor : TensorOf<[Tosa_Int32Or64]>; -def Tosa_FloatTensor : TensorOf<[Tosa_Float]>; +def Tosa_FloatTensor : TensorOf<[AnyFloat]>; // Either ranked or unranked tensor of TOSA supported element types. def Tosa_Tensor : TensorOf<[Tosa_AnyNumber]>; -def Tosa_Tensor_Plus_F64 : TensorOf<[Tosa_AnyNumber_Plus_F64]>; // Must be ranked but no further constraints def Tosa_RankedTensor : RankedTensorOf<[Tosa_AnyNumber]>; // Any tensor element type allowed in Tosa ops. def Tosa_ElementType : Type, "tosa.dtype">; + AnyFloat.predicate]>, "tosa.dtype">; class Tosa_TensorOfOrNone allowedTypes, string description = ""> : AnyTypeOf<[TensorOf, NoneType], description>; diff --git a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp index 539501082fd3..b78c372af77e 100644 --- a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp +++ b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp @@ -506,11 +506,10 @@ LogicalResult TosaValidation::applyVariableCheck(Operation *op) { } bool TosaValidation::isValidElementType(Type type) { - if ((profile == TosaProfileEnum::BaseInference) && isa(type)) { - return false; - } - if (type.isF64()) { - return false; + if (isa(type)) { + if (profile == TosaProfileEnum::BaseInference) + return false; + return type.isF32() || type.isF16() || type.isBF16(); } if (auto intTy = dyn_cast(type)) { if (intTy.isUnsigned()) { diff --git a/mlir/test/Dialect/Tosa/invalid.mlir b/mlir/test/Dialect/Tosa/invalid.mlir index 730ac41dd7a8..cb38d4d81ca2 100644 --- a/mlir/test/Dialect/Tosa/invalid.mlir +++ b/mlir/test/Dialect/Tosa/invalid.mlir @@ -20,7 +20,7 @@ func.func @test_conv2d(%arg0: tensor<*xi8>, %arg1: tensor<16x3x3x4xi8>, %arg2: t // ----- func.func @test_conv2d(%arg0: tensor<1x29x29x4xi8>, %arg1: tensor<*xi8>, %arg2: tensor<16xi8>) -> tensor<1x27x27x16xi8> { - // expected-error@+1 {{'tosa.conv2d' op operand #1 must be 4D tensor of 4-bit signless integer or 8-bit signless integer or Quint8 type or Qint4 type or Qint8 type or Qint16 type or Qint32 type or 32-bit float or 16-bit float or bfloat16 type values, but got 'tensor<*xi8>'}} + // expected-error@+1 {{'tosa.conv2d' op operand #1 must be 4D tensor of 4-bit signless integer or 8-bit signless integer or Quint8 type or Qint4 type or Qint8 type or Qint16 type or Qint32 type or floating-point values, but got 'tensor<*xi8>'}} %0 = tosa.conv2d %arg0, %arg1, %arg2 {dilation = array, pad = array, stride = array} : (tensor<1x29x29x4xi8>, tensor<*xi8>, tensor<16xi8>) -> tensor<1x27x27x16xi8> return %0 : tensor<1x27x27x16xi8> diff --git a/mlir/test/Dialect/Tosa/level_check.mlir b/mlir/test/Dialect/Tosa/level_check.mlir index d8dd878051f1..9b652f2d0bd1 100644 --- a/mlir/test/Dialect/Tosa/level_check.mlir +++ b/mlir/test/Dialect/Tosa/level_check.mlir @@ -131,6 +131,14 @@ func.func @test_const_ui32(%arg0 : tensor<1xui32>) { // ----- +func.func @test_const_f64(%arg0 : tensor<1xf64>) { + // expected-error@+1 {{'tosa.const' op is not profile-aligned: element type 'f64' is not legal}} + %0 = "tosa.const"() {value = dense<0.0> : tensor<1xf64>} : () -> tensor<1xf64> + return +} + +// ----- + func.func @test_avgpool2d_kernel_y(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x32x32x8xf32> { // expected-error@+1 {{'tosa.avg_pool2d' op failed level check: kernel <= MAX_KERNEL}} %0 = "tosa.avg_pool2d"(%arg0) {kernel = array, pad = array, stride = array, acc_type = f32} : -- GitLab From ecce5ccdd5725bd0669c24742bfd46dbf043fec2 Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Tue, 14 May 2024 08:28:41 +0200 Subject: [PATCH 179/578] TosaToLinalg: Allow to skip the TOSA validation pass (#91742) Allow to skip running the TOSA validation pass when spec conformance is not required. --- .../mlir/Conversion/TosaToLinalg/TosaToLinalg.h | 5 +++-- .../Conversion/TosaToLinalg/TosaToLinalgPass.cpp | 14 ++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/mlir/include/mlir/Conversion/TosaToLinalg/TosaToLinalg.h b/mlir/include/mlir/Conversion/TosaToLinalg/TosaToLinalg.h index 5fd77c8a0211..67965e34d8a3 100644 --- a/mlir/include/mlir/Conversion/TosaToLinalg/TosaToLinalg.h +++ b/mlir/include/mlir/Conversion/TosaToLinalg/TosaToLinalg.h @@ -38,8 +38,9 @@ void addTosaToLinalgPasses( const TosaToLinalgNamedOptions &tosaToLinalgNamedOptions = TosaToLinalgNamedOptions(), // Note: Default to 'none' level unless otherwise specified. - tosa::TosaValidationOptions const &validationOptions = { - tosa::TosaProfileEnum::Undefined, false, tosa::TosaLevelEnum::None}); + std::optional validationOptions = + tosa::TosaValidationOptions{tosa::TosaProfileEnum::Undefined, false, + tosa::TosaLevelEnum::None}); /// Populates TOSA to linalg pipelines /// Currently, this includes only the "tosa-to-linalg-pipeline". diff --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp index ad7f6cf84e5e..8904e3253922 100644 --- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp +++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp @@ -78,7 +78,7 @@ std::unique_ptr mlir::tosa::createTosaToLinalg() { void mlir::tosa::addTosaToLinalgPasses( OpPassManager &pm, const TosaToLinalgOptions &options, const TosaToLinalgNamedOptions &tosaToLinalgNamedOptions, - tosa::TosaValidationOptions const &validationOptions) { + std::optional validationOptions) { // Optional decompositions are designed to benefit linalg. if (!options.disableTosaDecompositions) pm.addNestedPass(tosa::createTosaOptionalDecompositions()); @@ -93,7 +93,8 @@ void mlir::tosa::addTosaToLinalgPasses( pm.addNestedPass(tosa::createTosaLayerwiseConstantFoldPass( {options.aggressiveReduceConstant})); pm.addNestedPass(tosa::createTosaMakeBroadcastablePass()); - pm.addPass(tosa::createTosaValidation(validationOptions)); + if (validationOptions) + pm.addPass(tosa::createTosaValidation(*validationOptions)); pm.addNestedPass(tosa::createTosaToLinalg()); } @@ -110,11 +111,12 @@ void mlir::tosa::registerTosaToLinalgPipelines() { [](OpPassManager &pm) { TosaToLinalgOptions tosaToLinalgOptions; TosaToLinalgNamedOptions tosaToLinalgNamedOptions; + TosaValidationOptions validationOptions; + validationOptions.profile = tosa::TosaProfileEnum::BaseInference; + validationOptions.StrictOperationSpecAlignment = true; + validationOptions.level = tosa::TosaLevelEnum::EightK; tosa::addTosaToLinalgPasses(pm, tosaToLinalgOptions, tosaToLinalgNamedOptions, - /* validationOptions = */ - {tosa::TosaProfileEnum::BaseInference, - /* StrictOperationSpecAlignment = */ true, - tosa::TosaLevelEnum::EightK}); + validationOptions); }); } -- GitLab From 4014e2e045f5160ce9cbb9562d151f540d61c0bb Mon Sep 17 00:00:00 2001 From: Alex Bradbury Date: Tue, 14 May 2024 07:19:40 +0100 Subject: [PATCH 180/578] [TableGen][RISCV] Strip experimental- prefix in profile names in SupportedExperimentalProfiles This matches what we do for extensions, and saves us having to do it in RISCVISAInfo. This is a minor tweak to what I added in #91993. --- llvm/test/TableGen/riscv-target-def.td | 2 +- llvm/utils/TableGen/RISCVTargetDefEmitter.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/test/TableGen/riscv-target-def.td b/llvm/test/TableGen/riscv-target-def.td index e328a6e3b583..fb58448d7ce8 100644 --- a/llvm/test/TableGen/riscv-target-def.td +++ b/llvm/test/TableGen/riscv-target-def.td @@ -147,7 +147,7 @@ def ROCKET : RISCVTuneProcessorModel<"rocket", // CHECK-NEXT: }; // CHECK: static constexpr RISCVProfile SupportedExperimentalProfiles[] = { -// CHECK-NEXT: {"experimental-rvi99u64","rv64i2p1"}, +// CHECK-NEXT: {"rvi99u64","rv64i2p1"}, // CHECK-NEXT: }; // CHECK: #endif // GET_SUPPORTED_PROFILES diff --git a/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp b/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp index d174b1961344..b76ba05954aa 100644 --- a/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp +++ b/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp @@ -134,7 +134,9 @@ static void printProfileTable(raw_ostream &OS, if (Rec->getValueAsBit("Experimental") != Experimental) continue; - OS.indent(4) << "{\"" << Rec->getValueAsString("Name") << "\",\""; + StringRef Name = Rec->getValueAsString("Name"); + Name.consume_front("experimental-"); + OS.indent(4) << "{\"" << Name << "\",\""; printMArch(OS, Rec->getValueAsListOfDefs("Implies")); OS << "\"},\n"; } -- GitLab From d488a54b408046eb4286727053cd44166dcd4daa Mon Sep 17 00:00:00 2001 From: Yeting Kuo <46629943+yetingk@users.noreply.github.com> Date: Tue, 14 May 2024 14:44:25 +0800 Subject: [PATCH 181/578] [RISCV] Use software guarded branch for indirect jump table branch. (#66762) When Zicfilp enabled, indirect jump table branch should be a software guarded branch. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 14 +++ llvm/lib/Target/RISCV/RISCVISelLowering.h | 7 ++ llvm/lib/Target/RISCV/RISCVInstrInfo.td | 11 +- llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 2 + .../test/CodeGen/RISCV/jumptable-swguarded.ll | 105 ++++++++++++++++++ 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/RISCV/jumptable-swguarded.ll diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 5a84ad4d436b..d3e8a86f8766 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -21660,6 +21660,20 @@ MCPhysReg RVVArgDispatcher::getNextPhysReg() { return AllocatedPhysRegs[CurIdx++]; } +SDValue RISCVTargetLowering::expandIndirectJTBranch(const SDLoc &dl, + SDValue Value, SDValue Addr, + int JTI, + SelectionDAG &DAG) const { + if (Subtarget.hasStdExtZicfilp()) { + // When Zicfilp enabled, we need to use software guarded branch for jump + // table branch. + SDValue JTInfo = DAG.getJumpTableDebugInfo(JTI, Value, dl); + return DAG.getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, JTInfo, + Addr); + } + return TargetLowering::expandIndirectJTBranch(dl, Value, Addr, JTI, DAG); +} + namespace llvm::RISCVVIntrinsicsTable { #define GET_RISCVVIntrinsicsTable_IMPL diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index 78f99e70c083..afc317f94dae 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -400,6 +400,10 @@ enum NodeType : unsigned { CZERO_EQZ, // vt.maskc for XVentanaCondOps. CZERO_NEZ, // vt.maskcn for XVentanaCondOps. + /// Software guarded BRIND node. Operand 0 is the chain operand and + /// operand 1 is the target address. + SW_GUARDED_BRIND, + // FP to 32 bit int conversions for RV64. These are used to keep track of the // result being sign extended to 64 bit. These saturate out of range inputs. STRICT_FCVT_W_RV64 = ISD::FIRST_TARGET_STRICTFP_OPCODE, @@ -869,6 +873,9 @@ public: bool supportKCFIBundles() const override { return true; } + SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, + int JTI, SelectionDAG &DAG) const override; + MachineInstr *EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index b867eccf4266..9d574edb4e6d 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -69,6 +69,8 @@ def riscv_brcc : SDNode<"RISCVISD::BR_CC", SDT_RISCVBrCC, def riscv_tail : SDNode<"RISCVISD::TAIL", SDT_RISCVCall, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; +def riscv_sw_guarded_brind : SDNode<"RISCVISD::SW_GUARDED_BRIND", + SDTBrind, [SDNPHasChain]>; def riscv_sllw : SDNode<"RISCVISD::SLLW", SDT_RISCVIntBinOpW>; def riscv_sraw : SDNode<"RISCVISD::SRAW", SDT_RISCVIntBinOpW>; def riscv_srlw : SDNode<"RISCVISD::SRLW", SDT_RISCVIntBinOpW>; @@ -1454,9 +1456,12 @@ def PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>, PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; let Predicates = [HasStdExtZicfilp], - isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in + isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in { def PseudoBRINDNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1, simm12:$imm12), []>, PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; +def PseudoBRINDX7 : Pseudo<(outs), (ins GPRX7:$rs1, simm12:$imm12), []>, + PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; +} // For Zicfilp, need to avoid using X7/T2 for indirect branches which need // landing pad. @@ -1464,6 +1469,10 @@ let Predicates = [HasStdExtZicfilp] in { def : Pat<(brind GPRJALRNonX7:$rs1), (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, 0)>; def : Pat<(brind (add GPRJALRNonX7:$rs1, simm12:$imm12)), (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, simm12:$imm12)>; + +def : Pat<(riscv_sw_guarded_brind GPRX7:$rs1), (PseudoBRINDX7 GPRX7:$rs1, 0)>; +def : Pat<(riscv_sw_guarded_brind (add GPRX7:$rs1, simm12:$imm12)), + (PseudoBRINDX7 GPRX7:$rs1, simm12:$imm12)>; } let Predicates = [NoStdExtZicfilp] in { diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td index 90e62dc39e6a..b12634c24622 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -167,6 +167,8 @@ def GPRNoX0 : GPRRegisterClass<(sub GPR, X0)>; def GPRNoX0X2 : GPRRegisterClass<(sub GPR, X0, X2)>; +def GPRX7 : GPRRegisterClass<(add X7)>; + // Don't use X1 or X5 for JALR since that is a hint to pop the return address // stack on some microarchitectures. Also remove the reserved registers X0, X2, // X3, and X4 as it reduces the number of register classes that get synthesized diff --git a/llvm/test/CodeGen/RISCV/jumptable-swguarded.ll b/llvm/test/CodeGen/RISCV/jumptable-swguarded.ll new file mode 100644 index 000000000000..9d57ca74cd78 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/jumptable-swguarded.ll @@ -0,0 +1,105 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp < %s | FileCheck %s +; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp < %s | FileCheck %s +; RUN: llc -mtriple riscv32 < %s | FileCheck %s --check-prefix=NO-ZICFILP +; RUN: llc -mtriple riscv64 < %s | FileCheck %s --check-prefix=NO-ZICFILP + +; Test using t2 to jump table branch. +define void @above_threshold(i32 signext %in, ptr %out) nounwind { +; CHECK-LABEL: above_threshold: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: addi a0, a0, -1 +; CHECK-NEXT: li a2, 5 +; CHECK-NEXT: bltu a2, a0, .LBB0_9 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: slli a0, a0, 2 +; CHECK-NEXT: lui a2, %hi(.LJTI0_0) +; CHECK-NEXT: addi a2, a2, %lo(.LJTI0_0) +; CHECK-NEXT: add a0, a0, a2 +; CHECK-NEXT: lw t2, 0(a0) +; CHECK-NEXT: jr t2 +; CHECK-NEXT: .LBB0_2: # %bb1 +; CHECK-NEXT: li a0, 4 +; CHECK-NEXT: j .LBB0_8 +; CHECK-NEXT: .LBB0_3: # %bb5 +; CHECK-NEXT: li a0, 100 +; CHECK-NEXT: j .LBB0_8 +; CHECK-NEXT: .LBB0_4: # %bb3 +; CHECK-NEXT: li a0, 2 +; CHECK-NEXT: j .LBB0_8 +; CHECK-NEXT: .LBB0_5: # %bb4 +; CHECK-NEXT: li a0, 1 +; CHECK-NEXT: j .LBB0_8 +; CHECK-NEXT: .LBB0_6: # %bb2 +; CHECK-NEXT: li a0, 3 +; CHECK-NEXT: j .LBB0_8 +; CHECK-NEXT: .LBB0_7: # %bb6 +; CHECK-NEXT: li a0, 200 +; CHECK-NEXT: .LBB0_8: # %exit +; CHECK-NEXT: sw a0, 0(a1) +; CHECK-NEXT: .LBB0_9: # %exit +; CHECK-NEXT: ret +; +; NO-ZICFILP-LABEL: above_threshold: +; NO-ZICFILP: # %bb.0: # %entry +; NO-ZICFILP-NEXT: addi a0, a0, -1 +; NO-ZICFILP-NEXT: li a2, 5 +; NO-ZICFILP-NEXT: bltu a2, a0, .LBB0_9 +; NO-ZICFILP-NEXT: # %bb.1: # %entry +; NO-ZICFILP-NEXT: slli a0, a0, 2 +; NO-ZICFILP-NEXT: lui a2, %hi(.LJTI0_0) +; NO-ZICFILP-NEXT: addi a2, a2, %lo(.LJTI0_0) +; NO-ZICFILP-NEXT: add a0, a0, a2 +; NO-ZICFILP-NEXT: lw a0, 0(a0) +; NO-ZICFILP-NEXT: jr a0 +; NO-ZICFILP-NEXT: .LBB0_2: # %bb1 +; NO-ZICFILP-NEXT: li a0, 4 +; NO-ZICFILP-NEXT: j .LBB0_8 +; NO-ZICFILP-NEXT: .LBB0_3: # %bb5 +; NO-ZICFILP-NEXT: li a0, 100 +; NO-ZICFILP-NEXT: j .LBB0_8 +; NO-ZICFILP-NEXT: .LBB0_4: # %bb3 +; NO-ZICFILP-NEXT: li a0, 2 +; NO-ZICFILP-NEXT: j .LBB0_8 +; NO-ZICFILP-NEXT: .LBB0_5: # %bb4 +; NO-ZICFILP-NEXT: li a0, 1 +; NO-ZICFILP-NEXT: j .LBB0_8 +; NO-ZICFILP-NEXT: .LBB0_6: # %bb2 +; NO-ZICFILP-NEXT: li a0, 3 +; NO-ZICFILP-NEXT: j .LBB0_8 +; NO-ZICFILP-NEXT: .LBB0_7: # %bb6 +; NO-ZICFILP-NEXT: li a0, 200 +; NO-ZICFILP-NEXT: .LBB0_8: # %exit +; NO-ZICFILP-NEXT: sw a0, 0(a1) +; NO-ZICFILP-NEXT: .LBB0_9: # %exit +; NO-ZICFILP-NEXT: ret +entry: + switch i32 %in, label %exit [ + i32 1, label %bb1 + i32 2, label %bb2 + i32 3, label %bb3 + i32 4, label %bb4 + i32 5, label %bb5 + i32 6, label %bb6 + ] +bb1: + store i32 4, ptr %out + br label %exit +bb2: + store i32 3, ptr %out + br label %exit +bb3: + store i32 2, ptr %out + br label %exit +bb4: + store i32 1, ptr %out + br label %exit +bb5: + store i32 100, ptr %out + br label %exit +bb6: + store i32 200, ptr %out + br label %exit +exit: + ret void +} -- GitLab From 9837a1cb53e94609c005ed44f937a99f24208452 Mon Sep 17 00:00:00 2001 From: Jacob Lambert Date: Mon, 13 May 2024 23:50:31 -0700 Subject: [PATCH 182/578] [NFC] Add missing spaces in BoolOption for apinotes (#92027) --- clang/include/clang/Driver/Options.td | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index ed3f1b8b2981..c9d8a1f50fec 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1858,13 +1858,13 @@ defm apinotes : BoolOption<"f", "apinotes", LangOpts<"APINotes">, DefaultFalse, PosFlag, NegFlag, - BothFlags<[], [ClangOption, CC1Option], "external API notes support">>, + BothFlags<[], [ClangOption, CC1Option], " external API notes support">>, Group; defm apinotes_modules : BoolOption<"f", "apinotes-modules", LangOpts<"APINotesModules">, DefaultFalse, PosFlag, NegFlag, - BothFlags<[], [ClangOption, CC1Option], "module-based external API notes support">>, + BothFlags<[], [ClangOption, CC1Option], " module-based external API notes support">>, Group; def fapinotes_swift_version : Joined<["-"], "fapinotes-swift-version=">, Group, Visibility<[ClangOption, CC1Option]>, -- GitLab From c441aa51e16e2fa5f407191287f48d2b7c302ceb Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Tue, 14 May 2024 10:59:16 +0400 Subject: [PATCH 183/578] [lldb] Add lldbutil.install_to_target() helper (#91944) It can be used in tests #91918, #91931 and such. --- lldb/packages/Python/lldbsuite/test/lldbutil.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lldb/packages/Python/lldbsuite/test/lldbutil.py b/lldb/packages/Python/lldbsuite/test/lldbutil.py index 58eb37fd742d..1ec036f885e7 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbutil.py @@ -1654,6 +1654,22 @@ def skip_if_library_missing(test, target, library): ) +def install_to_target(test, path): + if lldb.remote_platform: + filename = os.path.basename(path) + remote_path = append_to_process_working_directory(test, filename) + err = lldb.remote_platform.Install( + lldb.SBFileSpec(path, True), lldb.SBFileSpec(remote_path, False) + ) + if err.Fail(): + raise Exception( + "remote_platform.Install('%s', '%s') failed: %s" + % (path, remote_path, err) + ) + path = remote_path + return path + + def read_file_on_target(test, remote): if lldb.remote_platform: local = test.getBuildArtifact("file_from_target") -- GitLab From 2df06e42d733a1f7a1cdf715894921a5bbbc2956 Mon Sep 17 00:00:00 2001 From: Michael Klemm Date: Tue, 14 May 2024 09:01:51 +0200 Subject: [PATCH 184/578] [Flang][Driver] Add -print-resource-dir command line flag to emit Flang's resource directory (#90886) This should be a NFC change for all drivers, but Flang. --- clang/include/clang/Driver/Driver.h | 3 +++ clang/include/clang/Driver/Options.td | 5 ++++- clang/lib/Driver/Driver.cpp | 22 +++++++++++++++++++--- flang/test/Driver/print-resource-dir.F90 | 4 ++++ 4 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 flang/test/Driver/print-resource-dir.F90 diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index cc1538372d5f..084c3ffe69ae 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -747,6 +747,9 @@ private: /// option. void setDriverMode(StringRef DriverModeValue); + /// Set the resource directory, depending on which driver is being used. + void setResourceDirectory(); + /// Parse the \p Args list for LTO options and record the type of LTO /// compilation based on which -f(no-)?lto(=.*)? option occurs last. void setLTOMode(const llvm::opt::ArgList &Args); diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index c9d8a1f50fec..c54eb543d658 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5491,7 +5491,10 @@ def print_prog_name_EQ : Joined<["-", "--"], "print-prog-name=">, Visibility<[ClangOption, CLOption]>; def print_resource_dir : Flag<["-", "--"], "print-resource-dir">, HelpText<"Print the resource directory pathname">, - Visibility<[ClangOption, CLOption]>; + HelpTextForVariants<[FlangOption], + "Print the resource directory pathname that contains lib and " + "include directories with the runtime libraries and MODULE files.">, + Visibility<[ClangOption, CLOption, FlangOption]>; def print_search_dirs : Flag<["-", "--"], "print-search-dirs">, HelpText<"Print the paths used for finding libraries and programs">, Visibility<[ClangOption, CLOption]>; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 7b36d8e5084c..2868b4f2b02e 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -229,9 +229,6 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple, UserConfigDir = static_cast(P); } #endif - - // Compute the path to the resource directory. - ResourceDir = GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR); } void Driver::setDriverMode(StringRef Value) { @@ -250,6 +247,24 @@ void Driver::setDriverMode(StringRef Value) { Diag(diag::err_drv_unsupported_option_argument) << OptName << Value; } +void Driver::setResourceDirectory() { + // Compute the path to the resource directory, depending on the driver mode. + switch (Mode) { + case GCCMode: + case GXXMode: + case CPPMode: + case CLMode: + case DXCMode: + ResourceDir = GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR); + break; + case FlangMode: + SmallString<64> customResourcePathRelativeToDriver{".."}; + ResourceDir = + GetResourcesPath(ClangExecutable, customResourcePathRelativeToDriver); + break; + } +} + InputArgList Driver::ParseArgStrings(ArrayRef ArgStrings, bool UseDriverMode, bool &ContainsError) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); @@ -1202,6 +1217,7 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { if (!DriverMode.empty()) setDriverMode(DriverMode); + setResourceDirectory(); // FIXME: What are we going to do with -V and -b? // Arguments specified in command line. diff --git a/flang/test/Driver/print-resource-dir.F90 b/flang/test/Driver/print-resource-dir.F90 new file mode 100644 index 000000000000..8fd35f1800df --- /dev/null +++ b/flang/test/Driver/print-resource-dir.F90 @@ -0,0 +1,4 @@ +! DEFINE: %{resource_dir} = %S/Inputs/resource_dir +! RUN: %flang -print-resource-dir -resource-dir=%{resource_dir}.. \ +! RUN: | FileCheck -check-prefix=PRINT-RESOURCE-DIR -DFILE=%{resource_dir} %s +! PRINT-RESOURCE-DIR: [[FILE]] -- GitLab From 3ae63430aae52b260ce7ea99e5d586c77963b94a Mon Sep 17 00:00:00 2001 From: Vyacheslav Levytskyy Date: Tue, 14 May 2024 09:22:24 +0200 Subject: [PATCH 185/578] [SPIR-V] Set non-kernel function linkage type via OpDecorate for all linkage types except for static functions (#91598) This PR fixes the issue https://github.com/llvm/llvm-project/issues/91595 by setting non-kernel function linkage type via OpDecorate for all linkage types except for static functions. A new test case is added. --- llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp | 4 ++-- .../CodeGen/SPIRV/{ => linkage}/LinkOnceODR.ll | 0 .../SPIRV/{ => linkage}/LinkOnceODRFun.ll | 0 .../CodeGen/SPIRV/linkage/extern-weak-linkage.ll | 16 ++++++++++++++++ .../SPIRV/{ => linkage}/link-attribute.ll | 0 .../CodeGen/SPIRV/{ => linkage}/linkage-types.ll | 0 6 files changed, 18 insertions(+), 2 deletions(-) rename llvm/test/CodeGen/SPIRV/{ => linkage}/LinkOnceODR.ll (100%) rename llvm/test/CodeGen/SPIRV/{ => linkage}/LinkOnceODRFun.ll (100%) create mode 100644 llvm/test/CodeGen/SPIRV/linkage/extern-weak-linkage.ll rename llvm/test/CodeGen/SPIRV/{ => linkage}/link-attribute.ll (100%) rename llvm/test/CodeGen/SPIRV/{ => linkage}/linkage-types.ll (100%) diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp index c107b99cf4cb..727e4e584c05 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp @@ -430,8 +430,8 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, .addImm(static_cast(executionModel)) .addUse(FuncVReg); addStringImm(F.getName(), MIB); - } else if (F.getLinkage() == GlobalValue::LinkageTypes::ExternalLinkage || - F.getLinkage() == GlobalValue::LinkOnceODRLinkage) { + } else if (F.getLinkage() != GlobalValue::InternalLinkage && + F.getLinkage() != GlobalValue::PrivateLinkage) { SPIRV::LinkageType::LinkageType LnkTy = F.isDeclaration() ? SPIRV::LinkageType::Import diff --git a/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll b/llvm/test/CodeGen/SPIRV/linkage/LinkOnceODR.ll similarity index 100% rename from llvm/test/CodeGen/SPIRV/LinkOnceODR.ll rename to llvm/test/CodeGen/SPIRV/linkage/LinkOnceODR.ll diff --git a/llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll b/llvm/test/CodeGen/SPIRV/linkage/LinkOnceODRFun.ll similarity index 100% rename from llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll rename to llvm/test/CodeGen/SPIRV/linkage/LinkOnceODRFun.ll diff --git a/llvm/test/CodeGen/SPIRV/linkage/extern-weak-linkage.ll b/llvm/test/CodeGen/SPIRV/linkage/extern-weak-linkage.ll new file mode 100644 index 000000000000..e742de4bc1e2 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/linkage/extern-weak-linkage.ll @@ -0,0 +1,16 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV: Capability Linkage +; CHECK-SPIRV-DAG: OpName %[[#AbsFun:]] "abs" +; CHECK-SPIRV-DAG: OpName %[[#ExternalFun:]] "__devicelib_abs" +; CHECK-SPIRV-DAG: OpDecorate %[[#AbsFun]] LinkageAttributes "abs" Export +; CHECK-SPIRV-DAG: OpDecorate %[[#ExternalFun]] LinkageAttributes "__devicelib_abs" Import + +define weak dso_local spir_func i32 @abs(i32 noundef %x) { +entry: + %call = tail call spir_func i32 @__devicelib_abs(i32 noundef %x) #11 + ret i32 %call +} + +declare extern_weak dso_local spir_func i32 @__devicelib_abs(i32 noundef) diff --git a/llvm/test/CodeGen/SPIRV/link-attribute.ll b/llvm/test/CodeGen/SPIRV/linkage/link-attribute.ll similarity index 100% rename from llvm/test/CodeGen/SPIRV/link-attribute.ll rename to llvm/test/CodeGen/SPIRV/linkage/link-attribute.ll diff --git a/llvm/test/CodeGen/SPIRV/linkage-types.ll b/llvm/test/CodeGen/SPIRV/linkage/linkage-types.ll similarity index 100% rename from llvm/test/CodeGen/SPIRV/linkage-types.ll rename to llvm/test/CodeGen/SPIRV/linkage/linkage-types.ll -- GitLab From cf9a5a162b701b4c27eda1ddf823137ed16ca235 Mon Sep 17 00:00:00 2001 From: Vyacheslav Levytskyy Date: Tue, 14 May 2024 09:22:37 +0200 Subject: [PATCH 186/578] [SPIR-V] Support saturation arithmetic intrinsics in SPIR-V Backend (#91722) This PR is to support saturation arithmetic intrinsics in SPIR-V Backend. --- .../Target/SPIRV/SPIRVInstructionSelector.cpp | 9 +++++ llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 4 ++ .../SPIRV/llvm-intrinsics/satur-arith.ll | 37 +++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 llvm/test/CodeGen/SPIRV/llvm-intrinsics/satur-arith.ll diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 2051cdc7e01f..517a9b490eba 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -495,6 +495,15 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg, case TargetOpcode::G_UMULH: return selectExtInst(ResVReg, ResType, I, CL::u_mul_hi); + case TargetOpcode::G_SADDSAT: + return selectExtInst(ResVReg, ResType, I, CL::s_add_sat); + case TargetOpcode::G_UADDSAT: + return selectExtInst(ResVReg, ResType, I, CL::u_add_sat); + case TargetOpcode::G_SSUBSAT: + return selectExtInst(ResVReg, ResType, I, CL::s_sub_sat); + case TargetOpcode::G_USUBSAT: + return selectExtInst(ResVReg, ResType, I, CL::u_sub_sat); + case TargetOpcode::G_SEXT: return selectExt(ResVReg, ResType, I, true); case TargetOpcode::G_ANYEXT: diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp index e7b35555293a..42d36fd30ed6 100644 --- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp @@ -304,6 +304,10 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) { // Struct return types become a single scalar, so cannot easily legalize. getActionDefinitionsBuilder({G_SMULH, G_UMULH}).alwaysLegal(); + + // supported saturation arithmetic + getActionDefinitionsBuilder({G_SADDSAT, G_UADDSAT, G_SSUBSAT, G_USUBSAT}) + .legalFor(allIntScalarsAndVectors); } getLegacyLegalizerInfo().computeTables(); diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/satur-arith.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/satur-arith.ll new file mode 100644 index 000000000000..5b59206ff7f2 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/satur-arith.ll @@ -0,0 +1,37 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "OpenCL.std" +; CHECK-DAG: OpName %[[#Foo:]] "foo" +; CHECK-DAG: OpName %[[#Bar:]] "bar" +; CHECK: %[[#Foo]] = OpFunction +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] u_add_sat +; CHECK-NEXT: %[[#]] = OpExtInst %[[#]] %[[#]] u_sub_sat +; CHECK-NEXT: %[[#]] = OpExtInst %[[#]] %[[#]] s_add_sat +; CHECK-NEXT: %[[#]] = OpExtInst %[[#]] %[[#]] s_sub_sat +; CHECK: %[[#Bar]] = OpFunction +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] u_add_sat +; CHECK-NEXT: %[[#]] = OpExtInst %[[#]] %[[#]] u_sub_sat +; CHECK-NEXT: %[[#]] = OpExtInst %[[#]] %[[#]] s_add_sat +; CHECK-NEXT: %[[#]] = OpExtInst %[[#]] %[[#]] s_sub_sat + +define spir_func void @foo(i16 %x, i16 %y) { +entry: + %r1 = tail call i16 @llvm.uadd.sat.i16(i16 %x, i16 %y) + %r2 = tail call i16 @llvm.usub.sat.i16(i16 %x, i16 %y) + %r3 = tail call i16 @llvm.sadd.sat.i16(i16 %x, i16 %y) + %r4 = tail call i16 @llvm.ssub.sat.i16(i16 %x, i16 %y) + ret void +} + +define spir_func void @bar(<4 x i32> %x, <4 x i32> %y) { +entry: + %r1 = tail call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %x, <4 x i32> %y) + %r2 = tail call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %x, <4 x i32> %y) + %r3 = tail call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %x, <4 x i32> %y) + %r4 = tail call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %x, <4 x i32> %y) + ret void +} -- GitLab From e2f079cc6c3689fa5a6f64550b2d4fdc628dad6f Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Tue, 14 May 2024 11:26:14 +0400 Subject: [PATCH 187/578] [lldb] Fixed the test TestGdbRemoteLaunch (#91931) Install `a.out` to the remote target (after handshake) if necessary and use the remote path to call `vRun`. --- .../tools/lldb-server/TestGdbRemoteLaunch.py | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteLaunch.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteLaunch.py index 78a4d326c12d..ad84a40932c6 100644 --- a/lldb/test/API/tools/lldb-server/TestGdbRemoteLaunch.py +++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteLaunch.py @@ -12,13 +12,13 @@ class GdbRemoteLaunchTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): @add_test_categories(["llgs"]) def test_launch_via_A(self): self.build() - exe_path = self.getBuildArtifact("a.out") - args = [exe_path, "stderr:arg1", "stderr:arg2", "stderr:arg3"] - hex_args = [seven.hexlify(x) for x in args] - server = self.connect_to_debug_monitor() self.assertIsNotNone(server) self.do_handshake() + exe_path = lldbutil.install_to_target(self, self.getBuildArtifact("a.out")) + args = [exe_path, "stderr:arg1", "stderr:arg2", "stderr:arg3"] + hex_args = [seven.hexlify(x) for x in args] + # NB: strictly speaking we should use %x here but this packet # is deprecated, so no point in changing lldb-server's expectations self.test_sequence.add_log_lines( @@ -38,13 +38,13 @@ class GdbRemoteLaunchTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): @add_test_categories(["llgs"]) def test_launch_via_vRun(self): self.build() - exe_path = self.getBuildArtifact("a.out") - args = [exe_path, "stderr:arg1", "stderr:arg2", "stderr:arg3"] - hex_args = [seven.hexlify(x) for x in args] - server = self.connect_to_debug_monitor() self.assertIsNotNone(server) self.do_handshake() + exe_path = lldbutil.install_to_target(self, self.getBuildArtifact("a.out")) + args = [exe_path, "stderr:arg1", "stderr:arg2", "stderr:arg3"] + hex_args = [seven.hexlify(x) for x in args] + self.test_sequence.add_log_lines( [ "read packet: $vRun;%s;%s;%s;%s#00" % tuple(hex_args), @@ -60,12 +60,12 @@ class GdbRemoteLaunchTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): @add_test_categories(["llgs"]) def test_launch_via_vRun_no_args(self): self.build() - exe_path = self.getBuildArtifact("a.out") - hex_path = seven.hexlify(exe_path) - server = self.connect_to_debug_monitor() self.assertIsNotNone(server) self.do_handshake() + exe_path = lldbutil.install_to_target(self, self.getBuildArtifact("a.out")) + hex_path = seven.hexlify(exe_path) + self.test_sequence.add_log_lines( [ "read packet: $vRun;%s#00" % (hex_path,), @@ -78,6 +78,7 @@ class GdbRemoteLaunchTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): self.expect_gdbremote_sequence() @add_test_categories(["llgs"]) + @skipIfRemote def test_launch_failure_via_vRun(self): self.build() exe_path = self.getBuildArtifact("a.out") @@ -110,14 +111,13 @@ class GdbRemoteLaunchTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): @add_test_categories(["llgs"]) def test_QEnvironment(self): self.build() - exe_path = self.getBuildArtifact("a.out") - env = {"FOO": "test", "BAR": "a=z"} - args = [exe_path, "print-env:FOO", "print-env:BAR"] - hex_args = [seven.hexlify(x) for x in args] - server = self.connect_to_debug_monitor() self.assertIsNotNone(server) self.do_handshake() + exe_path = lldbutil.install_to_target(self, self.getBuildArtifact("a.out")) + env = {"FOO": "test", "BAR": "a=z"} + args = [exe_path, "print-env:FOO", "print-env:BAR"] + hex_args = [seven.hexlify(x) for x in args] for key, value in env.items(): self.test_sequence.add_log_lines( @@ -143,14 +143,13 @@ class GdbRemoteLaunchTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): @add_test_categories(["llgs"]) def test_QEnvironmentHexEncoded(self): self.build() - exe_path = self.getBuildArtifact("a.out") - env = {"FOO": "test", "BAR": "a=z", "BAZ": "a*}#z"} - args = [exe_path, "print-env:FOO", "print-env:BAR", "print-env:BAZ"] - hex_args = [seven.hexlify(x) for x in args] - server = self.connect_to_debug_monitor() self.assertIsNotNone(server) self.do_handshake() + exe_path = lldbutil.install_to_target(self, self.getBuildArtifact("a.out")) + env = {"FOO": "test", "BAR": "a=z", "BAZ": "a*}#z"} + args = [exe_path, "print-env:FOO", "print-env:BAR", "print-env:BAZ"] + hex_args = [seven.hexlify(x) for x in args] for key, value in env.items(): hex_enc = seven.hexlify("%s=%s" % (key, value)) -- GitLab From 2e165a2c4b2a0e9a9d34a721d756f9006d1502df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 14 May 2024 10:25:38 +0300 Subject: [PATCH 188/578] Revert "[ValueTracking] Compute knownbits from known fp classes (#86409)" This reverts commit d03a1a6e5838c7c2c0836d71507dfdf7840ade49. This change caused failed assertions, see https://github.com/llvm/llvm-project/pull/86409#issuecomment-2109469845 for details. --- llvm/include/llvm/IR/PatternMatch.h | 2 +- llvm/lib/Analysis/ValueTracking.cpp | 36 --- .../AMDGPU/amdgpu-simplify-libcall-pow.ll | 14 +- .../AMDGPU/amdgpu-simplify-libcall-pown.ll | 12 +- llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll | 10 +- .../test/Transforms/InstCombine/known-bits.ll | 264 ------------------ 6 files changed, 19 insertions(+), 319 deletions(-) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 0d6d86cb47e6..171ddab977de 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -1904,7 +1904,7 @@ template struct ElementWiseBitCast_match { ElementWiseBitCast_match(const Op_t &OpMatch) : Op(OpMatch) {} template bool match(OpTy *V) { - auto *I = dyn_cast(V); + BitCastInst *I = dyn_cast(V); if (!I) return false; Type *SrcType = I->getSrcTy(); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 2fdbb6e3ef84..375385aca7a3 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1118,42 +1118,6 @@ static void computeKnownBitsFromOperator(const Operator *I, break; } - const Value *V; - // Handle bitcast from floating point to integer. - if (match(I, m_ElementWiseBitCast(m_Value(V))) && - V->getType()->isFPOrFPVectorTy()) { - Type *FPType = V->getType()->getScalarType(); - KnownFPClass Result = computeKnownFPClass(V, fcAllFlags, Depth + 1, Q); - FPClassTest FPClasses = Result.KnownFPClasses; - - if (Result.isKnownNever(fcNormal | fcSubnormal | fcNan)) { - Known.Zero.setAllBits(); - Known.One.setAllBits(); - - if (FPClasses & fcInf) - Known = Known.intersectWith(KnownBits::makeConstant( - APFloat::getInf(FPType->getFltSemantics()).bitcastToAPInt())); - - if (FPClasses & fcZero) - Known = Known.intersectWith(KnownBits::makeConstant( - APInt::getZero(FPType->getScalarSizeInBits()))); - } - - if (Result.SignBit) { - if (*Result.SignBit) - Known.makeNegative(); - else - Known.makeNonNegative(); - } else { - Known.Zero.clearSignBit(); - Known.One.clearSignBit(); - } - - assert(!Known.hasConflict() && "Bits known to be one AND zero?"); - - break; - } - // Handle cast from vector integer type to scalar or vector integer. auto *SrcVecTy = dyn_cast(SrcTy); if (!SrcVecTy || !SrcVecTy->getElementType()->isIntegerTy() || diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll index 5db25a59d33f..c4bd4bc126f7 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll @@ -2216,7 +2216,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_sitofp(float %x, i32 %y) ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2304,7 +2304,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_uitofp(float %x, i32 %y) ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2353,7 +2353,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_uitofp_i256(float %x, i2 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2376,7 +2376,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_sitofp_i256(float %x, i2 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2399,7 +2399,7 @@ define <2 x float> @test_pow_afn_nnan_ninf_v2f32_known_integral_sitofp(<2 x floa ; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP4]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP5]] ; @@ -2448,7 +2448,7 @@ define <2 x float> @test_pow_afn_nnan_ninf_v2f32_known_integral_uitofp(<2 x floa ; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP4]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP5]] ; @@ -2560,7 +2560,7 @@ define float @test_pow_afn_f32_nnan_ninf__y_known_integral_trunc(float %x, float ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll index e298226ee7cc..8ddaf243db92 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll @@ -680,7 +680,7 @@ define float @test_pown_afn_nnan_ninf_f32(float %x, i32 %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; @@ -703,7 +703,7 @@ define <2 x float> @test_pown_afn_nnan_ninf_v2f32(<2 x float> %x, <2 x i32> %y) ; CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP2:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP3]] ; @@ -772,7 +772,7 @@ define half @test_pown_afn_nnan_ninf_f16(half %x, i32 %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast half [[X]] to i16 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i16 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast half [[__EXP2]] to i16 -; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i16 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or i16 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i16 [[TMP2]] to half ; CHECK-NEXT: ret half [[TMP3]] ; @@ -795,7 +795,7 @@ define <2 x half> @test_pown_afn_nnan_ninf_v2f16(<2 x half> %x, <2 x i32> %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x half> [[X]] to <2 x i16> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i16> [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x half> [[__EXP2]] to <2 x i16> -; CHECK-NEXT: [[TMP2:%.*]] = or disjoint <2 x i16> [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i16> [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x i16> [[TMP2]] to <2 x half> ; CHECK-NEXT: ret <2 x half> [[TMP3]] ; @@ -829,7 +829,7 @@ define float @test_pown_fast_f32_strictfp(float %x, i32 %y) #1 { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; @@ -1075,7 +1075,7 @@ define float @test_pown_afn_ninf_nnan_f32__x_known_positive(float nofpclass(ninf ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; diff --git a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll index 54ca33401ccf..204c8140d3f1 100644 --- a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll +++ b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll @@ -360,7 +360,7 @@ declare half @_Z4pownDhi(half, i32) ; GCN-NATIVE: %0 = bitcast half %x to i16 ; GCN-NATIVE: %__pow_sign = and i16 %__yeven, %0 ; GCN-NATIVE: %1 = bitcast half %__exp2 to i16 -; GCN-NATIVE: %2 = or disjoint i16 %__pow_sign, %1 +; GCN-NATIVE: %2 = or i16 %__pow_sign, %1 ; GCN-NATIVE: %3 = bitcast i16 %2 to half define half @test_pown_f16(half %x, i32 %y) { entry: @@ -378,7 +378,7 @@ declare float @_Z4pownfi(float, i32) ; GCN: %[[r0:.*]] = bitcast float %tmp to i32 ; GCN: %__pow_sign = and i32 %[[r0]], -2147483648 ; GCN: %[[r1:.*]] = bitcast float %__exp2 to i32 -; GCN: %[[r2:.*]] = or disjoint i32 %__pow_sign, %[[r1]] +; GCN: %[[r2:.*]] = or i32 %__pow_sign, %[[r1]] ; GCN: store i32 %[[r2]], ptr addrspace(1) %a, align 4 define amdgpu_kernel void @test_pow(ptr addrspace(1) nocapture %a) { entry: @@ -414,7 +414,7 @@ entry: ; GCN: %[[r0:.*]] = bitcast float %tmp to i32 ; GCN: %__pow_sign = and i32 %__yeven, %[[r0]] ; GCN: %[[r1:.*]] = bitcast float %__exp2 to i32 -; GCN: %[[r2:.*]] = or disjoint i32 %__pow_sign, %[[r1]] +; GCN: %[[r2:.*]] = or i32 %__pow_sign, %[[r1]] ; GCN: store i32 %[[r2]], ptr addrspace(1) %a, align 4 define amdgpu_kernel void @test_pown(ptr addrspace(1) nocapture %a) { entry: @@ -438,7 +438,7 @@ declare <2 x half> @_Z3powDv2_DhS_(<2 x half>, <2 x half>) ; GCN: %1 = bitcast half %x to i16 ; GCN: %__pow_sign = and i16 %1, -32768 ; GCN: %2 = bitcast half %__exp2 to i16 -; GCN: %3 = or disjoint i16 %__pow_sign, %2 +; GCN: %3 = or i16 %__pow_sign, %2 ; GCN: %4 = bitcast i16 %3 to half define half @test_pow_fast_f16__y_13(half %x) { %powr = tail call fast half @_Z3powDhDh(half %x, half 13.0) @@ -453,7 +453,7 @@ define half @test_pow_fast_f16__y_13(half %x) { ; GCN: %1 = bitcast <2 x half> %x to <2 x i16> ; GCN: %__pow_sign = and <2 x i16> %1, ; GCN: %2 = bitcast <2 x half> %__exp2 to <2 x i16> -; GCN: %3 = or disjoint <2 x i16> %__pow_sign, %2 +; GCN: %3 = or <2 x i16> %__pow_sign, %2 ; GCN: %4 = bitcast <2 x i16> %3 to <2 x half> define <2 x half> @test_pow_fast_v2f16__y_13(<2 x half> %x) { %powr = tail call fast <2 x half> @_Z3powDv2_DhS_(<2 x half> %x, <2 x half> ) diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index 816bd6f352df..8b4249b2c25a 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1374,269 +1374,5 @@ define i8 @nonzero_reduce_xor_vscale_odd( %xx) { ret i8 %r } -define i1 @test_sign_pos(float %x) { -; CHECK-LABEL: @test_sign_pos( -; CHECK-NEXT: ret i1 true -; - %fabs = call float @llvm.fabs.f32(float %x) - %y = bitcast float %fabs to i32 - %sign = icmp sgt i32 %y, -1 - ret i1 %sign -} - -define i1 @test_sign_pos_half(half %x) { -; CHECK-LABEL: @test_sign_pos_half( -; CHECK-NEXT: ret i1 true -; - %fabs = call half @llvm.fabs.f16(half %x) - %y = bitcast half %fabs to i16 - %sign = icmp sgt i16 %y, -1 - ret i1 %sign -} - -define i1 @test_sign_pos_half_non_elementwise(<2 x half> %x) { -; CHECK-LABEL: @test_sign_pos_half_non_elementwise( -; CHECK-NEXT: [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]]) -; CHECK-NEXT: [[Y:%.*]] = bitcast <2 x half> [[FABS]] to i32 -; CHECK-NEXT: [[SIGN:%.*]] = icmp sgt i32 [[Y]], -1 -; CHECK-NEXT: ret i1 [[SIGN]] -; - %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x) - %y = bitcast <2 x half> %fabs to i32 - %sign = icmp sgt i32 %y, -1 - ret i1 %sign -} - -define i1 @test_sign_neg(float %x) { -; CHECK-LABEL: @test_sign_neg( -; CHECK-NEXT: ret i1 true -; - %fabs = call float @llvm.fabs.f32(float %x) - %fnabs = fneg float %fabs - %y = bitcast float %fnabs to i32 - %sign = icmp slt i32 %y, 0 - ret i1 %sign -} - -define <2 x i1> @test_sign_pos_vec(<2 x float> %x) { -; CHECK-LABEL: @test_sign_pos_vec( -; CHECK-NEXT: ret <2 x i1> zeroinitializer -; - %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %x) - %y = bitcast <2 x float> %fabs to <2 x i32> - %sign = icmp slt <2 x i32> %y, zeroinitializer - ret <2 x i1> %sign -} - -define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) { -; CHECK-LABEL: @test_inf_only( -; CHECK-NEXT: ret i32 2139095040 -; - %y = bitcast float %x to i32 - %and = and i32 %y, 2147483647 - ret i32 %and -} - -define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) { -; CHECK-LABEL: @test_inf_only_bfloat( -; CHECK-NEXT: ret i16 32640 -; - %y = bitcast bfloat %x to i16 - %and = and i16 %y, 32767 - ret i16 %and -} - -define i128 @test_inf_only_ppc_fp128(ppc_fp128 nofpclass(nan sub norm zero) %x) { -; CHECK-LABEL: @test_inf_only_ppc_fp128( -; CHECK-NEXT: ret i128 9218868437227405312 -; - %y = bitcast ppc_fp128 %x to i128 - %and = and i128 %y, 170141183460469231731687303715884105727 - ret i128 %and -} - -define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) { -; CHECK-LABEL: @test_zero_only( -; CHECK-NEXT: ret i32 0 -; - %y = bitcast float %x to i32 - %and = and i32 %y, 2147483647 - ret i32 %and -} - -define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) { -; CHECK-LABEL: @test_zero_only_non_ieee( -; CHECK-NEXT: ret i80 0 -; - %y = bitcast x86_fp80 %x to i80 - %and = and i80 %y, 604462909807314587353087 - ret i80 %and -} - -define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) { -; CHECK-LABEL: @test_inf_nan_only( -; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 -; CHECK-NEXT: ret i32 [[AND]] -; - %y = bitcast float %x to i32 - %and = and i32 %y, 2130706432 - ret i32 %and -} - -define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) { -; CHECK-LABEL: @test_sub_zero_only( -; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 -; CHECK-NEXT: ret i32 [[AND]] -; - %y = bitcast float %x to i32 - %and = and i32 %y, 2130706432 - ret i32 %and -} - -define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) { -; CHECK-LABEL: @test_inf_zero_only( -; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 8388608 -; CHECK-NEXT: ret i32 [[AND]] -; - %y = bitcast float %x to i32 - %and = and i32 %y, 16777215 - ret i32 %and -} - - - -define i1 @test_simplify_icmp(i32 %x) { -; CHECK-LABEL: @test_simplify_icmp( -; CHECK-NEXT: ret i1 false -; - %cast1 = uitofp i32 %x to double - %cast2 = bitcast double %cast1 to i64 - %mask = and i64 %cast2, -140737488355328 - %cmp = icmp eq i64 %mask, -1970324836974592 - ret i1 %cmp -} - -define i32 @test_snan_quiet_bit1(float nofpclass(sub norm inf qnan) %x) { -; CHECK-LABEL: @test_snan_quiet_bit1( -; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 4194304 -; CHECK-NEXT: ret i32 [[MASKED]] -; - %bits = bitcast float %x to i32 - %masked = and i32 %bits, 4194304 - ret i32 %masked -} - -define i32 @test_snan_quiet_bit2(float nofpclass(sub norm inf qnan) %x) { -; CHECK-LABEL: @test_snan_quiet_bit2( -; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 2097152 -; CHECK-NEXT: ret i32 [[MASKED]] -; - %bits = bitcast float %x to i32 - %masked = and i32 %bits, 2097152 - ret i32 %masked -} - -define i32 @test_qnan_quiet_bit1(float nofpclass(sub norm inf snan) %x) { -; CHECK-LABEL: @test_qnan_quiet_bit1( -; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 4194304 -; CHECK-NEXT: ret i32 [[MASKED]] -; - %bits = bitcast float %x to i32 - %masked = and i32 %bits, 4194304 - ret i32 %masked -} - -define i32 @test_qnan_quiet_bit2(float nofpclass(sub norm inf snan) %x) { -; CHECK-LABEL: @test_qnan_quiet_bit2( -; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 2097152 -; CHECK-NEXT: ret i32 [[MASKED]] -; - %bits = bitcast float %x to i32 - %masked = and i32 %bits, 2097152 - ret i32 %masked -} - -define i16 @test_simplify_mask(i32 %ui, float %x) { -; CHECK-LABEL: @test_simplify_mask( -; CHECK-NEXT: [[CONV:%.*]] = uitofp i32 [[UI:%.*]] to float -; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[CONV]], [[X:%.*]] -; CHECK-NEXT: br i1 [[CMP]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]] -; CHECK: if.end: -; CHECK-NEXT: ret i16 31744 -; CHECK: if.else: -; CHECK-NEXT: ret i16 0 -; - %conv = uitofp i32 %ui to float - %cmp = fcmp olt float %x, %conv - br i1 %cmp, label %if.else, label %if.end - -if.end: - %cast = bitcast float %conv to i32 - %shr = lshr i32 %cast, 16 - %trunc = trunc i32 %shr to i16 - %and = and i16 %trunc, -32768 - %or = or disjoint i16 %and, 31744 - ret i16 %or - -if.else: - ret i16 0 -} - -; TODO: %cmp always evaluates to false - -define i1 @test_simplify_icmp2(double %x) { -; CHECK-LABEL: @test_simplify_icmp2( -; CHECK-NEXT: [[ABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]]) -; CHECK-NEXT: [[COND:%.*]] = fcmp oeq double [[ABS]], 0x7FF0000000000000 -; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] -; CHECK: if.then: -; CHECK-NEXT: [[CAST:%.*]] = bitcast double [[X]] to i64 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[CAST]], 3458764513820540928 -; CHECK-NEXT: ret i1 [[CMP]] -; CHECK: if.else: -; CHECK-NEXT: ret i1 false -; - %abs = tail call double @llvm.fabs.f64(double %x) - %cond = fcmp oeq double %abs, 0x7FF0000000000000 - br i1 %cond, label %if.then, label %if.else - -if.then: - %cast = bitcast double %x to i64 - %cmp = icmp eq i64 %cast, 3458764513820540928 - ret i1 %cmp - -if.else: - ret i1 false -} - -define i32 @test_snan_only(float nofpclass(qnan sub norm zero inf) %x) { -; CHECK-LABEL: @test_snan_only( -; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 4194304 -; CHECK-NEXT: ret i32 [[AND]] -; - %y = bitcast float %x to i32 - %and = and i32 %y, 4194304 - ret i32 %and -} - -define i32 @test_qnan_only(float nofpclass(snan sub norm zero inf) %x) { -; CHECK-LABEL: @test_qnan_only( -; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 4194304 -; CHECK-NEXT: ret i32 [[AND]] -; - %y = bitcast float %x to i32 - %and = and i32 %y, 4194304 - ret i32 %and -} - declare void @use(i1) declare void @sink(i8) -- GitLab From fcd020d561f28a2b33b6cc12a5a0164a6d5e4172 Mon Sep 17 00:00:00 2001 From: martinboehme Date: Tue, 14 May 2024 09:45:54 +0200 Subject: [PATCH 189/578] [Clang][Sema] Fix malformed AST for anonymous class access in template. (#90842) # Observed erroneous behavior Prior to this change, a `MemberExpr` that accesses an anonymous class might have a prvalue as its base (even though C++ mandates that the base of a `MemberExpr` must be a glvalue), if the code containing the `MemberExpr` was in a template. Here's an example on [godbolt](https://godbolt.org/z/Gz1Mer9oz) (that is essentially identical to the new test this patch adds). This example sets up a struct containing an anonymous struct: ```cxx struct S { struct { int i; }; }; ``` It then accesses the member `i` using the expression `S().i`. When we do this in a non-template function, we get the following AST: ``` `-ExprWithCleanups 'int' `-ImplicitCastExpr 'int' `-MemberExpr 'int' xvalue .i 0xbdcb3c0 `-MemberExpr 'S::(anonymous struct at line:2:3)' xvalue .S::(anonymous struct at line:2:3) 0xbdcb488 `-MaterializeTemporaryExpr 'S' xvalue `-CXXTemporaryObjectExpr 'S' 'void () noexcept' zeroing ``` As expected, the AST contains a `MaterializeTemporarExpr` to materialize the prvalue `S()` before accessing its members. When we perform this access in a function template (that doesn't actually even use its template parameter), the AST for the template itself looks the same as above. However, the AST for an instantiation of the template looks different: ``` `-ExprWithCleanups 'int' `-ImplicitCastExpr 'int' `-MemberExpr 'int' xvalue .i 0xbdcb3c0 `-MaterializeTemporaryExpr 'S::(anonymous struct at line:2:3)' xvalue `-MemberExpr 'S::(anonymous struct at line:2:3)' .S::(anonymous struct at line:2:3) 0xbdcb488 `-CXXTemporaryObjectExpr 'S' 'void () noexcept' zeroing ``` Note how the inner `MemberExpr` (the one accessing the anonymous struct) acts on a prvalue. Interestingly, this does not appear to cause any problems for CodeGen, probably because CodeGen is set up to deal with `MemberExpr`s on rvalues in C. However, it does cause issues in the dataflow framework, which only supports C++ today and expects the base of a `MemberExpr` to be a glvalue. Beyond the issues with the dataflow framework, I think this issue should be fixed because it goes contrary to what the C++ standard mandates, and the AST produced for the non-template case indicates that we want to follow the C++ rules here. # Reasons for erroneous behavior Here's why we're getting this malformed AST. First of all, `TreeTransform` [strips any `MaterializeTemporaryExpr`s](https://github.com/llvm/llvm-project/blob/cd132dcbeb0fc79fd657bd5e0a8e9244c3fb5da6/clang/lib/Sema/TreeTransform.h#L14853) from the AST. It is therefore up to [`TreeTransform::RebuildMemberExpr()`](https://github.com/llvm/llvm-project/blob/cd132dcbeb0fc79fd657bd5e0a8e9244c3fb5da6/clang/lib/Sema/TreeTransform.h#L2853) to recreate a `MaterializeTemporaryExpr` if needed. In the [general case](https://github.com/llvm/llvm-project/blob/cd132dcbeb0fc79fd657bd5e0a8e9244c3fb5da6/clang/lib/Sema/TreeTransform.h#L2915), it does this: It calls `Sema::BuildMemberReferenceExpr()`, which ensures that the base is a glvalue by [materializing a temporary](https://github.com/llvm/llvm-project/blob/cd132dcbeb0fc79fd657bd5e0a8e9244c3fb5da6/clang/lib/Sema/SemaExprMember.cpp#L1016) if needed. However, when `TreeTransform::RebuildMemberExpr()` encounters an anonymous class, it [calls `Sema::BuildFieldReferenceExpr()`](https://github.com/llvm/llvm-project/blob/cd132dcbeb0fc79fd657bd5e0a8e9244c3fb5da6/clang/lib/Sema/TreeTransform.h#L2880), which, unlike `Sema::BuildMemberReferenceExpr()`, does not make sure that the base is a glvalue. # Proposed fix I considered several possible ways to fix this issue: - Add logic to `Sema::BuildFieldReferenceExpr()` that materializes a temporary if needed. This appears to work, but it feels like the fix is in the wrong place: - AFAIU, other callers of `Sema::BuildFieldReferenceExpr()` don't need this logic. - The issue is caused by `TreeTransform` removing the `MaterializeTemporaryExpr`, so it seems the fix should also be in `TreeTransform` - Materialize the temporary directly in `TreeTransform::RebuildMemberExpr()` if needed (within the case that deals with anonymous classes). This would work, too, but it would duplicate logic that already exists in `Sema::BuildMemberReferenceExpr()` (which we leverage for the general case). - Use `Sema::BuildMemberReferenceExpr()` instead of `Sema::BuildFieldReferenceExpr()` for the anonymous class case, so that it also uses the existing logic for materializing the temporary. This is the option I've decided to go with here. There's a slight wrinkle in that we create a `LookupResult` that claims we looked up the unnamed field for the anonymous class -- even though we would obviously never be able to look up an unnamed field. I think this is defensible and still better than the other alternatives, but I would welcome feedback on this from others who know the code better. --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/TreeTransform.h | 13 ++++- clang/test/AST/ast-dump-anonymous-class.cpp | 49 +++++++++++++++++++ .../Analysis/FlowSensitive/TransferTest.cpp | 35 +++++++++++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 clang/test/AST/ast-dump-anonymous-class.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 28ac54127383..49ab222bec40 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -715,6 +715,7 @@ Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Clang now properly preserves ``FoundDecls`` within a ``ConceptReference``. (#GH82628) - The presence of the ``typename`` keyword is now stored in ``TemplateTemplateParmDecl``. +- Fixed malformed AST generated for anonymous union access in templates. (#GH90842) Miscellaneous Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 2d903dc52556..c039b95293af 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2874,10 +2874,21 @@ public: return ExprError(); Base = BaseResult.get(); + // `TranformMaterializeTemporaryExpr()` removes materialized temporaries + // from the AST, so we need to re-insert them if needed (since + // `BuildFieldRefereneExpr()` doesn't do this). + if (!isArrow && Base->isPRValue()) { + BaseResult = getSema().TemporaryMaterializationConversion(Base); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.get(); + } + CXXScopeSpec EmptySS; return getSema().BuildFieldReferenceExpr( Base, isArrow, OpLoc, EmptySS, cast(Member), - DeclAccessPair::make(FoundDecl, FoundDecl->getAccess()), MemberNameInfo); + DeclAccessPair::make(FoundDecl, FoundDecl->getAccess()), + MemberNameInfo); } CXXScopeSpec SS; diff --git a/clang/test/AST/ast-dump-anonymous-class.cpp b/clang/test/AST/ast-dump-anonymous-class.cpp new file mode 100644 index 000000000000..393c084c913d --- /dev/null +++ b/clang/test/AST/ast-dump-anonymous-class.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -ast-dump %s \ +// RUN: | FileCheck -strict-whitespace %s + +struct S { + struct { + int i; + }; +}; + +int accessInRegularFunction() { + return S().i; + // CHECK: FunctionDecl {{.*}} accessInRegularFunction 'int ()' + // CHECK: | `-ReturnStmt {{.*}} + // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'int' + // CHECK-NEXT: | `-MemberExpr {{.*}} 'int' xvalue .i + // CHECK-NEXT: | `-MemberExpr {{.*}} 'S::(anonymous struct at {{.*}}) + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'S' xvalue + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'S' 'void () noexcept' zeroing +} + +// AST should look the same in a function template with an unused template +// parameter. +template +int accessInFunctionTemplate() { + return S().i; + // CHECK: FunctionDecl {{.*}} accessInFunctionTemplate 'int ()' + // CHECK: | `-ReturnStmt {{.*}} + // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'int' + // CHECK-NEXT: | `-MemberExpr {{.*}} 'int' xvalue .i + // CHECK-NEXT: | `-MemberExpr {{.*}} 'S::(anonymous struct at {{.*}}) + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'S' xvalue + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'S' 'void () noexcept' zeroing +} + +// AST should look the same in an instantiation of the function template. +// This is a regression test: The AST used to contain the +// `MaterializeTemporaryExpr` in the wrong place, causing a `MemberExpr` to have +// a prvalue base (which is not allowed in C++). +template int accessInFunctionTemplate(); + // CHECK: FunctionDecl {{.*}} accessInFunctionTemplate 'int ()' explicit_instantiation_definition + // CHECK: `-ReturnStmt {{.*}} + // CHECK-NEXT: `-ExprWithCleanups {{.*}} 'int' + // CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' + // CHECK-NEXT: `-MemberExpr {{.*}} 'int' xvalue .i + // CHECK-NEXT: `-MemberExpr {{.*}} 'S::(anonymous struct at {{.*}}) + // CHECK-NEXT: `-MaterializeTemporaryExpr {{.*}} 'S' xvalue + // CHECK-NEXT: `-CXXTemporaryObjectExpr {{.*}} 'S' 'void () noexcept' zeroing diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index e1fb16b64fd6..5c0582e872eb 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -27,6 +27,14 @@ #include #include +namespace clang { +namespace dataflow { +namespace { +AST_MATCHER(FunctionDecl, isTemplated) { return Node.isTemplated(); } +} // namespace +} // namespace dataflow +} // namespace clang + namespace { using namespace clang; @@ -7416,4 +7424,31 @@ TEST(TransferTest, ConditionalRelation) { }); } +// This is a crash repro. +// We used to crash while transferring `S().i` because Clang contained a bug +// causing the AST to be malformed. +TEST(TransferTest, AnonymousUnionMemberExprInTemplate) { + using ast_matchers::functionDecl; + using ast_matchers::hasName; + using ast_matchers::unless; + + std::string Code = R"cc( + struct S { + struct { + int i; + }; + }; + + template + void target() { + S().i; + } + + template void target(); + )cc"; + auto Matcher = functionDecl(hasName("target"), unless(isTemplated())); + ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code, Matcher), + llvm::Succeeded()); +} + } // namespace -- GitLab From 79a6a7e28fffd14e54a9a208af12d724b6eeb2d4 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Tue, 14 May 2024 00:48:56 -0700 Subject: [PATCH 190/578] [RISCV] Fix a warning This patch fixes: llvm/lib/Target/RISCV/RISCVISelLowering.cpp:19848:11: error: enumeration value 'SW_GUARDED_BRIND' not handled in switch [-Werror,-Wswitch] --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index d3e8a86f8766..8d9b0f2acc5f 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -20067,6 +20067,7 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const { NODE_NAME_CASE(SWAP_CSR) NODE_NAME_CASE(CZERO_EQZ) NODE_NAME_CASE(CZERO_NEZ) + NODE_NAME_CASE(SW_GUARDED_BRIND) NODE_NAME_CASE(SF_VC_XV_SE) NODE_NAME_CASE(SF_VC_IV_SE) NODE_NAME_CASE(SF_VC_VV_SE) -- GitLab From 11e5d1cfee399cfaba373078879c1ac3e1109b11 Mon Sep 17 00:00:00 2001 From: Sameer Sahasrabuddhe Date: Tue, 14 May 2024 13:39:37 +0530 Subject: [PATCH 191/578] [AMDGPU] Respect existing glue when lowering convergence tokens (#90834) --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 8645f560d997..8f741ffc58a8 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -3859,20 +3859,20 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI, assert(Mask && "Missing call preserved mask for calling convention"); Ops.push_back(DAG.getRegisterMask(Mask)); - if (InGlue.getNode()) - Ops.push_back(InGlue); - - // NOTE: This potentially results in *two* glue operands, and the wrong one - // might possibly show up where the other was intended. In particular, - // Emitter::EmitMachineNode() expects only the glued convergence token if it - // exists. Similarly, the selection of the call expects to match only the - // InGlue operand if it exists. if (SDValue Token = CLI.ConvergenceControlToken) { - Ops.push_back(SDValue(DAG.getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, - DL, MVT::Glue, Token), - 0)); + SmallVector GlueOps; + GlueOps.push_back(Token); + if (InGlue) + GlueOps.push_back(InGlue); + + InGlue = SDValue(DAG.getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, DL, + MVT::Glue, GlueOps), + 0); } + if (InGlue) + Ops.push_back(InGlue); + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); // If we're doing a tall call, use a TC_RETURN here rather than an -- GitLab From c28529788955dbfada9f8a5092432f09eec2c3ab Mon Sep 17 00:00:00 2001 From: aabhinavg <78288544+aabhinavg@users.noreply.github.com> Date: Tue, 14 May 2024 13:44:17 +0530 Subject: [PATCH 192/578] [lldb] Fix redundant condition in Target.cpp (#91882) This commit addresses issue #87244, where a redundant condition was found in the Target.cpp file. Static analyzer cppcheck flagged the issue in the Target.cpp file fix #87244 --- lldb/source/Target/Target.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 82f3040e539a..77731167995e 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -841,7 +841,7 @@ static bool CheckIfWatchpointsSupported(Target *target, Status &error) { if (!num_supported_hardware_watchpoints) return true; - if (num_supported_hardware_watchpoints == 0) { + if (*num_supported_hardware_watchpoints == 0) { error.SetErrorStringWithFormat( "Target supports (%u) hardware watchpoint slots.\n", *num_supported_hardware_watchpoints); -- GitLab From 0b5b2027f94c60c73d6871cf64d3f580c27c5a53 Mon Sep 17 00:00:00 2001 From: Christian Ulmann Date: Tue, 14 May 2024 10:26:27 +0200 Subject: [PATCH 193/578] [MLIR][SROA] Reuse allocators to avoid rewalking the IR (#91971) This commit extends the SROA interfaces to ensure the interface instantiations can communicate newly created allocators to the algorithm. This ensures that the SROA implementation does no longer require re-walking the IR to find new allocators. --- .../mlir/Interfaces/MemorySlotInterfaces.td | 10 ++- mlir/include/mlir/Transforms/SROA.h | 6 +- mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp | 13 +-- .../Dialect/MemRef/IR/MemRefMemorySlot.cpp | 13 +-- mlir/lib/Transforms/SROA.cpp | 86 ++++++++++++------- mlir/test/Transforms/sroa.mlir | 31 +++++++ mlir/test/lib/Dialect/Test/TestOpDefs.cpp | 78 ++++++++++++++--- mlir/test/lib/Dialect/Test/TestOps.td | 5 +- 8 files changed, 184 insertions(+), 58 deletions(-) create mode 100644 mlir/test/Transforms/sroa.mlir diff --git a/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td b/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td index e2409cbec5fd..6f023f0c5263 100644 --- a/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td +++ b/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td @@ -298,14 +298,20 @@ def DestructurableAllocationOpInterface "destructure", (ins "const ::mlir::DestructurableMemorySlot &":$slot, "const ::llvm::SmallPtrSetImpl<::mlir::Attribute> &":$usedIndices, - "::mlir::OpBuilder &":$builder) + "::mlir::OpBuilder &":$builder, + "::mlir::SmallVectorImpl<::mlir::DestructurableAllocationOpInterface> &": + $newAllocators) >, InterfaceMethod<[{ Hook triggered once the destructuring of a slot is complete, meaning the original slot is no longer being refered to and could be deleted. This will only be called for slots declared by this operation. + + Must return a new destructurable allocation op if this hook creates + a new destructurable op, nullopt otherwise. }], - "void", "handleDestructuringComplete", + "::std::optional<::mlir::DestructurableAllocationOpInterface>", + "handleDestructuringComplete", (ins "const ::mlir::DestructurableMemorySlot &":$slot, "::mlir::OpBuilder &":$builder) >, diff --git a/mlir/include/mlir/Transforms/SROA.h b/mlir/include/mlir/Transforms/SROA.h index fa84fb1eae73..d48f809d3076 100644 --- a/mlir/include/mlir/Transforms/SROA.h +++ b/mlir/include/mlir/Transforms/SROA.h @@ -27,8 +27,10 @@ struct SROAStatistics { llvm::Statistic *maxSubelementAmount = nullptr; }; -/// Attempts to destructure the slots of destructurable allocators. Returns -/// failure if no slot was destructured. +/// Attempts to destructure the slots of destructurable allocators. Iteratively +/// retries the destructuring of all slots as destructuring one slot might +/// enable subsequent destructuring. Returns failure if no slot was +/// destructured. LogicalResult tryToDestructureMemorySlots( ArrayRef allocators, OpBuilder &builder, const DataLayout &dataLayout, diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp index 4fdf847a559c..3f1e5b1773bf 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp @@ -77,10 +77,10 @@ SmallVector LLVM::AllocaOp::getDestructurableSlots() { *destructuredType}}; } -DenseMap -LLVM::AllocaOp::destructure(const DestructurableMemorySlot &slot, - const SmallPtrSetImpl &usedIndices, - OpBuilder &builder) { +DenseMap LLVM::AllocaOp::destructure( + const DestructurableMemorySlot &slot, + const SmallPtrSetImpl &usedIndices, OpBuilder &builder, + SmallVectorImpl &newAllocators) { assert(slot.ptr == getResult()); builder.setInsertionPointAfter(*this); @@ -92,16 +92,19 @@ LLVM::AllocaOp::destructure(const DestructurableMemorySlot &slot, auto subAlloca = builder.create( getLoc(), LLVM::LLVMPointerType::get(getContext()), elemType, getArraySize()); + newAllocators.push_back(subAlloca); slotMap.try_emplace(index, {subAlloca.getResult(), elemType}); } return slotMap; } -void LLVM::AllocaOp::handleDestructuringComplete( +std::optional +LLVM::AllocaOp::handleDestructuringComplete( const DestructurableMemorySlot &slot, OpBuilder &builder) { assert(slot.ptr == getResult()); this->erase(); + return std::nullopt; } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp index e30598e6878f..631dee2d4053 100644 --- a/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp @@ -126,10 +126,10 @@ memref::AllocaOp::getDestructurableSlots() { DestructurableMemorySlot{{getMemref(), memrefType}, *destructuredType}}; } -DenseMap -memref::AllocaOp::destructure(const DestructurableMemorySlot &slot, - const SmallPtrSetImpl &usedIndices, - OpBuilder &builder) { +DenseMap memref::AllocaOp::destructure( + const DestructurableMemorySlot &slot, + const SmallPtrSetImpl &usedIndices, OpBuilder &builder, + SmallVectorImpl &newAllocators) { builder.setInsertionPointAfter(*this); DenseMap slotMap; @@ -139,6 +139,7 @@ memref::AllocaOp::destructure(const DestructurableMemorySlot &slot, Type elemType = memrefType.getTypeAtIndex(usedIndex); MemRefType elemPtr = MemRefType::get({}, elemType); auto subAlloca = builder.create(getLoc(), elemPtr); + newAllocators.push_back(subAlloca); slotMap.try_emplace(usedIndex, {subAlloca.getResult(), elemType}); } @@ -146,10 +147,12 @@ memref::AllocaOp::destructure(const DestructurableMemorySlot &slot, return slotMap; } -void memref::AllocaOp::handleDestructuringComplete( +std::optional +memref::AllocaOp::handleDestructuringComplete( const DestructurableMemorySlot &slot, OpBuilder &builder) { assert(slot.ptr == getResult()); this->erase(); + return std::nullopt; } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Transforms/SROA.cpp b/mlir/lib/Transforms/SROA.cpp index 4e28fa687ffd..67cbade07bc9 100644 --- a/mlir/lib/Transforms/SROA.cpp +++ b/mlir/lib/Transforms/SROA.cpp @@ -132,16 +132,17 @@ computeDestructuringInfo(DestructurableMemorySlot &slot, /// Performs the destructuring of a destructible slot given associated /// destructuring information. The provided slot will be destructured in /// subslots as specified by its allocator. -static void destructureSlot(DestructurableMemorySlot &slot, - DestructurableAllocationOpInterface allocator, - OpBuilder &builder, const DataLayout &dataLayout, - MemorySlotDestructuringInfo &info, - const SROAStatistics &statistics) { +static void destructureSlot( + DestructurableMemorySlot &slot, + DestructurableAllocationOpInterface allocator, OpBuilder &builder, + const DataLayout &dataLayout, MemorySlotDestructuringInfo &info, + SmallVectorImpl &newAllocators, + const SROAStatistics &statistics) { OpBuilder::InsertionGuard guard(builder); builder.setInsertionPointToStart(slot.ptr.getParentBlock()); DenseMap subslots = - allocator.destructure(slot, info.usedIndices, builder); + allocator.destructure(slot, info.usedIndices, builder, newAllocators); if (statistics.slotsWithMemoryBenefit && slot.elementPtrs.size() != info.usedIndices.size()) @@ -185,7 +186,11 @@ static void destructureSlot(DestructurableMemorySlot &slot, if (statistics.destructuredAmount) (*statistics.destructuredAmount)++; - allocator.handleDestructuringComplete(slot, builder); + std::optional newAllocator = + allocator.handleDestructuringComplete(slot, builder); + // Add newly created allocators to the worklist for further processing. + if (newAllocator) + newAllocators.push_back(*newAllocator); } LogicalResult mlir::tryToDestructureMemorySlots( @@ -194,16 +199,44 @@ LogicalResult mlir::tryToDestructureMemorySlots( SROAStatistics statistics) { bool destructuredAny = false; - for (DestructurableAllocationOpInterface allocator : allocators) { - for (DestructurableMemorySlot slot : allocator.getDestructurableSlots()) { - std::optional info = - computeDestructuringInfo(slot, dataLayout); - if (!info) - continue; + SmallVector workList(allocators.begin(), + allocators.end()); + SmallVector newWorkList; + newWorkList.reserve(allocators.size()); + // Destructuring a slot can allow for further destructuring of other + // slots, destructuring is tried until no destructuring succeeds. + while (true) { + bool changesInThisRound = false; + + for (DestructurableAllocationOpInterface allocator : workList) { + bool destructuredAnySlot = false; + for (DestructurableMemorySlot slot : allocator.getDestructurableSlots()) { + std::optional info = + computeDestructuringInfo(slot, dataLayout); + if (!info) + continue; - destructureSlot(slot, allocator, builder, dataLayout, *info, statistics); - destructuredAny = true; + destructureSlot(slot, allocator, builder, dataLayout, *info, + newWorkList, statistics); + destructuredAnySlot = true; + + // A break is required, since destructuring a slot may invalidate the + // remaning slots of an allocator. + break; + } + if (!destructuredAnySlot) + newWorkList.push_back(allocator); + changesInThisRound |= destructuredAnySlot; } + + if (!changesInThisRound) + break; + destructuredAny |= changesInThisRound; + + // Swap the vector's backing memory and clear the entries in newWorkList + // afterwards. This ensures that additional heap allocations can be avoided. + workList.swap(newWorkList); + newWorkList.clear(); } return success(destructuredAny); @@ -230,23 +263,16 @@ struct SROA : public impl::SROABase { OpBuilder builder(®ion.front(), region.front().begin()); - // Destructuring a slot can allow for further destructuring of other - // slots, destructuring is tried until no destructuring succeeds. - while (true) { - SmallVector allocators; - // Build a list of allocators to attempt to destructure the slots of. - // TODO: Update list on the fly to avoid repeated visiting of the same - // allocators. - region.walk([&](DestructurableAllocationOpInterface allocator) { - allocators.emplace_back(allocator); - }); - - if (failed(tryToDestructureMemorySlots(allocators, builder, dataLayout, - statistics))) - break; + SmallVector allocators; + // Build a list of allocators to attempt to destructure the slots of. + region.walk([&](DestructurableAllocationOpInterface allocator) { + allocators.emplace_back(allocator); + }); + // Attempt to destructure as many slots as possible. + if (succeeded(tryToDestructureMemorySlots(allocators, builder, dataLayout, + statistics))) changed = true; - } } if (!changed) markAllAnalysesPreserved(); diff --git a/mlir/test/Transforms/sroa.mlir b/mlir/test/Transforms/sroa.mlir new file mode 100644 index 000000000000..c9e80a6cf8dd --- /dev/null +++ b/mlir/test/Transforms/sroa.mlir @@ -0,0 +1,31 @@ +// RUN: mlir-opt %s --pass-pipeline='builtin.module(func.func(sroa))' --split-input-file | FileCheck %s + +// Verifies that allocators with mutliple slots are handled properly. + +// CHECK-LABEL: func.func @multi_slot_alloca +func.func @multi_slot_alloca() -> (i32, i32) { + %0 = arith.constant 0 : index + %1, %2 = test.multi_slot_alloca : () -> (memref<2xi32>, memref<4xi32>) + // CHECK-COUNT-2: test.multi_slot_alloca : () -> memref + %3 = memref.load %1[%0] {first}: memref<2xi32> + %4 = memref.load %2[%0] {second} : memref<4xi32> + return %3, %4 : i32, i32 +} + +// ----- + +// Verifies that a multi slot allocator can be partially destructured. + +func.func private @consumer(memref<2xi32>) + +// CHECK-LABEL: func.func @multi_slot_alloca_only_second +func.func @multi_slot_alloca_only_second() -> (i32, i32) { + %0 = arith.constant 0 : index + // CHECK: test.multi_slot_alloca : () -> memref<2xi32> + // CHECK: test.multi_slot_alloca : () -> memref + %1, %2 = test.multi_slot_alloca : () -> (memref<2xi32>, memref<4xi32>) + func.call @consumer(%1) : (memref<2xi32>) -> () + %3 = memref.load %1[%0] : memref<2xi32> + %4 = memref.load %2[%0] : memref<4xi32> + return %3, %4 : i32, i32 +} diff --git a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp index d22d48b139a0..0b676db18af4 100644 --- a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp +++ b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp @@ -1199,22 +1199,20 @@ void TestMultiSlotAlloca::handleBlockArgument(const MemorySlot &slot, // Not relevant for testing. } -std::optional -TestMultiSlotAlloca::handlePromotionComplete(const MemorySlot &slot, - Value defaultValue, - OpBuilder &builder) { - if (defaultValue && defaultValue.use_empty()) - defaultValue.getDefiningOp()->erase(); +/// Creates a new TestMultiSlotAlloca operation, just without the `slot`. +static std::optional +createNewMultiAllocaWithoutSlot(const MemorySlot &slot, OpBuilder &builder, + TestMultiSlotAlloca oldOp) { - if (getNumResults() == 1) { - erase(); + if (oldOp.getNumResults() == 1) { + oldOp.erase(); return std::nullopt; } SmallVector newTypes; SmallVector remainingValues; - for (Value oldResult : getResults()) { + for (Value oldResult : oldOp.getResults()) { if (oldResult == slot.ptr) continue; remainingValues.push_back(oldResult); @@ -1222,12 +1220,68 @@ TestMultiSlotAlloca::handlePromotionComplete(const MemorySlot &slot, } OpBuilder::InsertionGuard guard(builder); - builder.setInsertionPoint(*this); - auto replacement = builder.create(getLoc(), newTypes); + builder.setInsertionPoint(oldOp); + auto replacement = + builder.create(oldOp->getLoc(), newTypes); for (auto [oldResult, newResult] : llvm::zip_equal(remainingValues, replacement.getResults())) oldResult.replaceAllUsesWith(newResult); - erase(); + oldOp.erase(); return replacement; } + +std::optional +TestMultiSlotAlloca::handlePromotionComplete(const MemorySlot &slot, + Value defaultValue, + OpBuilder &builder) { + if (defaultValue && defaultValue.use_empty()) + defaultValue.getDefiningOp()->erase(); + return createNewMultiAllocaWithoutSlot(slot, builder, *this); +} + +SmallVector +TestMultiSlotAlloca::getDestructurableSlots() { + SmallVector slots; + for (Value result : getResults()) { + auto memrefType = cast(result.getType()); + auto destructurable = dyn_cast(memrefType); + if (!destructurable) + continue; + + std::optional> destructuredType = + destructurable.getSubelementIndexMap(); + if (!destructuredType) + continue; + slots.emplace_back( + DestructurableMemorySlot{{result, memrefType}, *destructuredType}); + } + return slots; +} + +DenseMap TestMultiSlotAlloca::destructure( + const DestructurableMemorySlot &slot, + const SmallPtrSetImpl &usedIndices, OpBuilder &builder, + SmallVectorImpl &newAllocators) { + OpBuilder::InsertionGuard guard(builder); + builder.setInsertionPointAfter(*this); + + DenseMap slotMap; + + for (Attribute usedIndex : usedIndices) { + Type elemType = slot.elementPtrs.lookup(usedIndex); + MemRefType elemPtr = MemRefType::get({}, elemType); + auto subAlloca = builder.create(getLoc(), elemPtr); + newAllocators.push_back(subAlloca); + slotMap.try_emplace(usedIndex, + {subAlloca.getResult(0), elemType}); + } + + return slotMap; +} + +std::optional +TestMultiSlotAlloca::handleDestructuringComplete( + const DestructurableMemorySlot &slot, OpBuilder &builder) { + return createNewMultiAllocaWithoutSlot(slot, builder, *this); +} diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td index e16ea2407314..7fc3d22d1895 100644 --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -3169,11 +3169,12 @@ def TestOpOptionallyImplementingInterface } //===----------------------------------------------------------------------===// -// Test Mem2Reg +// Test Mem2Reg & SROA //===----------------------------------------------------------------------===// def TestMultiSlotAlloca : TEST_Op<"multi_slot_alloca", - [DeclareOpInterfaceMethods]> { + [DeclareOpInterfaceMethods, + DeclareOpInterfaceMethods]> { let results = (outs Variadic>:$results); let assemblyFormat = "attr-dict `:` functional-type(operands, results)"; } -- GitLab From 346f2b76246a46d5e634dfcf0004d72ac5127f8e Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Tue, 14 May 2024 12:30:34 +0400 Subject: [PATCH 194/578] [lldb] Fix the test TestGdbRemotePlatformFile when run with a remote target (#91918) It is necessary to transfer the test file to/from the really remote target (for example Windows host and Linux target). Also ignore chmod check in case of the Windows host. --- .../lldb-server/TestGdbRemotePlatformFile.py | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py b/lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py index 4c8ce01e8ba3..2e1c72ee56d7 100644 --- a/lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py +++ b/lldb/test/API/tools/lldb-server/TestGdbRemotePlatformFile.py @@ -1,6 +1,7 @@ # lldb test suite imports from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import TestBase +from lldbsuite.test import lldbutil # gdb-remote-specific imports import lldbgdbserverutils @@ -117,6 +118,7 @@ class TestGdbRemotePlatformFile(GdbRemoteTestCaseBase): temp_file = self.getBuildArtifact("test") with open(temp_file, "wb"): pass + temp_file = lldbutil.install_to_target(self, temp_file) # attempt to open the file with O_CREAT|O_EXCL self.do_handshake() @@ -140,6 +142,7 @@ class TestGdbRemotePlatformFile(GdbRemoteTestCaseBase): test_data = b"test data of some length" with open(temp_path, "wb") as temp_file: temp_file.write(test_data) + temp_path = lldbutil.install_to_target(self, temp_path) self.do_handshake() self.test_sequence.add_log_lines( @@ -167,7 +170,11 @@ class TestGdbRemotePlatformFile(GdbRemoteTestCaseBase): test_mode = 0o751 with open(temp_path, "wb") as temp_file: - os.chmod(temp_file.fileno(), test_mode) + if lldbplatformutil.getHostPlatform() == "windows": + test_mode = 0o700 + else: + os.chmod(temp_file.fileno(), test_mode) + temp_path = lldbutil.install_to_target(self, temp_path) self.do_handshake() self.test_sequence.add_log_lines( @@ -213,6 +220,7 @@ class TestGdbRemotePlatformFile(GdbRemoteTestCaseBase): temp_path = self.getBuildArtifact("test") with open(temp_path, "wb"): pass + temp_path = lldbutil.install_to_target(self, temp_path) self.do_handshake() self.test_sequence.add_log_lines( @@ -244,6 +252,10 @@ class TestGdbRemotePlatformFile(GdbRemoteTestCaseBase): self.expect_gdbremote_sequence() @skipIfWindows + # FIXME: lldb.remote_platform.Install() cannot copy opened temp file on Windows. + # It is possible to use tempfile.NamedTemporaryFile(..., delete=False) and + # delete the temp file manually at the end. + @skipIf(hostoslist=["windows"]) @add_test_categories(["llgs"]) def test_platform_file_fstat(self): server = self.connect_to_debug_monitor() @@ -252,12 +264,13 @@ class TestGdbRemotePlatformFile(GdbRemoteTestCaseBase): with tempfile.NamedTemporaryFile() as temp_file: temp_file.write(b"some test data for stat") temp_file.flush() + temp_path = lldbutil.install_to_target(self, temp_file.name) self.do_handshake() self.test_sequence.add_log_lines( [ "read packet: $vFile:open:%s,0,0#00" - % (binascii.b2a_hex(temp_file.name.encode()).decode(),), + % (binascii.b2a_hex(temp_path.encode()).decode(),), { "direction": "send", "regex": r"^\$F([0-9a-fA-F]+)#[0-9a-fA-F]{2}$", @@ -359,9 +372,12 @@ class TestGdbRemotePlatformFile(GdbRemoteTestCaseBase): if creat: self.assertFalse(os.path.exists(temp_path)) + if lldb.remote_platform: + temp_path = lldbutil.append_to_process_working_directory(self, "test") else: with open(temp_path, "wb") as temp_file: temp_file.write(test_data.encode()) + temp_path = lldbutil.install_to_target(self, temp_path) # open the file for reading self.do_handshake() @@ -448,8 +464,19 @@ class TestGdbRemotePlatformFile(GdbRemoteTestCaseBase): if write: # check if the data was actually written + if lldb.remote_platform: + local_path = self.getBuildArtifact("file_from_target") + error = lldb.remote_platform.Get( + lldb.SBFileSpec(temp_path, False), lldb.SBFileSpec(local_path, True) + ) + self.assertTrue( + error.Success(), + "Reading file {0} failed: {1}".format(temp_path, error), + ) + temp_path = local_path + with open(temp_path, "rb") as temp_file: - if creat: + if creat and lldbplatformutil.getHostPlatform() != "windows": self.assertEqual( os.fstat(temp_file.fileno()).st_mode & 0o7777, 0o640 ) -- GitLab From 632317e9ab5548e991d8974954353033bea62a5b Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 14 May 2024 09:42:49 +0100 Subject: [PATCH 195/578] [VPlan] Add non-poison propagating LogicalAnd VPInstruction opcode. (#91897) Add a new opcode to mode non-poison propagating logical AND operations used when generating edge masks. This follows the similar decision to model Not as dedicated opcode as well, to improve clarity. This also helps to simplify the matchers for https://github.com/llvm/llvm-project/pull/89386. PR: https://github.com/llvm/llvm-project/pull/91897 --- .../Vectorize/LoopVectorizationPlanner.h | 6 ++++++ .../Transforms/Vectorize/LoopVectorize.cpp | 15 +++++++------- llvm/lib/Transforms/Vectorize/VPlan.h | 1 + .../lib/Transforms/Vectorize/VPlanRecipes.cpp | 9 +++++++++ .../LoopVectorize/vplan-printing.ll | 4 ++-- .../vplan-sink-scalars-and-merge.ll | 20 +++++++++---------- 6 files changed, 35 insertions(+), 20 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h index ece2a34f180c..c03c278fcebe 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h @@ -179,6 +179,12 @@ public: VPRecipeWithIRFlags::DisjointFlagsTy(false), DL, Name)); } + VPValue *createLogicalAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL = {}, + const Twine &Name = "") { + return tryInsertInstruction( + new VPInstruction(VPInstruction::LogicalAnd, {LHS, RHS}, DL, Name)); + } + VPValue *createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal, DebugLoc DL = {}, const Twine &Name = "", std::optional FMFs = std::nullopt) { diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 8b4cb5a6658d..ba02c98285c3 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -8011,14 +8011,13 @@ VPValue *VPRecipeBuilder::createEdgeMask(BasicBlock *Src, BasicBlock *Dst) { EdgeMask = Builder.createNot(EdgeMask, BI->getDebugLoc()); if (SrcMask) { // Otherwise block in-mask is all-one, no need to AND. - // The condition is 'SrcMask && EdgeMask', which is equivalent to - // 'select i1 SrcMask, i1 EdgeMask, i1 false'. - // The select version does not introduce new UB if SrcMask is false and - // EdgeMask is poison. Using 'and' here introduces undefined behavior. - VPValue *False = Plan.getOrAddLiveIn( - ConstantInt::getFalse(BI->getCondition()->getType())); - EdgeMask = - Builder.createSelect(SrcMask, EdgeMask, False, BI->getDebugLoc()); + // Use LogicalAnd as it does not propagate poison, i.e. does not introduce + // new UB if SrcMask is false and EdgeMask is poison. Using 'and' here + // introduces undefined behavior. + // The bitwise 'And' of SrcMask and EdgeMask introduces new UB if SrcMask + // is false and EdgeMask is poison. Avoid that by using 'LogicalAnd' + // instead which generates 'select i1 SrcMask, i1 EdgeMask, i1 false'. + EdgeMask = Builder.createLogicalAnd(SrcMask, EdgeMask, BI->getDebugLoc()); } return EdgeMaskCache[Edge] = EdgeMask; diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 0784665efd14..4b3cb15b5e1e 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -1177,6 +1177,7 @@ public: BranchOnCount, BranchOnCond, ComputeReductionResult, + LogicalAnd, // Non-poison propagating logical And. // Add an offset in bytes (second operand) to a base pointer (first // operand). Only generates scalar values (either for the first lane only or // for all lanes, depending on its uses). diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index 140516e08e79..fa634e774b5c 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -137,6 +137,7 @@ bool VPRecipeBase::mayHaveSideEffects() const { case VPInstruction::Not: case VPInstruction::CalculateTripCountMinusVF: case VPInstruction::CanonicalIVIncrementForPart: + case VPInstruction::LogicalAnd: case VPInstruction::PtrAdd: return false; default: @@ -557,6 +558,11 @@ Value *VPInstruction::generatePerPart(VPTransformState &State, unsigned Part) { return ReducedPartRdx; } + case VPInstruction::LogicalAnd: { + Value *A = State.get(getOperand(0), Part); + Value *B = State.get(getOperand(1), Part); + return Builder.CreateLogicalAnd(A, B, Name); + } case VPInstruction::PtrAdd: { assert(vputils::onlyFirstLaneUsed(this) && "can only generate first lane for PtrAdd"); @@ -689,6 +695,9 @@ void VPInstruction::print(raw_ostream &O, const Twine &Indent, case VPInstruction::ComputeReductionResult: O << "compute-reduction-result"; break; + case VPInstruction::LogicalAnd: + O << "logical-and"; + break; case VPInstruction::PtrAdd: O << "ptradd"; break; diff --git a/llvm/test/Transforms/LoopVectorize/vplan-printing.ll b/llvm/test/Transforms/LoopVectorize/vplan-printing.ll index 7056bbe6ba1b..c95f94bddf5e 100644 --- a/llvm/test/Transforms/LoopVectorize/vplan-printing.ll +++ b/llvm/test/Transforms/LoopVectorize/vplan-printing.ll @@ -432,7 +432,7 @@ define void @debug_loc_vpinstruction(ptr nocapture %asd, ptr nocapture %bsd) !db ; CHECK-NEXT: WIDEN ir<%cmp1> = icmp slt ir<%lsd>, ir<100> ; CHECK-NEXT: EMIT vp<[[NOT1:%.+]]> = not ir<%cmp1>, !dbg /tmp/s.c:5:3 ; CHECK-NEXT: WIDEN ir<%cmp2> = icmp sge ir<%lsd>, ir<200> -; CHECK-NEXT: EMIT vp<[[SEL1:%.+]]> = select vp<[[NOT1]]>, ir<%cmp2>, ir, !dbg /tmp/s.c:5:21 +; CHECK-NEXT: EMIT vp<[[SEL1:%.+]]> = logical-and vp<[[NOT1]]>, ir<%cmp2>, !dbg /tmp/s.c:5:21 ; CHECK-NEXT: EMIT vp<[[OR1:%.+]]> = or vp<[[SEL1]]>, ir<%cmp1> ; CHECK-NEXT: Successor(s): pred.sdiv ; CHECK-EMPTY: @@ -453,7 +453,7 @@ define void @debug_loc_vpinstruction(ptr nocapture %asd, ptr nocapture %bsd) !db ; CHECK-EMPTY: ; CHECK-NEXT: if.then.0: ; CHECK-NEXT: EMIT vp<[[NOT2:%.+]]> = not ir<%cmp2> -; CHECK-NEXT: EMIT vp<[[SEL2:%.+]]> = select vp<[[NOT1]]>, vp<[[NOT2]]>, ir +; CHECK-NEXT: EMIT vp<[[SEL2:%.+]]> = logical-and vp<[[NOT1]]>, vp<[[NOT2]]> ; CHECK-NEXT: BLEND ir<%ysd.0> = vp<[[PHI]]> ir<%psd>/vp<[[SEL2]]> ; CHECK-NEXT: vp<[[VEC_PTR2:%.+]]> = vector-pointer ir<%isd> ; CHECK-NEXT: WIDEN store vp<[[VEC_PTR2]]>, ir<%ysd.0> diff --git a/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll b/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll index 108b78a70fa1..1e60e57a5409 100644 --- a/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll +++ b/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll @@ -269,7 +269,7 @@ define void @uniform_gep(i64 %k, ptr noalias %A, ptr noalias %B) { ; CHECK-NEXT: CLONE ir<%lv> = load ir<%gep.A.uniform> ; CHECK-NEXT: WIDEN ir<%cmp> = icmp ult ir<%iv>, ir<%k> ; CHECK-NEXT: EMIT vp<[[NOT2:%.+]]> = not ir<%cmp> -; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = select vp<[[MASK]]>, vp<[[NOT2]]>, ir +; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = logical-and vp<[[MASK]]>, vp<[[NOT2]]> ; CHECK-NEXT: Successor(s): pred.store ; CHECK-EMPTY: ; CHECK-NEXT: pred.store: { @@ -340,7 +340,7 @@ define void @pred_cfg1(i32 %k, i32 %j) { ; CHECK-NEXT: EMIT vp<[[MASK1:%.+]]> = icmp ule ir<%iv>, vp<[[BTC]]> ; CHECK-NEXT: WIDEN ir<%c.1> = icmp ult ir<%iv>, ir<%j> ; CHECK-NEXT: WIDEN ir<%mul> = mul ir<%iv>, ir<10> -; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = select vp<[[MASK1]]>, ir<%c.1>, ir +; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = logical-and vp<[[MASK1]]>, ir<%c.1> ; CHECK-NEXT: Successor(s): pred.load ; CHECK-EMPTY: ; CHECK-NEXT: pred.load: { @@ -362,7 +362,7 @@ define void @pred_cfg1(i32 %k, i32 %j) { ; CHECK-EMPTY: ; CHECK-NEXT: then.0.0: ; CHECK-NEXT: EMIT vp<[[NOT:%.+]]> = not ir<%c.1> -; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = select vp<[[MASK1]]>, vp<[[NOT]]>, ir +; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = logical-and vp<[[MASK1]]>, vp<[[NOT]]> ; CHECK-NEXT: EMIT vp<[[OR:%.+]]> = or vp<[[MASK2]]>, vp<[[MASK3]]> ; CHECK-NEXT: BLEND ir<%p> = ir<0> vp<[[PRED]]>/vp<[[MASK2]]> ; CHECK-NEXT: Successor(s): pred.store @@ -441,7 +441,7 @@ define void @pred_cfg2(i32 %k, i32 %j) { ; CHECK-NEXT: WIDEN ir<%mul> = mul ir<%iv>, ir<10> ; CHECK-NEXT: WIDEN ir<%c.0> = icmp ult ir<%iv>, ir<%j> ; CHECK-NEXT: WIDEN ir<%c.1> = icmp ugt ir<%iv>, ir<%j> -; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = select vp<[[MASK1]]>, ir<%c.0>, ir +; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = logical-and vp<[[MASK1]]>, ir<%c.0> ; CHECK-NEXT: Successor(s): pred.load ; CHECK-EMPTY: ; CHECK-NEXT: pred.load: { @@ -463,10 +463,10 @@ define void @pred_cfg2(i32 %k, i32 %j) { ; CHECK-EMPTY: ; CHECK-NEXT: then.0.0: ; CHECK-NEXT: EMIT vp<[[NOT:%.+]]> = not ir<%c.0> -; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = select vp<[[MASK1]]>, vp<[[NOT]]>, ir +; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = logical-and vp<[[MASK1]]>, vp<[[NOT]]> ; CHECK-NEXT: EMIT vp<[[OR:%.+]]> = or vp<[[MASK2]]>, vp<[[MASK3]]> ; CHECK-NEXT: BLEND ir<%p> = ir<0> vp<[[PRED]]>/vp<[[MASK2]]> -; CHECK-NEXT: EMIT vp<[[MASK4:%.+]]> = select vp<[[OR]]>, ir<%c.1>, ir +; CHECK-NEXT: EMIT vp<[[MASK4:%.+]]> = logical-and vp<[[OR]]>, ir<%c.1> ; CHECK-NEXT: Successor(s): pred.store ; CHECK-EMPTY: ; CHECK-NEXT: pred.store: { @@ -549,7 +549,7 @@ define void @pred_cfg3(i32 %k, i32 %j) { ; CHECK-NEXT: EMIT vp<[[MASK1:%.+]]> = icmp ule ir<%iv>, vp<[[BTC]]> ; CHECK-NEXT: WIDEN ir<%mul> = mul ir<%iv>, ir<10> ; CHECK-NEXT: WIDEN ir<%c.0> = icmp ult ir<%iv>, ir<%j> -; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = select vp<[[MASK1:%.+]]>, ir<%c.0>, ir +; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = logical-and vp<[[MASK1:%.+]]>, ir<%c.0> ; CHECK-NEXT: Successor(s): pred.load ; CHECK-EMPTY: ; CHECK-NEXT: pred.load: { @@ -571,10 +571,10 @@ define void @pred_cfg3(i32 %k, i32 %j) { ; CHECK-EMPTY: ; CHECK-NEXT: then.0.0: ; CHECK-NEXT: EMIT vp<[[NOT:%.+]]> = not ir<%c.0> -; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = select vp<[[MASK1]]>, vp<[[NOT]]>, ir +; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = logical-and vp<[[MASK1]]>, vp<[[NOT]]> ; CHECK-NEXT: EMIT vp<[[MASK4:%.+]]> = or vp<[[MASK2]]>, vp<[[MASK3]]> ; CHECK-NEXT: BLEND ir<%p> = ir<0> vp<[[PRED]]>/vp<[[MASK2]]> -; CHECK-NEXT: EMIT vp<[[MASK5:%.+]]> = select vp<[[MASK4]]>, ir<%c.0>, ir +; CHECK-NEXT: EMIT vp<[[MASK5:%.+]]> = logical-and vp<[[MASK4]]>, ir<%c.0> ; CHECK-NEXT: Successor(s): pred.store ; CHECK-EMPTY: ; CHECK-NEXT: pred.store: { @@ -683,7 +683,7 @@ define void @merge_3_replicate_region(i32 %k, i32 %j) { ; CHECK-EMPTY: ; CHECK-NEXT: loop.3: ; CHECK-NEXT: WIDEN ir<%c.0> = icmp ult ir<%iv>, ir<%j> -; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = select vp<[[MASK]]>, ir<%c.0>, ir +; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = logical-and vp<[[MASK]]>, ir<%c.0> ; CHECK-NEXT: WIDEN ir<%mul> = mul vp<[[PRED1]]>, vp<[[PRED2]]> ; CHECK-NEXT: Successor(s): pred.store ; CHECK-EMPTY: -- GitLab From d9be51ce68b743bde4d73b6858c454e09df341c5 Mon Sep 17 00:00:00 2001 From: Hari Limaye Date: Tue, 14 May 2024 09:49:53 +0100 Subject: [PATCH 196/578] [AArch64] Improve code generation for experimental.cttz.elts (#91505) This patch extends support for lowering the experimental.cttz.elts intrinsic to BRKB + CNTP instruction sequences, using this lowering for all legal predicate types. An unused parameter is also removed from some of the related regression tests. --- .../Target/AArch64/AArch64ISelLowering.cpp | 7 +- .../lib/Target/AArch64/AArch64SVEInstrInfo.td | 36 +++ .../Analysis/CostModel/AArch64/cttz_elts.ll | 72 +++--- .../AArch64/intrinsic-cttz-elts-sve.ll | 212 +++++++++++++----- 4 files changed, 237 insertions(+), 90 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 2aa328e0a127..33cc8ffaf85d 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -1868,7 +1868,12 @@ bool AArch64TargetLowering::shouldExpandGetActiveLaneMask(EVT ResVT, } bool AArch64TargetLowering::shouldExpandCttzElements(EVT VT) const { - return !Subtarget->hasSVEorSME() || VT != MVT::nxv16i1; + if (!Subtarget->hasSVEorSME()) + return true; + + // We can only use the BRKB + CNTP sequence with legal predicate types. + return VT != MVT::nxv16i1 && VT != MVT::nxv8i1 && VT != MVT::nxv4i1 && + VT != MVT::nxv2i1; } void AArch64TargetLowering::addTypeForFixedLengthSVE(MVT VT) { diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index d4405a230613..bd5de628d852 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -2082,6 +2082,18 @@ let Predicates = [HasSVEorSME] in { def : Pat<(i64 (AArch64CttzElts nxv16i1:$Op1)), (CNTP_XPP_B (BRKB_PPzP (PTRUE_B 31), PPR:$Op1), (BRKB_PPzP (PTRUE_B 31), PPR:$Op1))>; + + def : Pat<(i64 (AArch64CttzElts nxv8i1:$Op1)), + (CNTP_XPP_H (BRKB_PPzP (PTRUE_H 31), PPR:$Op1), + (BRKB_PPzP (PTRUE_H 31), PPR:$Op1))>; + + def : Pat<(i64 (AArch64CttzElts nxv4i1:$Op1)), + (CNTP_XPP_S (BRKB_PPzP (PTRUE_S 31), PPR:$Op1), + (BRKB_PPzP (PTRUE_S 31), PPR:$Op1))>; + + def : Pat<(i64 (AArch64CttzElts nxv2i1:$Op1)), + (CNTP_XPP_D (BRKB_PPzP (PTRUE_D 31), PPR:$Op1), + (BRKB_PPzP (PTRUE_D 31), PPR:$Op1))>; } defm INCB_XPiI : sve_int_pred_pattern_a<0b000, "incb", add, int_aarch64_sve_cntb>; @@ -2175,6 +2187,30 @@ let Predicates = [HasSVEorSME] in { (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Op1, sub_32)), sub_32)>; + def : Pat<(i64 (add GPR64:$Op1, (i64 (AArch64CttzElts nxv8i1:$Op2)))), + (INCP_XP_H (BRKB_PPzP (PTRUE_H 31), PPR:$Op2), GPR64:$Op1)>; + + def : Pat<(i32 (add GPR32:$Op1, (trunc (i64 (AArch64CttzElts nxv8i1:$Op2))))), + (EXTRACT_SUBREG (INCP_XP_H (BRKB_PPzP (PTRUE_H 31), PPR:$Op2), + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Op1, sub_32)), + sub_32)>; + + def : Pat<(i64 (add GPR64:$Op1, (i64 (AArch64CttzElts nxv4i1:$Op2)))), + (INCP_XP_S (BRKB_PPzP (PTRUE_S 31), PPR:$Op2), GPR64:$Op1)>; + + def : Pat<(i32 (add GPR32:$Op1, (trunc (i64 (AArch64CttzElts nxv4i1:$Op2))))), + (EXTRACT_SUBREG (INCP_XP_S (BRKB_PPzP (PTRUE_S 31), PPR:$Op2), + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Op1, sub_32)), + sub_32)>; + + def : Pat<(i64 (add GPR64:$Op1, (i64 (AArch64CttzElts nxv2i1:$Op2)))), + (INCP_XP_D (BRKB_PPzP (PTRUE_D 31), PPR:$Op2), GPR64:$Op1)>; + + def : Pat<(i32 (add GPR32:$Op1, (trunc (i64 (AArch64CttzElts nxv2i1:$Op2))))), + (EXTRACT_SUBREG (INCP_XP_D (BRKB_PPzP (PTRUE_D 31), PPR:$Op2), + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Op1, sub_32)), + sub_32)>; + defm INDEX_RR : sve_int_index_rr<"index", AArch64mul_p_oneuse>; defm INDEX_IR : sve_int_index_ir<"index", AArch64mul_p, AArch64mul_p_oneuse>; defm INDEX_RI : sve_int_index_ri<"index">; diff --git a/llvm/test/Analysis/CostModel/AArch64/cttz_elts.ll b/llvm/test/Analysis/CostModel/AArch64/cttz_elts.ll index 01dc086d9385..cc1532ee33dc 100644 --- a/llvm/test/Analysis/CostModel/AArch64/cttz_elts.ll +++ b/llvm/test/Analysis/CostModel/AArch64/cttz_elts.ll @@ -3,14 +3,14 @@ define void @foo_no_vscale_range() { ; CHECK-LABEL: 'foo_no_vscale_range' -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv2i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %res.i64.nxv4i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %res.i64.nxv8i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv2i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv4i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv8i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv16i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv16i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 96 for instruction: %res.i64.nxv32i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv32i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv2i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv4i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %res.i32.nxv8i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv2i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv4i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv8i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv16i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv16i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %res.i32.nxv32i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.v2i1.zip = call i64 @llvm.experimental.cttz.elts.i64.v2i1(<2 x i1> undef, i1 true) @@ -23,14 +23,14 @@ define void @foo_no_vscale_range() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.v8i1.zip = call i32 @llvm.experimental.cttz.elts.i32.v8i1(<8 x i1> undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.v16i1.zip = call i32 @llvm.experimental.cttz.elts.i32.v16i1(<16 x i1> undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %res.i32.v32i1.zip = call i32 @llvm.experimental.cttz.elts.i32.v32i1(<32 x i1> undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv2i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %res.i64.nxv4i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %res.i64.nxv8i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv2i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv4i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv8i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv16i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv16i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 96 for instruction: %res.i64.nxv32i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv32i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv2i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv4i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %res.i32.nxv8i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv2i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv4i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv8i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv16i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv16i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %res.i32.nxv32i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.v2i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.v2i1(<2 x i1> undef, i1 false) @@ -95,24 +95,24 @@ define void @foo_no_vscale_range() { define void @foo_vscale_range_1_16() vscale_range(1,16) { ; CHECK-LABEL: 'foo_vscale_range_1_16' -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv2i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv4i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv8i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv2i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv4i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv8i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv16i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv16i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %res.i64.nxv32i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv32i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv2i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv4i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv8i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv2i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv4i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv8i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv16i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv16i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %res.i32.nxv32i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv2i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv4i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv8i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv2i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv4i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv8i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv16i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv16i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %res.i64.nxv32i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv32i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv2i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv4i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv8i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv2i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv4i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv8i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv16i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv16i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %res.i32.nxv32i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void @@ -144,24 +144,24 @@ define void @foo_vscale_range_1_16() vscale_range(1,16) { define void @foo_vscale_range_1_16384() vscale_range(1,16384) { ; CHECK-LABEL: 'foo_vscale_range_1_16384' -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv2i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv4i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %res.i64.nxv8i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv2i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv4i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv8i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv16i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv16i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %res.i64.nxv32i1.zip = call i64 @llvm.experimental.cttz.elts.i64.nxv32i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv2i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv4i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %res.i32.nxv8i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv2i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv4i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 true) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv8i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv16i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv16i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %res.i32.nxv32i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv2i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i64.nxv4i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %res.i64.nxv8i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv2i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv4i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv8i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv16i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv16i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %res.i64.nxv32i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv32i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv2i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %res.i32.nxv4i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %res.i32.nxv8i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv2i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv4i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv8i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv16i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv16i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %res.i32.nxv32i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void diff --git a/llvm/test/CodeGen/AArch64/intrinsic-cttz-elts-sve.ll b/llvm/test/CodeGen/AArch64/intrinsic-cttz-elts-sve.ll index 9bd2ed240810..211237542a15 100644 --- a/llvm/test/CodeGen/AArch64/intrinsic-cttz-elts-sve.ll +++ b/llvm/test/CodeGen/AArch64/intrinsic-cttz-elts-sve.ll @@ -4,25 +4,6 @@ ; WITH VSCALE RANGE -define i64 @ctz_nxv8i1( %a) #0 { -; CHECK-LABEL: ctz_nxv8i1: -; CHECK: // %bb.0: -; CHECK-NEXT: index z0.h, #0, #-1 -; CHECK-NEXT: mov z1.h, p0/z, #-1 // =0xffffffffffffffff -; CHECK-NEXT: ptrue p0.h -; CHECK-NEXT: cnth x9 -; CHECK-NEXT: inch z0.h -; CHECK-NEXT: and z0.d, z0.d, z1.d -; CHECK-NEXT: and z0.h, z0.h, #0xff -; CHECK-NEXT: umaxv h0, p0, z0.h -; CHECK-NEXT: fmov w8, s0 -; CHECK-NEXT: sub w8, w9, w8 -; CHECK-NEXT: and x0, x8, #0xff -; CHECK-NEXT: ret - %res = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( %a, i1 0) - ret i64 %res -} - define i32 @ctz_nxv32i1( %a) #0 { ; CHECK-LABEL: ctz_nxv32i1: ; CHECK: // %bb.0: @@ -156,41 +137,166 @@ define i64 @vscale_4096_poison( %a) #1 { ret i64 %res } -; NO VSCALE RANGE +; EFFICIENT LOWERING USING BRKB -define i32 @ctz_nxv8i1_no_range( %a) { -; CHECK-LABEL: ctz_nxv8i1_no_range: +define i32 @ctz_nxv2i1( %a) { +; CHECK-LABEL: ctz_nxv2i1: ; CHECK: // %bb.0: -; CHECK-NEXT: index z0.s, #0, #-1 -; CHECK-NEXT: cntw x8 -; CHECK-NEXT: punpklo p1.h, p0.b -; CHECK-NEXT: neg x8, x8 -; CHECK-NEXT: punpkhi p0.h, p0.b -; CHECK-NEXT: cnth x9 -; CHECK-NEXT: mov z1.s, w8 -; CHECK-NEXT: mov z2.s, p1/z, #-1 // =0xffffffffffffffff -; CHECK-NEXT: mov z3.s, p0/z, #-1 // =0xffffffffffffffff -; CHECK-NEXT: ptrue p0.s -; CHECK-NEXT: incw z0.s, all, mul #2 -; CHECK-NEXT: add z1.s, z0.s, z1.s -; CHECK-NEXT: and z0.d, z0.d, z2.d -; CHECK-NEXT: and z1.d, z1.d, z3.d -; CHECK-NEXT: umax z0.s, p0/m, z0.s, z1.s -; CHECK-NEXT: umaxv s0, p0, z0.s -; CHECK-NEXT: fmov w8, s0 -; CHECK-NEXT: sub w0, w9, w8 +; CHECK-NEXT: ptrue p1.d +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: cntp x0, p0, p0.d +; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 +; CHECK-NEXT: ret + %res = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( %a, i1 0) + ret i32 %res +} + +define i32 @ctz_nxv2i1_poison( %a) { +; CHECK-LABEL: ctz_nxv2i1_poison: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.d +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: cntp x0, p0, p0.d +; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 +; CHECK-NEXT: ret + %res = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( %a, i1 1) + ret i32 %res +} + +define i64 @add_i64_ctz_nxv2i1_poison( %a, i64 %b) { +; CHECK-LABEL: add_i64_ctz_nxv2i1_poison: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.d +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: incp x0, p0.d +; CHECK-NEXT: ret + %res = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( %a, i1 1) + %add = add i64 %res, %b + ret i64 %add +} + +define i32 @add_i32_ctz_nxv2i1_poison( %a, i32 %b) { +; CHECK-LABEL: add_i32_ctz_nxv2i1_poison: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.d +; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: incp x0, p0.d +; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 +; CHECK-NEXT: ret + %res = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( %a, i1 1) + %trunc = trunc i64 %res to i32 + %add = add i32 %trunc, %b + ret i32 %add +} + +define i32 @ctz_nxv4i1( %a) { +; CHECK-LABEL: ctz_nxv4i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.s +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: cntp x0, p0, p0.s +; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 +; CHECK-NEXT: ret + %res = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( %a, i1 0) + ret i32 %res +} + +define i32 @ctz_nxv4i1_poison( %a) { +; CHECK-LABEL: ctz_nxv4i1_poison: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.s +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: cntp x0, p0, p0.s +; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 +; CHECK-NEXT: ret + %res = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( %a, i1 1) + ret i32 %res +} + +define i64 @add_i64_ctz_nxv4i1_poison( %a, i64 %b) { +; CHECK-LABEL: add_i64_ctz_nxv4i1_poison: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.s +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: incp x0, p0.s +; CHECK-NEXT: ret + %res = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( %a, i1 1) + %add = add i64 %res, %b + ret i64 %add +} + +define i32 @add_i32_ctz_nxv4i1_poison( %a, i32 %b) { +; CHECK-LABEL: add_i32_ctz_nxv4i1_poison: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.s +; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: incp x0, p0.s +; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 +; CHECK-NEXT: ret + %res = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( %a, i1 1) + %trunc = trunc i64 %res to i32 + %add = add i32 %trunc, %b + ret i32 %add +} + +define i32 @ctz_nxv8i1( %a) { +; CHECK-LABEL: ctz_nxv8i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.h +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: cntp x0, p0, p0.h +; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 ; CHECK-NEXT: ret %res = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( %a, i1 0) ret i32 %res } -; MATCH WITH BRKB + CNTP +define i32 @ctz_nxv8i1_poison( %a) { +; CHECK-LABEL: ctz_nxv8i1_poison: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.h +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: cntp x0, p0, p0.h +; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 +; CHECK-NEXT: ret + %res = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( %a, i1 1) + ret i32 %res +} + +define i64 @add_i64_ctz_nxv8i1_poison( %a, i64 %b) { +; CHECK-LABEL: add_i64_ctz_nxv8i1_poison: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.h +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: incp x0, p0.h +; CHECK-NEXT: ret + %res = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( %a, i1 1) + %add = add i64 %res, %b + ret i64 %add +} -define i32 @ctz_nxv16i1( %pg, %a) { +define i32 @add_i32_ctz_nxv8i1_poison( %a, i32 %b) { +; CHECK-LABEL: add_i32_ctz_nxv8i1_poison: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.h +; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-NEXT: brkb p0.b, p1/z, p0.b +; CHECK-NEXT: incp x0, p0.h +; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 +; CHECK-NEXT: ret + %res = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( %a, i1 1) + %trunc = trunc i64 %res to i32 + %add = add i32 %trunc, %b + ret i32 %add +} + +define i32 @ctz_nxv16i1( %a) { ; CHECK-LABEL: ctz_nxv16i1: ; CHECK: // %bb.0: -; CHECK-NEXT: ptrue p0.b -; CHECK-NEXT: brkb p0.b, p0/z, p1.b +; CHECK-NEXT: ptrue p1.b +; CHECK-NEXT: brkb p0.b, p1/z, p0.b ; CHECK-NEXT: cntp x0, p0, p0.b ; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 ; CHECK-NEXT: ret @@ -198,11 +304,11 @@ define i32 @ctz_nxv16i1( %pg, %a) { ret i32 %res } -define i32 @ctz_nxv16i1_poison( %pg, %a) { +define i32 @ctz_nxv16i1_poison( %a) { ; CHECK-LABEL: ctz_nxv16i1_poison: ; CHECK: // %bb.0: -; CHECK-NEXT: ptrue p0.b -; CHECK-NEXT: brkb p0.b, p0/z, p1.b +; CHECK-NEXT: ptrue p1.b +; CHECK-NEXT: brkb p0.b, p1/z, p0.b ; CHECK-NEXT: cntp x0, p0, p0.b ; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 ; CHECK-NEXT: ret @@ -226,11 +332,11 @@ define i32 @ctz_and_nxv16i1( %pg, %a, %pg, %a, i64 %b) { +define i64 @add_i64_ctz_nxv16i1_poison( %a, i64 %b) { ; CHECK-LABEL: add_i64_ctz_nxv16i1_poison: ; CHECK: // %bb.0: -; CHECK-NEXT: ptrue p0.b -; CHECK-NEXT: brkb p0.b, p0/z, p1.b +; CHECK-NEXT: ptrue p1.b +; CHECK-NEXT: brkb p0.b, p1/z, p0.b ; CHECK-NEXT: incp x0, p0.b ; CHECK-NEXT: ret %res = call i64 @llvm.experimental.cttz.elts.i64.nxv16i1( %a, i1 1) @@ -238,12 +344,12 @@ define i64 @add_i64_ctz_nxv16i1_poison( %pg, %pg, %a, i32 %b) { +define i32 @add_i32_ctz_nxv16i1_poison( %a, i32 %b) { ; CHECK-LABEL: add_i32_ctz_nxv16i1_poison: ; CHECK: // %bb.0: -; CHECK-NEXT: ptrue p0.b +; CHECK-NEXT: ptrue p1.b ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 -; CHECK-NEXT: brkb p0.b, p0/z, p1.b +; CHECK-NEXT: brkb p0.b, p1/z, p0.b ; CHECK-NEXT: incp x0, p0.b ; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 ; CHECK-NEXT: ret -- GitLab From 0bc23f10328e9f61200c33c02391a44abde59b27 Mon Sep 17 00:00:00 2001 From: chuongg3 Date: Tue, 14 May 2024 10:04:21 +0100 Subject: [PATCH 197/578] [AArch64][GlobalISel] Select G_ICMP Zero Instruction (#90054) --- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 46 + llvm/test/CodeGen/AArch64/aarch64-addv.ll | 25 +- llvm/test/CodeGen/AArch64/arm64-vabs.ll | 227 ++-- llvm/test/CodeGen/AArch64/icmp.ll | 1070 +++++------------ .../AArch64/neon-bitwise-instructions.ll | 43 +- .../AArch64/neon-compare-instructions.ll | 532 +++----- 6 files changed, 640 insertions(+), 1303 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index bb32280fe51f..a39e3b7be76d 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -5449,6 +5449,52 @@ defm : SelectSetCCSwapOperands; defm : SelectSetCCSwapOperands; defm : SelectSetCCSwapOperands; +multiclass SelectSetCCZeroRHS { + def : Pat<(v8i8 (InFrag (v8i8 V64:$Rn), immAllZerosV)), + (v8i8 (!cast(INST # v8i8rz) (v8i8 V64:$Rn)))>; + def : Pat<(v16i8 (InFrag (v16i8 V128:$Rn), immAllZerosV)), + (v16i8 (!cast(INST # v16i8rz) (v16i8 V128:$Rn)))>; + def : Pat<(v4i16 (InFrag (v4i16 V64:$Rn), immAllZerosV)), + (v4i16 (!cast(INST # v4i16rz) (v4i16 V64:$Rn)))>; + def : Pat<(v8i16 (InFrag (v8i16 V128:$Rn), immAllZerosV)), + (v8i16 (!cast(INST # v8i16rz) (v8i16 V128:$Rn)))>; + def : Pat<(v2i32 (InFrag (v2i32 V64:$Rn), immAllZerosV)), + (v2i32 (!cast(INST # v2i32rz) (v2i32 V64:$Rn)))>; + def : Pat<(v4i32 (InFrag (v4i32 V128:$Rn), immAllZerosV)), + (v4i32 (!cast(INST # v4i32rz) (v4i32 V128:$Rn)))>; + def : Pat<(v2i64 (InFrag (v2i64 V128:$Rn), immAllZerosV)), + (v2i64 (!cast(INST # v2i64rz) (v2i64 V128:$Rn)))>; +} + +defm : SelectSetCCZeroRHS; +defm : SelectSetCCZeroRHS; +defm : SelectSetCCZeroRHS; +defm : SelectSetCCZeroRHS; +defm : SelectSetCCZeroRHS; + +multiclass SelectSetCCZeroLHS { + def : Pat<(v8i8 (InFrag immAllZerosV, (v8i8 V64:$Rn))), + (v8i8 (!cast(INST # v8i8rz) (v8i8 V64:$Rn)))>; + def : Pat<(v16i8 (InFrag immAllZerosV, (v16i8 V128:$Rn))), + (v16i8 (!cast(INST # v16i8rz) (v16i8 V128:$Rn)))>; + def : Pat<(v4i16 (InFrag immAllZerosV, (v4i16 V64:$Rn))), + (v4i16 (!cast(INST # v4i16rz) (v4i16 V64:$Rn)))>; + def : Pat<(v8i16 (InFrag immAllZerosV, (v8i16 V128:$Rn))), + (v8i16 (!cast(INST # v8i16rz) (v8i16 V128:$Rn)))>; + def : Pat<(v2i32 (InFrag immAllZerosV, (v2i32 V64:$Rn))), + (v2i32 (!cast(INST # v2i32rz) (v2i32 V64:$Rn)))>; + def : Pat<(v4i32 (InFrag immAllZerosV, (v4i32 V128:$Rn))), + (v4i32 (!cast(INST # v4i32rz) (v4i32 V128:$Rn)))>; + def : Pat<(v2i64 (InFrag immAllZerosV, (v2i64 V128:$Rn))), + (v2i64 (!cast(INST # v2i64rz) (v2i64 V128:$Rn)))>; +} + +defm : SelectSetCCZeroLHS; +defm : SelectSetCCZeroLHS; +defm : SelectSetCCZeroLHS; +defm : SelectSetCCZeroLHS; +defm : SelectSetCCZeroLHS; + let Predicates = [HasNEON] in { def : InstAlias<"mov{\t$dst.16b, $src.16b|.16b\t$dst, $src}", (ORRv16i8 V128:$dst, V128:$src, V128:$src), 1>; diff --git a/llvm/test/CodeGen/AArch64/aarch64-addv.ll b/llvm/test/CodeGen/AArch64/aarch64-addv.ll index ee035ec1941d..94b792b887eb 100644 --- a/llvm/test/CodeGen/AArch64/aarch64-addv.ll +++ b/llvm/test/CodeGen/AArch64/aarch64-addv.ll @@ -94,20 +94,19 @@ define i32 @oversized_ADDV_256(ptr noalias nocapture readonly %arg1, ptr noalias ; ; GISEL-LABEL: oversized_ADDV_256: ; GISEL: // %bb.0: // %entry -; GISEL-NEXT: ldr d1, [x0] -; GISEL-NEXT: ldr d2, [x1] -; GISEL-NEXT: movi v0.2d, #0000000000000000 +; GISEL-NEXT: ldr d0, [x0] +; GISEL-NEXT: ldr d1, [x1] +; GISEL-NEXT: ushll v0.8h, v0.8b, #0 ; GISEL-NEXT: ushll v1.8h, v1.8b, #0 -; GISEL-NEXT: ushll v2.8h, v2.8b, #0 -; GISEL-NEXT: usubl v3.4s, v1.4h, v2.4h -; GISEL-NEXT: usubl2 v1.4s, v1.8h, v2.8h -; GISEL-NEXT: cmgt v2.4s, v0.4s, v3.4s -; GISEL-NEXT: cmgt v0.4s, v0.4s, v1.4s -; GISEL-NEXT: neg v4.4s, v3.4s -; GISEL-NEXT: neg v5.4s, v1.4s -; GISEL-NEXT: bsl v2.16b, v4.16b, v3.16b -; GISEL-NEXT: bsl v0.16b, v5.16b, v1.16b -; GISEL-NEXT: add v0.4s, v2.4s, v0.4s +; GISEL-NEXT: usubl v2.4s, v0.4h, v1.4h +; GISEL-NEXT: usubl2 v0.4s, v0.8h, v1.8h +; GISEL-NEXT: cmlt v1.4s, v2.4s, #0 +; GISEL-NEXT: cmlt v3.4s, v0.4s, #0 +; GISEL-NEXT: neg v4.4s, v2.4s +; GISEL-NEXT: neg v5.4s, v0.4s +; GISEL-NEXT: bsl v1.16b, v4.16b, v2.16b +; GISEL-NEXT: bit v0.16b, v5.16b, v3.16b +; GISEL-NEXT: add v0.4s, v1.4s, v0.4s ; GISEL-NEXT: addv s0, v0.4s ; GISEL-NEXT: fmov w0, s0 ; GISEL-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/arm64-vabs.ll b/llvm/test/CodeGen/AArch64/arm64-vabs.ll index d64327656a9e..f7d31a214563 100644 --- a/llvm/test/CodeGen/AArch64/arm64-vabs.ll +++ b/llvm/test/CodeGen/AArch64/arm64-vabs.ll @@ -252,18 +252,17 @@ define i16 @uabd16b_rdx(ptr %a, ptr %b) { ; ; CHECK-GI-LABEL: uabd16b_rdx: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: ldr q1, [x0] -; CHECK-GI-NEXT: ldr q2, [x1] -; CHECK-GI-NEXT: movi.2d v0, #0000000000000000 -; CHECK-GI-NEXT: usubl.8h v3, v1, v2 -; CHECK-GI-NEXT: usubl2.8h v1, v1, v2 -; CHECK-GI-NEXT: cmgt.8h v2, v0, v3 -; CHECK-GI-NEXT: cmgt.8h v0, v0, v1 -; CHECK-GI-NEXT: neg.8h v4, v3 -; CHECK-GI-NEXT: neg.8h v5, v1 -; CHECK-GI-NEXT: bsl.16b v2, v4, v3 -; CHECK-GI-NEXT: bsl.16b v0, v5, v1 -; CHECK-GI-NEXT: add.8h v0, v2, v0 +; CHECK-GI-NEXT: ldr q0, [x0] +; CHECK-GI-NEXT: ldr q1, [x1] +; CHECK-GI-NEXT: usubl.8h v2, v0, v1 +; CHECK-GI-NEXT: usubl2.8h v0, v0, v1 +; CHECK-GI-NEXT: cmlt.8h v1, v2, #0 +; CHECK-GI-NEXT: cmlt.8h v3, v0, #0 +; CHECK-GI-NEXT: neg.8h v4, v2 +; CHECK-GI-NEXT: neg.8h v5, v0 +; CHECK-GI-NEXT: bsl.16b v1, v4, v2 +; CHECK-GI-NEXT: bit.16b v0, v5, v3 +; CHECK-GI-NEXT: add.8h v0, v1, v0 ; CHECK-GI-NEXT: addv.8h h0, v0 ; CHECK-GI-NEXT: fmov w0, s0 ; CHECK-GI-NEXT: ret @@ -290,29 +289,28 @@ define i32 @uabd16b_rdx_i32(<16 x i8> %a, <16 x i8> %b) { ; ; CHECK-GI-LABEL: uabd16b_rdx_i32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: ushll.8h v3, v0, #0 -; CHECK-GI-NEXT: ushll.8h v4, v1, #0 +; CHECK-GI-NEXT: ushll.8h v2, v0, #0 +; CHECK-GI-NEXT: ushll.8h v3, v1, #0 ; CHECK-GI-NEXT: ushll2.8h v0, v0, #0 ; CHECK-GI-NEXT: ushll2.8h v1, v1, #0 -; CHECK-GI-NEXT: movi.2d v2, #0000000000000000 -; CHECK-GI-NEXT: usubl.4s v5, v3, v4 -; CHECK-GI-NEXT: usubl2.4s v3, v3, v4 -; CHECK-GI-NEXT: usubl.4s v4, v0, v1 +; CHECK-GI-NEXT: usubl.4s v4, v2, v3 +; CHECK-GI-NEXT: usubl2.4s v2, v2, v3 +; CHECK-GI-NEXT: usubl.4s v3, v0, v1 ; CHECK-GI-NEXT: usubl2.4s v0, v0, v1 -; CHECK-GI-NEXT: cmgt.4s v1, v2, v5 -; CHECK-GI-NEXT: cmgt.4s v6, v2, v3 -; CHECK-GI-NEXT: neg.4s v16, v5 -; CHECK-GI-NEXT: cmgt.4s v7, v2, v4 -; CHECK-GI-NEXT: cmgt.4s v2, v2, v0 -; CHECK-GI-NEXT: neg.4s v17, v3 -; CHECK-GI-NEXT: neg.4s v18, v4 +; CHECK-GI-NEXT: cmlt.4s v1, v4, #0 +; CHECK-GI-NEXT: cmlt.4s v5, v2, #0 +; CHECK-GI-NEXT: neg.4s v16, v4 +; CHECK-GI-NEXT: cmlt.4s v6, v3, #0 +; CHECK-GI-NEXT: cmlt.4s v7, v0, #0 +; CHECK-GI-NEXT: neg.4s v17, v2 +; CHECK-GI-NEXT: neg.4s v18, v3 ; CHECK-GI-NEXT: neg.4s v19, v0 -; CHECK-GI-NEXT: bsl.16b v1, v16, v5 -; CHECK-GI-NEXT: bit.16b v3, v17, v6 -; CHECK-GI-NEXT: bit.16b v4, v18, v7 -; CHECK-GI-NEXT: bit.16b v0, v19, v2 -; CHECK-GI-NEXT: add.4s v1, v1, v3 -; CHECK-GI-NEXT: add.4s v0, v4, v0 +; CHECK-GI-NEXT: bsl.16b v1, v16, v4 +; CHECK-GI-NEXT: bit.16b v2, v17, v5 +; CHECK-GI-NEXT: bit.16b v3, v18, v6 +; CHECK-GI-NEXT: bit.16b v0, v19, v7 +; CHECK-GI-NEXT: add.4s v1, v1, v2 +; CHECK-GI-NEXT: add.4s v0, v3, v0 ; CHECK-GI-NEXT: add.4s v0, v1, v0 ; CHECK-GI-NEXT: addv.4s s0, v0 ; CHECK-GI-NEXT: fmov w0, s0 @@ -338,29 +336,28 @@ define i32 @sabd16b_rdx_i32(<16 x i8> %a, <16 x i8> %b) { ; ; CHECK-GI-LABEL: sabd16b_rdx_i32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: sshll.8h v3, v0, #0 -; CHECK-GI-NEXT: sshll.8h v4, v1, #0 +; CHECK-GI-NEXT: sshll.8h v2, v0, #0 +; CHECK-GI-NEXT: sshll.8h v3, v1, #0 ; CHECK-GI-NEXT: sshll2.8h v0, v0, #0 ; CHECK-GI-NEXT: sshll2.8h v1, v1, #0 -; CHECK-GI-NEXT: movi.2d v2, #0000000000000000 -; CHECK-GI-NEXT: ssubl.4s v5, v3, v4 -; CHECK-GI-NEXT: ssubl2.4s v3, v3, v4 -; CHECK-GI-NEXT: ssubl.4s v4, v0, v1 +; CHECK-GI-NEXT: ssubl.4s v4, v2, v3 +; CHECK-GI-NEXT: ssubl2.4s v2, v2, v3 +; CHECK-GI-NEXT: ssubl.4s v3, v0, v1 ; CHECK-GI-NEXT: ssubl2.4s v0, v0, v1 -; CHECK-GI-NEXT: cmgt.4s v1, v2, v5 -; CHECK-GI-NEXT: cmgt.4s v6, v2, v3 -; CHECK-GI-NEXT: neg.4s v16, v5 -; CHECK-GI-NEXT: cmgt.4s v7, v2, v4 -; CHECK-GI-NEXT: cmgt.4s v2, v2, v0 -; CHECK-GI-NEXT: neg.4s v17, v3 -; CHECK-GI-NEXT: neg.4s v18, v4 +; CHECK-GI-NEXT: cmlt.4s v1, v4, #0 +; CHECK-GI-NEXT: cmlt.4s v5, v2, #0 +; CHECK-GI-NEXT: neg.4s v16, v4 +; CHECK-GI-NEXT: cmlt.4s v6, v3, #0 +; CHECK-GI-NEXT: cmlt.4s v7, v0, #0 +; CHECK-GI-NEXT: neg.4s v17, v2 +; CHECK-GI-NEXT: neg.4s v18, v3 ; CHECK-GI-NEXT: neg.4s v19, v0 -; CHECK-GI-NEXT: bsl.16b v1, v16, v5 -; CHECK-GI-NEXT: bit.16b v3, v17, v6 -; CHECK-GI-NEXT: bit.16b v4, v18, v7 -; CHECK-GI-NEXT: bit.16b v0, v19, v2 -; CHECK-GI-NEXT: add.4s v1, v1, v3 -; CHECK-GI-NEXT: add.4s v0, v4, v0 +; CHECK-GI-NEXT: bsl.16b v1, v16, v4 +; CHECK-GI-NEXT: bit.16b v2, v17, v5 +; CHECK-GI-NEXT: bit.16b v3, v18, v6 +; CHECK-GI-NEXT: bit.16b v0, v19, v7 +; CHECK-GI-NEXT: add.4s v1, v1, v2 +; CHECK-GI-NEXT: add.4s v0, v3, v0 ; CHECK-GI-NEXT: add.4s v0, v1, v0 ; CHECK-GI-NEXT: addv.4s s0, v0 ; CHECK-GI-NEXT: fmov w0, s0 @@ -391,18 +388,17 @@ define i32 @uabd8h_rdx(ptr %a, ptr %b) { ; ; CHECK-GI-LABEL: uabd8h_rdx: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: ldr q1, [x0] -; CHECK-GI-NEXT: ldr q2, [x1] -; CHECK-GI-NEXT: movi.2d v0, #0000000000000000 -; CHECK-GI-NEXT: usubl.4s v3, v1, v2 -; CHECK-GI-NEXT: usubl2.4s v1, v1, v2 -; CHECK-GI-NEXT: cmgt.4s v2, v0, v3 -; CHECK-GI-NEXT: cmgt.4s v0, v0, v1 -; CHECK-GI-NEXT: neg.4s v4, v3 -; CHECK-GI-NEXT: neg.4s v5, v1 -; CHECK-GI-NEXT: bsl.16b v2, v4, v3 -; CHECK-GI-NEXT: bsl.16b v0, v5, v1 -; CHECK-GI-NEXT: add.4s v0, v2, v0 +; CHECK-GI-NEXT: ldr q0, [x0] +; CHECK-GI-NEXT: ldr q1, [x1] +; CHECK-GI-NEXT: usubl.4s v2, v0, v1 +; CHECK-GI-NEXT: usubl2.4s v0, v0, v1 +; CHECK-GI-NEXT: cmlt.4s v1, v2, #0 +; CHECK-GI-NEXT: cmlt.4s v3, v0, #0 +; CHECK-GI-NEXT: neg.4s v4, v2 +; CHECK-GI-NEXT: neg.4s v5, v0 +; CHECK-GI-NEXT: bsl.16b v1, v4, v2 +; CHECK-GI-NEXT: bit.16b v0, v5, v3 +; CHECK-GI-NEXT: add.4s v0, v1, v0 ; CHECK-GI-NEXT: addv.4s s0, v0 ; CHECK-GI-NEXT: fmov w0, s0 ; CHECK-GI-NEXT: ret @@ -428,15 +424,14 @@ define i32 @sabd8h_rdx(<8 x i16> %a, <8 x i16> %b) { ; ; CHECK-GI-LABEL: sabd8h_rdx: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v2, #0000000000000000 -; CHECK-GI-NEXT: ssubl.4s v3, v0, v1 +; CHECK-GI-NEXT: ssubl.4s v2, v0, v1 ; CHECK-GI-NEXT: ssubl2.4s v0, v0, v1 -; CHECK-GI-NEXT: neg.4s v4, v3 +; CHECK-GI-NEXT: cmlt.4s v1, v2, #0 +; CHECK-GI-NEXT: cmlt.4s v3, v0, #0 +; CHECK-GI-NEXT: neg.4s v4, v2 ; CHECK-GI-NEXT: neg.4s v5, v0 -; CHECK-GI-NEXT: cmgt.4s v1, v2, v3 -; CHECK-GI-NEXT: cmgt.4s v2, v2, v0 -; CHECK-GI-NEXT: bsl.16b v1, v4, v3 -; CHECK-GI-NEXT: bit.16b v0, v5, v2 +; CHECK-GI-NEXT: bsl.16b v1, v4, v2 +; CHECK-GI-NEXT: bit.16b v0, v5, v3 ; CHECK-GI-NEXT: add.4s v0, v1, v0 ; CHECK-GI-NEXT: addv.4s s0, v0 ; CHECK-GI-NEXT: fmov w0, s0 @@ -461,9 +456,8 @@ define i32 @uabdl4s_rdx_i32(<4 x i16> %a, <4 x i16> %b) { ; ; CHECK-GI-LABEL: uabdl4s_rdx_i32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v2, #0000000000000000 ; CHECK-GI-NEXT: usubl.4s v0, v0, v1 -; CHECK-GI-NEXT: cmgt.4s v1, v2, v0 +; CHECK-GI-NEXT: cmlt.4s v1, v0, #0 ; CHECK-GI-NEXT: neg.4s v2, v0 ; CHECK-GI-NEXT: bit.16b v0, v2, v1 ; CHECK-GI-NEXT: addv.4s s0, v0 @@ -494,18 +488,17 @@ define i64 @uabd4s_rdx(ptr %a, ptr %b, i32 %h) { ; ; CHECK-GI-LABEL: uabd4s_rdx: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: ldr q1, [x0] -; CHECK-GI-NEXT: ldr q2, [x1] -; CHECK-GI-NEXT: movi.2d v0, #0000000000000000 -; CHECK-GI-NEXT: usubl.2d v3, v1, v2 -; CHECK-GI-NEXT: usubl2.2d v1, v1, v2 -; CHECK-GI-NEXT: cmgt.2d v2, v0, v3 -; CHECK-GI-NEXT: cmgt.2d v0, v0, v1 -; CHECK-GI-NEXT: neg.2d v4, v3 -; CHECK-GI-NEXT: neg.2d v5, v1 -; CHECK-GI-NEXT: bsl.16b v2, v4, v3 -; CHECK-GI-NEXT: bsl.16b v0, v5, v1 -; CHECK-GI-NEXT: add.2d v0, v2, v0 +; CHECK-GI-NEXT: ldr q0, [x0] +; CHECK-GI-NEXT: ldr q1, [x1] +; CHECK-GI-NEXT: usubl.2d v2, v0, v1 +; CHECK-GI-NEXT: usubl2.2d v0, v0, v1 +; CHECK-GI-NEXT: cmlt.2d v1, v2, #0 +; CHECK-GI-NEXT: cmlt.2d v3, v0, #0 +; CHECK-GI-NEXT: neg.2d v4, v2 +; CHECK-GI-NEXT: neg.2d v5, v0 +; CHECK-GI-NEXT: bsl.16b v1, v4, v2 +; CHECK-GI-NEXT: bit.16b v0, v5, v3 +; CHECK-GI-NEXT: add.2d v0, v1, v0 ; CHECK-GI-NEXT: addp.2d d0, v0 ; CHECK-GI-NEXT: fmov x0, d0 ; CHECK-GI-NEXT: ret @@ -531,15 +524,14 @@ define i64 @sabd4s_rdx(<4 x i32> %a, <4 x i32> %b) { ; ; CHECK-GI-LABEL: sabd4s_rdx: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v2, #0000000000000000 -; CHECK-GI-NEXT: ssubl.2d v3, v0, v1 +; CHECK-GI-NEXT: ssubl.2d v2, v0, v1 ; CHECK-GI-NEXT: ssubl2.2d v0, v0, v1 -; CHECK-GI-NEXT: neg.2d v4, v3 +; CHECK-GI-NEXT: cmlt.2d v1, v2, #0 +; CHECK-GI-NEXT: cmlt.2d v3, v0, #0 +; CHECK-GI-NEXT: neg.2d v4, v2 ; CHECK-GI-NEXT: neg.2d v5, v0 -; CHECK-GI-NEXT: cmgt.2d v1, v2, v3 -; CHECK-GI-NEXT: cmgt.2d v2, v2, v0 -; CHECK-GI-NEXT: bsl.16b v1, v4, v3 -; CHECK-GI-NEXT: bit.16b v0, v5, v2 +; CHECK-GI-NEXT: bsl.16b v1, v4, v2 +; CHECK-GI-NEXT: bit.16b v0, v5, v3 ; CHECK-GI-NEXT: add.2d v0, v1, v0 ; CHECK-GI-NEXT: addp.2d d0, v0 ; CHECK-GI-NEXT: fmov x0, d0 @@ -564,9 +556,8 @@ define i64 @uabdl2d_rdx_i64(<2 x i32> %a, <2 x i32> %b) { ; ; CHECK-GI-LABEL: uabdl2d_rdx_i64: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v2, #0000000000000000 ; CHECK-GI-NEXT: usubl.2d v0, v0, v1 -; CHECK-GI-NEXT: cmgt.2d v1, v2, v0 +; CHECK-GI-NEXT: cmlt.2d v1, v0, #0 ; CHECK-GI-NEXT: neg.2d v2, v0 ; CHECK-GI-NEXT: bit.16b v0, v2, v1 ; CHECK-GI-NEXT: addp.2d d0, v0 @@ -1662,10 +1653,9 @@ define <2 x i32> @abspattern1(<2 x i32> %a) nounwind { ; ; CHECK-GI-LABEL: abspattern1: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v1, #0000000000000000 -; CHECK-GI-NEXT: neg.2s v2, v0 -; CHECK-GI-NEXT: cmge.2s v1, v0, v1 -; CHECK-GI-NEXT: bif.8b v0, v2, v1 +; CHECK-GI-NEXT: neg.2s v1, v0 +; CHECK-GI-NEXT: cmge.2s v2, v0, #0 +; CHECK-GI-NEXT: bif.8b v0, v1, v2 ; CHECK-GI-NEXT: ret %tmp1neg = sub <2 x i32> zeroinitializer, %a %b = icmp sge <2 x i32> %a, zeroinitializer @@ -1682,10 +1672,9 @@ define <4 x i16> @abspattern2(<4 x i16> %a) nounwind { ; ; CHECK-GI-LABEL: abspattern2: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v1, #0000000000000000 -; CHECK-GI-NEXT: neg.4h v2, v0 -; CHECK-GI-NEXT: cmgt.4h v1, v0, v1 -; CHECK-GI-NEXT: bif.8b v0, v2, v1 +; CHECK-GI-NEXT: neg.4h v1, v0 +; CHECK-GI-NEXT: cmgt.4h v2, v0, #0 +; CHECK-GI-NEXT: bif.8b v0, v1, v2 ; CHECK-GI-NEXT: ret %tmp1neg = sub <4 x i16> zeroinitializer, %a %b = icmp sgt <4 x i16> %a, zeroinitializer @@ -1701,10 +1690,9 @@ define <8 x i8> @abspattern3(<8 x i8> %a) nounwind { ; ; CHECK-GI-LABEL: abspattern3: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v1, #0000000000000000 -; CHECK-GI-NEXT: neg.8b v2, v0 -; CHECK-GI-NEXT: cmgt.8b v1, v1, v0 -; CHECK-GI-NEXT: bit.8b v0, v2, v1 +; CHECK-GI-NEXT: neg.8b v1, v0 +; CHECK-GI-NEXT: cmlt.8b v2, v0, #0 +; CHECK-GI-NEXT: bit.8b v0, v1, v2 ; CHECK-GI-NEXT: ret %tmp1neg = sub <8 x i8> zeroinitializer, %a %b = icmp slt <8 x i8> %a, zeroinitializer @@ -1720,10 +1708,9 @@ define <4 x i32> @abspattern4(<4 x i32> %a) nounwind { ; ; CHECK-GI-LABEL: abspattern4: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v1, #0000000000000000 -; CHECK-GI-NEXT: neg.4s v2, v0 -; CHECK-GI-NEXT: cmge.4s v1, v0, v1 -; CHECK-GI-NEXT: bif.16b v0, v2, v1 +; CHECK-GI-NEXT: neg.4s v1, v0 +; CHECK-GI-NEXT: cmge.4s v2, v0, #0 +; CHECK-GI-NEXT: bif.16b v0, v1, v2 ; CHECK-GI-NEXT: ret %tmp1neg = sub <4 x i32> zeroinitializer, %a %b = icmp sge <4 x i32> %a, zeroinitializer @@ -1739,10 +1726,9 @@ define <8 x i16> @abspattern5(<8 x i16> %a) nounwind { ; ; CHECK-GI-LABEL: abspattern5: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v1, #0000000000000000 -; CHECK-GI-NEXT: neg.8h v2, v0 -; CHECK-GI-NEXT: cmgt.8h v1, v0, v1 -; CHECK-GI-NEXT: bif.16b v0, v2, v1 +; CHECK-GI-NEXT: neg.8h v1, v0 +; CHECK-GI-NEXT: cmgt.8h v2, v0, #0 +; CHECK-GI-NEXT: bif.16b v0, v1, v2 ; CHECK-GI-NEXT: ret %tmp1neg = sub <8 x i16> zeroinitializer, %a %b = icmp sgt <8 x i16> %a, zeroinitializer @@ -1758,10 +1744,9 @@ define <16 x i8> @abspattern6(<16 x i8> %a) nounwind { ; ; CHECK-GI-LABEL: abspattern6: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v1, #0000000000000000 -; CHECK-GI-NEXT: neg.16b v2, v0 -; CHECK-GI-NEXT: cmgt.16b v1, v1, v0 -; CHECK-GI-NEXT: bit.16b v0, v2, v1 +; CHECK-GI-NEXT: neg.16b v1, v0 +; CHECK-GI-NEXT: cmlt.16b v2, v0, #0 +; CHECK-GI-NEXT: bit.16b v0, v1, v2 ; CHECK-GI-NEXT: ret %tmp1neg = sub <16 x i8> zeroinitializer, %a %b = icmp slt <16 x i8> %a, zeroinitializer @@ -1777,10 +1762,9 @@ define <2 x i64> @abspattern7(<2 x i64> %a) nounwind { ; ; CHECK-GI-LABEL: abspattern7: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v1, #0000000000000000 -; CHECK-GI-NEXT: neg.2d v2, v0 -; CHECK-GI-NEXT: cmge.2d v1, v1, v0 -; CHECK-GI-NEXT: bit.16b v0, v2, v1 +; CHECK-GI-NEXT: neg.2d v1, v0 +; CHECK-GI-NEXT: cmle.2d v2, v0, #0 +; CHECK-GI-NEXT: bit.16b v0, v1, v2 ; CHECK-GI-NEXT: ret %tmp1neg = sub <2 x i64> zeroinitializer, %a %b = icmp sle <2 x i64> %a, zeroinitializer @@ -1796,9 +1780,8 @@ define <2 x i64> @uabd_i32(<2 x i32> %a, <2 x i32> %b) { ; ; CHECK-GI-LABEL: uabd_i32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi.2d v2, #0000000000000000 ; CHECK-GI-NEXT: ssubl.2d v0, v0, v1 -; CHECK-GI-NEXT: cmgt.2d v1, v2, v0 +; CHECK-GI-NEXT: cmlt.2d v1, v0, #0 ; CHECK-GI-NEXT: neg.2d v2, v0 ; CHECK-GI-NEXT: bit.16b v0, v2, v1 ; CHECK-GI-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/icmp.ll b/llvm/test/CodeGen/AArch64/icmp.ll index 88b2f279ec3e..6baf1a84d407 100644 --- a/llvm/test/CodeGen/AArch64/icmp.ll +++ b/llvm/test/CodeGen/AArch64/icmp.ll @@ -1379,556 +1379,331 @@ entry: ; ===== ICMP Zero RHS ===== define <8 x i1> @icmp_eq_v8i8_Zero_RHS(<8 x i8> %a) { -; CHECK-SD-LABEL: icmp_eq_v8i8_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v8i8_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v8i8_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %c = icmp eq <8 x i8> %a, ret <8 x i1> %c } define <16 x i1> @icmp_eq_v16i8_Zero_RHS(<16 x i8> %a) { -; CHECK-SD-LABEL: icmp_eq_v16i8_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v16i8_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v16i8_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %c = icmp eq <16 x i8> %a, ret <16 x i1> %c } define <4 x i1> @icmp_eq_v4i16_Zero_RHS(<4 x i16> %a) { -; CHECK-SD-LABEL: icmp_eq_v4i16_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v4i16_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.4h, v0.4h, v1.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v4i16_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %c = icmp eq <4 x i16> %a, ret <4 x i1> %c } define <8 x i1> @icmp_eq_v8i16_Zero_RHS(<8 x i16> %a) { -; CHECK-SD-LABEL: icmp_eq_v8i16_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v8i16_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.8h, v0.8h, v1.8h -; CHECK-GI-NEXT: xtn v0.8b, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v8i16_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.8h, v0.8h, #0 +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret %c = icmp eq <8 x i16> %a, ret <8 x i1> %c } define <2 x i1> @icmp_eq_v2i32_Zero_RHS(<2 x i32> %a) { -; CHECK-SD-LABEL: icmp_eq_v2i32_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v2i32_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.2s, v0.2s, v1.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v2i32_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %c = icmp eq <2 x i32> %a, ret <2 x i1> %c } define <4 x i1> @icmp_eq_v4i32_Zero_RHS(<4 x i32> %a) { -; CHECK-SD-LABEL: icmp_eq_v4i32_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v4i32_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v4i32_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.4s, v0.4s, #0 +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret %c = icmp eq <4 x i32> %a, ret <4 x i1> %c } define <2 x i1> @icmp_eq_v2i64_Zero_RHS(<2 x i64> %a) { -; CHECK-SD-LABEL: icmp_eq_v2i64_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v2i64_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.2d, v0.2d, v1.2d -; CHECK-GI-NEXT: xtn v0.2s, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v2i64_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.2d, v0.2d, #0 +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret %c = icmp eq <2 x i64> %a, ret <2 x i1> %c } define <8 x i1> @icmp_sge_v8i8_Zero_RHS(<8 x i8> %a) { -; CHECK-SD-LABEL: icmp_sge_v8i8_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v8i8_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v8i8_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %c = icmp sge <8 x i8> %a, ret <8 x i1> %c } define <16 x i1> @icmp_sge_v16i8_Zero_RHS(<16 x i8> %a) { -; CHECK-SD-LABEL: icmp_sge_v16i8_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v16i8_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v16i8_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %c = icmp sge <16 x i8> %a, ret <16 x i1> %c } define <4 x i1> @icmp_sge_v4i16_Zero_RHS(<4 x i16> %a) { -; CHECK-SD-LABEL: icmp_sge_v4i16_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v4i16_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4h, v0.4h, v1.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v4i16_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %c = icmp sge <4 x i16> %a, ret <4 x i1> %c } define <8 x i1> @icmp_sge_v8i16_Zero_RHS(<8 x i16> %a) { -; CHECK-SD-LABEL: icmp_sge_v8i16_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v8i16_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8h, v0.8h, v1.8h -; CHECK-GI-NEXT: xtn v0.8b, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v8i16_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.8h, v0.8h, #0 +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret %c = icmp sge <8 x i16> %a, ret <8 x i1> %c } define <2 x i1> @icmp_sge_v2i32_Zero_RHS(<2 x i32> %a) { -; CHECK-SD-LABEL: icmp_sge_v2i32_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v2i32_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2s, v0.2s, v1.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v2i32_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %c = icmp sge <2 x i32> %a, ret <2 x i1> %c } define <4 x i1> @icmp_sge_v4i32_Zero_RHS(<4 x i32> %a) { -; CHECK-SD-LABEL: icmp_sge_v4i32_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v4i32_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v4i32_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.4s, v0.4s, #0 +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret %c = icmp sge <4 x i32> %a, ret <4 x i1> %c } define <2 x i1> @icmp_sge_v2i64_Zero_RHS(<2 x i64> %a) { -; CHECK-SD-LABEL: icmp_sge_v2i64_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v2i64_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2d, v0.2d, v1.2d -; CHECK-GI-NEXT: xtn v0.2s, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v2i64_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.2d, v0.2d, #0 +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret %c = icmp sge <2 x i64> %a, ret <2 x i1> %c } define <8 x i1> @icmp_sgt_v8i8_Zero_RHS(<8 x i8> %a) { -; CHECK-SD-LABEL: icmp_sgt_v8i8_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v8i8_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v8i8_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %c = icmp sgt <8 x i8> %a, ret <8 x i1> %c } define <16 x i1> @icmp_sgt_v16i8_Zero_RHS(<16 x i8> %a) { -; CHECK-SD-LABEL: icmp_sgt_v16i8_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v16i8_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v16i8_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %c = icmp sgt <16 x i8> %a, ret <16 x i1> %c } define <4 x i1> @icmp_sgt_v4i16_Zero_RHS(<4 x i16> %a) { -; CHECK-SD-LABEL: icmp_sgt_v4i16_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v4i16_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4h, v0.4h, v1.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v4i16_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %c = icmp sgt <4 x i16> %a, ret <4 x i1> %c } define <8 x i1> @icmp_sgt_v8i16_Zero_RHS(<8 x i16> %a) { -; CHECK-SD-LABEL: icmp_sgt_v8i16_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v8i16_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8h, v0.8h, v1.8h -; CHECK-GI-NEXT: xtn v0.8b, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v8i16_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.8h, v0.8h, #0 +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret %c = icmp sgt <8 x i16> %a, ret <8 x i1> %c } define <2 x i1> @icmp_sgt_v2i32_Zero_RHS(<2 x i32> %a) { -; CHECK-SD-LABEL: icmp_sgt_v2i32_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v2i32_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2s, v0.2s, v1.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v2i32_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %c = icmp sgt <2 x i32> %a, ret <2 x i1> %c } define <4 x i1> @icmp_sgt_v4i32_Zero_RHS(<4 x i32> %a) { -; CHECK-SD-LABEL: icmp_sgt_v4i32_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v4i32_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v4i32_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.4s, v0.4s, #0 +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret %c = icmp sgt <4 x i32> %a, ret <4 x i1> %c } define <2 x i1> @icmp_sgt_v2i64_Zero_RHS(<2 x i64> %a) { -; CHECK-SD-LABEL: icmp_sgt_v2i64_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v2i64_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2d, v0.2d, v1.2d -; CHECK-GI-NEXT: xtn v0.2s, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v2i64_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.2d, v0.2d, #0 +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret %c = icmp sgt <2 x i64> %a, ret <2 x i1> %c } define <8 x i1> @icmp_sle_v8i8_Zero_RHS(<8 x i8> %a) { -; CHECK-SD-LABEL: icmp_sle_v8i8_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v8i8_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8b, v1.8b, v0.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v8i8_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %c = icmp sle <8 x i8> %a, ret <8 x i1> %c } define <16 x i1> @icmp_sle_v16i8_Zero_RHS(<16 x i8> %a) { -; CHECK-SD-LABEL: icmp_sle_v16i8_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v16i8_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.16b, v1.16b, v0.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v16i8_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %c = icmp sle <16 x i8> %a, ret <16 x i1> %c } define <4 x i1> @icmp_sle_v4i16_Zero_RHS(<4 x i16> %a) { -; CHECK-SD-LABEL: icmp_sle_v4i16_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v4i16_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4h, v1.4h, v0.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v4i16_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %c = icmp sle <4 x i16> %a, ret <4 x i1> %c } define <8 x i1> @icmp_sle_v8i16_Zero_RHS(<8 x i16> %a) { -; CHECK-SD-LABEL: icmp_sle_v8i16_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v8i16_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8h, v1.8h, v0.8h -; CHECK-GI-NEXT: xtn v0.8b, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v8i16_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.8h, v0.8h, #0 +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret %c = icmp sle <8 x i16> %a, ret <8 x i1> %c } define <2 x i1> @icmp_sle_v2i32_Zero_RHS(<2 x i32> %a) { -; CHECK-SD-LABEL: icmp_sle_v2i32_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v2i32_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2s, v1.2s, v0.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v2i32_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %c = icmp sle <2 x i32> %a, ret <2 x i1> %c } define <4 x i1> @icmp_sle_v4i32_Zero_RHS(<4 x i32> %a) { -; CHECK-SD-LABEL: icmp_sle_v4i32_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v4i32_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4s, v1.4s, v0.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v4i32_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.4s, v0.4s, #0 +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret %c = icmp sle <4 x i32> %a, ret <4 x i1> %c } define <2 x i1> @icmp_sle_v2i64_Zero_RHS(<2 x i64> %a) { -; CHECK-SD-LABEL: icmp_sle_v2i64_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v2i64_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2d, v1.2d, v0.2d -; CHECK-GI-NEXT: xtn v0.2s, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v2i64_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.2d, v0.2d, #0 +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret %c = icmp sle <2 x i64> %a, ret <2 x i1> %c } define <8 x i1> @icmp_slt_v8i8_Zero_RHS(<8 x i8> %a) { -; CHECK-SD-LABEL: icmp_slt_v8i8_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v8i8_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8b, v1.8b, v0.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v8i8_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %c = icmp slt <8 x i8> %a, ret <8 x i1> %c } define <16 x i1> @icmp_slt_v16i8_Zero_RHS(<16 x i8> %a) { -; CHECK-SD-LABEL: icmp_slt_v16i8_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v16i8_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.16b, v1.16b, v0.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v16i8_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %c = icmp slt <16 x i8> %a, ret <16 x i1> %c } define <4 x i1> @icmp_slt_v4i16_Zero_RHS(<4 x i16> %a) { -; CHECK-SD-LABEL: icmp_slt_v4i16_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v4i16_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4h, v1.4h, v0.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v4i16_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %c = icmp slt <4 x i16> %a, ret <4 x i1> %c } define <8 x i1> @icmp_slt_v8i16_Zero_RHS(<8 x i16> %a) { -; CHECK-SD-LABEL: icmp_slt_v8i16_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v8i16_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8h, v1.8h, v0.8h -; CHECK-GI-NEXT: xtn v0.8b, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v8i16_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.8h, v0.8h, #0 +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret %c = icmp slt <8 x i16> %a, ret <8 x i1> %c } define <2 x i1> @icmp_slt_v2i32_Zero_RHS(<2 x i32> %a) { -; CHECK-SD-LABEL: icmp_slt_v2i32_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v2i32_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2s, v1.2s, v0.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v2i32_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %c = icmp slt <2 x i32> %a, ret <2 x i1> %c } define <4 x i1> @icmp_slt_v4i32_Zero_RHS(<4 x i32> %a) { -; CHECK-SD-LABEL: icmp_slt_v4i32_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v4i32_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4s, v1.4s, v0.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v4i32_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.4s, v0.4s, #0 +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret %c = icmp slt <4 x i32> %a, ret <4 x i1> %c } define <2 x i1> @icmp_slt_v2i64_Zero_RHS(<2 x i64> %a) { -; CHECK-SD-LABEL: icmp_slt_v2i64_Zero_RHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v2i64_Zero_RHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2d, v1.2d, v0.2d -; CHECK-GI-NEXT: xtn v0.2s, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v2i64_Zero_RHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.2d, v0.2d, #0 +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret %c = icmp slt <2 x i64> %a, ret <2 x i1> %c } @@ -1936,556 +1711,331 @@ define <2 x i1> @icmp_slt_v2i64_Zero_RHS(<2 x i64> %a) { ; ===== ICMP Zero LHS ===== define <8 x i1> @icmp_eq_v8i8_Zero_LHS(<8 x i8> %a) { -; CHECK-SD-LABEL: icmp_eq_v8i8_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v8i8_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.8b, v1.8b, v0.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v8i8_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %c = icmp eq <8 x i8> , %a ret <8 x i1> %c } define <16 x i1> @icmp_eq_v16i8_Zero_LHS(<16 x i8> %a) { -; CHECK-SD-LABEL: icmp_eq_v16i8_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v16i8_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.16b, v1.16b, v0.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v16i8_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %c = icmp eq <16 x i8> , %a ret <16 x i1> %c } define <4 x i1> @icmp_eq_v4i16_Zero_LHS(<4 x i16> %a) { -; CHECK-SD-LABEL: icmp_eq_v4i16_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v4i16_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.4h, v1.4h, v0.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v4i16_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %c = icmp eq <4 x i16> , %a ret <4 x i1> %c } define <8 x i1> @icmp_eq_v8i16_Zero_LHS(<8 x i16> %a) { -; CHECK-SD-LABEL: icmp_eq_v8i16_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v8i16_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.8h, v1.8h, v0.8h -; CHECK-GI-NEXT: xtn v0.8b, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v8i16_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.8h, v0.8h, #0 +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret %c = icmp eq <8 x i16> , %a ret <8 x i1> %c } define <2 x i1> @icmp_eq_v2i32_Zero_LHS(<2 x i32> %a) { -; CHECK-SD-LABEL: icmp_eq_v2i32_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v2i32_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.2s, v1.2s, v0.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v2i32_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %c = icmp eq <2 x i32> , %a ret <2 x i1> %c } define <4 x i1> @icmp_eq_v4i32_Zero_LHS(<4 x i32> %a) { -; CHECK-SD-LABEL: icmp_eq_v4i32_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v4i32_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.4s, v1.4s, v0.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v4i32_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.4s, v0.4s, #0 +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret %c = icmp eq <4 x i32> , %a ret <4 x i1> %c } define <2 x i1> @icmp_eq_v2i64_Zero_LHS(<2 x i64> %a) { -; CHECK-SD-LABEL: icmp_eq_v2i64_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_eq_v2i64_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.2d, v1.2d, v0.2d -; CHECK-GI-NEXT: xtn v0.2s, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_eq_v2i64_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.2d, v0.2d, #0 +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret %c = icmp eq <2 x i64> , %a ret <2 x i1> %c } define <8 x i1> @icmp_sge_v8i8_Zero_LHS(<8 x i8> %a) { -; CHECK-SD-LABEL: icmp_sge_v8i8_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v8i8_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8b, v1.8b, v0.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v8i8_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %c = icmp sge <8 x i8> , %a ret <8 x i1> %c } define <16 x i1> @icmp_sge_v16i8_Zero_LHS(<16 x i8> %a) { -; CHECK-SD-LABEL: icmp_sge_v16i8_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v16i8_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.16b, v1.16b, v0.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v16i8_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %c = icmp sge <16 x i8> , %a ret <16 x i1> %c } define <4 x i1> @icmp_sge_v4i16_Zero_LHS(<4 x i16> %a) { -; CHECK-SD-LABEL: icmp_sge_v4i16_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v4i16_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4h, v1.4h, v0.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v4i16_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %c = icmp sge <4 x i16> , %a ret <4 x i1> %c } define <8 x i1> @icmp_sge_v8i16_Zero_LHS(<8 x i16> %a) { -; CHECK-SD-LABEL: icmp_sge_v8i16_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v8i16_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8h, v1.8h, v0.8h -; CHECK-GI-NEXT: xtn v0.8b, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v8i16_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.8h, v0.8h, #0 +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret %c = icmp sge <8 x i16> , %a ret <8 x i1> %c } define <2 x i1> @icmp_sge_v2i32_Zero_LHS(<2 x i32> %a) { -; CHECK-SD-LABEL: icmp_sge_v2i32_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v2i32_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2s, v1.2s, v0.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v2i32_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %c = icmp sge <2 x i32> , %a ret <2 x i1> %c } define <4 x i1> @icmp_sge_v4i32_Zero_LHS(<4 x i32> %a) { -; CHECK-SD-LABEL: icmp_sge_v4i32_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v4i32_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4s, v1.4s, v0.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v4i32_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.4s, v0.4s, #0 +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret %c = icmp sge <4 x i32> , %a ret <4 x i1> %c } define <2 x i1> @icmp_sge_v2i64_Zero_LHS(<2 x i64> %a) { -; CHECK-SD-LABEL: icmp_sge_v2i64_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sge_v2i64_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2d, v1.2d, v0.2d -; CHECK-GI-NEXT: xtn v0.2s, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sge_v2i64_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.2d, v0.2d, #0 +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret %c = icmp sge <2 x i64> , %a ret <2 x i1> %c } define <8 x i1> @icmp_sgt_v8i8_Zero_LHS(<8 x i8> %a) { -; CHECK-SD-LABEL: icmp_sgt_v8i8_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v8i8_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8b, v1.8b, v0.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v8i8_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %c = icmp sgt <8 x i8> , %a ret <8 x i1> %c } define <16 x i1> @icmp_sgt_v16i8_Zero_LHS(<16 x i8> %a) { -; CHECK-SD-LABEL: icmp_sgt_v16i8_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v16i8_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.16b, v1.16b, v0.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v16i8_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %c = icmp sgt <16 x i8> , %a ret <16 x i1> %c } define <4 x i1> @icmp_sgt_v4i16_Zero_LHS(<4 x i16> %a) { -; CHECK-SD-LABEL: icmp_sgt_v4i16_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v4i16_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4h, v1.4h, v0.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v4i16_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %c = icmp sgt <4 x i16> , %a ret <4 x i1> %c } define <8 x i1> @icmp_sgt_v8i16_Zero_LHS(<8 x i16> %a) { -; CHECK-SD-LABEL: icmp_sgt_v8i16_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v8i16_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8h, v1.8h, v0.8h -; CHECK-GI-NEXT: xtn v0.8b, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v8i16_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.8h, v0.8h, #0 +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret %c = icmp sgt <8 x i16> , %a ret <8 x i1> %c } define <2 x i1> @icmp_sgt_v2i32_Zero_LHS(<2 x i32> %a) { -; CHECK-SD-LABEL: icmp_sgt_v2i32_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v2i32_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2s, v1.2s, v0.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v2i32_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %c = icmp sgt <2 x i32> , %a ret <2 x i1> %c } define <4 x i1> @icmp_sgt_v4i32_Zero_LHS(<4 x i32> %a) { -; CHECK-SD-LABEL: icmp_sgt_v4i32_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v4i32_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4s, v1.4s, v0.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v4i32_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.4s, v0.4s, #0 +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret %c = icmp sgt <4 x i32> , %a ret <4 x i1> %c } define <2 x i1> @icmp_sgt_v2i64_Zero_LHS(<2 x i64> %a) { -; CHECK-SD-LABEL: icmp_sgt_v2i64_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sgt_v2i64_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2d, v1.2d, v0.2d -; CHECK-GI-NEXT: xtn v0.2s, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sgt_v2i64_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.2d, v0.2d, #0 +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret %c = icmp sgt <2 x i64> , %a ret <2 x i1> %c } define <8 x i1> @icmp_sle_v8i8_Zero_LHS(<8 x i8> %a) { -; CHECK-SD-LABEL: icmp_sle_v8i8_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v8i8_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v8i8_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %c = icmp sle <8 x i8> , %a ret <8 x i1> %c } define <16 x i1> @icmp_sle_v16i8_Zero_LHS(<16 x i8> %a) { -; CHECK-SD-LABEL: icmp_sle_v16i8_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v16i8_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v16i8_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %c = icmp sle <16 x i8> , %a ret <16 x i1> %c } define <4 x i1> @icmp_sle_v4i16_Zero_LHS(<4 x i16> %a) { -; CHECK-SD-LABEL: icmp_sle_v4i16_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v4i16_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4h, v0.4h, v1.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v4i16_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %c = icmp sle <4 x i16> , %a ret <4 x i1> %c } define <8 x i1> @icmp_sle_v8i16_Zero_LHS(<8 x i16> %a) { -; CHECK-SD-LABEL: icmp_sle_v8i16_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v8i16_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8h, v0.8h, v1.8h -; CHECK-GI-NEXT: xtn v0.8b, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v8i16_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.8h, v0.8h, #0 +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret %c = icmp sle <8 x i16> , %a ret <8 x i1> %c } define <2 x i1> @icmp_sle_v2i32_Zero_LHS(<2 x i32> %a) { -; CHECK-SD-LABEL: icmp_sle_v2i32_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v2i32_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2s, v0.2s, v1.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v2i32_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %c = icmp sle <2 x i32> , %a ret <2 x i1> %c } define <4 x i1> @icmp_sle_v4i32_Zero_LHS(<4 x i32> %a) { -; CHECK-SD-LABEL: icmp_sle_v4i32_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v4i32_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v4i32_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.4s, v0.4s, #0 +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret %c = icmp sle <4 x i32> , %a ret <4 x i1> %c } define <2 x i1> @icmp_sle_v2i64_Zero_LHS(<2 x i64> %a) { -; CHECK-SD-LABEL: icmp_sle_v2i64_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_sle_v2i64_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2d, v0.2d, v1.2d -; CHECK-GI-NEXT: xtn v0.2s, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_sle_v2i64_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.2d, v0.2d, #0 +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret %c = icmp sle <2 x i64> , %a ret <2 x i1> %c } define <8 x i1> @icmp_slt_v8i8_Zero_LHS(<8 x i8> %a) { -; CHECK-SD-LABEL: icmp_slt_v8i8_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v8i8_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v8i8_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %c = icmp slt <8 x i8> , %a ret <8 x i1> %c } define <16 x i1> @icmp_slt_v16i8_Zero_LHS(<16 x i8> %a) { -; CHECK-SD-LABEL: icmp_slt_v16i8_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v16i8_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v16i8_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %c = icmp slt <16 x i8> , %a ret <16 x i1> %c } define <4 x i1> @icmp_slt_v4i16_Zero_LHS(<4 x i16> %a) { -; CHECK-SD-LABEL: icmp_slt_v4i16_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v4i16_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4h, v0.4h, v1.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v4i16_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %c = icmp slt <4 x i16> , %a ret <4 x i1> %c } define <8 x i1> @icmp_slt_v8i16_Zero_LHS(<8 x i16> %a) { -; CHECK-SD-LABEL: icmp_slt_v8i16_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v8i16_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8h, v0.8h, v1.8h -; CHECK-GI-NEXT: xtn v0.8b, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v8i16_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.8h, v0.8h, #0 +; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: ret %c = icmp slt <8 x i16> , %a ret <8 x i1> %c } define <2 x i1> @icmp_slt_v2i32_Zero_LHS(<2 x i32> %a) { -; CHECK-SD-LABEL: icmp_slt_v2i32_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v2i32_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2s, v0.2s, v1.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v2i32_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %c = icmp slt <2 x i32> , %a ret <2 x i1> %c } define <4 x i1> @icmp_slt_v4i32_Zero_LHS(<4 x i32> %a) { -; CHECK-SD-LABEL: icmp_slt_v4i32_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v4i32_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v4i32_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.4s, v0.4s, #0 +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret %c = icmp slt <4 x i32> , %a ret <4 x i1> %c } define <2 x i1> @icmp_slt_v2i64_Zero_LHS(<2 x i64> %a) { -; CHECK-SD-LABEL: icmp_slt_v2i64_Zero_LHS: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: icmp_slt_v2i64_Zero_LHS: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2d, v0.2d, v1.2d -; CHECK-GI-NEXT: xtn v0.2s, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: icmp_slt_v2i64_Zero_LHS: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.2d, v0.2d, #0 +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: ret %c = icmp slt <2 x i64> , %a ret <2 x i1> %c } diff --git a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll index 57f220f621cf..50c0c8b11e75 100644 --- a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll +++ b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll @@ -1513,8 +1513,7 @@ define <8 x i8> @vselect_cmpz_ne(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) { ; ; CHECK-GI-LABEL: vselect_cmpz_ne: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v3.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, v3.8b +; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, #0 ; CHECK-GI-NEXT: mvn v0.8b, v0.8b ; CHECK-GI-NEXT: bsl v0.8b, v1.8b, v2.8b ; CHECK-GI-NEXT: ret @@ -1524,38 +1523,23 @@ define <8 x i8> @vselect_cmpz_ne(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) { } define <8 x i8> @vselect_cmpz_eq(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) { -; CHECK-SD-LABEL: vselect_cmpz_eq: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: bsl v0.8b, v1.8b, v2.8b -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: vselect_cmpz_eq: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v3.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, v3.8b -; CHECK-GI-NEXT: bsl v0.8b, v1.8b, v2.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: vselect_cmpz_eq: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.8b, v0.8b, #0 +; CHECK-NEXT: bsl v0.8b, v1.8b, v2.8b +; CHECK-NEXT: ret %cmp = icmp eq <8 x i8> %a, zeroinitializer %d = select <8 x i1> %cmp, <8 x i8> %b, <8 x i8> %c ret <8 x i8> %d } define <8 x i8> @vselect_tst(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) { -; CHECK-SD-LABEL: vselect_tst: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: and v0.8b, v0.8b, v1.8b -; CHECK-SD-NEXT: cmeq v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: bsl v0.8b, v2.8b, v1.8b -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: vselect_tst: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v3.2d, #0000000000000000 -; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, v3.8b -; CHECK-GI-NEXT: bsl v0.8b, v2.8b, v1.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: vselect_tst: +; CHECK: // %bb.0: +; CHECK-NEXT: and v0.8b, v0.8b, v1.8b +; CHECK-NEXT: cmeq v0.8b, v0.8b, #0 +; CHECK-NEXT: bsl v0.8b, v2.8b, v1.8b +; CHECK-NEXT: ret %tmp3 = and <8 x i8> %a, %b %tmp4 = icmp eq <8 x i8> %tmp3, zeroinitializer %d = select <8 x i1> %tmp4, <8 x i8> %c, <8 x i8> %b @@ -1570,9 +1554,8 @@ define <8 x i8> @sext_tst(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) { ; ; CHECK-GI-LABEL: sext_tst: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v2.2d, #0000000000000000 ; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, v2.8b +; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, #0 ; CHECK-GI-NEXT: mvn v0.8b, v0.8b ; CHECK-GI-NEXT: ret %tmp3 = and <8 x i8> %a, %b diff --git a/llvm/test/CodeGen/AArch64/neon-compare-instructions.ll b/llvm/test/CodeGen/AArch64/neon-compare-instructions.ll index dbb5dfebd44a..59958afdd0d1 100644 --- a/llvm/test/CodeGen/AArch64/neon-compare-instructions.ll +++ b/llvm/test/CodeGen/AArch64/neon-compare-instructions.ll @@ -745,9 +745,8 @@ define <8 x i8> @cmtst8xi8(<8 x i8> %A, <8 x i8> %B) { ; ; CHECK-GI-LABEL: cmtst8xi8: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v2.2d, #0000000000000000 ; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, v2.8b +; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, #0 ; CHECK-GI-NEXT: mvn v0.8b, v0.8b ; CHECK-GI-NEXT: ret %tmp3 = and <8 x i8> %A, %B @@ -764,9 +763,8 @@ define <16 x i8> @cmtst16xi8(<16 x i8> %A, <16 x i8> %B) { ; ; CHECK-GI-LABEL: cmtst16xi8: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v2.2d, #0000000000000000 ; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: cmeq v0.16b, v0.16b, v2.16b +; CHECK-GI-NEXT: cmeq v0.16b, v0.16b, #0 ; CHECK-GI-NEXT: mvn v0.16b, v0.16b ; CHECK-GI-NEXT: ret %tmp3 = and <16 x i8> %A, %B @@ -783,9 +781,8 @@ define <4 x i16> @cmtst4xi16(<4 x i16> %A, <4 x i16> %B) { ; ; CHECK-GI-LABEL: cmtst4xi16: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v2.2d, #0000000000000000 ; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: cmeq v0.4h, v0.4h, v2.4h +; CHECK-GI-NEXT: cmeq v0.4h, v0.4h, #0 ; CHECK-GI-NEXT: mvn v0.8b, v0.8b ; CHECK-GI-NEXT: ret %tmp3 = and <4 x i16> %A, %B @@ -802,9 +799,8 @@ define <8 x i16> @cmtst8xi16(<8 x i16> %A, <8 x i16> %B) { ; ; CHECK-GI-LABEL: cmtst8xi16: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v2.2d, #0000000000000000 ; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: cmeq v0.8h, v0.8h, v2.8h +; CHECK-GI-NEXT: cmeq v0.8h, v0.8h, #0 ; CHECK-GI-NEXT: mvn v0.16b, v0.16b ; CHECK-GI-NEXT: ret %tmp3 = and <8 x i16> %A, %B @@ -821,9 +817,8 @@ define <2 x i32> @cmtst2xi32(<2 x i32> %A, <2 x i32> %B) { ; ; CHECK-GI-LABEL: cmtst2xi32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v2.2d, #0000000000000000 ; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: cmeq v0.2s, v0.2s, v2.2s +; CHECK-GI-NEXT: cmeq v0.2s, v0.2s, #0 ; CHECK-GI-NEXT: mvn v0.8b, v0.8b ; CHECK-GI-NEXT: ret %tmp3 = and <2 x i32> %A, %B @@ -840,9 +835,8 @@ define <4 x i32> @cmtst4xi32(<4 x i32> %A, <4 x i32> %B) { ; ; CHECK-GI-LABEL: cmtst4xi32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v2.2d, #0000000000000000 ; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, v2.4s +; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, #0 ; CHECK-GI-NEXT: mvn v0.16b, v0.16b ; CHECK-GI-NEXT: ret %tmp3 = and <4 x i32> %A, %B @@ -859,9 +853,8 @@ define <2 x i64> @cmtst2xi64(<2 x i64> %A, <2 x i64> %B) { ; ; CHECK-GI-LABEL: cmtst2xi64: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v2.2d, #0000000000000000 ; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: cmeq v0.2d, v0.2d, v2.2d +; CHECK-GI-NEXT: cmeq v0.2d, v0.2d, #0 ; CHECK-GI-NEXT: mvn v0.16b, v0.16b ; CHECK-GI-NEXT: ret %tmp3 = and <2 x i64> %A, %B @@ -873,112 +866,70 @@ define <2 x i64> @cmtst2xi64(<2 x i64> %A, <2 x i64> %B) { define <8 x i8> @cmeqz8xi8(<8 x i8> %A) { -; CHECK-SD-LABEL: cmeqz8xi8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmeqz8xi8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmeqz8xi8: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %tmp3 = icmp eq <8 x i8> %A, zeroinitializer %tmp4 = sext <8 x i1> %tmp3 to <8 x i8> ret <8 x i8> %tmp4 } define <16 x i8> @cmeqz16xi8(<16 x i8> %A) { -; CHECK-SD-LABEL: cmeqz16xi8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmeqz16xi8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmeqz16xi8: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %tmp3 = icmp eq <16 x i8> %A, zeroinitializer %tmp4 = sext <16 x i1> %tmp3 to <16 x i8> ret <16 x i8> %tmp4 } define <4 x i16> @cmeqz4xi16(<4 x i16> %A) { -; CHECK-SD-LABEL: cmeqz4xi16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmeqz4xi16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.4h, v0.4h, v1.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmeqz4xi16: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %tmp3 = icmp eq <4 x i16> %A, zeroinitializer %tmp4 = sext <4 x i1> %tmp3 to <4 x i16> ret <4 x i16> %tmp4 } define <8 x i16> @cmeqz8xi16(<8 x i16> %A) { -; CHECK-SD-LABEL: cmeqz8xi16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmeqz8xi16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.8h, v0.8h, v1.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmeqz8xi16: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.8h, v0.8h, #0 +; CHECK-NEXT: ret %tmp3 = icmp eq <8 x i16> %A, zeroinitializer %tmp4 = sext <8 x i1> %tmp3 to <8 x i16> ret <8 x i16> %tmp4 } define <2 x i32> @cmeqz2xi32(<2 x i32> %A) { -; CHECK-SD-LABEL: cmeqz2xi32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmeqz2xi32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.2s, v0.2s, v1.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmeqz2xi32: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %tmp3 = icmp eq <2 x i32> %A, zeroinitializer %tmp4 = sext <2 x i1> %tmp3 to <2 x i32> ret <2 x i32> %tmp4 } define <4 x i32> @cmeqz4xi32(<4 x i32> %A) { -; CHECK-SD-LABEL: cmeqz4xi32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmeqz4xi32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmeqz4xi32: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.4s, v0.4s, #0 +; CHECK-NEXT: ret %tmp3 = icmp eq <4 x i32> %A, zeroinitializer %tmp4 = sext <4 x i1> %tmp3 to <4 x i32> ret <4 x i32> %tmp4 } define <2 x i64> @cmeqz2xi64(<2 x i64> %A) { -; CHECK-SD-LABEL: cmeqz2xi64: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmeq v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmeqz2xi64: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.2d, v0.2d, v1.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmeqz2xi64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmeq v0.2d, v0.2d, #0 +; CHECK-NEXT: ret %tmp3 = icmp eq <2 x i64> %A, zeroinitializer %tmp4 = sext <2 x i1> %tmp3 to <2 x i64> ret <2 x i64> %tmp4 @@ -986,112 +937,70 @@ define <2 x i64> @cmeqz2xi64(<2 x i64> %A) { define <8 x i8> @cmgez8xi8(<8 x i8> %A) { -; CHECK-SD-LABEL: cmgez8xi8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgez8xi8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgez8xi8: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %tmp3 = icmp sge <8 x i8> %A, zeroinitializer %tmp4 = sext <8 x i1> %tmp3 to <8 x i8> ret <8 x i8> %tmp4 } define <16 x i8> @cmgez16xi8(<16 x i8> %A) { -; CHECK-SD-LABEL: cmgez16xi8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgez16xi8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgez16xi8: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %tmp3 = icmp sge <16 x i8> %A, zeroinitializer %tmp4 = sext <16 x i1> %tmp3 to <16 x i8> ret <16 x i8> %tmp4 } define <4 x i16> @cmgez4xi16(<4 x i16> %A) { -; CHECK-SD-LABEL: cmgez4xi16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgez4xi16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4h, v0.4h, v1.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgez4xi16: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %tmp3 = icmp sge <4 x i16> %A, zeroinitializer %tmp4 = sext <4 x i1> %tmp3 to <4 x i16> ret <4 x i16> %tmp4 } define <8 x i16> @cmgez8xi16(<8 x i16> %A) { -; CHECK-SD-LABEL: cmgez8xi16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgez8xi16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8h, v0.8h, v1.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgez8xi16: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.8h, v0.8h, #0 +; CHECK-NEXT: ret %tmp3 = icmp sge <8 x i16> %A, zeroinitializer %tmp4 = sext <8 x i1> %tmp3 to <8 x i16> ret <8 x i16> %tmp4 } define <2 x i32> @cmgez2xi32(<2 x i32> %A) { -; CHECK-SD-LABEL: cmgez2xi32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgez2xi32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2s, v0.2s, v1.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgez2xi32: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %tmp3 = icmp sge <2 x i32> %A, zeroinitializer %tmp4 = sext <2 x i1> %tmp3 to <2 x i32> ret <2 x i32> %tmp4 } define <4 x i32> @cmgez4xi32(<4 x i32> %A) { -; CHECK-SD-LABEL: cmgez4xi32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgez4xi32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgez4xi32: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.4s, v0.4s, #0 +; CHECK-NEXT: ret %tmp3 = icmp sge <4 x i32> %A, zeroinitializer %tmp4 = sext <4 x i1> %tmp3 to <4 x i32> ret <4 x i32> %tmp4 } define <2 x i64> @cmgez2xi64(<2 x i64> %A) { -; CHECK-SD-LABEL: cmgez2xi64: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmge v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgez2xi64: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2d, v0.2d, v1.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgez2xi64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmge v0.2d, v0.2d, #0 +; CHECK-NEXT: ret %tmp3 = icmp sge <2 x i64> %A, zeroinitializer %tmp4 = sext <2 x i1> %tmp3 to <2 x i64> ret <2 x i64> %tmp4 @@ -1324,224 +1233,140 @@ define <2 x i64> @cmgez2xi64_alt2(<2 x i64> %A) { define <8 x i8> @cmgtz8xi8(<8 x i8> %A) { -; CHECK-SD-LABEL: cmgtz8xi8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgtz8xi8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8b, v0.8b, v1.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgtz8xi8: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %tmp3 = icmp sgt <8 x i8> %A, zeroinitializer %tmp4 = sext <8 x i1> %tmp3 to <8 x i8> ret <8 x i8> %tmp4 } define <16 x i8> @cmgtz16xi8(<16 x i8> %A) { -; CHECK-SD-LABEL: cmgtz16xi8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgtz16xi8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.16b, v0.16b, v1.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgtz16xi8: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %tmp3 = icmp sgt <16 x i8> %A, zeroinitializer %tmp4 = sext <16 x i1> %tmp3 to <16 x i8> ret <16 x i8> %tmp4 } define <4 x i16> @cmgtz4xi16(<4 x i16> %A) { -; CHECK-SD-LABEL: cmgtz4xi16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgtz4xi16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4h, v0.4h, v1.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgtz4xi16: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %tmp3 = icmp sgt <4 x i16> %A, zeroinitializer %tmp4 = sext <4 x i1> %tmp3 to <4 x i16> ret <4 x i16> %tmp4 } define <8 x i16> @cmgtz8xi16(<8 x i16> %A) { -; CHECK-SD-LABEL: cmgtz8xi16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgtz8xi16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8h, v0.8h, v1.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgtz8xi16: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.8h, v0.8h, #0 +; CHECK-NEXT: ret %tmp3 = icmp sgt <8 x i16> %A, zeroinitializer %tmp4 = sext <8 x i1> %tmp3 to <8 x i16> ret <8 x i16> %tmp4 } define <2 x i32> @cmgtz2xi32(<2 x i32> %A) { -; CHECK-SD-LABEL: cmgtz2xi32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgtz2xi32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2s, v0.2s, v1.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgtz2xi32: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %tmp3 = icmp sgt <2 x i32> %A, zeroinitializer %tmp4 = sext <2 x i1> %tmp3 to <2 x i32> ret <2 x i32> %tmp4 } define <4 x i32> @cmgtz4xi32(<4 x i32> %A) { -; CHECK-SD-LABEL: cmgtz4xi32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgtz4xi32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgtz4xi32: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.4s, v0.4s, #0 +; CHECK-NEXT: ret %tmp3 = icmp sgt <4 x i32> %A, zeroinitializer %tmp4 = sext <4 x i1> %tmp3 to <4 x i32> ret <4 x i32> %tmp4 } define <2 x i64> @cmgtz2xi64(<2 x i64> %A) { -; CHECK-SD-LABEL: cmgtz2xi64: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmgt v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmgtz2xi64: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2d, v0.2d, v1.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmgtz2xi64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmgt v0.2d, v0.2d, #0 +; CHECK-NEXT: ret %tmp3 = icmp sgt <2 x i64> %A, zeroinitializer %tmp4 = sext <2 x i1> %tmp3 to <2 x i64> ret <2 x i64> %tmp4 } define <8 x i8> @cmlez8xi8(<8 x i8> %A) { -; CHECK-SD-LABEL: cmlez8xi8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmlez8xi8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8b, v1.8b, v0.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmlez8xi8: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %tmp3 = icmp sle <8 x i8> %A, zeroinitializer %tmp4 = sext <8 x i1> %tmp3 to <8 x i8> ret <8 x i8> %tmp4 } define <16 x i8> @cmlez16xi8(<16 x i8> %A) { -; CHECK-SD-LABEL: cmlez16xi8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmlez16xi8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.16b, v1.16b, v0.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmlez16xi8: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %tmp3 = icmp sle <16 x i8> %A, zeroinitializer %tmp4 = sext <16 x i1> %tmp3 to <16 x i8> ret <16 x i8> %tmp4 } define <4 x i16> @cmlez4xi16(<4 x i16> %A) { -; CHECK-SD-LABEL: cmlez4xi16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmlez4xi16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4h, v1.4h, v0.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmlez4xi16: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %tmp3 = icmp sle <4 x i16> %A, zeroinitializer %tmp4 = sext <4 x i1> %tmp3 to <4 x i16> ret <4 x i16> %tmp4 } define <8 x i16> @cmlez8xi16(<8 x i16> %A) { -; CHECK-SD-LABEL: cmlez8xi16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmlez8xi16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.8h, v1.8h, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmlez8xi16: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.8h, v0.8h, #0 +; CHECK-NEXT: ret %tmp3 = icmp sle <8 x i16> %A, zeroinitializer %tmp4 = sext <8 x i1> %tmp3 to <8 x i16> ret <8 x i16> %tmp4 } define <2 x i32> @cmlez2xi32(<2 x i32> %A) { -; CHECK-SD-LABEL: cmlez2xi32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmlez2xi32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2s, v1.2s, v0.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmlez2xi32: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %tmp3 = icmp sle <2 x i32> %A, zeroinitializer %tmp4 = sext <2 x i1> %tmp3 to <2 x i32> ret <2 x i32> %tmp4 } define <4 x i32> @cmlez4xi32(<4 x i32> %A) { -; CHECK-SD-LABEL: cmlez4xi32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmlez4xi32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.4s, v1.4s, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmlez4xi32: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.4s, v0.4s, #0 +; CHECK-NEXT: ret %tmp3 = icmp sle <4 x i32> %A, zeroinitializer %tmp4 = sext <4 x i1> %tmp3 to <4 x i32> ret <4 x i32> %tmp4 } define <2 x i64> @cmlez2xi64(<2 x i64> %A) { -; CHECK-SD-LABEL: cmlez2xi64: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmle v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmlez2xi64: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmge v0.2d, v1.2d, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmlez2xi64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmle v0.2d, v0.2d, #0 +; CHECK-NEXT: ret %tmp3 = icmp sle <2 x i64> %A, zeroinitializer %tmp4 = sext <2 x i1> %tmp3 to <2 x i64> ret <2 x i64> %tmp4 @@ -1661,112 +1486,70 @@ define <2 x i64> @cmlez2xi64_alt(<2 x i64> %A) { } define <8 x i8> @cmltz8xi8(<8 x i8> %A) { -; CHECK-SD-LABEL: cmltz8xi8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.8b, v0.8b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmltz8xi8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8b, v1.8b, v0.8b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmltz8xi8: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.8b, v0.8b, #0 +; CHECK-NEXT: ret %tmp3 = icmp slt <8 x i8> %A, zeroinitializer %tmp4 = sext <8 x i1> %tmp3 to <8 x i8> ret <8 x i8> %tmp4 } define <16 x i8> @cmltz16xi8(<16 x i8> %A) { -; CHECK-SD-LABEL: cmltz16xi8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.16b, v0.16b, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmltz16xi8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.16b, v1.16b, v0.16b -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmltz16xi8: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.16b, v0.16b, #0 +; CHECK-NEXT: ret %tmp3 = icmp slt <16 x i8> %A, zeroinitializer %tmp4 = sext <16 x i1> %tmp3 to <16 x i8> ret <16 x i8> %tmp4 } define <4 x i16> @cmltz4xi16(<4 x i16> %A) { -; CHECK-SD-LABEL: cmltz4xi16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.4h, v0.4h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmltz4xi16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4h, v1.4h, v0.4h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmltz4xi16: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.4h, v0.4h, #0 +; CHECK-NEXT: ret %tmp3 = icmp slt <4 x i16> %A, zeroinitializer %tmp4 = sext <4 x i1> %tmp3 to <4 x i16> ret <4 x i16> %tmp4 } define <8 x i16> @cmltz8xi16(<8 x i16> %A) { -; CHECK-SD-LABEL: cmltz8xi16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.8h, v0.8h, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmltz8xi16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.8h, v1.8h, v0.8h -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmltz8xi16: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.8h, v0.8h, #0 +; CHECK-NEXT: ret %tmp3 = icmp slt <8 x i16> %A, zeroinitializer %tmp4 = sext <8 x i1> %tmp3 to <8 x i16> ret <8 x i16> %tmp4 } define <2 x i32> @cmltz2xi32(<2 x i32> %A) { -; CHECK-SD-LABEL: cmltz2xi32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.2s, v0.2s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmltz2xi32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2s, v1.2s, v0.2s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmltz2xi32: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.2s, v0.2s, #0 +; CHECK-NEXT: ret %tmp3 = icmp slt <2 x i32> %A, zeroinitializer %tmp4 = sext <2 x i1> %tmp3 to <2 x i32> ret <2 x i32> %tmp4 } define <4 x i32> @cmltz4xi32(<4 x i32> %A) { -; CHECK-SD-LABEL: cmltz4xi32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.4s, v0.4s, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmltz4xi32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.4s, v1.4s, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmltz4xi32: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.4s, v0.4s, #0 +; CHECK-NEXT: ret %tmp3 = icmp slt <4 x i32> %A, zeroinitializer %tmp4 = sext <4 x i1> %tmp3 to <4 x i32> ret <4 x i32> %tmp4 } define <2 x i64> @cmltz2xi64(<2 x i64> %A) { -; CHECK-SD-LABEL: cmltz2xi64: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmlt v0.2d, v0.2d, #0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: cmltz2xi64: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmgt v0.2d, v1.2d, v0.2d -; CHECK-GI-NEXT: ret +; CHECK-LABEL: cmltz2xi64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmlt v0.2d, v0.2d, #0 +; CHECK-NEXT: ret %tmp3 = icmp slt <2 x i64> %A, zeroinitializer %tmp4 = sext <2 x i1> %tmp3 to <2 x i64> ret <2 x i64> %tmp4 @@ -1916,8 +1699,7 @@ define <8 x i8> @cmneqz8xi8(<8 x i8> %A) { ; ; CHECK-GI-LABEL: cmneqz8xi8: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, v1.8b +; CHECK-GI-NEXT: cmeq v0.8b, v0.8b, #0 ; CHECK-GI-NEXT: mvn v0.8b, v0.8b ; CHECK-GI-NEXT: ret %tmp3 = icmp ne <8 x i8> %A, zeroinitializer @@ -1933,8 +1715,7 @@ define <16 x i8> @cmneqz16xi8(<16 x i8> %A) { ; ; CHECK-GI-LABEL: cmneqz16xi8: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.16b, v0.16b, v1.16b +; CHECK-GI-NEXT: cmeq v0.16b, v0.16b, #0 ; CHECK-GI-NEXT: mvn v0.16b, v0.16b ; CHECK-GI-NEXT: ret %tmp3 = icmp ne <16 x i8> %A, zeroinitializer @@ -1950,8 +1731,7 @@ define <4 x i16> @cmneqz4xi16(<4 x i16> %A) { ; ; CHECK-GI-LABEL: cmneqz4xi16: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.4h, v0.4h, v1.4h +; CHECK-GI-NEXT: cmeq v0.4h, v0.4h, #0 ; CHECK-GI-NEXT: mvn v0.8b, v0.8b ; CHECK-GI-NEXT: ret %tmp3 = icmp ne <4 x i16> %A, zeroinitializer @@ -1967,8 +1747,7 @@ define <8 x i16> @cmneqz8xi16(<8 x i16> %A) { ; ; CHECK-GI-LABEL: cmneqz8xi16: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.8h, v0.8h, v1.8h +; CHECK-GI-NEXT: cmeq v0.8h, v0.8h, #0 ; CHECK-GI-NEXT: mvn v0.16b, v0.16b ; CHECK-GI-NEXT: ret %tmp3 = icmp ne <8 x i16> %A, zeroinitializer @@ -1984,8 +1763,7 @@ define <2 x i32> @cmneqz2xi32(<2 x i32> %A) { ; ; CHECK-GI-LABEL: cmneqz2xi32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: cmeq v0.2s, v0.2s, #0 ; CHECK-GI-NEXT: mvn v0.8b, v0.8b ; CHECK-GI-NEXT: ret %tmp3 = icmp ne <2 x i32> %A, zeroinitializer @@ -2001,8 +1779,7 @@ define <4 x i32> @cmneqz4xi32(<4 x i32> %A) { ; ; CHECK-GI-LABEL: cmneqz4xi32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, #0 ; CHECK-GI-NEXT: mvn v0.16b, v0.16b ; CHECK-GI-NEXT: ret %tmp3 = icmp ne <4 x i32> %A, zeroinitializer @@ -2018,8 +1795,7 @@ define <2 x i64> @cmneqz2xi64(<2 x i64> %A) { ; ; CHECK-GI-LABEL: cmneqz2xi64: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: movi v1.2d, #0000000000000000 -; CHECK-GI-NEXT: cmeq v0.2d, v0.2d, v1.2d +; CHECK-GI-NEXT: cmeq v0.2d, v0.2d, #0 ; CHECK-GI-NEXT: mvn v0.16b, v0.16b ; CHECK-GI-NEXT: ret %tmp3 = icmp ne <2 x i64> %A, zeroinitializer -- GitLab From 429ce59bd0a7d93ef833939d4a92b56aae103a5a Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Tue, 14 May 2024 13:15:03 +0400 Subject: [PATCH 198/578] [lldb][Windows] Fixed the test TestGdbRemoteMemoryTagging (#92077) Windows path is case insensitive. Tests `test_QMemTags_packets` and `test_qMemTags_packets` will use the same build dir and conflict. Added a suffix to resolve conflicts. --- .../lldb-server/memory-tagging/TestGdbRemoteMemoryTagging.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/test/API/tools/lldb-server/memory-tagging/TestGdbRemoteMemoryTagging.py b/lldb/test/API/tools/lldb-server/memory-tagging/TestGdbRemoteMemoryTagging.py index 584de5e2ef49..6ddd264057c3 100644 --- a/lldb/test/API/tools/lldb-server/memory-tagging/TestGdbRemoteMemoryTagging.py +++ b/lldb/test/API/tools/lldb-server/memory-tagging/TestGdbRemoteMemoryTagging.py @@ -84,7 +84,7 @@ class TestGdbRemoteMemoryTagging(gdbremote_testcase.GdbRemoteTestCaseBase): @skipUnlessArch("aarch64") @skipUnlessPlatform(["linux"]) @skipUnlessAArch64MTELinuxCompiler - def test_qMemTags_packets(self): + def test_tag_read_qMemTags_packets(self): """Test that qMemTags packets are parsed correctly and/or rejected.""" buf_address, page_size = self.prep_memtags_test() @@ -154,7 +154,7 @@ class TestGdbRemoteMemoryTagging(gdbremote_testcase.GdbRemoteTestCaseBase): @skipUnlessArch("aarch64") @skipUnlessPlatform(["linux"]) @skipUnlessAArch64MTELinuxCompiler - def test_QMemTags_packets(self): + def test_tag_write_QMemTags_packets(self): """Test that QMemTags packets are parsed correctly and/or rejected.""" buf_address, page_size = self.prep_memtags_test() -- GitLab From be9b4dab40c36a3d3d9be26498b24efedd8253bf Mon Sep 17 00:00:00 2001 From: Vyacheslav Levytskyy Date: Tue, 14 May 2024 11:35:11 +0200 Subject: [PATCH 199/578] [SPIR-V] Introduce support for 'spirv.Decorations' metadata node in SPIR-V Backend (#91736) This PR is to introduce support for 'spirv.Decorations' metadata node in SPIR-V Backend. See also https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/docs/SPIRVRepresentationInLLVM.rst that describes `spirv.Decorations` as an important part of SPIRV-friendly LLVM IR. --- llvm/docs/SPIRVUsage.rst | 4 +++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 11 +++++++ llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 7 +++++ llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp | 17 ++++++++++ llvm/lib/Target/SPIRV/SPIRVUtils.cpp | 28 +++++++++++++++++ llvm/lib/Target/SPIRV/SPIRVUtils.h | 4 +++ llvm/test/CodeGen/SPIRV/spirv-decoration.ll | 31 +++++++++++++++++++ 8 files changed, 103 insertions(+) create mode 100644 llvm/test/CodeGen/SPIRV/spirv-decoration.ll diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst index a183877c48cb..589ee7646ce1 100644 --- a/llvm/docs/SPIRVUsage.rst +++ b/llvm/docs/SPIRVUsage.rst @@ -253,6 +253,10 @@ SPIR-V backend, along with their descriptions and argument details. - None - `[Type, Vararg]` - Assigns names to types or values, enhancing readability and debuggability of SPIR-V code. Not emitted directly but used for metadata enrichment. + * - `int_spv_assign_decoration` + - None + - `[Type, Metadata]` + - Assigns decoration to values by associating them with metadatas. Not emitted directly but used to support SPIR-V representation in LLVM IR. * - `int_spv_track_constant` - Type - `[Type, Metadata]` diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index 8660782d71d9..931786ab9647 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -14,6 +14,7 @@ let TargetPrefix = "spv" in { def int_spv_assign_type : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>; def int_spv_assign_ptr_type : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg>]>; def int_spv_assign_name : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>; + def int_spv_assign_decoration : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>; def int_spv_track_constant : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_metadata_ty]>; def int_spv_init_global : Intrinsic<[], [llvm_any_ty, llvm_any_ty]>; diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index 0d539b1ed9a8..c00066f5dca6 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -111,6 +111,7 @@ class SPIRVEmitIntrinsics unsigned OperandToReplace, IRBuilder<> &B); void insertPtrCastOrAssignTypeInstr(Instruction *I, IRBuilder<> &B); + void insertSpirvDecorations(Instruction *I, IRBuilder<> &B); void processGlobalValue(GlobalVariable &GV, IRBuilder<> &B); void processParamTypes(Function *F, IRBuilder<> &B); void processParamTypesByFunHeader(Function *F, IRBuilder<> &B); @@ -1116,6 +1117,15 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I, } } +void SPIRVEmitIntrinsics::insertSpirvDecorations(Instruction *I, + IRBuilder<> &B) { + if (MDNode *MD = I->getMetadata("spirv.Decorations")) { + B.SetInsertPoint(I->getNextNode()); + B.CreateIntrinsic(Intrinsic::spv_assign_decoration, {I->getType()}, + {I, MetadataAsValue::get(I->getContext(), MD)}); + } +} + void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I, IRBuilder<> &B) { auto *II = dyn_cast(I); @@ -1287,6 +1297,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) { insertAssignPtrTypeIntrs(I, B); insertAssignTypeIntrs(I, B); insertPtrCastOrAssignTypeInstr(I, B); + insertSpirvDecorations(I, B); } for (auto &I : instructions(Func)) diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp index cebe230d3e8c..0a4e44e2dac7 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp @@ -691,6 +691,13 @@ Register SPIRVGlobalRegistry::buildGlobalVariable( buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn, {static_cast(BuiltInId)}); + // If it's a global variable with "spirv.Decorations" metadata node + // recognize it as a SPIR-V friendly LLVM IR and parse "spirv.Decorations" + // arguments. + MDNode *GVarMD = nullptr; + if (GVar && (GVarMD = GVar->getMetadata("spirv.Decorations")) != nullptr) + buildOpSpirvDecorations(Reg, MIRBuilder, GVarMD); + return Reg; } diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp index 84508fb5fe09..6ee5d90d9afe 100644 --- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp @@ -519,6 +519,22 @@ static void processInstrsWithTypeFolding(MachineFunction &MF, } } +static void insertSpirvDecorations(MachineFunction &MF, MachineIRBuilder MIB) { + SmallVector ToErase; + for (MachineBasicBlock &MBB : MF) { + for (MachineInstr &MI : MBB) { + if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration)) + continue; + MIB.setInsertPt(*MI.getParent(), MI); + buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB, + MI.getOperand(2).getMetadata()); + ToErase.push_back(&MI); + } + } + for (MachineInstr *MI : ToErase) + MI->eraseFromParent(); +} + // Find basic blocks of the switch and replace registers in spv_switch() by its // MBB equivalent. static void processSwitches(MachineFunction &MF, SPIRVGlobalRegistry *GR, @@ -639,6 +655,7 @@ bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) { processSwitches(MF, GR, MIB); processInstrsWithTypeFolding(MF, GR, MIB); removeImplicitFallthroughs(MF, MIB); + insertSpirvDecorations(MF, MIB); return true; } diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp index 871b95a28068..c20f3546a3e5 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp @@ -133,6 +133,34 @@ void buildOpDecorate(Register Reg, MachineInstr &I, const SPIRVInstrInfo &TII, finishBuildOpDecorate(MIB, DecArgs, StrImm); } +void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, + const MDNode *GVarMD) { + for (unsigned I = 0, E = GVarMD->getNumOperands(); I != E; ++I) { + auto *OpMD = dyn_cast(GVarMD->getOperand(I)); + if (!OpMD) + report_fatal_error("Invalid decoration"); + if (OpMD->getNumOperands() == 0) + report_fatal_error("Expect operand(s) of the decoration"); + ConstantInt *DecorationId = + mdconst::dyn_extract(OpMD->getOperand(0)); + if (!DecorationId) + report_fatal_error("Expect SPIR-V operand to be the first " + "element of the decoration"); + auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate) + .addUse(Reg) + .addImm(static_cast(DecorationId->getZExtValue())); + for (unsigned OpI = 1, OpE = OpMD->getNumOperands(); OpI != OpE; ++OpI) { + if (ConstantInt *OpV = + mdconst::dyn_extract(OpMD->getOperand(OpI))) + MIB.addImm(static_cast(OpV->getZExtValue())); + else if (MDString *OpV = dyn_cast(OpMD->getOperand(OpI))) + addStringImm(OpV->getString(), MIB); + else + report_fatal_error("Unexpected operand of the decoration"); + } + } +} + // TODO: maybe the following two functions should be handled in the subtarget // to allow for different OpenCL vs Vulkan handling. unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC) { diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h index 6a91b6e576f9..33cb509dc4a5 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.h +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h @@ -59,6 +59,10 @@ void buildOpDecorate(Register Reg, MachineInstr &I, const SPIRVInstrInfo &TII, const std::vector &DecArgs, StringRef StrImm = ""); +// Add an OpDecorate instruction by "spirv.Decorations" metadata node. +void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, + const MDNode *GVarMD); + // Convert a SPIR-V storage class to the corresponding LLVM IR address space. unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC); diff --git a/llvm/test/CodeGen/SPIRV/spirv-decoration.ll b/llvm/test/CodeGen/SPIRV/spirv-decoration.ll new file mode 100644 index 000000000000..783a2e916c22 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/spirv-decoration.ll @@ -0,0 +1,31 @@ +; RUN: llc -O0 -mtriple=spirv64v1.4-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64v1.4-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: OpName %[[#GV:]] "v" +; CHECK-DAG: OpName %[[#FunBar:]] "bar" +; CHECK-DAG: OpDecorate %[[#GV]] LinkageAttributes "v" Export +; CHECK-DAG: OpDecorate %[[#GV]] Constant +; CHECK-DAG: OpDecorate %[[#Idx:]] UserSemantic "SemanticValue" +; CHECK: %[[#FunBar]] = OpFunction +; CHECK: %[[#Idx]] = OpInBoundsPtrAccessChain + +@v = addrspace(1) global i32 0, !spirv.Decorations !0 + +define spir_kernel void @foo() { +entry: + %pv = load ptr addrspace(1), ptr addrspace(1) @v + store i32 3, ptr addrspace(1) %pv + ret void +} + +define spir_kernel void @bar(ptr addrspace(1) %arg) { +entry: + %idx = getelementptr inbounds i32, ptr addrspace(1) %arg, i64 1, !spirv.Decorations !3 + ret void +} + +!0 = !{!1, !2} +!1 = !{i32 22} ; 22 is Constant decoration +!2 = !{i32 41, !"v", i32 0} ; 41 is LinkageAttributes decoration with 2 extra operands +!3 = !{!4} +!4 = !{i32 5635, !"SemanticValue"} ; 5635 is UserSemantic decoration -- GitLab From 3b8b1022684175e988f043f14596f2dc9b31c6c7 Mon Sep 17 00:00:00 2001 From: aengelke Date: Tue, 14 May 2024 11:38:38 +0200 Subject: [PATCH 200/578] [MC] Make ELFEntrySizeMap a DenseMap (#91728) There is no need for an ordered std::map and also no need to duplicate the section name, which is owned by the ELFSectionKey. Therefore, use a DenseMap instead and don't copy the string. As a further, minor performance optimization, avoid the hash table lookup in isELFGenericMergeableSection when the section name was just added. This slightly improves compilation performance in our application, where we occasionally compile many small object files. --- llvm/include/llvm/MC/MCContext.h | 22 +++------------------- llvm/lib/MC/MCContext.cpp | 12 ++++++++---- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index ef9833cdf2b0..3de41b6a6ea7 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -391,29 +391,13 @@ private: /// Map of currently defined macros. StringMap MacroMap; - struct ELFEntrySizeKey { - std::string SectionName; - unsigned Flags; - unsigned EntrySize; - - ELFEntrySizeKey(StringRef SectionName, unsigned Flags, unsigned EntrySize) - : SectionName(SectionName), Flags(Flags), EntrySize(EntrySize) {} - - bool operator<(const ELFEntrySizeKey &Other) const { - if (SectionName != Other.SectionName) - return SectionName < Other.SectionName; - if (Flags != Other.Flags) - return Flags < Other.Flags; - return EntrySize < Other.EntrySize; - } - }; - // Symbols must be assigned to a section with a compatible entry size and // flags. This map is used to assign unique IDs to sections to distinguish // between sections with identical names but incompatible entry sizes and/or // flags. This can occur when a symbol is explicitly assigned to a section, - // e.g. via __attribute__((section("myname"))). - std::map ELFEntrySizeMap; + // e.g. via __attribute__((section("myname"))). The map key is the tuple + // (section name, flags, entry size). + DenseMap, unsigned> ELFEntrySizeMap; // This set is used to record the generic mergeable section names seen. // These are sections that are created as mergeable e.g. .debug_str. We need diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index 3aee96fdf57f..f027eb65d700 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -620,15 +620,20 @@ void MCContext::recordELFMergeableSectionInfo(StringRef SectionName, unsigned Flags, unsigned UniqueID, unsigned EntrySize) { bool IsMergeable = Flags & ELF::SHF_MERGE; - if (UniqueID == GenericSectionID) + if (UniqueID == GenericSectionID) { ELFSeenGenericMergeableSections.insert(SectionName); + // Minor performance optimization: avoid hash map lookup in + // isELFGenericMergeableSection, which will return true for SectionName. + IsMergeable = true; + } // For mergeable sections or non-mergeable sections with a generic mergeable // section name we enter their Unique ID into the ELFEntrySizeMap so that // compatible globals can be assigned to the same section. + if (IsMergeable || isELFGenericMergeableSection(SectionName)) { ELFEntrySizeMap.insert(std::make_pair( - ELFEntrySizeKey{SectionName, Flags, EntrySize}, UniqueID)); + std::make_tuple(SectionName, Flags, EntrySize), UniqueID)); } } @@ -645,8 +650,7 @@ bool MCContext::isELFGenericMergeableSection(StringRef SectionName) { std::optional MCContext::getELFUniqueIDForEntsize(StringRef SectionName, unsigned Flags, unsigned EntrySize) { - auto I = ELFEntrySizeMap.find( - MCContext::ELFEntrySizeKey{SectionName, Flags, EntrySize}); + auto I = ELFEntrySizeMap.find(std::make_tuple(SectionName, Flags, EntrySize)); return (I != ELFEntrySizeMap.end()) ? std::optional(I->second) : std::nullopt; } -- GitLab From 9f80f437c0b698478c6396c8c44ba094f7199144 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 14 May 2024 10:49:27 +0100 Subject: [PATCH 201/578] [Hexagon] Regenerate asr-rnd.ll + asr-rnd64.ll to show all test checks These are affected by upcoming support for AVG legalization --- llvm/test/CodeGen/Hexagon/asr-rnd.ll | 27 ++++++++++++++++++++++-- llvm/test/CodeGen/Hexagon/asr-rnd64.ll | 29 ++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/llvm/test/CodeGen/Hexagon/asr-rnd.ll b/llvm/test/CodeGen/Hexagon/asr-rnd.ll index bc77e2a7a3ad..cd088dd8f013 100644 --- a/llvm/test/CodeGen/Hexagon/asr-rnd.ll +++ b/llvm/test/CodeGen/Hexagon/asr-rnd.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 ; RUN: llc -march=hexagon < %s | FileCheck %s ; ; Check if we generate rounding-asr instruction. It is equivalent to @@ -6,8 +7,19 @@ target triple = "hexagon" ; Function Attrs: nounwind define i32 @f0(i32 %a0) #0 { +; CHECK-LABEL: f0: +; CHECK: // %bb.0: // %b0 +; CHECK-NEXT: { +; CHECK-NEXT: r0 = asr(r0,#10):rnd +; CHECK-NEXT: r1 = r0 +; CHECK-NEXT: r29 = add(r29,#-8) +; CHECK-NEXT: } +; CHECK-NEXT: { +; CHECK-NEXT: r29 = add(r29,#8) +; CHECK-NEXT: jumpr r31 +; CHECK-NEXT: memw(r29+#4) = r1 +; CHECK-NEXT: } b0: -; CHECK: asr{{.*}}:rnd %v0 = alloca i32, align 4 store i32 %a0, ptr %v0, align 4 %v1 = load i32, ptr %v0, align 4 @@ -19,8 +31,19 @@ b0: ; Function Attrs: nounwind define i64 @f1(i64 %a0) #0 { +; CHECK-LABEL: f1: +; CHECK: // %bb.0: // %b0 +; CHECK-NEXT: { +; CHECK-NEXT: r1:0 = asr(r1:0,#17):rnd +; CHECK-NEXT: r3:2 = combine(r1,r0) +; CHECK-NEXT: r29 = add(r29,#-8) +; CHECK-NEXT: } +; CHECK-NEXT: { +; CHECK-NEXT: r29 = add(r29,#8) +; CHECK-NEXT: jumpr r31 +; CHECK-NEXT: memd(r29+#0) = r3:2 +; CHECK-NEXT: } b0: -; CHECK: asr{{.*}}:rnd %v0 = alloca i64, align 8 store i64 %a0, ptr %v0, align 8 %v1 = load i64, ptr %v0, align 8 diff --git a/llvm/test/CodeGen/Hexagon/asr-rnd64.ll b/llvm/test/CodeGen/Hexagon/asr-rnd64.ll index 4928483e5be6..e32bdff7d764 100644 --- a/llvm/test/CodeGen/Hexagon/asr-rnd64.ll +++ b/llvm/test/CodeGen/Hexagon/asr-rnd64.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 ; RUN: llc -march=hexagon < %s | FileCheck %s ; ; Check if we generate rounding-asr instruction. It is equivalent to @@ -6,8 +7,20 @@ target triple = "hexagon" define i32 @f0(i32 %a0) { +; CHECK-LABEL: f0: +; CHECK: .cfi_startproc +; CHECK-NEXT: // %bb.0: // %b0 +; CHECK-NEXT: { +; CHECK-NEXT: r0 = asr(r0,#10):rnd +; CHECK-NEXT: r1 = r0 +; CHECK-NEXT: r29 = add(r29,#-8) +; CHECK-NEXT: } +; CHECK-NEXT: { +; CHECK-NEXT: r29 = add(r29,#8) +; CHECK-NEXT: jumpr r31 +; CHECK-NEXT: memw(r29+#4) = r1 +; CHECK-NEXT: } b0: -; CHECK: asr{{.*}}:rnd %v0 = alloca i32, align 4 store i32 %a0, ptr %v0, align 4 %v1 = load i32, ptr %v0, align 4 @@ -18,8 +31,20 @@ b0: } define i64 @f1(i64 %a0) { +; CHECK-LABEL: f1: +; CHECK: .cfi_startproc +; CHECK-NEXT: // %bb.0: // %b0 +; CHECK-NEXT: { +; CHECK-NEXT: r1:0 = asr(r1:0,#17):rnd +; CHECK-NEXT: r3:2 = combine(r1,r0) +; CHECK-NEXT: r29 = add(r29,#-8) +; CHECK-NEXT: } +; CHECK-NEXT: { +; CHECK-NEXT: r29 = add(r29,#8) +; CHECK-NEXT: jumpr r31 +; CHECK-NEXT: memd(r29+#0) = r3:2 +; CHECK-NEXT: } b0: -; CHECK: asr{{.*}}:rnd %v0 = alloca i64, align 8 store i64 %a0, ptr %v0, align 8 %v1 = load i64, ptr %v0, align 8 -- GitLab From 995a8af81dc10140109cdd95c44bfb093e8a4c02 Mon Sep 17 00:00:00 2001 From: Dominik Steenken Date: Tue, 14 May 2024 11:50:16 +0200 Subject: [PATCH 202/578] [SystemZ] Add extended mnemonics tests. (#91733) This adds tests for some extended mnemonics of load, branch, and compare-and-trap instructions. --- llvm/test/MC/SystemZ/insn-good-z13.s | 39 +++++++ llvm/test/MC/SystemZ/insn-good-z14.s | 12 +++ llvm/test/MC/SystemZ/insn-good-zEC12.s | 24 +++++ llvm/test/MC/SystemZ/insn-good.s | 143 +++++++++++++++++++++++++ 4 files changed, 218 insertions(+) diff --git a/llvm/test/MC/SystemZ/insn-good-z13.s b/llvm/test/MC/SystemZ/insn-good-z13.s index 37d80c34289b..709a95512c52 100644 --- a/llvm/test/MC/SystemZ/insn-good-z13.s +++ b/llvm/test/MC/SystemZ/insn-good-z13.s @@ -156,6 +156,19 @@ lochino %r11, 32512 lochi %r11, 32512, 15 +#CHECK: lochim %r10, 2766 # encoding: [0xec,0xa4,0x0a,0xce,0x00,0x42] +#CHECK: lochinm %r11, 6862 # encoding: [0xec,0xbb,0x1a,0xce,0x00,0x42] +#CHECK: lochip %r12, 10958 # encoding: [0xec,0xc2,0x2a,0xce,0x00,0x42] +#CHECK: lochiz %r13, 15054 # encoding: [0xec,0xd8,0x3a,0xce,0x00,0x42] +#CHECK: lochinp %r14, 19150 # encoding: [0xec,0xed,0x4a,0xce,0x00,0x42] +#CHECK: lochinz %r15, 23246 # encoding: [0xec,0xf7,0x5a,0xce,0x00,0x42] + lochim %r10, 2766 + lochinm %r11, 6862 + lochip %r12, 10958 + lochiz %r13, 15054 + lochinp %r14, 19150 + lochinz %r15, 23246 + #CHECK: locghi %r11, 42, 0 # encoding: [0xec,0xb0,0x00,0x2a,0x00,0x46] #CHECK: locghio %r11, 42 # encoding: [0xec,0xb1,0x00,0x2a,0x00,0x46] #CHECK: locghih %r11, 42 # encoding: [0xec,0xb2,0x00,0x2a,0x00,0x46] @@ -190,6 +203,19 @@ locghino %r11, 32512 locghi %r11, 32512, 15 +#CHECK: locghim %r10, 2766 # encoding: [0xec,0xa4,0x0a,0xce,0x00,0x46] +#CHECK: locghinm %r11, 6862 # encoding: [0xec,0xbb,0x1a,0xce,0x00,0x46] +#CHECK: locghip %r12, 10958 # encoding: [0xec,0xc2,0x2a,0xce,0x00,0x46] +#CHECK: locghiz %r13, 15054 # encoding: [0xec,0xd8,0x3a,0xce,0x00,0x46] +#CHECK: locghinp %r14, 19150 # encoding: [0xec,0xed,0x4a,0xce,0x00,0x46] +#CHECK: locghinz %r15, 23246 # encoding: [0xec,0xf7,0x5a,0xce,0x00,0x46] + locghim %r10, 2766 + locghinm %r11, 6862 + locghip %r12, 10958 + locghiz %r13, 15054 + locghinp %r14, 19150 + locghinz %r15, 23246 + #CHECK: lochhi %r11, 42, 0 # encoding: [0xec,0xb0,0x00,0x2a,0x00,0x4e] #CHECK: lochhio %r11, 42 # encoding: [0xec,0xb1,0x00,0x2a,0x00,0x4e] #CHECK: lochhih %r11, 42 # encoding: [0xec,0xb2,0x00,0x2a,0x00,0x4e] @@ -224,6 +250,19 @@ lochhino %r11, 32512 lochhi %r11, 32512, 15 +#CHECK: lochhim %r10, 2766 # encoding: [0xec,0xa4,0x0a,0xce,0x00,0x4e] +#CHECK: lochhinm %r11, 6862 # encoding: [0xec,0xbb,0x1a,0xce,0x00,0x4e] +#CHECK: lochhip %r12, 10958 # encoding: [0xec,0xc2,0x2a,0xce,0x00,0x4e] +#CHECK: lochhiz %r13, 15054 # encoding: [0xec,0xd8,0x3a,0xce,0x00,0x4e] +#CHECK: lochhinp %r14, 19150 # encoding: [0xec,0xed,0x4a,0xce,0x00,0x4e] +#CHECK: lochhinz %r15, 23246 # encoding: [0xec,0xf7,0x5a,0xce,0x00,0x4e] + lochhim %r10, 2766 + lochhinm %r11, 6862 + lochhip %r12, 10958 + lochhiz %r13, 15054 + lochhinp %r14, 19150 + lochhinz %r15, 23246 + #CHECK: locfh %r0, 0, 0 # encoding: [0xeb,0x00,0x00,0x00,0x00,0xe0] #CHECK: locfh %r0, 0, 15 # encoding: [0xeb,0x0f,0x00,0x00,0x00,0xe0] #CHECK: locfh %r0, -524288, 0 # encoding: [0xeb,0x00,0x00,0x00,0x80,0xe0] diff --git a/llvm/test/MC/SystemZ/insn-good-z14.s b/llvm/test/MC/SystemZ/insn-good-z14.s index 385fd3ce7d42..af2663bc50c2 100644 --- a/llvm/test/MC/SystemZ/insn-good-z14.s +++ b/llvm/test/MC/SystemZ/insn-good-z14.s @@ -96,9 +96,11 @@ #CHECK: bic 2, 0(%r7) # encoding: [0xe3,0x20,0x70,0x00,0x00,0x47] #CHECK: bih 0(%r15) # encoding: [0xe3,0x20,0xf0,0x00,0x00,0x47] +#CHECK: bip 0(%r14) # encoding: [0xe3,0x20,0xe0,0x00,0x00,0x47] bic 2, 0(%r7) bih 0(%r15) + bip 0(%r14) #CHECK: bic 3, 0(%r7) # encoding: [0xe3,0x30,0x70,0x00,0x00,0x47] #CHECK: binle 0(%r15) # encoding: [0xe3,0x30,0xf0,0x00,0x00,0x47] @@ -108,9 +110,11 @@ #CHECK: bic 4, 0(%r7) # encoding: [0xe3,0x40,0x70,0x00,0x00,0x47] #CHECK: bil 0(%r15) # encoding: [0xe3,0x40,0xf0,0x00,0x00,0x47] +#CHECK: bim 0(%r13) # encoding: [0xe3,0x40,0xd0,0x00,0x00,0x47] bic 4, 0(%r7) bil 0(%r15) + bim 0(%r13) #CHECK: bic 5, 0(%r7) # encoding: [0xe3,0x50,0x70,0x00,0x00,0x47] #CHECK: binhe 0(%r15) # encoding: [0xe3,0x50,0xf0,0x00,0x00,0x47] @@ -126,15 +130,19 @@ #CHECK: bic 7, 0(%r7) # encoding: [0xe3,0x70,0x70,0x00,0x00,0x47] #CHECK: bine 0(%r15) # encoding: [0xe3,0x70,0xf0,0x00,0x00,0x47] +#CHECK: binz 0(%r12) # encoding: [0xe3,0x70,0xc0,0x00,0x00,0x47] bic 7, 0(%r7) bine 0(%r15) + binz 0(%r12) #CHECK: bic 8, 0(%r7) # encoding: [0xe3,0x80,0x70,0x00,0x00,0x47] #CHECK: bie 0(%r15) # encoding: [0xe3,0x80,0xf0,0x00,0x00,0x47] +#CHECK: biz 0(%r11) # encoding: [0xe3,0x80,0xb0,0x00,0x00,0x47] bic 8, 0(%r7) bie 0(%r15) + biz 0(%r11) #CHECK: bic 9, 0(%r7) # encoding: [0xe3,0x90,0x70,0x00,0x00,0x47] #CHECK: binlh 0(%r15) # encoding: [0xe3,0x90,0xf0,0x00,0x00,0x47] @@ -150,9 +158,11 @@ #CHECK: bic 11, 0(%r7) # encoding: [0xe3,0xb0,0x70,0x00,0x00,0x47] #CHECK: binl 0(%r15) # encoding: [0xe3,0xb0,0xf0,0x00,0x00,0x47] +#CHECK: binm 0(%r10) # encoding: [0xe3,0xb0,0xa0,0x00,0x00,0x47] bic 11, 0(%r7) binl 0(%r15) + binm 0(%r10) #CHECK: bic 12, 0(%r7) # encoding: [0xe3,0xc0,0x70,0x00,0x00,0x47] #CHECK: bile 0(%r15) # encoding: [0xe3,0xc0,0xf0,0x00,0x00,0x47] @@ -162,9 +172,11 @@ #CHECK: bic 13, 0(%r7) # encoding: [0xe3,0xd0,0x70,0x00,0x00,0x47] #CHECK: binh 0(%r15) # encoding: [0xe3,0xd0,0xf0,0x00,0x00,0x47] +#CHECK: binp 0(%r9) # encoding: [0xe3,0xd0,0x90,0x00,0x00,0x47] bic 13, 0(%r7) binh 0(%r15) + binp 0(%r9) #CHECK: bic 14, 0(%r7) # encoding: [0xe3,0xe0,0x70,0x00,0x00,0x47] #CHECK: bino 0(%r15) # encoding: [0xe3,0xe0,0xf0,0x00,0x00,0x47] diff --git a/llvm/test/MC/SystemZ/insn-good-zEC12.s b/llvm/test/MC/SystemZ/insn-good-zEC12.s index c0ff72298fa6..db37d28686e9 100644 --- a/llvm/test/MC/SystemZ/insn-good-zEC12.s +++ b/llvm/test/MC/SystemZ/insn-good-zEC12.s @@ -149,6 +149,12 @@ #CHECK: cltne %r0, 0(%r15) # encoding: [0xeb,0x06,0xf0,0x00,0x00,0x23] #CHECK: cltnl %r0, 0(%r15) # encoding: [0xeb,0x0a,0xf0,0x00,0x00,0x23] #CHECK: cltnh %r0, 0(%r15) # encoding: [0xeb,0x0c,0xf0,0x00,0x00,0x23] +#CHECK: cltnle %r0, 0(%r15) # encoding: [0xeb,0x02,0xf0,0x00,0x00,0x23] +#CHECK: cltnhe %r0, 0(%r15) # encoding: [0xeb,0x04,0xf0,0x00,0x00,0x23] +#CHECK: cltnlh %r0, 0(%r15) # encoding: [0xeb,0x08,0xf0,0x00,0x00,0x23] +#CHECK: cltlh %r0, 0(%r15) # encoding: [0xeb,0x06,0xf0,0x00,0x00,0x23] +#CHECK: clthe %r0, 0(%r15) # encoding: [0xeb,0x0a,0xf0,0x00,0x00,0x23] +#CHECK: cltle %r0, 0(%r15) # encoding: [0xeb,0x0c,0xf0,0x00,0x00,0x23] clt %r0, 12, -524288 clt %r0, 12, -1 @@ -165,6 +171,12 @@ cltne %r0, 0(%r15) cltnl %r0, 0(%r15) cltnh %r0, 0(%r15) + cltnle %r0, 0(%r15) + cltnhe %r0, 0(%r15) + cltnlh %r0, 0(%r15) + cltlh %r0, 0(%r15) + clthe %r0, 0(%r15) + cltle %r0, 0(%r15) #CHECK: clgt %r0, 12, -524288 # encoding: [0xeb,0x0c,0x00,0x00,0x80,0x2b] #CHECK: clgt %r0, 12, -1 # encoding: [0xeb,0x0c,0x0f,0xff,0xff,0x2b] @@ -181,6 +193,12 @@ #CHECK: clgtne %r0, 0(%r15) # encoding: [0xeb,0x06,0xf0,0x00,0x00,0x2b] #CHECK: clgtnl %r0, 0(%r15) # encoding: [0xeb,0x0a,0xf0,0x00,0x00,0x2b] #CHECK: clgtnh %r0, 0(%r15) # encoding: [0xeb,0x0c,0xf0,0x00,0x00,0x2b] +#CHECK: clgtnle %r0, 0(%r15) # encoding: [0xeb,0x02,0xf0,0x00,0x00,0x2b] +#CHECK: clgtnhe %r0, 0(%r15) # encoding: [0xeb,0x04,0xf0,0x00,0x00,0x2b] +#CHECK: clgtnlh %r0, 0(%r15) # encoding: [0xeb,0x08,0xf0,0x00,0x00,0x2b] +#CHECK: clgtlh %r0, 0(%r15) # encoding: [0xeb,0x06,0xf0,0x00,0x00,0x2b] +#CHECK: clgthe %r0, 0(%r15) # encoding: [0xeb,0x0a,0xf0,0x00,0x00,0x2b] +#CHECK: clgtle %r0, 0(%r15) # encoding: [0xeb,0x0c,0xf0,0x00,0x00,0x2b] clgt %r0, 12, -524288 clgt %r0, 12, -1 @@ -197,6 +215,12 @@ clgtne %r0, 0(%r15) clgtnl %r0, 0(%r15) clgtnh %r0, 0(%r15) + clgtnle %r0, 0(%r15) + clgtnhe %r0, 0(%r15) + clgtnlh %r0, 0(%r15) + clgtlh %r0, 0(%r15) + clgthe %r0, 0(%r15) + clgtle %r0, 0(%r15) #CHECK: crdte %r0, %r0, %r0 # encoding: [0xb9,0x8f,0x00,0x00] #CHECK: crdte %r0, %r0, %r14 # encoding: [0xb9,0x8f,0x00,0x0e] diff --git a/llvm/test/MC/SystemZ/insn-good.s b/llvm/test/MC/SystemZ/insn-good.s index f5dd672f9dd8..2add4a108319 100644 --- a/llvm/test/MC/SystemZ/insn-good.s +++ b/llvm/test/MC/SystemZ/insn-good.s @@ -970,9 +970,11 @@ #CHECK: bc 2, 0(%r7) # encoding: [0x47,0x20,0x70,0x00] #CHECK: bh 0(%r15) # encoding: [0x47,0x20,0xf0,0x00] +#CHECK: bp 0(%r10) # encoding: [0x47,0x20,0xa0,0x00] bc 2, 0(%r7) bh 0(%r15) + bp 0(%r10) #CHECK: bc 3, 0(%r7) # encoding: [0x47,0x30,0x70,0x00] #CHECK: bnle 0(%r15) # encoding: [0x47,0x30,0xf0,0x00] @@ -982,9 +984,11 @@ #CHECK: bc 4, 0(%r7) # encoding: [0x47,0x40,0x70,0x00] #CHECK: bl 0(%r15) # encoding: [0x47,0x40,0xf0,0x00] +#CHECK: bm 0(%r14) # encoding: [0x47,0x40,0xe0,0x00] bc 4, 0(%r7) bl 0(%r15) + bm 0(%r14) #CHECK: bc 5, 0(%r7) # encoding: [0x47,0x50,0x70,0x00] #CHECK: bnhe 0(%r15) # encoding: [0x47,0x50,0xf0,0x00] @@ -1000,9 +1004,11 @@ #CHECK: bc 7, 0(%r7) # encoding: [0x47,0x70,0x70,0x00] #CHECK: bne 0(%r15) # encoding: [0x47,0x70,0xf0,0x00] +#CHECK: bnz 0(%r11) # encoding: [0x47,0x70,0xb0,0x00] bc 7, 0(%r7) bne 0(%r15) + bnz 0(%r11) #CHECK: bc 8, 0(%r7) # encoding: [0x47,0x80,0x70,0x00] #CHECK: be 0(%r15) # encoding: [0x47,0x80,0xf0,0x00] @@ -1024,9 +1030,11 @@ #CHECK: bc 11, 0(%r7) # encoding: [0x47,0xb0,0x70,0x00] #CHECK: bnl 0(%r15) # encoding: [0x47,0xb0,0xf0,0x00] +#CHECK: bnm 0(%r13) # encoding: [0x47,0xb0,0xd0,0x00] bc 11, 0(%r7) bnl 0(%r15) + bnm 0(%r13) #CHECK: bc 12, 0(%r7) # encoding: [0x47,0xc0,0x70,0x00] #CHECK: ble 0(%r15) # encoding: [0x47,0xc0,0xf0,0x00] @@ -1036,9 +1044,11 @@ #CHECK: bc 13, 0(%r7) # encoding: [0x47,0xd0,0x70,0x00] #CHECK: bnh 0(%r15) # encoding: [0x47,0xd0,0xf0,0x00] +#CHECK: bnp 0(%r12) # encoding: [0x47,0xd0,0xc0,0x00] bc 13, 0(%r7) bnh 0(%r15) + bnp 0(%r12) #CHECK: bc 14, 0(%r7) # encoding: [0x47,0xe0,0x70,0x00] #CHECK: bno 0(%r15) # encoding: [0x47,0xe0,0xf0,0x00] @@ -1046,6 +1056,13 @@ bc 14, 0(%r7) bno 0(%r15) +#CHECK: bc 8, 0(%r13) # encoding: [0x47,0x80,0xd0,0x00] +#CHECK: bz 0(%r6) # encoding: [0x47,0x80,0x60,0x00] + + bc 8, 0(%r13) + bz 0(%r6) + + #CHECK: bcr 0, %r0 # encoding: [0x07,0x00] #CHECK: bcr 0, %r15 # encoding: [0x07,0x0f] @@ -1176,6 +1193,36 @@ br %r14 br %r15 +#CHECK: bcr 4, %r7 # encoding: [0x07,0x47] +#CHECK: bmr %r0 # encoding: [0x07,0x40] + bcr 4, %r7 + bmr %r0 + +#CHECK: bcr 11, %r8 # encoding: [0x07,0xb8] +#CHECK: bnmr %r1 # encoding: [0x07,0xb1] + bcr 11, %r8 + bnmr %r1 + +#CHECK: bcr 13, %r9 # encoding: [0x07,0xd9] +#CHECK: bnpr %r2 # encoding: [0x07,0xd2] + bcr 13, %r9 + bnpr %r2 + +#CHECK: bcr 7, %r10 # encoding: [0x07,0x7a] +#CHECK: bnzr %r3 # encoding: [0x07,0x73] + bcr 7, %r10 + bnzr %r3 + +#CHECK: bcr 2, %r11 # encoding: [0x07,0x2b] +#CHECK: bpr %r4 # encoding: [0x07,0x24] + bcr 2, %r11 + bpr %r4 + +#CHECK: bcr 8, %r12 # encoding: [0x07,0x8c] +#CHECK: bzr %r5 # encoding: [0x07,0x85] + bcr 8, %r12 + bzr %r5 + #CHECK: bras %r0, .[[LAB:L.*]]-65536 # encoding: [0xa7,0x05,A,A] #CHECK: fixup A - offset: 2, value: (.[[LAB]]-65536)+2, kind: FK_390_PC16DBL #CHECK: bras %r0, .[[LAB:L.*]]-65536 # encoding: [0xa7,0x05,A,A] @@ -3823,6 +3870,12 @@ #CHECK: cgitne %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x60,0x70] #CHECK: cgitnl %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xa0,0x70] #CHECK: cgitnh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xc0,0x70] +#CHECK: cgitnle %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x20,0x70] +#CHECK: cgitnhe %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x40,0x70] +#CHECK: cgitnlh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x80,0x70] +#CHECK: cgitlh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x60,0x70] +#CHECK: cgithe %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xa0,0x70] +#CHECK: cgitle %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xc0,0x70] cgit %r0, 0, 12 cgit %r0, -1, 12 @@ -3834,6 +3887,12 @@ cgitne %r15, 1 cgitnl %r15, 1 cgitnh %r15, 1 + cgitnle %r15, 1 + cgitnhe %r15, 1 + cgitnlh %r15, 1 + cgitlh %r15, 1 + cgithe %r15, 1 + cgitle %r15, 1 #CHECK: cgr %r0, %r0 # encoding: [0xb9,0x20,0x00,0x00] #CHECK: cgr %r0, %r15 # encoding: [0xb9,0x20,0x00,0x0f] @@ -4198,6 +4257,12 @@ #CHECK: cgrtne %r0, %r15 # encoding: [0xb9,0x60,0x60,0x0f] #CHECK: cgrtnl %r0, %r15 # encoding: [0xb9,0x60,0xa0,0x0f] #CHECK: cgrtnh %r0, %r15 # encoding: [0xb9,0x60,0xc0,0x0f] +#CHECK: cgrtnle %r0, %r15 # encoding: [0xb9,0x60,0x20,0x0f] +#CHECK: cgrtnhe %r0, %r15 # encoding: [0xb9,0x60,0x40,0x0f] +#CHECK: cgrtnlh %r0, %r15 # encoding: [0xb9,0x60,0x80,0x0f] +#CHECK: cgrtlh %r0, %r15 # encoding: [0xb9,0x60,0x60,0x0f] +#CHECK: cgrthe %r0, %r15 # encoding: [0xb9,0x60,0xa0,0x0f] +#CHECK: cgrtle %r0, %r15 # encoding: [0xb9,0x60,0xc0,0x0f] cgrt %r0, %r1, 12 cgrt %r0, %r1, 12 @@ -4209,6 +4274,12 @@ cgrtne %r0, %r15 cgrtnl %r0, %r15 cgrtnh %r0, %r15 + cgrtnle %r0, %r15 + cgrtnhe %r0, %r15 + cgrtnlh %r0, %r15 + cgrtlh %r0, %r15 + cgrthe %r0, %r15 + cgrtle %r0, %r15 #CHECK: cgxbr %r0, 0, %f0 # encoding: [0xb3,0xaa,0x00,0x00] #CHECK: cgxbr %r0, 0, %f13 # encoding: [0xb3,0xaa,0x00,0x0d] @@ -4708,6 +4779,12 @@ #CHECK: citne %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x60,0x72] #CHECK: citnl %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xa0,0x72] #CHECK: citnh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xc0,0x72] +#CHECK: citnle %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x20,0x72] +#CHECK: citnhe %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x40,0x72] +#CHECK: citnlh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x80,0x72] +#CHECK: citlh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x60,0x72] +#CHECK: cithe %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xa0,0x72] +#CHECK: citle %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xc0,0x72] cit %r0, 0, 12 cit %r0, -1, 12 @@ -4719,6 +4796,12 @@ citne %r15, 1 citnl %r15, 1 citnh %r15, 1 + citnle %r15, 1 + citnhe %r15, 1 + citnlh %r15, 1 + citlh %r15, 1 + cithe %r15, 1 + citle %r15, 1 #CHECK: cksm %r0, %r8 # encoding: [0xb2,0x41,0x00,0x08] #CHECK: cksm %r0, %r14 # encoding: [0xb2,0x41,0x00,0x0e] @@ -4853,6 +4936,12 @@ #CHECK: clfitne %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x60,0x73] #CHECK: clfitnl %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xa0,0x73] #CHECK: clfitnh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xc0,0x73] +#CHECK: clfitnle %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x20,0x73] +#CHECK: clfitnhe %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x40,0x73] +#CHECK: clfitnlh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x80,0x73] +#CHECK: clfitlh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x60,0x73] +#CHECK: clfithe %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xa0,0x73] +#CHECK: clfitle %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xc0,0x73] clfit %r0, 0, 12 clfit %r0, 65535, 12 @@ -4863,6 +4952,12 @@ clfitne %r15, 1 clfitnl %r15, 1 clfitnh %r15, 1 + clfitnle %r15, 1 + clfitnhe %r15, 1 + clfitnlh %r15, 1 + clfitlh %r15, 1 + clfithe %r15, 1 + clfitle %r15, 1 #CHECK: clg %r0, -524288 # encoding: [0xe3,0x00,0x00,0x00,0x80,0x21] #CHECK: clg %r0, -1 # encoding: [0xe3,0x00,0x0f,0xff,0xff,0x21] @@ -5332,6 +5427,12 @@ #CHECK: clgitne %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x60,0x71] #CHECK: clgitnl %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xa0,0x71] #CHECK: clgitnh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xc0,0x71] +#CHECK: clgitnle %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x20,0x71] +#CHECK: clgitnhe %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x40,0x71] +#CHECK: clgitnlh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x80,0x71] +#CHECK: clgitlh %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0x60,0x71] +#CHECK: clgithe %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xa0,0x71] +#CHECK: clgitle %r15, 1 # encoding: [0xec,0xf0,0x00,0x01,0xc0,0x71] clgit %r0, 0, 12 clgit %r0, 65535, 12 @@ -5342,6 +5443,12 @@ clgitne %r15, 1 clgitnl %r15, 1 clgitnh %r15, 1 + clgitnle %r15, 1 + clgitnhe %r15, 1 + clgitnlh %r15, 1 + clgitlh %r15, 1 + clgithe %r15, 1 + clgitle %r15, 1 #CHECK: clgr %r0, %r0 # encoding: [0xb9,0x21,0x00,0x00] #CHECK: clgr %r0, %r15 # encoding: [0xb9,0x21,0x00,0x0f] @@ -6250,6 +6357,12 @@ #CHECK: clgrtne %r0, %r15 # encoding: [0xb9,0x61,0x60,0x0f] #CHECK: clgrtnl %r0, %r15 # encoding: [0xb9,0x61,0xa0,0x0f] #CHECK: clgrtnh %r0, %r15 # encoding: [0xb9,0x61,0xc0,0x0f] +#CHECK: clgrtnle %r0, %r15 # encoding: [0xb9,0x61,0x20,0x0f] +#CHECK: clgrtnhe %r0, %r15 # encoding: [0xb9,0x61,0x40,0x0f] +#CHECK: clgrtnlh %r0, %r15 # encoding: [0xb9,0x61,0x80,0x0f] +#CHECK: clgrtlh %r0, %r15 # encoding: [0xb9,0x61,0x60,0x0f] +#CHECK: clgrthe %r0, %r15 # encoding: [0xb9,0x61,0xa0,0x0f] +#CHECK: clgrtle %r0, %r15 # encoding: [0xb9,0x61,0xc0,0x0f] clgrt %r0, %r1, 12 clgrt %r0, %r1, 12 @@ -6261,6 +6374,12 @@ clgrtne %r0, %r15 clgrtnl %r0, %r15 clgrtnh %r0, %r15 + clgrtnle %r0, %r15 + clgrtnhe %r0, %r15 + clgrtnlh %r0, %r15 + clgrtlh %r0, %r15 + clgrthe %r0, %r15 + clgrtle %r0, %r15 #CHECK: clrj %r0, %r0, 0, .[[LAB:L.*]] # encoding: [0xec,0x00,A,A,0x00,0x77] #CHECK: fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL @@ -6539,6 +6658,12 @@ #CHECK: clrtne %r0, %r15 # encoding: [0xb9,0x73,0x60,0x0f] #CHECK: clrtnl %r0, %r15 # encoding: [0xb9,0x73,0xa0,0x0f] #CHECK: clrtnh %r0, %r15 # encoding: [0xb9,0x73,0xc0,0x0f] +#CHECK: clrtnle %r0, %r15 # encoding: [0xb9,0x73,0x20,0x0f] +#CHECK: clrtnhe %r0, %r15 # encoding: [0xb9,0x73,0x40,0x0f] +#CHECK: clrtnlh %r0, %r15 # encoding: [0xb9,0x73,0x80,0x0f] +#CHECK: clrtlh %r0, %r15 # encoding: [0xb9,0x73,0x60,0x0f] +#CHECK: clrthe %r0, %r15 # encoding: [0xb9,0x73,0xa0,0x0f] +#CHECK: clrtle %r0, %r15 # encoding: [0xb9,0x73,0xc0,0x0f] clrt %r0, %r1, 12 clrt %r0, %r1, 12 @@ -6550,6 +6675,12 @@ clrtne %r0, %r15 clrtnl %r0, %r15 clrtnh %r0, %r15 + clrtnle %r0, %r15 + clrtnhe %r0, %r15 + clrtnlh %r0, %r15 + clrtlh %r0, %r15 + clrthe %r0, %r15 + clrtle %r0, %r15 #CHECK: clst %r0, %r0 # encoding: [0xb2,0x5d,0x00,0x00] #CHECK: clst %r0, %r15 # encoding: [0xb2,0x5d,0x00,0x0f] @@ -7012,6 +7143,12 @@ #CHECK: crtne %r0, %r15 # encoding: [0xb9,0x72,0x60,0x0f] #CHECK: crtnl %r0, %r15 # encoding: [0xb9,0x72,0xa0,0x0f] #CHECK: crtnh %r0, %r15 # encoding: [0xb9,0x72,0xc0,0x0f] +#CHECK: crtnle %r0, %r15 # encoding: [0xb9,0x72,0x20,0x0f] +#CHECK: crtnhe %r0, %r15 # encoding: [0xb9,0x72,0x40,0x0f] +#CHECK: crtnlh %r0, %r15 # encoding: [0xb9,0x72,0x80,0x0f] +#CHECK: crtlh %r0, %r15 # encoding: [0xb9,0x72,0x60,0x0f] +#CHECK: crthe %r0, %r15 # encoding: [0xb9,0x72,0xa0,0x0f] +#CHECK: crtle %r0, %r15 # encoding: [0xb9,0x72,0xc0,0x0f] crt %r0, %r1, 12 crt %r0, %r1, 12 @@ -7023,6 +7160,12 @@ crtne %r0, %r15 crtnl %r0, %r15 crtnh %r0, %r15 + crtnle %r0, %r15 + crtnhe %r0, %r15 + crtnlh %r0, %r15 + crtlh %r0, %r15 + crthe %r0, %r15 + crtle %r0, %r15 #CHECK: cs %r0, %r0, 0 # encoding: [0xba,0x00,0x00,0x00] #CHECK: cs %r0, %r0, 4095 # encoding: [0xba,0x00,0x0f,0xff] -- GitLab From e7d09cecc9123f89ace1712a617e252d78b179e9 Mon Sep 17 00:00:00 2001 From: Petr Kurapov Date: Tue, 14 May 2024 11:50:35 +0200 Subject: [PATCH 203/578] [MLIR][Linalg] Ternary Op & Linalg select (#91461) Following #90236, adding `select` to linalg as `arith.select`. No implicit type casting. OpDSL doesn't expose a type restriction for bool, but I saw no reason in adding it (put a separate symbolic type and check the semantics in the builder). --------- Co-authored-by: Renato Golin Co-authored-by: Maksim Levental --- .../mlir/Dialect/Linalg/IR/LinalgBase.td | 3 + .../mlir/Dialect/Linalg/IR/LinalgEnums.td | 6 ++ .../Linalg/IR/LinalgNamedStructuredOps.yaml | 57 +++++++++++++++++ mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | 19 ++++++ .../linalg/opdsl/lang/comprehension.py | 61 ++++++++++++++++++- .../dialects/linalg/opdsl/lang/emitter.py | 7 +++ .../linalg/opdsl/ops/core_named_ops.py | 20 ++++++ .../Dialect/Linalg/generalize-named-ops.mlir | 25 ++++++++ mlir/test/Dialect/Linalg/named-ops-fail.mlir | 16 +++++ mlir/test/Dialect/Linalg/named-ops.mlir | 34 +++++++++++ .../mlir-linalg-ods-yaml-gen.cpp | 10 ++- 11 files changed, 255 insertions(+), 3 deletions(-) diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgBase.td b/mlir/include/mlir/Dialect/Linalg/IR/LinalgBase.td index e87e8b560010..73f984dc072d 100644 --- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgBase.td +++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgBase.td @@ -68,6 +68,9 @@ def UnaryFnAttr : EnumAttr { def BinaryFnAttr : EnumAttr { let assemblyFormat = "`<` $value `>`"; } +def TernaryFnAttr : EnumAttr { + let assemblyFormat = "`<` $value `>`"; +} def TypeFnAttr : EnumAttr { let assemblyFormat = "`<` $value `>`"; } diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgEnums.td b/mlir/include/mlir/Dialect/Linalg/IR/LinalgEnums.td index 6b4b073fc672..e615876a95d0 100644 --- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgEnums.td +++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgEnums.td @@ -49,6 +49,12 @@ def BinaryFn : I32EnumAttr<"BinaryFn", "", [ let genSpecializedAttr = 0; let cppNamespace = "::mlir::linalg"; } +def TernaryFn : I32EnumAttr<"TernaryFn", "", [ + I32EnumAttrCase<"select", 0> +]> { + let genSpecializedAttr = 0; + let cppNamespace = "::mlir::linalg"; +} def TypeFn : I32EnumAttr<"TypeFn", "", [ I32EnumAttrCase<"cast_signed", 0>, I32EnumAttrCase<"cast_unsigned", 1> diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml b/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml index 584bfcd8b59d..eb7dd37010a6 100644 --- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml +++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgNamedStructuredOps.yaml @@ -1008,6 +1008,63 @@ structured_op: !LinalgStructuredOpConfig - !ScalarExpression scalar_arg: rhs --- !LinalgOpConfig +metadata: !LinalgOpMetadata + name: select + cpp_class_name: SelectOp + doc: |- + Chooses one value based on a binary condition supplied as its first operand. + + The shapes and element types must be identical. The appropriate casts, + broadcasts and reductions should be done previously to calling this op. + + This means reduction/broadcast/element cast semantics is explicit. Further + passes can take that into account when lowering this code. For example, + a `linalg.broadcast` + `linalg.select` sequence can be lowered to a + `linalg.generic` with different affine maps for the two operands. +structured_op: !LinalgStructuredOpConfig + args: + - !LinalgOperandDefConfig + name: cond + kind: input_tensor + type_var: U + shape_map: affine_map<() -> ()> + - !LinalgOperandDefConfig + name: lhs + kind: input_tensor + type_var: T1 + shape_map: affine_map<() -> ()> + - !LinalgOperandDefConfig + name: rhs + kind: input_tensor + type_var: T1 + shape_map: affine_map<() -> ()> + - !LinalgOperandDefConfig + name: O + kind: output_tensor + type_var: T1 + shape_map: affine_map<() -> ()> + indexing_maps: !LinalgIndexingMapsConfig + static_indexing_maps: + - affine_map<() -> ()> + - affine_map<() -> ()> + - affine_map<() -> ()> + - affine_map<() -> ()> + iterator_types: [] + assignments: + - !ScalarAssign + arg: O + value: !ScalarExpression + scalar_fn: + kind: ternary + fn_name: select + operands: + - !ScalarExpression + scalar_arg: cond + - !ScalarExpression + scalar_arg: lhs + - !ScalarExpression + scalar_arg: rhs +--- !LinalgOpConfig metadata: !LinalgOpMetadata name: matmul cpp_class_name: MatmulOp diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp index e5f83331baf8..6a5f25a7605f 100644 --- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp @@ -492,6 +492,25 @@ public: llvm_unreachable("unsupported binary function"); } + // Build the ternary functions defined by OpDSL. + Value buildTernaryFn(TernaryFn ternaryFn, Value arg0, Value arg1, + Value arg2) { + bool headBool = + isInteger(arg0) && arg0.getType().getIntOrFloatBitWidth() == 1; + bool tailFloatingPoint = + isFloatingPoint(arg0) && isFloatingPoint(arg1) && isFloatingPoint(arg2); + bool tailInteger = isInteger(arg0) && isInteger(arg1) && isInteger(arg1); + OpBuilder::InsertionGuard g(builder); + builder.setInsertionPointToEnd(&block); + switch (ternaryFn) { + case TernaryFn::select: + if (!headBool && !(tailFloatingPoint || tailInteger)) + llvm_unreachable("unsupported non numeric type"); + return builder.create(arg0.getLoc(), arg0, arg1, arg2); + } + llvm_unreachable("unsupported ternary function"); + } + // Build the type functions defined by OpDSL. Value buildTypeFn(TypeFn typeFn, Type toType, Value operand) { switch (typeFn) { diff --git a/mlir/python/mlir/dialects/linalg/opdsl/lang/comprehension.py b/mlir/python/mlir/dialects/linalg/opdsl/lang/comprehension.py index bb43ebf2b692..1a198fc5ec6f 100644 --- a/mlir/python/mlir/dialects/linalg/opdsl/lang/comprehension.py +++ b/mlir/python/mlir/dialects/linalg/opdsl/lang/comprehension.py @@ -262,7 +262,8 @@ class index(TensorExpression): class FunctionKind(Enum): UNARY = 0 BINARY = 1 - TYPE = 2 + TERNARY = 2 + TYPE = 3 class UnaryFnType: @@ -339,6 +340,33 @@ class BinaryFn: powf = BinaryFnType("powf") +class TernaryFnType: + """Ternary function. + + A ternary function takes three tensor expressions and returns the + function evaluation result. + """ + + def __init__(self, fn_name: str): + self.fn_name = fn_name + + def __call__( + self, arg0: TensorExpression, arg1: TensorExpression, arg2: TensorExpression + ) -> "TensorFn": + return TensorFn( + FunctionKind.TERNARY, self.fn_name, None, None, [arg0, arg1, arg2] + ) + + def __repr__(self): + return f"{self.fn_name}" + + +class TernaryFn: + """Ternary function namespace.""" + + select = TernaryFnType("select") + + class TypeFnType: """Type conversion function. @@ -437,7 +465,8 @@ class OperandKind(Enum): INDEX_ATTR = 3 UNARY_FN_ATTR = 4 BINARY_FN_ATTR = 5 - TYPE_FN_ATTR = 6 + TERNARY_FN_ATTR = 6 + TYPE_FN_ATTR = 7 class OperandDef: @@ -489,6 +518,7 @@ class OperandDef: self.kind == OperandKind.INDEX_ATTR or self.kind == OperandKind.UNARY_FN_ATTR or self.kind == OperandKind.BINARY_FN_ATTR + or self.kind == OperandKind.TERNARY_FN_ATTR or self.kind == OperandKind.TYPE_FN_ATTR ) @@ -670,6 +700,33 @@ class BinaryFnAttrDef: return ReduceFnUse(None, self, *reduce_dims) +class TernaryFnAttrDef: + """Ternary function attribute definition. + + Ternary function attributes provide a way to make the arithmetic computation + parametrizable. Every attribute specifies a default Ternary function + that may be overwritten at operation instantiation time. + """ + + def __init__(self, default: "TernaryFnType"): + if not isinstance(default, TernaryFnType): + raise ValueError( + f"TernaryFnAttrDef requires default of type TernaryFnType " + f"but got {default}" + ) + self.operand_def = OperandDef( + OperandKind.TERNARY_FN_ATTR, default_fn=default.fn_name + ) + + def __call__(self, arg0: TensorExpression, arg1: TensorExpression) -> TensorFn: + return TensorFn( + FunctionKind.TERNARY, None, self.operand_def, None, [arg0, arg1] + ) + + def __getitem__(self, reduce_dims: Tuple[DimDef]) -> ReduceFnUse: + return ReduceFnUse(None, self, *reduce_dims) + + class TypeFnAttrDef: """Type conversion function attribute definition. diff --git a/mlir/python/mlir/dialects/linalg/opdsl/lang/emitter.py b/mlir/python/mlir/dialects/linalg/opdsl/lang/emitter.py index f91fc8b71600..845b533db52a 100644 --- a/mlir/python/mlir/dialects/linalg/opdsl/lang/emitter.py +++ b/mlir/python/mlir/dialects/linalg/opdsl/lang/emitter.py @@ -60,6 +60,7 @@ def prepare_common_structured_op( in [ OperandKind.UNARY_FN_ATTR, OperandKind.BINARY_FN_ATTR, + OperandKind.TERNARY_FN_ATTR, OperandKind.TYPE_FN_ATTR, ] ] @@ -180,6 +181,12 @@ def prepare_common_structured_op( f"Attribute {fn_attr.name} needs to be of type " f"BinaryFnType but got {type(attr_val)}" ) + elif attr_kind == OperandKind.TERNARY_FN_ATTR: + if not isinstance(fn, TernaryFnType): + raise ValueError( + f"Attribute {fn_attr.name} needs to be of type " + f"TernaryFnType but got {type(attr_val)}" + ) else: if not isinstance(fn, TypeFnType): raise ValueError( diff --git a/mlir/python/mlir/dialects/linalg/opdsl/ops/core_named_ops.py b/mlir/python/mlir/dialects/linalg/opdsl/ops/core_named_ops.py index ca2bb0c5f7f8..d73428a0f4df 100644 --- a/mlir/python/mlir/dialects/linalg/opdsl/ops/core_named_ops.py +++ b/mlir/python/mlir/dialects/linalg/opdsl/ops/core_named_ops.py @@ -351,6 +351,26 @@ def powf( O[None] = BinaryFn.powf(lhs[None], rhs[None]) +@linalg_structured_op +def select( + cond=TensorDef(U), + lhs=TensorDef(T1), + rhs=TensorDef(T1), + O=TensorDef(T1, output=True), +): + """Chooses one value based on a binary condition supplied as its first operand. + + The shapes and element types must be identical. The appropriate casts, + broadcasts and reductions should be done previously to calling this op. + + This means reduction/broadcast/element cast semantics is explicit. Further + passes can take that into account when lowering this code. For example, + a `linalg.broadcast` + `linalg.select` sequence can be lowered to a + `linalg.generic` with different affine maps for the two operands. + """ + O[None] = TernaryFn.select(cond[None], lhs[None], rhs[None]) + + @linalg_structured_op def matmul( A=TensorDef(T1, S.M, S.K), diff --git a/mlir/test/Dialect/Linalg/generalize-named-ops.mlir b/mlir/test/Dialect/Linalg/generalize-named-ops.mlir index 667ea3c18c8a..4f43ec2c9e1c 100644 --- a/mlir/test/Dialect/Linalg/generalize-named-ops.mlir +++ b/mlir/test/Dialect/Linalg/generalize-named-ops.mlir @@ -791,6 +791,31 @@ func.func @generalize_powf(%lhs: memref<7x14x21xf32>, %rhs: memref<7x14x21xf32>, // ----- +func.func @generalize_select(%cond: memref<7x14x21xi1>, %lhs: memref<7x14x21xf32>, %rhs: memref<7x14x21xf32>, + %out: memref<7x14x21xf32>) { + linalg.select ins(%cond, %lhs, %rhs: memref<7x14x21xi1>, memref<7x14x21xf32>, memref<7x14x21xf32>) + outs(%out: memref<7x14x21xf32>) + return +} + +// CHECK: #[[MAP:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)> + +// CHECK: func @generalize_select +// CHECK-SAME: (%[[COND:.+]]: memref<7x14x21xi1>, %[[LHS:.+]]: memref<7x14x21xf32>, %[[RHS:.+]]: memref<7x14x21xf32>, +// CHECK-SAME: %[[OUT:.+]]: memref<7x14x21xf32>) + +// CHECK: linalg.generic +// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]], #[[MAP]], #[[MAP]]] +// CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]} +// CHECK-SAME: ins(%[[COND]], %[[LHS]], %[[RHS]] : memref<7x14x21xi1>, memref<7x14x21xf32>, memref<7x14x21xf32>) +// CHECK-SAME: outs(%[[OUT]] : memref<7x14x21xf32>) + +// CHECK: ^{{.+}}(%[[BBARG0:.+]]: i1, %[[BBARG1:.+]]: f32, %[[BBARG2:.+]]: f32, %[[BBARG3:.+]]: f32) +// CHECK-NEXT: %[[select:.+]] = arith.select %[[BBARG0]], %[[BBARG1]], %[[BBARG2]] : f32 +// CHECK-NEXT: linalg.yield %[[select]] : f32 + + +// ----- // CHECK-LABEL: func @fill_tensor func.func @fill_tensor(%f: f32, %v: vector<2x4xf32>) -> (tensor, tensor>) { diff --git a/mlir/test/Dialect/Linalg/named-ops-fail.mlir b/mlir/test/Dialect/Linalg/named-ops-fail.mlir index e92a77aa7ad0..552a0abaa797 100644 --- a/mlir/test/Dialect/Linalg/named-ops-fail.mlir +++ b/mlir/test/Dialect/Linalg/named-ops-fail.mlir @@ -334,3 +334,19 @@ func.func @powf_broadcast(%arg0: memref<8x16xf32>, %arg1: memref<4x8x16xf32>, %a return } +// ----- + +func.func @select_type_cast(%arg0: memref<4x8x16xi1>, %arg1: memref<4x8x16xf16>, %arg2: memref<4x8x16xf32>, %arg3: memref<4x8x16xf32>) { + // CHECK: op failed to verify that all of {true_value, false_value, result} have same type + linalg.select ins(%arg0, %arg1, %arg2 : memref<4x8x16xi1>, memref<4x8x16xf16>, memref<4x8x16xf32>) outs(%arg3: memref<4x8x16xf32>) + return +} + +// ----- + +func.func @select_wrong_condition_type(%arg0: memref<4x8x16xf32>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>, %arg3: memref<4x8x16xf32>) { + // CHECK: op operand #0 must be bool-like, but got 'f32' + linalg.select ins(%arg0, %arg1, %arg2 : memref<4x8x16xf32>, memref<4x8x16xf32>, memref<4x8x16xf32>) outs(%arg3: memref<4x8x16xf32>) + return +} + diff --git a/mlir/test/Dialect/Linalg/named-ops.mlir b/mlir/test/Dialect/Linalg/named-ops.mlir index fefe5578947f..051054e67edf 100644 --- a/mlir/test/Dialect/Linalg/named-ops.mlir +++ b/mlir/test/Dialect/Linalg/named-ops.mlir @@ -1924,3 +1924,37 @@ func.func @fill_tensor(%f: f32, %v: vector<2x4xf32>) -> (tensor, tensor) outs(%e1 : tensor>) -> tensor> return %0, %1: tensor, tensor> } + +// ----- + +// CHECK-LABEL: func @select_dynamic +func.func @select_dynamic(%arg0: memref, %arg1: memref, %arg2: memref, %arg3: memref) { + // CHECK: linalg.select + // CHECK-SAME: ins(%{{.+}}, %{{.+}}, %{{.+}} : memref, memref, memref) + // CHECK-SAME: outs(%{{.+}} : memref) + linalg.select ins(%arg0, %arg1, %arg2 : memref, memref, memref) outs(%arg3: memref) + return +} + +// ----- + +// CHECK-LABEL: func @select_static +func.func @select_static(%arg0: memref<4x8x16xi1>, %arg1: memref<4x8x16xf32>, %arg2: memref<4x8x16xf32>, %arg3: memref<4x8x16xf32>) { + // CHECK: linalg.select + // CHECK-SAME: ins(%{{.+}}, %{{.+}}, %{{.+}} : memref<4x8x16xi1>, memref<4x8x16xf32>, memref<4x8x16xf32>) + // CHECK-SAME: outs(%{{.+}} : memref<4x8x16xf32>) + linalg.select ins(%arg0, %arg1, %arg2 : memref<4x8x16xi1>, memref<4x8x16xf32>, memref<4x8x16xf32>) outs(%arg3: memref<4x8x16xf32>) + return +} + +// ----- + +// CHECK-LABEL: func @select_tensor +func.func @select_tensor(%arg0: tensor<4x8x16xi1>, %arg1: tensor<4x8x16xf32>, %arg2: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> { + %0 = tensor.empty() : tensor<4x8x16xf32> + // CHECK: linalg.select + // CHECK-SAME: ins(%{{.+}}, %{{.+}}, %{{.+}} : tensor<4x8x16xi1>, tensor<4x8x16xf32>, tensor<4x8x16xf32>) + // CHECK-SAME: outs(%{{.+}} : tensor<4x8x16xf32>) + %1 = linalg.select ins(%arg0, %arg1, %arg2 : tensor<4x8x16xi1>, tensor<4x8x16xf32>, tensor<4x8x16xf32>) outs(%0: tensor<4x8x16xf32>) -> tensor<4x8x16xf32> + return %1 : tensor<4x8x16xf32> +} diff --git a/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp b/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp index fe6ad1504112..37240164c377 100644 --- a/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp +++ b/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp @@ -70,6 +70,7 @@ enum class LinalgOperandDefKind { IndexAttr, UnaryFnAttr, BinaryFnAttr, + TernaryFnAttr, TypeFnAttr }; @@ -94,7 +95,7 @@ struct LinalgIndexingMapsConfig { struct ScalarExpression; -enum class ScalarFnKind { Unary, Binary, Type }; +enum class ScalarFnKind { Unary, Binary, Ternary, Type }; struct ScalarFn { ScalarFnKind kind; @@ -214,6 +215,7 @@ struct ScalarEnumerationTraits { io.enumCase(value, "index_attr", LinalgOperandDefKind::IndexAttr); io.enumCase(value, "unary_fn_attr", LinalgOperandDefKind::UnaryFnAttr); io.enumCase(value, "binary_fn_attr", LinalgOperandDefKind::BinaryFnAttr); + io.enumCase(value, "ternary_fn_attr", LinalgOperandDefKind::TernaryFnAttr); io.enumCase(value, "type_fn_attr", LinalgOperandDefKind::TypeFnAttr); } }; @@ -284,6 +286,7 @@ struct ScalarEnumerationTraits { static void enumeration(IO &io, ScalarFnKind &value) { io.enumCase(value, "unary", ScalarFnKind::Unary); io.enumCase(value, "binary", ScalarFnKind::Binary); + io.enumCase(value, "ternary", ScalarFnKind::Ternary); io.enumCase(value, "type", ScalarFnKind::Type); } }; @@ -441,6 +444,7 @@ static ScalarAssign *findAssignment(StringRef name, static bool isFunctionAttribute(LinalgOperandDefKind kind) { return kind == LinalgOperandDefKind::UnaryFnAttr || kind == LinalgOperandDefKind::BinaryFnAttr || + kind == LinalgOperandDefKind::TernaryFnAttr || kind == LinalgOperandDefKind::TypeFnAttr; } @@ -456,6 +460,8 @@ std::string convertOperandKindToEnumName(LinalgOperandDefKind kind) { return std::string("UnaryFn"); case LinalgOperandDefKind::BinaryFnAttr: return std::string("BinaryFn"); + case LinalgOperandDefKind::TernaryFnAttr: + return std::string("TernaryFn"); case LinalgOperandDefKind::TypeFnAttr: return std::string("TypeFn"); default: @@ -471,6 +477,8 @@ std::string convertFunctionKindToEnumName(ScalarFnKind kind) { return std::string("UnaryFn"); case ScalarFnKind::Binary: return std::string("BinaryFn"); + case ScalarFnKind::Ternary: + return std::string("TernaryFn"); case ScalarFnKind::Type: return std::string("TypeFn"); } -- GitLab From 8fe21fda7469f2fdf83980a2720a15baad74ae4f Mon Sep 17 00:00:00 2001 From: Andrew Sukach <134116196+soukatch@users.noreply.github.com> Date: Tue, 14 May 2024 05:57:10 -0400 Subject: [PATCH 204/578] [clang][analyzer] Ignore try-statements in UnreachableCode checker (#91675) Fixes #90162 --- .../Checkers/UnreachableCodeChecker.cpp | 4 +++- clang/test/Analysis/unreachable-code-exceptions.cpp | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 clang/test/Analysis/unreachable-code-exceptions.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp index d24a124f5ffe..7ce9a5b5bb6d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp @@ -159,6 +159,8 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G, SL = DL.asLocation(); if (SR.isInvalid() || !SL.isValid()) continue; + if (isa(S)) + continue; } else continue; @@ -254,4 +256,4 @@ void ento::registerUnreachableCodeChecker(CheckerManager &mgr) { bool ento::shouldRegisterUnreachableCodeChecker(const CheckerManager &mgr) { return true; -} +} \ No newline at end of file diff --git a/clang/test/Analysis/unreachable-code-exceptions.cpp b/clang/test/Analysis/unreachable-code-exceptions.cpp new file mode 100644 index 000000000000..f47674ea8097 --- /dev/null +++ b/clang/test/Analysis/unreachable-code-exceptions.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_analyze_cc1 -verify %s -fcxx-exceptions -fexceptions -analyzer-checker=core,alpha.deadcode.UnreachableCode + +// expected-no-diagnostics + +void foo(); + +void fp_90162() { + try { // no-warning: The TryStmt shouldn't be unreachable. + foo(); + } catch (int) { + foo(); // We assume that catch handlers are reachable. + } +} -- GitLab From 7b1b1279414217ea7f2402a03dfb5a18ea5a5367 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Tue, 14 May 2024 13:57:37 +0400 Subject: [PATCH 205/578] [lldb][Windows] Enforce exec permission using Platform::Install() from Windows host (#91887) Target::Install() set 0700 permissions for the main executable file. Platform::Install() just copies permissions from the source. But the permission eFilePermissionsUserExecute is missing on the Windows host. A lot of tests failed in case of Windows host and Linux target because of this issue. There is no API to provide the exec flag. This patch set the permission eFilePermissionsUserExecute for all files installed via Platform::Install() from the Windows host. It fixes a lot of tests in case of Windows host and Linux target. --- lldb/source/Target/Platform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 4af4aa68ccd0..ee1f92470e16 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -1225,7 +1225,7 @@ Status Platform::PutFile(const FileSpec &source, const FileSpec &destination, uint32_t permissions = source_file.get()->GetPermissions(error); if (permissions == 0) - permissions = lldb::eFilePermissionsFileDefault; + permissions = lldb::eFilePermissionsUserRWX; lldb::user_id_t dest_file = OpenFile( destination, File::eOpenOptionCanCreate | File::eOpenOptionWriteOnly | -- GitLab From d7ef34bfe3d432ffd66a05fc9fcc87fd6c3db2ee Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Tue, 14 May 2024 10:59:26 +0100 Subject: [PATCH 206/578] [LV] update comment following 63d8058 (NFC) (#91120) Address a review comment post landing 63d8058 (LoopVectorize: guard appending InstsToScalarize; fix bug) to update a comment. --- llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index ba02c98285c3..9353666e417c 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -5813,10 +5813,11 @@ void LoopVectorizationCostModel::collectInstsToScalarize(ElementCount VF) { for (Instruction &I : *BB) if (isScalarWithPredication(&I, VF)) { ScalarCostsTy ScalarCosts; - // Do not apply discount if scalable, because that would lead to - // invalid scalarization costs. - // Do not apply discount logic if hacked cost is needed - // for emulated masked memrefs. + // Do not apply discount logic for: + // 1. Scalars after vectorization, as there will only be a single copy + // of the instruction. + // 2. Scalable VF, as that would lead to invalid scalarization costs. + // 3. Emulated masked memrefs, if a hacked cost is needed. if (!isScalarAfterVectorization(&I, VF) && !VF.isScalable() && !useEmulatedMaskMemRefHack(&I, VF) && computePredInstDiscount(&I, ScalarCosts, VF) >= 0) -- GitLab From ac42f7689d741feda2badc438101e7952db048f3 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Tue, 14 May 2024 14:00:16 +0400 Subject: [PATCH 207/578] [lldb] Fixed the test TestDyldLaunchLinux (#92080) Install a.out and libsignal_file.so to the remote target if necessary. --- .../dyld-launch-linux/TestDyldLaunchLinux.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lldb/test/API/functionalities/dyld-launch-linux/TestDyldLaunchLinux.py b/lldb/test/API/functionalities/dyld-launch-linux/TestDyldLaunchLinux.py index 26360c20db1e..c4eba023ea72 100644 --- a/lldb/test/API/functionalities/dyld-launch-linux/TestDyldLaunchLinux.py +++ b/lldb/test/API/functionalities/dyld-launch-linux/TestDyldLaunchLinux.py @@ -7,6 +7,7 @@ import os from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestLinux64LaunchingViaDynamicLoader(TestBase): @@ -39,11 +40,16 @@ class TestLinux64LaunchingViaDynamicLoader(TestBase): breakpoint_shared_library = target.BreakpointCreateBySourceRegex( "get_signal_crash", lldb.SBFileSpec("signal_file.cpp") ) + inferior_exe_path = lldbutil.install_to_target( + self, self.getBuildArtifact("a.out") + ) + lldbutil.install_to_target(self, self.getBuildArtifact("libsignal_file.so")) + launch_info = lldb.SBLaunchInfo( [ "--library-path", self.get_process_working_directory(), - self.getBuildArtifact("a.out"), + inferior_exe_path, ] ) launch_info.SetWorkingDirectory(self.get_process_working_directory()) -- GitLab From f658d84e01bcdd49e27dc9ef80e1a6cc5f9417fe Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Tue, 14 May 2024 14:02:31 +0400 Subject: [PATCH 208/578] [lldb] Fixed the test TestExec (#92082) Install `secondprog` to the remote target if necessary. --- lldb/test/API/functionalities/exec/TestExec.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lldb/test/API/functionalities/exec/TestExec.py b/lldb/test/API/functionalities/exec/TestExec.py index aab1f5c9455f..968b879c4cd4 100644 --- a/lldb/test/API/functionalities/exec/TestExec.py +++ b/lldb/test/API/functionalities/exec/TestExec.py @@ -45,6 +45,8 @@ class ExecTestCase(TestBase): # Create the target target = self.dbg.CreateTarget(exe) + lldbutil.install_to_target(self, secondprog) + # Create any breakpoints we need breakpoint1 = target.BreakpointCreateBySourceRegex( "Set breakpoint 1 here", lldb.SBFileSpec("main.c", False) @@ -143,6 +145,8 @@ class ExecTestCase(TestBase): exe = self.getBuildArtifact("a.out") target = self.dbg.CreateTarget(exe) + lldbutil.install_to_target(self, self.getBuildArtifact("secondprog")) + (target, process, thread, breakpoint1) = lldbutil.run_to_source_breakpoint( self, "Set breakpoint 1 here", lldb.SBFileSpec("main.c", False) ) -- GitLab From 3aae916ff7fe9d0953aa63b2ba1d0e871f6f76fc Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Tue, 14 May 2024 18:10:28 +0800 Subject: [PATCH 209/578] Reland "[ValueTracking] Compute knownbits from known fp classes" (#92084) This patch relands https://github.com/llvm/llvm-project/pull/86409. I mistakenly thought that `Known.makeNegative()` clears the sign bit of `Known.Zero`. This patch fixes the assertion failure by explicitly clearing the sign bit. --- llvm/include/llvm/IR/PatternMatch.h | 2 +- llvm/lib/Analysis/ValueTracking.cpp | 35 +++ .../AMDGPU/amdgpu-simplify-libcall-pow.ll | 14 +- .../AMDGPU/amdgpu-simplify-libcall-pown.ll | 12 +- llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll | 10 +- .../test/Transforms/InstCombine/known-bits.ll | 284 ++++++++++++++++++ 6 files changed, 338 insertions(+), 19 deletions(-) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 171ddab977de..0d6d86cb47e6 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -1904,7 +1904,7 @@ template struct ElementWiseBitCast_match { ElementWiseBitCast_match(const Op_t &OpMatch) : Op(OpMatch) {} template bool match(OpTy *V) { - BitCastInst *I = dyn_cast(V); + auto *I = dyn_cast(V); if (!I) return false; Type *SrcType = I->getSrcTy(); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 375385aca7a3..c8c527a2d4d2 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1118,6 +1118,41 @@ static void computeKnownBitsFromOperator(const Operator *I, break; } + const Value *V; + // Handle bitcast from floating point to integer. + if (match(I, m_ElementWiseBitCast(m_Value(V))) && + V->getType()->isFPOrFPVectorTy()) { + Type *FPType = V->getType()->getScalarType(); + KnownFPClass Result = computeKnownFPClass(V, fcAllFlags, Depth + 1, Q); + FPClassTest FPClasses = Result.KnownFPClasses; + + if (Result.isKnownNever(fcNormal | fcSubnormal | fcNan)) { + Known.Zero.setAllBits(); + Known.One.setAllBits(); + + if (FPClasses & fcInf) + Known = Known.intersectWith(KnownBits::makeConstant( + APFloat::getInf(FPType->getFltSemantics()).bitcastToAPInt())); + + if (FPClasses & fcZero) + Known = Known.intersectWith(KnownBits::makeConstant( + APInt::getZero(FPType->getScalarSizeInBits()))); + + Known.Zero.clearSignBit(); + Known.One.clearSignBit(); + } + + if (Result.SignBit) { + if (*Result.SignBit) + Known.makeNegative(); + else + Known.makeNonNegative(); + } + + assert(!Known.hasConflict() && "Bits known to be one AND zero?"); + break; + } + // Handle cast from vector integer type to scalar or vector integer. auto *SrcVecTy = dyn_cast(SrcTy); if (!SrcVecTy || !SrcVecTy->getElementType()->isIntegerTy() || diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll index c4bd4bc126f7..5db25a59d33f 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll @@ -2216,7 +2216,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_sitofp(float %x, i32 %y) ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2304,7 +2304,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_uitofp(float %x, i32 %y) ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2353,7 +2353,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_uitofp_i256(float %x, i2 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2376,7 +2376,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_sitofp_i256(float %x, i2 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2399,7 +2399,7 @@ define <2 x float> @test_pow_afn_nnan_ninf_v2f32_known_integral_sitofp(<2 x floa ; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP4]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP5]] ; @@ -2448,7 +2448,7 @@ define <2 x float> @test_pow_afn_nnan_ninf_v2f32_known_integral_uitofp(<2 x floa ; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP4]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP5]] ; @@ -2560,7 +2560,7 @@ define float @test_pow_afn_f32_nnan_ninf__y_known_integral_trunc(float %x, float ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll index 8ddaf243db92..e298226ee7cc 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll @@ -680,7 +680,7 @@ define float @test_pown_afn_nnan_ninf_f32(float %x, i32 %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; @@ -703,7 +703,7 @@ define <2 x float> @test_pown_afn_nnan_ninf_v2f32(<2 x float> %x, <2 x i32> %y) ; CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP3]] ; @@ -772,7 +772,7 @@ define half @test_pown_afn_nnan_ninf_f16(half %x, i32 %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast half [[X]] to i16 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i16 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast half [[__EXP2]] to i16 -; CHECK-NEXT: [[TMP2:%.*]] = or i16 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i16 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i16 [[TMP2]] to half ; CHECK-NEXT: ret half [[TMP3]] ; @@ -795,7 +795,7 @@ define <2 x half> @test_pown_afn_nnan_ninf_v2f16(<2 x half> %x, <2 x i32> %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x half> [[X]] to <2 x i16> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i16> [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x half> [[__EXP2]] to <2 x i16> -; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i16> [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint <2 x i16> [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x i16> [[TMP2]] to <2 x half> ; CHECK-NEXT: ret <2 x half> [[TMP3]] ; @@ -829,7 +829,7 @@ define float @test_pown_fast_f32_strictfp(float %x, i32 %y) #1 { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; @@ -1075,7 +1075,7 @@ define float @test_pown_afn_ninf_nnan_f32__x_known_positive(float nofpclass(ninf ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; diff --git a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll index 204c8140d3f1..54ca33401ccf 100644 --- a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll +++ b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll @@ -360,7 +360,7 @@ declare half @_Z4pownDhi(half, i32) ; GCN-NATIVE: %0 = bitcast half %x to i16 ; GCN-NATIVE: %__pow_sign = and i16 %__yeven, %0 ; GCN-NATIVE: %1 = bitcast half %__exp2 to i16 -; GCN-NATIVE: %2 = or i16 %__pow_sign, %1 +; GCN-NATIVE: %2 = or disjoint i16 %__pow_sign, %1 ; GCN-NATIVE: %3 = bitcast i16 %2 to half define half @test_pown_f16(half %x, i32 %y) { entry: @@ -378,7 +378,7 @@ declare float @_Z4pownfi(float, i32) ; GCN: %[[r0:.*]] = bitcast float %tmp to i32 ; GCN: %__pow_sign = and i32 %[[r0]], -2147483648 ; GCN: %[[r1:.*]] = bitcast float %__exp2 to i32 -; GCN: %[[r2:.*]] = or i32 %__pow_sign, %[[r1]] +; GCN: %[[r2:.*]] = or disjoint i32 %__pow_sign, %[[r1]] ; GCN: store i32 %[[r2]], ptr addrspace(1) %a, align 4 define amdgpu_kernel void @test_pow(ptr addrspace(1) nocapture %a) { entry: @@ -414,7 +414,7 @@ entry: ; GCN: %[[r0:.*]] = bitcast float %tmp to i32 ; GCN: %__pow_sign = and i32 %__yeven, %[[r0]] ; GCN: %[[r1:.*]] = bitcast float %__exp2 to i32 -; GCN: %[[r2:.*]] = or i32 %__pow_sign, %[[r1]] +; GCN: %[[r2:.*]] = or disjoint i32 %__pow_sign, %[[r1]] ; GCN: store i32 %[[r2]], ptr addrspace(1) %a, align 4 define amdgpu_kernel void @test_pown(ptr addrspace(1) nocapture %a) { entry: @@ -438,7 +438,7 @@ declare <2 x half> @_Z3powDv2_DhS_(<2 x half>, <2 x half>) ; GCN: %1 = bitcast half %x to i16 ; GCN: %__pow_sign = and i16 %1, -32768 ; GCN: %2 = bitcast half %__exp2 to i16 -; GCN: %3 = or i16 %__pow_sign, %2 +; GCN: %3 = or disjoint i16 %__pow_sign, %2 ; GCN: %4 = bitcast i16 %3 to half define half @test_pow_fast_f16__y_13(half %x) { %powr = tail call fast half @_Z3powDhDh(half %x, half 13.0) @@ -453,7 +453,7 @@ define half @test_pow_fast_f16__y_13(half %x) { ; GCN: %1 = bitcast <2 x half> %x to <2 x i16> ; GCN: %__pow_sign = and <2 x i16> %1, ; GCN: %2 = bitcast <2 x half> %__exp2 to <2 x i16> -; GCN: %3 = or <2 x i16> %__pow_sign, %2 +; GCN: %3 = or disjoint <2 x i16> %__pow_sign, %2 ; GCN: %4 = bitcast <2 x i16> %3 to <2 x half> define <2 x half> @test_pow_fast_v2f16__y_13(<2 x half> %x) { %powr = tail call fast <2 x half> @_Z3powDv2_DhS_(<2 x half> %x, <2 x half> ) diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index 8b4249b2c25a..7a3802050051 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1374,5 +1374,289 @@ define i8 @nonzero_reduce_xor_vscale_odd( %xx) { ret i8 %r } +define i1 @test_sign_pos(float %x) { +; CHECK-LABEL: @test_sign_pos( +; CHECK-NEXT: ret i1 true +; + %fabs = call float @llvm.fabs.f32(float %x) + %y = bitcast float %fabs to i32 + %sign = icmp sgt i32 %y, -1 + ret i1 %sign +} + +define i1 @test_sign_pos_half(half %x) { +; CHECK-LABEL: @test_sign_pos_half( +; CHECK-NEXT: ret i1 true +; + %fabs = call half @llvm.fabs.f16(half %x) + %y = bitcast half %fabs to i16 + %sign = icmp sgt i16 %y, -1 + ret i1 %sign +} + +define i1 @test_sign_pos_half_non_elementwise(<2 x half> %x) { +; CHECK-LABEL: @test_sign_pos_half_non_elementwise( +; CHECK-NEXT: [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]]) +; CHECK-NEXT: [[Y:%.*]] = bitcast <2 x half> [[FABS]] to i32 +; CHECK-NEXT: [[SIGN:%.*]] = icmp sgt i32 [[Y]], -1 +; CHECK-NEXT: ret i1 [[SIGN]] +; + %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x) + %y = bitcast <2 x half> %fabs to i32 + %sign = icmp sgt i32 %y, -1 + ret i1 %sign +} + +define i1 @test_sign_neg(float %x) { +; CHECK-LABEL: @test_sign_neg( +; CHECK-NEXT: ret i1 true +; + %fabs = call float @llvm.fabs.f32(float %x) + %fnabs = fneg float %fabs + %y = bitcast float %fnabs to i32 + %sign = icmp slt i32 %y, 0 + ret i1 %sign +} + +define <2 x i1> @test_sign_pos_vec(<2 x float> %x) { +; CHECK-LABEL: @test_sign_pos_vec( +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %x) + %y = bitcast <2 x float> %fabs to <2 x i32> + %sign = icmp slt <2 x i32> %y, zeroinitializer + ret <2 x i1> %sign +} + +define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) { +; CHECK-LABEL: @test_inf_only( +; CHECK-NEXT: ret i32 2139095040 +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2147483647 + ret i32 %and +} + +define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) { +; CHECK-LABEL: @test_inf_only_bfloat( +; CHECK-NEXT: ret i16 32640 +; + %y = bitcast bfloat %x to i16 + %and = and i16 %y, 32767 + ret i16 %and +} + +define i128 @test_inf_only_ppc_fp128(ppc_fp128 nofpclass(nan sub norm zero) %x) { +; CHECK-LABEL: @test_inf_only_ppc_fp128( +; CHECK-NEXT: ret i128 9218868437227405312 +; + %y = bitcast ppc_fp128 %x to i128 + %and = and i128 %y, 170141183460469231731687303715884105727 + ret i128 %and +} + +define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) { +; CHECK-LABEL: @test_zero_only( +; CHECK-NEXT: ret i32 0 +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2147483647 + ret i32 %and +} + +define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) { +; CHECK-LABEL: @test_zero_only_non_ieee( +; CHECK-NEXT: ret i80 0 +; + %y = bitcast x86_fp80 %x to i80 + %and = and i80 %y, 604462909807314587353087 + ret i80 %and +} + +define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) { +; CHECK-LABEL: @test_inf_nan_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2130706432 + ret i32 %and +} + +define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) { +; CHECK-LABEL: @test_sub_zero_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2130706432 + ret i32 %and +} + +define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) { +; CHECK-LABEL: @test_inf_zero_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 8388608 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 16777215 + ret i32 %and +} + +; Make sure that the signbit is cleared. +define i32 @test_ninf_only(double %x) { +; CHECK-LABEL: @test_ninf_only( +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[X:%.*]], 0xFFF0000000000000 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: ret i32 0 +; CHECK: if.else: +; CHECK-NEXT: ret i32 0 +; + %cmp = fcmp oeq double %x, 0xFFF0000000000000 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %cast = bitcast double %x to i64 + %trunc = trunc i64 %cast to i32 + ret i32 %trunc + +if.else: + ret i32 0 +} + +define i1 @test_simplify_icmp(i32 %x) { +; CHECK-LABEL: @test_simplify_icmp( +; CHECK-NEXT: ret i1 false +; + %cast1 = uitofp i32 %x to double + %cast2 = bitcast double %cast1 to i64 + %mask = and i64 %cast2, -140737488355328 + %cmp = icmp eq i64 %mask, -1970324836974592 + ret i1 %cmp +} + +define i32 @test_snan_quiet_bit1(float nofpclass(sub norm inf qnan) %x) { +; CHECK-LABEL: @test_snan_quiet_bit1( +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 4194304 +; CHECK-NEXT: ret i32 [[MASKED]] +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 4194304 + ret i32 %masked +} + +define i32 @test_snan_quiet_bit2(float nofpclass(sub norm inf qnan) %x) { +; CHECK-LABEL: @test_snan_quiet_bit2( +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 2097152 +; CHECK-NEXT: ret i32 [[MASKED]] +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 2097152 + ret i32 %masked +} + +define i32 @test_qnan_quiet_bit1(float nofpclass(sub norm inf snan) %x) { +; CHECK-LABEL: @test_qnan_quiet_bit1( +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 4194304 +; CHECK-NEXT: ret i32 [[MASKED]] +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 4194304 + ret i32 %masked +} + +define i32 @test_qnan_quiet_bit2(float nofpclass(sub norm inf snan) %x) { +; CHECK-LABEL: @test_qnan_quiet_bit2( +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 2097152 +; CHECK-NEXT: ret i32 [[MASKED]] +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 2097152 + ret i32 %masked +} + +define i16 @test_simplify_mask(i32 %ui, float %x) { +; CHECK-LABEL: @test_simplify_mask( +; CHECK-NEXT: [[CONV:%.*]] = uitofp i32 [[UI:%.*]] to float +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[CONV]], [[X:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]] +; CHECK: if.end: +; CHECK-NEXT: ret i16 31744 +; CHECK: if.else: +; CHECK-NEXT: ret i16 0 +; + %conv = uitofp i32 %ui to float + %cmp = fcmp olt float %x, %conv + br i1 %cmp, label %if.else, label %if.end + +if.end: + %cast = bitcast float %conv to i32 + %shr = lshr i32 %cast, 16 + %trunc = trunc i32 %shr to i16 + %and = and i16 %trunc, -32768 + %or = or disjoint i16 %and, 31744 + ret i16 %or + +if.else: + ret i16 0 +} + +; TODO: %cmp always evaluates to false + +define i1 @test_simplify_icmp2(double %x) { +; CHECK-LABEL: @test_simplify_icmp2( +; CHECK-NEXT: [[ABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]]) +; CHECK-NEXT: [[COND:%.*]] = fcmp oeq double [[ABS]], 0x7FF0000000000000 +; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[CAST:%.*]] = bitcast double [[X]] to i64 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[CAST]], 3458764513820540928 +; CHECK-NEXT: ret i1 [[CMP]] +; CHECK: if.else: +; CHECK-NEXT: ret i1 false +; + %abs = tail call double @llvm.fabs.f64(double %x) + %cond = fcmp oeq double %abs, 0x7FF0000000000000 + br i1 %cond, label %if.then, label %if.else + +if.then: + %cast = bitcast double %x to i64 + %cmp = icmp eq i64 %cast, 3458764513820540928 + ret i1 %cmp + +if.else: + ret i1 false +} + +define i32 @test_snan_only(float nofpclass(qnan sub norm zero inf) %x) { +; CHECK-LABEL: @test_snan_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 4194304 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 4194304 + ret i32 %and +} + +define i32 @test_qnan_only(float nofpclass(snan sub norm zero inf) %x) { +; CHECK-LABEL: @test_qnan_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 4194304 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 4194304 + ret i32 %and +} + declare void @use(i1) declare void @sink(i8) -- GitLab From 58b9564d5d12063bb9c662039802ede8df615374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 14 May 2024 10:47:12 +0200 Subject: [PATCH 210/578] [clang][Interp][NFC] Add some assertions Make sure we pass a non-null Descriptor when creating a new Block. --- clang/lib/AST/Interp/InterpBlock.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/Interp/InterpBlock.h b/clang/lib/AST/Interp/InterpBlock.h index 6d5856fbd4ea..506034e880d0 100644 --- a/clang/lib/AST/Interp/InterpBlock.h +++ b/clang/lib/AST/Interp/InterpBlock.h @@ -51,11 +51,15 @@ public: /// Creates a new block. Block(const std::optional &DeclID, const Descriptor *Desc, bool IsStatic = false, bool IsExtern = false) - : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {} + : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) { + assert(Desc); + } Block(const Descriptor *Desc, bool IsStatic = false, bool IsExtern = false) : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern), - Desc(Desc) {} + Desc(Desc) { + assert(Desc); + } /// Returns the block's descriptor. const Descriptor *getDescriptor() const { return Desc; } -- GitLab From 0aa5fa9630d0f4ea707c5b8d5cfa2f4bc8d06a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 14 May 2024 10:47:57 +0200 Subject: [PATCH 211/578] [clang][Interp][NFC] Improve Pointer::print() --- clang/lib/AST/Interp/Pointer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index 12bef73f7e21..d2e34f2c7f09 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -181,12 +181,12 @@ void Pointer::print(llvm::raw_ostream &OS) const { if (isBlockPointer()) { OS << "Block) {"; - if (PointeeStorage.BS.Base == RootPtrMark) - OS << "rootptr, "; + if (isRoot()) + OS << "rootptr(" << PointeeStorage.BS.Base << "), "; else OS << PointeeStorage.BS.Base << ", "; - if (Offset == PastEndMark) + if (isElementPastEnd()) OS << "pastend, "; else OS << Offset << ", "; -- GitLab From 5865482049872d3ae52ea5559abb9e8f4a1e55e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 14 May 2024 10:48:26 +0200 Subject: [PATCH 212/578] [clang][Interp][NFC] Don't pass on metadata size for composite arrays We don't need the metadata size for every element, just for the topmost descriptor. --- clang/lib/AST/Interp/Program.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index 6606149f1f69..0b95db849269 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -372,7 +372,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, // Arrays of composites. In this case, the array is a list of pointers, // followed by the actual elements. const Descriptor *ElemDesc = createDescriptor( - D, ElemTy.getTypePtr(), MDSize, IsConst, IsTemporary); + D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary); if (!ElemDesc) return nullptr; unsigned ElemSize = -- GitLab From c1bd68867497cf6e2f2afdba1a3a2993a47b5856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 14 May 2024 11:17:49 +0200 Subject: [PATCH 213/578] [clang][Interp] Fix some dummy-related FIXME comments --- clang/lib/AST/Interp/Interp.h | 9 +++++---- clang/lib/AST/Interp/Pointer.h | 7 ------- clang/lib/AST/Interp/Program.cpp | 6 +++++- clang/test/AST/Interp/arrays.cpp | 15 +++++++++++++++ 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index a0bf87430012..d9f23a4b8c96 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1569,9 +1569,7 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, APSInt NewIndex = (Op == ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset); S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index) - << NewIndex - << /*array*/ static_cast(!Ptr.inArray()) - << static_cast(MaxIndex); + << NewIndex << /*array*/ static_cast(!Ptr.inArray()) << MaxIndex; Invalid = true; }; @@ -1598,7 +1596,7 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, } } - if (Invalid && !Ptr.isDummy() && S.getLangOpts().CPlusPlus) + if (Invalid && S.getLangOpts().CPlusPlus) return false; // Offset is valid - compute it on unsigned. @@ -2110,6 +2108,9 @@ inline bool ArrayDecay(InterpState &S, CodePtr OpPC) { return true; } + if (!CheckRange(S, OpPC, Ptr, CSK_ArrayToPointer)) + return false; + if (!Ptr.isUnknownSizeArray() || Ptr.isDummy()) { S.Stk.push(Ptr.atIndex(0)); return true; diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index 79fab05670e9..9900f37e60d4 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -384,11 +384,6 @@ public: bool isUnknownSizeArray() const { if (!isBlockPointer()) return false; - // If this points inside a dummy block, return true. - // FIXME: This might change in the future. If it does, we need - // to set the proper Ctor/Dtor functions for dummy Descriptors. - if (!isRoot() && isDummy()) - return true; return getFieldDesc()->isUnknownSizeArray(); } /// Checks if the pointer points to an array. @@ -560,8 +555,6 @@ public: if (!asBlockPointer().Pointee) return false; - if (isDummy()) - return false; return isElementPastEnd() || getSize() == getOffset(); } diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index 0b95db849269..31a64e13d2b1 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -144,8 +144,12 @@ std::optional Program::getOrCreateDummy(const ValueDecl *VD) { if (auto It = DummyVariables.find(VD); It != DummyVariables.end()) return It->second; + QualType QT = VD->getType(); + if (const auto *RT = QT->getAs()) + QT = RT->getPointeeType(); + Descriptor *Desc; - if (std::optional T = Ctx.classify(VD->getType())) + if (std::optional T = Ctx.classify(QT)) Desc = createDescriptor(VD, *T, std::nullopt, true, false); else Desc = createDescriptor(VD, VD->getType().getTypePtr(), std::nullopt, true, diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp index f6d265d4b3d1..929f25b95fa1 100644 --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -580,3 +580,18 @@ constexpr ptrdiff_t d3 = &melchizedek[0] - &melchizedek[1]; // ok /// GH#88018 const int SZA[] = {}; void testZeroSizedArrayAccess() { unsigned c = SZA[4]; } + +#if __cplusplus >= 202002L +constexpr int test_multiarray2() { // both-error {{never produces a constant expression}} + int multi2[2][1]; // both-note {{declared here}} + return multi2[2][0]; // both-note {{cannot access array element of pointer past the end of object}} \ + // both-warning {{array index 2 is past the end of the array (that has type 'int[2][1]')}} +} + +/// Same but with a dummy pointer. +int multi22[2][2]; // both-note {{declared here}} +int test_multiarray22() { + return multi22[2][0]; // both-warning {{array index 2 is past the end of the array (that has type 'int[2][2]')}} +} + +#endif -- GitLab From 31fb0ae23d3d1a1b90198a68c80c9116d844a01f Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 14 May 2024 11:54:38 +0100 Subject: [PATCH 214/578] [PowerPC] Regenerate and_sext.ll with test checks I've kept the grep checks for extsh/extsb instructions, but we can now see the actual codegen as well --- llvm/test/CodeGen/PowerPC/and_sext.ll | 45 ++++++++++++++++++--------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/llvm/test/CodeGen/PowerPC/and_sext.ll b/llvm/test/CodeGen/PowerPC/and_sext.ll index 3b576ca18ee7..b67b86bd5132 100644 --- a/llvm/test/CodeGen/PowerPC/and_sext.ll +++ b/llvm/test/CodeGen/PowerPC/and_sext.ll @@ -1,28 +1,43 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 ; These tests should not contain a sign extend. +; RUN: llc -verify-machineinstrs < %s -mtriple=ppc32-- | FileCheck %s ; RUN: llc -verify-machineinstrs < %s -mtriple=ppc32-- | not grep extsh ; RUN: llc -verify-machineinstrs < %s -mtriple=ppc32-- | not grep extsb define i32 @test1(i32 %mode.0.i.0) { - %tmp.79 = trunc i32 %mode.0.i.0 to i16 - %tmp.80 = sext i16 %tmp.79 to i32 - %tmp.81 = and i32 %tmp.80, 24 - ret i32 %tmp.81 +; CHECK-LABEL: test1: +; CHECK: # %bb.0: +; CHECK-NEXT: rlwinm 3, 3, 0, 27, 28 +; CHECK-NEXT: blr + %tmp.79 = trunc i32 %mode.0.i.0 to i16 + %tmp.80 = sext i16 %tmp.79 to i32 + %tmp.81 = and i32 %tmp.80, 24 + ret i32 %tmp.81 } define signext i16 @test2(i16 signext %X, i16 signext %x) { - %tmp = sext i16 %X to i32 - %tmp1 = sext i16 %x to i32 - %tmp2 = add i32 %tmp, %tmp1 - %tmp4 = ashr i32 %tmp2, 1 - %tmp5 = trunc i32 %tmp4 to i16 - %tmp45 = sext i16 %tmp5 to i32 - %retval = trunc i32 %tmp45 to i16 - ret i16 %retval +; CHECK-LABEL: test2: +; CHECK: # %bb.0: +; CHECK-NEXT: add 3, 3, 4 +; CHECK-NEXT: srawi 3, 3, 1 +; CHECK-NEXT: blr + %tmp = sext i16 %X to i32 + %tmp1 = sext i16 %x to i32 + %tmp2 = add i32 %tmp, %tmp1 + %tmp4 = ashr i32 %tmp2, 1 + %tmp5 = trunc i32 %tmp4 to i16 + %tmp45 = sext i16 %tmp5 to i32 + %retval = trunc i32 %tmp45 to i16 + ret i16 %retval } define signext i16 @test3(i32 zeroext %X) { - %tmp1 = lshr i32 %X, 16 - %tmp2 = trunc i32 %tmp1 to i16 - ret i16 %tmp2 +; CHECK-LABEL: test3: +; CHECK: # %bb.0: +; CHECK-NEXT: srawi 3, 3, 16 +; CHECK-NEXT: blr + %tmp1 = lshr i32 %X, 16 + %tmp2 = trunc i32 %tmp1 to i16 + ret i16 %tmp2 } -- GitLab From c34d1893cb8b485e6871512ef4e743bfa2d462f8 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Tue, 14 May 2024 06:00:23 -0500 Subject: [PATCH 215/578] [Offload] Remove support for old "BUILD_PLUGIN" options. (#91644) Summary: Since the move to the statically linked plugins, we added a new way to directly control which plugins will be added. Delete these old ones as they will cause the build to fail and suggest the new format. --- offload/CMakeLists.txt | 6 ++++++ offload/plugins-nextgen/amdgpu/CMakeLists.txt | 7 ------- offload/plugins-nextgen/cuda/CMakeLists.txt | 7 ------- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/offload/CMakeLists.txt b/offload/CMakeLists.txt index 3f77583ffa3b..626df8125063 100644 --- a/offload/CMakeLists.txt +++ b/offload/CMakeLists.txt @@ -151,6 +151,11 @@ if (NOT LIBOMPTARGET_LLVM_INCLUDE_DIRS) message(FATAL_ERROR "Missing definition for LIBOMPTARGET_LLVM_INCLUDE_DIRS") endif() +if(DEFINED LIBOMPTARGET_BUILD_CUDA_PLUGIN OR + DEFINED LIBOMPTARGET_BUILD_AMDGPU_PLUGIN) + message(WARNING "Option removed, use 'LIBOMPTARGET_PLUGINS_TO_BUILD' instead") +endif() + set(LIBOMPTARGET_ALL_PLUGIN_TARGETS amdgpu cuda host) set(LIBOMPTARGET_PLUGINS_TO_BUILD "all" CACHE STRING "Semicolon-separated list of plugins to use: cuda, amdgpu, host or \"all\".") @@ -158,6 +163,7 @@ set(LIBOMPTARGET_PLUGINS_TO_BUILD "all" CACHE STRING if(LIBOMPTARGET_PLUGINS_TO_BUILD STREQUAL "all") set(LIBOMPTARGET_PLUGINS_TO_BUILD ${LIBOMPTARGET_ALL_PLUGIN_TARGETS}) endif() +message("Building with support for ${LIBOMPTARGET_PLUGINS_TO_BUILD} plugins") set(LIBOMPTARGET_ENUM_PLUGIN_TARGETS "") foreach(plugin IN LISTS LIBOMPTARGET_PLUGINS_TO_BUILD) diff --git a/offload/plugins-nextgen/amdgpu/CMakeLists.txt b/offload/plugins-nextgen/amdgpu/CMakeLists.txt index 738183f8945e..280cb57e22e9 100644 --- a/offload/plugins-nextgen/amdgpu/CMakeLists.txt +++ b/offload/plugins-nextgen/amdgpu/CMakeLists.txt @@ -12,13 +12,6 @@ ##===----------------------------------------------------------------------===## ################################################################################ -set(LIBOMPTARGET_BUILD_AMDGPU_PLUGIN TRUE CACHE BOOL - "Whether to build AMDGPU plugin") -if (NOT LIBOMPTARGET_BUILD_AMDGPU_PLUGIN) - libomptarget_say("Not building AMDGPU NextGen offloading plugin: LIBOMPTARGET_BUILD_AMDGPU_PLUGIN is false") - return() -endif() - # as of rocm-3.7, hsa is installed with cmake packages and kmt is found via hsa find_package(hsa-runtime64 QUIET 1.2.0 HINTS ${CMAKE_INSTALL_PREFIX} PATHS /opt/rocm) diff --git a/offload/plugins-nextgen/cuda/CMakeLists.txt b/offload/plugins-nextgen/cuda/CMakeLists.txt index dd684bb22343..3f3388e56c5f 100644 --- a/offload/plugins-nextgen/cuda/CMakeLists.txt +++ b/offload/plugins-nextgen/cuda/CMakeLists.txt @@ -9,13 +9,6 @@ # Build a plugin for a CUDA machine if available. # ##===----------------------------------------------------------------------===## -set(LIBOMPTARGET_BUILD_CUDA_PLUGIN TRUE CACHE BOOL - "Whether to build CUDA plugin") -if (NOT LIBOMPTARGET_BUILD_CUDA_PLUGIN) - libomptarget_say("Not building CUDA NextGen offloading plugin: LIBOMPTARGET_BUILD_CUDA_PLUGIN is false") - return() -endif() - if (NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(ppc64le)|(aarch64)$" AND CMAKE_SYSTEM_NAME MATCHES "Linux")) libomptarget_say("Not building CUDA NextGen offloading plugin: only support CUDA in Linux x86_64, ppc64le, or aarch64 hosts.") return() -- GitLab From 363258a3ccbb752ec23f681d19b6a874c4db99ab Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Tue, 14 May 2024 06:00:34 -0500 Subject: [PATCH 216/578] [Offload] Remove old references to `isCtor` (#91766) Summary: These have long since been removed, support for ctors / dtors now happens through special kernels the backend creates. --- offload/plugins-nextgen/common/include/PluginInterface.h | 6 ------ offload/plugins-nextgen/common/src/PluginInterface.cpp | 5 +---- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h index e7a008f3a857..c396099ac625 100644 --- a/offload/plugins-nextgen/common/include/PluginInterface.h +++ b/offload/plugins-nextgen/common/include/PluginInterface.h @@ -270,12 +270,6 @@ struct GenericKernelTy { /// Get the kernel name. const char *getName() const { return Name; } - /// Return true if this kernel is a constructor or destructor. - bool isCtorOrDtor() const { - // TODO: This is not a great solution and should be revisited. - return StringRef(Name).ends_with("tor"); - } - /// Get the kernel image. DeviceImageTy &getImage() const { assert(ImagePtr && "Kernel is not initialized!"); diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp index fae197527850..a5c8cce63fac 100644 --- a/offload/plugins-nextgen/common/src/PluginInterface.cpp +++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp @@ -470,7 +470,7 @@ GenericKernelTy::getKernelLaunchEnvironment( // Ctor/Dtor have no arguments, replaying uses the original kernel launch // environment. Older versions of the compiler do not generate a kernel // launch environment. - if (isCtorOrDtor() || RecordReplay.isReplaying() || + if (RecordReplay.isReplaying() || Version < OMP_KERNEL_ARG_MIN_VERSION_WITH_DYN_PTR) return nullptr; @@ -579,9 +579,6 @@ void *GenericKernelTy::prepareArgs( uint32_t &NumArgs, llvm::SmallVectorImpl &Args, llvm::SmallVectorImpl &Ptrs, KernelLaunchEnvironmentTy *KernelLaunchEnvironment) const { - if (isCtorOrDtor()) - return nullptr; - uint32_t KLEOffset = !!KernelLaunchEnvironment; NumArgs += KLEOffset; -- GitLab From cbd72cb0deec31a5c3063cf1f1af759761115eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Warzy=C5=84ski?= Date: Tue, 14 May 2024 12:08:57 +0100 Subject: [PATCH 217/578] [mlir][vector] Split `TransposeOpLowering` into 2 patterns (#91935) Splits `TransposeOpLowering` into two patterns: 1. `Transpose2DWithUnitDimToShapeCast` - rewrites 2D `vector.transpose` as `vector.shape_cast` (there has to be at least one unit dim), 2. `TransposeOpLowering` - the original pattern without the part extracted into `Transpose2DWithUnitDimToShapeCast`. The rationale behind the split: * the output generated by `Transpose2DWithUnitDimToShapeCast` doesn't really match the intended output from `TransposeOpLowering` as documented in the source file - it doesn't make much sense to keep it embedded inside `TransposeOpLowering`, * `Transpose2DWithUnitDimToShapeCast` _does_ work for scalable vectors, `TransposeOpLowering` _does_ not. --- .../Transforms/LowerVectorTranspose.cpp | 86 ++++++++++++++----- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/mlir/lib/Dialect/Vector/Transforms/LowerVectorTranspose.cpp b/mlir/lib/Dialect/Vector/Transforms/LowerVectorTranspose.cpp index 7011c478fefb..ca8a6f6d82a6 100644 --- a/mlir/lib/Dialect/Vector/Transforms/LowerVectorTranspose.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/LowerVectorTranspose.cpp @@ -326,6 +326,10 @@ public: VectorType inputType = op.getSourceVectorType(); VectorType resType = op.getResultVectorType(); + if (inputType.isScalable()) + return rewriter.notifyMatchFailure( + op, "This lowering does not support scalable vectors"); + // Set up convenience transposition table. ArrayRef transp = op.getPermutation(); @@ -334,28 +338,6 @@ public: return rewriter.notifyMatchFailure( op, "Options specifies lowering to shuffle"); - // Replace: - // vector.transpose %0, [1, 0] : vector> to - // vector<1xnxelty> - // with: - // vector.shape_cast %0 : vector> to vector<1xnxelty> - // - // Source with leading unit dim (inverse) is also replaced. Unit dim must - // be fixed. Non-unit can be scalable. - if (resType.getRank() == 2 && - ((resType.getShape().front() == 1 && - !resType.getScalableDims().front()) || - (resType.getShape().back() == 1 && - !resType.getScalableDims().back())) && - transp == ArrayRef({1, 0})) { - rewriter.replaceOpWithNewOp(op, resType, input); - return success(); - } - - // TODO: Add support for scalable vectors - if (inputType.isScalable()) - return failure(); - // Handle a true 2-D matrix transpose differently when requested. if (vectorTransformOptions.vectorTransposeLowering == vector::VectorTransposeLowering::Flat && @@ -411,6 +393,64 @@ private: vector::VectorTransformsOptions vectorTransformOptions; }; +/// Rewrites vector.transpose as vector.shape_cast. This pattern is only applied +/// to 2D vectors with at least one unit dim. For example: +/// +/// Replace: +/// vector.transpose %0, [1, 0] : vector<4x1xi32>> to +/// vector<1x4xi32> +/// with: +/// vector.shape_cast %0 : vector<4x1xi32> to vector<1x4xi32> +/// +/// Source with leading unit dim (inverse) is also replaced. Unit dim must +/// be fixed. Non-unit dim can be scalable. +/// +/// TODO: This pattern was introduced specifically to help lower scalable +/// vectors. In hindsight, a more specialised canonicalization (for shape_cast's +/// to cancel out) would be preferable: +/// +/// BEFORE: +/// %0 = some_op +/// %1 = vector.shape_cast %0 : vector<[4]xf32> to vector<[4]x1xf32> +/// %2 = vector.transpose %1 [1, 0] : vector<[4]x1xf32> to vector<1x[4]xf32> +/// AFTER: +/// %0 = some_op +/// %1 = vector.shape_cast %0 : vector<[4]xf32> to vector<1x[4]xf32> +/// +/// Given the context above, we may want to consider (re-)moving this pattern +/// at some later time. I am leaving it for now in case there are other users +/// that I am not aware of. +class Transpose2DWithUnitDimToShapeCast + : public OpRewritePattern { +public: + using OpRewritePattern::OpRewritePattern; + + Transpose2DWithUnitDimToShapeCast(MLIRContext *context, + PatternBenefit benefit = 1) + : OpRewritePattern(context, benefit) {} + + LogicalResult matchAndRewrite(vector::TransposeOp op, + PatternRewriter &rewriter) const override { + Value input = op.getVector(); + VectorType resType = op.getResultVectorType(); + + // Set up convenience transposition table. + ArrayRef transp = op.getPermutation(); + + if (resType.getRank() == 2 && + ((resType.getShape().front() == 1 && + !resType.getScalableDims().front()) || + (resType.getShape().back() == 1 && + !resType.getScalableDims().back())) && + transp == ArrayRef({1, 0})) { + rewriter.replaceOpWithNewOp(op, resType, input); + return success(); + } + + return failure(); + } +}; + /// Rewrite a 2-D vector.transpose as a sequence of shuffle ops. /// If the strategy is Shuffle1D, it will be lowered to: /// vector.shape_cast 2D -> 1D @@ -483,6 +523,8 @@ private: void mlir::vector::populateVectorTransposeLoweringPatterns( RewritePatternSet &patterns, VectorTransformsOptions options, PatternBenefit benefit) { + patterns.add(patterns.getContext(), + benefit); patterns.add( options, patterns.getContext(), benefit); } -- GitLab From e6d3a4212d20b49a8e63f11fedea79cccf261479 Mon Sep 17 00:00:00 2001 From: aengelke Date: Tue, 14 May 2024 13:13:24 +0200 Subject: [PATCH 218/578] [CodeGen] Use SmallVector for FixedStackPSVs (#91760) Frame indices are dense and consecutive, so use a vector instead of a std::map. Due to possibly negative frame indices, use zig-zag encoding. IndexedMap was not usable, as it attempted to copy the null value, which is not possible with a std::unique_ptr. This is just a minor performance improvement, but a low-hanging fruit. --- llvm/include/llvm/CodeGen/PseudoSourceValueManager.h | 4 ++-- llvm/lib/CodeGen/PseudoSourceValue.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/CodeGen/PseudoSourceValueManager.h b/llvm/include/llvm/CodeGen/PseudoSourceValueManager.h index 4be6ae0b60cb..8ea043bf0327 100644 --- a/llvm/include/llvm/CodeGen/PseudoSourceValueManager.h +++ b/llvm/include/llvm/CodeGen/PseudoSourceValueManager.h @@ -13,10 +13,10 @@ #ifndef LLVM_CODEGEN_PSEUDOSOURCEVALUEMANAGER_H #define LLVM_CODEGEN_PSEUDOSOURCEVALUEMANAGER_H +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/IR/ValueMap.h" -#include namespace llvm { @@ -27,7 +27,7 @@ class TargetMachine; class PseudoSourceValueManager { const TargetMachine &TM; const PseudoSourceValue StackPSV, GOTPSV, JumpTablePSV, ConstantPoolPSV; - std::map> FSValues; + SmallVector> FSValues; StringMap> ExternalCallEntries; ValueMap &V = FSValues[FI]; + // Frame index is often continuously positive, but can be negative. Use + // zig-zag encoding for dense index into FSValues vector. + unsigned Idx = (2 * unsigned(FI)) ^ (FI >> (sizeof(FI) * 8 - 1)); + if (FSValues.size() <= Idx) + FSValues.resize(Idx + 1); + std::unique_ptr &V = FSValues[Idx]; if (!V) V = std::make_unique(FI, TM); return V.get(); -- GitLab From c7c5666aac543a49b485a133f4a94865e2613a43 Mon Sep 17 00:00:00 2001 From: jeanPerier Date: Tue, 14 May 2024 13:34:46 +0200 Subject: [PATCH 219/578] [flang] Do not hoist all scalar sub-expressions from WHERE constructs (#91395) The HLFIR pass lowering WHERE (hlfir.where op) was too aggressive in its hoisting of scalar sub-expressions from LHS/RHS/MASKS outside of the loops generated for the WHERE construct. This violated F'2023 10.2.3.2 point 10 that stipulated that elemental operations must be evaluated only for elements corresponding to true values, because scalar operations are still elemental, and hoisting them is invalid if they could have side effects (e.g, division by zero) and if the MASK is always false (i.e., the loop body is never evaluated). The difficulty is that 10.2.3.2 point 9 mandates that nonelemental function must be evaluated before the loops. So it is not possible to simply stop hoisting non hlfir.elemental operations. Marking calls with an elemental/nonelemental attribute would not allow the pass to be correct if inlining is run before and drops this information, beside, extracting the argument tree that may have been CSE-ed with the rest of the expression evaluation would be a bit combursome. Instead, lower nonelemental calls into a new hlfir.exactly_once operation that will allow retaining the information that the operations contained inside its region must be hoisted. This allows inlining to operate before if desired in order to improve alias analysis. The LowerHLFIROrderedAssignments pass is updated to only hoist the operations contained inside hlfir.exactly_once bodies. --- flang/include/flang/Lower/StatementContext.h | 14 ++ .../include/flang/Optimizer/HLFIR/HLFIROps.td | 24 ++- flang/lib/Lower/Bridge.cpp | 45 ++-- flang/lib/Lower/ConvertCall.cpp | 38 ++++ .../LowerHLFIROrderedAssignments.cpp | 130 ++++++++++-- .../HLFIR/order_assignments/impure-where.fir | 9 +- .../order_assignments/inlined-stack-temp.fir | 2 +- .../user-defined-assignment-finalization.fir | 31 +-- .../HLFIR/order_assignments/where-cleanup.f90 | 44 ++++ .../where-codegen-no-conflict.fir | 4 +- .../order_assignments/where-hoisting.f90 | 50 +++++ flang/test/Lower/HLFIR/where-nonelemental.f90 | 198 ++++++++++++++++++ 12 files changed, 525 insertions(+), 64 deletions(-) create mode 100644 flang/test/HLFIR/order_assignments/where-cleanup.f90 create mode 100644 flang/test/HLFIR/order_assignments/where-hoisting.f90 create mode 100644 flang/test/Lower/HLFIR/where-nonelemental.f90 diff --git a/flang/include/flang/Lower/StatementContext.h b/flang/include/flang/Lower/StatementContext.h index cec9641d43a0..7776edc93ed7 100644 --- a/flang/include/flang/Lower/StatementContext.h +++ b/flang/include/flang/Lower/StatementContext.h @@ -18,6 +18,15 @@ #include #include +namespace mlir { +class Location; +class Region; +} // namespace mlir + +namespace fir { +class FirOpBuilder; +} + namespace Fortran::lower { /// When lowering a statement, temporaries for intermediate results may be @@ -105,6 +114,11 @@ private: llvm::SmallVector> cufs; }; +/// If \p context contains any cleanups, ensure \p region has a block, and +/// generate the cleanup inside that block. +void genCleanUpInRegionIfAny(mlir::Location loc, fir::FirOpBuilder &builder, + mlir::Region ®ion, StatementContext &context); + } // namespace Fortran::lower #endif // FORTRAN_LOWER_STATEMENTCONTEXT_H diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td index 9558a6832972..376417e3c353 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td @@ -1330,7 +1330,8 @@ def hlfir_RegionAssignOp : hlfir_Op<"region_assign", [hlfir_OrderedAssignmentTre } def hlfir_YieldOp : hlfir_Op<"yield", [Terminator, ParentOneOf<["RegionAssignOp", - "ElementalAddrOp", "ForallOp", "ForallMaskOp", "WhereOp", "ElseWhereOp"]>, + "ElementalAddrOp", "ForallOp", "ForallMaskOp", "WhereOp", "ElseWhereOp", + "ExactlyOnceOp"]>, SingleBlockImplicitTerminator<"fir::FirEndOp">, RecursivelySpeculatable, RecursiveMemoryEffects]> { @@ -1595,6 +1596,27 @@ def hlfir_ForallMaskOp : hlfir_AssignmentMaskOp<"forall_mask"> { let hasVerifier = 1; } +def hlfir_ExactlyOnceOp : hlfir_Op<"exactly_once", [RecursiveMemoryEffects]> { + let summary = "Execute exactly once its region in a WhereOp"; + let description = [{ + Inside a Where assignment, Fortran requires a non elemental call and its + arguments to be executed exactly once, regardless of the mask values. + This operation allows holding these evaluations that cannot be hoisted + until potential parent Forall loops have been created. + It also allows inlining the calls without losing the information that + these calls must be hoisted. + }]; + + let regions = (region SizedRegion<1>:$body); + + let results = (outs AnyFortranEntity:$result); + + let assemblyFormat = [{ + attr-dict `:` type($result) + $body + }]; +} + def hlfir_WhereOp : hlfir_AssignmentMaskOp<"where"> { let summary = "Represent a Fortran where construct or statement"; let description = [{ diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 79d6bbf65cbf..596049fcfc92 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -3687,22 +3687,6 @@ private: return hlfir::Entity{valueAndPair.first}; } - static void - genCleanUpInRegionIfAny(mlir::Location loc, fir::FirOpBuilder &builder, - mlir::Region ®ion, - Fortran::lower::StatementContext &context) { - if (!context.hasCode()) - return; - mlir::OpBuilder::InsertPoint insertPt = builder.saveInsertionPoint(); - if (region.empty()) - builder.createBlock(®ion); - else - builder.setInsertionPointToEnd(®ion.front()); - context.finalizeAndPop(); - hlfir::YieldOp::ensureTerminator(region, builder, loc); - builder.restoreInsertionPoint(insertPt); - } - bool firstDummyIsPointerOrAllocatable( const Fortran::evaluate::ProcedureRef &userDefinedAssignment) { using DummyAttr = Fortran::evaluate::characteristics::DummyDataObject::Attr; @@ -3928,7 +3912,8 @@ private: Fortran::lower::StatementContext rhsContext; hlfir::Entity rhs = evaluateRhs(rhsContext); auto rhsYieldOp = builder.create(loc, rhs); - genCleanUpInRegionIfAny(loc, builder, rhsYieldOp.getCleanup(), rhsContext); + Fortran::lower::genCleanUpInRegionIfAny( + loc, builder, rhsYieldOp.getCleanup(), rhsContext); // Lower LHS in its own region. builder.createBlock(®ionAssignOp.getLhsRegion()); Fortran::lower::StatementContext lhsContext; @@ -3936,15 +3921,15 @@ private: if (!lhsHasVectorSubscripts) { hlfir::Entity lhs = evaluateLhs(lhsContext); auto lhsYieldOp = builder.create(loc, lhs); - genCleanUpInRegionIfAny(loc, builder, lhsYieldOp.getCleanup(), - lhsContext); + Fortran::lower::genCleanUpInRegionIfAny( + loc, builder, lhsYieldOp.getCleanup(), lhsContext); lhsYield = lhs; } else { hlfir::ElementalAddrOp elementalAddr = Fortran::lower::convertVectorSubscriptedExprToElementalAddr( loc, *this, assign.lhs, localSymbols, lhsContext); - genCleanUpInRegionIfAny(loc, builder, elementalAddr.getCleanup(), - lhsContext); + Fortran::lower::genCleanUpInRegionIfAny( + loc, builder, elementalAddr.getCleanup(), lhsContext); lhsYield = elementalAddr.getYieldOp().getEntity(); } assert(lhsYield && "must have been set"); @@ -4299,7 +4284,8 @@ private: loc, *this, *maskExpr, localSymbols, maskContext); mask = hlfir::loadTrivialScalar(loc, *builder, mask); auto yieldOp = builder->create(loc, mask); - genCleanUpInRegionIfAny(loc, *builder, yieldOp.getCleanup(), maskContext); + Fortran::lower::genCleanUpInRegionIfAny(loc, *builder, yieldOp.getCleanup(), + maskContext); } void genFIR(const Fortran::parser::WhereConstructStmt &stmt) { const Fortran::semantics::SomeExpr *maskExpr = Fortran::semantics::GetExpr( @@ -5599,3 +5585,18 @@ Fortran::lower::LoweringBridge::LoweringBridge( fir::support::setMLIRDataLayout(*module.get(), targetMachine.createDataLayout()); } + +void Fortran::lower::genCleanUpInRegionIfAny( + mlir::Location loc, fir::FirOpBuilder &builder, mlir::Region ®ion, + Fortran::lower::StatementContext &context) { + if (!context.hasCode()) + return; + mlir::OpBuilder::InsertPoint insertPt = builder.saveInsertionPoint(); + if (region.empty()) + builder.createBlock(®ion); + else + builder.setInsertionPointToEnd(®ion.front()); + context.finalizeAndPop(); + hlfir::YieldOp::ensureTerminator(region, builder, loc); + builder.restoreInsertionPoint(insertPt); +} diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp index 3659dad367b4..c6bfe3592169 100644 --- a/flang/lib/Lower/ConvertCall.cpp +++ b/flang/lib/Lower/ConvertCall.cpp @@ -2682,10 +2682,48 @@ bool Fortran::lower::isIntrinsicModuleProcRef( return module && module->attrs().test(Fortran::semantics::Attr::INTRINSIC); } +static bool isInWhereMaskedExpression(fir::FirOpBuilder &builder) { + // The MASK of the outer WHERE is not masked itself. + mlir::Operation *op = builder.getRegion().getParentOp(); + return op && op->getParentOfType(); +} + std::optional Fortran::lower::convertCallToHLFIR( mlir::Location loc, Fortran::lower::AbstractConverter &converter, const evaluate::ProcedureRef &procRef, std::optional resultType, Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx) { + auto &builder = converter.getFirOpBuilder(); + if (resultType && !procRef.IsElemental() && + isInWhereMaskedExpression(builder) && + !builder.getRegion().getParentOfType()) { + // Non elemental calls inside a where-assignment-stmt must be executed + // exactly once without mask control. Lower them in a special region so that + // this can be enforced whenscheduling forall/where expression evaluations. + Fortran::lower::StatementContext localStmtCtx; + mlir::Type bogusType = builder.getIndexType(); + auto exactlyOnce = builder.create(loc, bogusType); + mlir::Block *block = builder.createBlock(&exactlyOnce.getBody()); + builder.setInsertionPointToStart(block); + CallContext callContext(procRef, resultType, loc, converter, symMap, + localStmtCtx); + std::optional res = + genProcedureRef(callContext); + assert(res.has_value() && "must be a function"); + auto yield = builder.create(loc, *res); + Fortran::lower::genCleanUpInRegionIfAny(loc, builder, yield.getCleanup(), + localStmtCtx); + builder.setInsertionPointAfter(exactlyOnce); + exactlyOnce->getResult(0).setType(res->getType()); + if (hlfir::isFortranValue(exactlyOnce.getResult())) + return hlfir::EntityWithAttributes{exactlyOnce.getResult()}; + // Create hlfir.declare for the result to satisfy + // hlfir::EntityWithAttributes requirements. + auto [exv, cleanup] = hlfir::translateToExtendedValue( + loc, builder, hlfir::Entity{exactlyOnce}); + assert(!cleanup && "resut is a variable"); + return hlfir::genDeclare(loc, builder, exv, ".func.pointer.result", + fir::FortranVariableFlagsAttr{}); + } CallContext callContext(procRef, resultType, loc, converter, symMap, stmtCtx); return genProcedureRef(callContext); } diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp index 63b52c0cd0bc..c9ff4b1c3374 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp @@ -56,7 +56,8 @@ namespace { /// expression and allows splitting the generation of the none elemental part /// from the elemental part. struct MaskedArrayExpr { - MaskedArrayExpr(mlir::Location loc, mlir::Region ®ion); + MaskedArrayExpr(mlir::Location loc, mlir::Region ®ion, + bool isOuterMaskExpr); /// Generate the none elemental part. Must be called outside of the /// loops created for the WHERE construct. @@ -79,16 +80,25 @@ struct MaskedArrayExpr { void generateNoneElementalCleanupIfAny(fir::FirOpBuilder &builder, mlir::IRMapping &mapper); + /// Helper to clone the clean-ups of the masked expr region terminator. + /// This is called outside of the loops for the initial mask, and inside + /// the loops for the other masked expressions. + mlir::Operation *generateMaskedExprCleanUps(fir::FirOpBuilder &builder, + mlir::IRMapping &mapper); + mlir::Location loc; mlir::Region ®ion; - /// Was generateNoneElementalPart called? - bool noneElementalPartWasGenerated = false; /// Set of operations that form the elemental parts of the /// expression evaluation. These are the hlfir.elemental and /// hlfir.elemental_addr that form the elemental tree producing /// the expression value. hlfir.elemental that produce values /// used inside transformational operations are not part of this set. llvm::SmallSet elementalParts{}; + /// Was generateNoneElementalPart called? + bool noneElementalPartWasGenerated = false; + /// Is this expression the mask expression of the outer where statement? + /// It is special because its evaluation is not masked by anything yet. + bool isOuterMaskExpr = false; }; } // namespace @@ -202,7 +212,7 @@ private: /// This method returns the scalar element (that may have been previously /// saved) for the current indices inside the where loop. mlir::Value generateMaskedEntity(mlir::Location loc, mlir::Region ®ion) { - MaskedArrayExpr maskedExpr(loc, region); + MaskedArrayExpr maskedExpr(loc, region, /*isOuterMaskExpr=*/!whereLoopNest); return generateMaskedEntity(maskedExpr); } mlir::Value generateMaskedEntity(MaskedArrayExpr &maskedExpr); @@ -524,7 +534,8 @@ void OrderedAssignmentRewriter::pre(hlfir::WhereOp whereOp) { return; } // The mask was not evaluated yet or can be safely re-evaluated. - MaskedArrayExpr mask(loc, whereOp.getMaskRegion()); + MaskedArrayExpr mask(loc, whereOp.getMaskRegion(), + /*isOuterMaskExpr=*/true); mask.generateNoneElementalPart(builder, mapper); mlir::Value shape = mask.generateShape(builder, mapper); whereLoopNest = hlfir::genLoopNest(loc, builder, shape); @@ -628,6 +639,13 @@ OrderedAssignmentRewriter::getIfSaved(mlir::Region ®ion) { return std::nullopt; } +static hlfir::YieldOp getYield(mlir::Region ®ion) { + auto yield = mlir::dyn_cast_or_null( + region.back().getOperations().back()); + assert(yield && "region computing entities must end with a YieldOp"); + return yield; +} + OrderedAssignmentRewriter::ValueAndCleanUp OrderedAssignmentRewriter::generateYieldedEntity( mlir::Region ®ion, std::optional castToType) { @@ -644,9 +662,7 @@ OrderedAssignmentRewriter::generateYieldedEntity( } assert(region.hasOneBlock() && "region must contain one block"); - auto oldYield = mlir::dyn_cast_or_null( - region.back().getOperations().back()); - assert(oldYield && "region computing entities must end with a YieldOp"); + auto oldYield = getYield(region); mlir::Block::OpListType &ops = region.back().getOperations(); // Inside Forall, scalars that do not depend on forall indices can be hoisted @@ -792,8 +808,15 @@ OrderedAssignmentRewriter::generateMaskedEntity(MaskedArrayExpr &maskedExpr) { // at the current insertion point (inside the where loops, and any fir.if // generated for previous masks). builder.restoreInsertionPoint(insertionPoint); - return maskedExpr.generateElementalParts( + mlir::Value scalar = maskedExpr.generateElementalParts( builder, whereLoopNest->oneBasedIndices, mapper); + /// Generate cleanups for the elemental parts inside the loops (setting the + /// location so that the assignment will be generated before the cleanups). + if (!maskedExpr.isOuterMaskExpr) + if (mlir::Operation *firstCleanup = + maskedExpr.generateMaskedExprCleanUps(builder, mapper)) + builder.setInsertionPoint(firstCleanup); + return scalar; } void OrderedAssignmentRewriter::generateCleanupIfAny( @@ -887,8 +910,9 @@ gatherElementalTree(hlfir::ElementalOpInterface elemental, } } -MaskedArrayExpr::MaskedArrayExpr(mlir::Location loc, mlir::Region ®ion) - : loc{loc}, region{region} { +MaskedArrayExpr::MaskedArrayExpr(mlir::Location loc, mlir::Region ®ion, + bool isOuterMaskExpr) + : loc{loc}, region{region}, isOuterMaskExpr{isOuterMaskExpr} { mlir::Operation &terminator = region.back().back(); if (auto elementalAddr = mlir::dyn_cast(terminator)) { @@ -907,13 +931,36 @@ void MaskedArrayExpr::generateNoneElementalPart(fir::FirOpBuilder &builder, mlir::IRMapping &mapper) { assert(!noneElementalPartWasGenerated && "none elemental parts already generated"); - // Clone all operations, except the elemental and the final yield. - mlir::Block::OpListType &ops = region.back().getOperations(); - assert(!ops.empty() && "yield block cannot be empty"); - auto end = ops.end(); - for (auto opIt = ops.begin(); std::next(opIt) != end; ++opIt) - if (!elementalParts.contains(&*opIt)) - (void)builder.clone(*opIt, mapper); + if (isOuterMaskExpr) { + // The outer mask expression is actually not masked, it is dealt as + // such so that its elemental part, if any, can be inlined in the WHERE + // loops. But all of the operations outside of hlfir.elemental/ + // hlfir.elemental_addr must be emitted now because their value may be + // required to deduce the mask shape and the WHERE loop bounds. + for (mlir::Operation &op : region.back().without_terminator()) + if (!elementalParts.contains(&op)) + (void)builder.clone(op, mapper); + } else { + // For actual masked expressions, Fortran requires elemental expressions, + // even the scalar ones that are not encoded with hlfir.elemental, to be + // evaluated only when the mask is true. Blindly hoisting all scalar SSA + // tree could be wrong if the scalar computation has side effects and + // would never have been evaluated (e.g. division by zero) if the mask + // is fully false. See F'2023 10.2.3.2 point 10. + // Clone only the bodies of all hlfir.exactly_once operations, which contain + // the evaluation of sub-expression tree whose root was a non elemental + // function call at the Fortran level (the call itself may have been inlined + // since). These must be evaluated only once as per F'2023 10.2.3.2 point 9. + for (mlir::Operation &op : region.back().without_terminator()) + if (auto exactlyOnce = mlir::dyn_cast(op)) { + for (mlir::Operation &subOp : + exactlyOnce.getBody().back().without_terminator()) + (void)builder.clone(subOp, mapper); + mlir::Value oldYield = getYield(exactlyOnce.getBody()).getEntity(); + auto newYield = mapper.lookupOrDefault(oldYield); + mapper.map(exactlyOnce.getResult(), newYield); + } + } noneElementalPartWasGenerated = true; } @@ -942,6 +989,15 @@ MaskedArrayExpr::generateElementalParts(fir::FirOpBuilder &builder, mlir::IRMapping &mapper) { assert(noneElementalPartWasGenerated && "non elemental part must have been generated"); + if (!isOuterMaskExpr) { + // Clone all operations that are not hlfir.exactly_once and that are not + // hlfir.elemental/hlfir.elemental_addr. + for (mlir::Operation &op : region.back().without_terminator()) + if (!mlir::isa(op) && !elementalParts.contains(&op)) + (void)builder.clone(op, mapper); + // For the outer mask, this was already done outside of the loop. + } + // Clone and "index" bodies of hlfir.elemental/hlfir.elemental_addr. mlir::Operation &terminator = region.back().back(); hlfir::ElementalOpInterface elemental = mlir::dyn_cast(terminator); @@ -966,8 +1022,11 @@ MaskedArrayExpr::generateElementalParts(fir::FirOpBuilder &builder, mustRecursivelyInline); } -void MaskedArrayExpr::generateNoneElementalCleanupIfAny( - fir::FirOpBuilder &builder, mlir::IRMapping &mapper) { +mlir::Operation * +MaskedArrayExpr::generateMaskedExprCleanUps(fir::FirOpBuilder &builder, + mlir::IRMapping &mapper) { + // Clone the clean-ups from the region itself, except for the destroy + // of the hlfir.elemental that have been inlined. mlir::Operation &terminator = region.back().back(); mlir::Region *cleanupRegion = nullptr; if (auto elementalAddr = mlir::dyn_cast(terminator)) { @@ -977,12 +1036,39 @@ void MaskedArrayExpr::generateNoneElementalCleanupIfAny( cleanupRegion = &yieldOp.getCleanup(); } if (cleanupRegion->empty()) - return; + return nullptr; + mlir::Operation *firstNewCleanup = nullptr; for (mlir::Operation &op : cleanupRegion->front().without_terminator()) { if (auto destroy = mlir::dyn_cast(op)) if (elementalParts.contains(destroy.getExpr().getDefiningOp())) continue; - (void)builder.clone(op, mapper); + mlir::Operation *cleanup = builder.clone(op, mapper); + if (!firstNewCleanup) + firstNewCleanup = cleanup; + } + return firstNewCleanup; +} + +void MaskedArrayExpr::generateNoneElementalCleanupIfAny( + fir::FirOpBuilder &builder, mlir::IRMapping &mapper) { + if (!isOuterMaskExpr) { + // Clone clean-ups of hlfir.exactly_once operations (in reverse order + // to properly deal with stack restores). + for (mlir::Operation &op : + llvm::reverse(region.back().without_terminator())) + if (auto exactlyOnce = mlir::dyn_cast(op)) { + mlir::Region &cleanupRegion = + getYield(exactlyOnce.getBody()).getCleanup(); + if (!cleanupRegion.empty()) + for (mlir::Operation &cleanupOp : + cleanupRegion.front().without_terminator()) + (void)builder.clone(cleanupOp, mapper); + } + } else { + // For the outer mask, the region clean-ups must be generated + // outside of the loops since the mask non hlfir.elemental part + // is generated before the loops. + generateMaskedExprCleanUps(builder, mapper); } } diff --git a/flang/test/HLFIR/order_assignments/impure-where.fir b/flang/test/HLFIR/order_assignments/impure-where.fir index 9399ea83d182..011a486b2baf 100644 --- a/flang/test/HLFIR/order_assignments/impure-where.fir +++ b/flang/test/HLFIR/order_assignments/impure-where.fir @@ -13,10 +13,13 @@ func.func @test_elsewhere_impure_mask(%x: !fir.ref>, %y: !fir hlfir.yield %mask : !fir.ref>> } do { hlfir.elsewhere mask { - %mask2 = fir.call @impure() : () -> !fir.heap>> - hlfir.yield %mask2 : !fir.heap>> cleanup { - fir.freemem %mask2 : !fir.heap>> + %mask2 = hlfir.exactly_once : !fir.heap>> { + %imp = fir.call @impure() : () -> !fir.heap>> + hlfir.yield %imp : !fir.heap>> cleanup { + fir.freemem %imp : !fir.heap>> + } } + hlfir.yield %mask2 : !fir.heap>> } do { hlfir.region_assign { hlfir.yield %y : !fir.ref> diff --git a/flang/test/HLFIR/order_assignments/inlined-stack-temp.fir b/flang/test/HLFIR/order_assignments/inlined-stack-temp.fir index 66ff55558ea6..0724d019537c 100644 --- a/flang/test/HLFIR/order_assignments/inlined-stack-temp.fir +++ b/flang/test/HLFIR/order_assignments/inlined-stack-temp.fir @@ -282,7 +282,6 @@ func.func @test_where_rhs_save(%x: !fir.ref>, %mask: !fir.ref // CHECK: %[[VAL_7:.*]] = arith.constant 10 : index // CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> // CHECK: %[[VAL_9:.*]] = arith.constant 1 : index -// CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_5]]:%[[VAL_4]]:%[[VAL_3]]) shape %[[VAL_6]] : (!fir.ref>, index, index, index, !fir.shape<1>) -> !fir.ref> // CHECK: %[[VAL_11:.*]] = arith.constant 0 : index // CHECK: %[[VAL_12:.*]] = arith.subi %[[VAL_7]], %[[VAL_9]] : index // CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_12]], %[[VAL_9]] : index @@ -300,6 +299,7 @@ func.func @test_where_rhs_save(%x: !fir.ref>, %mask: !fir.ref // CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_23]] : !fir.ref> // CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (!fir.logical<4>) -> i1 // CHECK: fir.if %[[VAL_25]] { +// CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_5]]:%[[VAL_4]]:%[[VAL_3]]) shape %[[VAL_6]] : (!fir.ref>, index, index, index, !fir.shape<1>) -> !fir.ref> // CHECK: %[[VAL_26:.*]] = hlfir.designate %[[VAL_10]] (%[[VAL_22]]) : (!fir.ref>, index) -> !fir.ref // CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_26]] : !fir.ref // CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_2]] : !fir.ref diff --git a/flang/test/HLFIR/order_assignments/user-defined-assignment-finalization.fir b/flang/test/HLFIR/order_assignments/user-defined-assignment-finalization.fir index bbb589169a80..ae5329a2d243 100644 --- a/flang/test/HLFIR/order_assignments/user-defined-assignment-finalization.fir +++ b/flang/test/HLFIR/order_assignments/user-defined-assignment-finalization.fir @@ -59,7 +59,7 @@ func.func @_QPtest1() { %7 = fir.call @_FortranADestroy(%6) fastmath : (!fir.box) -> none } } to { - hlfir.yield %2#0 : !fir.ref>}>> + hlfir.yield %2#0 : !fir.ref>}>> } user_defined_assign (%arg0: !fir.ref>}>>) to (%arg1: !fir.ref>}>>) { %3 = fir.embox %arg1 : (!fir.ref>}>>) -> !fir.box>}>> %4 = fir.convert %3 : (!fir.box>}>>) -> !fir.class>}>> @@ -119,7 +119,7 @@ func.func @_QPtest2() { fir.call @llvm.stackrestore.p0(%4) fastmath : (!fir.ref) -> () } } to { - hlfir.yield %3#0 : !fir.ref>}>>> + hlfir.yield %3#0 : !fir.ref>}>>> } user_defined_assign (%arg0: !fir.ref>}>>) to (%arg1: !fir.ref>}>>) { %4 = fir.embox %arg1 : (!fir.ref>}>>) -> !fir.box>}>> %5 = fir.convert %4 : (!fir.box>}>>) -> !fir.class>}>> @@ -193,18 +193,22 @@ func.func @_QPtest3(%arg0: !fir.ref> {fir.bindc_name = "y"}) { } } do { hlfir.region_assign { - %5 = fir.call @llvm.stacksave.p0() fastmath : () -> !fir.ref - %6 = fir.call @_QPnew_obja() fastmath : () -> !fir.array<2x!fir.type<_QMtypesTud_assign{x:!fir.box>}>> - fir.save_result %6 to %0(%2) : !fir.array<2x!fir.type<_QMtypesTud_assign{x:!fir.box>}>>, !fir.ref>}>>>, !fir.shape<1> - %7:2 = hlfir.declare %0(%2) {uniq_name = ".tmp.func_result"} : (!fir.ref>}>>>, !fir.shape<1>) -> (!fir.ref>}>>>, !fir.ref>}>>>) - hlfir.yield %7#0 : !fir.ref>}>>> cleanup { - %8 = fir.embox %0(%2) : (!fir.ref>}>>>, !fir.shape<1>) -> !fir.box>}>>> - %9 = fir.convert %8 : (!fir.box>}>>>) -> !fir.box - %10 = fir.call @_FortranADestroy(%9) fastmath : (!fir.box) -> none - fir.call @llvm.stackrestore.p0(%5) fastmath : (!fir.ref) -> () + %5 = hlfir.exactly_once : !fir.ref>}>>> { + %7 = fir.call @llvm.stacksave.p0() fastmath : () -> !fir.ref + %8 = fir.call @_QPnew_obja() fastmath : () -> !fir.array<2x!fir.type<_QMtypesTud_assign{x:!fir.box>}>> + fir.save_result %8 to %0(%2) : !fir.array<2x!fir.type<_QMtypesTud_assign{x:!fir.box>}>>, !fir.ref>}>>>, !fir.shape<1> + %9:2 = hlfir.declare %0(%2) {uniq_name = ".tmp.func_result"} : (!fir.ref>}>>>, !fir.shape<1>) -> (!fir.ref>}>>>, !fir.ref>}>>>) + hlfir.yield %9#0 : !fir.ref>}>>> cleanup { + %10 = fir.embox %0(%2) : (!fir.ref>}>>>, !fir.shape<1>) -> !fir.box>}>>> + %11 = fir.convert %10 : (!fir.box>}>>>) -> !fir.box + %12 = fir.call @_FortranADestroy(%11) fastmath : (!fir.box) -> none + fir.call @llvm.stackrestore.p0(%7) fastmath : (!fir.ref) -> () + } } + %6:2 = hlfir.declare %5(%2) {uniq_name = ".func.pointer.result"} : (!fir.ref>}>>>, !fir.shape<1>) -> (!fir.ref>}>>>, !fir.ref>}>>>) + hlfir.yield %6#0 : !fir.ref>}>>> } to { - hlfir.yield %3#0 : !fir.ref>}>>> + hlfir.yield %3#0 : !fir.ref>}>>> } user_defined_assign (%arg1: !fir.ref>}>>) to (%arg2: !fir.ref>}>>) { %5 = fir.embox %arg2 : (!fir.ref>}>>) -> !fir.box>}>> %6 = fir.convert %5 : (!fir.box>}>>) -> !fir.class>}>> @@ -246,7 +250,8 @@ func.func @_QPtest3(%arg0: !fir.ref> {fir.bindc_name = "y"}) { // CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_29]] : !fir.ref> // CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 // CHECK: fir.if %[[VAL_31]] { -// CHECK: %[[VAL_32:.*]] = hlfir.designate %[[VAL_20]]#0 (%[[VAL_28]]) : (!fir.ref>}>>>, index) -> !fir.ref>}>> +// CHECK: %[[VAL_20B:.*]]:2 = hlfir.declare %[[VAL_20]]#0(%[[VAL_7]]) {uniq_name = ".func.pointer.result"} +// CHECK: %[[VAL_32:.*]] = hlfir.designate %[[VAL_20B]]#0 (%[[VAL_28]]) : (!fir.ref>}>>>, index) -> !fir.ref>}>> // CHECK: %[[VAL_33:.*]] = fir.embox %[[VAL_32]] : (!fir.ref>}>>) -> !fir.box>}>> // CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_33]] : (!fir.box>}>>) -> !fir.box // CHECK: %[[VAL_35:.*]] = fir.call @_FortranAPushValue(%[[VAL_27]], %[[VAL_34]]) : (!fir.llvm_ptr, !fir.box) -> none diff --git a/flang/test/HLFIR/order_assignments/where-cleanup.f90 b/flang/test/HLFIR/order_assignments/where-cleanup.f90 new file mode 100644 index 000000000000..b4d16452bd2c --- /dev/null +++ b/flang/test/HLFIR/order_assignments/where-cleanup.f90 @@ -0,0 +1,44 @@ +// Test hlfir.where masked region cleanup lowering (the freemem in the tests). +// RUN: fir-opt %s --lower-hlfir-ordered-assignments | FileCheck %s + +func.func @loop_cleanup(%mask : !fir.ref>>, %x : !fir.ref>, %y : !fir.ref>) { + hlfir.where { + %1 = fir.allocmem !fir.array<10xi32> + hlfir.yield %mask : !fir.ref>> cleanup { + fir.freemem %1 : !fir.heap> + } + } do { + hlfir.region_assign { + %1 = fir.allocmem !fir.array<1xi32> + %2 = fir.allocmem !fir.array<2xi32> + hlfir.yield %x : !fir.ref> cleanup { + fir.freemem %2 : !fir.heap> + fir.freemem %1 : !fir.heap> + } + } to { + %1 = fir.allocmem !fir.array<3xi32> + %2 = fir.allocmem !fir.array<4xi32> + hlfir.yield %y : !fir.ref> cleanup { + fir.freemem %2 : !fir.heap> + fir.freemem %1 : !fir.heap> + } + } + } + return +} +// CHECK-LABEL: func.func @loop_cleanup( +// CHECK: %[[VAL_3:.*]] = fir.allocmem !fir.array<10xi32> +// CHECK: fir.do_loop +// CHECK: fir.if +// CHECK: %[[VAL_11:.*]] = fir.allocmem !fir.array<1xi32> +// CHECK: %[[VAL_12:.*]] = fir.allocmem !fir.array<2xi32> +// CHECK: %[[VAL_14:.*]] = fir.allocmem !fir.array<3xi32> +// CHECK: %[[VAL_15:.*]] = fir.allocmem !fir.array<4xi32> +// CHECK: hlfir.assign +// CHECK: fir.freemem %[[VAL_15]] : !fir.heap> +// CHECK: fir.freemem %[[VAL_14]] : !fir.heap> +// CHECK: fir.freemem %[[VAL_12]] : !fir.heap> +// CHECK: fir.freemem %[[VAL_11]] : !fir.heap> +// CHECK: } +// CHECK: } +// CHECK: fir.freemem %[[VAL_3]] : !fir.heap> diff --git a/flang/test/HLFIR/order_assignments/where-codegen-no-conflict.fir b/flang/test/HLFIR/order_assignments/where-codegen-no-conflict.fir index ac93e6828096..a1a357b45a64 100644 --- a/flang/test/HLFIR/order_assignments/where-codegen-no-conflict.fir +++ b/flang/test/HLFIR/order_assignments/where-codegen-no-conflict.fir @@ -290,8 +290,6 @@ func.func @inside_forall(%arg0: !fir.ref>, %arg1: !fir.ref // CHECK: fir.do_loop %[[VAL_15:.*]] = %[[VAL_12]] to %[[VAL_13]] step %[[VAL_14]] { // CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (index) -> i32 // CHECK: %[[VAL_17:.*]] = arith.constant 1 : index -// CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_16]] : (i32) -> i64 -// CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_9]]#0 (%[[VAL_18]], %[[VAL_2]]:%[[VAL_7]]:%[[VAL_2]]) shape %[[VAL_10]] : (!fir.ref>, i64, index, index, index, !fir.shape<1>) -> !fir.box> // CHECK: fir.do_loop %[[VAL_20:.*]] = %[[VAL_17]] to %[[VAL_7]] step %[[VAL_17]] { // CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_11]]#0 (%[[VAL_20]]) : (!fir.ref>, index) -> !fir.ref // CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref @@ -300,6 +298,8 @@ func.func @inside_forall(%arg0: !fir.ref>, %arg1: !fir.ref // CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (!fir.logical<4>) -> i1 // CHECK: fir.if %[[VAL_25]] { // CHECK: %[[VAL_26:.*]] = hlfir.designate %[[VAL_11]]#0 (%[[VAL_20]]) : (!fir.ref>, index) -> !fir.ref +// CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_16]] : (i32) -> i64 +// CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_9]]#0 (%[[VAL_18]], %[[VAL_2]]:%[[VAL_7]]:%[[VAL_2]]) shape %[[VAL_10]] : (!fir.ref>, i64, index, index, index, !fir.shape<1>) -> !fir.box> // CHECK: %[[VAL_27:.*]] = hlfir.designate %[[VAL_19]] (%[[VAL_20]]) : (!fir.box>, index) -> !fir.ref // CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_27]] : !fir.ref, !fir.ref // CHECK: } diff --git a/flang/test/HLFIR/order_assignments/where-hoisting.f90 b/flang/test/HLFIR/order_assignments/where-hoisting.f90 new file mode 100644 index 000000000000..6ed2ecb3624b --- /dev/null +++ b/flang/test/HLFIR/order_assignments/where-hoisting.f90 @@ -0,0 +1,50 @@ +! Test that scalar expressions are not hoisted from WHERE loops +! when they do not appear +! RUN: bbc -hlfir -o - -pass-pipeline="builtin.module(lower-hlfir-ordered-assignments)" %s | FileCheck %s + +subroutine do_not_hoist_div(n, mask, a) + integer :: a(10), n + logical :: mask(10) + where(mask) a=1/n +end subroutine +! CHECK-LABEL: func.func @_QPdo_not_hoist_div( +! CHECK-NOT: arith.divsi +! CHECK: fir.do_loop {{.*}} { +! CHECK: fir.if {{.*}} { +! CHECK: arith.divsi +! CHECK: } +! CHECK: } + +subroutine do_not_hoist_optional(n, mask, a) + integer :: a(10) + integer, optional :: n + logical :: mask(10) + where(mask) a=n +end subroutine +! CHECK-LABEL: func.func @_QPdo_not_hoist_optional( +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare {{.*}}"_QFdo_not_hoist_optionalEn" +! CHECK-NOT: fir.load %[[VAL_9]] +! CHECK: fir.do_loop {{.*}} { +! CHECK: fir.if {{.*}} { +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref +! CHECK: } +! CHECK: } + +subroutine hoist_function(n, mask, a) + integer :: a(10, 10) + integer, optional :: n + logical :: mask(10, 10) + forall (i=1:10) + where(mask(i, :)) a(i,:)=ihoist_me(i) + end forall +end subroutine +! CHECK-LABEL: func.func @_QPhoist_function( +! CHECK: fir.do_loop {{.*}} { +! CHECK: fir.call @_QPihoist_me +! CHECK: fir.do_loop {{.*}} { +! CHECK: fir.if %{{.*}} { +! CHECK-NOT: fir.call @_QPihoist_me +! CHECK: } +! CHECK: } +! CHECK: } +! CHECK-NOT: fir.call @_QPihoist_me diff --git a/flang/test/Lower/HLFIR/where-nonelemental.f90 b/flang/test/Lower/HLFIR/where-nonelemental.f90 new file mode 100644 index 000000000000..f0a6857f0f4b --- /dev/null +++ b/flang/test/Lower/HLFIR/where-nonelemental.f90 @@ -0,0 +1,198 @@ +! Test lowering of non elemental calls and there inputs inside WHERE +! constructs. These must be lowered inside hlfir.exactly_once so that +! they are properly hoisted once the loops are materialized and +! expression evaluations are scheduled. +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s + +subroutine test_where(a, b, c) + real, dimension(:) :: a, b, c + interface + function logical_func1() + logical :: logical_func1(100) + end function + function logical_func2() + logical :: logical_func2(100) + end function + real elemental function elem_func(x) + real, intent(in) :: x + end function + end interface + where (logical_func1()) + a = b + real_func(a+b+real_func2()) + elem_func(a) + elsewhere(logical_func2()) + a(1:ifoo()) = c + end where +end subroutine +! CHECK-LABEL: func.func @_QPtest_where( +! CHECK: hlfir.where { +! CHECK-NOT: hlfir.exactly_once +! CHECK: %[[VAL_17:.*]] = fir.call @llvm.stacksave.p0() fastmath : () -> !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.call @_QPlogical_func1() fastmath : () -> !fir.array<100x!fir.logical<4>> +! CHECK: hlfir.yield %{{.*}} : !hlfir.expr<100x!fir.logical<4>> cleanup { +! CHECK: fir.call @llvm.stackrestore.p0(%[[VAL_17]]) fastmath : (!fir.ref) -> () +! CHECK: } +! CHECK: } do { +! CHECK: hlfir.region_assign { +! CHECK: %[[VAL_24:.*]] = hlfir.exactly_once : f32 { +! CHECK: %[[VAL_28:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: } +! CHECK-NOT: hlfir.exactly_once +! CHECK: %[[VAL_35:.*]] = fir.call @_QPreal_func2() fastmath : () -> f32 +! CHECK: %[[VAL_36:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: ^bb0(%[[VAL_37:.*]]: index): +! CHECK: %[[VAL_38:.*]] = hlfir.apply %[[VAL_28]], %[[VAL_37]] : (!hlfir.expr, index) -> f32 +! CHECK: %[[VAL_39:.*]] = arith.addf %[[VAL_38]], %[[VAL_35]] fastmath : f32 +! CHECK: hlfir.yield_element %[[VAL_39]] : f32 +! CHECK: } +! CHECK: %[[VAL_41:.*]] = fir.call @_QPreal_func +! CHECK: hlfir.yield %[[VAL_41]] : f32 cleanup { +! CHECK: hlfir.destroy %[[VAL_36]] : !hlfir.expr +! CHECK: hlfir.destroy %[[VAL_28]] : !hlfir.expr +! CHECK: } +! CHECK: } +! CHECK: %[[VAL_45:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: arith.addf +! CHECK-NOT: hlfir.exactly_once +! CHECK: } +! CHECK: %[[VAL_53:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: fir.call @_QPelem_func +! CHECK: } +! CHECK: %[[VAL_57:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: arith.addf +! CHECK: } +! CHECK: hlfir.yield %[[VAL_57]] : !hlfir.expr cleanup { +! CHECK: hlfir.destroy %[[VAL_57]] : !hlfir.expr +! CHECK: hlfir.destroy %[[VAL_53]] : !hlfir.expr +! CHECK: hlfir.destroy %[[VAL_45]] : !hlfir.expr +! CHECK: } +! CHECK: } to { +! CHECK: hlfir.yield %{{.*}} : !fir.box> +! CHECK: } +! CHECK: hlfir.elsewhere mask { +! CHECK: %[[VAL_62:.*]] = hlfir.exactly_once : !hlfir.expr<100x!fir.logical<4>> { +! CHECK: %[[VAL_72:.*]] = fir.call @llvm.stacksave.p0() fastmath : () -> !fir.ref +! CHECK: fir.call @_QPlogical_func2() fastmath : () -> !fir.array<100x!fir.logical<4>> +! CHECK: hlfir.yield %{{.*}} : !hlfir.expr<100x!fir.logical<4>> cleanup { +! CHECK: fir.call @llvm.stackrestore.p0(%[[VAL_72]]) fastmath : (!fir.ref) -> () +! CHECK: } +! CHECK: } +! CHECK: hlfir.yield %[[VAL_62]] : !hlfir.expr<100x!fir.logical<4>> +! CHECK: } do { +! CHECK: hlfir.region_assign { +! CHECK: hlfir.yield %{{.*}} : !fir.box> +! CHECK: } to { +! CHECK: %[[VAL_80:.*]] = hlfir.exactly_once : i32 { +! CHECK: %[[VAL_81:.*]] = fir.call @_QPifoo() fastmath : () -> i32 +! CHECK: hlfir.yield %[[VAL_81]] : i32 +! CHECK: } +! CHECK: hlfir.yield %{{.*}} : !fir.box> +! CHECK: } +! CHECK: } +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine test_where_in_forall(a, b, c) + real, dimension(:, :) :: a, b, c + interface + pure function pure_logical_func1() + logical :: pure_logical_func1(100) + end function + pure function pure_logical_func2() + logical :: pure_logical_func2(100) + end function + real pure elemental function pure_elem_func(x) + real, intent(in) :: x + end function + integer pure function pure_ifoo() + end function + end interface + forall(i=1:10) + where (pure_logical_func1()) + a(2*i, :) = b(i, :) + pure_real_func(a(i,:)+b(i,:)+pure_real_func2()) + pure_elem_func(a(i,:)) + elsewhere(pure_logical_func2()) + a(2*i, 1:pure_ifoo()) = c(i, :) + end where + end forall +end subroutine +! CHECK-LABEL: func.func @_QPtest_where_in_forall( +! CHECK: hlfir.forall lb { +! CHECK: hlfir.yield %{{.*}} : i32 +! CHECK: } ub { +! CHECK: hlfir.yield %{{.*}} : i32 +! CHECK: } (%[[VAL_10:.*]]: i32) { +! CHECK: %[[VAL_11:.*]] = hlfir.forall_index "i" %[[VAL_10]] : (i32) -> !fir.ref +! CHECK: hlfir.where { +! CHECK: %[[VAL_21:.*]] = fir.call @llvm.stacksave.p0() fastmath : () -> !fir.ref +! CHECK-NOT: hlfir.exactly_once +! CHECK: %[[VAL_23:.*]] = fir.call @_QPpure_logical_func1() fastmath : () -> !fir.array<100x!fir.logical<4>> +! CHECK: hlfir.yield %{{.*}} : !hlfir.expr<100x!fir.logical<4>> cleanup { +! CHECK: fir.call @llvm.stackrestore.p0(%[[VAL_21]]) fastmath : (!fir.ref) -> () +! CHECK: } +! CHECK: } do { +! CHECK: hlfir.region_assign { +! CHECK: %[[VAL_41:.*]] = hlfir.designate +! CHECK: %[[VAL_42:.*]] = hlfir.exactly_once : f32 { +! CHECK: hlfir.designate +! CHECK: hlfir.designate +! CHECK: %[[VAL_71:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: arith.addf +! CHECK: } +! CHECK-NOT: hlfir.exactly_once +! CHECK: %[[VAL_78:.*]] = fir.call @_QPpure_real_func2() fastmath : () -> f32 +! CHECK: %[[VAL_79:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: arith.addf +! CHECK: } +! CHECK: %[[VAL_84:.*]] = fir.call @_QPpure_real_func( +! CHECK: hlfir.yield %[[VAL_84]] : f32 cleanup { +! CHECK: hlfir.destroy %[[VAL_79]] : !hlfir.expr +! CHECK: hlfir.destroy %[[VAL_71]] : !hlfir.expr +! CHECK: } +! CHECK: } +! CHECK: %[[VAL_85:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: arith.addf +! CHECK: } +! CHECK-NOT: hlfir.exactly_once +! CHECK: %[[VAL_104:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: ^bb0(%[[VAL_105:.*]]: index): +! CHECK-NOT: hlfir.exactly_once +! CHECK: fir.call @_QPpure_elem_func +! CHECK: } +! CHECK: %[[VAL_108:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: arith.addf +! CHECK: } +! CHECK: hlfir.yield %[[VAL_108]] : !hlfir.expr cleanup { +! CHECK: hlfir.destroy %[[VAL_108]] : !hlfir.expr +! CHECK: hlfir.destroy %[[VAL_104]] : !hlfir.expr +! CHECK: hlfir.destroy %[[VAL_85]] : !hlfir.expr +! CHECK: } +! CHECK: } to { +! CHECK: hlfir.designate +! CHECK: hlfir.yield %{{.*}} : !fir.box> +! CHECK: } +! CHECK: hlfir.elsewhere mask { +! CHECK: %[[VAL_129:.*]] = hlfir.exactly_once : !hlfir.expr<100x!fir.logical<4>> { +! CHECK: %[[VAL_139:.*]] = fir.call @llvm.stacksave.p0() fastmath : () -> !fir.ref +! CHECK: %[[VAL_141:.*]] = fir.call @_QPpure_logical_func2() fastmath : () -> !fir.array<100x!fir.logical<4>> +! CHECK: hlfir.yield %{{.*}} : !hlfir.expr<100x!fir.logical<4>> cleanup { +! CHECK: fir.call @llvm.stackrestore.p0(%[[VAL_139]]) fastmath : (!fir.ref) -> () +! CHECK: } +! CHECK: } +! CHECK: hlfir.yield %[[VAL_129]] : !hlfir.expr<100x!fir.logical<4>> +! CHECK: } do { +! CHECK: hlfir.region_assign { +! CHECK: hlfir.designate +! CHECK: hlfir.yield %{{.*}} : !fir.box> +! CHECK: } to { +! CHECK: %[[VAL_165:.*]] = hlfir.exactly_once : i32 { +! CHECK: %[[VAL_166:.*]] = fir.call @_QPpure_ifoo() fastmath : () -> i32 +! CHECK: hlfir.yield %[[VAL_166]] : i32 +! CHECK: } +! CHECK: hlfir.designate +! CHECK: hlfir.yield %{{.*}} : !fir.box> +! CHECK: } +! CHECK: } +! CHECK: } +! CHECK: } +! CHECK: return +! CHECK: } -- GitLab From b1e99a699db02f3a61d5b66f5d6dd68bae3b9a69 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 14 May 2024 12:43:47 +0100 Subject: [PATCH 220/578] [LV] Drop redundant comment from createEdgeMask (NFC). Follow-up to remove a redundant comment post-commit https://github.com/llvm/llvm-project/pull/91897 --- llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 9353666e417c..f2a541f5167a 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -8012,9 +8012,6 @@ VPValue *VPRecipeBuilder::createEdgeMask(BasicBlock *Src, BasicBlock *Dst) { EdgeMask = Builder.createNot(EdgeMask, BI->getDebugLoc()); if (SrcMask) { // Otherwise block in-mask is all-one, no need to AND. - // Use LogicalAnd as it does not propagate poison, i.e. does not introduce - // new UB if SrcMask is false and EdgeMask is poison. Using 'and' here - // introduces undefined behavior. // The bitwise 'And' of SrcMask and EdgeMask introduces new UB if SrcMask // is false and EdgeMask is poison. Avoid that by using 'LogicalAnd' // instead which generates 'select i1 SrcMask, i1 EdgeMask, i1 false'. -- GitLab From 292b300c5131e54b9977305bb4aca9a03e1b4fed Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Tue, 14 May 2024 13:55:24 +0200 Subject: [PATCH 221/578] [libc][bug] Fix out of bound write in memcpy w/ software prefetching (#90591) This patch adds tests for `memcpy` and `memset` making sure that we don't access buffers out of bounds. It relies on POSIX `mmap` / `mprotect` and works only when FULL_BUILD_MODE is disabled. The bug showed up while enabling software prefetching. `loop_and_tail_offset` is always running at least one iteration but in some configurations loop unrolled prefetching was actually needing only the tail operation and no loop iterations at all. --- .../memory_utils/x86_64/inline_memcpy.h | 16 ++- libc/test/src/string/memcpy_test.cpp | 41 ++++++++ .../src/string/memory_utils/protected_pages.h | 99 +++++++++++++++++++ libc/test/src/string/memset_test.cpp | 31 ++++++ 4 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 libc/test/src/string/memory_utils/protected_pages.h diff --git a/libc/src/string/memory_utils/x86_64/inline_memcpy.h b/libc/src/string/memory_utils/x86_64/inline_memcpy.h index ae61b1235bd0..507b3e25199e 100644 --- a/libc/src/string/memory_utils/x86_64/inline_memcpy.h +++ b/libc/src/string/memory_utils/x86_64/inline_memcpy.h @@ -107,7 +107,13 @@ inline_memcpy_x86_sse2_ge64_sw_prefetching(Ptr __restrict dst, offset += K_THREE_CACHELINES; } } - return builtin::Memcpy<32>::loop_and_tail_offset(dst, src, count, offset); + // We don't use 'loop_and_tail_offset' because it assumes at least one + // iteration of the loop. + while (offset + 32 <= count) { + builtin::Memcpy<32>::block_offset(dst, src, offset); + offset += 32; + } + return builtin::Memcpy<32>::tail(dst, src, count); } [[maybe_unused]] LIBC_INLINE void @@ -139,7 +145,13 @@ inline_memcpy_x86_avx_ge64_sw_prefetching(Ptr __restrict dst, builtin::Memcpy::block_offset(dst, src, offset); offset += K_THREE_CACHELINES; } - return builtin::Memcpy<64>::loop_and_tail_offset(dst, src, count, offset); + // We don't use 'loop_and_tail_offset' because it assumes at least one + // iteration of the loop. + while (offset + 64 <= count) { + builtin::Memcpy<64>::block_offset(dst, src, offset); + offset += 64; + } + return builtin::Memcpy<64>::tail(dst, src, count); } [[maybe_unused]] LIBC_INLINE void diff --git a/libc/test/src/string/memcpy_test.cpp b/libc/test/src/string/memcpy_test.cpp index b05d4202ea31..1ac963114844 100644 --- a/libc/test/src/string/memcpy_test.cpp +++ b/libc/test/src/string/memcpy_test.cpp @@ -7,9 +7,14 @@ //===----------------------------------------------------------------------===// #include "memory_utils/memory_check_utils.h" +#include "src/__support/macros/properties/os.h" // LIBC_TARGET_OS_IS_LINUX #include "src/string/memcpy.h" #include "test/UnitTest/Test.h" +#if !defined(LIBC_FULL_BUILD) && defined(LIBC_TARGET_OS_IS_LINUX) +#include "memory_utils/protected_pages.h" +#endif // !defined(LIBC_FULL_BUILD) && defined(LIBC_TARGET_OS_IS_LINUX) + namespace LIBC_NAMESPACE { // Adapt CheckMemcpy signature to memcpy. @@ -30,4 +35,40 @@ TEST(LlvmLibcMemcpyTest, SizeSweep) { } } +#if !defined(LIBC_FULL_BUILD) && defined(LIBC_TARGET_OS_IS_LINUX) + +TEST(LlvmLibcMemcpyTest, CheckAccess) { + static constexpr size_t MAX_SIZE = 1024; + LIBC_ASSERT(MAX_SIZE < GetPageSize()); + ProtectedPages pages; + const Page write_buffer = pages.GetPageA().WithAccess(PROT_WRITE); + const Page read_buffer = [&]() { + // We fetch page B in write mode. + auto page = pages.GetPageB().WithAccess(PROT_WRITE); + // And fill it with random numbers. + for (size_t i = 0; i < page.page_size; ++i) + page.page_ptr[i] = rand(); + // Then return it in read mode. + return page.WithAccess(PROT_READ); + }(); + for (size_t size = 0; size < MAX_SIZE; ++size) { + // We cross-check the function with two sources and two destinations. + // - The first of them (bottom) is always page aligned and faults when + // accessing bytes before it. + // - The second one (top) is not necessarily aligned and faults when + // accessing bytes after it. + const uint8_t *sources[2] = {read_buffer.bottom(size), + read_buffer.top(size)}; + uint8_t *destinations[2] = {write_buffer.bottom(size), + write_buffer.top(size)}; + for (const uint8_t *src : sources) { + for (uint8_t *dst : destinations) { + LIBC_NAMESPACE::memcpy(dst, src, size); + } + } + } +} + +#endif // !defined(LIBC_FULL_BUILD) && defined(LIBC_TARGET_OS_IS_LINUX) + } // namespace LIBC_NAMESPACE diff --git a/libc/test/src/string/memory_utils/protected_pages.h b/libc/test/src/string/memory_utils/protected_pages.h new file mode 100644 index 000000000000..50cfbaa37937 --- /dev/null +++ b/libc/test/src/string/memory_utils/protected_pages.h @@ -0,0 +1,99 @@ +//===-- protected_pages.h -------------------------------------------------===// +// +// 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 provides protected pages that fault when accessing prior or past +// it. This is useful to check memory functions that must not access outside of +// the provided size limited buffer. +//===----------------------------------------------------------------------===// + +#ifndef LIBC_TEST_SRC_STRING_MEMORY_UTILS_PROTECTED_PAGES_H +#define LIBC_TEST_SRC_STRING_MEMORY_UTILS_PROTECTED_PAGES_H + +#include "src/__support/macros/properties/os.h" // LIBC_TARGET_OS_IS_LINUX +#if defined(LIBC_FULL_BUILD) || !defined(LIBC_TARGET_OS_IS_LINUX) +#error "Protected pages requires mmap and cannot be used in full build mode." +#endif // defined(LIBC_FULL_BUILD) || !defined(LIBC_TARGET_OS_IS_LINUX) + +#include "src/__support/macros/attributes.h" // LIBC_INLINE +#include // size_t +#include // uint8_t +#include // mmap, munmap +#include // sysconf, _SC_PAGESIZE + +// Returns mmap page size. +LIBC_INLINE size_t GetPageSize() { + static const size_t PAGE_SIZE = sysconf(_SC_PAGESIZE); + return PAGE_SIZE; +} + +// Represents a page of memory whose access can be configured throught the +// 'WithAccess' function. Accessing data above or below this page will trap as +// it is sandwiched between two pages with no read / write access. +struct Page { + // Returns an aligned pointer that can be accessed up to page_size. Accessing + // data at ptr[-1] will fault. + LIBC_INLINE uint8_t *bottom(size_t size) const { + if (size >= page_size) + __builtin_trap(); + return page_ptr; + } + // Returns a pointer to a buffer that can be accessed up to size. Accessing + // data at ptr[size] will trap. + LIBC_INLINE uint8_t *top(size_t size) const { + return page_ptr + page_size - size; + } + + // protection is one of PROT_READ / PROT_WRITE. + LIBC_INLINE Page &WithAccess(int protection) { + if (mprotect(page_ptr, page_size, protection) != 0) + __builtin_trap(); + return *this; + } + + const size_t page_size; + uint8_t *const page_ptr; +}; + +// Allocates 5 consecutive pages that will trap if accessed. +// | page layout | access | page name | +// |-------------|--------|:---------:| +// | 0 | trap | | +// | 1 | custom | A | +// | 2 | trap | | +// | 3 | custom | B | +// | 4 | trap | | +// +// The pages A and B can be retrieved as with 'GetPageA' / 'GetPageB' and their +// accesses can be customized through the 'WithAccess' function. +struct ProtectedPages { + static constexpr size_t PAGES = 5; + + ProtectedPages() + : page_size(GetPageSize()), + ptr(mmap(/*address*/ nullptr, /*length*/ PAGES * page_size, + /*protection*/ PROT_NONE, + /*flags*/ MAP_PRIVATE | MAP_ANONYMOUS, /*fd*/ -1, + /*offset*/ 0)) { + if (reinterpret_cast(ptr) == -1) + __builtin_trap(); + } + ~ProtectedPages() { munmap(ptr, PAGES * page_size); } + + LIBC_INLINE Page GetPageA() const { return Page{page_size, page<1>()}; } + LIBC_INLINE Page GetPageB() const { return Page{page_size, page<3>()}; } + +private: + template LIBC_INLINE uint8_t *page() const { + static_assert(index < PAGES); + return static_cast(ptr) + (index * page_size); + } + + const size_t page_size; + void *const ptr = nullptr; +}; + +#endif // LIBC_TEST_SRC_STRING_MEMORY_UTILS_PROTECTED_PAGES_H diff --git a/libc/test/src/string/memset_test.cpp b/libc/test/src/string/memset_test.cpp index 3a54498498f6..d78b579a0edb 100644 --- a/libc/test/src/string/memset_test.cpp +++ b/libc/test/src/string/memset_test.cpp @@ -7,9 +7,14 @@ //===----------------------------------------------------------------------===// #include "memory_utils/memory_check_utils.h" +#include "src/__support/macros/properties/os.h" // LIBC_TARGET_OS_IS_LINUX #include "src/string/memset.h" #include "test/UnitTest/Test.h" +#if !defined(LIBC_FULL_BUILD) && defined(LIBC_TARGET_OS_IS_LINUX) +#include "memory_utils/protected_pages.h" +#endif // !defined(LIBC_FULL_BUILD) && defined(LIBC_TARGET_OS_IS_LINUX) + namespace LIBC_NAMESPACE { // Adapt CheckMemset signature to memset. @@ -27,4 +32,30 @@ TEST(LlvmLibcMemsetTest, SizeSweep) { } } +#if !defined(LIBC_FULL_BUILD) && defined(LIBC_TARGET_OS_IS_LINUX) + +TEST(LlvmLibcMemsetTest, CheckAccess) { + static constexpr size_t MAX_SIZE = 1024; + LIBC_ASSERT(MAX_SIZE < GetPageSize()); + ProtectedPages pages; + const Page write_buffer = pages.GetPageA().WithAccess(PROT_WRITE); + const cpp::array fill_chars = {0, 0x7F}; + for (int fill_char : fill_chars) { + for (size_t size = 0; size < MAX_SIZE; ++size) { + // We cross-check the function with two destinations. + // - The first of them (bottom) is always page aligned and faults when + // accessing bytes before it. + // - The second one (top) is not necessarily aligned and faults when + // accessing bytes after it. + uint8_t *destinations[2] = {write_buffer.bottom(size), + write_buffer.top(size)}; + for (uint8_t *dst : destinations) { + LIBC_NAMESPACE::memset(dst, fill_char, size); + } + } + } +} + +#endif // !defined(LIBC_FULL_BUILD) && defined(LIBC_TARGET_OS_IS_LINUX) + } // namespace LIBC_NAMESPACE -- GitLab From 9d4f7f44b64d87d1068859906f43b7ce03a7388b Mon Sep 17 00:00:00 2001 From: wanglei Date: Tue, 14 May 2024 19:39:47 +0800 Subject: [PATCH 222/578] [test][LoongArch] Add -mattr=+d option. NFC Because most of tests assume target-abi=`lp64d`, adding the corresponding feature is reasonable. rg -l loongarch -g '!*.s' | xargs sed -i '/mtriple=loongarch/ {/-mattr=/!{/target-abi/! s/mtriple=loongarch.. /&-mattr=+d /}}' --- llvm/test/CodeGen/LoongArch/O0-pipeline.ll | 4 ++-- llvm/test/CodeGen/LoongArch/addrspacecast.ll | 4 ++-- llvm/test/CodeGen/LoongArch/alloca.ll | 4 ++-- llvm/test/CodeGen/LoongArch/alsl.ll | 4 ++-- llvm/test/CodeGen/LoongArch/analyze-branch.ll | 2 +- llvm/test/CodeGen/LoongArch/andn-icmp.ll | 4 ++-- .../LoongArch/atomicrmw-uinc-udec-wrap.ll | 2 +- llvm/test/CodeGen/LoongArch/bitreverse.ll | 4 ++-- llvm/test/CodeGen/LoongArch/block-address.ll | 4 ++-- .../CodeGen/LoongArch/blockaddress-symbol.ll | 8 ++++---- llvm/test/CodeGen/LoongArch/bnez-beqz.ll | 4 ++-- .../LoongArch/branch-relaxation-spill-32.ll | 4 ++-- .../LoongArch/branch-relaxation-spill-64.ll | 4 ++-- .../CodeGen/LoongArch/branch-relaxation.ll | 8 ++++---- llvm/test/CodeGen/LoongArch/bstrins_d.ll | 2 +- llvm/test/CodeGen/LoongArch/bstrins_w.ll | 2 +- llvm/test/CodeGen/LoongArch/bstrpick_d.ll | 2 +- llvm/test/CodeGen/LoongArch/bstrpick_w.ll | 2 +- .../test/CodeGen/LoongArch/bswap-bitreverse.ll | 4 ++-- llvm/test/CodeGen/LoongArch/bswap.ll | 4 ++-- llvm/test/CodeGen/LoongArch/bytepick.ll | 4 ++-- llvm/test/CodeGen/LoongArch/code-models.ll | 6 +++--- .../test/CodeGen/LoongArch/cpu-name-generic.ll | 8 ++++---- llvm/test/CodeGen/LoongArch/cpus.ll | 6 +++--- llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll | 4 ++-- .../duplicate-returns-for-tailcall.ll | 2 +- llvm/test/CodeGen/LoongArch/dwarf-eh.ll | 8 ++++---- llvm/test/CodeGen/LoongArch/e_flags.ll | 4 ++-- llvm/test/CodeGen/LoongArch/eh-dwarf-cfa.ll | 4 ++-- .../CodeGen/LoongArch/emergency-spill-slot.ll | 2 +- .../LoongArch/exception-pointer-register.ll | 4 ++-- llvm/test/CodeGen/LoongArch/expand-call.ll | 4 ++-- llvm/test/CodeGen/LoongArch/frame.ll | 2 +- .../CodeGen/LoongArch/frameaddr-returnaddr.ll | 4 ++-- llvm/test/CodeGen/LoongArch/gep-imm.ll | 2 +- .../CodeGen/LoongArch/get-reg-error-la32.ll | 2 +- .../CodeGen/LoongArch/get-reg-error-la64.ll | 2 +- llvm/test/CodeGen/LoongArch/get-reg.ll | 2 +- .../CodeGen/LoongArch/get-setcc-result-type.ll | 2 +- llvm/test/CodeGen/LoongArch/global-address.ll | 12 ++++++------ .../LoongArch/global-variable-code-model.ll | 2 +- llvm/test/CodeGen/LoongArch/imm.ll | 2 +- .../LoongArch/inline-asm-constraint-ZB.ll | 4 ++-- .../LoongArch/inline-asm-constraint-ZC.ll | 4 ++-- .../LoongArch/inline-asm-constraint-k.ll | 4 ++-- .../LoongArch/inline-asm-constraint-m.ll | 4 ++-- .../CodeGen/LoongArch/inline-asm-constraint.ll | 4 ++-- .../LoongArch/inline-asm-operand-modifiers.ll | 4 ++-- .../LoongArch/inline-asm-reg-names-error.ll | 4 ++-- .../CodeGen/LoongArch/inline-asm-reg-names.ll | 4 ++-- .../LoongArch/intrinsic-csr-side-effects.ll | 4 ++-- .../LoongArch/intrinsic-iocsr-side-effects.ll | 2 +- .../CodeGen/LoongArch/intrinsic-la32-error.ll | 2 +- llvm/test/CodeGen/LoongArch/intrinsic-la32.ll | 2 +- .../CodeGen/LoongArch/intrinsic-la64-error.ll | 2 +- llvm/test/CodeGen/LoongArch/intrinsic-la64.ll | 2 +- .../test/CodeGen/LoongArch/intrinsic-memcpy.ll | 2 +- .../LoongArch/intrinsic-not-constant-error.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/add.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/and.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/ashr.ll | 4 ++-- .../LoongArch/ir-instruction/atomic-cmpxchg.ll | 2 +- .../ir-instruction/atomicrmw-minmax.ll | 2 +- .../LoongArch/ir-instruction/atomicrmw.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/br.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/call.ll | 4 ++-- .../ir-instruction/fence-singlethread.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/fence.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/icmp.ll | 4 ++-- .../LoongArch/ir-instruction/indirectbr.ll | 2 +- .../ir-instruction/load-store-atomic.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/lshr.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/mul.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/or.ll | 4 ++-- .../ir-instruction/sdiv-udiv-srem-urem.ll | 8 ++++---- .../ir-instruction/select-bare-int.ll | 4 ++-- .../LoongArch/ir-instruction/select-icc-int.ll | 4 ++-- .../ir-instruction/sext-zext-trunc.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/shl.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/sub.ll | 4 ++-- .../CodeGen/LoongArch/ir-instruction/xor.ll | 4 ++-- llvm/test/CodeGen/LoongArch/jump-table.ll | 8 ++++---- llvm/test/CodeGen/LoongArch/ldptr.ll | 4 ++-- llvm/test/CodeGen/LoongArch/ldx-stx-sp-2.ll | 4 ++-- llvm/test/CodeGen/LoongArch/ldx-stx-sp-3.ll | 4 ++-- llvm/test/CodeGen/LoongArch/legalicmpimm.ll | 4 ++-- .../CodeGen/LoongArch/load-store-offset.ll | 4 ++-- llvm/test/CodeGen/LoongArch/memcmp.ll | 2 +- .../test/CodeGen/LoongArch/mir-target-flags.ll | 4 ++-- llvm/test/CodeGen/LoongArch/nomerge.ll | 2 +- llvm/test/CodeGen/LoongArch/not.ll | 4 ++-- .../CodeGen/LoongArch/numeric-reg-names.ll | 4 ++-- llvm/test/CodeGen/LoongArch/opt-pipeline.ll | 12 ++++++------ .../LoongArch/patchable-function-entry.ll | 4 ++-- llvm/test/CodeGen/LoongArch/prefer-w-inst.ll | 4 ++-- .../CodeGen/LoongArch/preferred-alignments.ll | 4 ++-- .../LoongArch/psabi-restricted-scheduling.ll | 8 ++++---- .../register-coalescer-crash-pr79718.mir | 2 +- .../test/CodeGen/LoongArch/returnaddr-error.ll | 2 +- llvm/test/CodeGen/LoongArch/rotl-rotr.ll | 4 ++-- llvm/test/CodeGen/LoongArch/select-const.ll | 4 ++-- .../CodeGen/LoongArch/select-to-shiftand.ll | 4 ++-- .../LoongArch/sext-cheaper-than-zext.ll | 2 +- .../CodeGen/LoongArch/shift-masked-shamt.ll | 4 ++-- llvm/test/CodeGen/LoongArch/shrinkwrap.ll | 4 ++-- .../CodeGen/LoongArch/smul-with-overflow.ll | 4 ++-- .../CodeGen/LoongArch/spill-ra-without-kill.ll | 2 +- llvm/test/CodeGen/LoongArch/split-sp-adjust.ll | 2 +- ...-realignment-with-variable-sized-objects.ll | 4 ++-- .../CodeGen/LoongArch/stack-realignment.ll | 4 ++-- llvm/test/CodeGen/LoongArch/stptr.ll | 4 ++-- llvm/test/CodeGen/LoongArch/tail-calls.ll | 2 +- .../CodeGen/LoongArch/test_bl_fixupkind.mir | 2 +- llvm/test/CodeGen/LoongArch/thread-pointer.ll | 4 ++-- llvm/test/CodeGen/LoongArch/tls-models.ll | 18 +++++++++--------- llvm/test/CodeGen/LoongArch/trap.ll | 4 ++-- .../test/CodeGen/LoongArch/unaligned-access.ll | 4 ++-- .../xray-attribute-instrumentation.ll | 4 ++-- .../LoongArch/zext-with-load-is-free.ll | 4 ++-- .../LoongArch/load-store-atomic.ll | 4 ++-- .../CodeGenPrepare/LoongArch/splitgep.ll | 2 +- .../LoopDataPrefetch/LoongArch/basic.ll | 2 +- 122 files changed, 239 insertions(+), 239 deletions(-) diff --git a/llvm/test/CodeGen/LoongArch/O0-pipeline.ll b/llvm/test/CodeGen/LoongArch/O0-pipeline.ll index 84d235d78eb9..38c3291b6367 100644 --- a/llvm/test/CodeGen/LoongArch/O0-pipeline.ll +++ b/llvm/test/CodeGen/LoongArch/O0-pipeline.ll @@ -1,8 +1,8 @@ ;; When EXPENSIVE_CHECKS are enabled, the machine verifier appears between each ;; pass. Ignore it with 'grep -v'. -; RUN: llc --mtriple=loongarch32 -O0 --debug-pass=Structure %s -o /dev/null 2>&1 | \ +; RUN: llc --mtriple=loongarch32 -mattr=+d -O0 --debug-pass=Structure %s -o /dev/null 2>&1 | \ ; RUN: grep -v "Verify generated machine code" | FileCheck %s -; RUN: llc --mtriple=loongarch64 -O0 --debug-pass=Structure %s -o /dev/null 2>&1 | \ +; RUN: llc --mtriple=loongarch64 -mattr=+d -O0 --debug-pass=Structure %s -o /dev/null 2>&1 | \ ; RUN: grep -v "Verify generated machine code" | FileCheck %s ; REQUIRES: asserts diff --git a/llvm/test/CodeGen/LoongArch/addrspacecast.ll b/llvm/test/CodeGen/LoongArch/addrspacecast.ll index 7875562331be..1ca41705f974 100644 --- a/llvm/test/CodeGen/LoongArch/addrspacecast.ll +++ b/llvm/test/CodeGen/LoongArch/addrspacecast.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA64 define void @cast0(ptr addrspace(1) %ptr) { ; LA32-LABEL: cast0: diff --git a/llvm/test/CodeGen/LoongArch/alloca.ll b/llvm/test/CodeGen/LoongArch/alloca.ll index 75a05689e417..d298beaaa766 100644 --- a/llvm/test/CodeGen/LoongArch/alloca.ll +++ b/llvm/test/CodeGen/LoongArch/alloca.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 declare void @notdead(ptr) diff --git a/llvm/test/CodeGen/LoongArch/alsl.ll b/llvm/test/CodeGen/LoongArch/alsl.ll index 177e37de0952..6db9a179d65d 100644 --- a/llvm/test/CodeGen/LoongArch/alsl.ll +++ b/llvm/test/CodeGen/LoongArch/alsl.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define i8 @alsl_i8(i8 signext %a, i8 signext %b) nounwind { ; LA32-LABEL: alsl_i8: diff --git a/llvm/test/CodeGen/LoongArch/analyze-branch.ll b/llvm/test/CodeGen/LoongArch/analyze-branch.ll index fb89964af838..d15229a8c9e1 100644 --- a/llvm/test/CodeGen/LoongArch/analyze-branch.ll +++ b/llvm/test/CodeGen/LoongArch/analyze-branch.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s ;; This test checks that LLVM can do basic stripping and reapplying of branches ;; to basic blocks. diff --git a/llvm/test/CodeGen/LoongArch/andn-icmp.ll b/llvm/test/CodeGen/LoongArch/andn-icmp.ll index ff6935e2e23c..46bae6a9b70c 100644 --- a/llvm/test/CodeGen/LoongArch/andn-icmp.ll +++ b/llvm/test/CodeGen/LoongArch/andn-icmp.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define i1 @andn_icmp_eq_i8(i8 signext %a, i8 signext %b) nounwind { ; LA32-LABEL: andn_icmp_eq_i8: diff --git a/llvm/test/CodeGen/LoongArch/atomicrmw-uinc-udec-wrap.ll b/llvm/test/CodeGen/LoongArch/atomicrmw-uinc-udec-wrap.ll index b95c2e24737a..5ca6d8699135 100644 --- a/llvm/test/CodeGen/LoongArch/atomicrmw-uinc-udec-wrap.ll +++ b/llvm/test/CodeGen/LoongArch/atomicrmw-uinc-udec-wrap.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck --check-prefix=LA64 %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck --check-prefix=LA64 %s define i8 @atomicrmw_uinc_wrap_i8(ptr %ptr, i8 %val) { ; LA64-LABEL: atomicrmw_uinc_wrap_i8: diff --git a/llvm/test/CodeGen/LoongArch/bitreverse.ll b/llvm/test/CodeGen/LoongArch/bitreverse.ll index fcf523aa3c88..78d5c7e4a797 100644 --- a/llvm/test/CodeGen/LoongArch/bitreverse.ll +++ b/llvm/test/CodeGen/LoongArch/bitreverse.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 declare i7 @llvm.bitreverse.i7(i7) diff --git a/llvm/test/CodeGen/LoongArch/block-address.ll b/llvm/test/CodeGen/LoongArch/block-address.ll index 63d310dd9bea..eaba81f3563d 100644 --- a/llvm/test/CodeGen/LoongArch/block-address.ll +++ b/llvm/test/CodeGen/LoongArch/block-address.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 @addr = dso_local global ptr null diff --git a/llvm/test/CodeGen/LoongArch/blockaddress-symbol.ll b/llvm/test/CodeGen/LoongArch/blockaddress-symbol.ll index d07092230a4d..88864087ee4b 100644 --- a/llvm/test/CodeGen/LoongArch/blockaddress-symbol.ll +++ b/llvm/test/CodeGen/LoongArch/blockaddress-symbol.ll @@ -1,8 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s -; RUN: llc --mtriple=loongarch32 --no-integrated-as < %s | FileCheck %s -; RUN: llc --mtriple=loongarch64 --no-integrated-as < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+d --no-integrated-as < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d --no-integrated-as < %s | FileCheck %s ;; This regression test is for ensuring the AsmParser does not use the ;; getOrCreateSymbol interface to create blockaddress symbols. diff --git a/llvm/test/CodeGen/LoongArch/bnez-beqz.ll b/llvm/test/CodeGen/LoongArch/bnez-beqz.ll index d1652c73c25e..b2d7f3fe4173 100644 --- a/llvm/test/CodeGen/LoongArch/bnez-beqz.ll +++ b/llvm/test/CodeGen/LoongArch/bnez-beqz.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 declare void @bar() diff --git a/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-32.ll b/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-32.ll index 1ed9386310eb..5c96d5c416b9 100644 --- a/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-32.ll +++ b/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-32.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --filetype=obj --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --filetype=obj --verify-machineinstrs < %s \ ; RUN: -o /dev/null 2>&1 -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s | FileCheck %s define void @relax_b28_spill() { ; CHECK-LABEL: relax_b28_spill: diff --git a/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-64.ll b/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-64.ll index 1c4ef48a9761..a161fe97da9b 100644 --- a/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-64.ll +++ b/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-64.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 --filetype=obj --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --filetype=obj --verify-machineinstrs < %s \ ; RUN: -o /dev/null 2>&1 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | FileCheck %s define void @relax_b28_spill() { ; CHECK-LABEL: relax_b28_spill: diff --git a/llvm/test/CodeGen/LoongArch/branch-relaxation.ll b/llvm/test/CodeGen/LoongArch/branch-relaxation.ll index 296f543e18d9..6037ef9337dc 100644 --- a/llvm/test/CodeGen/LoongArch/branch-relaxation.ll +++ b/llvm/test/CodeGen/LoongArch/branch-relaxation.ll @@ -1,10 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --filetype=obj --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --filetype=obj --verify-machineinstrs < %s \ ; RUN: -o /dev/null 2>&1 -; RUN: llc --mtriple=loongarch64 --filetype=obj --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --filetype=obj --verify-machineinstrs < %s \ ; RUN: -o /dev/null 2>&1 -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA64 define i32 @relax_b18(i32 signext %a, i32 signext %b) { ; LA32-LABEL: relax_b18: diff --git a/llvm/test/CodeGen/LoongArch/bstrins_d.ll b/llvm/test/CodeGen/LoongArch/bstrins_d.ll index fe1f6270f966..ba43b63af6d6 100644 --- a/llvm/test/CodeGen/LoongArch/bstrins_d.ll +++ b/llvm/test/CodeGen/LoongArch/bstrins_d.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s ;; Test generation of the bstrins.d instruction. ;; There are 8 patterns that can be matched to bstrins.d. See performORCombine diff --git a/llvm/test/CodeGen/LoongArch/bstrins_w.ll b/llvm/test/CodeGen/LoongArch/bstrins_w.ll index e008caacad2a..92b98df21564 100644 --- a/llvm/test/CodeGen/LoongArch/bstrins_w.ll +++ b/llvm/test/CodeGen/LoongArch/bstrins_w.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s ;; Test generation of the bstrins.w instruction. ;; There are 8 patterns that can be matched to bstrins.w. See performORCombine diff --git a/llvm/test/CodeGen/LoongArch/bstrpick_d.ll b/llvm/test/CodeGen/LoongArch/bstrpick_d.ll index e93c1391d463..e6fc385b610d 100644 --- a/llvm/test/CodeGen/LoongArch/bstrpick_d.ll +++ b/llvm/test/CodeGen/LoongArch/bstrpick_d.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s define i64 @lshr40_and255(i64 %a) { ; CHECK-LABEL: lshr40_and255: diff --git a/llvm/test/CodeGen/LoongArch/bstrpick_w.ll b/llvm/test/CodeGen/LoongArch/bstrpick_w.ll index f9027e1fb32d..8d5c9d0df44c 100644 --- a/llvm/test/CodeGen/LoongArch/bstrpick_w.ll +++ b/llvm/test/CodeGen/LoongArch/bstrpick_w.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s define i32 @lshr10_and255(i32 %a) { ; CHECK-LABEL: lshr10_and255: diff --git a/llvm/test/CodeGen/LoongArch/bswap-bitreverse.ll b/llvm/test/CodeGen/LoongArch/bswap-bitreverse.ll index 828fb933bf3c..c8f9596b9b0c 100644 --- a/llvm/test/CodeGen/LoongArch/bswap-bitreverse.ll +++ b/llvm/test/CodeGen/LoongArch/bswap-bitreverse.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 declare i16 @llvm.bitreverse.i16(i16) diff --git a/llvm/test/CodeGen/LoongArch/bswap.ll b/llvm/test/CodeGen/LoongArch/bswap.ll index 71095ab972e3..122dab7fb496 100644 --- a/llvm/test/CodeGen/LoongArch/bswap.ll +++ b/llvm/test/CodeGen/LoongArch/bswap.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 declare i16 @llvm.bswap.i16(i16) diff --git a/llvm/test/CodeGen/LoongArch/bytepick.ll b/llvm/test/CodeGen/LoongArch/bytepick.ll index 1a2cd48448ba..22a78bcd5611 100644 --- a/llvm/test/CodeGen/LoongArch/bytepick.ll +++ b/llvm/test/CodeGen/LoongArch/bytepick.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 ;; a=00112233 b=44556677 diff --git a/llvm/test/CodeGen/LoongArch/code-models.ll b/llvm/test/CodeGen/LoongArch/code-models.ll index f93c31670928..4b2b72afaee1 100644 --- a/llvm/test/CodeGen/LoongArch/code-models.ll +++ b/llvm/test/CodeGen/LoongArch/code-models.ll @@ -1,9 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 --code-model=small < %s | \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=small < %s | \ ; RUN: FileCheck --check-prefix=SMALL %s -; RUN: llc --mtriple=loongarch64 --code-model=medium < %s | \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=medium < %s | \ ; RUN: FileCheck --check-prefix=MEDIUM %s -; RUN: llc --mtriple=loongarch64 --code-model=large < %s | \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=large < %s | \ ; RUN: FileCheck --check-prefix=LARGE %s declare void @llvm.memset.p0.i64(ptr, i8, i64, i1) diff --git a/llvm/test/CodeGen/LoongArch/cpu-name-generic.ll b/llvm/test/CodeGen/LoongArch/cpu-name-generic.ll index 1129d9fcb254..7472c1cc4f57 100644 --- a/llvm/test/CodeGen/LoongArch/cpu-name-generic.ll +++ b/llvm/test/CodeGen/LoongArch/cpu-name-generic.ll @@ -1,11 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --mcpu=generic < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --mcpu=generic < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch32 --mcpu=generic-la32 < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --mcpu=generic-la32 < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --mcpu=generic < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --mcpu=generic < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 -; RUN: llc --mtriple=loongarch64 --mcpu=generic-la64 < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --mcpu=generic-la64 < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 ;; The CPU name "generic" should map to the corresponding concrete names diff --git a/llvm/test/CodeGen/LoongArch/cpus.ll b/llvm/test/CodeGen/LoongArch/cpus.ll index 35945ae4de71..41ff1be496e3 100644 --- a/llvm/test/CodeGen/LoongArch/cpus.ll +++ b/llvm/test/CodeGen/LoongArch/cpus.ll @@ -1,9 +1,9 @@ ;; This tests that llc accepts all valid LoongArch CPUs. ;; Note the 'generic' names have been tested in cpu-name-generic.ll. -; RUN: llc < %s --mtriple=loongarch64 --mcpu=loongarch64 2>&1 | FileCheck %s -; RUN: llc < %s --mtriple=loongarch64 --mcpu=la464 2>&1 | FileCheck %s -; RUN: llc < %s --mtriple=loongarch64 2>&1 | FileCheck %s +; RUN: llc < %s --mtriple=loongarch64 -mattr=+d --mcpu=loongarch64 2>&1 | FileCheck %s +; RUN: llc < %s --mtriple=loongarch64 -mattr=+d --mcpu=la464 2>&1 | FileCheck %s +; RUN: llc < %s --mtriple=loongarch64 -mattr=+d 2>&1 | FileCheck %s ; CHECK-NOT: {{.*}} is not a recognized processor for this target diff --git a/llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll b/llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll index 9fa3f5076bb2..f17cec231f32 100644 --- a/llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll +++ b/llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 declare i8 @llvm.ctlz.i8(i8, i1) declare i16 @llvm.ctlz.i16(i16, i1) diff --git a/llvm/test/CodeGen/LoongArch/duplicate-returns-for-tailcall.ll b/llvm/test/CodeGen/LoongArch/duplicate-returns-for-tailcall.ll index 80e55ef9e21f..ac9d885c7ce0 100644 --- a/llvm/test/CodeGen/LoongArch/duplicate-returns-for-tailcall.ll +++ b/llvm/test/CodeGen/LoongArch/duplicate-returns-for-tailcall.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s ;; Perform tail call optimization for duplicate returns. declare i32 @test() diff --git a/llvm/test/CodeGen/LoongArch/dwarf-eh.ll b/llvm/test/CodeGen/LoongArch/dwarf-eh.ll index f4e347e07de5..cdeb6d81711d 100644 --- a/llvm/test/CodeGen/LoongArch/dwarf-eh.ll +++ b/llvm/test/CodeGen/LoongArch/dwarf-eh.ll @@ -1,7 +1,7 @@ -; RUN: llc --mtriple=loongarch32 --relocation-model=static < %s | FileCheck %s -; RUN: llc --mtriple=loongarch32 --relocation-model=pic < %s | FileCheck %s -; RUN: llc --mtriple=loongarch64 --relocation-model=static < %s | FileCheck %s -; RUN: llc --mtriple=loongarch64 --relocation-model=pic < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+d --relocation-model=static < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+d --relocation-model=pic < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d --relocation-model=static < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d --relocation-model=pic < %s | FileCheck %s declare void @throw_exception() diff --git a/llvm/test/CodeGen/LoongArch/e_flags.ll b/llvm/test/CodeGen/LoongArch/e_flags.ll index c004d1f9cdf4..25f3285bdf32 100644 --- a/llvm/test/CodeGen/LoongArch/e_flags.ll +++ b/llvm/test/CodeGen/LoongArch/e_flags.ll @@ -1,4 +1,4 @@ -; RUN: llc --mtriple=loongarch32 --filetype=obj %s -o %t-la32 +; RUN: llc --mtriple=loongarch32 -mattr=+d --filetype=obj %s -o %t-la32 ; RUN: llvm-readelf -h %t-la32 | FileCheck %s --check-prefixes=ILP32,ABI-D --match-full-lines ; RUN: llc --mtriple=loongarch32 --filetype=obj %s --target-abi=ilp32s -o %t-ilp32s @@ -10,7 +10,7 @@ ; RUN: llc --mtriple=loongarch32 --filetype=obj %s --target-abi=ilp32d -o %t-ilp32d ; RUN: llvm-readelf -h %t-ilp32d | FileCheck %s --check-prefixes=ILP32,ABI-D --match-full-lines -; RUN: llc --mtriple=loongarch64 --filetype=obj %s -o %t-la64 +; RUN: llc --mtriple=loongarch64 -mattr=+d --filetype=obj %s -o %t-la64 ; RUN: llvm-readelf -h %t-la64 | FileCheck %s --check-prefixes=LP64,ABI-D --match-full-lines ; RUN: llc --mtriple=loongarch64 --filetype=obj %s --target-abi=lp64s -o %t-lp64s diff --git a/llvm/test/CodeGen/LoongArch/eh-dwarf-cfa.ll b/llvm/test/CodeGen/LoongArch/eh-dwarf-cfa.ll index 796ada3a1a02..f00cf9491c08 100644 --- a/llvm/test/CodeGen/LoongArch/eh-dwarf-cfa.ll +++ b/llvm/test/CodeGen/LoongArch/eh-dwarf-cfa.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck --check-prefix=LA32 %s -; RUN: llc --mtriple=loongarch64 < %s | FileCheck --check-prefix=LA64 %s +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck --check-prefix=LA32 %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck --check-prefix=LA64 %s define void @dwarf() { ; LA32-LABEL: dwarf: diff --git a/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll b/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll index 4565c63f08d9..ccc5c703e71e 100644 --- a/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll +++ b/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 -O0 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d -O0 < %s | FileCheck %s @var = external global i32 diff --git a/llvm/test/CodeGen/LoongArch/exception-pointer-register.ll b/llvm/test/CodeGen/LoongArch/exception-pointer-register.ll index 797c7e520f5b..530d97ff4bab 100644 --- a/llvm/test/CodeGen/LoongArch/exception-pointer-register.ll +++ b/llvm/test/CodeGen/LoongArch/exception-pointer-register.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 declare void @foo(ptr %p); diff --git a/llvm/test/CodeGen/LoongArch/expand-call.ll b/llvm/test/CodeGen/LoongArch/expand-call.ll index e0d179f92de6..8c21adbcbb55 100644 --- a/llvm/test/CodeGen/LoongArch/expand-call.ll +++ b/llvm/test/CodeGen/LoongArch/expand-call.ll @@ -1,6 +1,6 @@ -; RUN: llc --mtriple=loongarch64 --stop-before loongarch-prera-expand-pseudo \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --stop-before loongarch-prera-expand-pseudo \ ; RUN: --verify-machineinstrs < %s | FileCheck %s --check-prefix=NOEXPAND -; RUN: llc --mtriple=loongarch64 --stop-before machine-opt-remark-emitter \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --stop-before machine-opt-remark-emitter \ ; RUN: --verify-machineinstrs < %s | FileCheck %s --check-prefix=EXPAND declare void @callee() diff --git a/llvm/test/CodeGen/LoongArch/frame.ll b/llvm/test/CodeGen/LoongArch/frame.ll index 8d3133316c43..ac5cb3c7e721 100644 --- a/llvm/test/CodeGen/LoongArch/frame.ll +++ b/llvm/test/CodeGen/LoongArch/frame.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s %struct.key_t = type { i32, [16 x i8] } diff --git a/llvm/test/CodeGen/LoongArch/frameaddr-returnaddr.ll b/llvm/test/CodeGen/LoongArch/frameaddr-returnaddr.ll index 01c9173c2e98..128d6e5a1dac 100644 --- a/llvm/test/CodeGen/LoongArch/frameaddr-returnaddr.ll +++ b/llvm/test/CodeGen/LoongArch/frameaddr-returnaddr.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 declare ptr @llvm.frameaddress(i32) declare ptr @llvm.returnaddress(i32) diff --git a/llvm/test/CodeGen/LoongArch/gep-imm.ll b/llvm/test/CodeGen/LoongArch/gep-imm.ll index c88d0b5a4543..567d3ea43ac9 100644 --- a/llvm/test/CodeGen/LoongArch/gep-imm.ll +++ b/llvm/test/CodeGen/LoongArch/gep-imm.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s define void @test(ptr %sp, ptr %t, i32 %n) { ; CHECK-LABEL: test: diff --git a/llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll b/llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll index 7440bfe5c85a..58b533a8b4e2 100644 --- a/llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll +++ b/llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: not llc < %s --mtriple=loongarch32 2>&1 | FileCheck %s +; RUN: not llc < %s --mtriple=loongarch32 -mattr=+d 2>&1 | FileCheck %s define i64 @read_sp() nounwind { entry: diff --git a/llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll b/llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll index 9312aa9020ba..ba2e83420327 100644 --- a/llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll +++ b/llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: not llc < %s --mtriple=loongarch64 2>&1 | FileCheck %s +; RUN: not llc < %s --mtriple=loongarch64 -mattr=+d 2>&1 | FileCheck %s define i32 @read_sp() nounwind { entry: diff --git a/llvm/test/CodeGen/LoongArch/get-reg.ll b/llvm/test/CodeGen/LoongArch/get-reg.ll index 323030da9e7f..e6d1de3baeb7 100644 --- a/llvm/test/CodeGen/LoongArch/get-reg.ll +++ b/llvm/test/CodeGen/LoongArch/get-reg.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s --mtriple=loongarch64 | FileCheck %s +; RUN: llc < %s --mtriple=loongarch64 -mattr=+d | FileCheck %s define i64 @get_stack() nounwind { ; CHECK-LABEL: get_stack: diff --git a/llvm/test/CodeGen/LoongArch/get-setcc-result-type.ll b/llvm/test/CodeGen/LoongArch/get-setcc-result-type.ll index 5e4c8418b222..6cf9d7d75b99 100644 --- a/llvm/test/CodeGen/LoongArch/get-setcc-result-type.ll +++ b/llvm/test/CodeGen/LoongArch/get-setcc-result-type.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s define void @getSetCCResultType(ptr %p) { diff --git a/llvm/test/CodeGen/LoongArch/global-address.ll b/llvm/test/CodeGen/LoongArch/global-address.ll index d32a17f488b1..0c8958b6ab33 100644 --- a/llvm/test/CodeGen/LoongArch/global-address.ll +++ b/llvm/test/CodeGen/LoongArch/global-address.ll @@ -1,10 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --relocation-model=static < %s | FileCheck %s --check-prefix=LA32NOPIC -; RUN: llc --mtriple=loongarch32 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA32PIC -; RUN: llc --mtriple=loongarch64 --relocation-model=static < %s | FileCheck %s --check-prefix=LA64NOPIC -; RUN: llc --mtriple=loongarch64 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64PIC -; RUN: llc --mtriple=loongarch64 --code-model=large --relocation-model=static < %s | FileCheck %s --check-prefix=LA64LARGENOPIC -; RUN: llc --mtriple=loongarch64 --code-model=large --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64LARGEPIC +; RUN: llc --mtriple=loongarch32 -mattr=+d --relocation-model=static < %s | FileCheck %s --check-prefix=LA32NOPIC +; RUN: llc --mtriple=loongarch32 -mattr=+d --relocation-model=pic < %s | FileCheck %s --check-prefix=LA32PIC +; RUN: llc --mtriple=loongarch64 -mattr=+d --relocation-model=static < %s | FileCheck %s --check-prefix=LA64NOPIC +; RUN: llc --mtriple=loongarch64 -mattr=+d --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64PIC +; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=large --relocation-model=static < %s | FileCheck %s --check-prefix=LA64LARGENOPIC +; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=large --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64LARGEPIC @g = dso_local global i32 zeroinitializer, align 4 @G = global i32 zeroinitializer, align 4 diff --git a/llvm/test/CodeGen/LoongArch/global-variable-code-model.ll b/llvm/test/CodeGen/LoongArch/global-variable-code-model.ll index aa4780834ac3..277b0b906139 100644 --- a/llvm/test/CodeGen/LoongArch/global-variable-code-model.ll +++ b/llvm/test/CodeGen/LoongArch/global-variable-code-model.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s @a= external dso_local global i32, code_model "small", align 4 diff --git a/llvm/test/CodeGen/LoongArch/imm.ll b/llvm/test/CodeGen/LoongArch/imm.ll index f8b7a61d6097..f84fddaec66b 100644 --- a/llvm/test/CodeGen/LoongArch/imm.ll +++ b/llvm/test/CodeGen/LoongArch/imm.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s define i64 @imm0() { ; CHECK-LABEL: imm0: diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-ZB.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-ZB.ll index 1a8f50abb658..526fd95da83f 100644 --- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-ZB.ll +++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-ZB.ll @@ -1,6 +1,6 @@ -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=ASM -; RUN: llc --mtriple=loongarch64 --print-after-isel -o /dev/null 2>&1 < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --print-after-isel -o /dev/null 2>&1 < %s \ ; RUN: | FileCheck %s --check-prefix=MACHINE-INSTR ;; Note amswap.w is not available on loongarch32. diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-ZC.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-ZC.ll index 9c053c4d2485..435235abed1a 100644 --- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-ZC.ll +++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-ZC.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA64 define i32 @ZC_offset_neg_32769(ptr %p) nounwind { ; LA32-LABEL: ZC_offset_neg_32769: diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-k.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-k.ll index 5ffe4b48c3f5..dccf2957981c 100644 --- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-k.ll +++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-k.ll @@ -1,6 +1,6 @@ -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=ASM -; RUN: llc --mtriple=loongarch64 --print-after-isel -o /dev/null 2>&1 < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --print-after-isel -o /dev/null 2>&1 < %s \ ; RUN: | FileCheck %s --check-prefix=MACHINE-INSTR define i64 @k_variable_offset(ptr %p, i64 %idx) nounwind { diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll index b6d8893d8ac9..281d52c47b68 100644 --- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll +++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA64 define i32 @m_offset_neg_2049(ptr %p) nounwind { ; LA32-LABEL: m_offset_neg_2049: diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll index 6ad52756b666..4bcc88be9739 100644 --- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll +++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs --no-integrated-as < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs --no-integrated-as < %s \ ; RUN: | FileCheck %s -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs --no-integrated-as < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs --no-integrated-as < %s \ ; RUN: | FileCheck %s @gi = external dso_local global i32, align 4 diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-operand-modifiers.ll b/llvm/test/CodeGen/LoongArch/inline-asm-operand-modifiers.ll index d3cf288bfd01..33651446c69f 100644 --- a/llvm/test/CodeGen/LoongArch/inline-asm-operand-modifiers.ll +++ b/llvm/test/CodeGen/LoongArch/inline-asm-operand-modifiers.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s | FileCheck %s -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | FileCheck %s define i32 @modifier_z_zero(i32 %a) nounwind { ; CHECK-LABEL: modifier_z_zero: diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-reg-names-error.ll b/llvm/test/CodeGen/LoongArch/inline-asm-reg-names-error.ll index 56c335ffb3a6..c6c0ac61607a 100644 --- a/llvm/test/CodeGen/LoongArch/inline-asm-reg-names-error.ll +++ b/llvm/test/CodeGen/LoongArch/inline-asm-reg-names-error.ll @@ -1,5 +1,5 @@ -; RUN: not llc --mtriple=loongarch32 2>&1 < %s | FileCheck %s -; RUN: not llc --mtriple=loongarch64 2>&1 < %s | FileCheck %s +; RUN: not llc --mtriple=loongarch32 -mattr=+d 2>&1 < %s | FileCheck %s +; RUN: not llc --mtriple=loongarch64 -mattr=+d 2>&1 < %s | FileCheck %s define i32 @non_exit_r32(i32 %a) nounwind { ; CHECK: error: couldn't allocate input reg for constraint '{$r32}' diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-reg-names.ll b/llvm/test/CodeGen/LoongArch/inline-asm-reg-names.ll index 4bc16e6cc5fb..36ccc1bb0163 100644 --- a/llvm/test/CodeGen/LoongArch/inline-asm-reg-names.ll +++ b/llvm/test/CodeGen/LoongArch/inline-asm-reg-names.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck --check-prefix=LA32 %s -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck --check-prefix=LA64 %s ;; These test that we can use architectural names ($r*) refer to registers in diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-csr-side-effects.ll b/llvm/test/CodeGen/LoongArch/intrinsic-csr-side-effects.ll index e3e23e46b04b..d14483939fbd 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-csr-side-effects.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-csr-side-effects.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s declare i32 @llvm.loongarch.csrrd.w(i32 immarg) nounwind declare i32 @llvm.loongarch.csrwr.w(i32, i32 immarg) nounwind diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-iocsr-side-effects.ll b/llvm/test/CodeGen/LoongArch/intrinsic-iocsr-side-effects.ll index ad78f7f53be1..e2a1f8a7ccd0 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-iocsr-side-effects.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-iocsr-side-effects.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s declare i32 @llvm.loongarch.iocsrrd.b(i32) nounwind declare void @llvm.loongarch.iocsrwr.b(i32, i32) nounwind diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll index 5302ba558940..bdbdaec8a1a0 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll @@ -1,4 +1,4 @@ -; RUN: not llc --mtriple=loongarch32 < %s 2>&1 | FileCheck %s +; RUN: not llc --mtriple=loongarch32 -mattr=+d < %s 2>&1 | FileCheck %s declare void @llvm.loongarch.cacop.w(i32, i32, i32) declare i32 @llvm.loongarch.crc.w.b.w(i32, i32) diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-la32.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la32.ll index 37e0902625a2..56f5146bb985 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-la32.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-la32.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s declare void @llvm.loongarch.cacop.w(i32, i32, i32) diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll index 4716d401d9fd..0a24e03838fd 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: not llc --mtriple=loongarch64 < %s 2>&1 | FileCheck %s +; RUN: not llc --mtriple=loongarch64 -mattr=+d < %s 2>&1 | FileCheck %s declare void @llvm.loongarch.cacop.w(i32, i32, i32) declare void @llvm.loongarch.cacop.d(i64, i64, i64) diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll index f0ebd8508ad1..4a59e2af533e 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s declare void @llvm.loongarch.cacop.d(i64, i64, i64) declare i32 @llvm.loongarch.crc.w.b.w(i32, i32) diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-memcpy.ll b/llvm/test/CodeGen/LoongArch/intrinsic-memcpy.ll index 06ef4d2f6c15..622001db3295 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-memcpy.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-memcpy.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s %Box = type [6 x i64] diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-not-constant-error.ll b/llvm/test/CodeGen/LoongArch/intrinsic-not-constant-error.ll index 9cb89670c293..9c6eb678588a 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-not-constant-error.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-not-constant-error.ll @@ -1,5 +1,5 @@ -; RUN: not llc --mtriple=loongarch32 < %s 2>&1 | FileCheck %s -; RUN: not llc --mtriple=loongarch64 < %s 2>&1 | FileCheck %s +; RUN: not llc --mtriple=loongarch32 -mattr=+d < %s 2>&1 | FileCheck %s +; RUN: not llc --mtriple=loongarch64 -mattr=+d < %s 2>&1 | FileCheck %s declare void @llvm.loongarch.dbar(i32) declare void @llvm.loongarch.ibar(i32) diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll index 709e0faeff90..c10d4949438f 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/add.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Exercise the 'add' LLVM IR: https://llvm.org/docs/LangRef.html#add-instruction diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/and.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/and.ll index b3e32cc5c00c..730d2609e64d 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/and.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/and.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Exercise the 'and' LLVM IR: https://llvm.org/docs/LangRef.html#and-instruction diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/ashr.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/ashr.ll index d4f766d460d1..6d04372d9222 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/ashr.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/ashr.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Exercise the 'ashr' LLVM IR: https://llvm.org/docs/LangRef.html#ashr-instruction diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/atomic-cmpxchg.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/atomic-cmpxchg.ll index 495974a59ba6..ad98397dfe8f 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/atomic-cmpxchg.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/atomic-cmpxchg.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define void @cmpxchg_i8_acquire_acquire(ptr %ptr, i8 %cmp, i8 %val) nounwind { ; LA64-LABEL: cmpxchg_i8_acquire_acquire: diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw-minmax.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw-minmax.ll index 794242f45fdb..2bd29c2670a6 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw-minmax.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw-minmax.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s | \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | \ ; RUN: FileCheck %s --check-prefix=LA64 ;; TODO: Testing for LA32 architecture will be added later diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw.ll index 9b83b4c9535e..f2f459ecaa2e 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define i8 @atomicrmw_xchg_i8_acquire(ptr %a, i8 %b) nounwind { ; LA32-LABEL: atomicrmw_xchg_i8_acquire: diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/br.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/br.ll index 36e39cc6d848..02375a925723 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/br.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/br.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefixes=ALL,LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefixes=ALL,LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefixes=ALL,LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefixes=ALL,LA64 define void @foo() noreturn nounwind { ; ALL-LABEL: foo: diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/call.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/call.ll index 90ee9490de74..697f7f79aa00 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/call.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/call.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck --check-prefix=LA32 %s -; RUN: llc --mtriple=loongarch64 < %s | FileCheck --check-prefix=LA64 %s +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck --check-prefix=LA32 %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck --check-prefix=LA64 %s declare i32 @external_function(i32) diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/fence-singlethread.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/fence-singlethread.ll index a8b164a4cd3c..cd62f4b1be68 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/fence-singlethread.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/fence-singlethread.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define void @fence_singlethread() { ; LA32-LABEL: fence_singlethread: diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/fence.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/fence.ll index c5b2232f9b80..717c5d0dc41b 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/fence.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/fence.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define void @fence_acquire() nounwind { ; LA32-LABEL: fence_acquire: diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/icmp.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/icmp.ll index 605b3ab29378..fabfbc3beeda 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/icmp.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/icmp.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Exercise the 'icmp' LLVM IR: https://llvm.org/docs/LangRef.html#icmp-instruction diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/indirectbr.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/indirectbr.ll index cd60183a0933..8a8fb5056609 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/indirectbr.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/indirectbr.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s define i32 @indirectbr(ptr %target) nounwind { ; CHECK-LABEL: indirectbr: diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/load-store-atomic.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/load-store-atomic.ll index 8b170c479eed..c51fded410e8 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/load-store-atomic.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/load-store-atomic.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define i8 @load_acquire_i8(ptr %ptr) { ; LA32-LABEL: load_acquire_i8: diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/lshr.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/lshr.ll index 7b28872780e8..ce7d1ec93d9d 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/lshr.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/lshr.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Exercise the 'lshr' LLVM IR: https://llvm.org/docs/LangRef.html#lshr-instruction diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll index cfa6ceae78f9..58cc0e7d6484 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Exercise the 'mul' LLVM IR: https://llvm.org/docs/LangRef.html#mul-instruction diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/or.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/or.ll index ead72507d751..7dacd3f6105d 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/or.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/or.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Exercise the 'or' LLVM IR: https://llvm.org/docs/LangRef.html#or-instruction diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll index 9c94bfeeadc0..381f69bb46f8 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll @@ -1,9 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 -; RUN: llc --mtriple=loongarch32 -loongarch-check-zero-division < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d -loongarch-check-zero-division < %s \ ; RUN: | FileCheck %s --check-prefix=LA32-TRAP -; RUN: llc --mtriple=loongarch64 -loongarch-check-zero-division < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d -loongarch-check-zero-division < %s \ ; RUN: | FileCheck %s --check-prefix=LA64-TRAP ;; Test the sdiv/udiv/srem/urem LLVM IR. diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/select-bare-int.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/select-bare-int.ll index ad0a241f5fd3..7239e27d9944 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/select-bare-int.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/select-bare-int.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Exercise the bare integers 'select' LLVM IR: https://llvm.org/docs/LangRef.html#select-instruction diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/select-icc-int.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/select-icc-int.ll index 0acf31f8bb1a..6a2e1f6972ad 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/select-icc-int.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/select-icc-int.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Test integers selection after integers comparison diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/sext-zext-trunc.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/sext-zext-trunc.ll index 7053d5340896..255bb79ad158 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/sext-zext-trunc.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/sext-zext-trunc.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Test sext/zext/trunc diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/shl.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/shl.ll index 3f35b76b1603..2be777cc8db0 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/shl.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/shl.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Exercise the 'shl' LLVM IR: https://llvm.org/docs/LangRef.html#shl-instruction diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/sub.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/sub.ll index bb236c11bb81..a593a66441b7 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/sub.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/sub.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Exercise the 'sub' LLVM IR: https://llvm.org/docs/LangRef.html#sub-instruction diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/xor.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/xor.ll index 373c9cf4b64e..703b812e8bcd 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/xor.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/xor.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Exercise the 'xor' LLVM IR: https://llvm.org/docs/LangRef.html#xor-instruction diff --git a/llvm/test/CodeGen/LoongArch/jump-table.ll b/llvm/test/CodeGen/LoongArch/jump-table.ll index 0cd6ef02d8da..bb3d49157ac6 100644 --- a/llvm/test/CodeGen/LoongArch/jump-table.ll +++ b/llvm/test/CodeGen/LoongArch/jump-table.ll @@ -1,11 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --min-jump-table-entries=5 < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --min-jump-table-entries=5 < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --min-jump-table-entries=5 < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --min-jump-table-entries=5 < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 -; RUN: llc --mtriple=loongarch32 --min-jump-table-entries=4 < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --min-jump-table-entries=4 < %s \ ; RUN: | FileCheck %s --check-prefix=LA32-JT -; RUN: llc --mtriple=loongarch64 --min-jump-table-entries=4 < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --min-jump-table-entries=4 < %s \ ; RUN: | FileCheck %s --check-prefix=LA64-JT ;; The default mininum number of entries to use a jump table is 4. diff --git a/llvm/test/CodeGen/LoongArch/ldptr.ll b/llvm/test/CodeGen/LoongArch/ldptr.ll index c7c2374d5fd5..c3656a6bdafb 100644 --- a/llvm/test/CodeGen/LoongArch/ldptr.ll +++ b/llvm/test/CodeGen/LoongArch/ldptr.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Check that ldptr.w is not emitted for small offsets. define signext i32 @ldptr_w_too_small_offset(ptr %p) nounwind { diff --git a/llvm/test/CodeGen/LoongArch/ldx-stx-sp-2.ll b/llvm/test/CodeGen/LoongArch/ldx-stx-sp-2.ll index be125f25ab2b..b5c9d1e7ff0f 100644 --- a/llvm/test/CodeGen/LoongArch/ldx-stx-sp-2.ll +++ b/llvm/test/CodeGen/LoongArch/ldx-stx-sp-2.ll @@ -1,5 +1,5 @@ -; RUN: llc --mtriple=loongarch32 < %s -; RUN: llc --mtriple=loongarch64 < %s +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s ;; This should not crash the code generator. diff --git a/llvm/test/CodeGen/LoongArch/ldx-stx-sp-3.ll b/llvm/test/CodeGen/LoongArch/ldx-stx-sp-3.ll index 45d2450bd64c..2bf9961b0af5 100644 --- a/llvm/test/CodeGen/LoongArch/ldx-stx-sp-3.ll +++ b/llvm/test/CodeGen/LoongArch/ldx-stx-sp-3.ll @@ -1,5 +1,5 @@ -; RUN: llc --mtriple=loongarch32 < %s -; RUN: llc --mtriple=loongarch64 < %s +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s ;; This should not crash the code generator. diff --git a/llvm/test/CodeGen/LoongArch/legalicmpimm.ll b/llvm/test/CodeGen/LoongArch/legalicmpimm.ll index 3dc8785631dc..71faf232640d 100644 --- a/llvm/test/CodeGen/LoongArch/legalicmpimm.ll +++ b/llvm/test/CodeGen/LoongArch/legalicmpimm.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define i32 @icmpimm(i32 %x) { ; LA32-LABEL: icmpimm: diff --git a/llvm/test/CodeGen/LoongArch/load-store-offset.ll b/llvm/test/CodeGen/LoongArch/load-store-offset.ll index 68777dfe0c2a..b83d5dc67dd4 100644 --- a/llvm/test/CodeGen/LoongArch/load-store-offset.ll +++ b/llvm/test/CodeGen/LoongArch/load-store-offset.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define i8 @load_i8() nounwind { ; LA32-LABEL: load_i8: diff --git a/llvm/test/CodeGen/LoongArch/memcmp.ll b/llvm/test/CodeGen/LoongArch/memcmp.ll index 4d4f376cd538..d8e322b3afe4 100644 --- a/llvm/test/CodeGen/LoongArch/memcmp.ll +++ b/llvm/test/CodeGen/LoongArch/memcmp.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s ;; Before getSelectionDAGInfo() interface hooks were defined DAGBuilder ;; would crash. diff --git a/llvm/test/CodeGen/LoongArch/mir-target-flags.ll b/llvm/test/CodeGen/LoongArch/mir-target-flags.ll index 9f3a061fe724..f530e3ef237c 100644 --- a/llvm/test/CodeGen/LoongArch/mir-target-flags.ll +++ b/llvm/test/CodeGen/LoongArch/mir-target-flags.ll @@ -1,6 +1,6 @@ -; RUN: llc --mtriple=loongarch64 --stop-after loongarch-prera-expand-pseudo \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --stop-after loongarch-prera-expand-pseudo \ ; RUN: --relocation-model=pic %s -o %t.mir -; RUN: llc --mtriple=loongarch64 --run-pass loongarch-prera-expand-pseudo \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --run-pass loongarch-prera-expand-pseudo \ ; RUN: %t.mir -o - | FileCheck %s ;; This tests the LoongArch-specific serialization and deserialization of diff --git a/llvm/test/CodeGen/LoongArch/nomerge.ll b/llvm/test/CodeGen/LoongArch/nomerge.ll index a8d5116f6b67..d35d3186b031 100644 --- a/llvm/test/CodeGen/LoongArch/nomerge.ll +++ b/llvm/test/CodeGen/LoongArch/nomerge.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s define void @foo(i32 %i) nounwind { ; CHECK-LABEL: foo: diff --git a/llvm/test/CodeGen/LoongArch/not.ll b/llvm/test/CodeGen/LoongArch/not.ll index b9e02bdf111d..05ece715e1c4 100644 --- a/llvm/test/CodeGen/LoongArch/not.ll +++ b/llvm/test/CodeGen/LoongArch/not.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define i8 @nor_i8(i8 %a, i8 %b) nounwind { ; LA32-LABEL: nor_i8: diff --git a/llvm/test/CodeGen/LoongArch/numeric-reg-names.ll b/llvm/test/CodeGen/LoongArch/numeric-reg-names.ll index 153a697a55b9..10a97a1778df 100644 --- a/llvm/test/CodeGen/LoongArch/numeric-reg-names.ll +++ b/llvm/test/CodeGen/LoongArch/numeric-reg-names.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --loongarch-numeric-reg < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --loongarch-numeric-reg < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --loongarch-numeric-reg < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-numeric-reg < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 @.str_1 = internal constant [7 x i8] c"hello\0A\00" diff --git a/llvm/test/CodeGen/LoongArch/opt-pipeline.ll b/llvm/test/CodeGen/LoongArch/opt-pipeline.ll index 803985fde215..f976dd8f9868 100644 --- a/llvm/test/CodeGen/LoongArch/opt-pipeline.ll +++ b/llvm/test/CodeGen/LoongArch/opt-pipeline.ll @@ -1,16 +1,16 @@ ;; When EXPENSIVE_CHECKS are enabled, the machine verifier appears between each ;; pass. Ignore it with 'grep -v'. -; RUN: llc --mtriple=loongarch32 -O1 --debug-pass=Structure %s -o /dev/null 2>&1 | \ +; RUN: llc --mtriple=loongarch32 -mattr=+d -O1 --debug-pass=Structure %s -o /dev/null 2>&1 | \ ; RUN: grep -v "Verify generated machine code" | FileCheck %s --check-prefix=LAXX -; RUN: llc --mtriple=loongarch32 -O2 --debug-pass=Structure %s -o /dev/null 2>&1 | \ +; RUN: llc --mtriple=loongarch32 -mattr=+d -O2 --debug-pass=Structure %s -o /dev/null 2>&1 | \ ; RUN: grep -v "Verify generated machine code" | FileCheck %s --check-prefix=LAXX -; RUN: llc --mtriple=loongarch32 -O3 --debug-pass=Structure %s -o /dev/null 2>&1 | \ +; RUN: llc --mtriple=loongarch32 -mattr=+d -O3 --debug-pass=Structure %s -o /dev/null 2>&1 | \ ; RUN: grep -v "Verify generated machine code" | FileCheck %s --check-prefix=LAXX -; RUN: llc --mtriple=loongarch64 -O1 --debug-pass=Structure %s -o /dev/null 2>&1 | \ +; RUN: llc --mtriple=loongarch64 -mattr=+d -O1 --debug-pass=Structure %s -o /dev/null 2>&1 | \ ; RUN: grep -v "Verify generated machine code" | FileCheck %s --check-prefixes=LAXX,LA64 -; RUN: llc --mtriple=loongarch64 -O2 --debug-pass=Structure %s -o /dev/null 2>&1 | \ +; RUN: llc --mtriple=loongarch64 -mattr=+d -O2 --debug-pass=Structure %s -o /dev/null 2>&1 | \ ; RUN: grep -v "Verify generated machine code" | FileCheck %s --check-prefixes=LAXX,LA64 -; RUN: llc --mtriple=loongarch64 -O3 --debug-pass=Structure %s -o /dev/null 2>&1 | \ +; RUN: llc --mtriple=loongarch64 -mattr=+d -O3 --debug-pass=Structure %s -o /dev/null 2>&1 | \ ; RUN: grep -v "Verify generated machine code" | FileCheck %s --check-prefixes=LAXX,LA64 ; REQUIRES: asserts diff --git a/llvm/test/CodeGen/LoongArch/patchable-function-entry.ll b/llvm/test/CodeGen/LoongArch/patchable-function-entry.ll index 2e390d1e2c33..fdb9288c2bd7 100644 --- a/llvm/test/CodeGen/LoongArch/patchable-function-entry.ll +++ b/llvm/test/CodeGen/LoongArch/patchable-function-entry.ll @@ -1,7 +1,7 @@ ;; Test the function attribute "patchable-function-entry". ;; Adapted from the RISCV test case. -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefixes=CHECK,LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefixes=CHECK,LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefixes=CHECK,LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefixes=CHECK,LA64 define void @f0() "patchable-function-entry"="0" { ; CHECK-LABEL: f0: diff --git a/llvm/test/CodeGen/LoongArch/prefer-w-inst.ll b/llvm/test/CodeGen/LoongArch/prefer-w-inst.ll index 385f27f04d5f..8a7c7183a75c 100644 --- a/llvm/test/CodeGen/LoongArch/prefer-w-inst.ll +++ b/llvm/test/CodeGen/LoongArch/prefer-w-inst.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck --check-prefixes=NO-PREFER-W-INST %s -; RUN: llc --mtriple=loongarch64 --loongarch-disable-cvt-to-d-suffix --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-disable-cvt-to-d-suffix --verify-machineinstrs < %s \ ; RUN: | FileCheck --check-prefixes=NO-CVT-D-INST %s ; RUN: llc --mtriple=loongarch64 --mattr=+prefer-w-inst --verify-machineinstrs < %s \ ; RUN: | FileCheck --check-prefixes=PREFER-W-INST %s diff --git a/llvm/test/CodeGen/LoongArch/preferred-alignments.ll b/llvm/test/CodeGen/LoongArch/preferred-alignments.ll index 30305127b94f..c3618db64601 100644 --- a/llvm/test/CodeGen/LoongArch/preferred-alignments.ll +++ b/llvm/test/CodeGen/LoongArch/preferred-alignments.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck --check-prefix=LA464 %s -; RUN: llc --mtriple=loongarch64 --mcpu=la464 < %s | FileCheck --check-prefix=LA464 %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck --check-prefix=LA464 %s +; RUN: llc --mtriple=loongarch64 -mattr=+d --mcpu=la464 < %s | FileCheck --check-prefix=LA464 %s define signext i32 @sum(ptr noalias nocapture noundef readonly %0, i32 noundef signext %1) { ; LA464-LABEL: sum: diff --git a/llvm/test/CodeGen/LoongArch/psabi-restricted-scheduling.ll b/llvm/test/CodeGen/LoongArch/psabi-restricted-scheduling.ll index d6f3e3469f75..0effd469e3fb 100644 --- a/llvm/test/CodeGen/LoongArch/psabi-restricted-scheduling.ll +++ b/llvm/test/CodeGen/LoongArch/psabi-restricted-scheduling.ll @@ -1,11 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 -; RUN: llc --mtriple=loongarch64 --code-model=medium --post-RA-scheduler=0 < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=medium --post-RA-scheduler=0 < %s \ ; RUN: | FileCheck %s --check-prefix=MEDIUM_NO_SCH -; RUN: llc --mtriple=loongarch64 --code-model=medium --post-RA-scheduler=1 < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=medium --post-RA-scheduler=1 < %s \ ; RUN: | FileCheck %s --check-prefix=MEDIUM_SCH -; RUN: llc --mtriple=loongarch64 --code-model=large --post-RA-scheduler=0 < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=large --post-RA-scheduler=0 < %s \ ; RUN: | FileCheck %s --check-prefix=LARGE_NO_SCH -; RUN: llc --mtriple=loongarch64 --code-model=large --post-RA-scheduler=1 < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=large --post-RA-scheduler=1 < %s \ ; RUN: | FileCheck %s --check-prefix=LARGE_SCH ;; FIXME: According to the description of the psABI v2.30, the code sequences diff --git a/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir b/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir index b3c44affb785..9c62983c6d45 100644 --- a/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir +++ b/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir @@ -1,5 +1,5 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 -# RUN: llc -o - %s -mtriple=loongarch64 \ +# RUN: llc -o - %s -mtriple=loongarch64 -mattr=+d \ # RUN: -run-pass=register-coalescer -join-liveintervals=1 -join-splitedges=0 | FileCheck %s --- diff --git a/llvm/test/CodeGen/LoongArch/returnaddr-error.ll b/llvm/test/CodeGen/LoongArch/returnaddr-error.ll index 6ac1e0afcd5c..efb23e0c2fa4 100644 --- a/llvm/test/CodeGen/LoongArch/returnaddr-error.ll +++ b/llvm/test/CodeGen/LoongArch/returnaddr-error.ll @@ -1,4 +1,4 @@ -; RUN: not llc --mtriple=loongarch64 < %s 2>&1 | FileCheck %s +; RUN: not llc --mtriple=loongarch64 -mattr=+d < %s 2>&1 | FileCheck %s declare ptr @llvm.returnaddress(i32 immarg) diff --git a/llvm/test/CodeGen/LoongArch/rotl-rotr.ll b/llvm/test/CodeGen/LoongArch/rotl-rotr.ll index b9fbd962e6bb..b2d46f5c088b 100644 --- a/llvm/test/CodeGen/LoongArch/rotl-rotr.ll +++ b/llvm/test/CodeGen/LoongArch/rotl-rotr.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define signext i32 @rotl_32(i32 signext %x, i32 signext %y) nounwind { ; LA32-LABEL: rotl_32: diff --git a/llvm/test/CodeGen/LoongArch/select-const.ll b/llvm/test/CodeGen/LoongArch/select-const.ll index 6a61cb66ef99..e9506b3a8359 100644 --- a/llvm/test/CodeGen/LoongArch/select-const.ll +++ b/llvm/test/CodeGen/LoongArch/select-const.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define signext i32 @select_const_int_one_away(i1 zeroext %a) nounwind { ; LA32-LABEL: select_const_int_one_away: diff --git a/llvm/test/CodeGen/LoongArch/select-to-shiftand.ll b/llvm/test/CodeGen/LoongArch/select-to-shiftand.ll index fa8879ea69dd..a40e31c5d303 100644 --- a/llvm/test/CodeGen/LoongArch/select-to-shiftand.ll +++ b/llvm/test/CodeGen/LoongArch/select-to-shiftand.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Compare if positive and select variable or zero. define i8 @pos_sel_variable_and_zero_i8(i8 signext %a, i8 signext %b) { diff --git a/llvm/test/CodeGen/LoongArch/sext-cheaper-than-zext.ll b/llvm/test/CodeGen/LoongArch/sext-cheaper-than-zext.ll index c363948a1494..fafd9ef092da 100644 --- a/llvm/test/CodeGen/LoongArch/sext-cheaper-than-zext.ll +++ b/llvm/test/CodeGen/LoongArch/sext-cheaper-than-zext.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s define signext i32 @sext_icmp(i32 signext %x, i32 signext %y) { ; CHECK-LABEL: sext_icmp: diff --git a/llvm/test/CodeGen/LoongArch/shift-masked-shamt.ll b/llvm/test/CodeGen/LoongArch/shift-masked-shamt.ll index 3494329e3e7c..4909a5f7098d 100644 --- a/llvm/test/CodeGen/LoongArch/shift-masked-shamt.ll +++ b/llvm/test/CodeGen/LoongArch/shift-masked-shamt.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; This test checks that unnecessary masking of shift amount operands is ;; eliminated during instruction selection. The test needs to ensure that the diff --git a/llvm/test/CodeGen/LoongArch/shrinkwrap.ll b/llvm/test/CodeGen/LoongArch/shrinkwrap.ll index 0323b56080f8..8e5ec17d6124 100644 --- a/llvm/test/CodeGen/LoongArch/shrinkwrap.ll +++ b/llvm/test/CodeGen/LoongArch/shrinkwrap.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 -O0 < %s | FileCheck %s --check-prefix=NOSHRINKW -; RUN: llc --mtriple=loongarch64 -O2 < %s | FileCheck %s --check-prefix=SHRINKW +; RUN: llc --mtriple=loongarch64 -mattr=+d -O0 < %s | FileCheck %s --check-prefix=NOSHRINKW +; RUN: llc --mtriple=loongarch64 -mattr=+d -O2 < %s | FileCheck %s --check-prefix=SHRINKW declare void @abort() diff --git a/llvm/test/CodeGen/LoongArch/smul-with-overflow.ll b/llvm/test/CodeGen/LoongArch/smul-with-overflow.ll index 0efb5fd4e640..739680e6141d 100644 --- a/llvm/test/CodeGen/LoongArch/smul-with-overflow.ll +++ b/llvm/test/CodeGen/LoongArch/smul-with-overflow.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 define zeroext i1 @smuloi64(i64 %v1, i64 %v2, ptr %res) { ; LA32-LABEL: smuloi64: diff --git a/llvm/test/CodeGen/LoongArch/spill-ra-without-kill.ll b/llvm/test/CodeGen/LoongArch/spill-ra-without-kill.ll index 7a52697d1529..08534e307e4e 100644 --- a/llvm/test/CodeGen/LoongArch/spill-ra-without-kill.ll +++ b/llvm/test/CodeGen/LoongArch/spill-ra-without-kill.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -O0 --mtriple=loongarch64 --verify-machineinstrs < %s | FileCheck %s +; RUN: llc -O0 --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | FileCheck %s ;; This test case is reduced from pr17377.c of the GCC C Torture Suite using ;; bugpoint. diff --git a/llvm/test/CodeGen/LoongArch/split-sp-adjust.ll b/llvm/test/CodeGen/LoongArch/split-sp-adjust.ll index 8217336637da..0605ceedf3e2 100644 --- a/llvm/test/CodeGen/LoongArch/split-sp-adjust.ll +++ b/llvm/test/CodeGen/LoongArch/split-sp-adjust.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s ;; The stack size is 2048 and the SP adjustment will be split. diff --git a/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll b/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll index 497ac065a8c3..1246b8bfa110 100644 --- a/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll +++ b/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 declare void @callee(ptr, ptr) diff --git a/llvm/test/CodeGen/LoongArch/stack-realignment.ll b/llvm/test/CodeGen/LoongArch/stack-realignment.ll index ac1397a9370d..43e61adb2bdc 100644 --- a/llvm/test/CodeGen/LoongArch/stack-realignment.ll +++ b/llvm/test/CodeGen/LoongArch/stack-realignment.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 declare void @callee(ptr) diff --git a/llvm/test/CodeGen/LoongArch/stptr.ll b/llvm/test/CodeGen/LoongArch/stptr.ll index cc198f9c2f8c..d70f9f4ba160 100644 --- a/llvm/test/CodeGen/LoongArch/stptr.ll +++ b/llvm/test/CodeGen/LoongArch/stptr.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 ;; Check that stptr.w is not emitted for small offsets. define void @stptr_w_too_small_offset(ptr %p, i32 signext %val) nounwind { diff --git a/llvm/test/CodeGen/LoongArch/tail-calls.ll b/llvm/test/CodeGen/LoongArch/tail-calls.ll index c22a65c77e70..8298d76d8e3a 100644 --- a/llvm/test/CodeGen/LoongArch/tail-calls.ll +++ b/llvm/test/CodeGen/LoongArch/tail-calls.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s ;; Perform tail call optimization for global address. declare i32 @callee_tail(i32 %i) diff --git a/llvm/test/CodeGen/LoongArch/test_bl_fixupkind.mir b/llvm/test/CodeGen/LoongArch/test_bl_fixupkind.mir index 70cd5fb8d7eb..7511193f1359 100644 --- a/llvm/test/CodeGen/LoongArch/test_bl_fixupkind.mir +++ b/llvm/test/CodeGen/LoongArch/test_bl_fixupkind.mir @@ -1,4 +1,4 @@ -# RUN: llc --mtriple=loongarch64 --filetype=obj %s -o - | \ +# RUN: llc --mtriple=loongarch64 -mattr=+d --filetype=obj %s -o - | \ # RUN: llvm-objdump -d - | FileCheck %s # REQUIRES: asserts diff --git a/llvm/test/CodeGen/LoongArch/thread-pointer.ll b/llvm/test/CodeGen/LoongArch/thread-pointer.ll index 805709e61c54..438f07e14665 100644 --- a/llvm/test/CodeGen/LoongArch/thread-pointer.ll +++ b/llvm/test/CodeGen/LoongArch/thread-pointer.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s --mtriple=loongarch32 | FileCheck %s -; RUN: llc < %s --mtriple=loongarch64 | FileCheck %s +; RUN: llc < %s --mtriple=loongarch32 -mattr=+d | FileCheck %s +; RUN: llc < %s --mtriple=loongarch64 -mattr=+d | FileCheck %s declare ptr @llvm.thread.pointer() diff --git a/llvm/test/CodeGen/LoongArch/tls-models.ll b/llvm/test/CodeGen/LoongArch/tls-models.ll index 6b250ec02162..bb89794d1c84 100644 --- a/llvm/test/CodeGen/LoongArch/tls-models.ll +++ b/llvm/test/CodeGen/LoongArch/tls-models.ll @@ -1,15 +1,15 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA32PIC -; RUN: llc --mtriple=loongarch64 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64PIC -; RUN: llc --mtriple=loongarch64 --code-model=large --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64LARGEPIC -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32NOPIC -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64NOPIC -; RUN: llc --mtriple=loongarch64 --code-model=large < %s | FileCheck %s --check-prefix=LA64LARGENOPIC -; RUN: llc --mtriple=loongarch32 --relocation-model=pic --enable-tlsdesc < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d --relocation-model=pic < %s | FileCheck %s --check-prefix=LA32PIC +; RUN: llc --mtriple=loongarch64 -mattr=+d --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64PIC +; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=large --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64LARGEPIC +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32NOPIC +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64NOPIC +; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=large < %s | FileCheck %s --check-prefix=LA64LARGENOPIC +; RUN: llc --mtriple=loongarch32 -mattr=+d --relocation-model=pic --enable-tlsdesc < %s \ ; RUN: | FileCheck %s --check-prefix=LA32DESC -; RUN: llc --mtriple=loongarch64 --relocation-model=pic --enable-tlsdesc < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --relocation-model=pic --enable-tlsdesc < %s \ ; RUN: | FileCheck %s --check-prefix=LA64DESC -; RUN: llc --mtriple=loongarch64 --relocation-model=pic --enable-tlsdesc \ +; RUN: llc --mtriple=loongarch64 -mattr=+d --relocation-model=pic --enable-tlsdesc \ ; RUN: --code-model=large < %s | FileCheck %s --check-prefix=DESC64 ;; Check that TLS symbols are lowered correctly based on the specified diff --git a/llvm/test/CodeGen/LoongArch/trap.ll b/llvm/test/CodeGen/LoongArch/trap.ll index 718b99160b20..15a7ad82bd7a 100644 --- a/llvm/test/CodeGen/LoongArch/trap.ll +++ b/llvm/test/CodeGen/LoongArch/trap.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s | FileCheck %s -; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+d --verify-machineinstrs < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | FileCheck %s ;; Verify that we lower @llvm.trap() and @llvm.debugtrap() correctly. diff --git a/llvm/test/CodeGen/LoongArch/unaligned-access.ll b/llvm/test/CodeGen/LoongArch/unaligned-access.ll index dd5b585fcca5..1eadbad65aa7 100644 --- a/llvm/test/CodeGen/LoongArch/unaligned-access.ll +++ b/llvm/test/CodeGen/LoongArch/unaligned-access.ll @@ -2,11 +2,11 @@ ;; Test the ual feature which is similar to AArch64/arm64-strict-align.ll. -; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32-ALIGNED +; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32-ALIGNED ; RUN: llc --mtriple=loongarch32 --mattr=+ual < %s | FileCheck %s --check-prefix=LA32-UNALIGNED ; RUN: llc --mtriple=loongarch32 --mattr=-ual < %s | FileCheck %s --check-prefix=LA32-ALIGNED -; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64-UNALIGNED +; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64-UNALIGNED ; RUN: llc --mtriple=loongarch64 --mattr=+ual < %s | FileCheck %s --check-prefix=LA64-UNALIGNED ; RUN: llc --mtriple=loongarch64 --mattr=-ual < %s | FileCheck %s --check-prefix=LA64-ALIGNED diff --git a/llvm/test/CodeGen/LoongArch/xray-attribute-instrumentation.ll b/llvm/test/CodeGen/LoongArch/xray-attribute-instrumentation.ll index 09442216c469..8999c2038700 100644 --- a/llvm/test/CodeGen/LoongArch/xray-attribute-instrumentation.ll +++ b/llvm/test/CodeGen/LoongArch/xray-attribute-instrumentation.ll @@ -1,5 +1,5 @@ -; RUN: llc --mtriple=loongarch64 %s -o - | FileCheck %s -; RUN: llc --mtriple=loongarch64 -filetype=obj %s -o %t +; RUN: llc --mtriple=loongarch64 -mattr=+d %s -o - | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d -filetype=obj %s -o %t ; RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=RELOC define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" { diff --git a/llvm/test/CodeGen/LoongArch/zext-with-load-is-free.ll b/llvm/test/CodeGen/LoongArch/zext-with-load-is-free.ll index d5c505f7160e..d745cd637803 100644 --- a/llvm/test/CodeGen/LoongArch/zext-with-load-is-free.ll +++ b/llvm/test/CodeGen/LoongArch/zext-with-load-is-free.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 -; RUN: llc --mtriple=loongarch32 -verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch32 -mattr=+d -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA32 -; RUN: llc --mtriple=loongarch64 -verify-machineinstrs < %s \ +; RUN: llc --mtriple=loongarch64 -mattr=+d -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefix=LA64 define zeroext i8 @test_zext_i8(ptr %p) nounwind { diff --git a/llvm/test/Transforms/AtomicExpand/LoongArch/load-store-atomic.ll b/llvm/test/Transforms/AtomicExpand/LoongArch/load-store-atomic.ll index 77c237a38a48..69448dc2bc8e 100644 --- a/llvm/test/Transforms/AtomicExpand/LoongArch/load-store-atomic.ll +++ b/llvm/test/Transforms/AtomicExpand/LoongArch/load-store-atomic.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S --mtriple=loongarch32 --passes=atomic-expand %s | FileCheck %s --check-prefix=LA32 -; RUN: opt -S --mtriple=loongarch64 --passes=atomic-expand %s | FileCheck %s --check-prefix=LA64 +; RUN: opt -S --mtriple=loongarch32 -mattr=+d --passes=atomic-expand %s | FileCheck %s --check-prefix=LA32 +; RUN: opt -S --mtriple=loongarch64 -mattr=+d --passes=atomic-expand %s | FileCheck %s --check-prefix=LA64 define i8 @load_acquire_i8(ptr %ptr) { ; LA32-LABEL: @load_acquire_i8( diff --git a/llvm/test/Transforms/CodeGenPrepare/LoongArch/splitgep.ll b/llvm/test/Transforms/CodeGenPrepare/LoongArch/splitgep.ll index 20cc25e95adf..304e703c09a1 100644 --- a/llvm/test/Transforms/CodeGenPrepare/LoongArch/splitgep.ll +++ b/llvm/test/Transforms/CodeGenPrepare/LoongArch/splitgep.ll @@ -1,4 +1,4 @@ -; RUN: opt --mtriple=loongarch64 -S --passes='require,function(codegenprepare)' %s | FileCheck %s +; RUN: opt --mtriple=loongarch64 -mattr=+d -S --passes='require,function(codegenprepare)' %s | FileCheck %s ; Check that we have deterministic output define void @test(ptr %sp, ptr %t, i32 %n) { diff --git a/llvm/test/Transforms/LoopDataPrefetch/LoongArch/basic.ll b/llvm/test/Transforms/LoopDataPrefetch/LoongArch/basic.ll index 55a2a2970d2d..8553171ac68a 100644 --- a/llvm/test/Transforms/LoopDataPrefetch/LoongArch/basic.ll +++ b/llvm/test/Transforms/LoopDataPrefetch/LoongArch/basic.ll @@ -1,6 +1,6 @@ ;; Tag this 'XFAIL' because we need a few more TTIs and ISels. ; XFAIL: * -; RUN: opt --mtriple=loongarch64 --passes=loop-data-prefetch -loongarch-enable-loop-data-prefetch -S < %s | FileCheck %s +; RUN: opt --mtriple=loongarch64 -mattr=+d --passes=loop-data-prefetch -loongarch-enable-loop-data-prefetch -S < %s | FileCheck %s define void @foo(ptr %a, ptr %b) { entry: -- GitLab From 415616daa0bdf6c0065c4c1967f1c4050e6ea836 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Tue, 14 May 2024 07:33:07 -0500 Subject: [PATCH 223/578] [flang][OpenMP] Lower standalone ops via OMP dispatch, NFC (#92045) This moves lowering of standalone OpenMP ops into the dispatch function. Follow-up to PR90098. --- flang/lib/Lower/OpenMP/OpenMP.cpp | 68 ++++++++++++------------------- 1 file changed, 27 insertions(+), 41 deletions(-) diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index f9ba2fcbbca7..f21acdd64d7c 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -1959,6 +1959,9 @@ static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, const List &clauses = item->clauses; switch (llvm::omp::Directive dir = item->id) { + case llvm::omp::Directive::OMPD_barrier: + genBarrierOp(converter, symTable, semaCtx, eval, loc, queue, item); + break; case llvm::omp::Directive::OMPD_distribute: genDistributeOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); @@ -1968,8 +1971,6 @@ static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, break; case llvm::omp::Directive::OMPD_loop: case llvm::omp::Directive::OMPD_masked: - case llvm::omp::Directive::OMPD_tile: - case llvm::omp::Directive::OMPD_unroll: TODO(loc, "Unhandled loop directive (" + llvm::omp::getOpenMPDirectiveName(dir) + ")"); break; @@ -1977,6 +1978,7 @@ static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, genMasterOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); break; case llvm::omp::Directive::OMPD_ordered: + // Block-associated "ordered" construct. genOrderedRegionOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); break; @@ -1984,6 +1986,10 @@ static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, genParallelOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item, /*outerCombined=*/false); break; + case llvm::omp::Directive::OMPD_section: + genSectionOp(converter, symTable, semaCtx, eval, loc, /*clauses=*/{}, queue, + item); + break; case llvm::omp::Directive::OMPD_sections: genSectionsOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); @@ -2025,9 +2031,20 @@ static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, genTaskloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); break; + case llvm::omp::Directive::OMPD_taskwait: + genTaskwaitOp(converter, symTable, semaCtx, eval, loc, clauses, queue, + item); + break; + case llvm::omp::Directive::OMPD_taskyield: + genTaskyieldOp(converter, symTable, semaCtx, eval, loc, queue, item); + break; case llvm::omp::Directive::OMPD_teams: genTeamsOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); break; + case llvm::omp::Directive::OMPD_tile: + case llvm::omp::Directive::OMPD_unroll: + TODO(loc, "Unhandled loop directive (" + + llvm::omp::getOpenMPDirectiveName(dir) + ")"); // case llvm::omp::Directive::OMPD_workdistribute: case llvm::omp::Directive::OMPD_workshare: // FIXME: Workshare is not a commonly used OpenMP construct, an @@ -2035,6 +2052,7 @@ static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, // that use this construct, add a single construct for now. genSingleOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); break; + // Composite constructs case llvm::omp::Directive::OMPD_distribute_parallel_do: genCompositeDistributeParallelDo(converter, symTable, semaCtx, eval, loc, @@ -2174,45 +2192,14 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, ConstructQueue queue{ buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx, eval, directive.source, directive.v, clauses)}; - - switch (directive.v) { - default: - break; - case llvm::omp::Directive::OMPD_barrier: - genBarrierOp(converter, symTable, semaCtx, eval, currentLocation, queue, - queue.begin()); - break; - case llvm::omp::Directive::OMPD_taskwait: - genTaskwaitOp(converter, symTable, semaCtx, eval, currentLocation, clauses, - queue, queue.begin()); - break; - case llvm::omp::Directive::OMPD_taskyield: - genTaskyieldOp(converter, symTable, semaCtx, eval, currentLocation, queue, - queue.begin()); - break; - case llvm::omp::Directive::OMPD_target_data: - genTargetDataOp(converter, symTable, semaCtx, eval, currentLocation, - clauses, queue, queue.begin()); - break; - case llvm::omp::Directive::OMPD_target_enter_data: - genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses, queue, - queue.begin()); - break; - case llvm::omp::Directive::OMPD_target_exit_data: - genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses, queue, - queue.begin()); - break; - case llvm::omp::Directive::OMPD_target_update: - genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, currentLocation, clauses, queue, - queue.begin()); - break; - case llvm::omp::Directive::OMPD_ordered: + if (directive.v == llvm::omp::Directive::OMPD_ordered) { + // Standalone "ordered" directive. genOrderedOp(converter, symTable, semaCtx, eval, currentLocation, clauses, queue, queue.begin()); - break; + } else { + // Dispatch handles the "block-associated" variant of "ordered". + genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); } } @@ -2466,8 +2453,7 @@ genOMP(Fortran::lower::AbstractConverter &converter, ConstructQueue queue{buildConstructQueue( converter.getFirOpBuilder().getModule(), semaCtx, eval, sectionConstruct.source, llvm::omp::Directive::OMPD_section, {})}; - genSectionOp(converter, symTable, semaCtx, eval, loc, - /*clauses=*/{}, queue, queue.begin()); + genOMPDispatch(converter, symTable, semaCtx, eval, loc, queue, queue.begin()); } static void -- GitLab From cc54129b983799e1aaea77aa0ff3040dc30cbc8c Mon Sep 17 00:00:00 2001 From: Justin Cady Date: Tue, 14 May 2024 08:48:04 -0400 Subject: [PATCH 224/578] Add option to exclude headers from clang-tidy analysis (#91400) This is a renewed attempt to land @toddlipcon's D34654. The comments on that patch indicate a broad desire for some ability to ignore headers. After considering various options, including migrating to std::regex, I believe this is the best path forward. It's intuitive to have separate regexes for including headers versus excluding them, and this approach has the added benefit of being completely opt-in. No existing configs will break, regardless of existing HeaderFilterRegex values. This functionality is useful for improving performance when analyzing a targeted subset of code, as well as in cases where some collection of headers cannot be modified (third party source, for example). --- .../ClangTidyDiagnosticConsumer.cpp | 28 ++- .../clang-tidy/ClangTidyDiagnosticConsumer.h | 1 + .../clang-tidy/ClangTidyOptions.cpp | 6 +- .../clang-tidy/ClangTidyOptions.h | 4 + .../clang-tidy/tool/ClangTidyMain.cpp | 18 ++ .../clang-tidy/tool/run-clang-tidy.py | 13 + clang-tools-extra/docs/ReleaseNotes.rst | 3 + clang-tools-extra/docs/clang-tidy/index.rst | 235 +++++++++--------- .../Inputs/config-files/.clang-tidy | 1 + .../Inputs/config-files/1/.clang-tidy | 1 + .../Inputs/config-files/3/.clang-tidy | 1 + .../infrastructure/config-files.cpp | 15 +- .../clang-tidy/infrastructure/file-filter.cpp | 7 + 13 files changed, 207 insertions(+), 126 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp index de2a3b51422a..200bb87a5ac3 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -311,7 +311,18 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer( : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine), RemoveIncompatibleErrors(RemoveIncompatibleErrors), GetFixesFromNotes(GetFixesFromNotes), - EnableNolintBlocks(EnableNolintBlocks) {} + EnableNolintBlocks(EnableNolintBlocks) { + + if (Context.getOptions().HeaderFilterRegex && + !Context.getOptions().HeaderFilterRegex->empty()) + HeaderFilter = + std::make_unique(*Context.getOptions().HeaderFilterRegex); + + if (Context.getOptions().ExcludeHeaderFilterRegex && + !Context.getOptions().ExcludeHeaderFilterRegex->empty()) + ExcludeHeaderFilter = std::make_unique( + *Context.getOptions().ExcludeHeaderFilterRegex); +} void ClangTidyDiagnosticConsumer::finalizeLastError() { if (!Errors.empty()) { @@ -562,22 +573,17 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location, } StringRef FileName(File->getName()); - LastErrorRelatesToUserCode = LastErrorRelatesToUserCode || - Sources.isInMainFile(Location) || - getHeaderFilter()->match(FileName); + LastErrorRelatesToUserCode = + LastErrorRelatesToUserCode || Sources.isInMainFile(Location) || + (HeaderFilter && + (HeaderFilter->match(FileName) && + !(ExcludeHeaderFilter && ExcludeHeaderFilter->match(FileName)))); unsigned LineNumber = Sources.getExpansionLineNumber(Location); LastErrorPassesLineFilter = LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber); } -llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() { - if (!HeaderFilter) - HeaderFilter = - std::make_unique(*Context.getOptions().HeaderFilterRegex); - return HeaderFilter.get(); -} - void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() { // Each error is modelled as the set of intervals in which it applies // replacements. To detect overlapping replacements, we use a sweep line diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h index 9280eb1e1f21..97e16a12febd 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h @@ -313,6 +313,7 @@ private: bool EnableNolintBlocks; std::vector Errors; std::unique_ptr HeaderFilter; + std::unique_ptr ExcludeHeaderFilter; bool LastErrorRelatesToUserCode = false; bool LastErrorPassesLineFilter = false; bool LastErrorWasIgnored = false; diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp index cbf21a0e2ae3..445c7f85c900 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -170,6 +170,8 @@ template <> struct MappingTraits { IO.mapOptional("ImplementationFileExtensions", Options.ImplementationFileExtensions); IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex); + IO.mapOptional("ExcludeHeaderFilterRegex", + Options.ExcludeHeaderFilterRegex); IO.mapOptional("FormatStyle", Options.FormatStyle); IO.mapOptional("User", Options.User); IO.mapOptional("CheckOptions", Options.CheckOptions); @@ -191,7 +193,8 @@ ClangTidyOptions ClangTidyOptions::getDefaults() { Options.WarningsAsErrors = ""; Options.HeaderFileExtensions = {"", "h", "hh", "hpp", "hxx"}; Options.ImplementationFileExtensions = {"c", "cc", "cpp", "cxx"}; - Options.HeaderFilterRegex = ""; + Options.HeaderFilterRegex = std::nullopt; + Options.ExcludeHeaderFilterRegex = std::nullopt; Options.SystemHeaders = false; Options.FormatStyle = "none"; Options.User = std::nullopt; @@ -231,6 +234,7 @@ ClangTidyOptions &ClangTidyOptions::mergeWith(const ClangTidyOptions &Other, overrideValue(ImplementationFileExtensions, Other.ImplementationFileExtensions); overrideValue(HeaderFilterRegex, Other.HeaderFilterRegex); + overrideValue(ExcludeHeaderFilterRegex, Other.ExcludeHeaderFilterRegex); overrideValue(SystemHeaders, Other.SystemHeaders); overrideValue(FormatStyle, Other.FormatStyle); overrideValue(User, Other.User); diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/clang-tools-extra/clang-tidy/ClangTidyOptions.h index e7636cb5d9b0..85d5a02ebbc1 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.h +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.h @@ -83,6 +83,10 @@ struct ClangTidyOptions { /// main files will always be displayed. std::optional HeaderFilterRegex; + /// \brief Exclude warnings from headers matching this filter, even if they + /// match \c HeaderFilterRegex. + std::optional ExcludeHeaderFilterRegex; + /// Output warnings from system headers matching \c HeaderFilterRegex. std::optional SystemHeaders; diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp index f82f4417141d..7388f20ef288 100644 --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -53,6 +53,7 @@ Configuration files: Checks - Same as '--checks'. Additionally, the list of globs can be specified as a list instead of a string. + ExcludeHeaderFilterRegex - Same as '--exclude-header-filter'. ExtraArgs - Same as '--extra-args'. ExtraArgsBefore - Same as '--extra-args-before'. FormatStyle - Same as '--format-style'. @@ -132,6 +133,20 @@ option in .clang-tidy file, if any. cl::init(""), cl::cat(ClangTidyCategory)); +static cl::opt ExcludeHeaderFilter("exclude-header-filter", + desc(R"( +Regular expression matching the names of the +headers to exclude diagnostics from. Diagnostics +from the main file of each translation unit are +always displayed. +Must be used together with --header-filter. +Can be used together with -line-filter. +This option overrides the 'ExcludeHeaderFilterRegex' +option in .clang-tidy file, if any. +)"), + cl::init(""), + cl::cat(ClangTidyCategory)); + static cl::opt SystemHeaders("system-headers", desc(R"( Display the errors from system headers. This option overrides the 'SystemHeaders' option @@ -353,6 +368,7 @@ static std::unique_ptr createOptionsProvider( DefaultOptions.Checks = DefaultChecks; DefaultOptions.WarningsAsErrors = ""; DefaultOptions.HeaderFilterRegex = HeaderFilter; + DefaultOptions.ExcludeHeaderFilterRegex = ExcludeHeaderFilter; DefaultOptions.SystemHeaders = SystemHeaders; DefaultOptions.FormatStyle = FormatStyle; DefaultOptions.User = llvm::sys::Process::GetEnv("USER"); @@ -367,6 +383,8 @@ static std::unique_ptr createOptionsProvider( OverrideOptions.WarningsAsErrors = WarningsAsErrors; if (HeaderFilter.getNumOccurrences() > 0) OverrideOptions.HeaderFilterRegex = HeaderFilter; + if (ExcludeHeaderFilter.getNumOccurrences() > 0) + OverrideOptions.ExcludeHeaderFilterRegex = ExcludeHeaderFilter; if (SystemHeaders.getNumOccurrences() > 0) OverrideOptions.SystemHeaders = SystemHeaders; if (FormatStyle.getNumOccurrences() > 0) diff --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py index 1bd4a5b28309..4dd20bec81d3 100755 --- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py +++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py @@ -106,11 +106,14 @@ def get_tidy_invocation( use_color, plugins, warnings_as_errors, + exclude_header_filter, ): """Gets a command line for clang-tidy.""" start = [clang_tidy_binary] if allow_enabling_alpha_checkers: start.append("-allow-enabling-analyzer-alpha-checkers") + if exclude_header_filter is not None: + start.append("--exclude-header-filter=" + exclude_header_filter) if header_filter is not None: start.append("-header-filter=" + header_filter) if line_filter is not None: @@ -228,6 +231,7 @@ def run_tidy(args, clang_tidy_binary, tmpdir, build_path, queue, lock, failed_fi args.use_color, args.plugins, args.warnings_as_errors, + args.exclude_header_filter, ) proc = subprocess.Popen( @@ -292,6 +296,14 @@ def main(): "-config option after reading specified config file. " "Use either -config-file or -config, not both.", ) + parser.add_argument( + "-exclude-header-filter", + default=None, + help="Regular expression matching the names of the " + "headers to exclude diagnostics from. Diagnostics from " + "the main file of each translation unit are always " + "displayed.", + ) parser.add_argument( "-header-filter", default=None, @@ -450,6 +462,7 @@ def main(): args.use_color, args.plugins, args.warnings_as_errors, + args.exclude_header_filter, ) invocation.append("-list-checks") invocation.append("-") diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 898c7acc1310..19f830741295 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -115,6 +115,9 @@ Improvements to clang-tidy - Fixed `--verify-config` option not properly parsing checks when using the literal operator in the `.clang-tidy` config. +- Added argument `--exclude-header-filter` and config option `ExcludeHeaderFilterRegex` + to exclude headers from analysis via a RegEx. + New checks ^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst index 852566f26672..9ccacefa3c2c 100644 --- a/clang-tools-extra/docs/clang-tidy/index.rst +++ b/clang-tools-extra/docs/clang-tidy/index.rst @@ -116,122 +116,130 @@ An overview of all the command-line options: Generic Options: - --help - Display available options (--help-hidden for more) - --help-list - Display list of available options (--help-list-hidden for more) - --version - Display the version of this program + --help - Display available options (--help-hidden for more) + --help-list - Display list of available options (--help-list-hidden for more) + --version - Display the version of this program clang-tidy options: - --checks= - Comma-separated list of globs with optional '-' - prefix. Globs are processed in order of - appearance in the list. Globs without '-' - prefix add checks with matching names to the - set, globs with the '-' prefix remove checks - with matching names from the set of enabled - checks. This option's value is appended to the - value of the 'Checks' option in .clang-tidy - file, if any. - --config= - Specifies a configuration in YAML/JSON format: - -config="{Checks: '*', - CheckOptions: {x: y}}" - When the value is empty, clang-tidy will - attempt to find a file named .clang-tidy for - each source file in its parent directories. - --config-file= - Specify the path of .clang-tidy or custom config file: - e.g. --config-file=/some/path/myTidyConfigFile - This option internally works exactly the same way as - --config option after reading specified config file. - Use either --config-file or --config, not both. - --dump-config - Dumps configuration in the YAML format to - stdout. This option can be used along with a - file name (and '--' if the file is outside of a - project with configured compilation database). - The configuration used for this file will be - printed. - Use along with -checks=* to include - configuration of all checks. - --enable-check-profile - Enable per-check timing profiles, and print a - report to stderr. - --enable-module-headers-parsing - Enables preprocessor-level module header parsing - for C++20 and above, empowering specific checks - to detect macro definitions within modules. This - feature may cause performance and parsing issues - and is therefore considered experimental. - --explain-config - For each enabled check explains, where it is - enabled, i.e. in clang-tidy binary, command - line or a specific configuration file. - --export-fixes= - YAML file to store suggested fixes in. The - stored fixes can be applied to the input source - code with clang-apply-replacements. - --extra-arg= - Additional argument to append to the compiler command line - --extra-arg-before= - Additional argument to prepend to the compiler command line - --fix - Apply suggested fixes. Without -fix-errors - clang-tidy will bail out if any compilation - errors were found. - --fix-errors - Apply suggested fixes even if compilation - errors were found. If compiler errors have - attached fix-its, clang-tidy will apply them as - well. - --fix-notes - If a warning has no fix, but a single fix can - be found through an associated diagnostic note, - apply the fix. - Specifying this flag will implicitly enable the - '--fix' flag. - --format-style= - Style for formatting code around applied fixes: - - 'none' (default) turns off formatting - - 'file' (literally 'file', not a placeholder) - uses .clang-format file in the closest parent - directory - - '{ }' specifies options inline, e.g. - -format-style='{BasedOnStyle: llvm, IndentWidth: 8}' - - 'llvm', 'google', 'webkit', 'mozilla' - See clang-format documentation for the up-to-date - information about formatting styles and options. - This option overrides the 'FormatStyle` option in - .clang-tidy file, if any. - --header-filter= - Regular expression matching the names of the - headers to output diagnostics from. Diagnostics - from the main file of each translation unit are - always displayed. - Can be used together with -line-filter. - This option overrides the 'HeaderFilterRegex' - option in .clang-tidy file, if any. - --line-filter= - List of files with line ranges to filter the - warnings. Can be used together with - -header-filter. The format of the list is a - JSON array of objects: - [ - {"name":"file1.cpp","lines":[[1,3],[5,7]]}, - {"name":"file2.h"} - ] - --list-checks - List all enabled checks and exit. Use with - -checks=* to list all available checks. - --load= - Load the specified plugin - -p - Build path - --quiet - Run clang-tidy in quiet mode. This suppresses - printing statistics about ignored warnings and - warnings treated as errors if the respective - options are specified. - --store-check-profile= - By default reports are printed in tabulated - format to stderr. When this option is passed, - these per-TU profiles are instead stored as JSON. - --system-headers - Display the errors from system headers. - This option overrides the 'SystemHeaders' option - in .clang-tidy file, if any. - --use-color - Use colors in diagnostics. If not set, colors - will be used if the terminal connected to - standard output supports colors. - This option overrides the 'UseColor' option in - .clang-tidy file, if any. - --verify-config - Check the config files to ensure each check and - option is recognized. - --vfsoverlay= - Overlay the virtual filesystem described by file - over the real file system. - --warnings-as-errors= - Upgrades warnings to errors. Same format as - '-checks'. - This option's value is appended to the value of - the 'WarningsAsErrors' option in .clang-tidy - file, if any. + --checks= - Comma-separated list of globs with optional '-' + prefix. Globs are processed in order of + appearance in the list. Globs without '-' + prefix add checks with matching names to the + set, globs with the '-' prefix remove checks + with matching names from the set of enabled + checks. This option's value is appended to the + value of the 'Checks' option in .clang-tidy + file, if any. + --config= - Specifies a configuration in YAML/JSON format: + -config="{Checks: '*', + CheckOptions: {x: y}}" + When the value is empty, clang-tidy will + attempt to find a file named .clang-tidy for + each source file in its parent directories. + --config-file= - Specify the path of .clang-tidy or custom config file: + e.g. --config-file=/some/path/myTidyConfigFile + This option internally works exactly the same way as + --config option after reading specified config file. + Use either --config-file or --config, not both. + --dump-config - Dumps configuration in the YAML format to + stdout. This option can be used along with a + file name (and '--' if the file is outside of a + project with configured compilation database). + The configuration used for this file will be + printed. + Use along with -checks=* to include + configuration of all checks. + --enable-check-profile - Enable per-check timing profiles, and print a + report to stderr. + --enable-module-headers-parsing - Enables preprocessor-level module header parsing + for C++20 and above, empowering specific checks + to detect macro definitions within modules. This + feature may cause performance and parsing issues + and is therefore considered experimental. + --exclude-header-filter= - Regular expression matching the names of the + headers to exclude diagnostics from. Diagnostics + from the main file of each translation unit are + always displayed. + Must be used together with --header-filter. + Can be used together with -line-filter. + This option overrides the 'ExcludeHeaderFilterRegex' + option in .clang-tidy file, if any. + --explain-config - For each enabled check explains, where it is + enabled, i.e. in clang-tidy binary, command + line or a specific configuration file. + --export-fixes= - YAML file to store suggested fixes in. The + stored fixes can be applied to the input source + code with clang-apply-replacements. + --extra-arg= - Additional argument to append to the compiler command line + --extra-arg-before= - Additional argument to prepend to the compiler command line + --fix - Apply suggested fixes. Without -fix-errors + clang-tidy will bail out if any compilation + errors were found. + --fix-errors - Apply suggested fixes even if compilation + errors were found. If compiler errors have + attached fix-its, clang-tidy will apply them as + well. + --fix-notes - If a warning has no fix, but a single fix can + be found through an associated diagnostic note, + apply the fix. + Specifying this flag will implicitly enable the + '--fix' flag. + --format-style= - Style for formatting code around applied fixes: + - 'none' (default) turns off formatting + - 'file' (literally 'file', not a placeholder) + uses .clang-format file in the closest parent + directory + - '{ }' specifies options inline, e.g. + -format-style='{BasedOnStyle: llvm, IndentWidth: 8}' + - 'llvm', 'google', 'webkit', 'mozilla' + See clang-format documentation for the up-to-date + information about formatting styles and options. + This option overrides the 'FormatStyle` option in + .clang-tidy file, if any. + --header-filter= - Regular expression matching the names of the + headers to output diagnostics from. Diagnostics + from the main file of each translation unit are + always displayed. + Can be used together with -line-filter. + This option overrides the 'HeaderFilterRegex' + option in .clang-tidy file, if any. + --line-filter= - List of files with line ranges to filter the + warnings. Can be used together with + -header-filter. The format of the list is a + JSON array of objects: + [ + {"name":"file1.cpp","lines":[[1,3],[5,7]]}, + {"name":"file2.h"} + ] + --list-checks - List all enabled checks and exit. Use with + -checks=* to list all available checks. + --load= - Load the specified plugin + -p - Build path + --quiet - Run clang-tidy in quiet mode. This suppresses + printing statistics about ignored warnings and + warnings treated as errors if the respective + options are specified. + --store-check-profile= - By default reports are printed in tabulated + format to stderr. When this option is passed, + these per-TU profiles are instead stored as JSON. + --system-headers - Display the errors from system headers. + This option overrides the 'SystemHeaders' option + in .clang-tidy file, if any. + --use-color - Use colors in diagnostics. If not set, colors + will be used if the terminal connected to + standard output supports colors. + This option overrides the 'UseColor' option in + .clang-tidy file, if any. + --verify-config - Check the config files to ensure each check and + option is recognized. + --vfsoverlay= - Overlay the virtual filesystem described by file + over the real file system. + --warnings-as-errors= - Upgrades warnings to errors. Same format as + '-checks'. + This option's value is appended to the value of + the 'WarningsAsErrors' option in .clang-tidy + file, if any. -p is used to read a compile command database. @@ -269,6 +277,7 @@ An overview of all the command-line options: Checks - Same as '--checks'. Additionally, the list of globs can be specified as a list instead of a string. + ExcludeHeaderFilterRegex - Same as '--exclude-header-filter'. ExtraArgs - Same as '--extra-args'. ExtraArgsBefore - Same as '--extra-args-before'. FormatStyle - Same as '--format-style'. diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/.clang-tidy b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/.clang-tidy index 942169f2ec42..83605c85dd92 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/.clang-tidy +++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/.clang-tidy @@ -1,2 +1,3 @@ Checks: 'from-parent' HeaderFilterRegex: 'parent' +ExcludeHeaderFilterRegex: 'exc-parent' diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/1/.clang-tidy b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/1/.clang-tidy index 800fd4e8eb2a..c37f16bc2d7d 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/1/.clang-tidy +++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/1/.clang-tidy @@ -1,2 +1,3 @@ Checks: 'from-child1' HeaderFilterRegex: 'child1' +ExcludeHeaderFilterRegex: 'exc-child1' diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/3/.clang-tidy b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/3/.clang-tidy index 28dc8517ac9f..9365108255bd 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/3/.clang-tidy +++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/3/.clang-tidy @@ -1,3 +1,4 @@ InheritParentConfig: true Checks: 'from-child3' HeaderFilterRegex: 'child3' +ExcludeHeaderFilterRegex: 'exc-child3' diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp index d287412454ca..44d43ebbf8d2 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp @@ -1,18 +1,23 @@ // RUN: clang-tidy -dump-config %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-BASE // CHECK-BASE: Checks: {{.*}}from-parent // CHECK-BASE: HeaderFilterRegex: parent +// CHECK-BASE: ExcludeHeaderFilterRegex: exc-parent // RUN: clang-tidy -dump-config %S/Inputs/config-files/1/- -- | FileCheck %s -check-prefix=CHECK-CHILD1 // CHECK-CHILD1: Checks: {{.*}}from-child1 // CHECK-CHILD1: HeaderFilterRegex: child1 +// CHECK-CHILD1: ExcludeHeaderFilterRegex: exc-child1 // RUN: clang-tidy -dump-config %S/Inputs/config-files/2/- -- | FileCheck %s -check-prefix=CHECK-CHILD2 // CHECK-CHILD2: Checks: {{.*}}from-parent // CHECK-CHILD2: HeaderFilterRegex: parent +// CHECK-CHILD2: ExcludeHeaderFilterRegex: exc-parent // RUN: clang-tidy -dump-config %S/Inputs/config-files/3/- -- | FileCheck %s -check-prefix=CHECK-CHILD3 // CHECK-CHILD3: Checks: {{.*}}from-parent,from-child3 // CHECK-CHILD3: HeaderFilterRegex: child3 -// RUN: clang-tidy -dump-config -checks='from-command-line' -header-filter='from command line' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-COMMAND-LINE +// CHECK-CHILD3: ExcludeHeaderFilterRegex: exc-child3 +// RUN: clang-tidy -dump-config -checks='from-command-line' -header-filter='from command line' -exclude-header-filter='from_command_line' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-COMMAND-LINE // CHECK-COMMAND-LINE: Checks: {{.*}}from-parent,from-command-line // CHECK-COMMAND-LINE: HeaderFilterRegex: from command line +// CHECK-COMMAND-LINE: ExcludeHeaderFilterRegex: from_command_line // For this test we have to use names of the real checks because otherwise values are ignored. // Running with the old key: , value: CheckOptions @@ -68,3 +73,11 @@ // Dumped config does not overflow for unsigned options // RUN: clang-tidy --dump-config %S/Inputs/config-files/5/- -- | FileCheck %s -check-prefix=CHECK-OVERFLOW // CHECK-OVERFLOW: misc-throw-by-value-catch-by-reference.MaxSize: '1152921504606846976' + +// RUN: clang-tidy -dump-config -checks='readability-function-size' -header-filter='foo/*' -exclude-header-filter='bar*' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-EXCLUDE-HEADERS +// CHECK-EXCLUDE-HEADERS: HeaderFilterRegex: 'foo/*' +// CHECK-EXCLUDE-HEADERS: ExcludeHeaderFilterRegex: 'bar*' + +// RUN: clang-tidy -dump-config -checks='readability-function-size' -header-filter='' -exclude-header-filter='' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=EMPTY-CHECK-EXCLUDE-HEADERS +// EMPTY-CHECK-EXCLUDE-HEADERS: HeaderFilterRegex: '' +// EMPTY-CHECK-EXCLUDE-HEADERS: ExcludeHeaderFilterRegex: '' diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp index a7498723de2b..448ef9ddf166 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp @@ -11,6 +11,7 @@ // RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers -quiet %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4-QUIET %s // RUN: clang-tidy -checks='-*,cppcoreguidelines-pro-type-cstyle-cast' -header-filter='.*' -system-headers %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK5 %s // RUN: clang-tidy -checks='-*,cppcoreguidelines-pro-type-cstyle-cast' -header-filter='.*' %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK5-NO-SYSTEM-HEADERS %s +// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -exclude-header-filter='header1\.h' %s -- -I %S/Inputs/file-filter/ -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK6 %s #include "header1.h" // CHECK-NOT: warning: @@ -21,6 +22,7 @@ // CHECK3-QUIET-NOT: warning: // CHECK4: header1.h:1:12: warning: single-argument constructors // CHECK4-QUIET: header1.h:1:12: warning: single-argument constructors +// CHECK6-NOT: warning: #include "header2.h" // CHECK-NOT: warning: @@ -31,6 +33,7 @@ // CHECK3-QUIET: header2.h:1:12: warning: single-argument constructors // CHECK4: header2.h:1:12: warning: single-argument constructors // CHECK4-QUIET: header2.h:1:12: warning: single-argument constructors +// CHECK6: header2.h:1:12: warning: single-argument constructors #include // CHECK-NOT: warning: @@ -41,6 +44,7 @@ // CHECK3-QUIET-NOT: warning: // CHECK4: system-header.h:1:12: warning: single-argument constructors // CHECK4-QUIET: system-header.h:1:12: warning: single-argument constructors +// CHECK6-NOT: warning: class A { A(int); }; // CHECK: :[[@LINE-1]]:11: warning: single-argument constructors @@ -51,6 +55,7 @@ class A { A(int); }; // CHECK3-QUIET: :[[@LINE-6]]:11: warning: single-argument constructors // CHECK4: :[[@LINE-7]]:11: warning: single-argument constructors // CHECK4-QUIET: :[[@LINE-8]]:11: warning: single-argument constructors +// CHECK6: :[[@LINE-9]]:11: warning: single-argument constructors // CHECK-NOT: warning: // CHECK-QUIET-NOT: warning: @@ -73,6 +78,8 @@ class A { A(int); }; // CHECK4-NOT: Suppressed {{.*}} warnings // CHECK4-NOT: Use -header-filter=.* {{.*}} // CHECK4-QUIET-NOT: Suppressed +// CHECK6: Suppressed 2 warnings (2 in non-user code) +// CHECK6: Use -header-filter=.* {{.*}} int x = 123; auto x_ptr = TO_FLOAT_PTR(&x); -- GitLab From bf7a0f9958b93d9979e0adf93b80ad056615706d Mon Sep 17 00:00:00 2001 From: AdityaK Date: Tue, 14 May 2024 06:13:11 -0700 Subject: [PATCH 225/578] Fix incorrect codegen with respect to GEPs #85333 (#92047) As mentioned in #68882 and https://discourse.llvm.org/t/rfc-replacing-getelementptr-with-ptradd/68699 Gep arithmetic isn't consistent with different types. GVNSink didn't realize this and sank all geps as long as their operands can be wired via PHIs in a post-dominator. Fixes: #85333 Reapply: #88440 after fixing the non-determinism issues in #90995 --- llvm/lib/Transforms/Scalar/GVNSink.cpp | 9 +- .../Transforms/GVNSink/different-gep-types.ll | 101 ++++++++++++++++++ 2 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 llvm/test/Transforms/GVNSink/different-gep-types.ll diff --git a/llvm/lib/Transforms/Scalar/GVNSink.cpp b/llvm/lib/Transforms/Scalar/GVNSink.cpp index 95a4c644a91a..7a183e4d3aa8 100644 --- a/llvm/lib/Transforms/Scalar/GVNSink.cpp +++ b/llvm/lib/Transforms/Scalar/GVNSink.cpp @@ -763,12 +763,11 @@ GVNSink::analyzeInstructionForSinking(LockstepReverseIterator &LRI, // try and continue making progress. Instruction *I0 = NewInsts[0]; - // If all instructions that are going to participate don't have the same - // number of operands, we can't do any useful PHI analysis for all operands. - auto hasDifferentNumOperands = [&I0](Instruction *I) { - return I->getNumOperands() != I0->getNumOperands(); + auto isNotSameOperation = [&I0](Instruction *I) { + return !I0->isSameOperationAs(I); }; - if (any_of(NewInsts, hasDifferentNumOperands)) + + if (any_of(NewInsts, isNotSameOperation)) return std::nullopt; for (unsigned OpNum = 0, E = I0->getNumOperands(); OpNum != E; ++OpNum) { diff --git a/llvm/test/Transforms/GVNSink/different-gep-types.ll b/llvm/test/Transforms/GVNSink/different-gep-types.ll new file mode 100644 index 000000000000..659be51cc56e --- /dev/null +++ b/llvm/test/Transforms/GVNSink/different-gep-types.ll @@ -0,0 +1,101 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=gvn-sink -S %s | FileCheck %s + +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + +%"struct.std::pair" = type <{ i32, %struct.substruct, [2 x i8] }> +%struct.substruct = type { i8, i8 } +%"struct.std::random_access_iterator_tag" = type { i8 } + +; Check that gep is not sunk as they are of different types. +define void @bar(ptr noundef nonnull align 4 dereferenceable(4) %__i, i32 noundef %__n) { +; CHECK-LABEL: define void @bar( +; CHECK-SAME: ptr noundef nonnull align 4 dereferenceable(4) [[__I:%.*]], i32 noundef [[__N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[__N]], 1 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__I]], align 4 +; CHECK-NEXT: [[INCDEC_PTR4:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i32 -8 +; CHECK-NEXT: br label [[IF_END6:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__I]], align 4 +; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds %"struct.std::pair", ptr [[TMP1]], i32 [[__N]] +; CHECK-NEXT: br label [[IF_END6]] +; CHECK: if.end6: +; CHECK-NEXT: [[INCDEC_PTR_SINK:%.*]] = phi ptr [ [[INCDEC_PTR4]], [[IF_THEN]] ], [ [[ADD_PTR]], [[IF_ELSE]] ] +; CHECK-NEXT: store ptr [[INCDEC_PTR_SINK]], ptr [[__I]], align 4 +; CHECK-NEXT: ret void +; +entry: + %cmp = icmp eq i32 %__n, 1 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %3 = load ptr, ptr %__i, align 4 + %incdec.ptr4 = getelementptr inbounds i8, ptr %3, i32 -8 + br label %if.end6 + +if.else: + %4 = load ptr, ptr %__i, align 4 + %add.ptr = getelementptr inbounds %"struct.std::pair", ptr %4, i32 %__n + br label %if.end6 + +if.end6: + %incdec.ptr.sink = phi ptr [ %incdec.ptr4, %if.then ], [ %add.ptr, %if.else ] + store ptr %incdec.ptr.sink, ptr %__i, align 4 + ret void +} + +; Check that load,gep, and store are all sunk as they are safe to do. +define void @foo(ptr noundef nonnull align 4 dereferenceable(4) %__i, i32 noundef %__n) { +; CHECK-LABEL: define void @foo( +; CHECK-SAME: ptr noundef nonnull align 4 dereferenceable(4) [[__I:%.*]], i32 noundef [[__N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[__N]], 1 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: br label [[IF_END6:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[__N]], -1 +; CHECK-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_ELSE5:%.*]] +; CHECK: if.then3: +; CHECK-NEXT: br label [[IF_END6]] +; CHECK: if.else5: +; CHECK-NEXT: br label [[IF_END6]] +; CHECK: if.end6: +; CHECK-NEXT: [[DOTSINK1:%.*]] = phi i32 [ -4, [[IF_ELSE5]] ], [ -8, [[IF_THEN3]] ], [ 8, [[IF_THEN]] ] +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__I]], align 4 +; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i32 [[DOTSINK1]] +; CHECK-NEXT: store ptr [[INCDEC_PTR]], ptr [[__I]], align 4 +; CHECK-NEXT: ret void +; +entry: + %cmp = icmp eq i32 %__n, 1 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %1 = load ptr, ptr %__i, align 4 + %incdec.ptr = getelementptr inbounds i8, ptr %1, i32 8 + store ptr %incdec.ptr, ptr %__i, align 4 + br label %if.end6 + +if.else: + %cmp2 = icmp eq i32 %__n, -1 + br i1 %cmp2, label %if.then3, label %if.else5 + +if.then3: + %3 = load ptr, ptr %__i, align 4 + %incdec.ptr4 = getelementptr inbounds i8, ptr %3, i32 -8 + store ptr %incdec.ptr4, ptr %__i, align 4 + br label %if.end6 + +if.else5: + %4 = load ptr, ptr %__i, align 4 + %add.ptr = getelementptr inbounds i8, ptr %4, i32 -4 + store ptr %add.ptr, ptr %__i, align 4 + br label %if.end6 + +if.end6: + ret void +} -- GitLab From e1685eb8d7de66ce6420cdd3340a2e3f892c09bd Mon Sep 17 00:00:00 2001 From: Mubashar Ahmad Date: Tue, 14 May 2024 14:32:50 +0100 Subject: [PATCH 226/578] [mlir][llvm] Add llvm.vector.deinterleave2 intrinsic (#91986) Adds the LLVM vector.deinterleave2 intrinsic to the MLIR LLVM dialect. The deinterleave2 intrinsic takes a vector and returns two vectors with the first having even elements and the second with odd elements from the input vector. The inverse of vector.interleave2. --- .../include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td | 6 ++++++ mlir/test/Dialect/LLVMIR/roundtrip.mlir | 7 +++++++ mlir/test/Target/LLVMIR/Import/intrinsic.ll | 9 +++++++++ mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir | 13 +++++++++++++ 4 files changed, 35 insertions(+) diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td index 759cbe6c1564..bd347d0cf630 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td @@ -1074,6 +1074,12 @@ def LLVM_vector_interleave2 ]>, Arguments<(ins LLVM_AnyVector:$vec1, LLVM_AnyVector:$vec2)>; +def LLVM_vector_deinterleave2 + : LLVM_OneResultIntrOp<"vector.deinterleave2", + /*overloadedResults=*/[], /*overloadedOperands=*/[0], + /*traits=*/[Pure]>, + Arguments<(ins LLVM_AnyVector:$vec)>; + // // LLVM Vector Predication operations. // diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir index 3b94db389f54..410122df1c14 100644 --- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir @@ -349,6 +349,13 @@ func.func @vector_interleave2(%vec1: vector<[4]xf16>, %vec2 : vector<[4]xf16>) { return } +// CHECK-LABEL: @vector_deinterleave2 +func.func @vector_deinterleave2(%vec: vector<[8]xf16>) { + // CHECK: = "llvm.intr.vector.deinterleave2"({{.*}}) : (vector<[8]xf16>) -> !llvm.struct<(vector<[4]xf16>, vector<[4]xf16>)> + %0 = "llvm.intr.vector.deinterleave2"(%vec) : (vector<[8]xf16>) -> !llvm.struct<(vector<[4]xf16>, vector<[4]xf16>)> + return +} + // CHECK-LABEL: @alloca func.func @alloca(%size : i64) { // CHECK: llvm.alloca %{{.*}} x i32 : (i64) -> !llvm.ptr diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic.ll b/mlir/test/Target/LLVMIR/Import/intrinsic.ll index bf6847a32ff4..e43024ff868e 100644 --- a/mlir/test/Target/LLVMIR/Import/intrinsic.ll +++ b/mlir/test/Target/LLVMIR/Import/intrinsic.ll @@ -786,6 +786,15 @@ define void @vector_extract( %0) { ret void } +; CHECK-LABEL: llvm.func @vector_deinterleave2 +define void @vector_deinterleave2(<4 x double> %0, %1) { + ; CHECK: "llvm.intr.vector.deinterleave2"(%{{.*}}) : (vector<4xf64>) -> !llvm.struct<(vector<2xf64>, vector<2xf64>)> + %3 = call { <2 x double>, <2 x double> } @llvm.vector.deinterleave2.v4f64(<4 x double> %0); + ; CHECK: "llvm.intr.vector.deinterleave2"(%{{.*}}) : (!llvm.vec) -> !llvm.struct<(vec, vec)> + %4 = call { , } @llvm.vector.deinterleave2.nxv8i32( %1); + ret void +} + ; CHECK-LABEL: llvm.func @vector_predication_intrinsics define void @vector_predication_intrinsics(<8 x i32> %0, <8 x i32> %1, <8 x float> %2, <8 x float> %3, <8 x i64> %4, <8 x double> %5, <8 x ptr> %6, i32 %7, float %8, ptr %9, ptr %10, <8 x i1> %11, i32 %12) { ; CHECK: "llvm.intr.vp.add"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (vector<8xi32>, vector<8xi32>, vector<8xi1>, i32) -> vector<8xi32> diff --git a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir index db5184a63d98..238c3e4263cb 100644 --- a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir @@ -942,6 +942,17 @@ llvm.func @vector_insert_extract(%f256: vector<8xi32>, %f128: vector<4xi32>, llvm.return } +// CHECK-LABEL: @vector_deinterleave2 +llvm.func @vector_deinterleave2(%vec1: vector<4xf64>, %vec2: vector<[8]xi32>) { + // CHECK: call { <2 x double>, <2 x double> } @llvm.vector.deinterleave2.v4f64(<4 x double> %{{.*}}) + %0 = "llvm.intr.vector.deinterleave2" (%vec1) : + (vector<4xf64>) -> !llvm.struct<(vector<2xf64>, vector<2xf64>)> + // CHECK: call { , } @llvm.vector.deinterleave2.nxv8i32( %{{.*}}) + %1 = "llvm.intr.vector.deinterleave2" (%vec2) : + (vector<[8]xi32>) -> !llvm.struct<(vector<[4]xi32>, vector<[4]xi32>)> + llvm.return +} + // CHECK-LABEL: @lifetime llvm.func @lifetime(%p: !llvm.ptr) { // CHECK: call void @llvm.lifetime.start @@ -1148,6 +1159,8 @@ llvm.func @experimental_constrained_fptrunc(%s: f64, %v: vector<4xf32>) { // CHECK-DAG: declare <8 x i32> @llvm.vector.extract.v8i32.nxv4i32(, i64 immarg) // CHECK-DAG: declare <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(, i64 immarg) // CHECK-DAG: declare <2 x i32> @llvm.vector.extract.v2i32.v8i32(<8 x i32>, i64 immarg) +// CHECK-DAG: declare { <2 x double>, <2 x double> } @llvm.vector.deinterleave2.v4f64(<4 x double>) +// CHECK-DAG: declare { , } @llvm.vector.deinterleave2.nxv8i32() // CHECK-DAG: declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) // CHECK-DAG: declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) // CHECK-DAG: declare ptr @llvm.invariant.start.p0(i64 immarg, ptr nocapture) -- GitLab From cfa09473a6f904d214a1b514f41b9d4d9276c927 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 14 May 2024 09:35:30 -0400 Subject: [PATCH 227/578] Cope with MCOperand null Insts (#91794) MCOperand has a constructor that permits a nullptr MCInst, and BOLT makes use of that. Adjust MCOperand's dumper to permit such use. --- llvm/lib/MC/MCInst.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/llvm/lib/MC/MCInst.cpp b/llvm/lib/MC/MCInst.cpp index 3cc50ff43513..639619fe4e99 100644 --- a/llvm/lib/MC/MCInst.cpp +++ b/llvm/lib/MC/MCInst.cpp @@ -38,7 +38,10 @@ void MCOperand::print(raw_ostream &OS, const MCRegisterInfo *RegInfo) const { OS << "Expr:(" << *getExpr() << ")"; } else if (isInst()) { OS << "Inst:("; - getInst()->print(OS, RegInfo); + if (const auto *Inst = getInst()) + Inst->print(OS, RegInfo); + else + OS << "NULL"; OS << ")"; } else OS << "UNDEFINED"; -- GitLab From 725014d866e2a75bfe293ee2d168d4c8f302fc74 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 14 May 2024 09:36:34 -0400 Subject: [PATCH 228/578] [BOLT][NFC] Simplify CFG validation (#91977) Remove 'Valid' local boolean that has a single use, and return directly instead. --- bolt/lib/Core/BinaryFunction.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index de34421ebeb0..4f44ba0d970c 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -3252,12 +3252,9 @@ bool BinaryFunction::validateCFG() const { if (CurrentState == State::CFG_Finalized) return true; - bool Valid = true; for (BinaryBasicBlock *BB : BasicBlocks) - Valid &= BB->validateSuccessorInvariants(); - - if (!Valid) - return Valid; + if (!BB->validateSuccessorInvariants()) + return false; // Make sure all blocks in CFG are valid. auto validateBlock = [this](const BinaryBasicBlock *BB, StringRef Desc) { @@ -3326,7 +3323,7 @@ bool BinaryFunction::validateCFG() const { } } - return Valid; + return true; } void BinaryFunction::fixBranches() { -- GitLab From 312f83f0e0672118a6d82d4b4d3568e9c812086d Mon Sep 17 00:00:00 2001 From: cor3ntin Date: Tue, 14 May 2024 15:37:06 +0200 Subject: [PATCH 229/578] [Clang] Fix dependency computation for pack indexing expression (#91933) Given `foo...[idx]` if idx is value dependent, the expression is type dependent. Fixes #91885 Fixes #91884 --- clang/lib/AST/ComputeDependence.cpp | 13 +++++++++--- clang/lib/Sema/SemaType.cpp | 13 ++++++++---- clang/test/SemaCXX/cxx2c-pack-indexing.cpp | 23 ++++++++++++++++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index bad8e75b2f87..62ca15ea398f 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -375,12 +375,19 @@ ExprDependence clang::computeDependence(PackExpansionExpr *E) { } ExprDependence clang::computeDependence(PackIndexingExpr *E) { + + ExprDependence PatternDep = E->getPackIdExpression()->getDependence() & + ~ExprDependence::UnexpandedPack; + ExprDependence D = E->getIndexExpr()->getDependence(); + if (D & ExprDependence::TypeValueInstantiation) + D |= E->getIndexExpr()->getDependence() | PatternDep | + ExprDependence::Instantiation; + ArrayRef Exprs = E->getExpressions(); if (Exprs.empty()) - D |= (E->getPackIdExpression()->getDependence() | - ExprDependence::TypeValueInstantiation) & - ~ExprDependence::UnexpandedPack; + D |= PatternDep | ExprDependence::Instantiation; + else if (!E->getIndexExpr()->isInstantiationDependent()) { std::optional Index = E->getSelectedIndex(); assert(Index && *Index < Exprs.size() && "pack index out of bound"); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index bfa3799bda06..d65fafc8cf4f 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -9351,15 +9351,20 @@ QualType Sema::BuildCountAttributedArrayType(QualType WrappedTy, /// that expression, according to the rules in C++11 /// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18. QualType Sema::getDecltypeForExpr(Expr *E) { - if (E->isTypeDependent()) - return Context.DependentTy; Expr *IDExpr = E; if (auto *ImplCastExpr = dyn_cast(E)) IDExpr = ImplCastExpr->getSubExpr(); - if (auto *PackExpr = dyn_cast(E)) - IDExpr = PackExpr->getSelectedExpr(); + if (auto *PackExpr = dyn_cast(E)) { + if (E->isInstantiationDependent()) + IDExpr = PackExpr->getPackIdExpression(); + else + IDExpr = PackExpr->getSelectedExpr(); + } + + if (E->isTypeDependent()) + return Context.DependentTy; // C++11 [dcl.type.simple]p4: // The type denoted by decltype(e) is defined as follows: diff --git a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp index a3e5a0931491..0ac85b5bcc14 100644 --- a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp +++ b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp @@ -194,3 +194,26 @@ void h() { // expected-note-re@-2 {{function template specialization '{{.*}}' requested here}} } } + +namespace GH91885 { + +void test(auto...args){ + [&](){ + using R = decltype( args...[idx] ) ; + }.template operator()<0>(); +} + +template +void test2(){ + [&](){ + using R = decltype( args...[idx] ) ; + }.template operator()<0>(); +} + +void f( ) { + test(1); + test2<1>(); +} + + +} -- GitLab From 1aff294f6ef9c0a1a264c55d55e441e37a353f17 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 14 May 2024 09:38:32 -0400 Subject: [PATCH 230/578] [BOLT][NFC] Simplify successor check (#91980) Remove excess parentheses and use `boolean ? true-case : false-case` idiom. --- bolt/lib/Core/BinaryBasicBlock.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bolt/lib/Core/BinaryBasicBlock.cpp b/bolt/lib/Core/BinaryBasicBlock.cpp index 4a83fece0e43..a4b9a7f558cd 100644 --- a/bolt/lib/Core/BinaryBasicBlock.cpp +++ b/bolt/lib/Core/BinaryBasicBlock.cpp @@ -131,11 +131,10 @@ bool BinaryBasicBlock::validateSuccessorInvariants() { break; } case 2: - Valid = (CondBranch && - (TBB == getConditionalSuccessor(true)->getLabel() && - ((!UncondBranch && !FBB) || - (UncondBranch && - FBB == getConditionalSuccessor(false)->getLabel())))); + Valid = + CondBranch && TBB == getConditionalSuccessor(true)->getLabel() && + (UncondBranch ? FBB == getConditionalSuccessor(false)->getLabel() + : !FBB); break; } } -- GitLab From 03eba209852c769ab6993be3bc01cdcc57d787b0 Mon Sep 17 00:00:00 2001 From: erichkeane Date: Tue, 14 May 2024 06:47:02 -0700 Subject: [PATCH 231/578] [OpenACC] Fix ast-print of device_type clause When writing the test for this I seemingly forgot to put 'CHECK' on the lines, so I didn't notice that I was printing the identifiers as pointers rather than their names. This patch corrects the tests and the print behavior. --- clang/lib/AST/OpenACCClause.cpp | 2 +- clang/test/AST/ast-print-openacc-compute-construct.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index f80ecc90d396..8ff6dabcbc48 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -473,7 +473,7 @@ void OpenACCClausePrinter::VisitDeviceTypeClause( if (Arch.first == nullptr) OS << "*"; else - OS << Arch.first; + OS << Arch.first->getName(); }); OS << ")"; } diff --git a/clang/test/AST/ast-print-openacc-compute-construct.cpp b/clang/test/AST/ast-print-openacc-compute-construct.cpp index cdd9ab3377d0..19965e749141 100644 --- a/clang/test/AST/ast-print-openacc-compute-construct.cpp +++ b/clang/test/AST/ast-print-openacc-compute-construct.cpp @@ -111,23 +111,23 @@ void foo() { bool SomeB; struct SomeStruct{} SomeStructImpl; -//#pragma acc parallel dtype(SomeB) +//CHECK: #pragma acc parallel dtype(SomeB) #pragma acc parallel dtype(SomeB) while(true); -//#pragma acc parallel device_type(SomeStruct) +//CHECK: #pragma acc parallel device_type(SomeStruct) #pragma acc parallel device_type(SomeStruct) while(true); -//#pragma acc parallel device_type(int) +//CHECK: #pragma acc parallel device_type(int) #pragma acc parallel device_type(int) while(true); -//#pragma acc parallel dtype(bool) +//CHECK: #pragma acc parallel dtype(bool) #pragma acc parallel dtype(bool) while(true); -//#pragma acc parallel device_type (SomeStructImpl) +//CHECK: #pragma acc parallel device_type(SomeStructImpl) #pragma acc parallel device_type (SomeStructImpl) while(true); } -- GitLab From e60b83a645685f22375af9bca5af6624b3a805d0 Mon Sep 17 00:00:00 2001 From: Youngsuk Kim Date: Tue, 14 May 2024 08:49:24 -0500 Subject: [PATCH 232/578] [libclc] Clarify condition expression (NFC) Closes #91188 --- libclc/generic/lib/math/log_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libclc/generic/lib/math/log_base.h b/libclc/generic/lib/math/log_base.h index 2558f016f60b..4e20329f641b 100644 --- a/libclc/generic/lib/math/log_base.h +++ b/libclc/generic/lib/math/log_base.h @@ -209,7 +209,7 @@ log(double x) const double log_thresh1 = 0x1.e0faap-1; const double log_thresh2 = 0x1.1082cp+0; - int is_near = x >= log_thresh1 & x <= log_thresh2; + bool is_near = x >= log_thresh1 && x <= log_thresh2; // Near 1 code double r = x - 1.0; -- GitLab From d422e90fcbdddd68749918ddd86c94188807efce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= Date: Tue, 14 May 2024 15:54:05 +0200 Subject: [PATCH 233/578] [GlobalIsel][AArch64] fix out of range access in regbankselect (#92072) Fixes https://github.com/llvm/llvm-project/issues/92062 --- .../AArch64/GISel/AArch64RegisterBankInfo.cpp | 5 ++++- llvm/test/CodeGen/AArch64/pr92062.ll | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AArch64/pr92062.ll diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp index 44ba9f0429e6..7785e020eaaf 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp @@ -600,8 +600,11 @@ bool AArch64RegisterBankInfo::isLoadFromFPType(const MachineInstr &MI) const { EltTy = GV->getValueType(); // Look at the first element of the struct to determine the type we are // loading - while (StructType *StructEltTy = dyn_cast(EltTy)) + while (StructType *StructEltTy = dyn_cast(EltTy)) { + if (StructEltTy->getNumElements() == 0) + break; EltTy = StructEltTy->getTypeAtIndex(0U); + } // Look at the first element of the array to determine its type if (isa(EltTy)) EltTy = EltTy->getArrayElementType(); diff --git a/llvm/test/CodeGen/AArch64/pr92062.ll b/llvm/test/CodeGen/AArch64/pr92062.ll new file mode 100644 index 000000000000..6111ee0fbe18 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/pr92062.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=aarch64 -O0 -global-isel %s -o - 2>&1 | FileCheck %s + +target triple = "arm64" + +@p = external global { {}, { ptr } } + +define void @foo() { +; CHECK-LABEL: foo: +; CHECK: // %bb.0: // %bb +; CHECK-NEXT: adrp x8, :got:p +; CHECK-NEXT: ldr x8, [x8, :got_lo12:p] +; CHECK-NEXT: ldr x8, [x8] +; CHECK-NEXT: mov x9, xzr +; CHECK-NEXT: str x8, [x9] +; CHECK-NEXT: ret +bb: + %i1 = load ptr, ptr @p, align 8 + store ptr %i1, ptr null, align 8 + ret void +} -- GitLab From 041baf2f60ac3e107399641aea04c77019e7eab8 Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Tue, 14 May 2024 14:59:01 +0100 Subject: [PATCH 234/578] [mlir][ArmSME] Use liveness information in the tile allocator (#90448) This patch rewrites the ArmSME tile allocator to use liveness information to make better tile allocation decisions and improve the correctness of the ArmSME dialect. This algorithm used here is a linear scan over live ranges, where live ranges are assigned to tiles as they appear in the program (chronologically). Live ranges release their assigned tile ID when the current program point is passed their end. This is a greedy algorithm (which is mainly to keep the implementation relatively straightforward), and because it seems to be sufficient for most kernels (e.g. matmuls) that use ArmSME. The general steps of this are roughly from https://link.springer.com/content/pdf/10.1007/3-540-45937-5_17.pdf, though there have been a few simplifications and assumptions made for our use case. Hopefully, the only changes needed for a user of the ArmSME dialect is that: - `-allocate-arm-sme-tiles` will no longer be a standalone pass - `-test-arm-sme-tile-allocation` is only for unit tests - `-convert-arm-sme-to-llvm` must happen after `-convert-scf-to-cf` - SME tile allocation is now part of the LLVM conversion By integrating this into the `ArmSME -> LLVM` conversion we can allow high-level (value-based) ArmSME operations to be side-effect-free, as we can guarantee nothing will rearrange ArmSME operations before we emit intrinsics (which could invalidate the tile allocation). The hope is for ArmSME operations to have no hidden state/side effects and allow easily lowering dialects such as `vector` and `arith` to SME, without making assumptions about how the input IR looks, as the semantics of the operations will be the same. That is no (new) side effects and the IR follows the rules of SSA (a value will never change). The aim is correctness, so we have a base for working on optimizations. --- .../Conversion/ArmSMEToLLVM/ArmSMEToLLVM.h | 4 +- mlir/include/mlir/Conversion/Passes.td | 7 +- mlir/include/mlir/Dialect/ArmSME/IR/ArmSME.h | 6 +- .../Dialect/ArmSME/IR/ArmSMEOpInterfaces.h | 27 + .../mlir/Dialect/ArmSME/IR/ArmSMEOps.td | 141 ++-- .../mlir/Dialect/ArmSME/Transforms/Passes.h | 3 - .../mlir/Dialect/ArmSME/Transforms/Passes.td | 22 +- .../Dialect/ArmSME/Transforms/Transforms.h | 9 + .../include/mlir/Dialect/ArmSME/Utils/Utils.h | 32 + .../Conversion/ArmSMEToLLVM/ArmSMEToLLVM.cpp | 125 +-- .../Conversion/ArmSMEToSCF/ArmSMEToSCF.cpp | 29 +- mlir/lib/Dialect/ArmSME/IR/ArmSME.cpp | 6 + mlir/lib/Dialect/ArmSME/IR/Utils.cpp | 53 ++ .../ArmSME/Transforms/TileAllocation.cpp | 791 ++++++++++++++---- .../ArmSMEToLLVM/arm-sme-to-llvm.mlir | 3 +- .../ArmSMEToLLVM/tile-spills-and-fills.mlir | 17 +- .../Conversion/ArmSMEToLLVM/unsupported.mlir | 2 +- .../Dialect/ArmSME/basic-tile-allocation.mlir | 2 +- mlir/test/Dialect/ArmSME/canonicalize.mlir | 14 +- mlir/test/Dialect/ArmSME/cse.mlir | 30 - mlir/test/Dialect/ArmSME/roundtrip.mlir | 9 + .../ArmSME/tile-allocation-copies.mlir | 159 ++++ .../ArmSME/tile-allocation-invalid.mlir | 14 +- .../ArmSME/tile-allocation-liveness.mlir | 381 +++++++-- ...location-spills-with-mixed-tile-types.mlir | 38 + mlir/test/Dialect/ArmSME/tile-zero-masks.mlir | 2 +- .../Linalg/CPU/ArmSME/use-too-many-tiles.mlir | 7 +- .../ArmSME/Emulated/test-setArmSVLBits.mlir | 3 +- mlir/test/lib/Dialect/ArmSME/CMakeLists.txt | 1 + .../lib/Dialect/ArmSME/TestLowerToArmSME.cpp | 19 +- 30 files changed, 1470 insertions(+), 486 deletions(-) create mode 100644 mlir/include/mlir/Dialect/ArmSME/IR/ArmSMEOpInterfaces.h delete mode 100644 mlir/test/Dialect/ArmSME/cse.mlir create mode 100644 mlir/test/Dialect/ArmSME/tile-allocation-copies.mlir create mode 100644 mlir/test/Dialect/ArmSME/tile-allocation-spills-with-mixed-tile-types.mlir diff --git a/mlir/include/mlir/Conversion/ArmSMEToLLVM/ArmSMEToLLVM.h b/mlir/include/mlir/Conversion/ArmSMEToLLVM/ArmSMEToLLVM.h index eab871ab4999..403f811a2569 100644 --- a/mlir/include/mlir/Conversion/ArmSMEToLLVM/ArmSMEToLLVM.h +++ b/mlir/include/mlir/Conversion/ArmSMEToLLVM/ArmSMEToLLVM.h @@ -12,6 +12,7 @@ #include #include "mlir/Dialect/ArmSME/Transforms/Passes.h" +#include "mlir/Interfaces/FunctionInterfaces.h" namespace mlir { class Pass; @@ -21,7 +22,8 @@ class RewritePatternSet; #include "mlir/Conversion/Passes.h.inc" /// Create a pass to convert from the ArmSME dialect to LLVM intrinsics. -std::unique_ptr createConvertArmSMEToLLVMPass(); +std::unique_ptr +createConvertArmSMEToLLVMPass(bool dumpTileLiveRanges = false); /// Configure target to convert from the ArmSME dialect to LLVM intrinsics. void configureArmSMEToLLVMConversionLegality(ConversionTarget &target); diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td index d094ee3b36ab..e6d678dc1b12 100644 --- a/mlir/include/mlir/Conversion/Passes.td +++ b/mlir/include/mlir/Conversion/Passes.td @@ -1285,7 +1285,7 @@ def ConvertArmSMEToSCF : Pass<"convert-arm-sme-to-scf"> { // ArmSMEToLLVM //===----------------------------------------------------------------------===// -def ConvertArmSMEToLLVM : Pass<"convert-arm-sme-to-llvm"> { +def ConvertArmSMEToLLVM : InterfacePass<"convert-arm-sme-to-llvm", "FunctionOpInterface"> { let summary = "Lower the operations from the ArmSME dialect into the LLVM " "dialect"; let constructor = "mlir::createConvertArmSMEToLLVMPass()"; @@ -1293,6 +1293,11 @@ def ConvertArmSMEToLLVM : Pass<"convert-arm-sme-to-llvm"> { "arm_sme::ArmSMEDialect", "LLVM::LLVMDialect" ]; + let options = [ + Option<"dumpTileLiveRanges", "dump-tile-live-ranges", + "bool", /*default=*/"false", + "Dump the live ranges of SME tiles (for debugging)"> + ]; } //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Dialect/ArmSME/IR/ArmSME.h b/mlir/include/mlir/Dialect/ArmSME/IR/ArmSME.h index c507cea5357a..dac54712c7f4 100644 --- a/mlir/include/mlir/Dialect/ArmSME/IR/ArmSME.h +++ b/mlir/include/mlir/Dialect/ArmSME/IR/ArmSME.h @@ -15,6 +15,7 @@ #include "mlir/Bytecode/BytecodeOpInterface.h" #include "mlir/Dialect/ArmSME/IR/ArmSMEEnums.h" +#include "mlir/Dialect/ArmSME/IR/ArmSMEOpInterfaces.h" #include "mlir/Dialect/ArmSME/Utils/Utils.h" #include "mlir/Dialect/LLVMIR/LLVMTypes.h" #include "mlir/Dialect/SCF/IR/SCF.h" @@ -24,11 +25,6 @@ #include "mlir/IR/OpDefinition.h" #include "mlir/Interfaces/SideEffectInterfaces.h" -namespace mlir::arm_sme { -static constexpr unsigned kInMemoryTileIdBase = 16; -#include "mlir/Dialect/ArmSME/IR/ArmSMEOpInterfaces.h.inc" -} // namespace mlir::arm_sme - #define GET_ATTRDEF_CLASSES #include "mlir/Dialect/ArmSME/IR/ArmSMEAttrDefs.h.inc" diff --git a/mlir/include/mlir/Dialect/ArmSME/IR/ArmSMEOpInterfaces.h b/mlir/include/mlir/Dialect/ArmSME/IR/ArmSMEOpInterfaces.h new file mode 100644 index 000000000000..9153fbb57ea8 --- /dev/null +++ b/mlir/include/mlir/Dialect/ArmSME/IR/ArmSMEOpInterfaces.h @@ -0,0 +1,27 @@ +//===- ArmSMEOpInterfaces.h - Arm SME Dialect OpInterfaces ------*- 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 MLIR_DIALECT_ARMSME_OPINTERFACES_H +#define MLIR_DIALECT_ARMSME_OPINTERFACES_H + +#include "mlir/Dialect/Vector/IR/VectorOps.h" + +namespace mlir::arm_sme { + +namespace detail { +LogicalResult verifyArmSMETileOpInterface(Operation *); +} + +// The first in-memory SME tile ID. This is set to 16 as that is the first tile +// ID larger than any virtual tile ID supported by the SME ISA. +static constexpr unsigned kInMemoryTileIdBase = 16; + +#include "mlir/Dialect/ArmSME/IR/ArmSMEOpInterfaces.h.inc" +} // namespace mlir::arm_sme + +#endif // MLIR_DIALECT_ARMSME_OPINTERFACES_H diff --git a/mlir/include/mlir/Dialect/ArmSME/IR/ArmSMEOps.td b/mlir/include/mlir/Dialect/ArmSME/IR/ArmSMEOps.td index 239c4beab10d..9178655f010c 100644 --- a/mlir/include/mlir/Dialect/ArmSME/IR/ArmSMEOps.td +++ b/mlir/include/mlir/Dialect/ArmSME/IR/ArmSMEOps.td @@ -39,10 +39,10 @@ def ArmSMETileType : I32EnumAttr<"ArmSMETileType", "Arm SME tile type", def ArmSMETileOpInterface : OpInterface<"ArmSMETileOpInterface"> { let description = [{ - An interface for operations that use or allocate Arm SME tiles. These - operations need to be assigned a tile ID, an i32 attribute, which specifies - which virtual tile within the ZA storage to use. The number of tiles - available depends on the type of the tile. This is summarized below: + An interface for operations that use Arm SME tiles. These operations need to + be assigned a tile ID, an i32 attribute, which specifies which virtual tile + within the ZA storage to use. The number of tiles available depends on the + type of the tile. This is summarized below: | Tile Vector Types | Possible Tile IDs | |-------------------------------------------------------------------------|---------------------| @@ -51,10 +51,6 @@ def ArmSMETileOpInterface : OpInterface<"ArmSMETileOpInterface"> { | `vector<[4]x[4]xi32>` or `vector<[4]x[4]xf32>` | 0 to 3 (inclusive) | | `vector<[2]x[2]xi64>` or `vector<[2]x[2]xf64>` | 0 to 7 (inclusive) | | `vector<[1]x[1]xi128>` | 0 to 15 (inclusive) | - - Operations that allocate a new tile (such as arm_sme.get_tile), are used as - the roots for tile allocation, with all operations that (transitively) - depend on a root being assigned the same tile ID. }]; let methods = [ InterfaceMethod< @@ -84,20 +80,6 @@ def ArmSMETileOpInterface : OpInterface<"ArmSMETileOpInterface"> { return op->getAttrOfType("tile_id"); }] >, - InterfaceMethod< - [{ - The type of tile this operation allocates. Returns none (std::nullopt) - if this operation does not allocate a tile. - }], - /*returnType=*/"std::optional<::mlir::arm_sme::ArmSMETileType>", - /*methodName=*/"getAllocatedTileType", - /*arguments=*/(ins), - /*methodBody=*/[{}], - /*defaultImpl=*/ [{ - // This operation does not allocate a tile. - return std::nullopt; - }] - >, InterfaceMethod< "Returns the VectorType of the tile used by this operation.", /*returnType=*/"VectorType", @@ -106,30 +88,13 @@ def ArmSMETileOpInterface : OpInterface<"ArmSMETileOpInterface"> { ]; let extraSharedClassDeclaration = [{ - // A helper to create a new operation and propagate this operations tile ID. - template - T createOpAndForwardTileId(::mlir::RewriterBase& rewriter, ::mlir::Location loc, Args &&...args) { - auto op = rewriter.create(loc, std::forward(args)...); - if (auto tileOp = ::llvm::dyn_cast(op.getOperation())) - tileOp.setTileId($_op.getTileId()); - return op; - } - - // A helper to replace this operation and forward its tile ID (if present). - template - T replaceWithAndForwardTileId(::mlir::RewriterBase& rewriter, Args &&...args) { - auto newOp = createOpAndForwardTileId(rewriter, $_op.getLoc(), std::forward(args)...); - rewriter.replaceOp($_op, newOp); - return newOp; - } - bool isInMemoryTile() { auto tileId = getTileId(); return tileId && tileId.getInt() >= kInMemoryTileIdBase; } }]; - let verify = [{ return ::mlir::arm_sme::verifyOperationHasValidTileId($_op); }]; + let verify = [{ return detail::verifyArmSMETileOpInterface($_op); }]; } //===----------------------------------------------------------------------===// @@ -255,30 +220,30 @@ def ArmSME_TypeSizeAttr : EnumAttr traits = []> : Op {} -def GetTileOp : ArmSME_Op<"get_tile", [ArmSMETileOpInterface]> { - let summary = "Returns a SME virtual tile"; +def GetTileOp : ArmSME_Op<"get_tile", [ArmSMETileOpInterface, Pure]> { + let summary = "Creates an undefined value of SME virtual tile type"; let description = [{ - Allocates a new SME "virtual tile" within a function. The contents of the - tile returned from this operation are undefined. + Creates a new SME "virtual tile" value within a function. The contents of + the tile returned from this operation are undefined. Example 1: ```mlir - // Allocate an 8-bit element "virtual tile" + // Create an 8-bit element "virtual tile" value: %za0_b = arm_sme.get_tile: vector<[16]x[16]xi8> ``` Example 2: ```mlir - // Allocate two 16-bit element "virtual tiles" + // Create two 16-bit element "virtual tiles" values: %za0_h = arm_sme.get_tile : vector<[8]x[8]xi16> %za1_h = arm_sme.get_tile : vector<[8]x[8]xi16> ``` Example 3: ```mlir - // Allocate an 128-bit element "virtual tile" + // Create an 128-bit element "virtual tile" value: %za0_q = arm_sme.get_tile : vector<[1]x[1]xi128> ``` }]; @@ -290,37 +255,15 @@ def GetTileOp : ArmSME_Op<"get_tile", [ArmSMETileOpInterface]> { VectorType getTileType() { return ::llvm::cast(getTile().getType()); } - - std::optional getAllocatedTileType() { - return arm_sme::getSMETileType(getTileType()); - } - }]; -} - -def MaterializeSSATileOp : ArmSME_Op<"materialize_ssa_tile", [Pure]> { - let summary = "SME tile placeholder"; - let description = [{ - A placeholder to preserve dataflow while lowering to SME intrinsics (which - do not take or return SME virtual tile values). This operation is intended - to be DCE'd once all ArmSME operations have been lowered. - - This operation is not intended to be used outside of the ArmSME -> LLVM - conversion. }]; - let results = (outs SMETile:$tile); - let assemblyFormat = "attr-dict `:` type($tile)"; } -// -// Tile reset. -// - -def ZeroOp : ArmSME_Op<"zero", [ArmSMETileOpInterface]> { - let summary = "Initialize the two-dimensional ZA array with 0s"; +def ZeroOp : ArmSME_Op<"zero", [ArmSMETileOpInterface, Pure]> { + let summary = "Creates a zero-initialized value of SME virtual tile type"; let results = (outs SMETile:$res); let description = [{ - Initialise ZA with 0. This operation is convenient wrapper for the SME - `zero` intrinsic and instruction. + Creates a new SME "virtual tile" value within a function. The contents of + the tile returned from this operation are zero-initialized. Example 1: Zero an 8-bit element ZA tile. @@ -338,9 +281,6 @@ def ZeroOp : ArmSME_Op<"zero", [ArmSMETileOpInterface]> { VectorType getVectorType() { return ::llvm::cast(getRes().getType()); } - std::optional getAllocatedTileType() { - return arm_sme::getSMETileType(getVectorType()); - } VectorType getTileType() { return getVectorType(); } @@ -348,6 +288,32 @@ def ZeroOp : ArmSME_Op<"zero", [ArmSMETileOpInterface]> { let assemblyFormat = "attr-dict `:` type($res)"; } +def CopyTileOp : ArmSME_Op<"copy_tile", [ + Pure, + ArmSMETileOpInterface, + AllTypesMatch<["tile", "result"]> +]> { + let summary = "Copies an SME tile value"; + let arguments = (ins SMETile:$tile); + let results = (outs SMETile:$result); + let description = [{ + Copies an SME "virtual tile" value to a new SSA value. This operation is + primarily intended to be used to normalize the IR prior to tile allocation. + + Example: + + ```mlir + %copy = arm_sme.copy_tile %tile : vector<[4]x[4]xf32> + ``` + }]; + let extraClassDeclaration = [{ + VectorType getTileType() { + return ::llvm::cast(getResult().getType()); + } + }]; + let assemblyFormat = "$tile attr-dict `:` type($result)"; +} + def TileLoadOp : ArmSME_Op<"tile_load", [ ArmSMETileOpInterface, AttrSizedOperandSegments, @@ -417,9 +383,6 @@ def TileLoadOp : ArmSME_Op<"tile_load", [ VectorType getVectorType() { return ::llvm::cast(getResult().getType()); } - std::optional getAllocatedTileType() { - return arm_sme::getSMETileType(getVectorType()); - } VectorType getTileType() { return getVectorType(); } @@ -545,7 +508,7 @@ def LoadTileSliceOp : ArmSME_Op<"load_tile_slice", [ ``` }]; let arguments = (ins - Arg:$base, SVEPredicate:$mask, + Arg:$base, SVEPredicate:$mask, SMETile:$tile, Variadic:$indices, Index:$tile_slice_index, ArmSME_TileSliceLayoutAttr:$layout ); @@ -630,7 +593,7 @@ def StoreTileSliceOp : ArmSME_Op<"store_tile_slice", [ } def MoveVectorToTileSliceOp : ArmSME_Op<"move_vector_to_tile_slice", [ - ArmSMETileOpInterface, + ArmSMETileOpInterface, Pure, AllTypesMatch<["tile", "result"]>, TypesMatchWith< "type of 'vector' matches type of 'tile' slice", @@ -679,7 +642,7 @@ def MoveVectorToTileSliceOp : ArmSME_Op<"move_vector_to_tile_slice", [ } def MoveTileSliceToVectorOp : ArmSME_Op<"move_tile_slice_to_vector", [ - ArmSMETileOpInterface, + ArmSMETileOpInterface, Pure, TypesMatchWith< "type of 'result' matches type of 'tile' slice", "tile", "result", @@ -736,6 +699,7 @@ class OuterProductResultTileTypeConstraint : def OuterProductOp : ArmSME_Op<"outerproduct", [ + Pure, ArmSMETileOpInterface, AttrSizedOperandSegments, AllTypesMatch<["lhs", "rhs"]>, @@ -802,12 +766,6 @@ let arguments = (ins VectorType getLhsType() { return llvm::cast(getLhs().getType()); } VectorType getRhsType() { return llvm::cast(getRhs().getType()); } VectorType getResultType() { return llvm::cast(getResult().getType()); } - std::optional getAllocatedTileType() { - // The outerproduct op allocates a new tile if no accumulator is passed. - if (!getAcc()) - return arm_sme::getSMETileType(getResultType()); - return std::nullopt; - } VectorType getTileType() { return getResultType(); } @@ -819,6 +777,7 @@ class OuterProductWideningBase allowedResultVectorTypes, int numOuterProducts> : ArmSME_Op, @@ -857,12 +816,6 @@ class OuterProductWideningBase(getLhs().getType()); } VectorType getRhsType() { return llvm::cast(getRhs().getType()); } VectorType getResultType() { return llvm::cast(getResult().getType()); } - std::optional getAllocatedTileType() { - // The outerproduct op allocates a new tile if no accumulator is passed. - if (!getAcc()) - return arm_sme::getSMETileType(getResultType()); - return std::nullopt; - } VectorType getTileType() { return getResultType(); } diff --git a/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.h b/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.h index c2f1b1f1b874..156744ba57e7 100644 --- a/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.h +++ b/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.h @@ -29,9 +29,6 @@ std::unique_ptr createEnableArmStreamingPass( const ArmStreamingMode = ArmStreamingMode::Streaming, const ArmZaMode = ArmZaMode::Disabled, bool onlyIfRequiredByOps = false); -/// Pass that allocates tile IDs to ArmSME operations. -std::unique_ptr createTileAllocationPass(); - /// Pass that fuses 'arm_sme.outerproduct' ops into 2-way or 4-way widening /// variants. std::unique_ptr createOuterProductFusionPass(); diff --git a/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.td b/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.td index 7959d291e892..869a031d6cae 100644 --- a/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.td +++ b/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.td @@ -124,17 +124,25 @@ def EnableArmStreaming let dependentDialects = ["func::FuncDialect"]; } -def TileAllocation - : Pass<"allocate-arm-sme-tiles", "mlir::func::FuncOp"> { - let summary = "Allocate SME tiles"; +def TestTileAllocation + : Pass<"test-arm-sme-tile-allocation", "mlir::func::FuncOp"> { + let summary = "Tests SME 'virtual tile' allocation"; let description = [{ This pass does tile allocation for SME "virtual tiles". It is run at the 'func.func' op level, and assigns tile IDs (via an attribute) to all ops - that implement the `ArmSMETileOpInterface`. An error will be emitted when - there's no tiles left. + that implement the `ArmSMETileOpInterface`. Note: This pass is only intended + to be used for testing, tile allocation is done as part of the ArmSME to + LLVM conversion (`convert-arm-sme-to-llvm`). }]; - let constructor = "mlir::arm_sme::createTileAllocationPass()"; - let dependentDialects = ["func::FuncDialect"]; + let options = [ + Option<"dumpTileLiveRanges", "dump-tile-live-ranges", + "bool", /*default=*/"false", + "Dump the live ranges of SME tiles (for debugging)">, + Option<"preprocessOnly", "preprocess-only", "bool", /*default=*/"false", + "Only preprocess IR so it is ready for tile allocation " + "(but do not allocate any tiles)"> + ]; + let dependentDialects = ["func::FuncDialect", "arm_sme::ArmSMEDialect"]; } def OuterProductFusion diff --git a/mlir/include/mlir/Dialect/ArmSME/Transforms/Transforms.h b/mlir/include/mlir/Dialect/ArmSME/Transforms/Transforms.h index e00c7503e699..a25b844f01ea 100644 --- a/mlir/include/mlir/Dialect/ArmSME/Transforms/Transforms.h +++ b/mlir/include/mlir/Dialect/ArmSME/Transforms/Transforms.h @@ -9,6 +9,8 @@ #ifndef MLIR_DIALECT_ARMSME_TRANSFORMS_H #define MLIR_DIALECT_ARMSME_TRANSFORMS_H +#include "mlir/Interfaces/FunctionInterfaces.h" + namespace mlir { class LLVMConversionTarget; @@ -16,7 +18,14 @@ class LLVMTypeConverter; class RewritePatternSet; namespace arm_sme { + void populateOuterProductFusionPatterns(RewritePatternSet &patterns); + +/// Allocate tile IDs to all ArmSME operations in a function. Requires the +/// function to be lowered to control flow (cf dialect). +LogicalResult allocateSMETiles(FunctionOpInterface function, + bool dumpRanges = false); + } // namespace arm_sme } // namespace mlir diff --git a/mlir/include/mlir/Dialect/ArmSME/Utils/Utils.h b/mlir/include/mlir/Dialect/ArmSME/Utils/Utils.h index 027ad8954f92..1f40eb6fc693 100644 --- a/mlir/include/mlir/Dialect/ArmSME/Utils/Utils.h +++ b/mlir/include/mlir/Dialect/ArmSME/Utils/Utils.h @@ -16,8 +16,10 @@ #define MLIR_DIALECT_ARMSME_UTILS_UTILS_H_ #include "mlir/Dialect/ArmSME/IR/ArmSMEEnums.h" +#include "mlir/Dialect/ArmSME/IR/ArmSMEOpInterfaces.h" #include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/IR/BuiltinTypes.h" +#include "mlir/Interfaces/FunctionInterfaces.h" #include namespace mlir { @@ -42,6 +44,11 @@ bool isValidSMETileElementType(Type type); /// otherwise. bool isValidSMETileVectorType(VectorType vType); +inline bool isValidSMETileVectorType(Type type) { + auto vType = dyn_cast(type); + return vType && isValidSMETileVectorType(vType); +} + /// Returns the type of SME tile this vector type corresponds to, or none if the /// vector type does not fit within an SME tile. std::optional getSMETileType(VectorType); @@ -63,6 +70,31 @@ bool isMultipleOfSMETileVectorType(VectorType vType); /// Creates a vector type for the SME tile of `elementType`. VectorType getSMETileTypeForElement(Type elementType); +/// Erase trivially dead tile ops from a function. +void eraseTriviallyDeadTileOps(IRRewriter &rewriter, + FunctionOpInterface function); + +/// Returns true if `tileOp` is trivially cloneable. A tile operation is +/// trivially cloneable if: +/// +/// 1. It has no operands (and only a single tile result) +/// 2. It is 'Pure' +/// +/// This ensures that the cloned operation will not share any dependencies with +/// the original operation (which could also need to be considered), and that +/// inserting the cloned operation at a different point in the program won't +/// change the semantics of the program (as it has no side effects). +bool isTriviallyCloneableTileOp(arm_sme::ArmSMETileOpInterface tileOp); + +/// Returns true if `tileOp` produces a tile result. +bool hasTileResult(arm_sme::ArmSMETileOpInterface tileOp); + +/// Returns the tile `OpOperand` for this `tileOp` (or null). +OpOperand *getTileOpOperand(arm_sme::ArmSMETileOpInterface tileOp); + +/// Returns true `typeA` is >= (in terms of bytes) than `typeB`. +bool isTileTypeGreaterOrEqual(ArmSMETileType typeA, ArmSMETileType typeB); + } // namespace mlir::arm_sme #endif // MLIR_DIALECT_ARMSME_UTILS_UTILS_H_ diff --git a/mlir/lib/Conversion/ArmSMEToLLVM/ArmSMEToLLVM.cpp b/mlir/lib/Conversion/ArmSMEToLLVM/ArmSMEToLLVM.cpp index 1ba1b88fc123..3dbc8e9916df 100644 --- a/mlir/lib/Conversion/ArmSMEToLLVM/ArmSMEToLLVM.cpp +++ b/mlir/lib/Conversion/ArmSMEToLLVM/ArmSMEToLLVM.cpp @@ -16,6 +16,7 @@ #include "mlir/Conversion/LLVMCommon/Pattern.h" #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/ArmSME/IR/ArmSME.h" +#include "mlir/Dialect/ArmSME/Transforms/Transforms.h" #include "mlir/Dialect/ArmSME/Utils/Utils.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" @@ -245,6 +246,10 @@ struct ConvertArmSMESpillsAndFillsToLLVM : public ConvertToLLVMPattern { if (!tileOp.isInMemoryTile()) return failure(); + tileOp->emitWarning( + "failed to allocate SME virtual tile to operation, all tile " + "operations will go through memory, expect degraded performance"); + // Step 1. Create an alloca for the tile at the top of the function (if one // does not already exist). auto loc = tileOp.getLoc(); @@ -391,20 +396,6 @@ addArmSMEConversionPatterns(RewritePatternSet &patterns, (addArmSMEConversionPattern(patterns, typeConverter), ...); } -struct GetTileConversion - : public ConvertArmSMEOpToLLVMPattern { - using ConvertArmSMEOpToLLVMPattern::ConvertArmSMEOpToLLVMPattern; - - LogicalResult - matchAndRewrite(arm_sme::GetTileOp getTile, OpAdaptor, - ConversionPatternRewriter &rewriter) const override { - rewriter.replaceOpWithNewOp( - getTile, getTile.getTileType()); - return success(); - } -}; - /// Lower 'arm_sme.zero' to SME intrinsics. /// /// BEFORE: @@ -415,11 +406,11 @@ struct GetTileConversion /// AFTER: /// ```mlir /// "arm_sme.intr.zero"() <{tile_mask = 17 : i32}> : () -> () -/// %v = arm_sme.materialize_ssa_tile : vector<[4]x[4]xi32> +/// %v = arm_sme.get_tile : vector<[4]x[4]xi32> /// ``` /// -/// The 'arm_sme.materialize_ssa_tile' (which models the return) will fold away -/// once all ArmSME ops have been converted to LLVM intrinsics. +/// The 'arm_sme.get_tile' (which models the return) will fold away once all +/// ArmSME ops have been converted to LLVM intrinsics. struct ZeroOpConversion : public ConvertArmSMEOpToLLVMPattern { using ConvertArmSMEOpToLLVMPattern::ConvertArmSMEOpToLLVMPattern; @@ -436,7 +427,8 @@ struct ZeroOpConversion : public ConvertArmSMEOpToLLVMPattern { // The base mask is just the mask to zero the first tile (of a size). // These masks are derived from: // https://developer.arm.com/documentation/ddi0602/2022-06/SME-Instructions/ZERO--Zero-a-list-of-64-bit-element-ZA-tiles- - arm_sme::ArmSMETileType tileType = *zero.getAllocatedTileType(); + arm_sme::ArmSMETileType tileType = + *arm_sme::getSMETileType(zero.getTileType()); auto baseMaskForSize = [&] { switch (tileType) { case arm_sme::ArmSMETileType::ZAB: @@ -488,8 +480,7 @@ struct ZeroOpConversion : public ConvertArmSMEOpToLLVMPattern { loc, rewriter.getI32IntegerAttr(zeroMask)); // Create a placeholder op to preserve dataflow. - rewriter.replaceOpWithNewOp( - zero, zero.getVectorType()); + rewriter.replaceOpWithNewOp(zero, zero.getVectorType()); return success(); } @@ -746,10 +737,12 @@ struct OuterProductOpConversion auto loc = outerProductOp.getLoc(); Value acc = outerProductOp.getAcc(); - if (!acc) + if (!acc) { // Initalize accumulator with zero. - acc = outerProductOp.createOpAndForwardTileId( - rewriter, loc, resultVectorType); + auto zero = rewriter.create(loc, resultVectorType); + zero.setTileId(tileId); + acc = zero; + } Value lhsMask = outerProductOp.getLhsMask(); Value rhsMask = outerProductOp.getRhsMask(); @@ -791,25 +784,27 @@ struct OuterProductWideningOpConversion if (!tileId) return failure(); + auto loc = op.getLoc(); Value acc = op.getAcc(); - if (!acc) + if (!acc) { // Initalize accumulator with zero. - acc = op.template createOpAndForwardTileId( - rewriter, op.getLoc(), op.getResultType()); + auto zero = rewriter.create(loc, op.getResultType()); + zero.setTileId(tileId); + acc = zero; + } Value lhsMask = op.getLhsMask(); Value rhsMask = op.getRhsMask(); if (!lhsMask || !rhsMask) { auto predTy = op.getLhsType().cloneWith({}, rewriter.getI1Type()); Value allActiveMask = rewriter.create( - op.getLoc(), DenseElementsAttr::get(predTy, true)); + loc, DenseElementsAttr::get(predTy, true)); lhsMask = allActiveMask; rhsMask = allActiveMask; } - rewriter.create(op.getLoc(), tileId, lhsMask, - rhsMask, adaptor.getLhs(), - adaptor.getRhs()); + rewriter.create( + loc, tileId, lhsMask, rhsMask, adaptor.getLhs(), adaptor.getRhs()); // The outerproduct intrinsics have no result, replace // 'arm_sme.outerproduct' with the input tile to preserve dataflow. @@ -865,15 +860,22 @@ namespace { struct ConvertArmSMEToLLVMPass : public impl::ConvertArmSMEToLLVMBase { + ConvertArmSMEToLLVMPass(bool dumpTileLiveRanges) { + this->dumpTileLiveRanges = dumpTileLiveRanges; + } void runOnOperation() override { + auto function = getOperation(); + + if (failed(arm_sme::allocateSMETiles(function, dumpTileLiveRanges))) + return signalPassFailure(); + LLVMConversionTarget target(getContext()); RewritePatternSet patterns(&getContext()); LLVMTypeConverter converter(&getContext()); configureArmSMEToLLVMConversionLegality(target); populateArmSMEToLLVMConversionPatterns(converter, patterns); - if (failed(applyPartialConversion(getOperation(), target, - std::move(patterns)))) + if (failed(applyPartialConversion(function, target, std::move(patterns)))) signalPassFailure(); } }; @@ -883,34 +885,38 @@ struct ConvertArmSMEToLLVMPass void mlir::configureArmSMEToLLVMConversionLegality(ConversionTarget &target) { target.addIllegalDialect(); target.addLegalOp< - arm_sme::MaterializeSSATileOp, arm_sme::aarch64_sme_zero, - arm_sme::aarch64_sme_str, arm_sme::aarch64_sme_ld1b_horiz, - arm_sme::aarch64_sme_ld1h_horiz, arm_sme::aarch64_sme_ld1w_horiz, - arm_sme::aarch64_sme_ld1d_horiz, arm_sme::aarch64_sme_ld1q_horiz, - arm_sme::aarch64_sme_st1b_horiz, arm_sme::aarch64_sme_st1h_horiz, - arm_sme::aarch64_sme_st1w_horiz, arm_sme::aarch64_sme_st1d_horiz, - arm_sme::aarch64_sme_st1q_horiz, arm_sme::aarch64_sme_ld1b_vert, - arm_sme::aarch64_sme_ld1h_vert, arm_sme::aarch64_sme_ld1w_vert, - arm_sme::aarch64_sme_ld1d_vert, arm_sme::aarch64_sme_ld1q_vert, - arm_sme::aarch64_sme_st1b_vert, arm_sme::aarch64_sme_st1h_vert, - arm_sme::aarch64_sme_st1w_vert, arm_sme::aarch64_sme_st1d_vert, - arm_sme::aarch64_sme_st1q_vert, arm_sme::aarch64_sme_read_horiz, - arm_sme::aarch64_sme_read_vert, arm_sme::aarch64_sme_write_horiz, - arm_sme::aarch64_sme_write_vert, arm_sme::aarch64_sme_mopa, - arm_sme::aarch64_sme_mopa_wide, arm_sme::aarch64_sme_mops_wide, - arm_sme::aarch64_sme_smopa_wide, arm_sme::aarch64_sme_smops_wide, - arm_sme::aarch64_sme_umopa_wide, arm_sme::aarch64_sme_umops_wide, - arm_sme::aarch64_sme_smopa_za32, arm_sme::aarch64_sme_smops_za32, - arm_sme::aarch64_sme_umopa_za32, arm_sme::aarch64_sme_umops_za32, - arm_sme::aarch64_sme_sumopa_wide, arm_sme::aarch64_sme_sumops_wide, - arm_sme::aarch64_sme_usmopa_wide, arm_sme::aarch64_sme_usmops_wide, - arm_sme::aarch64_sme_cntsb, arm_sme::aarch64_sme_cntsh, - arm_sme::aarch64_sme_cntsw, arm_sme::aarch64_sme_cntsd>(); + arm_sme::aarch64_sme_zero, arm_sme::aarch64_sme_str, + arm_sme::aarch64_sme_ld1b_horiz, arm_sme::aarch64_sme_ld1h_horiz, + arm_sme::aarch64_sme_ld1w_horiz, arm_sme::aarch64_sme_ld1d_horiz, + arm_sme::aarch64_sme_ld1q_horiz, arm_sme::aarch64_sme_st1b_horiz, + arm_sme::aarch64_sme_st1h_horiz, arm_sme::aarch64_sme_st1w_horiz, + arm_sme::aarch64_sme_st1d_horiz, arm_sme::aarch64_sme_st1q_horiz, + arm_sme::aarch64_sme_ld1b_vert, arm_sme::aarch64_sme_ld1h_vert, + arm_sme::aarch64_sme_ld1w_vert, arm_sme::aarch64_sme_ld1d_vert, + arm_sme::aarch64_sme_ld1q_vert, arm_sme::aarch64_sme_st1b_vert, + arm_sme::aarch64_sme_st1h_vert, arm_sme::aarch64_sme_st1w_vert, + arm_sme::aarch64_sme_st1d_vert, arm_sme::aarch64_sme_st1q_vert, + arm_sme::aarch64_sme_read_horiz, arm_sme::aarch64_sme_read_vert, + arm_sme::aarch64_sme_write_horiz, arm_sme::aarch64_sme_write_vert, + arm_sme::aarch64_sme_mopa, arm_sme::aarch64_sme_mopa_wide, + arm_sme::aarch64_sme_mops_wide, arm_sme::aarch64_sme_smopa_wide, + arm_sme::aarch64_sme_smops_wide, arm_sme::aarch64_sme_umopa_wide, + arm_sme::aarch64_sme_umops_wide, arm_sme::aarch64_sme_smopa_za32, + arm_sme::aarch64_sme_smops_za32, arm_sme::aarch64_sme_umopa_za32, + arm_sme::aarch64_sme_umops_za32, arm_sme::aarch64_sme_sumopa_wide, + arm_sme::aarch64_sme_sumops_wide, arm_sme::aarch64_sme_usmopa_wide, + arm_sme::aarch64_sme_usmops_wide, arm_sme::aarch64_sme_cntsb, + arm_sme::aarch64_sme_cntsh, arm_sme::aarch64_sme_cntsw, + arm_sme::aarch64_sme_cntsd>(); target.addLegalDialect(); - target.addLegalOp(); + // Pseudo operations. These cannot be code-generated but may exist in the + // input IR, or be generated during the conversion. They need to be eliminated + // before the final conversion to LLVM IR (and likely will be due to DCE). + target.addLegalOp(); } void mlir::populateArmSMEToLLVMConversionPatterns(LLVMTypeConverter &converter, @@ -955,9 +961,10 @@ void mlir::populateArmSMEToLLVMConversionPatterns(LLVMTypeConverter &converter, arm_sme::aarch64_sme_usmopa_wide>, OuterProductWideningOpConversion, - ZeroOpConversion, GetTileConversion>(patterns, converter); + ZeroOpConversion>(patterns, converter); } -std::unique_ptr mlir::createConvertArmSMEToLLVMPass() { - return std::make_unique(); +std::unique_ptr +mlir::createConvertArmSMEToLLVMPass(bool dumpTileLiveRanges) { + return std::make_unique(dumpTileLiveRanges); } diff --git a/mlir/lib/Conversion/ArmSMEToSCF/ArmSMEToSCF.cpp b/mlir/lib/Conversion/ArmSMEToSCF/ArmSMEToSCF.cpp index 16b61c282749..9f55932c33af 100644 --- a/mlir/lib/Conversion/ArmSMEToSCF/ArmSMEToSCF.cpp +++ b/mlir/lib/Conversion/ArmSMEToSCF/ArmSMEToSCF.cpp @@ -196,12 +196,9 @@ struct TileLoadOpConversion : public OpRewritePattern { // Initialize tile with zero to satisfy padding. Inactive cols will be // zeroed anyway since the loads use zeroing predication. For inactive // rows however, no load will occur so these need to be zeroed. - initTile = tileLoadOp.createOpAndForwardTileId( - rewriter, loc, tileType); + initTile = rewriter.create(loc, tileType); } else { - // Allocate a new SME tile. - initTile = tileLoadOp.createOpAndForwardTileId( - rewriter, loc, tileType); + initTile = rewriter.create(loc, tileType); } // Create a loop to load the active tile slices from memory. @@ -212,10 +209,9 @@ struct TileLoadOpConversion : public OpRewritePattern { Value currentTile) -> Value { // Create 'arm_sme.load_tile_slice' to load tile slice from memory // into tile. - return tileLoadOp.createOpAndForwardTileId( - rewriter, loc, tileType, tileLoadOp.getBase(), predicate, - currentTile, memrefIndices, tileSliceIndex, - tileLoadOp.getLayout()); + return rewriter.create( + loc, tileType, tileLoadOp.getBase(), predicate, currentTile, + memrefIndices, tileSliceIndex, tileLoadOp.getLayout()); }); if (failed(forOp)) @@ -292,9 +288,7 @@ struct TileLoadOpWithMaskAndPadNonZeroConversion auto numColsI32 = rewriter.create( loc, rewriter.getI32Type(), numCols); - // Allocate a new SME tile. - auto initTile = tileLoadOp.createOpAndForwardTileId( - rewriter, loc, tileType); + auto initTile = rewriter.create(loc, tileType); // Create a loop that loads each ZA tile slice from memory. auto step = rewriter.create(loc, 1); @@ -339,10 +333,9 @@ struct TileLoadOpWithMaskAndPadNonZeroConversion /*passthru=*/pad1DOp); // Create 'arm_sme.move_vector_to_tile_slice' to move slice into tile. - auto moveSlice = - tileLoadOp.createOpAndForwardTileId( - rewriter, loc, tileType, loadSlice->getResult(0), currentTile, - tileSliceIndex, tileLoadOp.getLayout()); + auto moveSlice = rewriter.create( + loc, tileType, loadSlice->getResult(0), currentTile, tileSliceIndex, + tileLoadOp.getLayout()); rewriter.create(loc, moveSlice.getResult()); rewriter.setInsertionPointAfter(forOp); @@ -386,8 +379,8 @@ struct TileStoreOpConversion : public OpRewritePattern { tileStoreOp.getIndices(), tileStoreOp.getMemRefType().getRank(), tileStoreOp.getMask(), [&](Value tileSliceIndex, ValueRange memrefIndices, Value predicate) { - tileStoreOp.replaceWithAndForwardTileId( - rewriter, tileStoreOp.getValueToStore(), tileSliceIndex, + rewriter.replaceOpWithNewOp( + tileStoreOp, tileStoreOp.getValueToStore(), tileSliceIndex, predicate, tileStoreOp.getBase(), memrefIndices, tileStoreOp.getLayout()); }); diff --git a/mlir/lib/Dialect/ArmSME/IR/ArmSME.cpp b/mlir/lib/Dialect/ArmSME/IR/ArmSME.cpp index 29fa9085a0a9..cb3a66584487 100644 --- a/mlir/lib/Dialect/ArmSME/IR/ArmSME.cpp +++ b/mlir/lib/Dialect/ArmSME/IR/ArmSME.cpp @@ -20,6 +20,12 @@ using namespace mlir; using namespace mlir::arm_sme; +namespace mlir::arm_sme::detail { +LogicalResult verifyArmSMETileOpInterface(Operation *op) { + return verifyOperationHasValidTileId(op); +} +} // namespace mlir::arm_sme::detail + //===----------------------------------------------------------------------===// // Tablegen Definitions //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/ArmSME/IR/Utils.cpp b/mlir/lib/Dialect/ArmSME/IR/Utils.cpp index 6a9e02218222..1f7305a5f814 100644 --- a/mlir/lib/Dialect/ArmSME/IR/Utils.cpp +++ b/mlir/lib/Dialect/ArmSME/IR/Utils.cpp @@ -116,4 +116,57 @@ VectorType getSMETileTypeForElement(Type elementType) { return VectorType::get({minNumElts, minNumElts}, elementType, {true, true}); } +void eraseTriviallyDeadTileOps(IRRewriter &rewriter, + FunctionOpInterface function) { + SmallVector worklist; + function->walk([&](Operation *op) { + auto armSMEOp = dyn_cast(op); + if (armSMEOp && isOpTriviallyDead(armSMEOp)) + worklist.push_back(armSMEOp); + }); + while (!worklist.empty()) { + Operation *op = worklist.pop_back_val(); + if (!isOpTriviallyDead(op)) + continue; + for (Value value : op->getOperands()) { + if (auto armSMEOp = value.getDefiningOp()) + worklist.push_back(armSMEOp); + } + rewriter.eraseOp(op); + } +} + +bool isTriviallyCloneableTileOp(arm_sme::ArmSMETileOpInterface tileOp) { + return tileOp && tileOp->getNumResults() == 1 && + tileOp->getNumOperands() == 0 && isPure(tileOp); +} + +bool hasTileResult(arm_sme::ArmSMETileOpInterface tileOp) { + for (Value result : tileOp->getResults()) { + if (arm_sme::isValidSMETileVectorType(result.getType())) + return true; + } + return false; +} + +OpOperand *getTileOpOperand(arm_sme::ArmSMETileOpInterface tileOp) { + if (!tileOp) + return nullptr; + auto isTileOperandType = [](OpOperand &operand) { + return arm_sme::isValidSMETileVectorType(operand.get().getType()); + }; + assert(llvm::count_if(tileOp->getOpOperands(), isTileOperandType) <= 1 && + "expected at most one tile operand"); + OpOperand *tileOperand = + llvm::find_if(tileOp->getOpOperands(), isTileOperandType); + if (tileOperand == tileOp->getOpOperands().end()) + return nullptr; + return tileOperand; +} + +bool isTileTypeGreaterOrEqual(ArmSMETileType typeA, ArmSMETileType typeB) { + // Note: This is <= due to how tile types are numbered in ArmSMEOps.td. + return static_cast(typeA) <= static_cast(typeB); +} + } // namespace mlir::arm_sme diff --git a/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp b/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp index 4acb2a8fb7b5..1e1e0e569124 100644 --- a/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp +++ b/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp @@ -6,12 +6,18 @@ // //===----------------------------------------------------------------------===// // -// This pass allocates SME tiles at the 'func.func' op level for ArmSME -// operations. It does this using a 16-bit tile mask that has a bit for each -// 128-bit element tile (ZA0.Q-ZA15.Q), the smallest ZA tile granule. +// This transform allocates SME tiles at the 'func.func' op level for ArmSME +// operations. It roughly implements a linear scan register allocator, similar +// to the one outlined in [1], but with simplifications and assumptions made for +// our use case. Note that this is a greedy allocator (so it may not always find +// the most optimal allocation of tiles). +// +// The allocator operates at the CF dialect level. It is the responsibility of +// users to ensure the IR has been lowered to CF before invoking the tile +// allocator. // // The 128-bit tiles overlap with other element tiles as follows (see section -// B2.3.2 of SME spec [1]): +// B2.3.2 of SME spec [2]): // // Tile Overlaps // --------------------------------------------------------------------------- @@ -32,39 +38,34 @@ // ZA6.D ZA6.Q, ZA14.Q // ZA7.D ZA7.Q, ZA15.Q // -// The tiles in use are tracked via a function attribute 'arm_sme.tiles_in_use' -// that is initalized during the first tile allocation within a function and -// updated on each subsequent allocation. -// -// [1] https://developer.arm.com/documentation/ddi0616/aa +// [1] "Linear Scan Register Allocation in the Context of SSA Form and Register +// Constraints" (Hanspeter Mössenböck and Michael Pfeiffer) +// https://link.springer.com/content/pdf/10.1007/3-540-45937-5_17.pdf +// [2] https://developer.arm.com/documentation/ddi0616/aa // //===----------------------------------------------------------------------===// +#include "mlir/Analysis/Liveness.h" #include "mlir/Dialect/ArmSME/IR/ArmSME.h" #include "mlir/Dialect/ArmSME/Transforms/Passes.h" +#include "mlir/Dialect/ArmSME/Transforms/Transforms.h" #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" #include "mlir/Dialect/Func/IR/FuncOps.h" -#include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "mlir/Transforms/RegionUtils.h" +#include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/TypeSwitch.h" +#include -#define DEBUG_TYPE "allocate-arm-sme-tiles" - -namespace mlir { -namespace arm_sme { -#define GEN_PASS_DEF_TILEALLOCATION +namespace mlir::arm_sme { +#define GEN_PASS_DEF_TESTTILEALLOCATION #include "mlir/Dialect/ArmSME/Transforms/Passes.h.inc" -} // namespace arm_sme -} // namespace mlir +} // namespace mlir::arm_sme using namespace mlir; using namespace mlir::arm_sme; namespace { -static constexpr StringLiteral kTilesInUseAttr("arm_sme.tiles_in_use"); -static constexpr StringLiteral - kNextInMemoryTileIdAttr("arm_sme.next_in_memory_tile_id"); - enum class TileMask : unsigned { // clang-format off kZA0B = 0xffff, // 1111 1111 1111 1111 @@ -137,172 +138,640 @@ static ArrayRef getMasks(ArmSMETileType type) { } } -/// Allocates and returns a tile ID. Returns an error if there are no tiles -/// left. -static FailureOr allocateTileId(ArmSMETileType tileType, - TileMask &tilesInUse) { - auto masks = getMasks(tileType); - for (auto [tileId, tileMask] : llvm::enumerate(masks)) { - if ((tilesInUse & tileMask) == TileMask::kNone) { - tilesInUse |= tileMask; - return tileId; +class TileAllocator { +public: + /// Allocates and returns a tile ID. Fails if there are no tiles left. + FailureOr allocateTileId(ArmSMETileType tileType) { + auto masks = getMasks(tileType); + for (auto [tileId, tileMask] : llvm::enumerate(masks)) { + if ((tilesInUse & tileMask) == TileMask::kNone) { + tilesInUse |= tileMask; + return tileId; + } } + return failure(); + } + + /// Releases a previously allocated tile ID. + void releaseTileId(ArmSMETileType tileType, unsigned tileId) { + TileMask tileMask = getMasks(tileType)[tileId]; + assert((tilesInUse & tileMask) != TileMask::kNone && + "cannot release unallocated tile!"); + tilesInUse ^= tileMask; } - return failure(); -} -/// Collects transitive uses of a root value through control flow. This can -/// handle basic SCF constructs, along with control flow (br and cond_br). -/// Simple loops work at the SCF level, while more complex control flow can be -/// dealt with after lowering to CF. This is used to implement basic tile -/// allocation. -static void findDependantOps(Value rootValue, - SetVector &dependantOps) { - auto traverseCorrespondingValues = [&](auto inputValues, auto exitValues) { - for (auto [idx, value] : llvm::enumerate(inputValues)) { - if (value == rootValue) - findDependantOps(exitValues[idx], dependantOps); + /// Allocates an in-memory tile ID. + unsigned allocateInMemoryTileId() { + // Note: We never release in-memory tile IDs. We could, which may allow + // reusing an allocation, but as we _never_ want to spill an SME tile this + // is not optimized. + return nextInMemoryTileId++; + } + +private: + TileMask tilesInUse = TileMask::kNone; + unsigned nextInMemoryTileId = kInMemoryTileIdBase; +}; + +/// Add new intermediate blocks for the true and false destinations of +/// `cf.cond_br`s that contain tile operands. This prevents spurious liveness +/// overlaps due to copies at branches. +/// +/// BEFORE: +/// ```mlir +/// cf.cond_br %cond, ^bb1(%tile: vector<[4]x[4]xf32>), ^bb2 +/// ``` +/// +/// AFTER: +/// ```mlir +/// cf.cond_br %cond, ^bb1_copy, ^bb2_copy +/// ^bb1_copy: +/// cf.br ^bb1(%tile: vector<[4]x[4]xf32>) +/// ^bb2_copy: +/// cf.br ^bb2 +/// ``` +void splitCondBranches(IRRewriter &rewriter, FunctionOpInterface function) { + SmallVector worklist; + function.walk([&](cf::CondBranchOp condBranch) { + if (llvm::any_of(condBranch->getOperands(), [&](Value value) { + return isValidSMETileVectorType(value.getType()); + })) { + worklist.push_back(condBranch); } + }); + + auto insertJump = [&](Location loc, Block *source, Block *dest, auto args) { + rewriter.setInsertionPointToEnd(source); + rewriter.create(loc, dest, args); }; - for (Operation *user : rootValue.getUsers()) { - if (dependantOps.contains(user)) + + for (auto condBranch : worklist) { + auto loc = condBranch.getLoc(); + Block *block = condBranch->getBlock(); + auto newTrueBranch = rewriter.splitBlock(block, block->end()); + auto newFalseBranch = rewriter.splitBlock(block, block->end()); + insertJump(loc, newTrueBranch, condBranch.getTrueDest(), + condBranch.getTrueDestOperands()); + insertJump(loc, newFalseBranch, condBranch.getFalseDest(), + condBranch.getFalseDestOperands()); + rewriter.modifyOpInPlace(condBranch, [&] { + condBranch.getFalseDestOperandsMutable().clear(); + condBranch.getTrueDestOperandsMutable().clear(); + condBranch.setSuccessor(newTrueBranch, 0); + condBranch.setSuccessor(newFalseBranch, 1); + }); + } +} + +/// Inserts tile copies at `cf.br` operations. +/// +/// BEFORE: +/// ```mlir +/// cf.br ^bb1(%tile: vector<[4]x[4]xf32>) +/// ``` +/// +/// AFTER: +/// ```mlir +/// %copy = arm_sme.copy_tile %tile : vector<[4]x[4]xf32> +/// cf.br ^bb1(%copy: vector<[4]x[4]xf32>) +/// ``` +void insertCopiesAtBranches(IRRewriter &rewriter, + FunctionOpInterface function) { + for (Block &block : function.getBlocks()) { + Operation *terminator = block.getTerminator(); + if (!isa(terminator)) continue; - dependantOps.insert(user); - TypeSwitch(user) - .Case([&](auto branchOp) { - // (CF) Follow branch. - traverseCorrespondingValues(branchOp.getDestOperands(), - branchOp.getDest()->getArguments()); - }) - .Case([&](auto condBranchOp) { - // (CF) Follow true branch. - traverseCorrespondingValues( - condBranchOp.getTrueOperands(), - condBranchOp.getTrueDest()->getArguments()); - // (CF) Follow false branch. - traverseCorrespondingValues( - condBranchOp.getFalseOperands(), - condBranchOp.getFalseDest()->getArguments()); - }) - .Case([&](auto loopOp) { - // (SCF) Follow iter_args of (basic) loops (e.g. for loops). - traverseCorrespondingValues(loopOp.getInits(), - loopOp.getRegionIterArgs()); - }) - .Case([&](auto yieldOp) { - // (SCF) Follow yields of (basic) control flow (e.g. for loops). - auto parent = user->getParentOp(); - traverseCorrespondingValues(user->getOperands(), - parent->getResults()); + rewriter.setInsertionPoint(terminator); + for (OpOperand &operand : terminator->getOpOperands()) { + if (isValidSMETileVectorType(operand.get().getType())) { + auto copy = + rewriter.create(terminator->getLoc(), operand.get()); + rewriter.modifyOpInPlace(terminator, [&] { operand.assign(copy); }); + } + } + } +} + +/// Prepares the IR for tile allocation. It does this by first 'splitting' +/// conditional branches (see `splitCondBranches`), then inserting tile copies +/// at branch operations. The conditional branches are split to prevent the +/// copies needed for them overlapping between the true and false paths of the +/// branch (see `tile-allocation-copies.mlir` and +/// `tile-allocation-liveness.mlir` for examples). The copies break up live +/// ranges and ensure when moving out of SSA the semantics of the program are +/// preserved. +void preprocessForTileAllocation(IRRewriter &rewriter, + FunctionOpInterface function) { + splitCondBranches(rewriter, function); + insertCopiesAtBranches(rewriter, function); +} + +/// A live range for a (collection of) tile values. A live range is built up of +/// non-overlapping intervals [start, end) which represent parts of the program +/// where a value in the range needs to be live (i.e. in an SME virtual tile). +/// Note that as the intervals are non-overlapping all values within a live +/// range can be allocated to the same SME virtual tile. +struct LiveRange { + using RangeSet = llvm::IntervalMap>; + using Allocator = RangeSet::Allocator; + // Dummy value for the IntervalMap. Only the keys matter (the intervals). + static constexpr uint8_t kValidLiveRange = 0xff; + + LiveRange(Allocator &allocator) + : ranges(std::make_unique(allocator)) {} + + /// Returns true if this range overlaps with `otherRange`. + bool overlaps(LiveRange const &otherRange) const { + return llvm::IntervalMapOverlaps(*ranges, + *otherRange.ranges) + .valid(); + } + + /// Unions this live range with `otherRange`, aborts if the ranges overlap. + void unionWith(LiveRange const &otherRange) { + for (auto it = otherRange.ranges->begin(); it != otherRange.ranges->end(); + ++it) + ranges->insert(it.start(), it.stop(), kValidLiveRange); + values.set_union(otherRange.values); + } + + /// Inserts an interval [start, end) for `value` into this range. + void insert(Value value, unsigned start, unsigned end) { + values.insert(value); + if (start != end) + ranges->insert(start, end, kValidLiveRange); + } + + bool empty() const { return ranges->empty(); } + unsigned start() const { return ranges->start(); } + unsigned end() const { return ranges->stop(); } + bool operator<(LiveRange const &other) const { + return start() < other.start(); + } + + ArmSMETileType getTileType() const { + return *getSMETileType(cast(values[0].getType())); + } + + /// The values contained in this live range. + SetVector values; + + /// A set of (non-overlapping) intervals that mark where any value in `values` + /// is live. + std::unique_ptr ranges; + + /// The tile ID (or none) assigned to this live range. + std::optional tileId; +}; + +/// Number operations within a function to allow computing live ranges. +/// Operations are numbered consecutively wihin blocks, and the blocks are +/// topologically sorted (using forward edges). This function is only correct if +/// all ArmSME have been converted to CF (which is asserted). +DenseMap +generateOperationNumbering(FunctionOpInterface function) { + unsigned index = 0; + SetVector blocks = + getTopologicallySortedBlocks(function.getFunctionBody()); + DenseMap operationToIndexMap; + for (Block *block : blocks) { + index++; // We want block args to have their own number. + for (Operation &op : block->getOperations()) { +#ifndef NDEBUG + op.walk([&](ArmSMETileOpInterface nestedOp) { + assert(&op == nestedOp.getOperation() && + "ArmSME tile allocation does not support nested regions"); + }); +#endif + operationToIndexMap.try_emplace(&op, index++); + } + } + return operationToIndexMap; +} + +/// Gather live ranges for SME tiles from the MLIR liveness analysis. +DenseMap +gatherTileLiveRanges(DenseMap const &operationToIndexMap, + LiveRange::Allocator &liveRangeAllocator, + Liveness &liveness, FunctionOpInterface function) { + assert(!operationToIndexMap.empty() && "expected operation numbering"); + DenseMap liveRanges; + /// Defines or updates a live range for an SME tile value. Live-ins may update + /// an existing live range (rather than define a new one). Note: If + /// `liveAtBlockEntry` is true then `firstUseOrDef` is the first operation in + /// the block. + auto defineOrUpdateValueLiveRange = [&](Value value, Operation *firstUseOrDef, + LivenessBlockInfo const &livenessInfo, + bool liveAtBlockEntry = false) { + if (!isValidSMETileVectorType(value.getType())) + return; + // Find or create a live range for `value`. + auto [it, _] = liveRanges.try_emplace(value, liveRangeAllocator); + LiveRange &valueLiveRange = it->second; + auto lastUseInBlock = livenessInfo.getEndOperation(value, firstUseOrDef); + // Add the interval [firstUseOrDef, lastUseInBlock) to the live range. + unsigned startOpIdx = + operationToIndexMap.at(firstUseOrDef) + (liveAtBlockEntry ? -1 : 0); + unsigned endOpIdx = operationToIndexMap.at(lastUseInBlock); + valueLiveRange.insert(value, startOpIdx, endOpIdx); + }; + + for (Block &block : function.getBlocks()) { + LivenessBlockInfo const *livenessInfo = liveness.getLiveness(&block); + // Handle block arguments: + for (Value argument : block.getArguments()) + defineOrUpdateValueLiveRange(argument, &block.front(), *livenessInfo, + /*liveAtBlockEntry=*/true); + // Handle live-ins: + for (Value liveIn : livenessInfo->in()) + defineOrUpdateValueLiveRange(liveIn, &block.front(), *livenessInfo, + /*liveAtBlockEntry=*/true); + // Handle new definitions: + for (Operation &op : block) { + for (Value result : op.getResults()) + defineOrUpdateValueLiveRange(result, &op, *livenessInfo); + } + } + + return liveRanges; +} + +/// Iterate over all predecessor tile values to a (tile) block argument. +static void forEachPredecessorTileValue(BlockArgument blockArg, + function_ref callback) { + Block *block = blockArg.getOwner(); + unsigned argNumber = blockArg.getArgNumber(); + for (Block *pred : block->getPredecessors()) { + TypeSwitch(pred->getTerminator()) + .Case([&](auto branch) { + Value predecessorOperand = branch.getDestOperands()[argNumber]; + callback(predecessorOperand); }) - .Default([&](auto) { - // Otherwise, assume users of _any_ result are dependant. - for (Value result : user->getResults()) - findDependantOps(result, dependantOps); + .Case([&](auto condBranch) { + if (condBranch.getFalseDest() == block) { + Value predecessorOperand = + condBranch.getFalseDestOperands()[argNumber]; + callback(predecessorOperand); + } + if (condBranch.getTrueDest() == block) { + Value predecessorOperand = + condBranch.getTrueDestOperands()[argNumber]; + callback(predecessorOperand); + } }); } } -struct AssignTileIDsPattern - : public OpInterfaceRewritePattern { - using OpInterfaceRewritePattern::OpInterfaceRewritePattern; - LogicalResult matchAndRewrite(ArmSMETileOpInterface tileOp, - PatternRewriter &rewriter) const override { - if (tileOp.getTileId()) - return failure(); - - auto func = tileOp->getParentOfType(); - auto getDiscardableIntAttr = [&](StringRef name, unsigned defaultVal = 0) { - if (auto attr = llvm::dyn_cast_or_null( - func->getDiscardableAttr(name))) - return unsigned(attr.getInt()); - return defaultVal; - }; - auto setDiscardableIntAttr = [&](StringRef name, auto value) { - rewriter.modifyOpInPlace(tileOp, [&] { - func->setDiscardableAttr(name, - rewriter.getI32IntegerAttr((unsigned)value)); - }); - }; - std::optional tileType = tileOp.getAllocatedTileType(); - if (!tileType) - return rewriter.notifyMatchFailure(tileOp, "op does not allocate a tile"); - - TileMask tilesInUse = - static_cast(getDiscardableIntAttr(kTilesInUseAttr)); - auto tileId = allocateTileId(*tileType, tilesInUse); - bool tileIsInMemory = failed(tileId); - if (tileIsInMemory) { - // If we could not find a real tile ID, use an in-memory tile ID (ID >= - // 16). A later pass will insert the necessary spills and reloads. - tileId = - getDiscardableIntAttr(kNextInMemoryTileIdAttr, kInMemoryTileIdBase); - tileOp->emitWarning( - "failed to allocate SME virtual tile to operation, all tile " - "operations will go through memory, expect degraded performance"); +/// Coalesce live ranges where it would prevent unnecessary tile moves. +SmallVector +coalesceTileLiveRanges(DenseMap &initialLiveRanges) { + DenseMap liveRanges; + for (auto &[value, liveRange] : initialLiveRanges) { + liveRanges.insert({value, &liveRange}); + } + + // Merge the live ranges of values `a` and `b` into one (if they do not + // overlap). After this, the values `a` and `b` will both point to the same + // live range (which will contain multiple values). + auto mergeValuesIfNonOverlapping = [&](Value a, Value b) { + LiveRange *aLiveRange = liveRanges.at(a); + LiveRange *bLiveRange = liveRanges.at(b); + if (aLiveRange != bLiveRange && !aLiveRange->overlaps(*bLiveRange)) { + aLiveRange->unionWith(*bLiveRange); + for (Value value : bLiveRange->values) + liveRanges[value] = aLiveRange; + } + }; + + // Merge the live ranges of new definitions with their tile operands. + auto unifyDefinitionsWithOperands = [&](Value value) { + auto armSMEOp = value.getDefiningOp(); + if (!armSMEOp) + return; + for (auto operand : armSMEOp->getOperands()) { + if (isValidSMETileVectorType(operand.getType())) + mergeValuesIfNonOverlapping(value, operand); } + }; + + // Merge the live ranges of block arguments with their predecessors. + auto unifyBlockArgumentsWithPredecessors = [&](Value value) { + auto blockArg = dyn_cast(value); + if (!blockArg) + return; + forEachPredecessorTileValue(blockArg, [&](Value predecessorTile) { + mergeValuesIfNonOverlapping(blockArg, predecessorTile); + }); + }; + + auto applyRule = [&](auto rule) { + llvm::for_each(llvm::make_first_range(initialLiveRanges), rule); + }; + + // Unify as many live ranges as we can. This prevents unnecessary moves. + applyRule(unifyBlockArgumentsWithPredecessors); + applyRule(unifyDefinitionsWithOperands); + + // Remove duplicate live range entries. + SetVector uniqueLiveRanges; + for (auto [_, liveRange] : liveRanges) { + if (!liveRange->empty()) + uniqueLiveRanges.insert(liveRange); + } + + // Sort the new live ranges by starting point (ready for tile allocation). + auto coalescedLiveRanges = uniqueLiveRanges.takeVector(); + std::sort(coalescedLiveRanges.begin(), coalescedLiveRanges.end(), + [](LiveRange *a, LiveRange *b) { return *a < *b; }); + return std::move(coalescedLiveRanges); +} + +/// Choose a live range to spill (via some heuristics). This picks either an +/// active live range from `activeRanges` or the new live range `newRange`. +LiveRange *chooseSpillUsingHeuristics(ArrayRef activeRanges, + LiveRange *newRange) { + // Heuristic: Spill trivially copyable operations (usually free). + auto isTrivialSpill = [&](LiveRange *allocatedRange) { + return isTileTypeGreaterOrEqual(allocatedRange->getTileType(), + newRange->getTileType()) && + allocatedRange->values.size() == 1 && + isTriviallyCloneableTileOp( + allocatedRange->values[0] + .getDefiningOp()); + }; + if (isTrivialSpill(newRange)) + return newRange; + auto trivialSpill = llvm::find_if(activeRanges, isTrivialSpill); + if (trivialSpill != activeRanges.end()) + return *trivialSpill; + + // Heuristic: Spill the range that ends last (with a compatible tile type). + auto isSmallerTileTypeOrEndsEarlier = [](LiveRange *a, LiveRange *b) { + return !isTileTypeGreaterOrEqual(a->getTileType(), b->getTileType()) || + a->end() < b->end(); + }; + LiveRange *lastActiveLiveRange = *std::max_element( + activeRanges.begin(), activeRanges.end(), isSmallerTileTypeOrEndsEarlier); + if (!isSmallerTileTypeOrEndsEarlier(lastActiveLiveRange, newRange)) + return lastActiveLiveRange; + return newRange; +} + +/// Greedily allocate tile IDs to live ranges. Spill using simple heuristics. +/// Note: This does not attempt to fill holes in active live ranges. +void allocateTilesToLiveRanges( + ArrayRef liveRangesSortedByStartPoint) { + TileAllocator tileAllocator; + SetVector activeRanges; + for (LiveRange *nextRange : liveRangesSortedByStartPoint) { + // Release tile IDs from live ranges that have ended. + activeRanges.remove_if([&](LiveRange *activeRange) { + if (activeRange->end() <= nextRange->start()) { + tileAllocator.releaseTileId(activeRange->getTileType(), + *activeRange->tileId); + return true; + } + return false; + }); - // Set all operations dependent on `tileOp` to use the same tile ID. - // This is a naive tile allocation scheme, but works for common cases. For - // example, as this only allocates tile IDs to existing ops, it can't solve - // cases like this (%tileA and %tileB come from different root operations): - // - // %tile = scf.if %some_cond -> vector<[4]x[4]xi32> { - // scf.yield %tileA {tile_id = 0} : vector<[4]x[4]xi32> - // } else { - // scf.yield %tileB {tile_id = 1} : vector<[4]x[4]xi32> - // } - // - // This case would require allocating a new tile for the result of the - // scf.if, and moving the contents of %tileA or %tileB to result tile (based - // on the %some_cond). - // Find all the ops that (transitively) depend on this tile. - SetVector dependantOps; - findDependantOps(tileOp->getResult(0), dependantOps); - auto tileIDAttr = rewriter.getI32IntegerAttr(*tileId); - for (auto *op : dependantOps) { - if (auto dependantTileOp = llvm::dyn_cast(op)) { - auto currentTileId = dependantTileOp.getTileId(); - if (currentTileId && unsigned(currentTileId.getInt()) != tileId) - return dependantTileOp.emitOpError( - "already assigned different SME virtual tile!"); + // Allocate a tile ID to `nextRange`. + auto rangeTileType = nextRange->getTileType(); + auto tileId = tileAllocator.allocateTileId(rangeTileType); + if (succeeded(tileId)) { + nextRange->tileId = *tileId; + } else { + LiveRange *rangeToSpill = + chooseSpillUsingHeuristics(activeRanges.getArrayRef(), nextRange); + if (rangeToSpill != nextRange) { + // Spill an active live range (so release its tile ID first). + tileAllocator.releaseTileId(rangeToSpill->getTileType(), + *rangeToSpill->tileId); + activeRanges.remove(rangeToSpill); + // This will always succeed after a spill (of an active live range). + nextRange->tileId = *tileAllocator.allocateTileId(rangeTileType); } + rangeToSpill->tileId = tileAllocator.allocateInMemoryTileId(); + } + + // Insert the live range into the active ranges. + if (nextRange->tileId < kInMemoryTileIdBase) + activeRanges.insert(nextRange); + } +} + +/// Assigns a tile ID to an MLIR value. +void assignTileIdToValue(IRRewriter &rewriter, Value value, + IntegerAttr tileIdAttr) { + if (auto tileOp = value.getDefiningOp()) + rewriter.modifyOpInPlace(tileOp, [&] { tileOp.setTileId(tileIdAttr); }); + for (Operation *user : value.getUsers()) { + if (auto tileOp = dyn_cast(user)) { + // Ensure ArmSME ops that don't produce a value still get a tile ID. + if (!hasTileResult(tileOp)) + rewriter.modifyOpInPlace(tileOp, [&] { tileOp.setTileId(tileIdAttr); }); } + } +} + +/// Assign tile IDs back to IR and attempt to resolve trivial tile ID conflicts. +LogicalResult assignTileIdsAndResolveTrivialConflicts( + IRRewriter &rewriter, FunctionOpInterface function, + ArrayRef allocatedLiveRanges) { + for (LiveRange const *liveRange : allocatedLiveRanges) { + auto tileIdAttr = rewriter.getI32IntegerAttr(*liveRange->tileId); + auto isAllocatedToSameTile = [&](Value value) { + if (auto tileOp = value.getDefiningOp(); + tileOp && tileOp.getTileId() == tileIdAttr) + return true; + return liveRange->values.contains(value); + }; + + /// Eliminates copies where the operand has the same tile ID. + auto foldRedundantCopies = [&](Value value) -> LogicalResult { + auto copyOp = value.getDefiningOp(); + if (!copyOp || !isAllocatedToSameTile(copyOp.getTile())) + return failure(); + rewriter.replaceAllUsesWith(copyOp, copyOp.getTile()); + return success(); + }; + + /// Validates each predecessor to a tile block argument has been assigned + /// the same tile ID. + auto validateBlockArguments = [&](Value value) { + auto blockArg = dyn_cast(value); + if (!blockArg) { + // Not a block argument (nothing to validate). + return success(); + } + bool tileMismatch = false; + forEachPredecessorTileValue(blockArg, [&](Value predecessorTile) { + if (tileMismatch) + return; + if (!isAllocatedToSameTile(predecessorTile)) { + blockArg.getOwner()->getParentOp()->emitOpError( + "block argument not allocated to the same SME virtial tile as " + "predecessors"); + tileMismatch = true; + } + }); + return success(/*isSuccess=*/!tileMismatch); + }; - // Rewrite IR. - if (!tileIsInMemory) - setDiscardableIntAttr(kTilesInUseAttr, tilesInUse); - else - setDiscardableIntAttr(kNextInMemoryTileIdAttr, *tileId + 1); - rewriter.modifyOpInPlace(tileOp, [&] { tileOp.setTileId(tileIDAttr); }); - for (auto *op : dependantOps) { - if (auto dependantTileOp = llvm::dyn_cast(op)) { + /// Attempts to resolve (trivial) tile ID conflicts. + auto resolveTrivialTileConflicts = [&](Value value) -> LogicalResult { + auto tileOp = value.getDefiningOp(); + OpOperand *tileOperand = getTileOpOperand(tileOp); + if (!tileOperand || isAllocatedToSameTile(tileOperand->get())) { + // Operand already allocated to the correct tile. + // No conflict to resolve. + return success(); + } + auto operandTileOp = + tileOperand->get().getDefiningOp(); + if (!isTriviallyCloneableTileOp(operandTileOp)) { + auto error = + tileOp.emitOpError("tile operand allocated to different SME " + "virtial tile (move required)"); + error.attachNote(tileOperand->get().getLoc()) + << "tile operand is: " << tileOperand->get(); + return error; + } + // Cloning prevents a move/spill (though may require recomputation). + rewriter.setInsertionPoint(tileOp); + auto clonedOp = operandTileOp.clone(); + rewriter.modifyOpInPlace(clonedOp, + [&] { clonedOp.setTileId(tileOp.getTileId()); }); + rewriter.insert(clonedOp); + if (isa(tileOp)) { + rewriter.replaceAllUsesWith(tileOp->getResult(0), + clonedOp->getResult(0)); + } else { rewriter.modifyOpInPlace( - dependantTileOp, [&] { dependantTileOp.setTileId(tileIDAttr); }); + tileOp, [&] { tileOperand->assign(clonedOp->getResult(0)); }); } + return success(); + }; + + for (Value value : liveRange->values) { + // 1. Assign the tile ID to the value. + assignTileIdToValue(rewriter, value, tileIdAttr); + + // 2. Attempt to eliminate redundant tile copies. + if (succeeded(foldRedundantCopies(value))) + continue; + + // 3. Validate tile block arguments. + if (failed(validateBlockArguments(value))) + return failure(); + + // 4. Attempt to resolve (trivial) tile ID conflicts. + if (failed(resolveTrivialTileConflicts(value))) + return failure(); } + } + return success(); +} - return success(); +/// Prints live ranges alongside operation names for debugging. +void dumpLiveRanges(DenseMap const &operationToIndexMap, + ArrayRef liveRanges, + FunctionOpInterface function) { + llvm::errs() << "SME Tile Liveness: @" << function.getName() + << "\nKey:\nS - Start\nE - End\n| - Live\n"; + for (auto [blockIdx, block] : llvm::enumerate(function.getBlocks())) { + llvm::errs() << "^bb" << blockIdx << ":\n"; + for (Operation &op : block.getOperations()) { + unsigned operationIndex = operationToIndexMap.at(&op); + for (LiveRange const *range : liveRanges) { + char liveness = ' '; + for (auto it = range->ranges->begin(); it != range->ranges->end(); + ++it) { + if (it.start() == operationIndex) + liveness = (liveness == 'E' ? '|' : 'S'); + else if (it.stop() == operationIndex) + liveness = (liveness == 'S' ? '|' : 'E'); + else if (operationIndex >= it.start() && operationIndex < it.stop()) + liveness = '|'; + } + llvm::errs() << liveness; + } + llvm::errs() << ' ' << op.getName() << '\n'; + } } -}; + llvm::errs() << "==========\n"; +} -struct TileAllocationPass - : public arm_sme::impl::TileAllocationBase { +struct TestTileAllocationPass + : public arm_sme::impl::TestTileAllocationBase { + using TestTileAllocationBase::TestTileAllocationBase; void runOnOperation() override { - RewritePatternSet patterns(&getContext()); - patterns.add(patterns.getContext()); - GreedyRewriteConfig config; - // Setting useTopDownTraversal ensures tiles are allocated in program - // order. - config.useTopDownTraversal = true; - if (mlir::failed(mlir::applyPatternsAndFoldGreedily( - getOperation(), std::move(patterns), config))) { - signalPassFailure(); + FunctionOpInterface function = getOperation(); + if (preprocessOnly) { + IRRewriter rewriter(function); + return preprocessForTileAllocation(rewriter, function); } + if (failed(arm_sme::allocateSMETiles(function, dumpTileLiveRanges))) + signalPassFailure(); } }; } // namespace -std::unique_ptr mlir::arm_sme::createTileAllocationPass() { - return std::make_unique(); +LogicalResult mlir::arm_sme::allocateSMETiles(FunctionOpInterface function, + bool dumpRanges) { + if (function.empty()) { + // TODO: Also return early if the function contains no ArmSME ops? + return success(); + } + + LiveRange::Allocator liveRangeAllocator; + IRRewriter rewriter(function.getContext()); + + // 1. Preprocess the IR for tile allocation. + preprocessForTileAllocation(rewriter, function); + + // 2. Gather live ranges for each ArmSME tile within the function. + Liveness liveness(function); + auto operationToIndexMap = generateOperationNumbering(function); + auto initialLiveRanges = gatherTileLiveRanges( + operationToIndexMap, liveRangeAllocator, liveness, function); + if (initialLiveRanges.empty()) + return success(); + + if (dumpRanges) { + // Wrangle initial live ranges into a form suitable for printing. + auto nonEmpty = llvm::make_filter_range( + llvm::make_second_range(initialLiveRanges), + [&](LiveRange const &liveRange) { return !liveRange.empty(); }); + auto initialRanges = llvm::to_vector(llvm::map_range( + nonEmpty, [](LiveRange const &liveRange) { return &liveRange; })); + std::sort(initialRanges.begin(), initialRanges.end(), + [](LiveRange const *a, LiveRange const *b) { return *a < *b; }); + llvm::errs() << "\n========== Initial Live Ranges:\n"; + dumpLiveRanges(operationToIndexMap, initialRanges, function); + } + + // 3. Coalesce (non-overlapping) live ranges where it would be beneficial + // for tile allocation. E.g. Unify the result of an operation with its + // operands. + auto coalescedLiveRanges = coalesceTileLiveRanges(initialLiveRanges); + + if (dumpRanges) { + llvm::errs() << "\n========== Coalesced Live Ranges:\n"; + dumpLiveRanges(operationToIndexMap, coalescedLiveRanges, function); + } + + // 4. Allocate tile IDs to live ranges. + allocateTilesToLiveRanges(coalescedLiveRanges); + + // 5. Assign the tile IDs back to the ArmSME operations. + if (failed(assignTileIdsAndResolveTrivialConflicts(rewriter, function, + coalescedLiveRanges))) { + return failure(); + } + + // 6. Erase trivially dead tile operations (e.g. a ZeroOp with no + // users). This prevents the LLVM conversion needlessly inserting spills. + eraseTriviallyDeadTileOps(rewriter, function); + return success(); } diff --git a/mlir/test/Conversion/ArmSMEToLLVM/arm-sme-to-llvm.mlir b/mlir/test/Conversion/ArmSMEToLLVM/arm-sme-to-llvm.mlir index f48046a8d799..14b1f323da3a 100644 --- a/mlir/test/Conversion/ArmSMEToLLVM/arm-sme-to-llvm.mlir +++ b/mlir/test/Conversion/ArmSMEToLLVM/arm-sme-to-llvm.mlir @@ -1,5 +1,4 @@ -// RUN: mlir-opt %s -allocate-arm-sme-tiles -convert-arm-sme-to-llvm -cse -canonicalize -split-input-file -verify-diagnostics | FileCheck %s - +// RUN: mlir-opt %s --pass-pipeline="builtin.module(func.func(convert-arm-sme-to-llvm,cse,canonicalize))" -split-input-file | FileCheck %s // Test conversion of ArmSME ops to LLVM intrinsics. //===----------------------------------------------------------------------===// diff --git a/mlir/test/Conversion/ArmSMEToLLVM/tile-spills-and-fills.mlir b/mlir/test/Conversion/ArmSMEToLLVM/tile-spills-and-fills.mlir index a9c1a65a296f..2c3868d7f25c 100644 --- a/mlir/test/Conversion/ArmSMEToLLVM/tile-spills-and-fills.mlir +++ b/mlir/test/Conversion/ArmSMEToLLVM/tile-spills-and-fills.mlir @@ -1,6 +1,6 @@ -// RUN: mlir-opt %s -allocate-arm-sme-tiles -split-input-file -verify-diagnostics | \ +// RUN: mlir-opt %s -test-arm-sme-tile-allocation -split-input-file | \ // RUN: FileCheck %s --check-prefix=AFTER-TILE-ALLOC -// RUN: mlir-opt %s -allocate-arm-sme-tiles -convert-arm-sme-to-llvm -canonicalize -cse \ +// RUN: mlir-opt %s --pass-pipeline="builtin.module(func.func(convert-arm-sme-to-llvm,cse,canonicalize))" \ // RUN: -split-input-file -verify-diagnostics | \ // RUN: FileCheck %s --check-prefix=AFTER-LLVM-LOWERING @@ -56,6 +56,9 @@ func.func @use_too_many_tiles() { %1 = arm_sme.zero : vector<[4]x[4]xi32> // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} %2 = arm_sme.zero : vector<[8]x[8]xi16> + "test.some_use"(%0) : (vector<[4]x[4]xi32>) -> () + "test.some_use"(%1) : (vector<[4]x[4]xi32>) -> () + "test.some_use"(%2) : (vector<[8]x[8]xi16>) -> () return } // AFTER-TILE-ALLOC-LABEL: @use_too_many_tiles @@ -131,18 +134,16 @@ func.func @use_too_many_tiles() { /// Note: In this example an entire tile swap is inserted before/after the /// `arm_sme.load_tile_slice` operation. Really, this only needs to spill a /// single tile slice (and can omit the initial load, like in the previous example). -func.func @very_excessive_spills(%memref : memref) -> vector<[4]x[4]xf32> { - %useAllTiles = arm_sme.get_tile : vector<[16]x[16]xi8> +func.func @very_excessive_spills(%useAllTiles : vector<[16]x[16]xi8>, %memref: memref) -> vector<[4]x[4]xf32> { %c0 = arith.constant 0 : index - // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} %tile = arm_sme.get_tile : vector<[4]x[4]xf32> %mask = vector.constant_mask [4] : vector<[4]xi1> + // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} %loadSlice = arm_sme.load_tile_slice %memref[%c0, %c0], %mask, %tile, %c0 : memref, vector<[4]xi1>, vector<[4]x[4]xf32> - "test.some_use"(%loadSlice) : (vector<[4]x[4]xf32>) -> () + "test.some_use"(%useAllTiles) : (vector<[16]x[16]xi8>) -> () + return %loadSlice : vector<[4]x[4]xf32> } // AFTER-TILE-ALLOC-LABEL: @very_excessive_spills -// AFTER-TILE-ALLOC: arm_sme.get_tile -// AFTER-TILE-ALLOC-SAME: tile_id = 0 // AFTER-TILE-ALLOC: arm_sme.load_tile_slice // AFTER-TILE-ALLOC-SAME: tile_id = 16 diff --git a/mlir/test/Conversion/ArmSMEToLLVM/unsupported.mlir b/mlir/test/Conversion/ArmSMEToLLVM/unsupported.mlir index 15767ff1dec3..a62ca080ab8d 100644 --- a/mlir/test/Conversion/ArmSMEToLLVM/unsupported.mlir +++ b/mlir/test/Conversion/ArmSMEToLLVM/unsupported.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt %s -allocate-arm-sme-tiles -convert-arm-sme-to-llvm -split-input-file -allow-unregistered-dialect -verify-diagnostics +// RUN: mlir-opt %s --pass-pipeline="builtin.module(func.func(convert-arm-sme-to-llvm))" -verify-diagnostics //===----------------------------------------------------------------------===// // arm_sme.outerproduct diff --git a/mlir/test/Dialect/ArmSME/basic-tile-allocation.mlir b/mlir/test/Dialect/ArmSME/basic-tile-allocation.mlir index e144bac970a7..8b46998d56b0 100644 --- a/mlir/test/Dialect/ArmSME/basic-tile-allocation.mlir +++ b/mlir/test/Dialect/ArmSME/basic-tile-allocation.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt %s -allocate-arm-sme-tiles -split-input-file | FileCheck %s +// RUN: mlir-opt %s -test-arm-sme-tile-allocation -split-input-file | FileCheck %s // ----- diff --git a/mlir/test/Dialect/ArmSME/canonicalize.mlir b/mlir/test/Dialect/ArmSME/canonicalize.mlir index b7ba3f728c70..643dfd4a7cbd 100644 --- a/mlir/test/Dialect/ArmSME/canonicalize.mlir +++ b/mlir/test/Dialect/ArmSME/canonicalize.mlir @@ -1,18 +1,14 @@ -// RUN: mlir-opt -canonicalize -split-input-file -verify-diagnostics %s | mlir-opt | FileCheck %s +// RUN: mlir-opt %s -canonicalize | mlir-opt | FileCheck %s -// This tests that the `arm_sme.materialize_ssa_tile` placeholder is removed -// once it becomes unused, after lowering to control flow. +// This tests that dead tile values are removed from control flow. -// ----- - -// CHECK-LABEL: @unused_materialize_ssa_tile_is_removed_from_blocks -// CHECK-NOT: arm_sme.materialize_ssa_tile +// CHECK-LABEL: @unused_ssa_tile_is_removed_from_blocks // CHECK-NOT: vector<[4]x[4]xf32> -func.func @unused_materialize_ssa_tile_is_removed_from_blocks(%arg0: memref) { +func.func @unused_ssa_tile_is_removed_from_blocks(%arg0: memref) { %c10 = arith.constant 10 : index %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index - %tile = arm_sme.materialize_ssa_tile : vector<[4]x[4]xf32> + %tile = arm_sme.get_tile : vector<[4]x[4]xf32> cf.br ^bb1(%c0, %tile : index, vector<[4]x[4]xf32>) ^bb1(%1: index, %2: vector<[4]x[4]xf32>): // 2 preds: ^bb0, ^bb2 %3 = arith.cmpi slt, %1, %c10 : index diff --git a/mlir/test/Dialect/ArmSME/cse.mlir b/mlir/test/Dialect/ArmSME/cse.mlir deleted file mode 100644 index 74e7293eaeca..000000000000 --- a/mlir/test/Dialect/ArmSME/cse.mlir +++ /dev/null @@ -1,30 +0,0 @@ -// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline='builtin.module(func.func(cse))' | FileCheck %s - -// This test is checking that CSE does not remove 'arm_sme.zero/get_tile' ops as -// duplicates. - -// CHECK-LABEL: @zero_tile -// CHECK: %[[TILE_0:.*]] = arm_sme.zero : vector<[4]x[4]xi32> -// CHECK: %[[TILE_1:.*]] = arm_sme.zero : vector<[4]x[4]xi32> -// CHECK: "prevent.dce"(%[[TILE_0]]) : (vector<[4]x[4]xi32>) -> () -// CHECK: "prevent.dce"(%[[TILE_1]]) : (vector<[4]x[4]xi32>) -> () -func.func @zero_tile() { - %tile_1 = arm_sme.zero : vector<[4]x[4]xi32> - %tile_2 = arm_sme.zero : vector<[4]x[4]xi32> - "prevent.dce"(%tile_1) : (vector<[4]x[4]xi32>) -> () - "prevent.dce"(%tile_2) : (vector<[4]x[4]xi32>) -> () - return -} - -// CHECK-LABEL: @get_tile -// CHECK: %[[TILE_0:.*]] = arm_sme.get_tile : vector<[4]x[4]xi32> -// CHECK: %[[TILE_1:.*]] = arm_sme.get_tile : vector<[4]x[4]xi32> -// CHECK: "prevent.dce"(%[[TILE_0]]) : (vector<[4]x[4]xi32>) -> () -// CHECK: "prevent.dce"(%[[TILE_1]]) : (vector<[4]x[4]xi32>) -> () -func.func @get_tile() { - %tile_1 = arm_sme.get_tile : vector<[4]x[4]xi32> - %tile_2 = arm_sme.get_tile : vector<[4]x[4]xi32> - "prevent.dce"(%tile_1) : (vector<[4]x[4]xi32>) -> () - "prevent.dce"(%tile_2) : (vector<[4]x[4]xi32>) -> () - return -} diff --git a/mlir/test/Dialect/ArmSME/roundtrip.mlir b/mlir/test/Dialect/ArmSME/roundtrip.mlir index ab46c7adca59..6095fdc11ead 100644 --- a/mlir/test/Dialect/ArmSME/roundtrip.mlir +++ b/mlir/test/Dialect/ArmSME/roundtrip.mlir @@ -1403,3 +1403,12 @@ func.func @arm_sme_usmops_4way_i16i16_to_i64(%vecA: vector<[8]xi16>, %vecB: vect %reuslt = arm_sme.usmops_4way %vecA, %vecB : vector<[8]xi16>, vector<[8]xi16> into vector<[2]x[2]xi64> return %reuslt : vector<[2]x[2]xi64> } + +//===----------------------------------------------------------------------===// +// arm_sme.copy_tile +//===----------------------------------------------------------------------===// + +func.func @arm_sme_copy_tile(%vec: vector<[4]x[4]xf32>) -> vector<[4]x[4]xf32> { + %result = arm_sme.copy_tile %vec : vector<[4]x[4]xf32> + return %result : vector<[4]x[4]xf32> +} diff --git a/mlir/test/Dialect/ArmSME/tile-allocation-copies.mlir b/mlir/test/Dialect/ArmSME/tile-allocation-copies.mlir new file mode 100644 index 000000000000..6d9cbf36a162 --- /dev/null +++ b/mlir/test/Dialect/ArmSME/tile-allocation-copies.mlir @@ -0,0 +1,159 @@ +// RUN: mlir-opt %s -test-arm-sme-tile-allocation=preprocess-only -split-input-file | FileCheck %s + +// This file tests the inserting copies for the SME tile allocation. Copies are +// inserted at `cf.br` ops (the predecessors to block arguments). Conditional +// branches are split to prevent conflicts (see cond_br_with_backedge). + +// CHECK-LABEL: func.func @simple_branch( +// CHECK-SAME: %[[TILE:.*]]: vector<[4]x[4]xf32>) +// %[[COPY:.*]] = arm_sme.copy_tile %[[TILE]] : vector<[4]x[4]xf32> +// cf.br ^bb1(%[[COPY]] : vector<[4]x[4]xf32>) +// ^bb1(%[[BLOCK_ARG:.*]]: vector<[4]x[4]xf32>): + +func.func @simple_branch(%tile : vector<[4]x[4]xf32>) { + cf.br ^bb1(%tile: vector<[4]x[4]xf32>) +^bb1(%blockArg: vector<[4]x[4]xf32>): + return +} + +// ----- + +// Note: The ^POINTLESS_SHIM_FOR_BB2 block is added as the cond_br splitting does +// not check if it needs to insert a copy or not (there is no harm in the empty +// block though -- it will fold away later). + +// CHECK-LABEL: func.func @cond_branch( +// CHECK-SAME: %[[COND:.*]]: i1, %[[TILE:.*]]: vector<[4]x[4]xf32> +// CHECK: cf.cond_br %[[COND]], ^[[BB1_COPIES:[[:alnum:]]+]], ^[[POINTLESS_SHIM_FOR_BB2:[[:alnum:]]+]] +// CHECK: ^[[POINTLESS_SHIM_FOR_BB2]]: +// CHECK: cf.br ^[[BB2:.*]] +// CHECK: ^[[BB1_COPIES]]: +// CHECK: arm_sme.copy_tile %[[TILE]] : vector<[4]x[4]xf32> +// CHECK: cf.br ^[[BB1:.*]] +func.func @cond_branch(%cond: i1, %tile: vector<[4]x[4]xf32>) { + cf.cond_br %cond, ^bb1(%tile: vector<[4]x[4]xf32>), ^bb2 +^bb1(%blockArg: vector<[4]x[4]xf32>): + return +^bb2: + return +} + +// ----- + +// Reduction of a real world example that shows why we must split conditional branches. + +// CHECK-LABEL: @cond_branch_with_backedge( +// CHECK-SAME: %[[TILEA:[[:alnum:]]+]]: vector<[4]x[4]xf32>, %[[TILEB:[[:alnum:]]+]]: vector<[4]x[4]xf32>, +// CHECK-SAME: %[[TILEC:[[:alnum:]]+]]: vector<[4]x[4]xf32>, %[[TILED:[[:alnum:]]+]]: vector<[4]x[4]xf32>, +// CHECK: %[[BB1_COPY_0:.*]] = arm_sme.copy_tile %[[TILEA]] : vector<[4]x[4]xf32> +// CHECK: cf.br ^bb1(%{{[[:alnum:]]+}}, %[[BB1_COPY_0]] +// CHECK: ^bb1(%[[CURRENT_INDEX:.*]]: index, %[[ITER_TILE:.*]]: vector<[4]x[4]xf32>): +// CHECK: %[[CONTINUE_LOOP:.*]] = arith.cmpi +// CHECK: cf.cond_br %[[CONTINUE_LOOP]], ^[[BB2_COPIES:[[:alnum:]]+]], ^[[BB3_COPIES:[[:alnum:]]+]] +// CHECK: ^[[BB3_COPIES]]: +// CHECK-NEXT: %[[BB3_COPY_0:.*]] = arm_sme.copy_tile %[[ITER_TILE]] : vector<[4]x[4]xf32> +// CHECK-NEXT: %[[BB3_COPY_1:.*]] = arm_sme.copy_tile %[[TILEB]] : vector<[4]x[4]xf32> +// CHECK-NEXT: %[[BB3_COPY_2:.*]] = arm_sme.copy_tile %[[TILEC]] : vector<[4]x[4]xf32> +// CHECK-NEXT: %[[BB3_COPY_3:.*]] = arm_sme.copy_tile %[[TILED]] : vector<[4]x[4]xf32> +// CHECK-NEXT: cf.br ^[[BB3:[[:alnum:]]+]](%[[BB3_COPY_0]], %[[BB3_COPY_1]], %[[BB3_COPY_2]], %[[BB3_COPY_3]] +// CHECK: ^[[BB2_COPIES]]: +// CHECK-NEXT: cf.br ^[[BB2:[[:alnum:]]+]] +// CHECK: ^[[BB2]]: +// CHECK-NEXT: %[[NEXT_TILE:.*]] = arm_sme.move_vector_to_tile_slice %{{.*}}, %[[ITER_TILE]] +// CHECK: %[[BB1_COPY_1:.*]] = arm_sme.copy_tile %[[NEXT_TILE]] : vector<[4]x[4]xf32> +// CHECK: cf.br ^bb1(%{{[[:alnum:]]+}}, %[[BB1_COPY_1]] +// CHECK: ^[[BB3]](%{{.*}}: vector<[4]x[4]xf32>): +// CHECK-NEXT: return +func.func @cond_branch_with_backedge(%tileA: vector<[4]x[4]xf32>, %tileB: vector<[4]x[4]xf32>, %tileC: vector<[4]x[4]xf32>, %tileD: vector<[4]x[4]xf32>, %slice: vector<[4]xf32>) { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c10 = arith.constant 10 : index + // Live here: %tileA, %tileB, %tileC, %tileD + cf.br ^bb1(%c0, %tileA : index, vector<[4]x[4]xf32>) +^bb1(%currentIndex: index, %iterTile: vector<[4]x[4]xf32>): + %continueLoop = arith.cmpi slt, %currentIndex, %c10 : index + // Live here: %iterTile, %tileB, %tileC, %tileD + // %iterTile, %tileB, %tileC, %tileD are live out (in the ^bb2 case). If we + // inserted the (four) `arm_sme.copy_tile` operations here we would run out of tiles. + // However, note that the copies are only needed if we take the ^bb3 path. So, if we add + // a new block along that path we can insert the copies without any conflicts. + cf.cond_br %continueLoop, ^bb2, ^bb3(%iterTile, %tileB, %tileC, %tileD : vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>) +^bb2: + // Live here: %iterTile, %tileB, %tileC, %tileD + %nextTile = arm_sme.move_vector_to_tile_slice %slice, %iterTile, %currentIndex : vector<[4]xf32> into vector<[4]x[4]xf32> + %nextIndex = arith.addi %currentIndex, %c1 : index + cf.br ^bb1(%nextIndex, %nextTile : index, vector<[4]x[4]xf32>) +^bb3(%finalTileA: vector<[4]x[4]xf32>, %finalTileB: vector<[4]x[4]xf32>, %finalTileC: vector<[4]x[4]xf32>, %finalTileD: vector<[4]x[4]xf32>): + // Live here: %finalTileA, %finalTileB, %finalTileC, %finalTileD + return +} + +// ----- + +// CHECK-LABEL: @tile_dominance +// CHECK-NOT: arm_sme.copy_tile +func.func @tile_dominance(%arg0: vector<[4]x[4]xf32>) { + cf.br ^bb1 +^bb1: // 2 preds: ^bb0, ^bb4 + "test.some_use"(%arg0) : (vector<[4]x[4]xf32>) -> () + return +^bb2: // no predecessors + %0 = arm_sme.get_tile : vector<[4]x[4]xf32> + cf.br ^bb3 +^bb3: // pred: ^bb2 + "test.some_use"(%0) : (vector<[4]x[4]xf32>) -> () + return +^bb4: // no predecessors + cf.br ^bb1 +^bb5: // no predecessors + return +} + +// ----- + +// CHECK-LABEL: func.func @cond_branch_true_and_false_tile_args( +// CHECK-SAME: %[[COND:.*]]: i1, %[[TILE:.*]]: vector<[4]x[4]xf32> +// CHECK-NEXT: cf.cond_br %[[COND]], ^[[BB1_COPIES:[[:alnum:]]+]], ^[[BB2_COPIES:[[:alnum:]]+]] +// CHECK: ^[[BB2_COPIES]]: +// CHECK-NEXT: %[[COPY_0:.*]] = arm_sme.copy_tile %[[TILE]] : vector<[4]x[4]xf32> +// CHECK-NEXT: cf.br ^[[BB2:[[:alnum:]]+]](%[[COPY_0]] +// CHECK: ^[[BB1_COPIES]]: +// CHECK-NEXT: %[[COPY_1:.*]] = arm_sme.copy_tile %[[TILE]] : vector<[4]x[4]xf32> +// CHECK-NEXT: cf.br ^[[BB1:[[:alnum:]]+]](%[[COPY_1]] +// CHECK: ^[[BB1]]{{.*}}: +// CHECK-NEXT: return +// CHECK: ^[[BB2]]{{.*}}: +// CHECK-NEXT: return +func.func @cond_branch_true_and_false_tile_args(%cond: i1, %tile: vector<[4]x[4]xf32>) { + cf.cond_br %cond, ^bb1(%tile: vector<[4]x[4]xf32>), ^bb2(%tile: vector<[4]x[4]xf32>) +^bb1(%blockArg0: vector<[4]x[4]xf32>): + return +^bb2(%blockArg1: vector<[4]x[4]xf32>): + return +} + +// ----- + +// CHECK-LABEL: @multiple_predecessors +// CHECK: ^bb1: +// CHECK-NEXT: %[[TILE:.*]] = arm_sme.get_tile : vector<[4]x[4]xf32> +// CHECK-NEXT: %[[COPY_0:.*]] = arm_sme.copy_tile %[[TILE]] : vector<[4]x[4]xf32> +// CHECK-NEXT: cf.br ^bb3(%[[COPY_0]] : vector<[4]x[4]xf32>) +// CHECK: ^bb2: +// CHECK-NEXT: %[[ZERO:.*]] = arm_sme.zero : vector<[4]x[4]xf32> +// CHECK-NEXT: %[[COPY_1:.*]] = arm_sme.copy_tile %[[ZERO]] : vector<[4]x[4]xf32> +// CHECK-NEXT: cf.br ^bb3(%[[COPY_1]] : vector<[4]x[4]xf32>) +// CHECK: ^bb3({{.*}}): +// CHECK-NEXT: return +func.func @multiple_predecessors(%cond: i1) +{ + cf.cond_br %cond, ^bb1, ^bb2 +^bb1: + %tile = arm_sme.get_tile : vector<[4]x[4]xf32> + cf.br ^bb3(%tile : vector<[4]x[4]xf32>) +^bb2: + %zero = arm_sme.zero : vector<[4]x[4]xf32> + cf.br ^bb3(%zero : vector<[4]x[4]xf32>) +^bb3(%blockArg: vector<[4]x[4]xf32>): // pred: ^bb1, ^bb2 + return +} diff --git a/mlir/test/Dialect/ArmSME/tile-allocation-invalid.mlir b/mlir/test/Dialect/ArmSME/tile-allocation-invalid.mlir index 39d9ab6491e3..6b5e44365bf5 100644 --- a/mlir/test/Dialect/ArmSME/tile-allocation-invalid.mlir +++ b/mlir/test/Dialect/ArmSME/tile-allocation-invalid.mlir @@ -1,19 +1,17 @@ -// RUN: mlir-opt %s -allocate-arm-sme-tiles -split-input-file -verify-diagnostics +// RUN: mlir-opt %s -convert-scf-to-cf -test-arm-sme-tile-allocation -verify-diagnostics -// ----- +// Select between tileA and tileB. This is currently unsupported as it would +// require inserting (runtime) tile moves. -func.func @selecting_between_different_tiles_is_unsupported(%dest : memref, %cond: i1) { +// expected-note@below {{tile operand is: of type 'vector<[4]x[4]xi32>'}} +func.func @selecting_between_different_tiles_is_unsupported(%dest : memref, %tileA : vector<[4]x[4]xi32>, %tileB : vector<[4]x[4]xi32>, %cond: i1) { %c0 = arith.constant 0 : index - %tileA = arm_sme.get_tile : vector<[4]x[4]xi32> - %tileB = arm_sme.get_tile : vector<[4]x[4]xi32> - // Select between tileA and tileB. This is currently unsupported as it would - // require inserting tile move operations during tile allocation. + // expected-error@below {{op tile operand allocated to different SME virtial tile (move required)}} %tile = scf.if %cond -> vector<[4]x[4]xi32> { scf.yield %tileA : vector<[4]x[4]xi32> } else { scf.yield %tileB : vector<[4]x[4]xi32> } - // expected-error@+1 {{op already assigned different SME virtual tile!}} arm_sme.tile_store %tile, %dest[%c0, %c0] : memref, vector<[4]x[4]xi32> return } diff --git a/mlir/test/Dialect/ArmSME/tile-allocation-liveness.mlir b/mlir/test/Dialect/ArmSME/tile-allocation-liveness.mlir index 2dedcb2fbc24..88fc8a8923d3 100644 --- a/mlir/test/Dialect/ArmSME/tile-allocation-liveness.mlir +++ b/mlir/test/Dialect/ArmSME/tile-allocation-liveness.mlir @@ -1,18 +1,26 @@ -// RUN: mlir-opt %s -allocate-arm-sme-tiles -split-input-file -verify-diagnostics | FileCheck %s --check-prefix=CHECK-BAD +// RUN: mlir-opt %s -convert-scf-to-cf -test-arm-sme-tile-allocation -split-input-file -verify-diagnostics | FileCheck %s +// RUN: mlir-opt %s -convert-scf-to-cf -test-arm-sme-tile-allocation=dump-tile-live-ranges -mlir-disable-threading -split-input-file -verify-diagnostics 2>&1 >/dev/null | FileCheck %s --check-prefix=CHECK-LIVE-RANGE -// This file tests some aspects of liveness issues in the SME tile allocator. -// These tests were designed with a new liveness-based tile allocator in mind -// (where the names of test cases make more sense), with the current tile -// allocator these tests all give incorrect results (which is documented by -// `CHECK-BAD`). +// This file tests some simple aspects of using liveness in the SME tile allocator. +// Note: We use -convert-scf-to-cf first as the tile allocator expects CF, but +// some of these tests are written in SCF (to make things easier to follow). -// Incorrect result! The second `move_vector_to_tile_slice` overwrites the first (which is still live). -// -// CHECK-BAD-LABEL: @constant_with_multiple_users -// CHECK-BAD: %[[ZERO_TILE:.*]] = arm_sme.zero {tile_id = 0 : i32} : vector<[4]x[4]xf32> -// CHECK-BAD: %[[INSERT_TILE_1:.*]] = arm_sme.move_vector_to_tile_slice %{{.*}} {tile_id = 0 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> -// CHECK-BAD: %[[INSERT_TILE_0:.*]] = arm_sme.move_vector_to_tile_slice %{{.*}} {tile_id = 0 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> +// CHECK-LIVE-RANGE-LABEL: @constant_with_multiple_users +// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges: +// CHECK-LIVE-RANGE: ^bb0: +// CHECK-LIVE-RANGE: S arm_sme.zero +// CHECK-LIVE-RANGE-NEXT: |S arm_sme.move_vector_to_tile_slice +// CHECK-LIVE-RANGE-NEXT: || arm_sme.move_vector_to_tile_slice +// CHECK-LIVE-RANGE-NEXT: |E test.some_use +// CHECK-LIVE-RANGE-NEXT: E test.some_use + +// CHECK-LABEL: @constant_with_multiple_users( +// CHECK-SAME: %[[VECTOR_A:.*]]: vector<[4]xf32>, %[[VECTOR_B:.*]]: vector<[4]xf32> func.func @constant_with_multiple_users(%a: vector<[4]xf32>, %b: vector<[4]xf32>, %index: index) { + // CHECK-NEXT: %[[ZERO_TILE_0:.*]] = arm_sme.zero {tile_id = 0 : i32} : vector<[4]x[4]xf32> + // CHECK-NEXT: %[[ZERO_TILE_1:.*]] = arm_sme.zero {tile_id = 1 : i32} : vector<[4]x[4]xf32> + // CHECK-NEXT: %[[INSERT_TILE_1:.*]] = arm_sme.move_vector_to_tile_slice %[[VECTOR_A]], %[[ZERO_TILE_1]], %{{.*}} {tile_id = 1 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> + // CHECK-NEXT: %[[INSERT_TILE_0:.*]] = arm_sme.move_vector_to_tile_slice %[[VECTOR_B]], %[[ZERO_TILE_0]], %{{.*}} {tile_id = 0 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> %zero = arm_sme.zero : vector<[4]x[4]xf32> %tile_a = arm_sme.move_vector_to_tile_slice %a, %zero, %index : vector<[4]xf32> into vector<[4]x[4]xf32> %tile_b = arm_sme.move_vector_to_tile_slice %b, %zero, %index : vector<[4]xf32> into vector<[4]x[4]xf32> @@ -23,12 +31,17 @@ func.func @constant_with_multiple_users(%a: vector<[4]xf32>, %b: vector<[4]xf32> // ----- -// (No tile IDs -- the current tile allocator ignores this case) +// CHECK-LIVE-RANGE-LABEL: @value_with_multiple_users +// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges: +// CHECK-LIVE-RANGE: ^bb0: +// CHECK-LIVE-RANGE-NEXT: |S arm_sme.move_vector_to_tile_slice +// CHECK-LIVE-RANGE-NEXT: || arm_sme.move_vector_to_tile_slice +// CHECK-LIVE-RANGE-NEXT: |E test.some_use +// CHECK-LIVE-RANGE-NEXT: E test.some_use -// CHECK-BAD-LABEL: @value_with_multiple_users -// CHECK-BAD-NOT: tile_id +// expected-note@below {{tile operand is: of type 'vector<[4]x[4]xf32>'}} func.func @value_with_multiple_users(%tile: vector<[4]x[4]xf32>, %a: vector<[4]xf32>, %b: vector<[4]xf32>, %index: index) { - // A future allocator should error here (as `%tile` would need to be copied). + // expected-error@below {{op tile operand allocated to different SME virtial tile (move required)}} %tile_a = arm_sme.move_vector_to_tile_slice %a, %tile, %index : vector<[4]xf32> into vector<[4]x[4]xf32> %tile_b = arm_sme.move_vector_to_tile_slice %b, %tile, %index : vector<[4]xf32> into vector<[4]x[4]xf32> "test.some_use"(%tile_a) : (vector<[4]x[4]xf32>) -> () @@ -38,12 +51,38 @@ func.func @value_with_multiple_users(%tile: vector<[4]x[4]xf32>, %a: vector<[4]x // ----- -// CHECK-BAD-LABEL: @reuse_tiles_after_initial_use +// CHECK-LIVE-RANGE-LABEL: @reuse_tiles_after_initial_use +// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges: +// CHECK-LIVE-RANGE: ^bb0: +// CHECK-LIVE-RANGE-NEXT: S arm_sme.get_tile +// CHECK-LIVE-RANGE-NEXT: |S arm_sme.get_tile +// CHECK-LIVE-RANGE-NEXT: ||S arm_sme.get_tile +// CHECK-LIVE-RANGE-NEXT: |||S arm_sme.get_tile +// CHECK-LIVE-RANGE-NEXT: |||| test.dummy +// CHECK-LIVE-RANGE-NEXT: |||| test.dummy +// CHECK-LIVE-RANGE-NEXT: |||| test.dummy +// CHECK-LIVE-RANGE-NEXT: E||| test.some_use +// CHECK-LIVE-RANGE-NEXT: E|| test.some_use +// CHECK-LIVE-RANGE-NEXT: E| test.some_use +// CHECK-LIVE-RANGE-NEXT: E test.some_use +// CHECK-LIVE-RANGE-NEXT: S arm_sme.zero +// CHECK-LIVE-RANGE-NEXT: |S arm_sme.zero +// CHECK-LIVE-RANGE-NEXT: ||S arm_sme.zero +// CHECK-LIVE-RANGE-NEXT: |||S arm_sme.zero +// CHECK-LIVE-RANGE-NEXT: |||| test.dummy +// CHECK-LIVE-RANGE-NEXT: |||| test.dummy +// CHECK-LIVE-RANGE-NEXT: |||| test.dummy +// CHECK-LIVE-RANGE-NEXT: E||| test.some_use +// CHECK-LIVE-RANGE-NEXT: E|| test.some_use +// CHECK-LIVE-RANGE-NEXT: E| test.some_use +// CHECK-LIVE-RANGE-NEXT: E test.some_use + +// CHECK-LABEL: @reuse_tiles_after_initial_use func.func @reuse_tiles_after_initial_use() { - // CHECK-BAD: arm_sme.get_tile {tile_id = 0 : i32} - // CHECK-BAD: arm_sme.get_tile {tile_id = 1 : i32} - // CHECK-BAD: arm_sme.get_tile {tile_id = 2 : i32} - // CHECK-BAD: arm_sme.get_tile {tile_id = 3 : i32} + // CHECK: arm_sme.get_tile {tile_id = 0 : i32} + // CHECK: arm_sme.get_tile {tile_id = 1 : i32} + // CHECK: arm_sme.get_tile {tile_id = 2 : i32} + // CHECK: arm_sme.get_tile {tile_id = 3 : i32} %tile_a = arm_sme.get_tile : vector<[4]x[4]xf32> %tile_b = arm_sme.get_tile : vector<[4]x[4]xf32> %tile_c = arm_sme.get_tile : vector<[4]x[4]xf32> @@ -55,19 +94,13 @@ func.func @reuse_tiles_after_initial_use() { "test.some_use"(%tile_b) : (vector<[4]x[4]xf32>) -> () "test.some_use"(%tile_c) : (vector<[4]x[4]xf32>) -> () "test.some_use"(%tile_d) : (vector<[4]x[4]xf32>) -> () - // -> Spills after the fourth tile (unnecessary): - // CHECK-BAD: arm_sme.zero {tile_id = 16 : i32} - // CHECK-BAD: arm_sme.zero {tile_id = 17 : i32} - // CHECK-BAD: arm_sme.zero {tile_id = 18 : i32} - // CHECK-BAD: arm_sme.zero {tile_id = 19 : i32} - // Unnecessary spills: - // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} + // CHECK: arm_sme.zero {tile_id = 0 : i32} + // CHECK: arm_sme.zero {tile_id = 1 : i32} + // CHECK: arm_sme.zero {tile_id = 2 : i32} + // CHECK: arm_sme.zero {tile_id = 3 : i32} %tile_1 = arm_sme.zero : vector<[4]x[4]xf32> - // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} %tile_2 = arm_sme.zero : vector<[4]x[4]xf32> - // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} %tile_3 = arm_sme.zero : vector<[4]x[4]xf32> - // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} %tile_4 = arm_sme.zero : vector<[4]x[4]xf32> "test.dummy"(): () -> () "test.dummy"(): () -> () @@ -81,16 +114,123 @@ func.func @reuse_tiles_after_initial_use() { // ----- -// Incorrect result! Both branches should yield the result via the same tile. +// CHECK-LIVE-RANGE-LABEL: @tile_live_ins +// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges: +// CHECK-LIVE-RANGE: ^bb0: +// CHECK-LIVE-RANGE-NEXT: S arm_sme.get_tile +// CHECK-LIVE-RANGE-NEXT: |S arm_sme.zero +// CHECK-LIVE-RANGE-NEXT: EE cf.br +// CHECK-LIVE-RANGE-NEXT: ^bb1: +// CHECK-LIVE-RANGE-NEXT: || test.dummy +// CHECK-LIVE-RANGE-NEXT: || test.dummy +// CHECK-LIVE-RANGE-NEXT: EE cf.br +// CHECK-LIVE-RANGE-NEXT: ^bb2: +// CHECK-LIVE-RANGE-NEXT: || test.dummy +// CHECK-LIVE-RANGE-NEXT: || test.dummy +// CHECK-LIVE-RANGE-NEXT: EE cf.br +// CHECK-LIVE-RANGE-NEXT: ^bb3: +// CHECK-LIVE-RANGE-NEXT: E| test.some_use +// CHECK-LIVE-RANGE-NEXT: E test.some_use + +// CHECK-LABEL: @tile_live_ins +func.func @tile_live_ins() +{ + // CHECK: arm_sme.get_tile {tile_id = 0 : i32} : vector<[4]x[4]xf32> + // CHECK: arm_sme.zero {tile_id = 1 : i32} : vector<[4]x[4]xf32> + %tile_1 = arm_sme.get_tile : vector<[4]x[4]xf32> + %tile_2 = arm_sme.zero : vector<[4]x[4]xf32> + cf.br ^bb1 +^bb1: + "test.dummy"(): () -> () + "test.dummy"(): () -> () + cf.br ^bb2 +^bb2: + "test.dummy"(): () -> () + "test.dummy"(): () -> () + cf.br ^bb3 +^bb3: + "test.some_use"(%tile_1) : (vector<[4]x[4]xf32>) -> () + "test.some_use"(%tile_2) : (vector<[4]x[4]xf32>) -> () + return +} + +// ----- + +// This is basically the same test as tile_live_ins but shows that the order of +// the blocks within the source does not relate to the liveness, which is based +// on successors and predecessors (not textual order). +// +// So %tile_1 is live on the path bb0 -> bb2 -> bb1 (and dies in bb1). The +// 'hole' when looking at the live range dump comes from the textual order +// (and would disappear if bb1 was moved before bb2 in the source). // -// CHECK-BAD-LABEL: @non_overlapping_branches -// CHECK-BAD: arm_sme.zero {tile_id = 0 : i32} : vector<[4]x[4]xf32> -// CHECK-BAD: arm_sme.get_tile {tile_id = 1 : i32} : vector<[4]x[4]xf32> +// When looking at the live range dump (outside of straight-line code) it +// normally makes more sense to consider blocks in isolation (and how they +// relate to the CFG). + +// CHECK-LIVE-RANGE-LABEL: @non_sequential_live_ins +// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges: +// CHECK-LIVE-RANGE: ^bb0: +// CHECK-LIVE-RANGE-NEXT: S arm_sme.get_tile +// CHECK-LIVE-RANGE-NEXT: | test.dummy +// CHECK-LIVE-RANGE-NEXT: E cf.br +// CHECK-LIVE-RANGE-NEXT: ^bb1: +// CHECK-LIVE-RANGE-NEXT: E| test.some_use +// CHECK-LIVE-RANGE-NEXT: | test.dummy +// CHECK-LIVE-RANGE-NEXT: E cf.br +// CHECK-LIVE-RANGE-NEXT: ^bb2: +// CHECK-LIVE-RANGE-NEXT: |S arm_sme.zero +// CHECK-LIVE-RANGE-NEXT: || test.dummy +// CHECK-LIVE-RANGE-NEXT: EE cf.cond_br +// CHECK-LIVE-RANGE-NEXT: ^bb3: +// CHECK-LIVE-RANGE-NEXT: | test.dummy +// CHECK-LIVE-RANGE-NEXT: E test.some_use +// CHECK-LIVE-RANGE-NEXT: func.return + +// CHECK-LABEL: @non_sequential_live_ins +func.func @non_sequential_live_ins(%cond: i1) { + // CHECK: arm_sme.get_tile {tile_id = 0 : i32} : vector<[4]x[4]xf32> + // CHECK: arm_sme.zero {tile_id = 1 : i32} : vector<[4]x[4]xf32> + %tile_1 = arm_sme.get_tile : vector<[4]x[4]xf32> + "test.dummy"(): () -> () + cf.br ^bb2 +^bb1: + "test.some_use"(%tile_1) : (vector<[4]x[4]xf32>) -> () + "test.dummy"(): () -> () + cf.br ^bb3 +^bb2: + %tile_2 = arm_sme.zero : vector<[4]x[4]xf32> + "test.dummy"(): () -> () + cf.cond_br %cond, ^bb1, ^bb3 +^bb3: + "test.dummy"(): () -> () + "test.some_use"(%tile_2) : (vector<[4]x[4]xf32>) -> () + return +} + +// ----- + +// CHECK-LIVE-RANGE-LABEL: @non_overlapping_branches +// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges: +// CHECK-LIVE-RANGE: ^bb1: +// CHECK-LIVE-RANGE-NEXT: S arm_sme.zero +// CHECK-LIVE-RANGE-NEXT: | arm_sme.copy_tile +// CHECK-LIVE-RANGE-NEXT: E cf.br +// CHECK-LIVE-RANGE-NEXT: ^bb2: +// CHECK-LIVE-RANGE-NEXT: S arm_sme.get_tile +// CHECK-LIVE-RANGE-NEXT: | arm_sme.copy_tile +// CHECK-LIVE-RANGE-NEXT: E cf.br + +// CHECK-LABEL: @non_overlapping_branches func.func @non_overlapping_branches(%cond: i1) { + // CHECK: arm_sme.zero {tile_id = 0 : i32} : vector<[4]x[4]xf32> + // CHECK: arm_sme.get_tile {tile_id = 0 : i32} : vector<[4]x[4]xf32> %tile = scf.if %cond -> vector<[4]x[4]xf32> { + // ^bb1: %zero = arm_sme.zero : vector<[4]x[4]xf32> scf.yield %zero : vector<[4]x[4]xf32> } else { + // ^bb2: %undef = arm_sme.get_tile : vector<[4]x[4]xf32> scf.yield %undef : vector<[4]x[4]xf32> } @@ -100,52 +240,65 @@ func.func @non_overlapping_branches(%cond: i1) { // ----- -// Incorrect result! Everything assigned to tile 0 (which means values that are still live are overwritten). -// -// CHECK-BAD-LABEL: @constant_loop_init_with_multiple_users -// CHECK-BAD: arm_sme.zero {tile_id = 0 : i32} : vector<[4]x[4]xf32> -// CHECK-BAD: arm_sme.move_vector_to_tile_slice {{.*}} {tile_id = 0 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> -// CHECK-BAD: arm_sme.move_vector_to_tile_slice {{.*}} {tile_id = 0 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> -func.func @constant_loop_init_with_multiple_users(%a: vector<[4]xf32>, %b: vector<[4]xf32>) { - %c0 = arith.constant 0 : index - %c1 = arith.constant 1 : index - %c10 = arith.constant 10 : index - %init = arm_sme.zero : vector<[4]x[4]xf32> - %tile_a = scf.for %i = %c0 to %c10 step %c1 iter_args(%iter = %init) -> vector<[4]x[4]xf32> { - %new_tile = arm_sme.move_vector_to_tile_slice %a, %iter, %i : vector<[4]xf32> into vector<[4]x[4]xf32> - scf.yield %new_tile : vector<[4]x[4]xf32> - } - %tile_b = scf.for %i = %c0 to %c10 step %c1 iter_args(%iter = %init) -> vector<[4]x[4]xf32> { - %new_tile = arm_sme.move_vector_to_tile_slice %a, %iter, %i : vector<[4]xf32> into vector<[4]x[4]xf32> - scf.yield %new_tile : vector<[4]x[4]xf32> +// Here %vecA and %vecB are not merged into the same live range (as they are unknown values). +// This means that %vecA and %vecB are both allocated to different tiles (which is not legal). + +// expected-note@below {{tile operand is: of type 'vector<[4]x[4]xf32>'}} +func.func @overlapping_branches(%cond: i1, %vecA: vector<[4]x[4]xf32>, %vecB: vector<[4]x[4]xf32>) { + // expected-error@below {{op tile operand allocated to different SME virtial tile (move required)}} + %tile = scf.if %cond -> vector<[4]x[4]xf32> { + scf.yield %vecA : vector<[4]x[4]xf32> + } else { + scf.yield %vecB : vector<[4]x[4]xf32> } - "test.some_use"(%tile_a) : (vector<[4]x[4]xf32>) -> () - "test.some_use"(%tile_b) : (vector<[4]x[4]xf32>) -> () + "test.some_use"(%tile) : (vector<[4]x[4]xf32>) -> () return } // ----- -// Incorrect result! Everything assigned to tile 0 (which means values that are still live are overwritten). -// -// CHECK-BAD-LABEL: @run_out_of_tiles_but_avoid_spill -// CHECK-BAD: arm_sme.zero {tile_id = 0 : i32} -// CHECK-BAD-COUNT-4: arm_sme.move_vector_to_tile_slice {{.*}} {tile_id = 0 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> +// CHECK-LIVE-RANGE-LABEL: @run_out_of_tiles_but_avoid_spill +// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges: +// CHECK-LIVE-RANGE: ^bb2: +// CHECK-LIVE-RANGE-NEXT: |S arm_sme.copy_tile +// CHECK-LIVE-RANGE-NEXT: ||S arm_sme.copy_tile +// CHECK-LIVE-RANGE-NEXT: |||S arm_sme.copy_tile +// CHECK-LIVE-RANGE-NEXT: ||||S arm_sme.copy_tile +// CHECK-LIVE-RANGE-NEXT: EEEEE cf.br + +// Note in the live ranges (above) there is five tile values, but we only have four tiles. +// There is no 'real' spill as we spill the `arm_sme.zero` but are then able to clone it +// at each of its uses. + +// CHECK-LABEL: @run_out_of_tiles_but_avoid_spill func.func @run_out_of_tiles_but_avoid_spill(%a: vector<[4]xf32>, %b: vector<[4]xf32>, %c: vector<[4]xf32>, %d: vector<[4]xf32>) { %init = arm_sme.zero : vector<[4]x[4]xf32> %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c10 = arith.constant 10 : index + // Live = %init scf.for %i = %c0 to %c10 step %c1 { + // CHECK: arm_sme.zero {tile_id = 1 : i32} + // CHECK: arm_sme.zero {tile_id = 2 : i32} + // CHECK: arm_sme.zero {tile_id = 3 : i32} + // CHECK: arm_sme.zero {tile_id = 0 : i32} %tile_a, %tile_b, %tile_c, %tile_d = scf.for %j = %c0 to %c10 step %c1 iter_args(%iter_a = %init, %iter_b = %init, %iter_c = %init, %iter_d = %init) -> (vector<[4]x[4]xf32>, vector<[4]x[4]xf32> , vector<[4]x[4]xf32> , vector<[4]x[4]xf32>) { + // ^bb2: + // CHECK: arm_sme.move_vector_to_tile_slice {{.*}} {tile_id = 1 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> + // CHECK: arm_sme.move_vector_to_tile_slice {{.*}} {tile_id = 2 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> + // CHECK: arm_sme.move_vector_to_tile_slice {{.*}} {tile_id = 3 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> + // CHECK: arm_sme.move_vector_to_tile_slice {{.*}} {tile_id = 0 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> %new_a = arm_sme.move_vector_to_tile_slice %a, %iter_a, %i : vector<[4]xf32> into vector<[4]x[4]xf32> %new_b = arm_sme.move_vector_to_tile_slice %b, %iter_b, %i : vector<[4]xf32> into vector<[4]x[4]xf32> %new_c = arm_sme.move_vector_to_tile_slice %c, %iter_c, %i : vector<[4]xf32> into vector<[4]x[4]xf32> %new_d = arm_sme.move_vector_to_tile_slice %d, %iter_d, %i : vector<[4]xf32> into vector<[4]x[4]xf32> scf.yield %new_a, %new_b, %new_c, %new_d : vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32> } + // Live = %init, %tile_a, %tile_b, %tile_c, %tile_d (out of tiles!) + // This should be resolved by duplicating the arm_sme.zero (from folding + // arm_sme.copy_tile operations inserted by the tile allocator). "test.some_use"(%tile_a) : (vector<[4]x[4]xf32>) -> () "test.some_use"(%tile_b) : (vector<[4]x[4]xf32>) -> () "test.some_use"(%tile_c) : (vector<[4]x[4]xf32>) -> () @@ -156,24 +309,48 @@ func.func @run_out_of_tiles_but_avoid_spill(%a: vector<[4]xf32>, %b: vector<[4]x // ----- -// Incorrect result! Everything other than zero assigned to tile 1 (which means values that are still live are overwritten). -// -// CHECK-BAD-LABEL: @avoidable_spill -// CHECK-BAD: arm_sme.zero {tile_id = 0 : i32} -// CHECK-BAD: arm_sme.get_tile {tile_id = 1 : i32} -// CHECK-BAD-COUNT-4: arm_sme.move_vector_to_tile_slice {{.*}} {tile_id = 1 : i32} +// We should be able to avoid spills like this, but logic handling this case is +// not implemented yet. Note tile ID >= 16 means a spill/in-memory tile. + +// CHECK-LIVE-RANGE-LABEL: @avoidable_spill +// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges: +// CHECK-LIVE-RANGE: ^bb2: +// CHECK-LIVE-RANGE-NEXT: || test.some_use +// CHECK-LIVE-RANGE-NEXT: ||S arm_sme.move_vector_to_tile_slice +// CHECK-LIVE-RANGE-NEXT: |||S arm_sme.move_vector_to_tile_slice +// CHECK-LIVE-RANGE-NEXT: ||||S arm_sme.move_vector_to_tile_slice +// CHECK-LIVE-RANGE-NEXT: |||||S arm_sme.move_vector_to_tile_slice +// CHECK-LIVE-RANGE-NEXT: ||E||| test.some_use +// CHECK-LIVE-RANGE-NEXT: || E|| test.some_use +// CHECK-LIVE-RANGE-NEXT: || E| test.some_use +// CHECK-LIVE-RANGE-NEXT: || E test.some_use +// CHECK-LIVE-RANGE-NEXT: || arith.addi +// CHECK-LIVE-RANGE-NEXT: EE cf.br + +// Note in the live ranges (above) there is two constant live-ins (first two ranges), +// which gives six overlapping live ranges (at the point where %tile_d is defined). +// The allocator currently will spill the first constant (which results in a real +// spill at it's use), however, this could be avoided by using the knowledge that +// at the first "test.some_use" there's actually only two live ranges (so we can +// fix this be duplicating the constant). + +// CHECK-LABEL: @avoidable_spill func.func @avoidable_spill(%a: vector<[4]xf32>, %b: vector<[4]xf32>, %c: vector<[4]xf32>, %d: vector<[4]xf32>) { + // CHECK: arm_sme.zero {tile_id = 16 : i32} : vector<[4]x[4]xf32> %zero = arm_sme.zero : vector<[4]x[4]xf32> %tile = arm_sme.get_tile : vector<[4]x[4]xf32> %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c10 = arith.constant 10 : index scf.for %i = %c0 to %c10 step %c1 { + // So spilled here (unnecessarily). + // The arm_sme.zero op could be moved into the loop to avoid this. "test.some_use"(%zero) : (vector<[4]x[4]xf32>) -> () %tile_a = arm_sme.move_vector_to_tile_slice %a, %tile, %c0 : vector<[4]xf32> into vector<[4]x[4]xf32> %tile_b = arm_sme.move_vector_to_tile_slice %b, %tile, %c0 : vector<[4]xf32> into vector<[4]x[4]xf32> %tile_c = arm_sme.move_vector_to_tile_slice %c, %tile, %c0 : vector<[4]xf32> into vector<[4]x[4]xf32> %tile_d = arm_sme.move_vector_to_tile_slice %d, %tile, %c0 : vector<[4]xf32> into vector<[4]x[4]xf32> + // %zero is still live here (due the the backedge) "test.some_use"(%tile_a) : (vector<[4]x[4]xf32>) -> () "test.some_use"(%tile_b) : (vector<[4]x[4]xf32>) -> () "test.some_use"(%tile_c) : (vector<[4]x[4]xf32>) -> () @@ -181,3 +358,75 @@ func.func @avoidable_spill(%a: vector<[4]xf32>, %b: vector<[4]xf32>, %c: vector< } return } + +// ----- + +// This test is a follow up to the test of the same name in `tile-allocation-copies.mlir`. +// This shows the live ranges (which are why we need to split the conditional branch). + +// CHECK-LIVE-RANGE-LABEL: @cond_branch_with_backedge +// CHECK-LIVE-RANGE: ^bb1: +// CHECK-LIVE-RANGE--NEXT: ||| | arith.cmpi +// CHECK-LIVE-RANGE--NEXT: EEE E cf.cond_br +// +// CHECK-LIVE-RANGE--NEXT: ^[[BB3_COPIES:[[:alnum:]]+]]: +// CHECK-LIVE-RANGE--NEXT: ||| ES arm_sme.copy_tile +// CHECK-LIVE-RANGE--NEXT: E|| |S arm_sme.copy_tile +// CHECK-LIVE-RANGE--NEXT: E| ||S arm_sme.copy_tile +// CHECK-LIVE-RANGE--NEXT: E |||S arm_sme.copy_tile +// CHECK-LIVE-RANGE--NEXT: EEEE cf.br +// +// It is important to note that the first three live ranges in ^bb1 do not end +// at the `cf.cond_br` they are live-out via the backedge bb1 -> bb2 -> bb1. +// This means that if we placed the `arm_sme.tile_copies` before the `cf.cond_br` +// then those live ranges would not end at the copies, resulting in unwanted +// overlapping live ranges (and hence tile spills). +// +// With the conditional branch split and the copies placed in the BB3_COPIES +// block the first three live ranges end at the copy operations (as the +// BB3_COPIES block is on the path out of the loop and has no backedge). This +// means there is no overlaps and the live ranges all merge, as shown below. +// +// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges: +// CHECK-LIVE-RANGE: ^bb1: +// CHECK-LIVE-RANGE--NEXT: |||| arith.cmpi +// CHECK-LIVE-RANGE--NEXT: EEEE cf.cond_br +// +// CHECK-LIVE-RANGE--NEXT: ^[[BB3_COPIES]]: +// CHECK-LIVE-RANGE--NEXT: |||| arm_sme.copy_tile +// CHECK-LIVE-RANGE--NEXT: |||| arm_sme.copy_tile +// CHECK-LIVE-RANGE--NEXT: |||| arm_sme.copy_tile +// CHECK-LIVE-RANGE--NEXT: |||| arm_sme.copy_tile +// CHECK-LIVE-RANGE--NEXT: EEEE cf.br + +// CHECK-LABEL: @cond_branch_with_backedge +// CHECK-NOT: tile_id = 16 +// CHECK: arm_sme.get_tile {tile_id = 0 : i32} : vector<[4]x[4]xf32> +// CHECK: arm_sme.get_tile {tile_id = 1 : i32} : vector<[4]x[4]xf32> +// CHECK: arm_sme.get_tile {tile_id = 2 : i32} : vector<[4]x[4]xf32> +// CHECK: arm_sme.get_tile {tile_id = 3 : i32} : vector<[4]x[4]xf32> +// CHECK: arm_sme.move_vector_to_tile_slice {{.*}} {tile_id = 0 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32> +// CHECK-NOT tile_id = 16 +func.func @cond_branch_with_backedge(%slice: vector<[4]xf32>) { + %tileA = arm_sme.get_tile : vector<[4]x[4]xf32> + %tileB = arm_sme.get_tile : vector<[4]x[4]xf32> + %tileC = arm_sme.get_tile : vector<[4]x[4]xf32> + %tileD = arm_sme.get_tile : vector<[4]x[4]xf32> + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c10 = arith.constant 10 : index + // Live here: %tileA, %tileB, %tileC, %tileD + cf.br ^bb1(%c0, %tileA : index, vector<[4]x[4]xf32>) +^bb1(%currentIndex: index, %iterTile: vector<[4]x[4]xf32>): + %continueLoop = arith.cmpi slt, %currentIndex, %c10 : index + // Live here: %iterTile, %tileB, %tileC, %tileD + cf.cond_br %continueLoop, ^bb2, ^bb3(%iterTile, %tileB, %tileC, %tileD : vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>) +^bb2: + // Live here: %iterTile, %tileB, %tileC, %tileD + %nextTile = arm_sme.move_vector_to_tile_slice %slice, %iterTile, %currentIndex : vector<[4]xf32> into vector<[4]x[4]xf32> + %nextIndex = arith.addi %currentIndex, %c1 : index + cf.br ^bb1(%nextIndex, %nextTile : index, vector<[4]x[4]xf32>) +^bb3(%finalTileA: vector<[4]x[4]xf32>, %finalTileB: vector<[4]x[4]xf32>, %finalTileC: vector<[4]x[4]xf32>, %finalTileD: vector<[4]x[4]xf32>): + // Live here: %finalTileA, %finalTileB, %finalTileC, %finalTileD + return +} diff --git a/mlir/test/Dialect/ArmSME/tile-allocation-spills-with-mixed-tile-types.mlir b/mlir/test/Dialect/ArmSME/tile-allocation-spills-with-mixed-tile-types.mlir new file mode 100644 index 000000000000..27757e29c1e2 --- /dev/null +++ b/mlir/test/Dialect/ArmSME/tile-allocation-spills-with-mixed-tile-types.mlir @@ -0,0 +1,38 @@ + +// RUN: mlir-opt %s -test-arm-sme-tile-allocation -split-input-file | FileCheck %s + +// CHECK-LABEL: @always_spill_larger_or_equal_tile_type +// CHECK: arm_sme.zero {tile_id = 0 : i32} : vector<[4]x[4]xf32> +// CHECK: arm_sme.zero {tile_id = 1 : i32} : vector<[4]x[4]xf32> +// CHECK: arm_sme.zero {tile_id = 2 : i32} : vector<[4]x[4]xf32> +// CHECK: arm_sme.zero {tile_id = 3 : i32} : vector<[4]x[4]xf32> +// CHECK: arm_sme.tile_load {{.*}} {tile_id = 16 : i32} : memref, vector<[8]x[8]xf16> +func.func @always_spill_larger_or_equal_tile_type(%memref: memref) -> (vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[8]x[8]xf16>) { + %c0 = arith.constant 0 : index + %0 = arm_sme.zero : vector<[4]x[4]xf32> + %1 = arm_sme.zero : vector<[4]x[4]xf32> + %2 = arm_sme.zero : vector<[4]x[4]xf32> + %3 = arm_sme.zero : vector<[4]x[4]xf32> + // The load will be spilled (even though the zero's are 'trivial' spills) as a single `f32` tile would not fit the load. + %load = arm_sme.tile_load %memref[%c0, %c0] : memref, vector<[8]x[8]xf16> + return %0, %1, %2, %3, %load : vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[8]x[8]xf16> +} + +// ----- + +// CHECK-LABEL: @spill_larger_tile_type +// CHECK: arm_sme.zero {tile_id = 16 : i32} : vector<[16]x[16]xi8> +// CHECK: arm_sme.tile_load {{.*}} {tile_id = 0 : i32} : memref, vector<[4]x[4]xf32> +// CHECK: arm_sme.tile_load {{.*}} {tile_id = 1 : i32} : memref, vector<[4]x[4]xf32> +// CHECK: arm_sme.tile_load {{.*}} {tile_id = 2 : i32} : memref, vector<[4]x[4]xf32> +// CHECK: arm_sme.tile_load {{.*}} {tile_id = 3 : i32} : memref, vector<[4]x[4]xf32> +func.func @spill_larger_tile_type(%memref: memref) -> (vector<[16]x[16]xi8>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>) { + %c0 = arith.constant 0 : index + // Spilling the `arm_sme.zero` should free up space for all four f32 tiles. + %0 = arm_sme.zero : vector<[16]x[16]xi8> + %1 = arm_sme.tile_load %memref[%c0, %c0] : memref, vector<[4]x[4]xf32> + %2 = arm_sme.tile_load %memref[%c0, %c0] : memref, vector<[4]x[4]xf32> + %3 = arm_sme.tile_load %memref[%c0, %c0] : memref, vector<[4]x[4]xf32> + %4 = arm_sme.tile_load %memref[%c0, %c0] : memref, vector<[4]x[4]xf32> + return %0, %1, %2, %3, %4 : vector<[16]x[16]xi8>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32>, vector<[4]x[4]xf32> +} diff --git a/mlir/test/Dialect/ArmSME/tile-zero-masks.mlir b/mlir/test/Dialect/ArmSME/tile-zero-masks.mlir index cac2dcc24d10..ca339be5fb56 100644 --- a/mlir/test/Dialect/ArmSME/tile-zero-masks.mlir +++ b/mlir/test/Dialect/ArmSME/tile-zero-masks.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt %s -allocate-arm-sme-tiles -convert-arm-sme-to-llvm -canonicalize | FileCheck %s +// RUN: mlir-opt %s --pass-pipeline="builtin.module(func.func(convert-arm-sme-to-llvm,canonicalize))" | FileCheck %s // This test verifies the tile mask operand of the zero intrinsic zeroes // the correct tiles. Both integer and floating-point datatypes are checked. diff --git a/mlir/test/Integration/Dialect/Linalg/CPU/ArmSME/use-too-many-tiles.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/ArmSME/use-too-many-tiles.mlir index 588b44a36c29..14d9712e971a 100644 --- a/mlir/test/Integration/Dialect/Linalg/CPU/ArmSME/use-too-many-tiles.mlir +++ b/mlir/test/Integration/Dialect/Linalg/CPU/ArmSME/use-too-many-tiles.mlir @@ -13,26 +13,29 @@ /// performance (hence the warning). func.func @use_too_many_tiles(%a: memref, %b: memref, %c: memref) { %c0 = arith.constant 0 : index + // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} %tile_a = arith.constant dense<0> : vector<[8]x[8]xi16> + // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} %tile_b = arith.constant dense<1> : vector<[8]x[8]xi16> // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} %tile_c = arm_sme.tile_load %a[%c0, %c0] : memref, vector<[8]x[8]xi16> - // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} %tile_d = arm_sme.tile_load %b[%c0, %c0] : memref, vector<[8]x[8]xi16> - // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} %tile_e = arm_sme.tile_load %c[%c0, %c0] : memref, vector<[8]x[8]xi16> // CHECK-LABEL: tile_a: // CHECK-COUNT-8: ( 0, 0, 0, 0, 0, 0, 0, 0 vector.print str "tile_a:\n" + // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} vector.print %tile_a : vector<[8]x[8]xi16> // CHECK-LABEL: tile_b: // CHECK-COUNT-8: ( 1, 1, 1, 1, 1, 1, 1, 1 vector.print str "tile_b:\n" + // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} vector.print %tile_b : vector<[8]x[8]xi16> // CHECK-LABEL: tile_c: // CHECK-COUNT-8: ( 2, 2, 2, 2, 2, 2, 2, 2 vector.print str "tile_c:\n" + // expected-warning @below {{failed to allocate SME virtual tile to operation, all tile operations will go through memory, expect degraded performance}} vector.print %tile_c : vector<[8]x[8]xi16> // CHECK-LABEL: tile_d: // CHECK-COUNT-8: ( 3, 3, 3, 3, 3, 3, 3, 3 diff --git a/mlir/test/Integration/Dialect/Vector/CPU/ArmSME/Emulated/test-setArmSVLBits.mlir b/mlir/test/Integration/Dialect/Vector/CPU/ArmSME/Emulated/test-setArmSVLBits.mlir index 1794564a6a72..0648e771b889 100644 --- a/mlir/test/Integration/Dialect/Vector/CPU/ArmSME/Emulated/test-setArmSVLBits.mlir +++ b/mlir/test/Integration/Dialect/Vector/CPU/ArmSME/Emulated/test-setArmSVLBits.mlir @@ -1,5 +1,6 @@ // DEFINE: %{entry_point} = main -// DEFINE: %{compile} = mlir-opt %s -convert-arm-sme-to-llvm -test-lower-to-llvm +// DEFINE: %{compile} = mlir-opt %s \ +// DEFINE: --pass-pipeline="builtin.module(func.func(convert-arm-sme-to-llvm),test-lower-to-llvm)" // DEFINE: %{run} = %mcr_aarch64_cmd \ // DEFINE: -march=aarch64 -mattr=+sve,+sme \ // DEFINE: -e %{entry_point} -entry-point-result=void \ diff --git a/mlir/test/lib/Dialect/ArmSME/CMakeLists.txt b/mlir/test/lib/Dialect/ArmSME/CMakeLists.txt index e942c7b8ac05..cdd8afe14142 100644 --- a/mlir/test/lib/Dialect/ArmSME/CMakeLists.txt +++ b/mlir/test/lib/Dialect/ArmSME/CMakeLists.txt @@ -15,4 +15,5 @@ add_mlir_library(MLIRArmSMETestPasses MLIRTransforms MLIRVectorToArmSME MLIRVectorToSCF + MLIRSCFToControlFlow ) diff --git a/mlir/test/lib/Dialect/ArmSME/TestLowerToArmSME.cpp b/mlir/test/lib/Dialect/ArmSME/TestLowerToArmSME.cpp index 48d4a5859f8a..d3dabaf200fd 100644 --- a/mlir/test/lib/Dialect/ArmSME/TestLowerToArmSME.cpp +++ b/mlir/test/lib/Dialect/ArmSME/TestLowerToArmSME.cpp @@ -14,10 +14,12 @@ #include "mlir/Conversion/ArithToArmSME/ArithToArmSME.h" #include "mlir/Conversion/ArmSMEToLLVM/ArmSMEToLLVM.h" #include "mlir/Conversion/ArmSMEToSCF/ArmSMEToSCF.h" +#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h" #include "mlir/Conversion/VectorToArmSME/VectorToArmSME.h" #include "mlir/Conversion/VectorToSCF/VectorToSCF.h" #include "mlir/Dialect/ArmSME/Transforms/Passes.h" #include "mlir/Dialect/ArmSVE/Transforms/Passes.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/DialectRegistry.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" @@ -34,6 +36,10 @@ struct TestLowerToArmSMEOptions llvm::cl::desc("Fuse outer product operations via " "'-arm-sme-outer-product-fusion' pass"), llvm::cl::init(true)}; + PassOptions::Option dumpTileLiveRanges{ + *this, "dump-tile-live-ranges", + llvm::cl::desc("Dump the live ranges of SME tiles (for debugging)"), + llvm::cl::init(false)}; }; void buildTestLowerToArmSME(OpPassManager &pm, @@ -65,20 +71,17 @@ void buildTestLowerToArmSME(OpPassManager &pm, pm.addPass(createConvertVectorToSCFPass( VectorTransferToSCFOptions().enableFullUnroll())); - // Allocate tiles for ArmSME operations. - // - // Later passes may create further ArmSME ops that implement the - // ArmSMETileOpInterface, but tiles are allocated for root operations, - // all of which should now exist. - pm.addPass(arm_sme::createTileAllocationPass()); - // Enable streaming-mode and ZA. pm.addPass(arm_sme::createEnableArmStreamingPass( arm_sme::ArmStreamingMode::StreamingLocally, arm_sme::ArmZaMode::NewZA, /*onlyIfRequiredByOps=*/true)); + // Convert SCF to CF (required for ArmSME tile allocation). + pm.addPass(createConvertSCFToCFPass()); + // Convert ArmSME to LLVM. - pm.addPass(createConvertArmSMEToLLVMPass()); + pm.addNestedPass( + createConvertArmSMEToLLVMPass(options.dumpTileLiveRanges)); // Sprinkle some cleanups. pm.addPass(createCanonicalizerPass()); -- GitLab From 2b15c4a62be6ceab124cb2505ae8dc6a98ba6e7d Mon Sep 17 00:00:00 2001 From: Graham Hunter Date: Tue, 14 May 2024 15:16:42 +0100 Subject: [PATCH 235/578] [AArch64] Postcommit fixes for histogram intrinsic (#92095) A buildbot with expensive checks enabled flagged some problems with my patch. There was also a post-commit nit on the langref changes. --- llvm/docs/LangRef.rst | 4 ++-- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 14 ++++++++------ .../Transforms/Scalar/ScalarizeMaskedMemIntrin.cpp | 2 +- .../CodeGen/AArch64/neon-scalarize-histogram.ll | 2 +- llvm/test/CodeGen/AArch64/sve2-histcnt.ll | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 06809f8bf445..e2f4d8bfcaee 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -19143,8 +19143,8 @@ will be on any later loop iteration. This intrinsic will only return 0 if the input count is also 0. A non-zero input count will produce a non-zero result. -'``llvm.experimental.vector.histogram.*``' Intrinsics -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +'``llvm.experimental.vector.histogram.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ These intrinsics are overloaded. diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 33cc8ffaf85d..f6d80f78910c 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -27395,9 +27395,11 @@ SDValue AArch64TargetLowering::LowerVECTOR_HISTOGRAM(SDValue Op, SDValue IncSplat = DAG.getSplatVector(MemVT, DL, Inc); SDValue Ops[] = {Chain, PassThru, Mask, Ptr, Index, Scale}; - // Set the MMO to load only, rather than load|store. - MachineMemOperand *GMMO = HG->getMemOperand(); - GMMO->setFlags(MachineMemOperand::MOLoad); + MachineMemOperand *MMO = HG->getMemOperand(); + // Create an MMO for the gather, without load|store flags. + MachineMemOperand *GMMO = DAG.getMachineFunction().getMachineMemOperand( + MMO->getPointerInfo(), MachineMemOperand::MOLoad, MMO->getSize(), + MMO->getAlign(), MMO->getAAInfo()); ISD::MemIndexType IndexType = HG->getIndexType(); SDValue Gather = DAG.getMaskedGather(DAG.getVTList(MemVT, MVT::Other), MemVT, DL, Ops, @@ -27412,10 +27414,10 @@ SDValue AArch64TargetLowering::LowerVECTOR_HISTOGRAM(SDValue Op, SDValue Mul = DAG.getNode(ISD::MUL, DL, MemVT, HistCnt, IncSplat); SDValue Add = DAG.getNode(ISD::ADD, DL, MemVT, Gather, Mul); - // Create a new MMO for the scatter. + // Create an MMO for the scatter, without load|store flags. MachineMemOperand *SMMO = DAG.getMachineFunction().getMachineMemOperand( - GMMO->getPointerInfo(), MachineMemOperand::MOStore, GMMO->getSize(), - GMMO->getAlign(), GMMO->getAAInfo()); + MMO->getPointerInfo(), MachineMemOperand::MOStore, MMO->getSize(), + MMO->getAlign(), MMO->getAAInfo()); SDValue ScatterOps[] = {GChain, Add, Mask, Ptr, Index, Scale}; SDValue Scatter = DAG.getMaskedScatter(DAG.getVTList(MVT::Other), MemVT, DL, diff --git a/llvm/lib/Transforms/Scalar/ScalarizeMaskedMemIntrin.cpp b/llvm/lib/Transforms/Scalar/ScalarizeMaskedMemIntrin.cpp index de80fa2c0502..8f820a3bba2b 100644 --- a/llvm/lib/Transforms/Scalar/ScalarizeMaskedMemIntrin.cpp +++ b/llvm/lib/Transforms/Scalar/ScalarizeMaskedMemIntrin.cpp @@ -1006,7 +1006,7 @@ static bool optimizeCallInst(CallInst *CI, bool &ModifiedDT, CI->getArgOperand(1)->getType())) return false; scalarizeMaskedVectorHistogram(DL, CI, DTU, ModifiedDT); - break; + return true; case Intrinsic::masked_load: // Scalarize unsupported vector masked load if (TTI.isLegalMaskedLoad( diff --git a/llvm/test/CodeGen/AArch64/neon-scalarize-histogram.ll b/llvm/test/CodeGen/AArch64/neon-scalarize-histogram.ll index 45f1429a810a..e59d9098a30d 100644 --- a/llvm/test/CodeGen/AArch64/neon-scalarize-histogram.ll +++ b/llvm/test/CodeGen/AArch64/neon-scalarize-histogram.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 -; RUN: llc -mtriple=aarch64 < %s -o - | FileCheck %s +; RUN: llc -mtriple=aarch64 -verify-machineinstrs < %s -o - | FileCheck %s ;; This test exercises the default lowering of the histogram to scalarized code. diff --git a/llvm/test/CodeGen/AArch64/sve2-histcnt.ll b/llvm/test/CodeGen/AArch64/sve2-histcnt.ll index 557a42116cdb..db164e288abd 100644 --- a/llvm/test/CodeGen/AArch64/sve2-histcnt.ll +++ b/llvm/test/CodeGen/AArch64/sve2-histcnt.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 -; RUN: llc -mtriple=aarch64 < %s -o - | FileCheck %s +; RUN: llc -mtriple=aarch64 -verify-machineinstrs < %s -o - | FileCheck %s define void @histogram_i64( %buckets, i64 %inc, %mask) #0 { ; CHECK-LABEL: histogram_i64: -- GitLab From d9db2664994ff672f50d7fd0117477935dac04f1 Mon Sep 17 00:00:00 2001 From: Jake Egan Date: Tue, 14 May 2024 10:32:30 -0400 Subject: [PATCH 236/578] [PowerPC][test] Catch any exception when retrieving git revision (#92004) This makes the `vc-rev-enabled` feature unsupported if we fail to retrieve the git revision for any reason, such as if git is not installed. --- llvm/test/CodeGen/PowerPC/lit.local.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/CodeGen/PowerPC/lit.local.cfg b/llvm/test/CodeGen/PowerPC/lit.local.cfg index 4cc802afef4a..e56ce48eff40 100644 --- a/llvm/test/CodeGen/PowerPC/lit.local.cfg +++ b/llvm/test/CodeGen/PowerPC/lit.local.cfg @@ -9,8 +9,8 @@ def get_revision(repo_path): cmd = ['git', '-C', repo_path, 'rev-parse', 'HEAD'] try: return subprocess.run(cmd, stdout=subprocess.PIPE, check=True).stdout.decode() - except subprocess.CalledProcessError: - print("An error occurred retrieving the git revision.") + except Exception as e: + print("An error occurred retrieving the git revision:", e) return None if config.have_vc_rev: -- GitLab From 8070b2defa6df1f1a3f3d4ed4989047b0e1bb639 Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Tue, 14 May 2024 22:44:01 +0800 Subject: [PATCH 237/578] [Clang] Retain the angle loci for invented template parameters of constraints (#92104) Clangd uses it to determine whether the argument is within the selection range. Fixes https://github.com/clangd/clangd/issues/2033 --- .../clangd/unittests/SelectionTests.cpp | 6 ++++++ clang/lib/Sema/SemaType.cpp | 3 ++- clang/test/AST/ast-dump-concepts.cpp | 13 +++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp index db516a1f62a3..aaaf758e7223 100644 --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -589,6 +589,12 @@ TEST(SelectionTest, CommonAncestor) { auto x = [[ns::^C]]; )cpp", "ConceptReference"}, + {R"cpp( + template + concept D = true; + template void g(D<[[^T]]> auto abc) {} + )cpp", + "TemplateTypeParmTypeLoc"}, }; for (const Case &C : Cases) { diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index d65fafc8cf4f..eb67546d048a 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3099,7 +3099,8 @@ InventTemplateParameter(TypeProcessingState &state, QualType T, // The 'auto' appears in the decl-specifiers; we've not finished forming // TypeSourceInfo for it yet. TemplateIdAnnotation *TemplateId = D.getDeclSpec().getRepAsTemplateId(); - TemplateArgumentListInfo TemplateArgsInfo; + TemplateArgumentListInfo TemplateArgsInfo(TemplateId->LAngleLoc, + TemplateId->RAngleLoc); bool Invalid = false; if (TemplateId->LAngleLoc.isValid()) { ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), diff --git a/clang/test/AST/ast-dump-concepts.cpp b/clang/test/AST/ast-dump-concepts.cpp index 5bb174e3548e..a5e0673c241e 100644 --- a/clang/test/AST/ast-dump-concepts.cpp +++ b/clang/test/AST/ast-dump-concepts.cpp @@ -107,3 +107,16 @@ auto FooFunc(C auto V) -> C decltype(auto) { } } + +namespace constraint_auto_params { + +template +concept C = true; + +template +void g(C auto Foo) {} + +// CHECK: TemplateTypeParmDecl {{.*}} depth 0 index 1 Foo:auto +// CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} + +} -- GitLab From a4accdfe0c9415ad1bd3dac7dda8cb8bbcd1be2f Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Tue, 14 May 2024 10:53:53 -0400 Subject: [PATCH 238/578] [Support] Add option to print SMDiagnostic into a buffer without the filename and location info (#92050) --- llvm/include/llvm/Support/SourceMgr.h | 2 +- llvm/lib/Support/SourceMgr.cpp | 4 ++-- llvm/unittests/Support/SourceMgrTest.cpp | 11 +++++++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/Support/SourceMgr.h b/llvm/include/llvm/Support/SourceMgr.h index 6f5bee7f8cc2..7a4b6de1162d 100644 --- a/llvm/include/llvm/Support/SourceMgr.h +++ b/llvm/include/llvm/Support/SourceMgr.h @@ -317,7 +317,7 @@ public: ArrayRef getFixIts() const { return FixIts; } void print(const char *ProgName, raw_ostream &S, bool ShowColors = true, - bool ShowKindLabel = true) const; + bool ShowKindLabel = true, bool ShowLocation = true) const; }; } // end namespace llvm diff --git a/llvm/lib/Support/SourceMgr.cpp b/llvm/lib/Support/SourceMgr.cpp index ebeff87c3954..6eaa8783a531 100644 --- a/llvm/lib/Support/SourceMgr.cpp +++ b/llvm/lib/Support/SourceMgr.cpp @@ -482,7 +482,7 @@ static void printSourceLine(raw_ostream &S, StringRef LineContents) { static bool isNonASCII(char c) { return c & 0x80; } void SMDiagnostic::print(const char *ProgName, raw_ostream &OS, bool ShowColors, - bool ShowKindLabel) const { + bool ShowKindLabel, bool ShowLocation) const { ColorMode Mode = ShowColors ? ColorMode::Auto : ColorMode::Disable; { @@ -491,7 +491,7 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &OS, bool ShowColors, if (ProgName && ProgName[0]) S << ProgName << ": "; - if (!Filename.empty()) { + if (ShowLocation && !Filename.empty()) { if (Filename == "-") S << ""; else diff --git a/llvm/unittests/Support/SourceMgrTest.cpp b/llvm/unittests/Support/SourceMgrTest.cpp index cbd17ff47689..75a0cfe35aaf 100644 --- a/llvm/unittests/Support/SourceMgrTest.cpp +++ b/llvm/unittests/Support/SourceMgrTest.cpp @@ -532,3 +532,14 @@ TEST_F(SourceMgrTest, FixitForTab) { Output); } +TEST_F(SourceMgrTest, PrintWithoutLoc) { + raw_string_ostream OS(Output); + auto Diag = + llvm::SMDiagnostic("file.in", llvm::SourceMgr::DK_Error, "message"); + Diag.print(nullptr, OS); + OS.flush(); + EXPECT_EQ("file.in: error: message\n", Output); + Output.clear(); + Diag.print(nullptr, OS, false, false, false); + EXPECT_EQ("message\n", Output); +} -- GitLab From e08f1fda7508138d408cd61608bcbf30f8c3bb4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= Date: Tue, 14 May 2024 17:00:40 +0200 Subject: [PATCH 239/578] [clang][SPIR-V] Always add convergence intrinsics (#88918) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #80680 added bits in the codegen to lazily add convergence intrinsics when required. This logic relied on the LoopStack. The issue is when parsing the condition, the loopstack doesn't yet reflect the correct values, as expected since we are not yet in the loop. However, convergence tokens should sometimes already be available. The solution which seemed the simplest is to greedily generate the tokens when we generate SPIR-V. Fixes #88144 --------- Signed-off-by: Nathan Gauër --- clang/lib/CodeGen/CGBuiltin.cpp | 88 +------------ clang/lib/CodeGen/CGCall.cpp | 5 +- clang/lib/CodeGen/CGStmt.cpp | 93 ++++++++++++++ clang/lib/CodeGen/CodeGenFunction.cpp | 9 ++ clang/lib/CodeGen/CodeGenFunction.h | 9 +- clang/lib/CodeGen/CodeGenModule.h | 8 ++ .../builtins/RWBuffer-constructor.hlsl | 1 - clang/test/CodeGenHLSL/builtins/lerp.hlsl | 82 ++++++------ clang/test/CodeGenHLSL/builtins/mad.hlsl | 104 +++++++++++---- .../CodeGenHLSL/convergence/do.while.hlsl | 90 +++++++++++++ clang/test/CodeGenHLSL/convergence/for.hlsl | 121 ++++++++++++++++++ clang/test/CodeGenHLSL/convergence/while.hlsl | 119 +++++++++++++++++ 12 files changed, 580 insertions(+), 149 deletions(-) create mode 100644 clang/test/CodeGenHLSL/convergence/do.while.hlsl create mode 100644 clang/test/CodeGenHLSL/convergence/for.hlsl create mode 100644 clang/test/CodeGenHLSL/convergence/while.hlsl diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f9ee93049b12..e251091c6ce3 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -1141,91 +1141,8 @@ struct BitTest { static BitTest decodeBitTestBuiltin(unsigned BuiltinID); }; -// Returns the first convergence entry/loop/anchor instruction found in |BB|. -// std::nullptr otherwise. -llvm::IntrinsicInst *getConvergenceToken(llvm::BasicBlock *BB) { - for (auto &I : *BB) { - auto *II = dyn_cast(&I); - if (II && isConvergenceControlIntrinsic(II->getIntrinsicID())) - return II; - } - return nullptr; -} - } // namespace -llvm::CallBase * -CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input, - llvm::Value *ParentToken) { - llvm::Value *bundleArgs[] = {ParentToken}; - llvm::OperandBundleDef OB("convergencectrl", bundleArgs); - auto Output = llvm::CallBase::addOperandBundle( - Input, llvm::LLVMContext::OB_convergencectrl, OB, Input); - Input->replaceAllUsesWith(Output); - Input->eraseFromParent(); - return Output; -} - -llvm::IntrinsicInst * -CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB, - llvm::Value *ParentToken) { - CGBuilderTy::InsertPoint IP = Builder.saveIP(); - Builder.SetInsertPoint(&BB->front()); - auto CB = Builder.CreateIntrinsic( - llvm::Intrinsic::experimental_convergence_loop, {}, {}); - Builder.restoreIP(IP); - - auto I = addConvergenceControlToken(CB, ParentToken); - return cast(I); -} - -llvm::IntrinsicInst * -CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) { - auto *BB = &F->getEntryBlock(); - auto *token = getConvergenceToken(BB); - if (token) - return token; - - // Adding a convergence token requires the function to be marked as - // convergent. - F->setConvergent(); - - CGBuilderTy::InsertPoint IP = Builder.saveIP(); - Builder.SetInsertPoint(&BB->front()); - auto I = Builder.CreateIntrinsic( - llvm::Intrinsic::experimental_convergence_entry, {}, {}); - assert(isa(I)); - Builder.restoreIP(IP); - - return cast(I); -} - -llvm::IntrinsicInst * -CodeGenFunction::getOrEmitConvergenceLoopToken(const LoopInfo *LI) { - assert(LI != nullptr); - - auto *token = getConvergenceToken(LI->getHeader()); - if (token) - return token; - - llvm::IntrinsicInst *PII = - LI->getParent() - ? emitConvergenceLoopToken( - LI->getHeader(), getOrEmitConvergenceLoopToken(LI->getParent())) - : getOrEmitConvergenceEntryToken(LI->getHeader()->getParent()); - - return emitConvergenceLoopToken(LI->getHeader(), PII); -} - -llvm::CallBase * -CodeGenFunction::addControlledConvergenceToken(llvm::CallBase *Input) { - llvm::Value *ParentToken = - LoopStack.hasInfo() - ? getOrEmitConvergenceLoopToken(&LoopStack.getInfo()) - : getOrEmitConvergenceEntryToken(Input->getFunction()); - return addConvergenceControlToken(Input, ParentToken); -} - BitTest BitTest::decodeBitTestBuiltin(unsigned BuiltinID) { switch (BuiltinID) { // Main portable variants. @@ -18402,12 +18319,9 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, ArrayRef{Op0}, nullptr, "dx.rsqrt"); } case Builtin::BI__builtin_hlsl_wave_get_lane_index: { - auto *CI = EmitRuntimeCall(CGM.CreateRuntimeFunction( + return EmitRuntimeCall(CGM.CreateRuntimeFunction( llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", {}, false, true)); - if (getTarget().getTriple().isSPIRVLogical()) - CI = dyn_cast(addControlledConvergenceToken(CI)); - return CI; } } return nullptr; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 0c7eef59db53..1b4ca2a8b2fe 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4830,6 +4830,9 @@ llvm::CallInst *CodeGenFunction::EmitRuntimeCall(llvm::FunctionCallee callee, llvm::CallInst *call = Builder.CreateCall( callee, args, getBundlesForFunclet(callee.getCallee()), name); call->setCallingConv(getRuntimeCC()); + + if (CGM.shouldEmitConvergenceTokens() && call->isConvergent()) + return addControlledConvergenceToken(call); return call; } @@ -5730,7 +5733,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (!CI->getType()->isVoidTy()) CI->setName("call"); - if (getTarget().getTriple().isSPIRVLogical() && CI->isConvergent()) + if (CGM.shouldEmitConvergenceTokens() && CI->isConvergent()) CI = addControlledConvergenceToken(CI); // Update largest vector width from the return type. diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 479945e3b4cb..36776846cd44 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -978,6 +978,10 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S, JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond"); EmitBlock(LoopHeader.getBlock()); + if (CGM.shouldEmitConvergenceTokens()) + ConvergenceTokenStack.push_back(emitConvergenceLoopToken( + LoopHeader.getBlock(), ConvergenceTokenStack.back())); + // Create an exit block for when the condition fails, which will // also become the break target. JumpDest LoopExit = getJumpDestInCurrentScope("while.end"); @@ -1079,6 +1083,9 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S, // block. if (llvm::EnableSingleByteCoverage) incrementProfileCounter(&S); + + if (CGM.shouldEmitConvergenceTokens()) + ConvergenceTokenStack.pop_back(); } void CodeGenFunction::EmitDoStmt(const DoStmt &S, @@ -1098,6 +1105,11 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S, EmitBlockWithFallThrough(LoopBody, S.getBody()); else EmitBlockWithFallThrough(LoopBody, &S); + + if (CGM.shouldEmitConvergenceTokens()) + ConvergenceTokenStack.push_back( + emitConvergenceLoopToken(LoopBody, ConvergenceTokenStack.back())); + { RunCleanupsScope BodyScope(*this); EmitStmt(S.getBody()); @@ -1151,6 +1163,9 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S, // block. if (llvm::EnableSingleByteCoverage) incrementProfileCounter(&S); + + if (CGM.shouldEmitConvergenceTokens()) + ConvergenceTokenStack.pop_back(); } void CodeGenFunction::EmitForStmt(const ForStmt &S, @@ -1170,6 +1185,10 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S, llvm::BasicBlock *CondBlock = CondDest.getBlock(); EmitBlock(CondBlock); + if (CGM.shouldEmitConvergenceTokens()) + ConvergenceTokenStack.push_back( + emitConvergenceLoopToken(CondBlock, ConvergenceTokenStack.back())); + const SourceRange &R = S.getSourceRange(); LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), ForAttrs, SourceLocToDebugLoc(R.getBegin()), @@ -1279,6 +1298,9 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S, // block. if (llvm::EnableSingleByteCoverage) incrementProfileCounter(&S); + + if (CGM.shouldEmitConvergenceTokens()) + ConvergenceTokenStack.pop_back(); } void @@ -1301,6 +1323,10 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S, llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); EmitBlock(CondBlock); + if (CGM.shouldEmitConvergenceTokens()) + ConvergenceTokenStack.push_back( + emitConvergenceLoopToken(CondBlock, ConvergenceTokenStack.back())); + const SourceRange &R = S.getSourceRange(); LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), ForAttrs, SourceLocToDebugLoc(R.getBegin()), @@ -1369,6 +1395,9 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S, // block. if (llvm::EnableSingleByteCoverage) incrementProfileCounter(&S); + + if (CGM.shouldEmitConvergenceTokens()) + ConvergenceTokenStack.pop_back(); } void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) { @@ -3158,3 +3187,67 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) { return F; } + +namespace { +// Returns the first convergence entry/loop/anchor instruction found in |BB|. +// std::nullptr otherwise. +llvm::IntrinsicInst *getConvergenceToken(llvm::BasicBlock *BB) { + for (auto &I : *BB) { + auto *II = dyn_cast(&I); + if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) + return II; + } + return nullptr; +} + +} // namespace + +llvm::CallBase * +CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input, + llvm::Value *ParentToken) { + llvm::Value *bundleArgs[] = {ParentToken}; + llvm::OperandBundleDef OB("convergencectrl", bundleArgs); + auto Output = llvm::CallBase::addOperandBundle( + Input, llvm::LLVMContext::OB_convergencectrl, OB, Input); + Input->replaceAllUsesWith(Output); + Input->eraseFromParent(); + return Output; +} + +llvm::IntrinsicInst * +CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB, + llvm::Value *ParentToken) { + CGBuilderTy::InsertPoint IP = Builder.saveIP(); + if (BB->empty()) + Builder.SetInsertPoint(BB); + else + Builder.SetInsertPoint(BB->getFirstInsertionPt()); + + llvm::CallBase *CB = Builder.CreateIntrinsic( + llvm::Intrinsic::experimental_convergence_loop, {}, {}); + Builder.restoreIP(IP); + + llvm::CallBase *I = addConvergenceControlToken(CB, ParentToken); + return cast(I); +} + +llvm::IntrinsicInst * +CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) { + llvm::BasicBlock *BB = &F->getEntryBlock(); + llvm::IntrinsicInst *Token = getConvergenceToken(BB); + if (Token) + return Token; + + // Adding a convergence token requires the function to be marked as + // convergent. + F->setConvergent(); + + CGBuilderTy::InsertPoint IP = Builder.saveIP(); + Builder.SetInsertPoint(&BB->front()); + llvm::CallBase *I = Builder.CreateIntrinsic( + llvm::Intrinsic::experimental_convergence_entry, {}, {}); + assert(isa(I)); + Builder.restoreIP(IP); + + return cast(I); +} diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 9f16fcb43855..34dc0bd5c15b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -353,6 +353,12 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { assert(DeferredDeactivationCleanupStack.empty() && "mismatched activate/deactivate of cleanups!"); + if (CGM.shouldEmitConvergenceTokens()) { + ConvergenceTokenStack.pop_back(); + assert(ConvergenceTokenStack.empty() && + "mismatched push/pop in convergence stack!"); + } + bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0 && NumSimpleReturnExprs == NumReturnExprs && ReturnBlock.getBlock()->use_empty(); @@ -1277,6 +1283,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, if (CurFuncDecl) if (const auto *VecWidth = CurFuncDecl->getAttr()) LargestVectorWidth = VecWidth->getVectorWidth(); + + if (CGM.shouldEmitConvergenceTokens()) + ConvergenceTokenStack.push_back(getOrEmitConvergenceEntryToken(CurFn)); } void CodeGenFunction::EmitFunctionBody(const Stmt *Body) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index e1e687af6a78..362f4a5fe72a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -315,6 +315,9 @@ public: /// Stack to track the Logical Operator recursion nest for MC/DC. SmallVector MCDCLogOpStack; + /// Stack to track the controlled convergence tokens. + SmallVector ConvergenceTokenStack; + /// Number of nested loop to be consumed by the last surrounding /// loop-associated directive. int ExpectedOMPLoopDepth = 0; @@ -5076,7 +5079,11 @@ public: const llvm::Twine &Name = ""); // Adds a convergence_ctrl token to |Input| and emits the required parent // convergence instructions. - llvm::CallBase *addControlledConvergenceToken(llvm::CallBase *Input); + template + CallType *addControlledConvergenceToken(CallType *Input) { + return cast( + addConvergenceControlToken(Input, ConvergenceTokenStack.back())); + } private: // Emits a convergence_loop instruction for the given |BB|, with |ParentToken| diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index be43a18fc608..0f68418130ea 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1586,6 +1586,14 @@ public: void AddGlobalDtor(llvm::Function *Dtor, int Priority = 65535, bool IsDtorAttrFunc = false); + // Return whether structured convergence intrinsics should be generated for + // this target. + bool shouldEmitConvergenceTokens() const { + // TODO: this should probably become unconditional once the controlled + // convergence becomes the norm. + return getTriple().isSPIRVLogical(); + } + private: llvm::Constant *GetOrCreateLLVMFunction( StringRef MangledName, llvm::Type *Ty, GlobalDecl D, bool ForVTable, diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl index 74b3f59bf760..e51eac7f57c2 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl @@ -1,4 +1,3 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV RWBuffer Buf; diff --git a/clang/test/CodeGenHLSL/builtins/lerp.hlsl b/clang/test/CodeGenHLSL/builtins/lerp.hlsl index 87b2e3af5765..bbb419acaf3b 100644 --- a/clang/test/CodeGenHLSL/builtins/lerp.hlsl +++ b/clang/test/CodeGenHLSL/builtins/lerp.hlsl @@ -14,88 +14,98 @@ // RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF,SPIR_NO_HALF,SPIR_CHECK -// DXIL_NATIVE_HALF: %hlsl.lerp = call half @llvm.dx.lerp.f16(half %0, half %1, half %2) -// SPIR_NATIVE_HALF: %hlsl.lerp = call half @llvm.spv.lerp.f16(half %0, half %1, half %2) +// DXIL_NATIVE_HALF: %hlsl.lerp = call half @llvm.dx.lerp.f16(half %{{.*}}, half %{{.*}}, half %{{.*}}) +// SPIR_NATIVE_HALF: %hlsl.lerp = call half @llvm.spv.lerp.f16(half %{{.*}}, half %{{.*}}, half %{{.*}}) // NATIVE_HALF: ret half %hlsl.lerp -// DXIL_NO_HALF: %hlsl.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) -// SPIR_NO_HALF: %hlsl.lerp = call float @llvm.spv.lerp.f32(float %0, float %1, float %2) +// DXIL_NO_HALF: %hlsl.lerp = call float @llvm.dx.lerp.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) +// SPIR_NO_HALF: %hlsl.lerp = call float @llvm.spv.lerp.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) // NO_HALF: ret float %hlsl.lerp half test_lerp_half(half p0) { return lerp(p0, p0, p0); } -// DXIL_NATIVE_HALF: %hlsl.lerp = call <2 x half> @llvm.dx.lerp.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) -// SPIR_NATIVE_HALF: %hlsl.lerp = call <2 x half> @llvm.spv.lerp.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) +// DXIL_NATIVE_HALF: %hlsl.lerp = call <2 x half> @llvm.dx.lerp.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, <2 x half> %{{.*}}) +// SPIR_NATIVE_HALF: %hlsl.lerp = call <2 x half> @llvm.spv.lerp.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, <2 x half> %{{.*}}) // NATIVE_HALF: ret <2 x half> %hlsl.lerp -// DXIL_NO_HALF: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// SPIR_NO_HALF: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// DXIL_NO_HALF: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}) +// SPIR_NO_HALF: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}) // NO_HALF: ret <2 x float> %hlsl.lerp half2 test_lerp_half2(half2 p0) { return lerp(p0, p0, p0); } -// DXIL_NATIVE_HALF: %hlsl.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) -// SPIR_NATIVE_HALF: %hlsl.lerp = call <3 x half> @llvm.spv.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) +// DXIL_NATIVE_HALF: %hlsl.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %{{.*}}, <3 x half> %{{.*}}, <3 x half> %{{.*}}) +// SPIR_NATIVE_HALF: %hlsl.lerp = call <3 x half> @llvm.spv.lerp.v3f16(<3 x half> %{{.*}}, <3 x half> %{{.*}}, <3 x half> %{{.*}}) // NATIVE_HALF: ret <3 x half> %hlsl.lerp -// DXIL_NO_HALF: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) -// SPIR_NO_HALF: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// DXIL_NO_HALF: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, <3 x float> %{{.*}}) +// SPIR_NO_HALF: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, <3 x float> %{{.*}}) // NO_HALF: ret <3 x float> %hlsl.lerp half3 test_lerp_half3(half3 p0) { return lerp(p0, p0, p0); } -// DXIL_NATIVE_HALF: %hlsl.lerp = call <4 x half> @llvm.dx.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) -// SPIR_NATIVE_HALF: %hlsl.lerp = call <4 x half> @llvm.spv.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) +// DXIL_NATIVE_HALF: %hlsl.lerp = call <4 x half> @llvm.dx.lerp.v4f16(<4 x half> %{{.*}}, <4 x half> %{{.*}}, <4 x half> %{{.*}}) +// SPIR_NATIVE_HALF: %hlsl.lerp = call <4 x half> @llvm.spv.lerp.v4f16(<4 x half> %{{.*}}, <4 x half> %{{.*}}, <4 x half> %{{.*}}) // NATIVE_HALF: ret <4 x half> %hlsl.lerp -// DXIL_NO_HALF: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) -// SPIR_NO_HALF: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// DXIL_NO_HALF: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) +// SPIR_NO_HALF: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) // NO_HALF: ret <4 x float> %hlsl.lerp half4 test_lerp_half4(half4 p0) { return lerp(p0, p0, p0); } -// DXIL_CHECK: %hlsl.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) -// SPIR_CHECK: %hlsl.lerp = call float @llvm.spv.lerp.f32(float %0, float %1, float %2) +// DXIL_CHECK: %hlsl.lerp = call float @llvm.dx.lerp.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) +// SPIR_CHECK: %hlsl.lerp = call float @llvm.spv.lerp.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) // CHECK: ret float %hlsl.lerp float test_lerp_float(float p0) { return lerp(p0, p0, p0); } -// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}) +// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}) // CHECK: ret <2 x float> %hlsl.lerp float2 test_lerp_float2(float2 p0) { return lerp(p0, p0, p0); } -// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) -// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, <3 x float> %{{.*}}) +// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, <3 x float> %{{.*}}) // CHECK: ret <3 x float> %hlsl.lerp float3 test_lerp_float3(float3 p0) { return lerp(p0, p0, p0); } -// DXIL_CHECK: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) -// SPIR_CHECK: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// DXIL_CHECK: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) +// SPIR_CHECK: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) // CHECK: ret <4 x float> %hlsl.lerp float4 test_lerp_float4(float4 p0) { return lerp(p0, p0, p0); } -// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) -// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) +// CHECK: %[[b:.*]] = load <2 x float>, ptr %p1.addr, align 8 +// CHECK: %[[c:.*]] = load <2 x float>, ptr %p1.addr, align 8 +// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %[[b]], <2 x float> %[[c]]) +// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %[[b]], <2 x float> %[[c]]) // CHECK: ret <2 x float> %hlsl.lerp float2 test_lerp_float2_splat(float p0, float2 p1) { return lerp(p0, p1, p1); } -// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) -// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) +// CHECK: %[[b:.*]] = load <3 x float>, ptr %p1.addr, align 16 +// CHECK: %[[c:.*]] = load <3 x float>, ptr %p1.addr, align 16 +// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %[[b]], <3 x float> %[[c]]) +// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %[[b]], <3 x float> %[[c]]) // CHECK: ret <3 x float> %hlsl.lerp float3 test_lerp_float3_splat(float p0, float3 p1) { return lerp(p0, p1, p1); } -// DXIL_CHECK: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) -// SPIR_CHECK: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) +// CHECK: %[[b:.*]] = load <4 x float>, ptr %p1.addr, align 16 +// CHECK: %[[c:.*]] = load <4 x float>, ptr %p1.addr, align 16 +// DXIL_CHECK: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %[[b]], <4 x float> %[[c]]) +// SPIR_CHECK: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %[[b]], <4 x float> %[[c]]) // CHECK: ret <4 x float> %hlsl.lerp float4 test_lerp_float4_splat(float p0, float4 p1) { return lerp(p0, p1, p1); } -// CHECK: %conv = sitofp i32 %2 to float +// CHECK: %[[a:.*]] = load <2 x float>, ptr %p0.addr, align 8 +// CHECK: %[[b:.*]] = load <2 x float>, ptr %p0.addr, align 8 +// CHECK: %conv = sitofp i32 {{.*}} to float // CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer -// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) -// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) +// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %[[a]], <2 x float> %[[b]], <2 x float> %splat.splat) +// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %[[a]], <2 x float> %[[b]], <2 x float> %splat.splat) // CHECK: ret <2 x float> %hlsl.lerp float2 test_lerp_float2_int_splat(float2 p0, int p1) { return lerp(p0, p0, p1); } -// CHECK: %conv = sitofp i32 %2 to float +// CHECK: %[[a:.*]] = load <3 x float>, ptr %p0.addr, align 16 +// CHECK: %[[b:.*]] = load <3 x float>, ptr %p0.addr, align 16 +// CHECK: %conv = sitofp i32 {{.*}} to float // CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer -// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) -// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) +// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %[[a]], <3 x float> %[[b]], <3 x float> %splat.splat) +// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %[[a]], <3 x float> %[[b]], <3 x float> %splat.splat) // CHECK: ret <3 x float> %hlsl.lerp float3 test_lerp_float3_int_splat(float3 p0, int p1) { return lerp(p0, p0, p1); diff --git a/clang/test/CodeGenHLSL/builtins/mad.hlsl b/clang/test/CodeGenHLSL/builtins/mad.hlsl index b4dc636b00b7..559e1d1dd390 100644 --- a/clang/test/CodeGenHLSL/builtins/mad.hlsl +++ b/clang/test/CodeGenHLSL/builtins/mad.hlsl @@ -64,59 +64,107 @@ int16_t3 test_mad_int16_t3(int16_t3 p0, int16_t3 p1, int16_t3 p2) { return mad(p int16_t4 test_mad_int16_t4(int16_t4 p0, int16_t4 p1, int16_t4 p2) { return mad(p0, p1, p2); } #endif // __HLSL_ENABLE_16_BIT -// NATIVE_HALF: %hlsl.fmad = call half @llvm.fmuladd.f16(half %0, half %1, half %2) +// NATIVE_HALF: %[[p0:.*]] = load half, ptr %p0.addr, align 2 +// NATIVE_HALF: %[[p1:.*]] = load half, ptr %p1.addr, align 2 +// NATIVE_HALF: %[[p2:.*]] = load half, ptr %p2.addr, align 2 +// NATIVE_HALF: %hlsl.fmad = call half @llvm.fmuladd.f16(half %[[p0]], half %[[p1]], half %[[p2]]) // NATIVE_HALF: ret half %hlsl.fmad -// NO_HALF: %hlsl.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) +// NO_HALF: %[[p0:.*]] = load float, ptr %p0.addr, align 4 +// NO_HALF: %[[p1:.*]] = load float, ptr %p1.addr, align 4 +// NO_HALF: %[[p2:.*]] = load float, ptr %p2.addr, align 4 +// NO_HALF: %hlsl.fmad = call float @llvm.fmuladd.f32(float %[[p0]], float %[[p1]], float %[[p2]]) // NO_HALF: ret float %hlsl.fmad half test_mad_half(half p0, half p1, half p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %hlsl.fmad = call <2 x half> @llvm.fmuladd.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) +// NATIVE_HALF: %[[p0:.*]] = load <2 x half>, ptr %p0.addr, align 4 +// NATIVE_HALF: %[[p1:.*]] = load <2 x half>, ptr %p1.addr, align 4 +// NATIVE_HALF: %[[p2:.*]] = load <2 x half>, ptr %p2.addr, align 4 +// NATIVE_HALF: %hlsl.fmad = call <2 x half> @llvm.fmuladd.v2f16(<2 x half> %[[p0]], <2 x half> %[[p1]], <2 x half> %[[p2]]) // NATIVE_HALF: ret <2 x half> %hlsl.fmad -// NO_HALF: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// NO_HALF: %[[p0:.*]] = load <2 x float>, ptr %p0.addr, align 8 +// NO_HALF: %[[p1:.*]] = load <2 x float>, ptr %p1.addr, align 8 +// NO_HALF: %[[p2:.*]] = load <2 x float>, ptr %p2.addr, align 8 +// NO_HALF: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %[[p0]], <2 x float> %[[p1]], <2 x float> %[[p2]]) // NO_HALF: ret <2 x float> %hlsl.fmad half2 test_mad_half2(half2 p0, half2 p1, half2 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %hlsl.fmad = call <3 x half> @llvm.fmuladd.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) +// NATIVE_HALF: %[[p0:.*]] = load <3 x half>, ptr %p0.addr, align 8 +// NATIVE_HALF: %[[p1:.*]] = load <3 x half>, ptr %p1.addr, align 8 +// NATIVE_HALF: %[[p2:.*]] = load <3 x half>, ptr %p2.addr, align 8 +// NATIVE_HALF: %hlsl.fmad = call <3 x half> @llvm.fmuladd.v3f16(<3 x half> %[[p0]], <3 x half> %[[p1]], <3 x half> %[[p2]]) // NATIVE_HALF: ret <3 x half> %hlsl.fmad -// NO_HALF: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// NO_HALF: %[[p0:.*]] = load <3 x float>, ptr %p0.addr, align 16 +// NO_HALF: %[[p1:.*]] = load <3 x float>, ptr %p1.addr, align 16 +// NO_HALF: %[[p2:.*]] = load <3 x float>, ptr %p2.addr, align 16 +// NO_HALF: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %[[p0]], <3 x float> %[[p1]], <3 x float> %[[p2]]) // NO_HALF: ret <3 x float> %hlsl.fmad half3 test_mad_half3(half3 p0, half3 p1, half3 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %hlsl.fmad = call <4 x half> @llvm.fmuladd.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) +// NATIVE_HALF: %[[p0:.*]] = load <4 x half>, ptr %p0.addr, align 8 +// NATIVE_HALF: %[[p1:.*]] = load <4 x half>, ptr %p1.addr, align 8 +// NATIVE_HALF: %[[p2:.*]] = load <4 x half>, ptr %p2.addr, align 8 +// NATIVE_HALF: %hlsl.fmad = call <4 x half> @llvm.fmuladd.v4f16(<4 x half> %[[p0]], <4 x half> %[[p1]], <4 x half> %[[p2]]) // NATIVE_HALF: ret <4 x half> %hlsl.fmad -// NO_HALF: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// NO_HALF: %[[p0:.*]] = load <4 x float>, ptr %p0.addr, align 16 +// NO_HALF: %[[p1:.*]] = load <4 x float>, ptr %p1.addr, align 16 +// NO_HALF: %[[p2:.*]] = load <4 x float>, ptr %p2.addr, align 16 +// NO_HALF: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %[[p0]], <4 x float> %[[p1]], <4 x float> %[[p2]]) // NO_HALF: ret <4 x float> %hlsl.fmad half4 test_mad_half4(half4 p0, half4 p1, half4 p2) { return mad(p0, p1, p2); } -// CHECK: %hlsl.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) +// CHECK: %[[p0:.*]] = load float, ptr %p0.addr, align 4 +// CHECK: %[[p1:.*]] = load float, ptr %p1.addr, align 4 +// CHECK: %[[p2:.*]] = load float, ptr %p2.addr, align 4 +// CHECK: %hlsl.fmad = call float @llvm.fmuladd.f32(float %[[p0]], float %[[p1]], float %[[p2]]) // CHECK: ret float %hlsl.fmad float test_mad_float(float p0, float p1, float p2) { return mad(p0, p1, p2); } -// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// CHECK: %[[p0:.*]] = load <2 x float>, ptr %p0.addr, align 8 +// CHECK: %[[p1:.*]] = load <2 x float>, ptr %p1.addr, align 8 +// CHECK: %[[p2:.*]] = load <2 x float>, ptr %p2.addr, align 8 +// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %[[p0]], <2 x float> %[[p1]], <2 x float> %[[p2]]) // CHECK: ret <2 x float> %hlsl.fmad float2 test_mad_float2(float2 p0, float2 p1, float2 p2) { return mad(p0, p1, p2); } -// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// CHECK: %[[p0:.*]] = load <3 x float>, ptr %p0.addr, align 16 +// CHECK: %[[p1:.*]] = load <3 x float>, ptr %p1.addr, align 16 +// CHECK: %[[p2:.*]] = load <3 x float>, ptr %p2.addr, align 16 +// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %[[p0]], <3 x float> %[[p1]], <3 x float> %[[p2]]) // CHECK: ret <3 x float> %hlsl.fmad float3 test_mad_float3(float3 p0, float3 p1, float3 p2) { return mad(p0, p1, p2); } -// CHECK: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// CHECK: %[[p0:.*]] = load <4 x float>, ptr %p0.addr, align 16 +// CHECK: %[[p1:.*]] = load <4 x float>, ptr %p1.addr, align 16 +// CHECK: %[[p2:.*]] = load <4 x float>, ptr %p2.addr, align 16 +// CHECK: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %[[p0]], <4 x float> %[[p1]], <4 x float> %[[p2]]) // CHECK: ret <4 x float> %hlsl.fmad float4 test_mad_float4(float4 p0, float4 p1, float4 p2) { return mad(p0, p1, p2); } -// CHECK: %hlsl.fmad = call double @llvm.fmuladd.f64(double %0, double %1, double %2) +// CHECK: %[[p0:.*]] = load double, ptr %p0.addr, align 8 +// CHECK: %[[p1:.*]] = load double, ptr %p1.addr, align 8 +// CHECK: %[[p2:.*]] = load double, ptr %p2.addr, align 8 +// CHECK: %hlsl.fmad = call double @llvm.fmuladd.f64(double %[[p0]], double %[[p1]], double %[[p2]]) // CHECK: ret double %hlsl.fmad double test_mad_double(double p0, double p1, double p2) { return mad(p0, p1, p2); } -// CHECK: %hlsl.fmad = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %0, <2 x double> %1, <2 x double> %2) +// CHECK: %[[p0:.*]] = load <2 x double>, ptr %p0.addr, align 16 +// CHECK: %[[p1:.*]] = load <2 x double>, ptr %p1.addr, align 16 +// CHECK: %[[p2:.*]] = load <2 x double>, ptr %p2.addr, align 16 +// CHECK: %hlsl.fmad = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %[[p0]], <2 x double> %[[p1]], <2 x double> %[[p2]]) // CHECK: ret <2 x double> %hlsl.fmad double2 test_mad_double2(double2 p0, double2 p1, double2 p2) { return mad(p0, p1, p2); } -// CHECK: %hlsl.fmad = call <3 x double> @llvm.fmuladd.v3f64(<3 x double> %0, <3 x double> %1, <3 x double> %2) +// CHECK: %[[p0:.*]] = load <3 x double>, ptr %p0.addr, align 32 +// CHECK: %[[p1:.*]] = load <3 x double>, ptr %p1.addr, align 32 +// CHECK: %[[p2:.*]] = load <3 x double>, ptr %p2.addr, align 32 +// CHECK: %hlsl.fmad = call <3 x double> @llvm.fmuladd.v3f64(<3 x double> %[[p0]], <3 x double> %[[p1]], <3 x double> %[[p2]]) // CHECK: ret <3 x double> %hlsl.fmad double3 test_mad_double3(double3 p0, double3 p1, double3 p2) { return mad(p0, p1, p2); } -// CHECK: %hlsl.fmad = call <4 x double> @llvm.fmuladd.v4f64(<4 x double> %0, <4 x double> %1, <4 x double> %2) +// CHECK: %[[p0:.*]] = load <4 x double>, ptr %p0.addr, align 32 +// CHECK: %[[p1:.*]] = load <4 x double>, ptr %p1.addr, align 32 +// CHECK: %[[p2:.*]] = load <4 x double>, ptr %p2.addr, align 32 +// CHECK: %hlsl.fmad = call <4 x double> @llvm.fmuladd.v4f64(<4 x double> %[[p0]], <4 x double> %[[p1]], <4 x double> %[[p2]]) // CHECK: ret <4 x double> %hlsl.fmad double4 test_mad_double4(double4 p0, double4 p1, double4 p2) { return mad(p0, p1, p2); } @@ -216,31 +264,41 @@ uint64_t3 test_mad_uint64_t3(uint64_t3 p0, uint64_t3 p1, uint64_t3 p2) { return // SPIR_CHECK: add nuw <4 x i64> %{{.*}}, %{{.*}} uint64_t4 test_mad_uint64_t4(uint64_t4 p0, uint64_t4 p1, uint64_t4 p2) { return mad(p0, p1, p2); } -// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) +// CHECK: %[[p1:.*]] = load <2 x float>, ptr %p1.addr, align 8 +// CHECK: %[[p2:.*]] = load <2 x float>, ptr %p2.addr, align 8 +// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %splat.splat, <2 x float> %[[p1]], <2 x float> %[[p2]]) // CHECK: ret <2 x float> %hlsl.fmad float2 test_mad_float2_splat(float p0, float2 p1, float2 p2) { return mad(p0, p1, p2); } -// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) +// CHECK: %[[p1:.*]] = load <3 x float>, ptr %p1.addr, align 16 +// CHECK: %[[p2:.*]] = load <3 x float>, ptr %p2.addr, align 16 +// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %splat.splat, <3 x float> %[[p1]], <3 x float> %[[p2]]) // CHECK: ret <3 x float> %hlsl.fmad float3 test_mad_float3_splat(float p0, float3 p1, float3 p2) { return mad(p0, p1, p2); } -// CHECK: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) +// CHECK: %[[p1:.*]] = load <4 x float>, ptr %p1.addr, align 16 +// CHECK: %[[p2:.*]] = load <4 x float>, ptr %p2.addr, align 16 +// CHECK: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %splat.splat, <4 x float> %[[p1]], <4 x float> %[[p2]]) // CHECK: ret <4 x float> %hlsl.fmad float4 test_mad_float4_splat(float p0, float4 p1, float4 p2) { return mad(p0, p1, p2); } -// CHECK: %conv = sitofp i32 %2 to float +// CHECK: %[[p0:.*]] = load <2 x float>, ptr %p0.addr, align 8 +// CHECK: %[[p1:.*]] = load <2 x float>, ptr %p1.addr, align 8 +// CHECK: %conv = sitofp i32 %{{.*}} to float // CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer -// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) +// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %[[p0]], <2 x float> %[[p1]], <2 x float> %splat.splat) // CHECK: ret <2 x float> %hlsl.fmad float2 test_mad_float2_int_splat(float2 p0, float2 p1, int p2) { return mad(p0, p1, p2); } -// CHECK: %conv = sitofp i32 %2 to float +// CHECK: %[[p0:.*]] = load <3 x float>, ptr %p0.addr, align 16 +// CHECK: %[[p1:.*]] = load <3 x float>, ptr %p1.addr, align 16 +// CHECK: %conv = sitofp i32 %{{.*}} to float // CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer -// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) +// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %[[p0]], <3 x float> %[[p1]], <3 x float> %splat.splat) // CHECK: ret <3 x float> %hlsl.fmad float3 test_mad_float3_int_splat(float3 p0, float3 p1, int p2) { return mad(p0, p1, p2); diff --git a/clang/test/CodeGenHLSL/convergence/do.while.hlsl b/clang/test/CodeGenHLSL/convergence/do.while.hlsl new file mode 100644 index 000000000000..ea5a45ba8fd7 --- /dev/null +++ b/clang/test/CodeGenHLSL/convergence/do.while.hlsl @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +bool cond(); +void foo(); + +void test1() { + do { + } while (cond()); +} +// CHECK: define spir_func void @_Z5test1v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: do.body: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: do.cond: +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +void test2() { + do { + foo(); + } while (cond()); +} +// CHECK: define spir_func void @_Z5test2v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: do.body: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: do.cond: +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +void test3() { + do { + if (cond()) + foo(); + } while (cond()); +} +// CHECK: define spir_func void @_Z5test3v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: do.body: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: if.then: +// CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: do.cond: +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +void test4() { + do { + if (cond()) { + foo(); + break; + } + } while (cond()); +} +// CHECK: define spir_func void @_Z5test4v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: do.body: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: if.then: +// CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: do.cond: +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +void test5() { + do { + while (cond()) { + if (cond()) { + foo(); + break; + } + } + } while (cond()); +} +// CHECK: define spir_func void @_Z5test5v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: do.body: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: while.cond: +// CHECK: [[T2:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T1]]) ] +// CHECK: if.then: +// CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T2]]) ] +// CHECK: do.cond: +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +// CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} } +// CHECK-DAG: attributes [[A3]] = { {{.*}}convergent{{.*}} } diff --git a/clang/test/CodeGenHLSL/convergence/for.hlsl b/clang/test/CodeGenHLSL/convergence/for.hlsl new file mode 100644 index 000000000000..180fae74ba75 --- /dev/null +++ b/clang/test/CodeGenHLSL/convergence/for.hlsl @@ -0,0 +1,121 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +bool cond(); +bool cond2(); +void foo(); + +void test1() { + for (;;) { + foo(); + } +} +// CHECK: define spir_func void @_Z5test1v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: for.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +void test2() { + for (;cond();) { + foo(); + } +} +// CHECK: define spir_func void @_Z5test2v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: for.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: for.body: +// CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +void test3() { + for (cond();;) { + foo(); + } +} +// CHECK: define spir_func void @_Z5test3v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T0]]) ] +// CHECK: for.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +void test4() { + for (cond();cond2();) { + foo(); + } +} +// CHECK: define spir_func void @_Z5test4v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T0]]) ] +// CHECK: for.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func noundef i1 @_Z5cond2v() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: for.body: +// CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +void test5() { + for (cond();cond2();foo()) { + } +} +// CHECK: define spir_func void @_Z5test5v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T0]]) ] +// CHECK: for.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func noundef i1 @_Z5cond2v() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: for.inc: +// CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +void test6() { + for (cond();cond2();foo()) { + if (cond()) { + foo(); + break; + } + } +} +// CHECK: define spir_func void @_Z5test6v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T0]]) ] +// CHECK: for.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func noundef i1 @_Z5cond2v() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: for.body: +// CHECK: [[C1:%[a-zA-Z0-9]+]] = call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: br i1 [[C1]], label %if.then, label %if.end +// CHECK: if.then: +// CHECK call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: br label %for.end +// CHECK: if.end: +// CHECK: br label %for.inc +// CHECK: for.inc: +// CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +void test7() { + for (cond();;) { + for (cond();;) { + foo(); + } + } +} +// CHECK: define spir_func void @_Z5test7v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T0]]) ] +// CHECK: for.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: for.cond3: +// CHECK: [[T2:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T1]]) ] +// CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T2]]) ] + +// CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} } +// CHECK-DAG: attributes [[A3]] = { {{.*}}convergent{{.*}} } diff --git a/clang/test/CodeGenHLSL/convergence/while.hlsl b/clang/test/CodeGenHLSL/convergence/while.hlsl new file mode 100644 index 000000000000..92777000190d --- /dev/null +++ b/clang/test/CodeGenHLSL/convergence/while.hlsl @@ -0,0 +1,119 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +bool cond(); +void foo(); + +void test1() { + while (cond()) { + } +} +// CHECK: define spir_func void @_Z5test1v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: while.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] + +void test2() { + while (cond()) { + foo(); + } +} +// CHECK: define spir_func void @_Z5test2v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: while.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: while.body: +// CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] + +void test3() { + while (cond()) { + if (cond()) + break; + foo(); + } +} +// CHECK: define spir_func void @_Z5test3v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: while.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: if.then: +// CHECK: br label %while.end +// CHECK: if.end: +// CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: br label %while.cond + +void test4() { + while (cond()) { + if (cond()) { + foo(); + break; + } + } +} +// CHECK: define spir_func void @_Z5test4v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: while.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: if.then: +// CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: br label %while.end +// CHECK: if.end: +// CHECK: br label %while.cond + +void test5() { + while (cond()) { + while (cond()) { + if (cond()) { + foo(); + break; + } + } + } +} +// CHECK: define spir_func void @_Z5test5v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: while.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: while.cond2: +// CHECK: [[T2:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T1]]) ] +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T2]]) ] +// CHECK: if.then: +// CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T2]]) ] +// CHECK: br label %while.end + +void test6() { + while (cond()) { + while (cond()) { + } + + if (cond()) { + foo(); + break; + } + } +} +// CHECK: define spir_func void @_Z5test6v() [[A0:#[0-9]+]] { +// CHECK: entry: +// CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: while.cond: +// CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: while.cond2: +// CHECK: [[T2:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T1]]) ] +// CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T2]]) ] +// CHECK: if.then: +// CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] +// CHECK: br label %while.end + +// CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} } +// CHECK-DAG: attributes [[A3]] = { {{.*}}convergent{{.*}} } -- GitLab From ac0d415552922436c3136e3dd1446294858c2d7d Mon Sep 17 00:00:00 2001 From: Krzysztof Drewniak Date: Tue, 14 May 2024 10:03:48 -0500 Subject: [PATCH 240/578] Update documentation for buffer fat pointers (#92034) Now that we've got (minus some issues around datatypes and invariant loads) working lowerings for address space 7, update the table in the AMDGPU usage guide to properly indicate the nature of these address spaces. --- llvm/docs/AMDGPUUsage.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst index 51969be85648..75536bc5bea6 100644 --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -824,8 +824,8 @@ supported for the ``amdgcn`` target. Constant 4 constant *same as global* 64 0x0000000000000000 Private 5 private scratch 32 0xFFFFFFFF Constant 32-bit 6 *TODO* 0x00000000 - Buffer Fat Pointer (experimental) 7 *TODO* - Buffer Resource (experimental) 8 *TODO* + Buffer Fat Pointer 7 N/A N/A 160 0 + Buffer Resource 8 N/A V# 128 0x00000000000000000000000000000000 Buffer Strided Pointer (experimental) 9 *TODO* Streamout Registers 128 N/A GS_REGS ===================================== =============== =========== ================ ======= ============================ -- GitLab From 736ffdc38347f3f83cf7b3c034b8e837f46f7eab Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 14 May 2024 08:06:10 -0700 Subject: [PATCH 241/578] [RISCV] Add X27 to SavedRegs when X26 is in SavedRegs for cm.push/pop (#92067) cm.push can't save X26 without also saving X27. This removes two other checks for this case. This causes CFI to be emitted since X27 is now explicitly a callee saved register. The affected tests use inline assembly to clobber X26 rather than the whole range of s0-s10. --- llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 10 ++++++---- llvm/test/CodeGen/RISCV/push-pop-popret.ll | 4 ++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index 316f6a90893a..436bd4a38a31 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -265,7 +265,6 @@ getPushPopEncodingAndNum(const Register MaxReg) { default: llvm_unreachable("Unexpected Reg for Push/Pop Inst"); case RISCV::X27: /*s11*/ - case RISCV::X26: /*s10*/ return std::make_pair(llvm::RISCVZC::RLISTENCODE::RA_S0_S11, 13); case RISCV::X25: /*s9*/ return std::make_pair(llvm::RISCVZC::RLISTENCODE::RA_S0_S9, 11); @@ -302,9 +301,7 @@ static Register getMaxPushPopReg(const MachineFunction &MF, }) != std::end(FixedCSRFIMap)) MaxPushPopReg = std::max(MaxPushPopReg.id(), CS.getReg().id()); } - // if rlist is {rs, s0-s10}, then s11 will also be included - if (MaxPushPopReg == RISCV::X26) - MaxPushPopReg = RISCV::X27; + assert(MaxPushPopReg != RISCV::X26 && "x26 requires x27 to also be pushed"); return MaxPushPopReg; } @@ -1047,6 +1044,11 @@ void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF, // Mark BP as used if function has dedicated base pointer. if (hasBP(MF)) SavedRegs.set(RISCVABI::getBPReg()); + + // When using cm.push/pop we must save X27 if we save X26. + auto *RVFI = MF.getInfo(); + if (RVFI->isPushable(MF) && SavedRegs.test(RISCV::X26)) + SavedRegs.set(RISCV::X27); } std::pair diff --git a/llvm/test/CodeGen/RISCV/push-pop-popret.ll b/llvm/test/CodeGen/RISCV/push-pop-popret.ll index e007dcc764e9..7548faaae61f 100644 --- a/llvm/test/CodeGen/RISCV/push-pop-popret.ll +++ b/llvm/test/CodeGen/RISCV/push-pop-popret.ll @@ -3225,6 +3225,7 @@ define void @spill_x10() { ; RV32IZCMP-NEXT: cm.push {ra, s0-s11}, -64 ; RV32IZCMP-NEXT: .cfi_def_cfa_offset 64 ; RV32IZCMP-NEXT: .cfi_offset s10, -8 +; RV32IZCMP-NEXT: .cfi_offset s11, -4 ; RV32IZCMP-NEXT: #APP ; RV32IZCMP-NEXT: li s10, 0 ; RV32IZCMP-NEXT: #NO_APP @@ -3235,6 +3236,7 @@ define void @spill_x10() { ; RV64IZCMP-NEXT: cm.push {ra, s0-s11}, -112 ; RV64IZCMP-NEXT: .cfi_def_cfa_offset 112 ; RV64IZCMP-NEXT: .cfi_offset s10, -16 +; RV64IZCMP-NEXT: .cfi_offset s11, -8 ; RV64IZCMP-NEXT: #APP ; RV64IZCMP-NEXT: li s10, 0 ; RV64IZCMP-NEXT: #NO_APP @@ -3245,6 +3247,7 @@ define void @spill_x10() { ; RV32IZCMP-SR-NEXT: cm.push {ra, s0-s11}, -64 ; RV32IZCMP-SR-NEXT: .cfi_def_cfa_offset 64 ; RV32IZCMP-SR-NEXT: .cfi_offset s10, -8 +; RV32IZCMP-SR-NEXT: .cfi_offset s11, -4 ; RV32IZCMP-SR-NEXT: #APP ; RV32IZCMP-SR-NEXT: li s10, 0 ; RV32IZCMP-SR-NEXT: #NO_APP @@ -3255,6 +3258,7 @@ define void @spill_x10() { ; RV64IZCMP-SR-NEXT: cm.push {ra, s0-s11}, -112 ; RV64IZCMP-SR-NEXT: .cfi_def_cfa_offset 112 ; RV64IZCMP-SR-NEXT: .cfi_offset s10, -16 +; RV64IZCMP-SR-NEXT: .cfi_offset s11, -8 ; RV64IZCMP-SR-NEXT: #APP ; RV64IZCMP-SR-NEXT: li s10, 0 ; RV64IZCMP-SR-NEXT: #NO_APP -- GitLab From 2766f2174e428842a9ab1a9ba5b320be5878f87d Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 14 May 2024 08:08:18 -0700 Subject: [PATCH 242/578] [ORC] Loosen __objc_imageinfo flag merging to match ld (#91767) Allow mixing objects with/without signed class ro data and category class properties as long as it happens before we register the metadata. These combinations are a warning in ld, not a hard error. The only case that is ABI-breaking is if we already registered with the feature enabled but later try to load an object that doesn't support it. rdar://127336061 --- .../TestCases/Darwin/arm64/objc-imageinfo.S | 22 ++++++++++++++++--- .../TestCases/Darwin/x86-64/objc-imageinfo.S | 22 ++++++++++++++++--- .../lib/ExecutionEngine/Orc/MachOPlatform.cpp | 14 ++++++++++-- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/compiler-rt/test/orc/TestCases/Darwin/arm64/objc-imageinfo.S b/compiler-rt/test/orc/TestCases/Darwin/arm64/objc-imageinfo.S index d58943f9681d..2ee7d3f5eac1 100644 --- a/compiler-rt/test/orc/TestCases/Darwin/arm64/objc-imageinfo.S +++ b/compiler-rt/test/orc/TestCases/Darwin/arm64/objc-imageinfo.S @@ -27,9 +27,6 @@ // Check error conditions. -// RUN: not %llvm_jitlink %t/main.o %t/objc_old.o %t/objc_new.o 2>&1 | FileCheck %s -check-prefix=CATEGORY -// CATEGORY: ObjC category class property support in {{.*}} does not match first registered flags - // RUN: not %llvm_jitlink %t/main.o %t/swift_4.o %t/swift_5.o 2>&1 | FileCheck %s -check-prefix=SWIFT_ABI // SWIFT_ABI: Swift ABI version in {{.*}} does not match first registered flags @@ -47,6 +44,14 @@ // RUN: %llvm_jitlink -debug-only=orc %t/main.o %t/swift_59.o %t/swift_5.o %t/objc_new.o 2>&1 | FileCheck %s -check-prefix=SWIFT_MIX3 // SWIFT_MIX3: MachOPlatform: Merging __objc_imageinfo flags for main {{.*}} -> 0x5000740 +// Disable categories. +// RUN: %llvm_jitlink -debug-only=orc %t/main.o %t/objc_old.o %t/objc_new.o 2>&1 | FileCheck %s -check-prefix=SWIFT_MIX4 +// SWIFT_MIX4: MachOPlatform: Merging __objc_imageinfo flags for main {{.*}} -> 0x0000 + +// Disable signed class_ro. +// RUN: %llvm_jitlink -debug-only=orc %t/main.o %t/objc_new.o %t/objc_new_signed_ro.o 2>&1 | FileCheck %s -check-prefix=SWIFT_MIX5 +// SWIFT_MIX5: MachOPlatform: Merging __objc_imageinfo flags for main {{.*}} -> 0x0040 + //--- main.S .section __TEXT,__text,regular,pure_instructions .globl _main @@ -76,6 +81,17 @@ L_OBJC_IMAGE_INFO: .long 0 .long 64 +//--- objc_new_signed_ro.S +.section __TEXT,__text,regular,pure_instructions +.globl _objc3 +_objc3: + ret + + .section __DATA,__objc_imageinfo,regular,no_dead_strip +L_OBJC_IMAGE_INFO: + .long 0 + .long 80 + //--- swift_4.S .section __TEXT,__text,regular,pure_instructions .globl _swift4 diff --git a/compiler-rt/test/orc/TestCases/Darwin/x86-64/objc-imageinfo.S b/compiler-rt/test/orc/TestCases/Darwin/x86-64/objc-imageinfo.S index 90b5c3a38eeb..d4e9b4b05fb8 100644 --- a/compiler-rt/test/orc/TestCases/Darwin/x86-64/objc-imageinfo.S +++ b/compiler-rt/test/orc/TestCases/Darwin/x86-64/objc-imageinfo.S @@ -27,9 +27,6 @@ // Check error conditions. -// RUN: not %llvm_jitlink %t/main.o %t/objc_old.o %t/objc_new.o 2>&1 | FileCheck %s -check-prefix=CATEGORY -// CATEGORY: ObjC category class property support in {{.*}} does not match first registered flags - // RUN: not %llvm_jitlink %t/main.o %t/swift_4.o %t/swift_5.o 2>&1 | FileCheck %s -check-prefix=SWIFT_ABI // SWIFT_ABI: Swift ABI version in {{.*}} does not match first registered flags @@ -47,6 +44,14 @@ // RUN: %llvm_jitlink -debug-only=orc %t/main.o %t/swift_59.o %t/swift_5.o %t/objc_new.o 2>&1 | FileCheck %s -check-prefix=SWIFT_MIX3 // SWIFT_MIX3: MachOPlatform: Merging __objc_imageinfo flags for main {{.*}} -> 0x5000740 +// Disable categories. +// RUN: %llvm_jitlink -debug-only=orc %t/main.o %t/objc_old.o %t/objc_new.o 2>&1 | FileCheck %s -check-prefix=SWIFT_MIX4 +// SWIFT_MIX4: MachOPlatform: Merging __objc_imageinfo flags for main {{.*}} -> 0x0000 + +// Disable signed class_ro. +// RUN: %llvm_jitlink -debug-only=orc %t/main.o %t/objc_new.o %t/objc_new_signed_ro.o 2>&1 | FileCheck %s -check-prefix=SWIFT_MIX5 +// SWIFT_MIX5: MachOPlatform: Merging __objc_imageinfo flags for main {{.*}} -> 0x0040 + //--- main.S .section __TEXT,__text,regular,pure_instructions .globl _main @@ -76,6 +81,17 @@ L_OBJC_IMAGE_INFO: .long 0 .long 64 +//--- objc_new_signed_ro.S +.section __TEXT,__text,regular,pure_instructions +.globl _objc3 +_objc3: + ret + + .section __DATA,__objc_imageinfo,regular,no_dead_strip +L_OBJC_IMAGE_INFO: + .long 0 + .long 80 + //--- swift_4.S .section __TEXT,__text,regular,pure_instructions .globl _swift4 diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp index 1fa8a1274911..2b397b2d48e7 100644 --- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp +++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp @@ -1134,12 +1134,16 @@ Error MachOPlatform::MachOPlatformPlugin::mergeImageInfoFlags( " does not match first registered flags", inconvertibleErrorCode()); - if (Old.HasCategoryClassProperties != New.HasCategoryClassProperties) + // HasCategoryClassProperties and HasSignedObjCClassROs can be disabled before + // they are registered, if necessary, but once they are in use must be + // supported by subsequent objects. + if (Info.Finalized && Old.HasCategoryClassProperties && + !New.HasCategoryClassProperties) return make_error("ObjC category class property support in " + G.getName() + " does not match first registered flags", inconvertibleErrorCode()); - if (Old.HasSignedObjCClassROs != New.HasSignedObjCClassROs) + if (Info.Finalized && Old.HasSignedObjCClassROs && !New.HasSignedObjCClassROs) return make_error("ObjC class_ro_t pointer signing in " + G.getName() + " does not match first registered flags", @@ -1158,6 +1162,12 @@ Error MachOPlatform::MachOPlatformPlugin::mergeImageInfoFlags( // Add a Swift ABI version if it was pure objc before. if (!New.SwiftABIVersion) New.SwiftABIVersion = Old.SwiftABIVersion; + // Disable class properties if any object does not support it. + if (Old.HasCategoryClassProperties != New.HasCategoryClassProperties) + New.HasCategoryClassProperties = false; + // Disable signed class ro data if any object does not support it. + if (Old.HasSignedObjCClassROs != New.HasSignedObjCClassROs) + New.HasSignedObjCClassROs = false; LLVM_DEBUG({ dbgs() << "MachOPlatform: Merging __objc_imageinfo flags for " -- GitLab From 82434c70b792c4a3773515f8d3172df11e4e615f Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Tue, 14 May 2024 22:45:09 +0800 Subject: [PATCH 243/578] [LoongArch] Add test cases for div/mod to cover various extended combinations of 32-bit integers. NFC --- .../ir-instruction/sdiv-udiv-srem-urem.ll | 528 ++++++++++++++++-- 1 file changed, 484 insertions(+), 44 deletions(-) diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll index 381f69bb46f8..2064c398948f 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll @@ -148,6 +148,113 @@ entry: ret i32 %r } +define i32 @sdiv_ui32_si32_si32(i32 signext %a, i32 signext %b) { +; LA32-LABEL: sdiv_ui32_si32_si32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: div.w $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: sdiv_ui32_si32_si32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: div.d $a0, $a0, $a1 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: sdiv_ui32_si32_si32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: div.w $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB4_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB4_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: sdiv_ui32_si32_si32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: div.d $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB4_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB4_2: # %entry +; LA64-TRAP-NEXT: ret +entry: + %r = sdiv i32 %a, %b + ret i32 %r +} + +define signext i32 @sdiv_si32_ui32_ui32(i32 %a, i32 %b) { +; LA32-LABEL: sdiv_si32_ui32_ui32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: div.w $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: sdiv_si32_ui32_ui32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: addi.w $a1, $a1, 0 +; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: div.d $a0, $a0, $a1 +; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: sdiv_si32_ui32_ui32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: div.w $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB5_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB5_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: sdiv_si32_ui32_ui32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: addi.w $a1, $a1, 0 +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 +; LA64-TRAP-NEXT: div.d $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB5_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB5_2: # %entry +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 +; LA64-TRAP-NEXT: ret +entry: + %r = sdiv i32 %a, %b + ret i32 %r +} + +define signext i32 @sdiv_si32_si32_si32(i32 signext %a, i32 signext %b) { +; LA32-LABEL: sdiv_si32_si32_si32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: div.w $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: sdiv_si32_si32_si32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: div.d $a0, $a0, $a1 +; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: sdiv_si32_si32_si32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: div.w $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB6_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB6_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: sdiv_si32_si32_si32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: div.d $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB6_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB6_2: # %entry +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 +; LA64-TRAP-NEXT: ret +entry: + %r = sdiv i32 %a, %b + ret i32 %r +} + define i64 @sdiv_i64(i64 %a, i64 %b) { ; LA32-LABEL: sdiv_i64: ; LA32: # %bb.0: # %entry @@ -179,10 +286,10 @@ define i64 @sdiv_i64(i64 %a, i64 %b) { ; LA64-TRAP-LABEL: sdiv_i64: ; LA64-TRAP: # %bb.0: # %entry ; LA64-TRAP-NEXT: div.d $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB4_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB7_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB4_2: # %entry +; LA64-TRAP-NEXT: .LBB7_2: # %entry ; LA64-TRAP-NEXT: ret entry: %r = sdiv i64 %a, %b @@ -230,10 +337,10 @@ define i8 @udiv_i8(i8 %a, i8 %b) { ; LA32-TRAP-NEXT: andi $a1, $a1, 255 ; LA32-TRAP-NEXT: andi $a0, $a0, 255 ; LA32-TRAP-NEXT: div.wu $a0, $a0, $a1 -; LA32-TRAP-NEXT: bnez $a1, .LBB6_2 +; LA32-TRAP-NEXT: bnez $a1, .LBB9_2 ; LA32-TRAP-NEXT: # %bb.1: # %entry ; LA32-TRAP-NEXT: break 7 -; LA32-TRAP-NEXT: .LBB6_2: # %entry +; LA32-TRAP-NEXT: .LBB9_2: # %entry ; LA32-TRAP-NEXT: ret ; ; LA64-TRAP-LABEL: udiv_i8: @@ -241,10 +348,10 @@ define i8 @udiv_i8(i8 %a, i8 %b) { ; LA64-TRAP-NEXT: andi $a1, $a1, 255 ; LA64-TRAP-NEXT: andi $a0, $a0, 255 ; LA64-TRAP-NEXT: div.du $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB6_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB9_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB6_2: # %entry +; LA64-TRAP-NEXT: .LBB9_2: # %entry ; LA64-TRAP-NEXT: ret entry: %r = udiv i8 %a, %b @@ -271,10 +378,10 @@ define i16 @udiv_i16(i16 %a, i16 %b) { ; LA32-TRAP-NEXT: bstrpick.w $a1, $a1, 15, 0 ; LA32-TRAP-NEXT: bstrpick.w $a0, $a0, 15, 0 ; LA32-TRAP-NEXT: div.wu $a0, $a0, $a1 -; LA32-TRAP-NEXT: bnez $a1, .LBB7_2 +; LA32-TRAP-NEXT: bnez $a1, .LBB10_2 ; LA32-TRAP-NEXT: # %bb.1: # %entry ; LA32-TRAP-NEXT: break 7 -; LA32-TRAP-NEXT: .LBB7_2: # %entry +; LA32-TRAP-NEXT: .LBB10_2: # %entry ; LA32-TRAP-NEXT: ret ; ; LA64-TRAP-LABEL: udiv_i16: @@ -282,10 +389,10 @@ define i16 @udiv_i16(i16 %a, i16 %b) { ; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 15, 0 ; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 15, 0 ; LA64-TRAP-NEXT: div.du $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB7_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB10_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB7_2: # %entry +; LA64-TRAP-NEXT: .LBB10_2: # %entry ; LA64-TRAP-NEXT: ret entry: %r = udiv i16 %a, %b @@ -308,10 +415,10 @@ define i32 @udiv_i32(i32 %a, i32 %b) { ; LA32-TRAP-LABEL: udiv_i32: ; LA32-TRAP: # %bb.0: # %entry ; LA32-TRAP-NEXT: div.wu $a0, $a0, $a1 -; LA32-TRAP-NEXT: bnez $a1, .LBB8_2 +; LA32-TRAP-NEXT: bnez $a1, .LBB11_2 ; LA32-TRAP-NEXT: # %bb.1: # %entry ; LA32-TRAP-NEXT: break 7 -; LA32-TRAP-NEXT: .LBB8_2: # %entry +; LA32-TRAP-NEXT: .LBB11_2: # %entry ; LA32-TRAP-NEXT: ret ; ; LA64-TRAP-LABEL: udiv_i32: @@ -319,10 +426,125 @@ define i32 @udiv_i32(i32 %a, i32 %b) { ; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 ; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-TRAP-NEXT: div.du $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB8_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB11_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB11_2: # %entry +; LA64-TRAP-NEXT: ret +entry: + %r = udiv i32 %a, %b + ret i32 %r +} + +define i32 @udiv_ui32_si32_si32(i32 signext %a, i32 signext %b) { +; LA32-LABEL: udiv_ui32_si32_si32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: div.wu $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: udiv_ui32_si32_si32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: div.du $a0, $a0, $a1 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: udiv_ui32_si32_si32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: div.wu $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB12_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB12_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: udiv_ui32_si32_si32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-TRAP-NEXT: div.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB12_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB12_2: # %entry +; LA64-TRAP-NEXT: ret +entry: + %r = udiv i32 %a, %b + ret i32 %r +} + +define signext i32 @udiv_si32_ui32_ui32(i32 %a, i32 %b) { +; LA32-LABEL: udiv_si32_ui32_ui32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: div.wu $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: udiv_si32_ui32_ui32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: div.du $a0, $a0, $a1 +; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: udiv_si32_ui32_ui32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: div.wu $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB13_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB13_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: udiv_si32_ui32_ui32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-TRAP-NEXT: div.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB13_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB13_2: # %entry +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 +; LA64-TRAP-NEXT: ret +entry: + %r = udiv i32 %a, %b + ret i32 %r +} + +define signext i32 @udiv_si32_si32_si32(i32 signext %a, i32 signext %b) { +; LA32-LABEL: udiv_si32_si32_si32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: div.wu $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: udiv_si32_si32_si32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: div.du $a0, $a0, $a1 +; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: udiv_si32_si32_si32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: div.wu $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB14_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB14_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: udiv_si32_si32_si32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-TRAP-NEXT: div.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB14_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB8_2: # %entry +; LA64-TRAP-NEXT: .LBB14_2: # %entry +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 ; LA64-TRAP-NEXT: ret entry: %r = udiv i32 %a, %b @@ -360,10 +582,10 @@ define i64 @udiv_i64(i64 %a, i64 %b) { ; LA64-TRAP-LABEL: udiv_i64: ; LA64-TRAP: # %bb.0: # %entry ; LA64-TRAP-NEXT: div.du $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB9_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB15_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB9_2: # %entry +; LA64-TRAP-NEXT: .LBB15_2: # %entry ; LA64-TRAP-NEXT: ret entry: %r = udiv i64 %a, %b @@ -415,10 +637,10 @@ define i8 @srem_i8(i8 %a, i8 %b) { ; LA32-TRAP-NEXT: ext.w.b $a1, $a1 ; LA32-TRAP-NEXT: ext.w.b $a0, $a0 ; LA32-TRAP-NEXT: mod.w $a0, $a0, $a1 -; LA32-TRAP-NEXT: bnez $a1, .LBB11_2 +; LA32-TRAP-NEXT: bnez $a1, .LBB17_2 ; LA32-TRAP-NEXT: # %bb.1: # %entry ; LA32-TRAP-NEXT: break 7 -; LA32-TRAP-NEXT: .LBB11_2: # %entry +; LA32-TRAP-NEXT: .LBB17_2: # %entry ; LA32-TRAP-NEXT: ret ; ; LA64-TRAP-LABEL: srem_i8: @@ -426,10 +648,10 @@ define i8 @srem_i8(i8 %a, i8 %b) { ; LA64-TRAP-NEXT: ext.w.b $a1, $a1 ; LA64-TRAP-NEXT: ext.w.b $a0, $a0 ; LA64-TRAP-NEXT: mod.d $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB11_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB17_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB11_2: # %entry +; LA64-TRAP-NEXT: .LBB17_2: # %entry ; LA64-TRAP-NEXT: ret entry: %r = srem i8 %a, %b @@ -456,10 +678,10 @@ define i16 @srem_i16(i16 %a, i16 %b) { ; LA32-TRAP-NEXT: ext.w.h $a1, $a1 ; LA32-TRAP-NEXT: ext.w.h $a0, $a0 ; LA32-TRAP-NEXT: mod.w $a0, $a0, $a1 -; LA32-TRAP-NEXT: bnez $a1, .LBB12_2 +; LA32-TRAP-NEXT: bnez $a1, .LBB18_2 ; LA32-TRAP-NEXT: # %bb.1: # %entry ; LA32-TRAP-NEXT: break 7 -; LA32-TRAP-NEXT: .LBB12_2: # %entry +; LA32-TRAP-NEXT: .LBB18_2: # %entry ; LA32-TRAP-NEXT: ret ; ; LA64-TRAP-LABEL: srem_i16: @@ -467,10 +689,10 @@ define i16 @srem_i16(i16 %a, i16 %b) { ; LA64-TRAP-NEXT: ext.w.h $a1, $a1 ; LA64-TRAP-NEXT: ext.w.h $a0, $a0 ; LA64-TRAP-NEXT: mod.d $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB12_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB18_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB12_2: # %entry +; LA64-TRAP-NEXT: .LBB18_2: # %entry ; LA64-TRAP-NEXT: ret entry: %r = srem i16 %a, %b @@ -493,10 +715,10 @@ define i32 @srem_i32(i32 %a, i32 %b) { ; LA32-TRAP-LABEL: srem_i32: ; LA32-TRAP: # %bb.0: # %entry ; LA32-TRAP-NEXT: mod.w $a0, $a0, $a1 -; LA32-TRAP-NEXT: bnez $a1, .LBB13_2 +; LA32-TRAP-NEXT: bnez $a1, .LBB19_2 ; LA32-TRAP-NEXT: # %bb.1: # %entry ; LA32-TRAP-NEXT: break 7 -; LA32-TRAP-NEXT: .LBB13_2: # %entry +; LA32-TRAP-NEXT: .LBB19_2: # %entry ; LA32-TRAP-NEXT: ret ; ; LA64-TRAP-LABEL: srem_i32: @@ -504,10 +726,113 @@ define i32 @srem_i32(i32 %a, i32 %b) { ; LA64-TRAP-NEXT: addi.w $a1, $a1, 0 ; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 ; LA64-TRAP-NEXT: mod.d $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB13_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB19_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB13_2: # %entry +; LA64-TRAP-NEXT: .LBB19_2: # %entry +; LA64-TRAP-NEXT: ret +entry: + %r = srem i32 %a, %b + ret i32 %r +} + +define i32 @srem_ui32_si32_si32(i32 signext %a, i32 signext %b) { +; LA32-LABEL: srem_ui32_si32_si32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: mod.w $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: srem_ui32_si32_si32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: mod.d $a0, $a0, $a1 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: srem_ui32_si32_si32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: mod.w $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB20_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB20_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: srem_ui32_si32_si32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: mod.d $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB20_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB20_2: # %entry +; LA64-TRAP-NEXT: ret +entry: + %r = srem i32 %a, %b + ret i32 %r +} + +define signext i32 @srem_si32_ui32_ui32(i32 %a, i32 %b) { +; LA32-LABEL: srem_si32_ui32_ui32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: mod.w $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: srem_si32_ui32_ui32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: addi.w $a1, $a1, 0 +; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: mod.d $a0, $a0, $a1 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: srem_si32_ui32_ui32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: mod.w $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB21_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB21_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: srem_si32_ui32_ui32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: addi.w $a1, $a1, 0 +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 +; LA64-TRAP-NEXT: mod.d $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB21_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB21_2: # %entry +; LA64-TRAP-NEXT: ret +entry: + %r = srem i32 %a, %b + ret i32 %r +} + +define signext i32 @srem_si32_si32_si32(i32 signext %a, i32 signext %b) { +; LA32-LABEL: srem_si32_si32_si32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: mod.w $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: srem_si32_si32_si32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: mod.d $a0, $a0, $a1 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: srem_si32_si32_si32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: mod.w $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB22_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB22_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: srem_si32_si32_si32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: mod.d $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB22_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB22_2: # %entry ; LA64-TRAP-NEXT: ret entry: %r = srem i32 %a, %b @@ -545,10 +870,10 @@ define i64 @srem_i64(i64 %a, i64 %b) { ; LA64-TRAP-LABEL: srem_i64: ; LA64-TRAP: # %bb.0: # %entry ; LA64-TRAP-NEXT: mod.d $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB14_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB23_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB14_2: # %entry +; LA64-TRAP-NEXT: .LBB23_2: # %entry ; LA64-TRAP-NEXT: ret entry: %r = srem i64 %a, %b @@ -600,10 +925,10 @@ define i8 @urem_i8(i8 %a, i8 %b) { ; LA32-TRAP-NEXT: andi $a1, $a1, 255 ; LA32-TRAP-NEXT: andi $a0, $a0, 255 ; LA32-TRAP-NEXT: mod.wu $a0, $a0, $a1 -; LA32-TRAP-NEXT: bnez $a1, .LBB16_2 +; LA32-TRAP-NEXT: bnez $a1, .LBB25_2 ; LA32-TRAP-NEXT: # %bb.1: # %entry ; LA32-TRAP-NEXT: break 7 -; LA32-TRAP-NEXT: .LBB16_2: # %entry +; LA32-TRAP-NEXT: .LBB25_2: # %entry ; LA32-TRAP-NEXT: ret ; ; LA64-TRAP-LABEL: urem_i8: @@ -611,10 +936,10 @@ define i8 @urem_i8(i8 %a, i8 %b) { ; LA64-TRAP-NEXT: andi $a1, $a1, 255 ; LA64-TRAP-NEXT: andi $a0, $a0, 255 ; LA64-TRAP-NEXT: mod.du $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB16_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB25_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB16_2: # %entry +; LA64-TRAP-NEXT: .LBB25_2: # %entry ; LA64-TRAP-NEXT: ret entry: %r = urem i8 %a, %b @@ -641,10 +966,10 @@ define i16 @urem_i16(i16 %a, i16 %b) { ; LA32-TRAP-NEXT: bstrpick.w $a1, $a1, 15, 0 ; LA32-TRAP-NEXT: bstrpick.w $a0, $a0, 15, 0 ; LA32-TRAP-NEXT: mod.wu $a0, $a0, $a1 -; LA32-TRAP-NEXT: bnez $a1, .LBB17_2 +; LA32-TRAP-NEXT: bnez $a1, .LBB26_2 ; LA32-TRAP-NEXT: # %bb.1: # %entry ; LA32-TRAP-NEXT: break 7 -; LA32-TRAP-NEXT: .LBB17_2: # %entry +; LA32-TRAP-NEXT: .LBB26_2: # %entry ; LA32-TRAP-NEXT: ret ; ; LA64-TRAP-LABEL: urem_i16: @@ -652,10 +977,10 @@ define i16 @urem_i16(i16 %a, i16 %b) { ; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 15, 0 ; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 15, 0 ; LA64-TRAP-NEXT: mod.du $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB17_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB26_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB17_2: # %entry +; LA64-TRAP-NEXT: .LBB26_2: # %entry ; LA64-TRAP-NEXT: ret entry: %r = urem i16 %a, %b @@ -678,10 +1003,10 @@ define i32 @urem_i32(i32 %a, i32 %b) { ; LA32-TRAP-LABEL: urem_i32: ; LA32-TRAP: # %bb.0: # %entry ; LA32-TRAP-NEXT: mod.wu $a0, $a0, $a1 -; LA32-TRAP-NEXT: bnez $a1, .LBB18_2 +; LA32-TRAP-NEXT: bnez $a1, .LBB27_2 ; LA32-TRAP-NEXT: # %bb.1: # %entry ; LA32-TRAP-NEXT: break 7 -; LA32-TRAP-NEXT: .LBB18_2: # %entry +; LA32-TRAP-NEXT: .LBB27_2: # %entry ; LA32-TRAP-NEXT: ret ; ; LA64-TRAP-LABEL: urem_i32: @@ -689,10 +1014,125 @@ define i32 @urem_i32(i32 %a, i32 %b) { ; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 ; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-TRAP-NEXT: mod.du $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB18_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB27_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB18_2: # %entry +; LA64-TRAP-NEXT: .LBB27_2: # %entry +; LA64-TRAP-NEXT: ret +entry: + %r = urem i32 %a, %b + ret i32 %r +} + +define i32 @urem_ui32_si32_si32(i32 signext %a, i32 signext %b) { +; LA32-LABEL: urem_ui32_si32_si32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: mod.wu $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: urem_ui32_si32_si32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: mod.du $a0, $a0, $a1 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: urem_ui32_si32_si32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: mod.wu $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB28_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB28_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: urem_ui32_si32_si32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-TRAP-NEXT: mod.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB28_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB28_2: # %entry +; LA64-TRAP-NEXT: ret +entry: + %r = urem i32 %a, %b + ret i32 %r +} + +define signext i32 @urem_si32_ui32_ui32(i32 %a, i32 %b) { +; LA32-LABEL: urem_si32_ui32_ui32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: mod.wu $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: urem_si32_ui32_ui32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: mod.du $a0, $a0, $a1 +; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: urem_si32_ui32_ui32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: mod.wu $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB29_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB29_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: urem_si32_ui32_ui32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-TRAP-NEXT: mod.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB29_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB29_2: # %entry +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 +; LA64-TRAP-NEXT: ret +entry: + %r = urem i32 %a, %b + ret i32 %r +} + +define signext i32 @urem_si32_si32_si32(i32 signext %a, i32 signext %b) { +; LA32-LABEL: urem_si32_si32_si32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: mod.wu $a0, $a0, $a1 +; LA32-NEXT: ret +; +; LA64-LABEL: urem_si32_si32_si32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: mod.du $a0, $a0, $a1 +; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: ret +; +; LA32-TRAP-LABEL: urem_si32_si32_si32: +; LA32-TRAP: # %bb.0: # %entry +; LA32-TRAP-NEXT: mod.wu $a0, $a0, $a1 +; LA32-TRAP-NEXT: bnez $a1, .LBB30_2 +; LA32-TRAP-NEXT: # %bb.1: # %entry +; LA32-TRAP-NEXT: break 7 +; LA32-TRAP-NEXT: .LBB30_2: # %entry +; LA32-TRAP-NEXT: ret +; +; LA64-TRAP-LABEL: urem_si32_si32_si32: +; LA64-TRAP: # %bb.0: # %entry +; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 +; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-TRAP-NEXT: mod.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: bnez $a1, .LBB30_2 +; LA64-TRAP-NEXT: # %bb.1: # %entry +; LA64-TRAP-NEXT: break 7 +; LA64-TRAP-NEXT: .LBB30_2: # %entry +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 ; LA64-TRAP-NEXT: ret entry: %r = urem i32 %a, %b @@ -730,10 +1170,10 @@ define i64 @urem_i64(i64 %a, i64 %b) { ; LA64-TRAP-LABEL: urem_i64: ; LA64-TRAP: # %bb.0: # %entry ; LA64-TRAP-NEXT: mod.du $a0, $a0, $a1 -; LA64-TRAP-NEXT: bnez $a1, .LBB19_2 +; LA64-TRAP-NEXT: bnez $a1, .LBB31_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 -; LA64-TRAP-NEXT: .LBB19_2: # %entry +; LA64-TRAP-NEXT: .LBB31_2: # %entry ; LA64-TRAP-NEXT: ret entry: %r = urem i64 %a, %b -- GitLab From 08536b0f9ccc208ea170b9451026eb1fe1fbb780 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Tue, 14 May 2024 16:19:55 +0100 Subject: [PATCH 244/578] [LAA] refactor tryToCreateDiffCheck (NFC) (#92110) tryToCreateDiffCheck has one caller, and exits early if CanUseDiffCheck is false. Hence, we can get/set CanUseDiffCheck in the caller to avoid wastefully calling tryToCreateDiffCheck. This patch is an NFC simplification of program logic. --- .../llvm/Analysis/LoopAccessAnalysis.h | 2 +- llvm/lib/Analysis/LoopAccessAnalysis.cpp | 55 +++++++------------ 2 files changed, 21 insertions(+), 36 deletions(-) diff --git a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h index 6ebd0fb8477a..c22e1d470f38 100644 --- a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h @@ -540,7 +540,7 @@ private: /// Try to create add a new (pointer-difference, access size) pair to /// DiffCheck for checking groups \p CGI and \p CGJ. If pointer-difference /// checks cannot be used for the groups, set CanUseDiffCheck to false. - void tryToCreateDiffCheck(const RuntimeCheckingPtrGroup &CGI, + bool tryToCreateDiffCheck(const RuntimeCheckingPtrGroup &CGI, const RuntimeCheckingPtrGroup &CGJ); MemoryDepChecker &DC; diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index d071e5332440..e92aa0265a1f 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -250,18 +250,13 @@ void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr, NeedsFreeze); } -void RuntimePointerChecking::tryToCreateDiffCheck( +bool RuntimePointerChecking::tryToCreateDiffCheck( const RuntimeCheckingPtrGroup &CGI, const RuntimeCheckingPtrGroup &CGJ) { - if (!CanUseDiffCheck) - return; - // If either group contains multiple different pointers, bail out. // TODO: Support multiple pointers by using the minimum or maximum pointer, // depending on src & sink. - if (CGI.Members.size() != 1 || CGJ.Members.size() != 1) { - CanUseDiffCheck = false; - return; - } + if (CGI.Members.size() != 1 || CGJ.Members.size() != 1) + return false; PointerInfo *Src = &Pointers[CGI.Members[0]]; PointerInfo *Sink = &Pointers[CGJ.Members[0]]; @@ -269,10 +264,8 @@ void RuntimePointerChecking::tryToCreateDiffCheck( // If either pointer is read and written, multiple checks may be needed. Bail // out. if (!DC.getOrderForAccess(Src->PointerValue, !Src->IsWritePtr).empty() || - !DC.getOrderForAccess(Sink->PointerValue, !Sink->IsWritePtr).empty()) { - CanUseDiffCheck = false; - return; - } + !DC.getOrderForAccess(Sink->PointerValue, !Sink->IsWritePtr).empty()) + return false; ArrayRef AccSrc = DC.getOrderForAccess(Src->PointerValue, Src->IsWritePtr); @@ -280,10 +273,9 @@ void RuntimePointerChecking::tryToCreateDiffCheck( DC.getOrderForAccess(Sink->PointerValue, Sink->IsWritePtr); // If either pointer is accessed multiple times, there may not be a clear // src/sink relation. Bail out for now. - if (AccSrc.size() != 1 || AccSink.size() != 1) { - CanUseDiffCheck = false; - return; - } + if (AccSrc.size() != 1 || AccSink.size() != 1) + return false; + // If the sink is accessed before src, swap src/sink. if (AccSink[0] < AccSrc[0]) std::swap(Src, Sink); @@ -291,10 +283,8 @@ void RuntimePointerChecking::tryToCreateDiffCheck( auto *SrcAR = dyn_cast(Src->Expr); auto *SinkAR = dyn_cast(Sink->Expr); if (!SrcAR || !SinkAR || SrcAR->getLoop() != DC.getInnermostLoop() || - SinkAR->getLoop() != DC.getInnermostLoop()) { - CanUseDiffCheck = false; - return; - } + SinkAR->getLoop() != DC.getInnermostLoop()) + return false; SmallVector SrcInsts = DC.getInstructionsForAccess(Src->PointerValue, Src->IsWritePtr); @@ -302,10 +292,9 @@ void RuntimePointerChecking::tryToCreateDiffCheck( DC.getInstructionsForAccess(Sink->PointerValue, Sink->IsWritePtr); Type *SrcTy = getLoadStoreType(SrcInsts[0]); Type *DstTy = getLoadStoreType(SinkInsts[0]); - if (isa(SrcTy) || isa(DstTy)) { - CanUseDiffCheck = false; - return; - } + if (isa(SrcTy) || isa(DstTy)) + return false; + const DataLayout &DL = SinkAR->getLoop()->getHeader()->getModule()->getDataLayout(); unsigned AllocSize = @@ -316,10 +305,8 @@ void RuntimePointerChecking::tryToCreateDiffCheck( // future. auto *Step = dyn_cast(SinkAR->getStepRecurrence(*SE)); if (!Step || Step != SrcAR->getStepRecurrence(*SE) || - Step->getAPInt().abs() != AllocSize) { - CanUseDiffCheck = false; - return; - } + Step->getAPInt().abs() != AllocSize) + return false; IntegerType *IntTy = IntegerType::get(Src->PointerValue->getContext(), @@ -332,10 +319,8 @@ void RuntimePointerChecking::tryToCreateDiffCheck( const SCEV *SinkStartInt = SE->getPtrToIntExpr(SinkAR->getStart(), IntTy); const SCEV *SrcStartInt = SE->getPtrToIntExpr(SrcAR->getStart(), IntTy); if (isa(SinkStartInt) || - isa(SrcStartInt)) { - CanUseDiffCheck = false; - return; - } + isa(SrcStartInt)) + return false; const Loop *InnerLoop = SrcAR->getLoop(); // If the start values for both Src and Sink also vary according to an outer @@ -356,8 +341,7 @@ void RuntimePointerChecking::tryToCreateDiffCheck( SinkStartAR->getStepRecurrence(*SE)) { LLVM_DEBUG(dbgs() << "LAA: Not creating diff runtime check, since these " "cannot be hoisted out of the outer loop\n"); - CanUseDiffCheck = false; - return; + return false; } } @@ -366,6 +350,7 @@ void RuntimePointerChecking::tryToCreateDiffCheck( << "SinkStartInt: " << *SinkStartInt << '\n'); DiffChecks.emplace_back(SrcStartInt, SinkStartInt, AllocSize, Src->NeedsFreeze || Sink->NeedsFreeze); + return true; } SmallVector RuntimePointerChecking::generateChecks() { @@ -377,7 +362,7 @@ SmallVector RuntimePointerChecking::generateChecks() { const RuntimeCheckingPtrGroup &CGJ = CheckingGroups[J]; if (needsChecking(CGI, CGJ)) { - tryToCreateDiffCheck(CGI, CGJ); + CanUseDiffCheck = CanUseDiffCheck && tryToCreateDiffCheck(CGI, CGJ); Checks.push_back(std::make_pair(&CGI, &CGJ)); } } -- GitLab From 3d6f18db7b5bbf85bdd40c7c7d627baff2802b7c Mon Sep 17 00:00:00 2001 From: Sander de Smalen Date: Tue, 14 May 2024 16:28:28 +0100 Subject: [PATCH 245/578] [AArch64] Remove redundant FDIV Combine. (#91924) The target combine is no longer required because InstCombine will transform the DIV by a power of 2 into a multiply, so in practice this case will never trigger. Additionally, the generated code would have been incorrect for streaming(-compatible) functions, because it assumed NEON was available. --- .../Target/AArch64/AArch64ISelLowering.cpp | 73 +--------- llvm/test/CodeGen/AArch64/fdiv_combine.ll | 126 ------------------ .../CodeGen/AArch64/sitofp-fixed-legal.ll | 42 ------ 3 files changed, 1 insertion(+), 240 deletions(-) delete mode 100644 llvm/test/CodeGen/AArch64/fdiv_combine.ll delete mode 100644 llvm/test/CodeGen/AArch64/sitofp-fixed-legal.ll diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index f6d80f78910c..2ec9f66214b6 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -1040,7 +1040,7 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM, ISD::UINT_TO_FP}); setTargetDAGCombine({ISD::FP_TO_SINT, ISD::FP_TO_UINT, ISD::FP_TO_SINT_SAT, - ISD::FP_TO_UINT_SAT, ISD::FADD, ISD::FDIV}); + ISD::FP_TO_UINT_SAT, ISD::FADD}); // Try and combine setcc with csel setTargetDAGCombine(ISD::SETCC); @@ -17963,75 +17963,6 @@ static SDValue performFpToIntCombine(SDNode *N, SelectionDAG &DAG, return FixConv; } -/// Fold a floating-point divide by power of two into fixed-point to -/// floating-point conversion. -static SDValue performFDivCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const AArch64Subtarget *Subtarget) { - if (!Subtarget->hasNEON()) - return SDValue(); - - SDValue Op = N->getOperand(0); - unsigned Opc = Op->getOpcode(); - if (!Op.getValueType().isVector() || !Op.getValueType().isSimple() || - !Op.getOperand(0).getValueType().isSimple() || - (Opc != ISD::SINT_TO_FP && Opc != ISD::UINT_TO_FP)) - return SDValue(); - - SDValue ConstVec = N->getOperand(1); - if (!isa(ConstVec)) - return SDValue(); - - MVT IntTy = Op.getOperand(0).getSimpleValueType().getVectorElementType(); - int32_t IntBits = IntTy.getSizeInBits(); - if (IntBits != 16 && IntBits != 32 && IntBits != 64) - return SDValue(); - - MVT FloatTy = N->getSimpleValueType(0).getVectorElementType(); - int32_t FloatBits = FloatTy.getSizeInBits(); - if (FloatBits != 32 && FloatBits != 64) - return SDValue(); - - // Avoid conversions where iN is larger than the float (e.g., i64 -> float). - if (IntBits > FloatBits) - return SDValue(); - - BitVector UndefElements; - BuildVectorSDNode *BV = cast(ConstVec); - int32_t C = BV->getConstantFPSplatPow2ToLog2Int(&UndefElements, FloatBits + 1); - if (C == -1 || C == 0 || C > FloatBits) - return SDValue(); - - MVT ResTy; - unsigned NumLanes = Op.getValueType().getVectorNumElements(); - switch (NumLanes) { - default: - return SDValue(); - case 2: - ResTy = FloatBits == 32 ? MVT::v2i32 : MVT::v2i64; - break; - case 4: - ResTy = FloatBits == 32 ? MVT::v4i32 : MVT::v4i64; - break; - } - - if (ResTy == MVT::v4i64 && DCI.isBeforeLegalizeOps()) - return SDValue(); - - SDLoc DL(N); - SDValue ConvInput = Op.getOperand(0); - bool IsSigned = Opc == ISD::SINT_TO_FP; - if (IntBits < FloatBits) - ConvInput = DAG.getNode(IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, DL, - ResTy, ConvInput); - - unsigned IntrinsicOpcode = IsSigned ? Intrinsic::aarch64_neon_vcvtfxs2fp - : Intrinsic::aarch64_neon_vcvtfxu2fp; - return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Op.getValueType(), - DAG.getConstant(IntrinsicOpcode, DL, MVT::i32), ConvInput, - DAG.getConstant(C, DL, MVT::i32)); -} - static SDValue tryCombineToBSL(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const AArch64TargetLowering &TLI) { EVT VT = N->getValueType(0); @@ -24720,8 +24651,6 @@ SDValue AArch64TargetLowering::PerformDAGCombine(SDNode *N, case ISD::FP_TO_SINT_SAT: case ISD::FP_TO_UINT_SAT: return performFpToIntCombine(N, DAG, DCI, Subtarget); - case ISD::FDIV: - return performFDivCombine(N, DAG, DCI, Subtarget); case ISD::OR: return performORCombine(N, DCI, Subtarget, *this); case ISD::AND: diff --git a/llvm/test/CodeGen/AArch64/fdiv_combine.ll b/llvm/test/CodeGen/AArch64/fdiv_combine.ll deleted file mode 100644 index 10b5f4386dd5..000000000000 --- a/llvm/test/CodeGen/AArch64/fdiv_combine.ll +++ /dev/null @@ -1,126 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=aarch64-linux-gnu -aarch64-neon-syntax=apple -verify-machineinstrs -o - %s | FileCheck %s - -; Test signed conversion. -define <2 x float> @test1(<2 x i32> %in) { -; CHECK-LABEL: test1: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: scvtf.2s v0, v0, #4 -; CHECK-NEXT: ret -entry: - %vcvt.i = sitofp <2 x i32> %in to <2 x float> - %div.i = fdiv <2 x float> %vcvt.i, - ret <2 x float> %div.i -} - -; Test unsigned conversion. -define <2 x float> @test2(<2 x i32> %in) { -; CHECK-LABEL: test2: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: ucvtf.2s v0, v0, #3 -; CHECK-NEXT: ret -entry: - %vcvt.i = uitofp <2 x i32> %in to <2 x float> - %div.i = fdiv <2 x float> %vcvt.i, - ret <2 x float> %div.i -} - -; Test which should not fold due to non-power of 2. -define <2 x float> @test3(<2 x i32> %in) { -; CHECK-LABEL: test3: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fmov.2s v1, #9.00000000 -; CHECK-NEXT: scvtf.2s v0, v0 -; CHECK-NEXT: fdiv.2s v0, v0, v1 -; CHECK-NEXT: ret -entry: - %vcvt.i = sitofp <2 x i32> %in to <2 x float> - %div.i = fdiv <2 x float> %vcvt.i, - ret <2 x float> %div.i -} - -; Test which should not fold due to power of 2 out of range. -define <2 x float> @test4(<2 x i32> %in) { -; CHECK-LABEL: test4: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: movi.2s v1, #80, lsl #24 -; CHECK-NEXT: scvtf.2s v0, v0 -; CHECK-NEXT: fdiv.2s v0, v0, v1 -; CHECK-NEXT: ret -entry: - %vcvt.i = sitofp <2 x i32> %in to <2 x float> - %div.i = fdiv <2 x float> %vcvt.i, - ret <2 x float> %div.i -} - -; Test case where const is max power of 2 (i.e., 2^32). -define <2 x float> @test5(<2 x i32> %in) { -; CHECK-LABEL: test5: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: scvtf.2s v0, v0, #32 -; CHECK-NEXT: ret -entry: - %vcvt.i = sitofp <2 x i32> %in to <2 x float> - %div.i = fdiv <2 x float> %vcvt.i, - ret <2 x float> %div.i -} - -; Test quadword. -define <4 x float> @test6(<4 x i32> %in) { -; CHECK-LABEL: test6: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: scvtf.4s v0, v0, #2 -; CHECK-NEXT: ret -entry: - %vcvt.i = sitofp <4 x i32> %in to <4 x float> - %div.i = fdiv <4 x float> %vcvt.i, - ret <4 x float> %div.i -} - -; Test unsigned i16 to float -define <4 x float> @test7(<4 x i16> %in) { -; CHECK-LABEL: test7: -; CHECK: // %bb.0: -; CHECK-NEXT: ushll.4s v0, v0, #0 -; CHECK-NEXT: ucvtf.4s v0, v0, #1 -; CHECK-NEXT: ret - %conv = uitofp <4 x i16> %in to <4 x float> - %shift = fdiv <4 x float> %conv, - ret <4 x float> %shift -} - -; Test signed i16 to float -define <4 x float> @test8(<4 x i16> %in) { -; CHECK-LABEL: test8: -; CHECK: // %bb.0: -; CHECK-NEXT: sshll.4s v0, v0, #0 -; CHECK-NEXT: scvtf.4s v0, v0, #2 -; CHECK-NEXT: ret - %conv = sitofp <4 x i16> %in to <4 x float> - %shift = fdiv <4 x float> %conv, - ret <4 x float> %shift -} - -; Can't convert i64 to float. -define <2 x float> @test9(<2 x i64> %in) { -; CHECK-LABEL: test9: -; CHECK: // %bb.0: -; CHECK-NEXT: ucvtf.2d v0, v0 -; CHECK-NEXT: movi.2s v1, #64, lsl #24 -; CHECK-NEXT: fcvtn v0.2s, v0.2d -; CHECK-NEXT: fdiv.2s v0, v0, v1 -; CHECK-NEXT: ret - %conv = uitofp <2 x i64> %in to <2 x float> - %shift = fdiv <2 x float> %conv, - ret <2 x float> %shift -} - -define <2 x double> @test10(<2 x i64> %in) { -; CHECK-LABEL: test10: -; CHECK: // %bb.0: -; CHECK-NEXT: ucvtf.2d v0, v0, #1 -; CHECK-NEXT: ret - %conv = uitofp <2 x i64> %in to <2 x double> - %shift = fdiv <2 x double> %conv, - ret <2 x double> %shift -} diff --git a/llvm/test/CodeGen/AArch64/sitofp-fixed-legal.ll b/llvm/test/CodeGen/AArch64/sitofp-fixed-legal.ll deleted file mode 100644 index 5a5a669e92ee..000000000000 --- a/llvm/test/CodeGen/AArch64/sitofp-fixed-legal.ll +++ /dev/null @@ -1,42 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=aarch64-apple-ios %s -o - | FileCheck %s - -define <16 x double> @test_sitofp_fixed(<16 x i32> %in) { -; CHECK-LABEL: test_sitofp_fixed: -; CHECK: ; %bb.0: -; CHECK-NEXT: sshll2.2d v4, v0, #0 -; CHECK-NEXT: sshll.2d v0, v0, #0 -; CHECK-NEXT: sshll2.2d v5, v1, #0 -; CHECK-NEXT: sshll.2d v6, v1, #0 -; CHECK-NEXT: sshll.2d v7, v2, #0 -; CHECK-NEXT: sshll2.2d v16, v2, #0 -; CHECK-NEXT: sshll2.2d v17, v3, #0 -; CHECK-NEXT: sshll.2d v18, v3, #0 -; CHECK-NEXT: scvtf.2d v1, v4, #6 -; CHECK-NEXT: scvtf.2d v0, v0, #6 -; CHECK-NEXT: scvtf.2d v3, v5, #6 -; CHECK-NEXT: scvtf.2d v2, v6, #6 -; CHECK-NEXT: scvtf.2d v4, v7, #6 -; CHECK-NEXT: scvtf.2d v5, v16, #6 -; CHECK-NEXT: scvtf.2d v7, v17, #6 -; CHECK-NEXT: scvtf.2d v6, v18, #6 -; CHECK-NEXT: ret - - %flt = sitofp <16 x i32> %in to <16 x double> - %res = fdiv <16 x double> %flt, - ret <16 x double> %res -} - -; This one is small enough to satisfy isSimple, but still illegally large. -define <4 x double> @test_sitofp_fixed_shortish(<4 x i64> %in) { -; CHECK-LABEL: test_sitofp_fixed_shortish: -; CHECK: ; %bb.0: -; CHECK-NEXT: scvtf.2d v0, v0, #6 -; CHECK-NEXT: scvtf.2d v1, v1, #6 -; CHECK-NEXT: ret - - - %flt = sitofp <4 x i64> %in to <4 x double> - %res = fdiv <4 x double> %flt, - ret <4 x double> %res -} -- GitLab From b2c5e9b9bf2a1cb4a8d4fc67f3201db55ae2cae1 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 14 May 2024 16:36:25 +0100 Subject: [PATCH 246/578] [ARM] iabs.ll - regenerate test checks --- llvm/test/CodeGen/ARM/iabs.ll | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/llvm/test/CodeGen/ARM/iabs.ll b/llvm/test/CodeGen/ARM/iabs.ll index bcedcc8fe63b..fffa9555b296 100644 --- a/llvm/test/CodeGen/ARM/iabs.ll +++ b/llvm/test/CodeGen/ARM/iabs.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 ; RUN: llc -mtriple=arm-eabi -mattr=+v4t %s -o - | FileCheck %s ;; Integer absolute value, should produce something as good as: ARM: @@ -6,13 +7,15 @@ ;; bx lr define i32 @test(i32 %a) { - %tmp1neg = sub i32 0, %a - %b = icmp sgt i32 %a, -1 - %abs = select i1 %b, i32 %a, i32 %tmp1neg - ret i32 %abs -; CHECK: cmp -; CHECK: rsbmi r0, r0, #0 -; CHECK: bx lr +; CHECK-LABEL: test: +; CHECK: @ %bb.0: +; CHECK-NEXT: cmp r0, #0 +; CHECK-NEXT: rsbmi r0, r0, #0 +; CHECK-NEXT: bx lr + %tmp1neg = sub i32 0, %a + %b = icmp sgt i32 %a, -1 + %abs = select i1 %b, i32 %a, i32 %tmp1neg + ret i32 %abs } ; rdar://11633193 @@ -21,11 +24,12 @@ define i32 @test(i32 %a) { ;; rsbmi ;; bx define i32 @test2(i32 %a, i32 %b) nounwind readnone ssp { +; CHECK-LABEL: test2: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: subs r0, r0, r1 +; CHECK-NEXT: rsbmi r0, r0, #0 +; CHECK-NEXT: bx lr entry: -; CHECK: test2 -; CHECK: subs -; CHECK-NEXT: rsbmi -; CHECK-NEXT: bx %sub = sub nsw i32 %a, %b %cmp = icmp sgt i32 %sub, -1 %sub1 = sub nsw i32 0, %sub -- GitLab From 0f17d9a28c40eebd42c83956e2a7b5186c1814d7 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Tue, 14 May 2024 20:05:22 +0400 Subject: [PATCH 247/578] [lldb] Fixed the test TestThreadStates when run with a remote target (#92086) self.wait_for_running_event(process) is always called after self.runCmd("continue"). It is strange to expect eStateConnected here. This test failed in case of a remote target. The correct state is eStateRunning. Removed incorrect checking. --- .../test/API/functionalities/thread/state/TestThreadStates.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lldb/test/API/functionalities/thread/state/TestThreadStates.py b/lldb/test/API/functionalities/thread/state/TestThreadStates.py index f4c17df52338..4dbe230c0ce8 100644 --- a/lldb/test/API/functionalities/thread/state/TestThreadStates.py +++ b/lldb/test/API/functionalities/thread/state/TestThreadStates.py @@ -102,10 +102,6 @@ class ThreadStateTestCase(TestBase): def wait_for_running_event(self, process): listener = self.dbg.GetListener() - if lldb.remote_platform: - lldbutil.expect_state_changes( - self, listener, process, [lldb.eStateConnected] - ) lldbutil.expect_state_changes(self, listener, process, [lldb.eStateRunning]) def thread_state_after_continue_test(self): -- GitLab From 4c68de5a0027fca9ebff5f8ffec3a35a43d14e74 Mon Sep 17 00:00:00 2001 From: Min-Yih Hsu Date: Tue, 14 May 2024 09:18:08 -0700 Subject: [PATCH 248/578] [RISCV][CostModel] Add cost model for experimental.cttz.elts (#91778) The cost of `experimental.cttz.elts` in RISC-V equals to the cost of vfirst when the zero_is_poison argument is true. Otherwise, we add additional costs of cmp + select to convert the -1 result from vfirst to EVL. --- llvm/lib/Target/RISCV/RISCVISelLowering.h | 4 +- .../Target/RISCV/RISCVTargetTransformInfo.cpp | 21 ++++++++ .../Analysis/CostModel/RISCV/cttz_elts.ll | 48 +++++++++---------- 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index afc317f94dae..1efc54566b4b 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -567,6 +567,8 @@ public: shouldExpandBuildVectorWithShuffles(EVT VT, unsigned DefinedValues) const override; + bool shouldExpandCttzElements(EVT VT) const override; + /// Return the cost of LMUL for linear operations. InstructionCost getLMULCost(MVT VT) const; @@ -1001,8 +1003,6 @@ private: bool shouldExpandGetVectorLength(EVT TripCountVT, unsigned VF, bool IsScalable) const override; - bool shouldExpandCttzElements(EVT VT) const override; - /// RVV code generation for fixed length vectors does not lower all /// BUILD_VECTORs. This makes BUILD_VECTOR legalisation a source of stores to /// merge. However, merging them creates a BUILD_VECTOR that is just as diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index d94dff5f2b1f..4d2479fc233f 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -97,6 +97,7 @@ RISCVTTIImpl::getRISCVInstructionCost(ArrayRef OpCodes, MVT VT, case RISCV::VMANDN_MM: case RISCV::VMNAND_MM: case RISCV::VCPOP_M: + case RISCV::VFIRST_M: Cost += 1; break; default: @@ -901,6 +902,26 @@ RISCVTTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, getRISCVInstructionCost(RISCV::VADD_VX, LT.second, CostKind); return 1 + (LT.first - 1); } + case Intrinsic::experimental_cttz_elts: { + Type *ArgTy = ICA.getArgTypes()[0]; + EVT ArgType = TLI->getValueType(DL, ArgTy, true); + if (getTLI()->shouldExpandCttzElements(ArgType)) + break; + InstructionCost Cost = getRISCVInstructionCost( + RISCV::VFIRST_M, getTypeLegalizationCost(ArgTy).second, CostKind); + + // If zero_is_poison is false, then we will generate additional + // cmp + select instructions to convert -1 to EVL. + Type *BoolTy = Type::getInt1Ty(RetTy->getContext()); + if (ICA.getArgs().size() > 1 && + cast(ICA.getArgs()[1])->isZero()) + Cost += getCmpSelInstrCost(Instruction::ICmp, BoolTy, RetTy, + CmpInst::ICMP_SLT, CostKind) + + getCmpSelInstrCost(Instruction::Select, RetTy, BoolTy, + CmpInst::BAD_ICMP_PREDICATE, CostKind); + + return Cost; + } case Intrinsic::vp_rint: { // RISC-V target uses at least 5 instructions to lower rounding intrinsics. unsigned Cost = 5; diff --git a/llvm/test/Analysis/CostModel/RISCV/cttz_elts.ll b/llvm/test/Analysis/CostModel/RISCV/cttz_elts.ll index ca09d027b547..118d92b80d25 100644 --- a/llvm/test/Analysis/CostModel/RISCV/cttz_elts.ll +++ b/llvm/test/Analysis/CostModel/RISCV/cttz_elts.ll @@ -17,19 +17,19 @@ define void @foo_no_vscale_range() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv32i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv64i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv64i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 390 for instruction: %res.i32.nxv128i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv128i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv2i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv4i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv8i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv16i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv16i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv32i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv32i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv64i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv64i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv2i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv4i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv8i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv16i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv16i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv32i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv32i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv64i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv64i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 781 for instruction: %res.i64.nxv128i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv128i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv2i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv4i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv8i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv16i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv16i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv32i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv64i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv64i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv2i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv4i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv8i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv16i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv16i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv32i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv64i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv64i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 390 for instruction: %res.i32.nxv128i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv128i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -83,19 +83,19 @@ define void @foo_vscale_range_2_16() vscale_range(2,16) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv32i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv64i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv64i1( undef, i1 true) ; CHECK-NEXT: Cost Model: Found an estimated cost of 195 for instruction: %res.i32.nxv128i1.zip = call i32 @llvm.experimental.cttz.elts.i32.nxv128i1( undef, i1 true) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv2i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv4i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv8i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv16i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv16i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv32i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv32i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i64.nxv64i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv64i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv2i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv2i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv4i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv4i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv8i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv8i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv16i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv16i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv32i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv32i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i64.nxv64i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv64i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 195 for instruction: %res.i64.nxv128i1.nzip = call i64 @llvm.experimental.cttz.elts.i64.nxv128i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv2i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv4i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv8i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv16i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv16i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv32i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 false) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %res.i32.nxv64i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv64i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv2i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv2i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv4i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv4i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv8i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv8i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv16i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv16i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv32i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv32i1( undef, i1 false) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %res.i32.nxv64i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv64i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 195 for instruction: %res.i32.nxv128i1.nzip = call i32 @llvm.experimental.cttz.elts.i32.nxv128i1( undef, i1 false) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; -- GitLab From 8019cbbbbc94658d133583f7be6cd0023d30b0f3 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 14 May 2024 12:28:58 -0400 Subject: [PATCH 249/578] [Clang][Sema] Earlier type checking for builtin unary operators (#90500) Currently, clang postpones all semantic analysis of unary operators with operands of pointer/pointer to member/array/function type until instantiation whenever that type is dependent (e.g. `T*` where `T` is a type template parameter). Consequently, the uninstantiated AST nodes all have the type `ASTContext::DependentTy` (which, for the purposes of #90152, is undesirable as that type may be the current instantiation! (e.g. `*this`)) This patch moves the point at which we perform semantic analysis for such expression to be prior to instantiation. --- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/AST/Type.h | 5 +- clang/lib/Sema/SemaExpr.cpp | 354 +++++++++--------- clang/test/AST/ast-dump-expr-json.cpp | 4 +- clang/test/AST/ast-dump-expr.cpp | 2 +- clang/test/AST/ast-dump-lambda.cpp | 2 +- .../expr/expr.unary/expr.unary.general/p1.cpp | 65 ++++ clang/test/CXX/over/over.built/ast.cpp | 158 ++++++-- clang/test/CXX/over/over.built/p10.cpp | 2 +- clang/test/CXX/over/over.built/p11.cpp | 2 +- .../temp.res/temp.dep/temp.dep.type/p4.cpp | 25 +- clang/test/Frontend/noderef_templates.cpp | 4 +- clang/test/SemaCXX/cxx2b-deducing-this.cpp | 6 +- .../test/SemaTemplate/class-template-spec.cpp | 12 +- .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 6 +- 15 files changed, 404 insertions(+), 246 deletions(-) create mode 100644 clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 49ab222bec40..a2e44efe4134 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -55,6 +55,9 @@ C++ Specific Potentially Breaking Changes - Clang now rejects pointer to member from parenthesized expression in unevaluated context such as ``decltype(&(foo::bar))``. (#GH40906). +- 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. + ABI Changes in This Version --------------------------- - Fixed Microsoft name mangling of implicitly defined variables used for thread diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index e6643469e0b3..da3834f19ca0 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -8044,7 +8044,10 @@ inline bool Type::isUndeducedType() const { /// Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { - return isDependentType() || isRecordType() || isEnumeralType(); + if (!CanonicalType->isDependentType()) + return isRecordType() || isEnumeralType(); + return !isArrayType() && !isFunctionType() && !isAnyPointerType() && + !isMemberPointerType(); } /// Determines whether this type is written as a typedef-name. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index e6c3fa51d54d..18fd5ba700ad 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -672,12 +672,12 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // We don't want to throw lvalue-to-rvalue casts on top of // expressions of certain types in C++. - if (getLangOpts().CPlusPlus && - (E->getType() == Context.OverloadTy || - // FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied - // to pointer types even if the pointee type is dependent. - (T->isDependentType() && !T->isPointerType()) || T->isRecordType())) - return E; + if (getLangOpts().CPlusPlus) { + if (T == Context.OverloadTy || T->isRecordType() || + (T->isDependentType() && !T->isAnyPointerType() && + !T->isMemberPointerType())) + return E; + } // The C standard is actually really unclear on this point, and // DR106 tells us what the result should be but not why. It's @@ -10827,7 +10827,7 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc, if (const AtomicType *ResAtomicType = ResType->getAs()) ResType = ResAtomicType->getValueType(); - assert(ResType->isAnyPointerType() && !ResType->isDependentType()); + assert(ResType->isAnyPointerType()); QualType PointeeTy = ResType->getPointeeType(); return S.RequireCompleteSizedType( Loc, PointeeTy, @@ -13955,11 +13955,8 @@ static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS, static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, ExprValueKind &VK, ExprObjectKind &OK, - SourceLocation OpLoc, - bool IsInc, bool IsPrefix) { - if (Op->isTypeDependent()) - return S.Context.DependentTy; - + SourceLocation OpLoc, bool IsInc, + bool IsPrefix) { QualType ResType = Op->getType(); // Atomic types can be used for increment / decrement where the non-atomic // versions can, so ignore the _Atomic() specifier for the purpose of @@ -14041,7 +14038,6 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, } } - /// getPrimaryDecl - Helper function for CheckAddressOfOperand(). /// This routine allows us to typecheck complex/recursive expressions /// where the declaration is needed for type checking. We only need to @@ -14411,9 +14407,6 @@ static void RecordModifiableNonNullParam(Sema &S, const Expr *Exp) { static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, SourceLocation OpLoc, bool IsAfterAmp = false) { - if (Op->isTypeDependent()) - return S.Context.DependentTy; - ExprResult ConvResult = S.UsualUnaryConversions(Op); if (ConvResult.isInvalid()) return QualType(); @@ -15467,188 +15460,191 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 1); } - switch (Opc) { - case UO_PreInc: - case UO_PreDec: - case UO_PostInc: - case UO_PostDec: - resultType = CheckIncrementDecrementOperand(*this, Input.get(), VK, OK, - OpLoc, - Opc == UO_PreInc || - Opc == UO_PostInc, - Opc == UO_PreInc || - Opc == UO_PreDec); - CanOverflow = isOverflowingIntegerType(Context, resultType); - break; - case UO_AddrOf: - resultType = CheckAddressOfOperand(Input, OpLoc); - CheckAddressOfNoDeref(InputExpr); - RecordModifiableNonNullParam(*this, InputExpr); - break; - case UO_Deref: { - Input = DefaultFunctionArrayLvalueConversion(Input.get()); - if (Input.isInvalid()) return ExprError(); - resultType = - CheckIndirectionOperand(*this, Input.get(), VK, OpLoc, IsAfterAmp); - break; - } - case UO_Plus: - case UO_Minus: - CanOverflow = Opc == UO_Minus && - isOverflowingIntegerType(Context, Input.get()->getType()); - Input = UsualUnaryConversions(Input.get()); - if (Input.isInvalid()) return ExprError(); - // Unary plus and minus require promoting an operand of half vector to a - // float vector and truncating the result back to a half vector. For now, we - // do this only when HalfArgsAndReturns is set (that is, when the target is - // arm or arm64). - ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get()); - - // If the operand is a half vector, promote it to a float vector. - if (ConvertHalfVec) - Input = convertVector(Input.get(), Context.FloatTy, *this); - resultType = Input.get()->getType(); - if (resultType->isDependentType()) - break; - if (resultType->isArithmeticType()) // C99 6.5.3.3p1 - break; - else if (resultType->isVectorType() && - // The z vector extensions don't allow + or - with bool vectors. - (!Context.getLangOpts().ZVector || - resultType->castAs()->getVectorKind() != - VectorKind::AltiVecBool)) - break; - else if (resultType->isSveVLSBuiltinType()) // SVE vectors allow + and - - break; - else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 - Opc == UO_Plus && - resultType->isPointerType()) + if (InputExpr->isTypeDependent() && + InputExpr->getType()->isSpecificBuiltinType(BuiltinType::Dependent)) { + resultType = Context.DependentTy; + } else { + switch (Opc) { + case UO_PreInc: + case UO_PreDec: + case UO_PostInc: + case UO_PostDec: + resultType = + CheckIncrementDecrementOperand(*this, Input.get(), VK, OK, OpLoc, + Opc == UO_PreInc || Opc == UO_PostInc, + Opc == UO_PreInc || Opc == UO_PreDec); + CanOverflow = isOverflowingIntegerType(Context, resultType); break; - - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - - case UO_Not: // bitwise complement - Input = UsualUnaryConversions(Input.get()); - if (Input.isInvalid()) - return ExprError(); - resultType = Input.get()->getType(); - if (resultType->isDependentType()) + case UO_AddrOf: + resultType = CheckAddressOfOperand(Input, OpLoc); + CheckAddressOfNoDeref(InputExpr); + RecordModifiableNonNullParam(*this, InputExpr); break; - // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. - if (resultType->isComplexType() || resultType->isComplexIntegerType()) - // C99 does not support '~' for complex conjugation. - Diag(OpLoc, diag::ext_integer_complement_complex) - << resultType << Input.get()->getSourceRange(); - else if (resultType->hasIntegerRepresentation()) + case UO_Deref: { + Input = DefaultFunctionArrayLvalueConversion(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = + CheckIndirectionOperand(*this, Input.get(), VK, OpLoc, IsAfterAmp); break; - else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { - // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate - // on vector float types. - QualType T = resultType->castAs()->getElementType(); - if (!T->isIntegerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } else { - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - break; - - case UO_LNot: // logical negation - // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). - Input = DefaultFunctionArrayLvalueConversion(Input.get()); - if (Input.isInvalid()) return ExprError(); - resultType = Input.get()->getType(); - - // Though we still have to promote half FP to float... - if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) { - Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast).get(); - resultType = Context.FloatTy; } + case UO_Plus: + case UO_Minus: + CanOverflow = Opc == UO_Minus && + isOverflowingIntegerType(Context, Input.get()->getType()); + Input = UsualUnaryConversions(Input.get()); + if (Input.isInvalid()) + return ExprError(); + // Unary plus and minus require promoting an operand of half vector to a + // float vector and truncating the result back to a half vector. For now, + // we do this only when HalfArgsAndReturns is set (that is, when the + // target is arm or arm64). + ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get()); + + // If the operand is a half vector, promote it to a float vector. + if (ConvertHalfVec) + Input = convertVector(Input.get(), Context.FloatTy, *this); + resultType = Input.get()->getType(); + if (resultType->isArithmeticType()) // C99 6.5.3.3p1 + break; + else if (resultType->isVectorType() && + // The z vector extensions don't allow + or - with bool vectors. + (!Context.getLangOpts().ZVector || + resultType->castAs()->getVectorKind() != + VectorKind::AltiVecBool)) + break; + else if (resultType->isSveVLSBuiltinType()) // SVE vectors allow + and - + break; + else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 + Opc == UO_Plus && resultType->isPointerType()) + break; - // WebAsembly tables can't be used in unary expressions. - if (resultType->isPointerType() && - resultType->getPointeeType().isWebAssemblyReferenceType()) { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); - } - if (resultType->isDependentType()) - break; - if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) { - // C99 6.5.3.3p1: ok, fallthrough; - if (Context.getLangOpts().CPlusPlus) { - // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: - // operand contextually converted to bool. - Input = ImpCastExprToType(Input.get(), Context.BoolTy, - ScalarTypeToBooleanCastKind(resultType)); - } else if (Context.getLangOpts().OpenCL && - Context.getLangOpts().OpenCLVersion < 120) { - // OpenCL v1.1 6.3.h: The logical operator not (!) does not - // operate on scalar float types. - if (!resultType->isIntegerType() && !resultType->isPointerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - } else if (resultType->isExtVectorType()) { - if (Context.getLangOpts().OpenCL && - Context.getLangOpts().getOpenCLCompatibleVersion() < 120) { - // OpenCL v1.1 6.3.h: The logical operator not (!) does not - // operate on vector float types. + case UO_Not: // bitwise complement + Input = UsualUnaryConversions(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = Input.get()->getType(); + // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. + if (resultType->isComplexType() || resultType->isComplexIntegerType()) + // C99 does not support '~' for complex conjugation. + Diag(OpLoc, diag::ext_integer_complement_complex) + << resultType << Input.get()->getSourceRange(); + else if (resultType->hasIntegerRepresentation()) + break; + else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate + // on vector float types. QualType T = resultType->castAs()->getElementType(); if (!T->isIntegerType()) return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); } - // Vector logical not returns the signed variant of the operand type. - resultType = GetSignedVectorType(resultType); break; - } else if (Context.getLangOpts().CPlusPlus && resultType->isVectorType()) { - const VectorType *VTy = resultType->castAs(); - if (VTy->getVectorKind() != VectorKind::Generic) + + case UO_LNot: // logical negation + // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). + Input = DefaultFunctionArrayLvalueConversion(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = Input.get()->getType(); + + // Though we still have to promote half FP to float... + if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) { + Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast) + .get(); + resultType = Context.FloatTy; + } + + // WebAsembly tables can't be used in unary expressions. + if (resultType->isPointerType() && + resultType->getPointeeType().isWebAssemblyReferenceType()) { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); + } - // Vector logical not returns the signed variant of the operand type. - resultType = GetSignedVectorType(resultType); - break; - } else { - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } + if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) { + // C99 6.5.3.3p1: ok, fallthrough; + if (Context.getLangOpts().CPlusPlus) { + // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: + // operand contextually converted to bool. + Input = ImpCastExprToType(Input.get(), Context.BoolTy, + ScalarTypeToBooleanCastKind(resultType)); + } else if (Context.getLangOpts().OpenCL && + Context.getLangOpts().OpenCLVersion < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on scalar float types. + if (!resultType->isIntegerType() && !resultType->isPointerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + } else if (resultType->isExtVectorType()) { + if (Context.getLangOpts().OpenCL && + Context.getLangOpts().getOpenCLCompatibleVersion() < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on vector float types. + QualType T = resultType->castAs()->getElementType(); + if (!T->isIntegerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; + } else if (Context.getLangOpts().CPlusPlus && + resultType->isVectorType()) { + const VectorType *VTy = resultType->castAs(); + if (VTy->getVectorKind() != VectorKind::Generic) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); - // LNot always has type int. C99 6.5.3.3p5. - // In C++, it's bool. C++ 5.3.1p8 - resultType = Context.getLogicalOperationType(); - break; - case UO_Real: - case UO_Imag: - resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); - // _Real maps ordinary l-values into ordinary l-values. _Imag maps ordinary - // complex l-values to ordinary l-values and all other values to r-values. - if (Input.isInvalid()) return ExprError(); - if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { - if (Input.get()->isGLValue() && - Input.get()->getObjectKind() == OK_Ordinary) - VK = Input.get()->getValueKind(); - } else if (!getLangOpts().CPlusPlus) { - // In C, a volatile scalar is read by __imag. In C++, it is not. - Input = DefaultLvalueConversion(Input.get()); + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + + // LNot always has type int. C99 6.5.3.3p5. + // In C++, it's bool. C++ 5.3.1p8 + resultType = Context.getLogicalOperationType(); + break; + case UO_Real: + case UO_Imag: + resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); + // _Real maps ordinary l-values into ordinary l-values. _Imag maps + // ordinary complex l-values to ordinary l-values and all other values to + // r-values. + if (Input.isInvalid()) + return ExprError(); + if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { + if (Input.get()->isGLValue() && + Input.get()->getObjectKind() == OK_Ordinary) + VK = Input.get()->getValueKind(); + } else if (!getLangOpts().CPlusPlus) { + // In C, a volatile scalar is read by __imag. In C++, it is not. + Input = DefaultLvalueConversion(Input.get()); + } + break; + case UO_Extension: + resultType = Input.get()->getType(); + VK = Input.get()->getValueKind(); + OK = Input.get()->getObjectKind(); + break; + case UO_Coawait: + // It's unnecessary to represent the pass-through operator co_await in the + // AST; just return the input expression instead. + assert(!Input.get()->getType()->isDependentType() && + "the co_await expression must be non-dependant before " + "building operator co_await"); + return Input; } - break; - case UO_Extension: - resultType = Input.get()->getType(); - VK = Input.get()->getValueKind(); - OK = Input.get()->getObjectKind(); - break; - case UO_Coawait: - // It's unnecessary to represent the pass-through operator co_await in the - // AST; just return the input expression instead. - assert(!Input.get()->getType()->isDependentType() && - "the co_await expression must be non-dependant before " - "building operator co_await"); - return Input; } if (resultType.isNull() || Input.isInvalid()) return ExprError(); diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index 0fb07b0b434c..4b7365e554cb 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -4261,9 +4261,9 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "" +// CHECK-NEXT: "qualType": "V" // CHECK-NEXT: }, -// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "valueCategory": "lvalue", // CHECK-NEXT: "isPostfix": false, // CHECK-NEXT: "opcode": "*", // CHECK-NEXT: "canOverflow": false, diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 69e65e22d61d..4df5ba4276ab 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -282,7 +282,7 @@ void PrimaryExpressions(Ts... a) { // CHECK-NEXT: CompoundStmt // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:8 implicit 'V' // CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} 'NULL TYPE' - // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} '' prefix '*' cannot overflow + // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} 'V' lvalue prefix '*' cannot overflow // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} 'V *' this } }; diff --git a/clang/test/AST/ast-dump-lambda.cpp b/clang/test/AST/ast-dump-lambda.cpp index ef8789cd97d3..a4d3fe4fbda5 100644 --- a/clang/test/AST/ast-dump-lambda.cpp +++ b/clang/test/AST/ast-dump-lambda.cpp @@ -81,7 +81,7 @@ template void test(Ts... a) { // CHECK-NEXT: | | | `-CompoundStmt {{.*}} // CHECK-NEXT: | | `-FieldDecl {{.*}} col:8{{( imported)?}} implicit 'V' // CHECK-NEXT: | |-ParenListExpr {{.*}} 'NULL TYPE' -// CHECK-NEXT: | | `-UnaryOperator {{.*}} '' prefix '*' cannot overflow +// CHECK-NEXT: | | `-UnaryOperator {{.*}} 'V' lvalue prefix '*' cannot overflow // CHECK-NEXT: | | `-CXXThisExpr {{.*}} 'V *' this // CHECK-NEXT: | `-CompoundStmt {{.*}} // CHECK-NEXT: |-DeclStmt {{.*}} diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp new file mode 100644 index 000000000000..6744ce1cad17 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -Wno-unused -fsyntax-only %s -verify + +struct A { + void operator*(); + void operator+(); + void operator-(); + void operator!(); + void operator~(); + void operator&(); + void operator++(); + void operator--(); +}; + +struct B { }; + +template +void dependent(T t, T* pt, T U::* mpt, T(&ft)(), T(&at)[4]) { + *t; + +t; + -t; + !t; + ~t; + &t; + ++t; + --t; + + *pt; + +pt; + -pt; // expected-error {{invalid argument type 'T *' to unary expression}} + !pt; + ~pt; // expected-error {{invalid argument type 'T *' to unary expression}} + &pt; + ++pt; + --pt; + + *mpt; // expected-error {{indirection requires pointer operand ('T U::*' invalid)}} + +mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} + -mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} + !mpt; + ~mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} + &mpt; + ++mpt; // expected-error {{cannot increment value of type 'T U::*'}} + --mpt; // expected-error {{cannot decrement value of type 'T U::*'}} + + *ft; + +ft; + -ft; // expected-error {{invalid argument type 'T (*)()' to unary expression}} + !ft; + ~ft; // expected-error {{invalid argument type 'T (*)()' to unary expression}} + &ft; + ++ft; // expected-error {{cannot increment value of type 'T ()'}} + --ft; // expected-error {{cannot decrement value of type 'T ()'}} + + *at; + +at; + -at; // expected-error {{invalid argument type 'T *' to unary expression}} + !at; + ~at; // expected-error {{invalid argument type 'T *' to unary expression}} + &at; + ++at; // expected-error {{cannot increment value of type 'T[4]'}} + --at; // expected-error {{cannot decrement value of type 'T[4]'}} +} + +// Make sure we only emit diagnostics once. +template void dependent(A t, A* pt, A B::* mpt, A(&ft)(), A(&at)[4]); diff --git a/clang/test/CXX/over/over.built/ast.cpp b/clang/test/CXX/over/over.built/ast.cpp index 56a63431269f..78f86edb1e96 100644 --- a/clang/test/CXX/over/over.built/ast.cpp +++ b/clang/test/CXX/over/over.built/ast.cpp @@ -1,41 +1,139 @@ -// RUN: %clang_cc1 -std=c++17 -ast-dump %s -ast-dump-filter Test | FileCheck %s +// RUN: %clang_cc1 -std=c++17 -Wno-unused -ast-dump %s -ast-dump-filter Test | FileCheck %s -struct A{}; +namespace Test { + template + void Unary(T t, T* pt, T U::* mpt, T(&ft)(), T(&at)[4]) { + // CHECK: UnaryOperator {{.*}} '' lvalue prefix '*' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + *t; -template -auto Test(T* pt, U* pu) { - // CHECK: UnaryOperator {{.*}} '' lvalue prefix '*' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)*pt; + // CHECK: UnaryOperator {{.*}} '' prefix '+' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + +t; - // CHECK: UnaryOperator {{.*}} '' lvalue prefix '++' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)(++pt); + // CHECK: UnaryOperator {{.*}} '' prefix '-' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + -t; - // CHECK: UnaryOperator {{.*}} '' prefix '+' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)(+pt); + // CHECK: UnaryOperator {{.*}} '' prefix '!' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + !t; - // CHECK: BinaryOperator {{.*}} '' '+' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3 - (void)(pt + 3); + // CHECK: UnaryOperator {{.*}} '' prefix '~' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + ~t; - // CHECK: BinaryOperator {{.*}} '' '-' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)(pt - pt); + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + &t; - // CHECK: BinaryOperator {{.*}} '' '-' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' - (void)(pt - pu); + // CHECK: UnaryOperator {{.*}} '' lvalue prefix '++' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + ++t; - // CHECK: BinaryOperator {{.*}} '' '==' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' - (void)(pt == pu); + // CHECK: UnaryOperator {{.*}} '' lvalue prefix '--' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + --t; -} + // CHECK: UnaryOperator {{.*}} 'T' lvalue prefix '*' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + *pt; + // CHECK: UnaryOperator {{.*}} 'T *' prefix '+' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + +pt; + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + !pt; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + &pt; + + // CHECK: UnaryOperator {{.*}} 'T *' lvalue prefix '++' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + ++pt; + + // CHECK: UnaryOperator {{.*}} 'T *' lvalue prefix '--' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + --pt; + + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T U::*' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T U::*' lvalue ParmVar {{.*}} 'mpt' 'T U::*' + !mpt; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T U::*' lvalue ParmVar {{.*}} 'mpt' 'T U::*' + &mpt; + + // CHECK: UnaryOperator {{.*}} 'T ()' lvalue prefix '*' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + *ft; + + // CHECK: UnaryOperator {{.*}} 'T (*)()' prefix '+' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + +ft; + + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + !ft; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + &ft; + + // CHECK: UnaryOperator {{.*}} 'T' lvalue prefix '*' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + *at; + + // CHECK: UnaryOperator {{.*}} 'T *' prefix '+' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + +at; + + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + !at; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + &at; + } + + template + void Binary(T* pt, U* pu) { + // CHECK: BinaryOperator {{.*}} '' '+' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3 + pt + 3; + + // CHECK: BinaryOperator {{.*}} '' '-' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + pt - pt; + + // CHECK: BinaryOperator {{.*}} '' '-' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' + pt - pu; + + // CHECK: BinaryOperator {{.*}} '' '==' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' + pt == pu; + } +} // namespace Test diff --git a/clang/test/CXX/over/over.built/p10.cpp b/clang/test/CXX/over/over.built/p10.cpp index 678056da5820..8ff2396d0b6f 100644 --- a/clang/test/CXX/over/over.built/p10.cpp +++ b/clang/test/CXX/over/over.built/p10.cpp @@ -15,6 +15,6 @@ void f(int i, float f, bool b, char c, int* pi, A* pa, T* pt) { (void)-pi; // expected-error {{invalid argument type}} (void)-pa; // expected-error {{invalid argument type}} - (void)-pt; // FIXME: we should be able to give an error here. + (void)-pt; // expected-error {{invalid argument type}} } diff --git a/clang/test/CXX/over/over.built/p11.cpp b/clang/test/CXX/over/over.built/p11.cpp index 7ebf16b95439..f7a741db726d 100644 --- a/clang/test/CXX/over/over.built/p11.cpp +++ b/clang/test/CXX/over/over.built/p11.cpp @@ -7,6 +7,6 @@ void f(int i, float f, bool b, char c, int* pi, T* pt) { (void)~b; (void)~c; (void)~pi; // expected-error {{invalid argument type}} - (void)~pt; // FIXME: we should be able to give an error here. + (void)~pt; // expected-error {{invalid argument type}} } diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp index 3ca7c6c7eb8e..982e5372f5b0 100644 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp @@ -357,17 +357,14 @@ namespace N0 { a->A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} a->B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - // FIXME: An overloaded unary 'operator*' is built for these - // even though the operand is a pointer (to a dependent type). - // Type::isOverloadableType should return false for such cases. - (*this).x4; - (*this).B::x4; - (*this).A::x4; - (*this).B::A::x4; - (*this).f4(); - (*this).B::f4(); - (*this).A::f4(); - (*this).B::A::f4(); + (*this).x4; // expected-error{{no member named 'x4' in 'B'}} + (*this).B::x4; // expected-error{{no member named 'x4' in 'B'}} + (*this).A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} + (*this).B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} + (*this).f4(); // expected-error{{no member named 'f4' in 'B'}} + (*this).B::f4(); // expected-error{{no member named 'f4' in 'B'}} + (*this).A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} + (*this).B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} b.x4; // expected-error{{no member named 'x4' in 'B'}} b.B::x4; // expected-error{{no member named 'x4' in 'B'}} @@ -399,15 +396,13 @@ namespace N1 { f<0>(); this->f<0>(); a->f<0>(); - // FIXME: This should not require 'template'! - (*this).f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + (*this).f<0>(); b.f<0>(); x.f<0>(); this->x.f<0>(); a->x.f<0>(); - // FIXME: This should not require 'template'! - (*this).x.f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + (*this).x.f<0>(); b.x.f<0>(); // FIXME: None of these should require 'template'! diff --git a/clang/test/Frontend/noderef_templates.cpp b/clang/test/Frontend/noderef_templates.cpp index 5fde6efd87c7..9e54cd5d7889 100644 --- a/clang/test/Frontend/noderef_templates.cpp +++ b/clang/test/Frontend/noderef_templates.cpp @@ -3,8 +3,8 @@ #define NODEREF __attribute__((noderef)) template -int func(T NODEREF *a) { // expected-note 2 {{a declared here}} - return *a + 1; // expected-warning 2 {{dereferencing a; was declared with a 'noderef' type}} +int func(T NODEREF *a) { // expected-note 3 {{a declared here}} + return *a + 1; // expected-warning 3 {{dereferencing a; was declared with a 'noderef' type}} } void func() { diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp b/clang/test/SemaCXX/cxx2b-deducing-this.cpp index 5f29a955e053..aa64530bd5be 100644 --- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp +++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp @@ -19,7 +19,7 @@ struct S { // new and delete are implicitly static void *operator new(this unsigned long); // expected-error{{an explicit object parameter cannot appear in a static function}} void operator delete(this void*); // expected-error{{an explicit object parameter cannot appear in a static function}} - + void g(this auto) const; // expected-error{{explicit object member function cannot have 'const' qualifier}} void h(this auto) &; // expected-error{{explicit object member function cannot have '&' qualifier}} void i(this auto) &&; // expected-error{{explicit object member function cannot have '&&' qualifier}} @@ -198,9 +198,7 @@ void func(int i) { void TestMutationInLambda() { [i = 0](this auto &&){ i++; }(); [i = 0](this auto){ i++; }(); - [i = 0](this const auto&){ i++; }(); - // expected-error@-1 {{cannot assign to a variable captured by copy in a non-mutable lambda}} - // expected-note@-2 {{in instantiation of}} + [i = 0](this const auto&){ i++; }(); // expected-error {{cannot assign to a variable captured by copy in a non-mutable lambda}} int x; const auto l1 = [x](this auto&) { x = 42; }; // expected-error {{cannot assign to a variable captured by copy in a non-mutable lambda}} diff --git a/clang/test/SemaTemplate/class-template-spec.cpp b/clang/test/SemaTemplate/class-template-spec.cpp index 56b8207bd9a4..faa54c367538 100644 --- a/clang/test/SemaTemplate/class-template-spec.cpp +++ b/clang/test/SemaTemplate/class-template-spec.cpp @@ -18,7 +18,7 @@ int test_specs(A *a1, A *a2) { return a1->x + a2->y; } -int test_incomplete_specs(A *a1, +int test_incomplete_specs(A *a1, A *a2) { (void)a1->x; // expected-error{{member access into incomplete type}} @@ -39,7 +39,7 @@ template <> struct X { int foo(); }; // #1 template <> struct X { int bar(); }; // #2 typedef int int_type; -void testme(X *x1, X *x2) { +void testme(X *x1, X *x2) { (void)x1->foo(); // okay: refers to #1 (void)x2->bar(); // okay: refers to #2 } @@ -53,7 +53,7 @@ struct A { A::A() { } // Make sure we can see specializations defined before the primary template. -namespace N{ +namespace N{ template struct A0; } @@ -97,7 +97,7 @@ namespace M { template<> struct ::A; // expected-error{{must occur at global scope}} } -template<> struct N::B { +template<> struct N::B { int testf(int x) { return f(x); } }; @@ -138,9 +138,9 @@ namespace PR18009 { template struct C { template struct S; - template struct S {}; // expected-error {{depends on a template parameter of the partial specialization}} + template struct S {}; // ok }; - C c; // expected-note {{in instantiation of}} + C c; template struct outer { template struct inner {}; diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index c08deb903f12..f26140675fd4 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1572,9 +1572,9 @@ TEST_P(ASTMatchersTest, IsArrow_MatchesMemberVariablesViaArrow) { EXPECT_TRUE( matches("template class Y { void x() { this->m; } int m; };", memberExpr(isArrow()))); - EXPECT_TRUE( - notMatches("template class Y { void x() { (*this).m; } };", - cxxDependentScopeMemberExpr(isArrow()))); + EXPECT_TRUE(notMatches( + "template class Y { void x() { (*this).m; } int m; };", + memberExpr(isArrow()))); } TEST_P(ASTMatchersTest, IsArrow_MatchesStaticMemberVariablesViaArrow) { -- GitLab From 2ff43ce87e66d9324370e35ea6743ef57400c76e Mon Sep 17 00:00:00 2001 From: Jeremy Kun Date: Tue, 14 May 2024 09:45:39 -0700 Subject: [PATCH 250/578] Restore #91137 (#92003) #91137 reverted in #92001 A build error fix added in 28d5ece8ca93ef04fee9b0258b70b750b66c05ca --------- Co-authored-by: Jeremy Kun --- .../mlir/Dialect/Polynomial/IR/Polynomial.h | 193 ++++++++++++++---- .../mlir/Dialect/Polynomial/IR/Polynomial.td | 139 ++++++++----- mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp | 75 +++---- .../Polynomial/IR/PolynomialAttributes.cpp | 172 +++++++--------- mlir/test/Dialect/Polynomial/attributes.mlir | 22 +- mlir/test/Dialect/Polynomial/ops.mlir | 64 +++--- mlir/test/Dialect/Polynomial/ops_errors.mlir | 66 +++--- mlir/test/Dialect/Polynomial/types.mlir | 65 +++--- 8 files changed, 448 insertions(+), 348 deletions(-) diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h index 3325a6fa3f9f..7f44c29a9870 100644 --- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h +++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h @@ -11,10 +11,13 @@ #include "mlir/Support/LLVM.h" #include "mlir/Support/LogicalResult.h" +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" namespace mlir { @@ -27,98 +30,202 @@ namespace polynomial { /// would want to specify 128-bit polynomials statically in the source code. constexpr unsigned apintBitWidth = 64; -/// A class representing a monomial of a single-variable polynomial with integer -/// coefficients. -class Monomial { +template +class MonomialBase { public: - Monomial(int64_t coeff, uint64_t expo) - : coefficient(apintBitWidth, coeff), exponent(apintBitWidth, expo) {} - - Monomial(const APInt &coeff, const APInt &expo) + MonomialBase(const CoefficientType &coeff, const APInt &expo) : coefficient(coeff), exponent(expo) {} + virtual ~MonomialBase() = default; - Monomial() : coefficient(apintBitWidth, 0), exponent(apintBitWidth, 0) {} + const CoefficientType &getCoefficient() const { return coefficient; } + CoefficientType &getMutableCoefficient() { return coefficient; } + const APInt &getExponent() const { return exponent; } + void setCoefficient(const CoefficientType &coeff) { coefficient = coeff; } + void setExponent(const APInt &exp) { exponent = exp; } - bool operator==(const Monomial &other) const { + bool operator==(const MonomialBase &other) const { return other.coefficient == coefficient && other.exponent == exponent; } - bool operator!=(const Monomial &other) const { + bool operator!=(const MonomialBase &other) const { return other.coefficient != coefficient || other.exponent != exponent; } /// Monomials are ordered by exponent. - bool operator<(const Monomial &other) const { + bool operator<(const MonomialBase &other) const { return (exponent.ult(other.exponent)); } - friend ::llvm::hash_code hash_value(const Monomial &arg); + virtual bool isMonic() const = 0; + virtual void + coefficientToString(llvm::SmallString<16> &coeffString) const = 0; -public: - APInt coefficient; + template + friend ::llvm::hash_code hash_value(const MonomialBase &arg); - // Always unsigned +protected: + CoefficientType coefficient; APInt exponent; }; -/// A single-variable polynomial with integer coefficients. -/// -/// Eg: x^1024 + x + 1 -/// -/// The symbols used as the polynomial's indeterminate don't matter, so long as -/// it is used consistently throughout the polynomial. -class Polynomial { +/// A class representing a monomial of a single-variable polynomial with integer +/// coefficients. +class IntMonomial : public MonomialBase { public: - Polynomial() = delete; + IntMonomial(int64_t coeff, uint64_t expo) + : MonomialBase(APInt(apintBitWidth, coeff), APInt(apintBitWidth, expo)) {} - explicit Polynomial(ArrayRef terms) : terms(terms){}; + IntMonomial() + : MonomialBase(APInt(apintBitWidth, 0), APInt(apintBitWidth, 0)) {} - // Returns a Polynomial from a list of monomials. - // Fails if two monomials have the same exponent. - static FailureOr fromMonomials(ArrayRef monomials); + ~IntMonomial() = default; - /// Returns a polynomial with coefficients given by `coeffs`. The value - /// coeffs[i] is converted to a monomial with exponent i. - static Polynomial fromCoefficients(ArrayRef coeffs); + bool isMonic() const override { return coefficient == 1; } + + void coefficientToString(llvm::SmallString<16> &coeffString) const override { + coefficient.toStringSigned(coeffString); + } +}; + +/// A class representing a monomial of a single-variable polynomial with integer +/// coefficients. +class FloatMonomial : public MonomialBase { +public: + FloatMonomial(double coeff, uint64_t expo) + : MonomialBase(APFloat(coeff), APInt(apintBitWidth, expo)) {} + + FloatMonomial() : MonomialBase(APFloat((double)0), APInt(apintBitWidth, 0)) {} + + ~FloatMonomial() = default; + + bool isMonic() const override { return coefficient == APFloat(1.0); } + + void coefficientToString(llvm::SmallString<16> &coeffString) const override { + coefficient.toString(coeffString); + } +}; + +template +class PolynomialBase { +public: + PolynomialBase() = delete; + + explicit PolynomialBase(ArrayRef terms) : terms(terms) {}; explicit operator bool() const { return !terms.empty(); } - bool operator==(const Polynomial &other) const { + bool operator==(const PolynomialBase &other) const { return other.terms == terms; } - bool operator!=(const Polynomial &other) const { + bool operator!=(const PolynomialBase &other) const { return !(other.terms == terms); } - // Prints polynomial to 'os'. - void print(raw_ostream &os) const; void print(raw_ostream &os, ::llvm::StringRef separator, - ::llvm::StringRef exponentiation) const; + ::llvm::StringRef exponentiation) const { + bool first = true; + for (const Monomial &term : getTerms()) { + if (first) { + first = false; + } else { + os << separator; + } + std::string coeffToPrint; + if (term.isMonic() && term.getExponent().uge(1)) { + coeffToPrint = ""; + } else { + llvm::SmallString<16> coeffString; + term.coefficientToString(coeffString); + coeffToPrint = coeffString.str(); + } + + if (term.getExponent() == 0) { + os << coeffToPrint; + } else if (term.getExponent() == 1) { + os << coeffToPrint << "x"; + } else { + llvm::SmallString<16> expString; + term.getExponent().toStringSigned(expString); + os << coeffToPrint << "x" << exponentiation << expString; + } + } + } + + // Prints polynomial to 'os'. + void print(raw_ostream &os) const { print(os, " + ", "**"); } + void dump() const; // Prints polynomial so that it can be used as a valid identifier - std::string toIdentifier() const; + std::string toIdentifier() const { + std::string result; + llvm::raw_string_ostream os(result); + print(os, "_", ""); + return os.str(); + } - unsigned getDegree() const; + unsigned getDegree() const { + return terms.back().getExponent().getZExtValue(); + } ArrayRef getTerms() const { return terms; } - friend ::llvm::hash_code hash_value(const Polynomial &arg); + template + friend ::llvm::hash_code hash_value(const PolynomialBase &arg); private: // The monomial terms for this polynomial. SmallVector terms; }; -// Make Polynomial hashable. -inline ::llvm::hash_code hash_value(const Polynomial &arg) { +/// A single-variable polynomial with integer coefficients. +/// +/// Eg: x^1024 + x + 1 +class IntPolynomial : public PolynomialBase { +public: + explicit IntPolynomial(ArrayRef terms) : PolynomialBase(terms) {} + + // Returns a Polynomial from a list of monomials. + // Fails if two monomials have the same exponent. + static FailureOr + fromMonomials(ArrayRef monomials); + + /// Returns a polynomial with coefficients given by `coeffs`. The value + /// coeffs[i] is converted to a monomial with exponent i. + static IntPolynomial fromCoefficients(ArrayRef coeffs); +}; + +/// A single-variable polynomial with double coefficients. +/// +/// Eg: 1.0 x^1024 + 3.5 x + 1e-05 +class FloatPolynomial : public PolynomialBase { +public: + explicit FloatPolynomial(ArrayRef terms) + : PolynomialBase(terms) {} + + // Returns a Polynomial from a list of monomials. + // Fails if two monomials have the same exponent. + static FailureOr + fromMonomials(ArrayRef monomials); + + /// Returns a polynomial with coefficients given by `coeffs`. The value + /// coeffs[i] is converted to a monomial with exponent i. + static FloatPolynomial fromCoefficients(ArrayRef coeffs); +}; + +// Make Polynomials hashable. +template +inline ::llvm::hash_code hash_value(const PolynomialBase &arg) { return ::llvm::hash_combine_range(arg.terms.begin(), arg.terms.end()); } -inline ::llvm::hash_code hash_value(const Monomial &arg) { +template +inline ::llvm::hash_code hash_value(const MonomialBase &arg) { return llvm::hash_combine(::llvm::hash_value(arg.coefficient), ::llvm::hash_value(arg.exponent)); } -inline raw_ostream &operator<<(raw_ostream &os, const Polynomial &polynomial) { +template +inline raw_ostream &operator<<(raw_ostream &os, + const PolynomialBase &polynomial) { polynomial.print(os); return os; } diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td index ed1f4ce8b7e5..ae8484501a50 100644 --- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td +++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td @@ -39,14 +39,14 @@ def Polynomial_Dialect : Dialect { %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring> // A constant polynomial in a ring with i32 coefficients, modulo (x^1024 + 1) - #modulus = #polynomial.polynomial<1 + x**1024> + #modulus = #polynomial.int_polynomial<1 + x**1024> #ring = #polynomial.ring %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring> // A constant polynomial in a ring with i32 coefficients, with a polynomial // modulus of (x^1024 + 1) and a coefficient modulus of 17. - #modulus = #polynomial.polynomial<1 + x**1024> - #ring = #polynomial.ring + #modulus = #polynomial.int_polynomial<1 + x**1024> + #ring = #polynomial.ring %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring> ``` }]; @@ -60,12 +60,12 @@ class Polynomial_Attr traits = []> let mnemonic = attrMnemonic; } -def Polynomial_PolynomialAttr : Polynomial_Attr<"Polynomial", "polynomial"> { - let summary = "An attribute containing a single-variable polynomial."; +def Polynomial_IntPolynomialAttr : Polynomial_Attr<"IntPolynomial", "int_polynomial"> { + let summary = "An attribute containing a single-variable polynomial with integer coefficients."; let description = [{ - A polynomial attribute represents a single-variable polynomial, which - is used to define the modulus of a `RingAttr`, as well as to define constants - and perform constant folding for `polynomial` ops. + A polynomial attribute represents a single-variable polynomial with integer + coefficients, which is used to define the modulus of a `RingAttr`, as well + as to define constants and perform constant folding for `polynomial` ops. The polynomial must be expressed as a list of monomial terms, with addition or subtraction between them. The choice of variable name is arbitrary, but @@ -76,10 +76,32 @@ def Polynomial_PolynomialAttr : Polynomial_Attr<"Polynomial", "polynomial"> { Example: ```mlir - #poly = #polynomial.polynomial + #poly = #polynomial.int_polynomial ``` }]; - let parameters = (ins "::mlir::polynomial::Polynomial":$polynomial); + let parameters = (ins "::mlir::polynomial::IntPolynomial":$polynomial); + let hasCustomAssemblyFormat = 1; +} + +def Polynomial_FloatPolynomialAttr : Polynomial_Attr<"FloatPolynomial", "float_polynomial"> { + let summary = "An attribute containing a single-variable polynomial with double precision floating point coefficients."; + let description = [{ + A polynomial attribute represents a single-variable polynomial with double + precision floating point coefficients. + + The polynomial must be expressed as a list of monomial terms, with addition + or subtraction between them. The choice of variable name is arbitrary, but + must be consistent across all the monomials used to define a single + attribute. The order of monomial terms is arbitrary, each monomial degree + must occur at most once. + + Example: + + ```mlir + #poly = #polynomial.float_polynomial<0.5 x**7 + 1.5> + ``` + }]; + let parameters = (ins "FloatPolynomial":$polynomial); let hasCustomAssemblyFormat = 1; } @@ -104,9 +126,9 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> { `x**1024 - 1`. ```mlir - #poly_mod = #polynomial.polynomial<-1 + x**1024> + #poly_mod = #polynomial.int_polynomial<-1 + x**1024> #ring = #polynomial.ring %0 = ... : polynomial.polynomial<#ring> @@ -123,19 +145,24 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> { let parameters = (ins "Type": $coefficientType, OptionalParameter<"::mlir::IntegerAttr">: $coefficientModulus, - OptionalParameter<"::mlir::polynomial::PolynomialAttr">: $polynomialModulus, + OptionalParameter<"::mlir::polynomial::IntPolynomialAttr">: $polynomialModulus, OptionalParameter<"::mlir::IntegerAttr">: $primitiveRoot ); - + let assemblyFormat = "`<` struct(params) `>`"; let builders = [ - AttrBuilder< + AttrBuilderWithInferredContext< (ins "::mlir::Type":$coefficientTy, - "::mlir::IntegerAttr":$coefficientModulusAttr, - "::mlir::polynomial::PolynomialAttr":$polynomialModulusAttr), [{ - return $_get($_ctxt, coefficientTy, coefficientModulusAttr, polynomialModulusAttr, nullptr); - }]> + CArg<"::mlir::IntegerAttr", "nullptr"> :$coefficientModulusAttr, + CArg<"::mlir::polynomial::IntPolynomialAttr", "nullptr"> :$polynomialModulusAttr, + CArg<"::mlir::IntegerAttr", "nullptr"> :$primitiveRootAttr), [{ + return $_get( + coefficientTy.getContext(), + coefficientTy, + coefficientModulusAttr, + polynomialModulusAttr, + primitiveRootAttr); + }]>, ]; - let hasCustomAssemblyFormat = 1; } class Polynomial_Type @@ -149,7 +176,7 @@ def Polynomial_PolynomialType : Polynomial_Type<"Polynomial", "polynomial"> { A type for polynomials in a polynomial quotient ring. }]; let parameters = (ins Polynomial_RingAttr:$ring); - let assemblyFormat = "`<` $ring `>`"; + let assemblyFormat = "`<` struct(params) `>`"; } def PolynomialLike: TypeOrContainer; @@ -187,10 +214,10 @@ def Polynomial_AddOp : Polynomial_BinaryOp<"add", [Commutative]> { ```mlir // add two polynomials modulo x^1024 - 1 - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> - %1 = polynomial.constant #polynomial.polynomial : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> + %1 = polynomial.constant #polynomial.int_polynomial : !polynomial.polynomial<#ring> %2 = polynomial.add %0, %1 : !polynomial.polynomial<#ring> ``` }]; @@ -211,10 +238,10 @@ def Polynomial_SubOp : Polynomial_BinaryOp<"sub"> { ```mlir // subtract two polynomials modulo x^1024 - 1 - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> - %1 = polynomial.constant #polynomial.polynomial : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> + %1 = polynomial.constant #polynomial.int_polynomial : !polynomial.polynomial<#ring> %2 = polynomial.sub %0, %1 : !polynomial.polynomial<#ring> ``` }]; @@ -235,10 +262,10 @@ def Polynomial_MulOp : Polynomial_BinaryOp<"mul", [Commutative]> { ```mlir // multiply two polynomials modulo x^1024 - 1 - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> - %1 = polynomial.constant #polynomial.polynomial : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> + %1 = polynomial.constant #polynomial.int_polynomial : !polynomial.polynomial<#ring> %2 = polynomial.mul %0, %1 : !polynomial.polynomial<#ring> ``` }]; @@ -260,9 +287,9 @@ def Polynomial_MulScalarOp : Polynomial_Op<"mul_scalar", [ ```mlir // multiply two polynomials modulo x^1024 - 1 - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> %1 = arith.constant 3 : i32 %2 = polynomial.mul_scalar %0, %1 : !polynomial.polynomial<#ring>, i32 ``` @@ -291,9 +318,9 @@ def Polynomial_LeadingTermOp: Polynomial_Op<"leading_term"> { Example: ```mlir - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> %1, %2 = polynomial.leading_term %0 : !polynomial.polynomial<#ring> -> (index, i32) ``` }]; @@ -314,8 +341,8 @@ def Polynomial_MonomialOp: Polynomial_Op<"monomial"> { Example: ```mlir - #poly = #polynomial.polynomial - #ring = #polynomial.ring + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring %deg = arith.constant 1023 : index %five = arith.constant 5 : i32 %0 = polynomial.monomial %five, %deg : (i32, index) -> !polynomial.polynomial<#ring> @@ -354,8 +381,8 @@ def Polynomial_FromTensorOp : Polynomial_Op<"from_tensor", [Pure]> { Example: ```mlir - #poly = #polynomial.polynomial - #ring = #polynomial.ring + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring %two = arith.constant 2 : i32 %five = arith.constant 5 : i32 %coeffs = tensor.from_elements %two, %two, %five : tensor<3xi32> @@ -393,8 +420,8 @@ def Polynomial_ToTensorOp : Polynomial_Op<"to_tensor", [Pure]> { Example: ```mlir - #poly = #polynomial.polynomial - #ring = #polynomial.ring + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring %two = arith.constant 2 : i32 %five = arith.constant 5 : i32 %coeffs = tensor.from_elements %two, %two, %five : tensor<3xi32> @@ -405,24 +432,32 @@ def Polynomial_ToTensorOp : Polynomial_Op<"to_tensor", [Pure]> { let arguments = (ins Polynomial_PolynomialType:$input); let results = (outs RankedTensorOf<[AnyInteger]>:$output); let assemblyFormat = "$input attr-dict `:` type($input) `->` type($output)"; - let hasVerifier = 1; } -def Polynomial_ConstantOp : Polynomial_Op<"constant", [Pure]> { +def Polynomial_AnyPolynomialAttr : AnyAttrOf<[ + Polynomial_FloatPolynomialAttr, + Polynomial_IntPolynomialAttr +]>; + +// Not deriving from Polynomial_Op due to need for custom assembly format +def Polynomial_ConstantOp : Op { let summary = "Define a constant polynomial via an attribute."; let description = [{ Example: ```mlir - #poly = #polynomial.polynomial - #ring = #polynomial.ring - %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring> + #poly = #polynomial.int_polynomial + #ring = #polynomial.ring + %0 = polynomial.constant #polynomial.int_polynomial<1 + x**2> : !polynomial.polynomial<#ring> + + #float_ring = #polynomial.ring + %0 = polynomial.constant #polynomial.float_polynomial<0.5 + 1.3e06 x**2> : !polynomial.polynomial<#float_ring> ``` }]; - let arguments = (ins Polynomial_PolynomialAttr:$input); + let arguments = (ins Polynomial_AnyPolynomialAttr:$value); let results = (outs Polynomial_PolynomialType:$output); - let assemblyFormat = "$input attr-dict `:` type($output)"; + let assemblyFormat = "attr-dict `:` type($output)"; } def Polynomial_NTTOp : Polynomial_Op<"ntt", [Pure]> { diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp index 5916ffba78e2..e85bced3cca7 100644 --- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp +++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp @@ -9,87 +9,60 @@ #include "mlir/Dialect/Polynomial/IR/Polynomial.h" #include "mlir/Support/LogicalResult.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/raw_ostream.h" namespace mlir { namespace polynomial { -FailureOr Polynomial::fromMonomials(ArrayRef monomials) { +template +FailureOr fromMonomialsImpl(ArrayRef monomials) { // A polynomial's terms are canonically stored in order of increasing degree. - auto monomialsCopy = llvm::SmallVector(monomials); + auto monomialsCopy = llvm::SmallVector(monomials); std::sort(monomialsCopy.begin(), monomialsCopy.end()); // Ensure non-unique exponents are not present. Since we sorted the list by // exponent, a linear scan of adjancent monomials suffices. if (std::adjacent_find(monomialsCopy.begin(), monomialsCopy.end(), - [](const Monomial &lhs, const Monomial &rhs) { - return lhs.exponent == rhs.exponent; + [](const MonomialT &lhs, const MonomialT &rhs) { + return lhs.getExponent() == rhs.getExponent(); }) != monomialsCopy.end()) { return failure(); } - return Polynomial(monomialsCopy); + return PolyT(monomialsCopy); } -Polynomial Polynomial::fromCoefficients(ArrayRef coeffs) { - llvm::SmallVector monomials; +FailureOr +IntPolynomial::fromMonomials(ArrayRef monomials) { + return fromMonomialsImpl(monomials); +} + +FailureOr +FloatPolynomial::fromMonomials(ArrayRef monomials) { + return fromMonomialsImpl(monomials); +} + +template +PolyT fromCoefficientsImpl(ArrayRef coeffs) { + llvm::SmallVector monomials; auto size = coeffs.size(); monomials.reserve(size); for (size_t i = 0; i < size; i++) { monomials.emplace_back(coeffs[i], i); } - auto result = Polynomial::fromMonomials(monomials); + auto result = PolyT::fromMonomials(monomials); // Construction guarantees unique exponents, so the failure mode of // fromMonomials can be bypassed. assert(succeeded(result)); return result.value(); } -void Polynomial::print(raw_ostream &os, ::llvm::StringRef separator, - ::llvm::StringRef exponentiation) const { - bool first = true; - for (const Monomial &term : terms) { - if (first) { - first = false; - } else { - os << separator; - } - std::string coeffToPrint; - if (term.coefficient == 1 && term.exponent.uge(1)) { - coeffToPrint = ""; - } else { - llvm::SmallString<16> coeffString; - term.coefficient.toStringSigned(coeffString); - coeffToPrint = coeffString.str(); - } - - if (term.exponent == 0) { - os << coeffToPrint; - } else if (term.exponent == 1) { - os << coeffToPrint << "x"; - } else { - llvm::SmallString<16> expString; - term.exponent.toStringSigned(expString); - os << coeffToPrint << "x" << exponentiation << expString; - } - } -} - -void Polynomial::print(raw_ostream &os) const { print(os, " + ", "**"); } - -std::string Polynomial::toIdentifier() const { - std::string result; - llvm::raw_string_ostream os(result); - print(os, "_", ""); - return os.str(); +IntPolynomial IntPolynomial::fromCoefficients(ArrayRef coeffs) { + return fromCoefficientsImpl(coeffs); } -unsigned Polynomial::getDegree() const { - return terms.back().exponent.getZExtValue(); +FloatPolynomial FloatPolynomial::fromCoefficients(ArrayRef coeffs) { + return fromCoefficientsImpl(coeffs); } } // namespace polynomial diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp index 236bb7896635..890ce5226c30 100644 --- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp +++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/Polynomial/IR/Polynomial.h" #include "mlir/Support/LLVM.h" #include "mlir/Support/LogicalResult.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" @@ -17,22 +18,31 @@ namespace mlir { namespace polynomial { -void PolynomialAttr::print(AsmPrinter &p) const { - p << '<'; - p << getPolynomial(); - p << '>'; +void IntPolynomialAttr::print(AsmPrinter &p) const { + p << '<' << getPolynomial() << '>'; } +void FloatPolynomialAttr::print(AsmPrinter &p) const { + p << '<' << getPolynomial() << '>'; +} + +/// A callable that parses the coefficient using the appropriate method for the +/// given monomial type, and stores the parsed coefficient value on the +/// monomial. +template +using ParseCoefficientFn = std::function; + /// Try to parse a monomial. If successful, populate the fields of the outparam /// `monomial` with the results, and the `variable` outparam with the parsed /// variable name. Sets shouldParseMore to true if the monomial is followed by /// a '+'. -ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, - llvm::StringRef &variable, bool &isConstantTerm, - bool &shouldParseMore) { - APInt parsedCoeff(apintBitWidth, 1); - auto parsedCoeffResult = parser.parseOptionalInteger(parsedCoeff); - monomial.coefficient = parsedCoeff; +/// +template +ParseResult +parseMonomial(AsmParser &parser, Monomial &monomial, llvm::StringRef &variable, + bool &isConstantTerm, bool &shouldParseMore, + ParseCoefficientFn parseAndStoreCoefficient) { + OptionalParseResult parsedCoeffResult = parseAndStoreCoefficient(monomial); isConstantTerm = false; shouldParseMore = false; @@ -44,7 +54,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, if (!parsedCoeffResult.has_value()) { return failure(); } - monomial.exponent = APInt(apintBitWidth, 0); + monomial.setExponent(APInt(apintBitWidth, 0)); isConstantTerm = true; shouldParseMore = true; return success(); @@ -58,7 +68,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, return failure(); } - monomial.exponent = APInt(apintBitWidth, 0); + monomial.setExponent(APInt(apintBitWidth, 0)); isConstantTerm = true; return success(); } @@ -80,9 +90,9 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, return failure(); } - monomial.exponent = parsedExponent; + monomial.setExponent(parsedExponent); } else { - monomial.exponent = APInt(apintBitWidth, 1); + monomial.setExponent(APInt(apintBitWidth, 1)); } if (succeeded(parser.parseOptionalPlus())) { @@ -91,22 +101,21 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, return success(); } -Attribute PolynomialAttr::parse(AsmParser &parser, Type type) { - if (failed(parser.parseLess())) - return {}; - - llvm::SmallVector monomials; - llvm::StringSet<> variables; - +template +LogicalResult +parsePolynomialAttr(AsmParser &parser, llvm::SmallVector &monomials, + llvm::StringSet<> &variables, + ParseCoefficientFn parseAndStoreCoefficient) { while (true) { Monomial parsedMonomial; llvm::StringRef parsedVariableRef; bool isConstantTerm; bool shouldParseMore; - if (failed(parseMonomial(parser, parsedMonomial, parsedVariableRef, - isConstantTerm, shouldParseMore))) { + if (failed(parseMonomial( + parser, parsedMonomial, parsedVariableRef, isConstantTerm, + shouldParseMore, parseAndStoreCoefficient))) { parser.emitError(parser.getCurrentLocation(), "expected a monomial"); - return {}; + return failure(); } if (!isConstantTerm) { @@ -124,7 +133,7 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) { parser.emitError( parser.getCurrentLocation(), "expected + and more monomials, or > to end polynomial attribute"); - return {}; + return failure(); } if (variables.size() > 1) { @@ -133,96 +142,67 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) { parser.getCurrentLocation(), "polynomials must have one indeterminate, but there were multiple: " + vars); + return failure(); } - auto result = Polynomial::fromMonomials(monomials); - if (failed(result)) { - parser.emitError(parser.getCurrentLocation()) - << "parsed polynomial must have unique exponents among monomials"; - return {}; - } - return PolynomialAttr::get(parser.getContext(), result.value()); -} - -void RingAttr::print(AsmPrinter &p) const { - p << "#polynomial.ring monomials; + llvm::StringSet<> variables; - if (failed(parser.parseEqual())) + if (failed(parsePolynomialAttr( + parser, monomials, variables, + [&](IntMonomial &monomial) -> OptionalParseResult { + APInt parsedCoeff(apintBitWidth, 1); + OptionalParseResult result = + parser.parseOptionalInteger(parsedCoeff); + monomial.setCoefficient(parsedCoeff); + return result; + }))) { return {}; + } - Type ty; - if (failed(parser.parseType(ty))) + auto result = IntPolynomial::fromMonomials(monomials); + if (failed(result)) { + parser.emitError(parser.getCurrentLocation()) + << "parsed polynomial must have unique exponents among monomials"; return {}; + } + return IntPolynomialAttr::get(parser.getContext(), result.value()); +} - if (failed(parser.parseComma())) +Attribute FloatPolynomialAttr::parse(AsmParser &parser, Type type) { + if (failed(parser.parseLess())) return {}; - IntegerAttr coefficientModulusAttr = nullptr; - if (succeeded(parser.parseKeyword("coefficientModulus"))) { - if (failed(parser.parseEqual())) - return {}; - - IntegerType iType = mlir::dyn_cast(ty); - if (!iType) { - parser.emitError(parser.getCurrentLocation(), - "coefficientType must specify an integer type"); - return {}; - } - APInt coefficientModulus(iType.getWidth(), 0); - auto result = parser.parseInteger(coefficientModulus); - if (failed(result)) { - parser.emitError(parser.getCurrentLocation(), - "invalid coefficient modulus"); - return {}; - } - coefficientModulusAttr = IntegerAttr::get(iType, coefficientModulus); - - if (failed(parser.parseComma())) - return {}; - } - - PolynomialAttr polyAttr = nullptr; - if (succeeded(parser.parseKeyword("polynomialModulus"))) { - if (failed(parser.parseEqual())) - return {}; + llvm::SmallVector monomials; + llvm::StringSet<> variables; - PolynomialAttr attr; - if (failed(parser.parseAttribute(attr))) - return {}; - polyAttr = attr; - } + ParseCoefficientFn parseAndStoreCoefficient = + [&](FloatMonomial &monomial) -> OptionalParseResult { + double coeffValue = 1.0; + ParseResult result = parser.parseFloat(coeffValue); + monomial.setCoefficient(APFloat(coeffValue)); + return OptionalParseResult(result); + }; - Polynomial poly = polyAttr.getPolynomial(); - APInt root(coefficientModulusAttr.getValue().getBitWidth(), 0); - IntegerAttr rootAttr = nullptr; - if (succeeded(parser.parseOptionalComma())) { - if (failed(parser.parseKeyword("primitiveRoot")) || - failed(parser.parseEqual())) - return {}; - - ParseResult result = parser.parseInteger(root); - if (failed(result)) { - parser.emitError(parser.getCurrentLocation(), "invalid primitiveRoot"); - return {}; - } - rootAttr = IntegerAttr::get(coefficientModulusAttr.getType(), root); + if (failed(parsePolynomialAttr( + parser, monomials, variables, parseAndStoreCoefficient))) { + return {}; } - if (failed(parser.parseGreater())) + auto result = FloatPolynomial::fromMonomials(monomials); + if (failed(result)) { + parser.emitError(parser.getCurrentLocation()) + << "parsed polynomial must have unique exponents among monomials"; return {}; - - return RingAttr::get(parser.getContext(), ty, coefficientModulusAttr, - polyAttr, rootAttr); + } + return FloatPolynomialAttr::get(parser.getContext(), result.value()); } } // namespace polynomial diff --git a/mlir/test/Dialect/Polynomial/attributes.mlir b/mlir/test/Dialect/Polynomial/attributes.mlir index 3973ae394433..4bdfd44fd4d1 100644 --- a/mlir/test/Dialect/Polynomial/attributes.mlir +++ b/mlir/test/Dialect/Polynomial/attributes.mlir @@ -1,6 +1,6 @@ // RUN: mlir-opt %s --split-input-file --verify-diagnostics -#my_poly = #polynomial.polynomial +#my_poly = #polynomial.int_polynomial // expected-error@below {{polynomials must have one indeterminate, but there were multiple: x, y}} #ring1 = #polynomial.ring @@ -9,37 +9,31 @@ // expected-error@below {{expected integer value}} // expected-error@below {{expected a monomial}} // expected-error@below {{found invalid integer exponent}} -#my_poly = #polynomial.polynomial<5 + x**f> +#my_poly = #polynomial.int_polynomial<5 + x**f> #ring1 = #polynomial.ring // ----- -#my_poly = #polynomial.polynomial<5 + x**2 + 3x**2> +#my_poly = #polynomial.int_polynomial<5 + x**2 + 3x**2> // expected-error@below {{parsed polynomial must have unique exponents among monomials}} #ring1 = #polynomial.ring // ----- // expected-error@below {{expected + and more monomials, or > to end polynomial attribute}} -#my_poly = #polynomial.polynomial<5 + x**2 7> +#my_poly = #polynomial.int_polynomial<5 + x**2 7> #ring1 = #polynomial.ring // ----- // expected-error@below {{expected a monomial}} -#my_poly = #polynomial.polynomial<5 + x**2 +> +#my_poly = #polynomial.int_polynomial<5 + x**2 +> #ring1 = #polynomial.ring // ----- -#my_poly = #polynomial.polynomial<5 + x**2> -// expected-error@below {{coefficientType must specify an integer type}} -#ring1 = #polynomial.ring - -// ----- - -#my_poly = #polynomial.polynomial<5 + x**2> -// expected-error@below {{expected integer value}} -// expected-error@below {{invalid coefficient modulus}} +#my_poly = #polynomial.int_polynomial<5 + x**2> +// expected-error@below {{failed to parse Polynomial_RingAttr parameter 'coefficientModulus' which is to be a `::mlir::IntegerAttr`}} +// expected-error@below {{expected attribute value}} #ring1 = #polynomial.ring diff --git a/mlir/test/Dialect/Polynomial/ops.mlir b/mlir/test/Dialect/Polynomial/ops.mlir index a29cfc2e9cc5..ff709960c50e 100644 --- a/mlir/test/Dialect/Polynomial/ops.mlir +++ b/mlir/test/Dialect/Polynomial/ops.mlir @@ -2,85 +2,87 @@ // This simply tests for syntax. -#my_poly = #polynomial.polynomial<1 + x**1024> -#my_poly_2 = #polynomial.polynomial<2> -#my_poly_3 = #polynomial.polynomial<3x> -#my_poly_4 = #polynomial.polynomial +#my_poly = #polynomial.int_polynomial<1 + x**1024> +#my_poly_2 = #polynomial.int_polynomial<2> +#my_poly_3 = #polynomial.int_polynomial<3x> +#my_poly_4 = #polynomial.int_polynomial #ring1 = #polynomial.ring -#one_plus_x_squared = #polynomial.polynomial<1 + x**2> +#ring2 = #polynomial.ring +#one_plus_x_squared = #polynomial.int_polynomial<1 + x**2> -#ideal = #polynomial.polynomial<-1 + x**1024> +#ideal = #polynomial.int_polynomial<-1 + x**1024> #ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +!poly_ty = !polynomial.polynomial -#ntt_poly = #polynomial.polynomial<-1 + x**8> +#ntt_poly = #polynomial.int_polynomial<-1 + x**8> #ntt_ring = #polynomial.ring -!ntt_poly_ty = !polynomial.polynomial<#ntt_ring> +!ntt_poly_ty = !polynomial.polynomial module { - func.func @test_multiply() -> !polynomial.polynomial<#ring1> { + func.func @test_multiply() -> !polynomial.polynomial { %c0 = arith.constant 0 : index %two = arith.constant 2 : i16 %five = arith.constant 5 : i16 %coeffs1 = tensor.from_elements %two, %two, %five : tensor<3xi16> %coeffs2 = tensor.from_elements %five, %five, %two : tensor<3xi16> - %poly1 = polynomial.from_tensor %coeffs1 : tensor<3xi16> -> !polynomial.polynomial<#ring1> - %poly2 = polynomial.from_tensor %coeffs2 : tensor<3xi16> -> !polynomial.polynomial<#ring1> + %poly1 = polynomial.from_tensor %coeffs1 : tensor<3xi16> -> !polynomial.polynomial + %poly2 = polynomial.from_tensor %coeffs2 : tensor<3xi16> -> !polynomial.polynomial - %3 = polynomial.mul %poly1, %poly2 : !polynomial.polynomial<#ring1> + %3 = polynomial.mul %poly1, %poly2 : !polynomial.polynomial - return %3 : !polynomial.polynomial<#ring1> + return %3 : !polynomial.polynomial } - func.func @test_elementwise(%p0 : !polynomial.polynomial<#ring1>, %p1: !polynomial.polynomial<#ring1>) { - %tp0 = tensor.from_elements %p0, %p1 : tensor<2x!polynomial.polynomial<#ring1>> - %tp1 = tensor.from_elements %p1, %p0 : tensor<2x!polynomial.polynomial<#ring1>> + func.func @test_elementwise(%p0 : !polynomial.polynomial, %p1: !polynomial.polynomial) { + %tp0 = tensor.from_elements %p0, %p1 : tensor<2x!polynomial.polynomial> + %tp1 = tensor.from_elements %p1, %p0 : tensor<2x!polynomial.polynomial> %c = arith.constant 2 : i32 - %mul_const_sclr = polynomial.mul_scalar %tp0, %c : tensor<2x!polynomial.polynomial<#ring1>>, i32 + %mul_const_sclr = polynomial.mul_scalar %tp0, %c : tensor<2x!polynomial.polynomial>, i32 - %add = polynomial.add %tp0, %tp1 : tensor<2x!polynomial.polynomial<#ring1>> - %sub = polynomial.sub %tp0, %tp1 : tensor<2x!polynomial.polynomial<#ring1>> - %mul = polynomial.mul %tp0, %tp1 : tensor<2x!polynomial.polynomial<#ring1>> + %add = polynomial.add %tp0, %tp1 : tensor<2x!polynomial.polynomial> + %sub = polynomial.sub %tp0, %tp1 : tensor<2x!polynomial.polynomial> + %mul = polynomial.mul %tp0, %tp1 : tensor<2x!polynomial.polynomial> return } - func.func @test_to_from_tensor(%p0 : !polynomial.polynomial<#ring1>) { + func.func @test_to_from_tensor(%p0 : !polynomial.polynomial) { %c0 = arith.constant 0 : index %two = arith.constant 2 : i16 %coeffs1 = tensor.from_elements %two, %two : tensor<2xi16> // CHECK: from_tensor - %poly = polynomial.from_tensor %coeffs1 : tensor<2xi16> -> !polynomial.polynomial<#ring1> + %poly = polynomial.from_tensor %coeffs1 : tensor<2xi16> -> !polynomial.polynomial // CHECK: to_tensor - %tensor = polynomial.to_tensor %poly : !polynomial.polynomial<#ring1> -> tensor<1024xi16> + %tensor = polynomial.to_tensor %poly : !polynomial.polynomial -> tensor<1024xi16> return } - func.func @test_degree(%p0 : !polynomial.polynomial<#ring1>) { - %0, %1 = polynomial.leading_term %p0 : !polynomial.polynomial<#ring1> -> (index, i32) + func.func @test_degree(%p0 : !polynomial.polynomial) { + %0, %1 = polynomial.leading_term %p0 : !polynomial.polynomial -> (index, i32) return } func.func @test_monomial() { %deg = arith.constant 1023 : index %five = arith.constant 5 : i16 - %0 = polynomial.monomial %five, %deg : (i16, index) -> !polynomial.polynomial<#ring1> + %0 = polynomial.monomial %five, %deg : (i16, index) -> !polynomial.polynomial return } func.func @test_monic_monomial_mul() { %five = arith.constant 5 : index - %0 = polynomial.constant #one_plus_x_squared : !polynomial.polynomial<#ring1> - %1 = polynomial.monic_monomial_mul %0, %five : (!polynomial.polynomial<#ring1>, index) -> !polynomial.polynomial<#ring1> + %0 = polynomial.constant {value=#one_plus_x_squared} : !polynomial.polynomial + %1 = polynomial.monic_monomial_mul %0, %five : (!polynomial.polynomial, index) -> !polynomial.polynomial return } func.func @test_constant() { - %0 = polynomial.constant #one_plus_x_squared : !polynomial.polynomial<#ring1> - %1 = polynomial.constant <1 + x**2> : !polynomial.polynomial<#ring1> + %0 = polynomial.constant {value=#one_plus_x_squared} : !polynomial.polynomial + %1 = polynomial.constant {value=#polynomial.int_polynomial<1 + x**2>} : !polynomial.polynomial + %2 = polynomial.constant {value=#polynomial.float_polynomial<1.5 + 0.5 x**2>} : !polynomial.polynomial return } diff --git a/mlir/test/Dialect/Polynomial/ops_errors.mlir b/mlir/test/Dialect/Polynomial/ops_errors.mlir index 2c20e7bcbf1d..af8e4aa5da86 100644 --- a/mlir/test/Dialect/Polynomial/ops_errors.mlir +++ b/mlir/test/Dialect/Polynomial/ops_errors.mlir @@ -1,8 +1,8 @@ // RUN: mlir-opt --split-input-file --verify-diagnostics %s -#my_poly = #polynomial.polynomial<1 + x**1024> -#ring = #polynomial.ring -!ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<1 + x**1024> +#ring = #polynomial.ring +!ty = !polynomial.polynomial func.func @test_from_tensor_too_large_coeffs() { %two = arith.constant 2 : i32 @@ -15,13 +15,13 @@ func.func @test_from_tensor_too_large_coeffs() { // ----- -#my_poly = #polynomial.polynomial<1 + x**4> -#ring = #polynomial.ring -!ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<1 + x**4> +#ring = #polynomial.ring +!ty = !polynomial.polynomial func.func @test_from_tensor_wrong_tensor_type() { %two = arith.constant 2 : i32 %coeffs1 = tensor.from_elements %two, %two, %two, %two, %two : tensor<5xi32> - // expected-error@below {{input type 'tensor<5xi32>' does not match output type '!polynomial.polynomial<#polynomial.ring>>'}} + // expected-error@below {{input type 'tensor<5xi32>' does not match output type '!polynomial.polynomial>>'}} // expected-note@below {{at most the degree of the polynomialModulus of the output type's ring attribute}} %poly = polynomial.from_tensor %coeffs1 : tensor<5xi32> -> !ty return @@ -29,11 +29,11 @@ func.func @test_from_tensor_wrong_tensor_type() { // ----- -#my_poly = #polynomial.polynomial<1 + x**4> -#ring = #polynomial.ring -!ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<1 + x**4> +#ring = #polynomial.ring +!ty = !polynomial.polynomial func.func @test_to_tensor_wrong_output_tensor_type(%arg0 : !ty) { - // expected-error@below {{input type '!polynomial.polynomial<#polynomial.ring>>' does not match output type 'tensor<5xi32>'}} + // expected-error@below {{input type '!polynomial.polynomial>>' does not match output type 'tensor<5xi32>'}} // expected-note@below {{at most the degree of the polynomialModulus of the input type's ring attribute}} %tensor = polynomial.to_tensor %arg0 : !ty -> tensor<5xi32> return @@ -41,9 +41,9 @@ func.func @test_to_tensor_wrong_output_tensor_type(%arg0 : !ty) { // ----- -#my_poly = #polynomial.polynomial<1 + x**1024> -#ring = #polynomial.ring -!ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<1 + x**1024> +#ring = #polynomial.ring +!ty = !polynomial.polynomial func.func @test_mul_scalar_wrong_type(%arg0: !ty) -> !ty { %scalar = arith.constant 2 : i32 // should be i16 @@ -54,9 +54,9 @@ func.func @test_mul_scalar_wrong_type(%arg0: !ty) -> !ty { // ----- -#my_poly = #polynomial.polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_ntt // CHECK-NOT: polynomial.ntt @@ -68,9 +68,9 @@ func.func @test_invalid_ntt(%0 : !poly_ty) { // ----- -#my_poly = #polynomial.polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_ntt // CHECK-NOT: polynomial.ntt @@ -82,10 +82,10 @@ func.func @test_invalid_ntt(%0 : !poly_ty) { // ----- -#my_poly = #polynomial.polynomial<-1 + x**1024> -#ring = #polynomial.ring -#ring1 = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<-1 + x**1024> +#ring = #polynomial.ring +#ring1 = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_intt // CHECK-NOT: polynomial.intt @@ -97,9 +97,9 @@ func.func @test_invalid_intt(%0 : tensor<1024xi32, #ring1>) { // ----- -#my_poly = #polynomial.polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_intt // CHECK-NOT: polynomial.intt @@ -112,9 +112,9 @@ func.func @test_invalid_intt(%0 : tensor<1025xi32, #ring>) { // ----- -#my_poly = #polynomial.polynomial<-1 + x**1024> -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#my_poly = #polynomial.int_polynomial<-1 + x**1024> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_ntt // CHECK-NOT: polynomial.ntt @@ -126,10 +126,10 @@ func.func @test_invalid_ntt(%0 : !poly_ty) { // ----- -#my_poly = #polynomial.polynomial<-1 + x**8> +#my_poly = #polynomial.int_polynomial<-1 + x**8> // A valid root is 31 -#ring = #polynomial.ring -!poly_ty = !polynomial.polynomial<#ring> +#ring = #polynomial.ring +!poly_ty = !polynomial.polynomial // CHECK-NOT: @test_invalid_intt // CHECK-NOT: polynomial.intt diff --git a/mlir/test/Dialect/Polynomial/types.mlir b/mlir/test/Dialect/Polynomial/types.mlir index 00296a36e890..dcc5663ceb84 100644 --- a/mlir/test/Dialect/Polynomial/types.mlir +++ b/mlir/test/Dialect/Polynomial/types.mlir @@ -2,13 +2,13 @@ // CHECK-LABEL: func @test_types // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: #polynomial.ring< -// CHECK-SAME: coefficientType=i32, -// CHECK-SAME: coefficientModulus=2837465 : i32, -// CHECK-SAME: polynomialModulus=#polynomial.polynomial<1 + x**1024>>> -#my_poly = #polynomial.polynomial<1 + x**1024> -#ring1 = #polynomial.ring -!ty = !polynomial.polynomial<#ring1> +// CHECK-SAME: ring = < +// CHECK-SAME: coefficientType = i32, +// CHECK-SAME: coefficientModulus = 2837465 : i32, +// CHECK-SAME: polynomialModulus = <1 + x**1024>>> +#my_poly = #polynomial.int_polynomial<1 + x**1024> +#ring1 = #polynomial.ring +!ty = !polynomial.polynomial func.func @test_types(%0: !ty) -> !ty { return %0 : !ty } @@ -16,13 +16,13 @@ func.func @test_types(%0: !ty) -> !ty { // CHECK-LABEL: func @test_non_x_variable_64_bit // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: #polynomial.ring< -// CHECK-SAME: coefficientType=i64, -// CHECK-SAME: coefficientModulus=2837465 : i64, -// CHECK-SAME: polynomialModulus=#polynomial.polynomial<2 + 4x + x**3>>> -#my_poly_2 = #polynomial.polynomial -#ring2 = #polynomial.ring -!ty2 = !polynomial.polynomial<#ring2> +// CHECK-SAME: ring = < +// CHECK-SAME: coefficientType = i64, +// CHECK-SAME: coefficientModulus = 2837465 : i64, +// CHECK-SAME: polynomialModulus = <2 + 4x + x**3>>> +#my_poly_2 = #polynomial.int_polynomial +#ring2 = #polynomial.ring +!ty2 = !polynomial.polynomial func.func @test_non_x_variable_64_bit(%0: !ty2) -> !ty2 { return %0 : !ty2 } @@ -30,27 +30,36 @@ func.func @test_non_x_variable_64_bit(%0: !ty2) -> !ty2 { // CHECK-LABEL: func @test_linear_poly // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: #polynomial.ring< -// CHECK-SAME: coefficientType=i32, -// CHECK-SAME: coefficientModulus=12 : i32, -// CHECK-SAME: polynomialModulus=#polynomial.polynomial<4x>> -#my_poly_3 = #polynomial.polynomial<4x> -#ring3 = #polynomial.ring -!ty3 = !polynomial.polynomial<#ring3> +// CHECK-SAME: ring = < +// CHECK-SAME: coefficientType = i32, +// CHECK-SAME: coefficientModulus = 12 : i32, +// CHECK-SAME: polynomialModulus = <4x>> +#my_poly_3 = #polynomial.int_polynomial<4x> +#ring3 = #polynomial.ring +!ty3 = !polynomial.polynomial func.func @test_linear_poly(%0: !ty3) -> !ty3 { return %0 : !ty3 } // CHECK-LABEL: func @test_negative_leading_1 // CHECK-SAME: !polynomial.polynomial< -// CHECK-SAME: #polynomial.ring< -// CHECK-SAME: coefficientType=i32, -// CHECK-SAME: coefficientModulus=2837465 : i32, -// CHECK-SAME: polynomialModulus=#polynomial.polynomial<-1 + x**1024>>> -#my_poly_4 = #polynomial.polynomial<-1 + x**1024> -#ring4 = #polynomial.ring -!ty4 = !polynomial.polynomial<#ring4> +// CHECK-SAME: ring = < +// CHECK-SAME: coefficientType = i32, +// CHECK-SAME: coefficientModulus = 2837465 : i32, +// CHECK-SAME: polynomialModulus = <-1 + x**1024>>> +#my_poly_4 = #polynomial.int_polynomial<-1 + x**1024> +#ring4 = #polynomial.ring +!ty4 = !polynomial.polynomial func.func @test_negative_leading_1(%0: !ty4) -> !ty4 { return %0 : !ty4 } +// CHECK-LABEL: func @test_float_coefficients +// CHECK-SAME: !polynomial.polynomial> +#my_poly_5 = #polynomial.float_polynomial<0.5 + 1.6e03 x**1024> +#ring5 = #polynomial.ring +!ty5 = !polynomial.polynomial +func.func @test_float_coefficients(%0: !ty5) -> !ty5 { + return %0 : !ty5 +} + -- GitLab From 344c73ee831995d78d6eca1bed101878b5bae1bc Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Tue, 14 May 2024 19:04:40 +0200 Subject: [PATCH 251/578] [libc][bazel] Updates for 292b300c5131e54b9977305bb4aca9a03e1b4fed --- .../libc/test/src/string/BUILD.bazel | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/string/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/string/BUILD.bazel index d96f390c0c38..fb0046e9f89d 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/string/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/src/string/BUILD.bazel @@ -126,13 +126,26 @@ libc_support_library( ], ) +libc_support_library( + name = "protected_pages", + hdrs = ["memory_utils/protected_pages.h"], + deps = [ + "//libc:__support_macros_attributes", + "//libc:__support_macros_properties_os", + ], +) + libc_test( name = "memcpy_test", srcs = ["memcpy_test.cpp"], libc_function_deps = [ "//libc:memcpy", ], - deps = [":memory_check_utils"], + deps = [ + ":memory_check_utils", + ":protected_pages", + "//libc:__support_macros_properties_os", + ], ) libc_test( @@ -149,7 +162,11 @@ libc_test( libc_function_deps = [ "//libc:memset", ], - deps = [":memory_check_utils"], + deps = [ + ":memory_check_utils", + ":protected_pages", + "//libc:__support_macros_properties_os", + ], ) libc_test( -- GitLab From 5f7477a72b826d0d6e7369ebe93cefcd55682d95 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 14 May 2024 10:07:13 -0700 Subject: [PATCH 252/578] RISCVAsmParser: Make diagnostics more conventional Most diagnostics obey https://llvm.org/docs/CodingStandards.html#error-and-warning-messages but some diverge. Fix them. While here, adjust some diagnostics. Pull Request: https://github.com/llvm/llvm-project/pull/92024 --- .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 47 ++-- llvm/test/MC/RISCV/option-invalid.s | 6 +- .../test/MC/RISCV/rv32xtheadmempair-invalid.s | 8 +- llvm/test/MC/RISCV/rv32zcmp-invalid.s | 2 +- .../test/MC/RISCV/rv64xtheadmempair-invalid.s | 12 +- llvm/test/MC/RISCV/rv64zcmp-invalid.s | 2 +- llvm/test/MC/RISCV/rvv/invalid.s | 260 +++++++++--------- llvm/test/MC/RISCV/rvv/xsfvcp-invalid.s | 8 +- llvm/test/MC/RISCV/rvv/zvbb-invalid.s | 6 +- llvm/test/MC/RISCV/rvv/zvkned-invalid.s | 10 +- llvm/test/MC/RISCV/rvv/zvknh-invalid.s | 12 +- llvm/test/MC/RISCV/rvv/zvksed-invalid.s | 2 +- llvm/test/MC/RISCV/rvv/zvksh-invalid.s | 4 +- 13 files changed, 189 insertions(+), 190 deletions(-) diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 6af1d5010d3a..7da1b7e360c7 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -2829,12 +2829,12 @@ bool RISCVAsmParser::parseDirectiveOption() { if (isDigit(Arch.back())) return Error( - Loc, "Extension version number parsing not currently implemented"); + Loc, "extension version number parsing not currently implemented"); std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch); if (!enableExperimentalExtension() && StringRef(Feature).starts_with("experimental-")) - return Error(Loc, "Unexpected experimental extensions."); + return Error(Loc, "unexpected experimental extensions"); auto Ext = llvm::lower_bound(RISCVFeatureKV, Feature); if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Feature) return Error(Loc, "unknown extension feature"); @@ -2866,10 +2866,10 @@ bool RISCVAsmParser::parseDirectiveOption() { for (auto &Feature : RISCVFeatureKV) { if (getSTI().hasFeature(Feature.Value) && Feature.Implies.test(Ext->Value)) - return Error(Loc, - Twine("Can't disable ") + Ext->Key + " extension, " + - Feature.Key + " extension requires " + Ext->Key + - " extension be enabled"); + return Error(Loc, Twine("can't disable ") + Ext->Key + + " extension; " + Feature.Key + + " extension requires " + Ext->Key + + " extension"); } clearFeatureBits(Ext->Value, Ext->Key); @@ -3382,8 +3382,8 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst, unsigned TempReg = Inst.getOperand(1).getReg(); if (DestReg == TempReg) { SMLoc Loc = Operands.back()->getStartLoc(); - return Error(Loc, "The temporary vector register cannot be the same as " - "the destination register."); + return Error(Loc, "the temporary vector register cannot be the same as " + "the destination register"); } } @@ -3395,8 +3395,7 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst, // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair. if (Rs1 == Rd1 && Rs1 == Rd2) { SMLoc Loc = Operands[1]->getStartLoc(); - return Error(Loc, "The source register and destination registers " - "cannot be equal."); + return Error(Loc, "rs1, rd1, and rd2 cannot all be the same"); } } @@ -3405,7 +3404,7 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst, unsigned Rd2 = Inst.getOperand(1).getReg(); if (Rd1 == Rd2) { SMLoc Loc = Operands[1]->getStartLoc(); - return Error(Loc, "'rs1' and 'rs2' must be different."); + return Error(Loc, "rs1 and rs2 must be different"); } } @@ -3416,10 +3415,10 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst, // depending on the data width. if (IsTHeadMemPair32 && Inst.getOperand(4).getImm() != 3) { SMLoc Loc = Operands.back()->getStartLoc(); - return Error(Loc, "Operand must be constant 3."); + return Error(Loc, "operand must be constant 3"); } else if (IsTHeadMemPair64 && Inst.getOperand(4).getImm() != 4) { SMLoc Loc = Operands.back()->getStartLoc(); - return Error(Loc, "Operand must be constant 4."); + return Error(Loc, "operand must be constant 4"); } const MCInstrDesc &MCID = MII.get(Opcode); @@ -3434,14 +3433,14 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst, if (MCID.TSFlags & RISCVII::VS1Constraint) { unsigned VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg(); if (VCIXDst == VCIXRs1) - return Error(VCIXDstLoc, "The destination vector register group cannot" - " overlap the source vector register group."); + return Error(VCIXDstLoc, "the destination vector register group cannot" + " overlap the source vector register group"); } if (MCID.TSFlags & RISCVII::VS2Constraint) { unsigned VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg(); if (VCIXDst == VCIXRs2) - return Error(VCIXDstLoc, "The destination vector register group cannot" - " overlap the source vector register group."); + return Error(VCIXDstLoc, "the destination vector register group cannot" + " overlap the source vector register group"); } return false; } @@ -3457,14 +3456,14 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst, if (MCID.TSFlags & RISCVII::VS2Constraint) { unsigned CheckReg = Inst.getOperand(Offset + 1).getReg(); if (DestReg == CheckReg) - return Error(Loc, "The destination vector register group cannot overlap" - " the source vector register group."); + return Error(Loc, "the destination vector register group cannot overlap" + " the source vector register group"); } if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) { unsigned CheckReg = Inst.getOperand(Offset + 2).getReg(); if (DestReg == CheckReg) - return Error(Loc, "The destination vector register group cannot overlap" - " the source vector register group."); + return Error(Loc, "the destination vector register group cannot overlap" + " the source vector register group"); } if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) { // vadc, vsbc are special cases. These instructions have no mask register. @@ -3474,7 +3473,7 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst, Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM || Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM || Opcode == RISCV::VMERGE_VXM) - return Error(Loc, "The destination vector register group cannot be V0."); + return Error(Loc, "the destination vector register group cannot be V0"); // Regardless masked or unmasked version, the number of operands is the // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister" @@ -3485,8 +3484,8 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst, "Unexpected register for mask operand"); if (DestReg == CheckReg) - return Error(Loc, "The destination vector register group cannot overlap" - " the mask register."); + return Error(Loc, "the destination vector register group cannot overlap" + " the mask register"); } return false; } diff --git a/llvm/test/MC/RISCV/option-invalid.s b/llvm/test/MC/RISCV/option-invalid.s index ee520e08746a..7f6de5f38c52 100644 --- a/llvm/test/MC/RISCV/option-invalid.s +++ b/llvm/test/MC/RISCV/option-invalid.s @@ -34,14 +34,14 @@ # CHECK: :[[#@LINE+1]]:18: error: expected comma .option arch, +c foo -# CHECK: :[[#@LINE+1]]:16: error: Extension version number parsing not currently implemented +# CHECK: :[[#@LINE+1]]:16: error: extension version number parsing not currently implemented .option arch, +c2p0 .option arch, +d -# CHECK: :[[#@LINE+1]]:16: error: Can't disable f extension, d extension requires f extension be enabled +# CHECK: :[[#@LINE+1]]:16: error: can't disable f extension; d extension requires f extension .option arch, -f -# CHECK: :[[#@LINE+1]]:16: error: Can't disable zicsr extension, f extension requires zicsr extension be enabled +# CHECK: :[[#@LINE+1]]:16: error: can't disable zicsr extension; f extension requires zicsr extension .option arch, -zicsr # CHECK: :[[#@LINE+1]]:20: error: 'f' and 'zfinx' extensions are incompatible diff --git a/llvm/test/MC/RISCV/rv32xtheadmempair-invalid.s b/llvm/test/MC/RISCV/rv32xtheadmempair-invalid.s index 94319dea1c17..9124218c1f8f 100644 --- a/llvm/test/MC/RISCV/rv32xtheadmempair-invalid.s +++ b/llvm/test/MC/RISCV/rv32xtheadmempair-invalid.s @@ -8,13 +8,13 @@ th.sdd a0, a1, (a2) # CHECK: [[@LINE]]:1: error: too few operands for in th.sdd a0, a1, (a2), 3, 5 # CHECK: [[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} th.lwud t0, t1, (t2), 5, 4 # CHECK: [[@LINE]]:23: error: immediate must be an integer in the range [0, 3] th.lwud t0, t1, (t2) # CHECK: [[@LINE]]:1: error: too few operands for instruction -th.lwud t0, t1, (t2), 3, 5 # CHECK: [[@LINE]]:26: error: Operand must be constant 3. +th.lwud t0, t1, (t2), 3, 5 # CHECK: [[@LINE]]:26: error: operand must be constant 3 th.lwd a3, a4, (a5), 5, 4 # CHECK: [[@LINE]]:22: error: immediate must be an integer in the range [0, 3] th.lwd a3, a4, (a5) # CHECK: [[@LINE]]:1: error: too few operands for instruction -th.lwd a3, a4, (a5), 3, 5 # CHECK: [[@LINE]]:25: error: Operand must be constant 3. +th.lwd a3, a4, (a5), 3, 5 # CHECK: [[@LINE]]:25: error: operand must be constant 3 th.swd t3, t4, (t5), 5, 4 # CHECK: [[@LINE]]:22: error: immediate must be an integer in the range [0, 3] th.swd t3, t4, (t5) # CHECK: [[@LINE]]:1: error: too few operands for instruction -th.swd t3, t4, (t5), 3, 5 # CHECK: [[@LINE]]:25: error: Operand must be constant 3. -th.lwud x6, x6, (x6), 2, 3 # CHECK: [[@LINE]]:9: error: The source register and destination registers cannot be equal. +th.swd t3, t4, (t5), 3, 5 # CHECK: [[@LINE]]:25: error: operand must be constant 3 +th.lwud x6, x6, (x6), 2, 3 # CHECK: [[@LINE]]:9: error: rs1, rd1, and rd2 cannot all be the same th.ldd t0, t1, (t2), 2, 4 # CHECK: [[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} th.sdd t0, t1, (t2), 2, 4 # CHECK: [[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}} diff --git a/llvm/test/MC/RISCV/rv32zcmp-invalid.s b/llvm/test/MC/RISCV/rv32zcmp-invalid.s index 1acea187585f..2ed82bc55be3 100644 --- a/llvm/test/MC/RISCV/rv32zcmp-invalid.s +++ b/llvm/test/MC/RISCV/rv32zcmp-invalid.s @@ -4,7 +4,7 @@ # CHECK-ERROR: error: invalid operand for instruction cm.mvsa01 a1, a2 -# CHECK-ERROR: error: 'rs1' and 'rs2' must be different +# CHECK-ERROR: error: rs1 and rs2 must be different cm.mvsa01 s0, s0 # CHECK-ERROR: error: invalid operand for instruction diff --git a/llvm/test/MC/RISCV/rv64xtheadmempair-invalid.s b/llvm/test/MC/RISCV/rv64xtheadmempair-invalid.s index cf56a1fcccaf..342db21bbca6 100644 --- a/llvm/test/MC/RISCV/rv64xtheadmempair-invalid.s +++ b/llvm/test/MC/RISCV/rv64xtheadmempair-invalid.s @@ -2,17 +2,17 @@ th.ldd t0, t1, (t2), 5, 4 # CHECK: [[@LINE]]:22: error: immediate must be an integer in the range [0, 3] th.ldd t0, t1, (t2) # CHECK: [[@LINE]]:1: error: too few operands for instruction -th.ldd t0, t1, (t2), 3, 5 # CHECK: [[@LINE]]:25: error: Operand must be constant 4. +th.ldd t0, t1, (t2), 3, 5 # CHECK: [[@LINE]]:25: error: operand must be constant 4 th.sdd a0, a1, (a2), 5, 4 # CHECK: [[@LINE]]:22: error: immediate must be an integer in the range [0, 3] th.sdd a0, a1, (a2) # CHECK: [[@LINE]]:1: error: too few operands for instruction -th.sdd a0, a1, (a2), 3, 5 # CHECK: [[@LINE]]:25: error: Operand must be constant 4. +th.sdd a0, a1, (a2), 3, 5 # CHECK: [[@LINE]]:25: error: operand must be constant 4 th.lwud t0, t1, (t2), 5, 4 # CHECK: [[@LINE]]:23: error: immediate must be an integer in the range [0, 3] th.lwud t0, t1, (t2) # CHECK: [[@LINE]]:1: error: too few operands for instruction -th.lwud t0, t1, (t2), 3, 5 # CHECK: [[@LINE]]:26: error: Operand must be constant 3. +th.lwud t0, t1, (t2), 3, 5 # CHECK: [[@LINE]]:26: error: operand must be constant 3 th.lwd a3, a4, (a5), 5, 4 # CHECK: [[@LINE]]:22: error: immediate must be an integer in the range [0, 3] th.lwd a3, a4, (a5) # CHECK: [[@LINE]]:1: error: too few operands for instruction -th.lwd a3, a4, (a5), 3, 5 # CHECK: [[@LINE]]:25: error: Operand must be constant 3. +th.lwd a3, a4, (a5), 3, 5 # CHECK: [[@LINE]]:25: error: operand must be constant 3 th.swd t3, t4, (t5), 5, 4 # CHECK: [[@LINE]]:22: error: immediate must be an integer in the range [0, 3] th.swd t3, t4, (t5) # CHECK: [[@LINE]]:1: error: too few operands for instruction -th.swd t3, t4, (t5), 3, 5 # CHECK: [[@LINE]]:25: error: Operand must be constant 3. -th.lwud x6, x6, (x6), 2, 3 # CHECK: [[@LINE]]:9: error: The source register and destination registers cannot be equal. +th.swd t3, t4, (t5), 3, 5 # CHECK: [[@LINE]]:25: error: operand must be constant 3 +th.lwud x6, x6, (x6), 2, 3 # CHECK: [[@LINE]]:9: error: rs1, rd1, and rd2 cannot all be the same diff --git a/llvm/test/MC/RISCV/rv64zcmp-invalid.s b/llvm/test/MC/RISCV/rv64zcmp-invalid.s index bf34554095ea..8f353e8a7bb4 100644 --- a/llvm/test/MC/RISCV/rv64zcmp-invalid.s +++ b/llvm/test/MC/RISCV/rv64zcmp-invalid.s @@ -4,7 +4,7 @@ # CHECK-ERROR: error: invalid operand for instruction cm.mvsa01 a1, a2 -# CHECK-ERROR: error: 'rs1' and 'rs2' must be different +# CHECK-ERROR: error: rs1 and rs2 must be different cm.mvsa01 s0, s0 # CHECK-ERROR: error: invalid operand for instruction diff --git a/llvm/test/MC/RISCV/rvv/invalid.s b/llvm/test/MC/RISCV/rvv/invalid.s index 09fd2c3bebf0..8c50f7ed048c 100644 --- a/llvm/test/MC/RISCV/rvv/invalid.s +++ b/llvm/test/MC/RISCV/rvv/invalid.s @@ -96,471 +96,471 @@ vmslt.vi v1, v2, 17 # CHECK-ERROR: immediate must be in the range [-15, 16] viota.m v0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: viota.m v0, v2, v0.t viota.m v2, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: viota.m v2, v2 vfwcvt.xu.f.v v0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwcvt.xu.f.v v0, v2, v0.t vfwcvt.xu.f.v v2, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwcvt.xu.f.v v2, v2 vfwcvt.x.f.v v0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwcvt.x.f.v v0, v2, v0.t vfwcvt.x.f.v v2, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwcvt.x.f.v v2, v2 vfwcvt.f.xu.v v0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwcvt.f.xu.v v0, v2, v0.t vfwcvt.f.xu.v v2, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwcvt.f.xu.v v2, v2 vfwcvt.f.x.v v0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwcvt.f.x.v v0, v2, v0.t vfwcvt.f.x.v v2, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwcvt.f.x.v v2, v2 vfwcvt.f.f.v v0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwcvt.f.f.v v0, v2, v0.t vfwcvt.f.f.v v2, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwcvt.f.f.v v2, v2 vslideup.vx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vslideup.vx v0, v2, a0, v0.t vslideup.vx v2, v2, a0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vslideup.vx v2, v2, a0 vslideup.vi v0, v2, 31, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vslideup.vi v0, v2, 31, v0.t vslideup.vi v2, v2, 31 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vslideup.vi v2, v2, 31 vslide1up.vx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vslide1up.vx v0, v2, a0, v0.t vslide1up.vx v2, v2, a0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vslide1up.vx v2, v2, a0 vrgather.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vrgather.vv v0, v2, v4, v0.t vrgather.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vrgather.vv v2, v2, v4 vrgather.vx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vrgather.vx v0, v2, a0, v0.t vrgather.vx v2, v2, a0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vrgather.vx v2, v2, a0 vrgather.vi v0, v2, 31, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vrgather.vi v0, v2, 31, v0.t vrgather.vi v2, v2, 31 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vrgather.vi v2, v2, 31 vwaddu.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwaddu.vv v0, v2, v4, v0.t vwaddu.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwaddu.vv v2, v2, v4 vwsubu.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwsubu.vv v0, v2, v4, v0.t vwsubu.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwsubu.vv v2, v2, v4 vwadd.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwadd.vv v0, v2, v4, v0.t vwadd.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwadd.vv v2, v2, v4 vwsub.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwsub.vv v0, v2, v4, v0.t vwsub.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwsub.vv v2, v2, v4 vwmul.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmul.vv v0, v2, v4, v0.t vwmul.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmul.vv v2, v2, v4 vwmulu.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmulu.vv v0, v2, v4, v0.t vwmulu.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmulu.vv v2, v2, v4 vwmulsu.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmulsu.vv v0, v2, v4, v0.t vwmulsu.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmulsu.vv v2, v2, v4 vwmaccu.vv v0, v4, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmaccu.vv v0, v4, v2, v0.t vwmaccu.vv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmaccu.vv v2, v4, v2 vwmacc.vv v0, v4, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmacc.vv v0, v4, v2, v0.t vwmacc.vv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmacc.vv v2, v4, v2 vwmaccsu.vv v0, v4, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmaccsu.vv v0, v4, v2, v0.t vwmaccsu.vv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmaccsu.vv v2, v4, v2 vfwadd.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwadd.vv v0, v2, v4, v0.t vfwadd.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwadd.vv v2, v2, v4 vfwsub.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwsub.vv v0, v2, v4, v0.t vfwsub.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwsub.vv v2, v2, v4 vfwmul.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwmul.vv v0, v2, v4, v0.t vfwmul.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwmul.vv v2, v2, v4 vfwmacc.vv v0, v4, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwmacc.vv v0, v4, v2, v0.t vfwmacc.vv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwmacc.vv v2, v4, v2 vfwnmacc.vv v0, v4, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwnmacc.vv v0, v4, v2, v0.t vfwnmacc.vv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwnmacc.vv v2, v4, v2 vfwmsac.vv v0, v4, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwmsac.vv v0, v4, v2, v0.t vfwmsac.vv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwmsac.vv v2, v4, v2 vfwnmsac.vv v0, v4, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwnmsac.vv v0, v4, v2, v0.t vfwnmsac.vv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwnmsac.vv v2, v4, v2 vwaddu.vx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwaddu.vx v0, v2, a0, v0.t vwaddu.vx v2, v2, a0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwaddu.vx v2, v2, a0 vwsubu.vx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwsubu.vx v0, v2, a0, v0.t vwsubu.vx v2, v2, a0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwsubu.vx v2, v2, a0 vwadd.vx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwadd.vx v0, v2, a0, v0.t vwadd.vx v2, v2, a0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwadd.vx v2, v2, a0 vwsub.vx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwsub.vx v0, v2, a0, v0.t vwsub.vx v2, v2, a0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwsub.vx v2, v2, a0 vwmul.vx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmul.vx v0, v2, a0, v0.t vwmul.vx v2, v2, a0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmul.vx v2, v2, a0 vwmulu.vx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmulu.vx v0, v2, a0, v0.t vwmulu.vx v2, v2, a0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmulu.vx v2, v2, a0 vwmulsu.vx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmulsu.vx v0, v2, a0, v0.t vwmulsu.vx v2, v2, a0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmulsu.vx v2, v2, a0 vwmaccu.vx v0, a0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmaccu.vx v0, a0, v2, v0.t vwmaccu.vx v2, a0, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmaccu.vx v2, a0, v2 vwmacc.vx v0, a0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmacc.vx v0, a0, v2, v0.t vwmacc.vx v2, a0, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmacc.vx v2, a0, v2 vwmaccsu.vx v0, a0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmaccsu.vx v0, a0, v2, v0.t vwmaccsu.vx v2, a0, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmaccsu.vx v2, a0, v2 vwmaccus.vx v0, a0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwmaccus.vx v0, a0, v2, v0.t vwmaccus.vx v2, a0, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwmaccus.vx v2, a0, v2 vfwadd.vf v0, v2, fa0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwadd.vf v0, v2, fa0, v0.t vfwadd.vf v2, v2, fa0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwadd.vf v2, v2, fa0 vfwsub.vf v0, v2, fa0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwsub.vf v0, v2, fa0, v0.t vfwsub.vf v2, v2, fa0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwsub.vf v2, v2, fa0 vfwmul.vf v0, v2, fa0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwmul.vf v0, v2, fa0, v0.t vfwmul.vf v2, v2, fa0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwmul.vf v2, v2, fa0 vfwmacc.vf v0, fa0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwmacc.vf v0, fa0, v2, v0.t vfwmacc.vf v2, fa0, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwmacc.vf v2, fa0, v2 vfwnmacc.vf v0, fa0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwnmacc.vf v0, fa0, v2, v0.t vfwnmacc.vf v2, fa0, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwnmacc.vf v2, fa0, v2 vfwmsac.vf v0, fa0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwmsac.vf v0, fa0, v2, v0.t vfwmsac.vf v2, fa0, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwmsac.vf v2, fa0, v2 vfwnmsac.vf v0, fa0, v2, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwnmsac.vf v0, fa0, v2, v0.t vfwnmsac.vf v2, fa0, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwnmsac.vf v2, fa0, v2 vcompress.vm v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vcompress.vm v2, v2, v4 vwaddu.wv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwaddu.wv v0, v2, v4, v0.t vwaddu.wv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwaddu.wv v2, v4, v2 vwsubu.wv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwsubu.wv v0, v2, v4, v0.t vwsubu.wv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwsubu.wv v2, v4, v2 vwadd.wv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwadd.wv v0, v2, v4, v0.t vwadd.wv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwadd.wv v2, v4, v2 vwsub.wv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwsub.wv v0, v2, v4, v0.t vwsub.wv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwsub.wv v2, v4, v2 vfwadd.wv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwadd.wv v0, v2, v4, v0.t vfwadd.wv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwadd.wv v2, v4, v2 vfwsub.wv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwsub.wv v0, v2, v4, v0.t vfwsub.wv v2, v4, v2 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vfwsub.wv v2, v4, v2 vwaddu.wx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwaddu.wx v0, v2, a0, v0.t vwsubu.wx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwsubu.wx v0, v2, a0, v0.t vwadd.wx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwadd.wx v0, v2, a0, v0.t vwsub.wx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vwsub.wx v0, v2, a0, v0.t vfwadd.wf v0, v2, fa0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwadd.wf v0, v2, fa0, v0.t vfwsub.wf v0, v2, fa0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfwsub.wf v0, v2, fa0, v0.t vadc.vvm v0, v2, v4, v0 -# CHECK-ERROR: The destination vector register group cannot be V0. +# CHECK-ERROR: the destination vector register group cannot be V0 # CHECK-ERROR-LABEL: vadc.vvm v0, v2, v4, v0 vadd.vv v0, v2, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vadd.vv v0, v2, v4, v0.t vadd.vx v0, v2, a0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vadd.vx v0, v2, a0, v0.t vadd.vi v0, v2, 1, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vadd.vi v0, v2, 1, v0.t vmsge.vx v0, v4, a0, v0.t @@ -568,47 +568,47 @@ vmsge.vx v0, v4, a0, v0.t # CHECK-ERROR-LABEL: vmsge.vx v0, v4, a0, v0.t vmerge.vim v0, v1, 1, v0 -# CHECK-ERROR: The destination vector register group cannot be V0. +# CHECK-ERROR: the destination vector register group cannot be V0 # CHECK-ERROR-LABEL: vmerge.vim v0, v1, 1, v0 vmerge.vvm v0, v1, v2, v0 -# CHECK-ERROR: The destination vector register group cannot be V0. +# CHECK-ERROR: the destination vector register group cannot be V0 # CHECK-ERROR-LABEL: vmerge.vvm v0, v1, v2, v0 vmerge.vxm v0, v1, x1, v0 -# CHECK-ERROR: The destination vector register group cannot be V0. +# CHECK-ERROR: the destination vector register group cannot be V0 # CHECK-ERROR-LABEL: vmerge.vxm v0, v1, x1, v0 vfmerge.vfm v0, v1, f1, v0 -# CHECK-ERROR: The destination vector register group cannot be V0. +# CHECK-ERROR: the destination vector register group cannot be V0 # CHECK-ERROR-LABEL: vfmerge.vfm v0, v1, f1, v0 vle8.v v0, (a0), v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vle8.v v0, (a0), v0.t vfclass.v v0, v1, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfclass.v v0, v1, v0.t vfsqrt.v v0, v1, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfsqrt.v v0, v1, v0.t vzext.vf2 v0, v1, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vzext.vf2 v0, v1, v0.t vid.v v0, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vid.v v0, v0.t vnsrl.wv v0, v4, v20, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vnsrl.wv v0, v4, v20, v0.t vfncvt.xu.f.w v0, v4, v0.t -# CHECK-ERROR: The destination vector register group cannot overlap the mask register. +# CHECK-ERROR: the destination vector register group cannot overlap the mask register # CHECK-ERROR-LABEL: vfncvt.xu.f.w v0, v4, v0.t vl2re8.v v1, (a0) @@ -750,7 +750,7 @@ vmsgeu.vx v2, v4, a0, v0.t, v0 # CHECK-ERROR: invalid operand for instruction vmsge.vx v2, v4, a0, v0.t, v2 -# CHECK-ERROR: The temporary vector register cannot be the same as the destination register. +# CHECK-ERROR: the temporary vector register cannot be the same as the destination register vmsgeu.vx v2, v4, a0, v0.t, v2 -# CHECK-ERROR: The temporary vector register cannot be the same as the destination register. +# CHECK-ERROR: the temporary vector register cannot be the same as the destination register diff --git a/llvm/test/MC/RISCV/rvv/xsfvcp-invalid.s b/llvm/test/MC/RISCV/rvv/xsfvcp-invalid.s index 52dc32b8c6a8..9ba2a8d2f729 100644 --- a/llvm/test/MC/RISCV/rvv/xsfvcp-invalid.s +++ b/llvm/test/MC/RISCV/rvv/xsfvcp-invalid.s @@ -4,17 +4,17 @@ # RUN: | FileCheck %s --check-prefix=CHECK-ERROR sf.vc.v.vvw 0x3, v0, v2, v0 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group.{{$}} +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group{{$}} # CHECK-ERROR-LABEL: sf.vc.v.vvw 0x3, v0, v2, v0{{$}} sf.vc.v.xvw 0x3, v0, v0, a1 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group.{{$}} +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group{{$}} # CHECK-ERROR-LABEL: sf.vc.v.xvw 0x3, v0, v0, a1{{$}} sf.vc.v.ivw 0x3, v0, v0, 15 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group.{{$}} +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group{{$}} # CHECK-ERROR-LABEL: sf.vc.v.ivw 0x3, v0, v0, 15{{$}} sf.vc.v.fvw 0x1, v0, v0, fa1 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group.{{$}} +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group{{$}} # CHECK-ERROR-LABEL: sf.vc.v.fvw 0x1, v0, v0, fa1{{$}} diff --git a/llvm/test/MC/RISCV/rvv/zvbb-invalid.s b/llvm/test/MC/RISCV/rvv/zvbb-invalid.s index ca581de02fd6..42113c3c0ffe 100644 --- a/llvm/test/MC/RISCV/rvv/zvbb-invalid.s +++ b/llvm/test/MC/RISCV/rvv/zvbb-invalid.s @@ -2,13 +2,13 @@ # RUN: | FileCheck %s --check-prefix=CHECK-ERROR vwsll.vv v2, v2, v4 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwsll.vv v2, v2, v4 vwsll.vx v2, v2, x10 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwsll.vx v2, v2, x10 vwsll.vi v2, v2, 1 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vwsll.vi v2, v2, 1 diff --git a/llvm/test/MC/RISCV/rvv/zvkned-invalid.s b/llvm/test/MC/RISCV/rvv/zvkned-invalid.s index 9230bc08e3fa..2d57a2816980 100644 --- a/llvm/test/MC/RISCV/rvv/zvkned-invalid.s +++ b/llvm/test/MC/RISCV/rvv/zvkned-invalid.s @@ -2,22 +2,22 @@ # RUN: | FileCheck %s --check-prefix=CHECK-ERROR vaesdf.vs v10, v10 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vaesdf.vs v10, v10 vaesef.vs v11, v11 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vaesef.vs v11, v11 vaesdm.vs v12, v12 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vaesdm.vs v12, v12 vaesem.vs v13, v13 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vaesem.vs v13, v13 vaesz.vs v14, v14 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vaesz.vs v14, v14 diff --git a/llvm/test/MC/RISCV/rvv/zvknh-invalid.s b/llvm/test/MC/RISCV/rvv/zvknh-invalid.s index d9902511c0e1..f5c9ee57ff78 100644 --- a/llvm/test/MC/RISCV/rvv/zvknh-invalid.s +++ b/llvm/test/MC/RISCV/rvv/zvknh-invalid.s @@ -2,25 +2,25 @@ # RUN: | FileCheck %s --check-prefix=CHECK-ERROR vsha2ms.vv v10, v10, v11 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vsha2ms.vv v10, v10, v11 vsha2ms.vv v11, v10, v11 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vsha2ms.vv v11, v10, v11 vsha2ch.vv v12, v12, v11 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vsha2ch.vv v12, v12, v11 vsha2ch.vv v11, v12, v11 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vsha2ch.vv v11, v12, v11 vsha2cl.vv v13, v13, v15 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vsha2cl.vv v13, v13, v15 vsha2cl.vv v15, v13, v15 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vsha2cl.vv v15, v13, v15 diff --git a/llvm/test/MC/RISCV/rvv/zvksed-invalid.s b/llvm/test/MC/RISCV/rvv/zvksed-invalid.s index 41df8d3bc296..0f348a2ca5ad 100644 --- a/llvm/test/MC/RISCV/rvv/zvksed-invalid.s +++ b/llvm/test/MC/RISCV/rvv/zvksed-invalid.s @@ -2,5 +2,5 @@ # RUN: | FileCheck %s --check-prefix=CHECK-ERROR vsm4r.vs v10, v10 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vsm4r.vs v10, v10 diff --git a/llvm/test/MC/RISCV/rvv/zvksh-invalid.s b/llvm/test/MC/RISCV/rvv/zvksh-invalid.s index cccec44b8191..27a11ed9b969 100644 --- a/llvm/test/MC/RISCV/rvv/zvksh-invalid.s +++ b/llvm/test/MC/RISCV/rvv/zvksh-invalid.s @@ -2,9 +2,9 @@ # RUN: | FileCheck %s --check-prefix=CHECK-ERROR vsm3me.vv v10, v10, v8 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vsm3me.vv v10, v10, v8 vsm3c.vi v9, v9, 7 -# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR: the destination vector register group cannot overlap the source vector register group # CHECK-ERROR-LABEL: vsm3c.vi v9, v9, 7 -- GitLab From 1355dcbb6e8b40780f1fbaa89cde50aa763dab89 Mon Sep 17 00:00:00 2001 From: quanwanandy <150498259+quanwanandy@users.noreply.github.com> Date: Tue, 14 May 2024 10:07:26 -0700 Subject: [PATCH 253/578] Fix Bazel Build (#92139) --- .../llvm-project-overlay/mlir/BUILD.bazel | 19 +++++++++++++++++++ .../mlir/test/BUILD.bazel | 2 ++ 2 files changed, 21 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index debd8daf5549..a3171287a84b 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -2092,6 +2092,20 @@ gentbl_cc_library( deps = [":ArmSMETdFiles"], ) +cc_library( + name = "ArmSMEOpInterfaces", + hdrs = [ + "include/mlir/Dialect/ArmSME/IR/ArmSMEOpInterfaces.h", + ], + includes = ["include"], + deps = [ + ":ArmSMEOpInterfacesIncGen", + ":IR", + ":Support", + "//llvm:Support", + ], +) + gentbl_cc_library( name = "ArmSMEIntrinsicOpsIncGen", tbl_outs = [ @@ -2137,9 +2151,11 @@ cc_library( ":ArmSMEEnums", ":ArmSMEIncGen", ":ArmSMEIntrinsicOpsIncGen", + ":ArmSMEOpInterfaces", ":ArmSMEOpInterfacesIncGen", ":ArmSMEOpsIncGen", ":BytecodeOpInterface", + ":FunctionInterfaces", ":IR", ":LLVMDialect", ":MemRefDialect", @@ -2156,6 +2172,7 @@ cc_library( hdrs = glob(["include/mlir/Dialect/ArmSME/Transforms/*.h"]), includes = ["include"], deps = [ + ":Analysis", ":ArithUtils", ":ArmSMEDialect", ":ArmSMETransformsPassIncGen", @@ -2163,6 +2180,7 @@ cc_library( ":DialectUtils", ":FuncDialect", ":FuncTransforms", + ":FunctionInterfaces", ":IR", ":LLVMCommonConversion", ":LLVMDialect", @@ -2200,6 +2218,7 @@ cc_library( ":ArmSMETransforms", ":ConversionPassIncGen", ":FuncDialect", + ":FunctionInterfaces", ":LLVMCommonConversion", ":LLVMDialect", ":MemRefDialect", diff --git a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel index 65b31dc97e2d..258cc88ebbf3 100644 --- a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel @@ -951,8 +951,10 @@ cc_library( "//mlir:ArmSMEToSCF", "//mlir:ArmSMETransforms", "//mlir:ArmSVETransforms", + "//mlir:FuncDialect", "//mlir:IR", "//mlir:Pass", + "//mlir:SCFToControlFlow", "//mlir:Transforms", "//mlir:VectorToArmSME", "//mlir:VectorToSCF", -- GitLab From 77b80bd8186b392ed9bc87cd526a64093dd03522 Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Tue, 14 May 2024 18:08:10 +0100 Subject: [PATCH 254/578] [mlir][flang] Improve handling of fortran module variables. (#91604) Currently, only those global variables which are at compile unit scope are added to the 'globals' list of the DICompileUnit. This does not work for languages which support modules (e.g. Fortran) where hierarchy can be variable -> module -> compile unit. To fix this, if a variable scope points to a module, we walk one level up and see if module is in the compile unit scope. This was initially part of #91582 which adds debug information for Fortran module variables. @kiranchandramohan pointed out that MLIR changes should go in separate PRs. --- mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 15 +++++++++++++-- mlir/test/Target/LLVMIR/llvmir-debug.mlir | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index 669b95a9c6a5..2e4b0feb1973 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -1030,10 +1030,21 @@ LogicalResult ModuleTranslation::convertGlobals() { llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable(); var->addDebugInfo(diGlobalExpr); + // There is no `globals` field in DICompileUnitAttr which can be directly + // assigned to DICompileUnit. We have to build the list by looking at the + // dbgExpr of all the GlobalOps. The scope of the variable is used to get + // the DICompileUnit in which to add it. But for the languages that + // support modules, the scope hierarchy can be + // variable -> module -> compile unit + // If a variable scope points to the module then we use the scope of the + // module to get the compile unit. + llvm::DIScope *scope = diGlobalVar->getScope(); + if (llvm::DIModule *mod = dyn_cast_if_present(scope)) + scope = mod->getScope(); + // Get the compile unit (scope) of the the global variable. if (llvm::DICompileUnit *compileUnit = - dyn_cast_if_present( - diGlobalVar->getScope())) { + dyn_cast_if_present(scope)) { // Update the compile unit with this incoming global variable expression // during the finalizing step later. allGVars[compileUnit].push_back(diGlobalExpr); diff --git a/mlir/test/Target/LLVMIR/llvmir-debug.mlir b/mlir/test/Target/LLVMIR/llvmir-debug.mlir index 1f0fc969364a..15d4b8ccd88b 100644 --- a/mlir/test/Target/LLVMIR/llvmir-debug.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-debug.mlir @@ -311,6 +311,25 @@ llvm.mlir.global external @global_with_expr_2() {addr_space = 0 : i32, dbg_expr // ----- +// CHECK: @module_global = external global i64, !dbg {{.*}} +// CHECK: !llvm.module.flags = !{{{.*}}} +// CHECK: !llvm.dbg.cu = !{{{.*}}} +// CHECK-DAG: ![[FILE:.*]] = !DIFile(filename: "test.f90", directory: "existence") +// CHECK-DAG: ![[TYPE:.*]] = !DIBasicType(name: "integer", size: 64, encoding: DW_ATE_signed) +// CHECK-DAG: ![[SCOPE:.*]] = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: ![[FILE]], producer: "MLIR", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: ![[GVALS:.*]]) +// CHECK-DAG: ![[SCOPE1:.*]] = !DIModule(scope: ![[SCOPE]], name: "module2", file: ![[FILE]], line: 120) +// CHECK-DAG: ![[GVAR:.*]] = distinct !DIGlobalVariable(name: "module_global", linkageName: "module_global", scope: ![[SCOPE1]], file: ![[FILE]], line: 121, type: ![[TYPE]], isLocal: false, isDefinition: true) +// CHECK-DAG: ![[GEXPR:.*]] = !DIGlobalVariableExpression(var: ![[GVAR]], expr: !DIExpression()) +// CHECK-DAG: ![[GVALS]] = !{![[GEXPR]]} + +#di_file = #llvm.di_file<"test.f90" in "existence"> +#di_compile_unit = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "MLIR", isOptimized = true, emissionKind = Full> +#di_basic_type = #llvm.di_basic_type +#di_module = #llvm.di_module +llvm.mlir.global external @module_global() {dbg_expr = #llvm.di_global_variable_expression, expr = <>>} : i64 + +// ----- + // Nameless and scopeless global constant. // CHECK-LABEL: @.str.1 = external constant [10 x i8] -- GitLab From b04c07bf271be097a5e5726730c538454fd30992 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Tue, 14 May 2024 10:11:20 -0700 Subject: [PATCH 255/578] [RISCV] Only allow up to e64 in vsetvli (#92010) These larger SEWs aren't in the ratified V spec. Thanks to dzaima and sorear on IRC for pointing this one out. Signed-off-by: Palmer Dabbelt --- .../llvm/TargetParser/RISCVTargetParser.h | 2 +- .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 2 +- llvm/test/MC/RISCV/rvv/invalid.s | 64 +++++++++++-------- 3 files changed, 40 insertions(+), 28 deletions(-) diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h index cdd19189f8dc..5b1494efe7bd 100644 --- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h +++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h @@ -61,7 +61,7 @@ enum { namespace RISCVVType { // Is this a SEW value that can be encoded into the VTYPE format. inline static bool isValidSEW(unsigned SEW) { - return isPowerOf2_32(SEW) && SEW >= 8 && SEW <= 1024; + return isPowerOf2_32(SEW) && SEW >= 8 && SEW <= 64; } // Is this a LMUL value that can be encoded into the VTYPE format. diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 7da1b7e360c7..d92998ced91e 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -2225,7 +2225,7 @@ bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) { return Error( ErrorLoc, "operand must be " - "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]"); + "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]"); } ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) { diff --git a/llvm/test/MC/RISCV/rvv/invalid.s b/llvm/test/MC/RISCV/rvv/invalid.s index 8c50f7ed048c..07e7b9db6606 100644 --- a/llvm/test/MC/RISCV/rvv/invalid.s +++ b/llvm/test/MC/RISCV/rvv/invalid.s @@ -2,83 +2,95 @@ # RUN: | FileCheck %s --check-prefix=CHECK-ERROR vsetivli a2, 32, e8,m1 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetivli a2, zero, e8,m1 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetivli a2, 5, (1 << 10) -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetivli a2, 5, 0x400 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetivli a2, 5, e31 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, (1 << 11) -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, 0x800 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e31 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e32,m3 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, m1,e32 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e32,m16 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] + +vsetvli a2, a0, e128,m8 +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] + +vsetvli a2, a0, e256,m8 +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] + +vsetvli a2, a0, e512,m8 +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] + +vsetvli a2, a0, e1024,m8 +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e2048,m8 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e1,m8 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8,m1,tx -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8,m1,ta,mx -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8,m1,ma -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8,m1,mu -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8x,m1,tu,mu -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8,m1z,tu,mu -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8,mf1,tu,mu -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8,m1,tu,mut -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8,m1,tut,mu -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8,m1 -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8,m1,ta -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vsetvli a2, a0, e8,1,ta,ma -# CHECK-ERROR: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] +# CHECK-ERROR: operand must be e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] vadd.vv v1, v3, v2, v4.t # CHECK-ERROR: operand must be v0.t -- GitLab From 6c8ebc053533c691099ab60c41261b3cb4ba2fa3 Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Tue, 14 May 2024 10:13:57 -0700 Subject: [PATCH 256/578] [NFC][CallPromotionUtils]Extract a helper function versionCallSiteWithCond from versionCallSite (#81181) * This is to be used by https://github.com/llvm/llvm-project/pull/81378 to implement a variant of versionCallSite that compares vtables. * The parent patch is https://github.com/llvm/llvm-project/pull/81051 --- .../Transforms/Utils/CallPromotionUtils.cpp | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp b/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp index 48c33d6c0c8e..9ca9aaf9ee9d 100644 --- a/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp +++ b/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp @@ -188,10 +188,9 @@ static void createRetBitCast(CallBase &CB, Type *RetTy, CastInst **RetBitCast) { /// Predicate and clone the given call site. /// /// This function creates an if-then-else structure at the location of the call -/// site. The "if" condition compares the call site's called value to the given -/// callee. The original call site is moved into the "else" block, and a clone -/// of the call site is placed in the "then" block. The cloned instruction is -/// returned. +/// site. The "if" condition is specified by `Cond`. The original call site is +/// moved into the "else" block, and a clone of the call site is placed in the +/// "then" block. The cloned instruction is returned. /// /// For example, the call instruction below: /// @@ -202,7 +201,7 @@ static void createRetBitCast(CallBase &CB, Type *RetTy, CastInst **RetBitCast) { /// Is replace by the following: /// /// orig_bb: -/// %cond = icmp eq i32 ()* %ptr, @func +/// %cond = Cond /// br i1 %cond, %then_bb, %else_bb /// /// then_bb: @@ -232,7 +231,7 @@ static void createRetBitCast(CallBase &CB, Type *RetTy, CastInst **RetBitCast) { /// Is replace by the following: /// /// orig_bb: -/// %cond = icmp eq i32 ()* %ptr, @func +/// %cond = Cond /// br i1 %cond, %then_bb, %else_bb /// /// then_bb: @@ -267,7 +266,7 @@ static void createRetBitCast(CallBase &CB, Type *RetTy, CastInst **RetBitCast) { /// Is replaced by the following: /// /// cond_bb: -/// %cond = icmp eq i32 ()* %ptr, @func +/// %cond = Cond /// br i1 %cond, %then_bb, %orig_bb /// /// then_bb: @@ -280,19 +279,13 @@ static void createRetBitCast(CallBase &CB, Type *RetTy, CastInst **RetBitCast) { /// ; The original call instruction stays in its original block. /// %t0 = musttail call i32 %ptr() /// ret %t0 -CallBase &llvm::versionCallSite(CallBase &CB, Value *Callee, - MDNode *BranchWeights) { +static CallBase &versionCallSiteWithCond(CallBase &CB, Value *Cond, + MDNode *BranchWeights) { IRBuilder<> Builder(&CB); CallBase *OrigInst = &CB; BasicBlock *OrigBlock = OrigInst->getParent(); - // Create the compare. The called value and callee must have the same type to - // be compared. - if (CB.getCalledOperand()->getType() != Callee->getType()) - Callee = Builder.CreateBitCast(Callee, CB.getCalledOperand()->getType()); - auto *Cond = Builder.CreateICmpEQ(CB.getCalledOperand(), Callee); - if (OrigInst->isMustTailCall()) { // Create an if-then structure. The original instruction stays in its block, // and a clone of the original instruction is placed in the "then" block. @@ -380,6 +373,22 @@ CallBase &llvm::versionCallSite(CallBase &CB, Value *Callee, return *NewInst; } +// Predicate and clone the given call site using condition `CB.callee == +// Callee`. See the comment `versionCallSiteWithCond` for the transformation. +CallBase &llvm::versionCallSite(CallBase &CB, Value *Callee, + MDNode *BranchWeights) { + + IRBuilder<> Builder(&CB); + + // Create the compare. The called value and callee must have the same type to + // be compared. + if (CB.getCalledOperand()->getType() != Callee->getType()) + Callee = Builder.CreateBitCast(Callee, CB.getCalledOperand()->getType()); + auto *Cond = Builder.CreateICmpEQ(CB.getCalledOperand(), Callee); + + return versionCallSiteWithCond(CB, Cond, BranchWeights); +} + bool llvm::isLegalToPromote(const CallBase &CB, Function *Callee, const char **FailureReason) { assert(!CB.getCalledFunction() && "Only indirect call sites can be promoted"); -- GitLab From 54435b5df32d80c68c94acf96a7565ffd3d86542 Mon Sep 17 00:00:00 2001 From: Piotr Zegar Date: Tue, 14 May 2024 19:17:47 +0200 Subject: [PATCH 257/578] [clang-tidy] Ignore implicit casts with errors in bugprone-implicit-widening-of-multiplication-result (#92025) When expression got errors (missing typedef) and clang-tidy is compiled with asserts enabled, then we crash in this check on assert because type with errors is visible as an dependent one. This is issue caused by invalid input. But as there is not point to crash in such case and generate additional confusion, such expressions with errors will be now ignored. Fixes #89515, #55293 --- .../ImplicitWideningOfMultiplicationResultCheck.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/ImplicitWideningOfMultiplicationResultCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ImplicitWideningOfMultiplicationResultCheck.cpp index 6f22f02f3018..f99beac668ce 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ImplicitWideningOfMultiplicationResultCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ImplicitWideningOfMultiplicationResultCheck.cpp @@ -9,20 +9,20 @@ #include "ImplicitWideningOfMultiplicationResultCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchersMacros.h" #include "clang/Lex/Lexer.h" #include using namespace clang::ast_matchers; -namespace clang { +namespace clang::tidy::bugprone { + namespace { AST_MATCHER(ImplicitCastExpr, isPartOfExplicitCast) { return Node.isPartOfExplicitCast(); } +AST_MATCHER(Expr, containsErrors) { return Node.containsErrors(); } } // namespace -} // namespace clang - -namespace clang::tidy::bugprone { static const Expr *getLHSOfMulBinOp(const Expr *E) { assert(E == E->IgnoreParens() && "Already skipped all parens!"); @@ -250,7 +250,8 @@ void ImplicitWideningOfMultiplicationResultCheck::handlePointerOffsetting( void ImplicitWideningOfMultiplicationResultCheck::registerMatchers( MatchFinder *Finder) { - Finder->addMatcher(implicitCastExpr(unless(anyOf(isInTemplateInstantiation(), + Finder->addMatcher(implicitCastExpr(unless(anyOf(containsErrors(), + isInTemplateInstantiation(), isPartOfExplicitCast())), hasCastKind(CK_IntegralCast)) .bind("x"), -- GitLab From 97e35e0098e863bff959f726f1492654a6cfe441 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 14 May 2024 13:22:01 -0400 Subject: [PATCH 258/578] Revert "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" (#92149) This reverts commit 8019cbbbbc94658d133583f7be6cd0023d30b0f3. --- clang/docs/ReleaseNotes.rst | 3 - clang/include/clang/AST/Type.h | 5 +- clang/lib/Sema/SemaExpr.cpp | 351 +++++++++--------- clang/test/AST/ast-dump-expr-json.cpp | 4 +- clang/test/AST/ast-dump-expr.cpp | 2 +- clang/test/AST/ast-dump-lambda.cpp | 2 +- .../expr/expr.unary/expr.unary.general/p1.cpp | 65 ---- clang/test/CXX/over/over.built/ast.cpp | 158 ++------ clang/test/CXX/over/over.built/p10.cpp | 2 +- clang/test/CXX/over/over.built/p11.cpp | 2 +- .../temp.res/temp.dep/temp.dep.type/p4.cpp | 25 +- clang/test/Frontend/noderef_templates.cpp | 4 +- clang/test/SemaCXX/cxx2b-deducing-this.cpp | 6 +- .../test/SemaTemplate/class-template-spec.cpp | 12 +- .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 6 +- 15 files changed, 245 insertions(+), 402 deletions(-) delete mode 100644 clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a2e44efe4134..49ab222bec40 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -55,9 +55,6 @@ C++ Specific Potentially Breaking Changes - Clang now rejects pointer to member from parenthesized expression in unevaluated context such as ``decltype(&(foo::bar))``. (#GH40906). -- 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. - ABI Changes in This Version --------------------------- - Fixed Microsoft name mangling of implicitly defined variables used for thread diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index da3834f19ca0..e6643469e0b3 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -8044,10 +8044,7 @@ inline bool Type::isUndeducedType() const { /// Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { - if (!CanonicalType->isDependentType()) - return isRecordType() || isEnumeralType(); - return !isArrayType() && !isFunctionType() && !isAnyPointerType() && - !isMemberPointerType(); + return isDependentType() || isRecordType() || isEnumeralType(); } /// Determines whether this type is written as a typedef-name. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 18fd5ba700ad..ec84798e4ce6 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -672,12 +672,12 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // We don't want to throw lvalue-to-rvalue casts on top of // expressions of certain types in C++. - if (getLangOpts().CPlusPlus) { - if (T == Context.OverloadTy || T->isRecordType() || - (T->isDependentType() && !T->isAnyPointerType() && - !T->isMemberPointerType())) - return E; - } + if (getLangOpts().CPlusPlus && + (E->getType() == Context.OverloadTy || + // FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied + // to pointer types even if the pointee type is dependent. + (T->isDependentType() && !T->isPointerType()) || T->isRecordType())) + return E; // The C standard is actually really unclear on this point, and // DR106 tells us what the result should be but not why. It's @@ -10827,7 +10827,7 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc, if (const AtomicType *ResAtomicType = ResType->getAs()) ResType = ResAtomicType->getValueType(); - assert(ResType->isAnyPointerType()); + assert(ResType->isAnyPointerType() && !ResType->isDependentType()); QualType PointeeTy = ResType->getPointeeType(); return S.RequireCompleteSizedType( Loc, PointeeTy, @@ -13957,6 +13957,9 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, ExprObjectKind &OK, SourceLocation OpLoc, bool IsInc, bool IsPrefix) { + if (Op->isTypeDependent()) + return S.Context.DependentTy; + QualType ResType = Op->getType(); // Atomic types can be used for increment / decrement where the non-atomic // versions can, so ignore the _Atomic() specifier for the purpose of @@ -14407,6 +14410,9 @@ static void RecordModifiableNonNullParam(Sema &S, const Expr *Exp) { static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, SourceLocation OpLoc, bool IsAfterAmp = false) { + if (Op->isTypeDependent()) + return S.Context.DependentTy; + ExprResult ConvResult = S.UsualUnaryConversions(Op); if (ConvResult.isInvalid()) return QualType(); @@ -15460,191 +15466,190 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 1); } - if (InputExpr->isTypeDependent() && - InputExpr->getType()->isSpecificBuiltinType(BuiltinType::Dependent)) { - resultType = Context.DependentTy; - } else { - switch (Opc) { - case UO_PreInc: - case UO_PreDec: - case UO_PostInc: - case UO_PostDec: - resultType = - CheckIncrementDecrementOperand(*this, Input.get(), VK, OK, OpLoc, - Opc == UO_PreInc || Opc == UO_PostInc, - Opc == UO_PreInc || Opc == UO_PreDec); - CanOverflow = isOverflowingIntegerType(Context, resultType); + switch (Opc) { + case UO_PreInc: + case UO_PreDec: + case UO_PostInc: + case UO_PostDec: + resultType = + CheckIncrementDecrementOperand(*this, Input.get(), VK, OK, OpLoc, + Opc == UO_PreInc || Opc == UO_PostInc, + Opc == UO_PreInc || Opc == UO_PreDec); + CanOverflow = isOverflowingIntegerType(Context, resultType); + break; + case UO_AddrOf: + resultType = CheckAddressOfOperand(Input, OpLoc); + CheckAddressOfNoDeref(InputExpr); + RecordModifiableNonNullParam(*this, InputExpr); + break; + case UO_Deref: { + Input = DefaultFunctionArrayLvalueConversion(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = + CheckIndirectionOperand(*this, Input.get(), VK, OpLoc, IsAfterAmp); + break; + } + case UO_Plus: + case UO_Minus: + CanOverflow = Opc == UO_Minus && + isOverflowingIntegerType(Context, Input.get()->getType()); + Input = UsualUnaryConversions(Input.get()); + if (Input.isInvalid()) + return ExprError(); + // Unary plus and minus require promoting an operand of half vector to a + // float vector and truncating the result back to a half vector. For now, we + // do this only when HalfArgsAndReturns is set (that is, when the target is + // arm or arm64). + ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get()); + + // If the operand is a half vector, promote it to a float vector. + if (ConvertHalfVec) + Input = convertVector(Input.get(), Context.FloatTy, *this); + resultType = Input.get()->getType(); + if (resultType->isDependentType()) break; - case UO_AddrOf: - resultType = CheckAddressOfOperand(Input, OpLoc); - CheckAddressOfNoDeref(InputExpr); - RecordModifiableNonNullParam(*this, InputExpr); + if (resultType->isArithmeticType()) // C99 6.5.3.3p1 break; - case UO_Deref: { - Input = DefaultFunctionArrayLvalueConversion(Input.get()); - if (Input.isInvalid()) - return ExprError(); - resultType = - CheckIndirectionOperand(*this, Input.get(), VK, OpLoc, IsAfterAmp); + else if (resultType->isVectorType() && + // The z vector extensions don't allow + or - with bool vectors. + (!Context.getLangOpts().ZVector || + resultType->castAs()->getVectorKind() != + VectorKind::AltiVecBool)) + break; + else if (resultType->isSveVLSBuiltinType()) // SVE vectors allow + and - + break; + else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 + Opc == UO_Plus && resultType->isPointerType()) break; + + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + + case UO_Not: // bitwise complement + Input = UsualUnaryConversions(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = Input.get()->getType(); + if (resultType->isDependentType()) + break; + // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. + if (resultType->isComplexType() || resultType->isComplexIntegerType()) + // C99 does not support '~' for complex conjugation. + Diag(OpLoc, diag::ext_integer_complement_complex) + << resultType << Input.get()->getSourceRange(); + else if (resultType->hasIntegerRepresentation()) + break; + else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate + // on vector float types. + QualType T = resultType->castAs()->getElementType(); + if (!T->isIntegerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); } - case UO_Plus: - case UO_Minus: - CanOverflow = Opc == UO_Minus && - isOverflowingIntegerType(Context, Input.get()->getType()); - Input = UsualUnaryConversions(Input.get()); - if (Input.isInvalid()) - return ExprError(); - // Unary plus and minus require promoting an operand of half vector to a - // float vector and truncating the result back to a half vector. For now, - // we do this only when HalfArgsAndReturns is set (that is, when the - // target is arm or arm64). - ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get()); - - // If the operand is a half vector, promote it to a float vector. - if (ConvertHalfVec) - Input = convertVector(Input.get(), Context.FloatTy, *this); - resultType = Input.get()->getType(); - if (resultType->isArithmeticType()) // C99 6.5.3.3p1 - break; - else if (resultType->isVectorType() && - // The z vector extensions don't allow + or - with bool vectors. - (!Context.getLangOpts().ZVector || - resultType->castAs()->getVectorKind() != - VectorKind::AltiVecBool)) - break; - else if (resultType->isSveVLSBuiltinType()) // SVE vectors allow + and - - break; - else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 - Opc == UO_Plus && resultType->isPointerType()) - break; + break; + case UO_LNot: // logical negation + // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). + Input = DefaultFunctionArrayLvalueConversion(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = Input.get()->getType(); + + // Though we still have to promote half FP to float... + if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) { + Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast) + .get(); + resultType = Context.FloatTy; + } + + // WebAsembly tables can't be used in unary expressions. + if (resultType->isPointerType() && + resultType->getPointeeType().isWebAssemblyReferenceType()) { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); + } - case UO_Not: // bitwise complement - Input = UsualUnaryConversions(Input.get()); - if (Input.isInvalid()) - return ExprError(); - resultType = Input.get()->getType(); - // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. - if (resultType->isComplexType() || resultType->isComplexIntegerType()) - // C99 does not support '~' for complex conjugation. - Diag(OpLoc, diag::ext_integer_complement_complex) - << resultType << Input.get()->getSourceRange(); - else if (resultType->hasIntegerRepresentation()) - break; - else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { - // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate - // on vector float types. + if (resultType->isDependentType()) + break; + if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) { + // C99 6.5.3.3p1: ok, fallthrough; + if (Context.getLangOpts().CPlusPlus) { + // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: + // operand contextually converted to bool. + Input = ImpCastExprToType(Input.get(), Context.BoolTy, + ScalarTypeToBooleanCastKind(resultType)); + } else if (Context.getLangOpts().OpenCL && + Context.getLangOpts().OpenCLVersion < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on scalar float types. + if (!resultType->isIntegerType() && !resultType->isPointerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + } else if (resultType->isExtVectorType()) { + if (Context.getLangOpts().OpenCL && + Context.getLangOpts().getOpenCLCompatibleVersion() < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on vector float types. QualType T = resultType->castAs()->getElementType(); if (!T->isIntegerType()) return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); - } else { - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); } + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); break; - - case UO_LNot: // logical negation - // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). - Input = DefaultFunctionArrayLvalueConversion(Input.get()); - if (Input.isInvalid()) - return ExprError(); - resultType = Input.get()->getType(); - - // Though we still have to promote half FP to float... - if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) { - Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast) - .get(); - resultType = Context.FloatTy; - } - - // WebAsembly tables can't be used in unary expressions. - if (resultType->isPointerType() && - resultType->getPointeeType().isWebAssemblyReferenceType()) { + } else if (Context.getLangOpts().CPlusPlus && resultType->isVectorType()) { + const VectorType *VTy = resultType->castAs(); + if (VTy->getVectorKind() != VectorKind::Generic) return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); - } - if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) { - // C99 6.5.3.3p1: ok, fallthrough; - if (Context.getLangOpts().CPlusPlus) { - // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: - // operand contextually converted to bool. - Input = ImpCastExprToType(Input.get(), Context.BoolTy, - ScalarTypeToBooleanCastKind(resultType)); - } else if (Context.getLangOpts().OpenCL && - Context.getLangOpts().OpenCLVersion < 120) { - // OpenCL v1.1 6.3.h: The logical operator not (!) does not - // operate on scalar float types. - if (!resultType->isIntegerType() && !resultType->isPointerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - } else if (resultType->isExtVectorType()) { - if (Context.getLangOpts().OpenCL && - Context.getLangOpts().getOpenCLCompatibleVersion() < 120) { - // OpenCL v1.1 6.3.h: The logical operator not (!) does not - // operate on vector float types. - QualType T = resultType->castAs()->getElementType(); - if (!T->isIntegerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - // Vector logical not returns the signed variant of the operand type. - resultType = GetSignedVectorType(resultType); - break; - } else if (Context.getLangOpts().CPlusPlus && - resultType->isVectorType()) { - const VectorType *VTy = resultType->castAs(); - if (VTy->getVectorKind() != VectorKind::Generic) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - - // Vector logical not returns the signed variant of the operand type. - resultType = GetSignedVectorType(resultType); - break; - } else { - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - - // LNot always has type int. C99 6.5.3.3p5. - // In C++, it's bool. C++ 5.3.1p8 - resultType = Context.getLogicalOperationType(); + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); break; - case UO_Real: - case UO_Imag: - resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); - // _Real maps ordinary l-values into ordinary l-values. _Imag maps - // ordinary complex l-values to ordinary l-values and all other values to - // r-values. - if (Input.isInvalid()) - return ExprError(); - if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { - if (Input.get()->isGLValue() && - Input.get()->getObjectKind() == OK_Ordinary) - VK = Input.get()->getValueKind(); - } else if (!getLangOpts().CPlusPlus) { - // In C, a volatile scalar is read by __imag. In C++, it is not. - Input = DefaultLvalueConversion(Input.get()); - } - break; - case UO_Extension: - resultType = Input.get()->getType(); - VK = Input.get()->getValueKind(); - OK = Input.get()->getObjectKind(); - break; - case UO_Coawait: - // It's unnecessary to represent the pass-through operator co_await in the - // AST; just return the input expression instead. - assert(!Input.get()->getType()->isDependentType() && - "the co_await expression must be non-dependant before " - "building operator co_await"); - return Input; + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + + // LNot always has type int. C99 6.5.3.3p5. + // In C++, it's bool. C++ 5.3.1p8 + resultType = Context.getLogicalOperationType(); + break; + case UO_Real: + case UO_Imag: + resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); + // _Real maps ordinary l-values into ordinary l-values. _Imag maps ordinary + // complex l-values to ordinary l-values and all other values to r-values. + if (Input.isInvalid()) + return ExprError(); + if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { + if (Input.get()->isGLValue() && + Input.get()->getObjectKind() == OK_Ordinary) + VK = Input.get()->getValueKind(); + } else if (!getLangOpts().CPlusPlus) { + // In C, a volatile scalar is read by __imag. In C++, it is not. + Input = DefaultLvalueConversion(Input.get()); } + break; + case UO_Extension: + resultType = Input.get()->getType(); + VK = Input.get()->getValueKind(); + OK = Input.get()->getObjectKind(); + break; + case UO_Coawait: + // It's unnecessary to represent the pass-through operator co_await in the + // AST; just return the input expression instead. + assert(!Input.get()->getType()->isDependentType() && + "the co_await expression must be non-dependant before " + "building operator co_await"); + return Input; } if (resultType.isNull() || Input.isInvalid()) return ExprError(); diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index 4b7365e554cb..0fb07b0b434c 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -4261,9 +4261,9 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "V" +// CHECK-NEXT: "qualType": "" // CHECK-NEXT: }, -// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "isPostfix": false, // CHECK-NEXT: "opcode": "*", // CHECK-NEXT: "canOverflow": false, diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 4df5ba4276ab..69e65e22d61d 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -282,7 +282,7 @@ void PrimaryExpressions(Ts... a) { // CHECK-NEXT: CompoundStmt // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:8 implicit 'V' // CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} 'NULL TYPE' - // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} 'V' lvalue prefix '*' cannot overflow + // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} '' prefix '*' cannot overflow // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} 'V *' this } }; diff --git a/clang/test/AST/ast-dump-lambda.cpp b/clang/test/AST/ast-dump-lambda.cpp index a4d3fe4fbda5..ef8789cd97d3 100644 --- a/clang/test/AST/ast-dump-lambda.cpp +++ b/clang/test/AST/ast-dump-lambda.cpp @@ -81,7 +81,7 @@ template void test(Ts... a) { // CHECK-NEXT: | | | `-CompoundStmt {{.*}} // CHECK-NEXT: | | `-FieldDecl {{.*}} col:8{{( imported)?}} implicit 'V' // CHECK-NEXT: | |-ParenListExpr {{.*}} 'NULL TYPE' -// CHECK-NEXT: | | `-UnaryOperator {{.*}} 'V' lvalue prefix '*' cannot overflow +// CHECK-NEXT: | | `-UnaryOperator {{.*}} '' prefix '*' cannot overflow // CHECK-NEXT: | | `-CXXThisExpr {{.*}} 'V *' this // CHECK-NEXT: | `-CompoundStmt {{.*}} // CHECK-NEXT: |-DeclStmt {{.*}} diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp deleted file mode 100644 index 6744ce1cad17..000000000000 --- a/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// RUN: %clang_cc1 -Wno-unused -fsyntax-only %s -verify - -struct A { - void operator*(); - void operator+(); - void operator-(); - void operator!(); - void operator~(); - void operator&(); - void operator++(); - void operator--(); -}; - -struct B { }; - -template -void dependent(T t, T* pt, T U::* mpt, T(&ft)(), T(&at)[4]) { - *t; - +t; - -t; - !t; - ~t; - &t; - ++t; - --t; - - *pt; - +pt; - -pt; // expected-error {{invalid argument type 'T *' to unary expression}} - !pt; - ~pt; // expected-error {{invalid argument type 'T *' to unary expression}} - &pt; - ++pt; - --pt; - - *mpt; // expected-error {{indirection requires pointer operand ('T U::*' invalid)}} - +mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} - -mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} - !mpt; - ~mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} - &mpt; - ++mpt; // expected-error {{cannot increment value of type 'T U::*'}} - --mpt; // expected-error {{cannot decrement value of type 'T U::*'}} - - *ft; - +ft; - -ft; // expected-error {{invalid argument type 'T (*)()' to unary expression}} - !ft; - ~ft; // expected-error {{invalid argument type 'T (*)()' to unary expression}} - &ft; - ++ft; // expected-error {{cannot increment value of type 'T ()'}} - --ft; // expected-error {{cannot decrement value of type 'T ()'}} - - *at; - +at; - -at; // expected-error {{invalid argument type 'T *' to unary expression}} - !at; - ~at; // expected-error {{invalid argument type 'T *' to unary expression}} - &at; - ++at; // expected-error {{cannot increment value of type 'T[4]'}} - --at; // expected-error {{cannot decrement value of type 'T[4]'}} -} - -// Make sure we only emit diagnostics once. -template void dependent(A t, A* pt, A B::* mpt, A(&ft)(), A(&at)[4]); diff --git a/clang/test/CXX/over/over.built/ast.cpp b/clang/test/CXX/over/over.built/ast.cpp index 78f86edb1e96..56a63431269f 100644 --- a/clang/test/CXX/over/over.built/ast.cpp +++ b/clang/test/CXX/over/over.built/ast.cpp @@ -1,139 +1,41 @@ -// RUN: %clang_cc1 -std=c++17 -Wno-unused -ast-dump %s -ast-dump-filter Test | FileCheck %s +// RUN: %clang_cc1 -std=c++17 -ast-dump %s -ast-dump-filter Test | FileCheck %s -namespace Test { - template - void Unary(T t, T* pt, T U::* mpt, T(&ft)(), T(&at)[4]) { - // CHECK: UnaryOperator {{.*}} '' lvalue prefix '*' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' - *t; +struct A{}; - // CHECK: UnaryOperator {{.*}} '' prefix '+' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' - +t; +template +auto Test(T* pt, U* pu) { + // CHECK: UnaryOperator {{.*}} '' lvalue prefix '*' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + (void)*pt; - // CHECK: UnaryOperator {{.*}} '' prefix '-' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' - -t; + // CHECK: UnaryOperator {{.*}} '' lvalue prefix '++' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + (void)(++pt); - // CHECK: UnaryOperator {{.*}} '' prefix '!' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' - !t; + // CHECK: UnaryOperator {{.*}} '' prefix '+' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + (void)(+pt); - // CHECK: UnaryOperator {{.*}} '' prefix '~' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' - ~t; + // CHECK: BinaryOperator {{.*}} '' '+' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3 + (void)(pt + 3); - // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' - &t; + // CHECK: BinaryOperator {{.*}} '' '-' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + (void)(pt - pt); - // CHECK: UnaryOperator {{.*}} '' lvalue prefix '++' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' - ++t; + // CHECK: BinaryOperator {{.*}} '' '-' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' + (void)(pt - pu); - // CHECK: UnaryOperator {{.*}} '' lvalue prefix '--' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' - --t; + // CHECK: BinaryOperator {{.*}} '' '==' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' + (void)(pt == pu); - // CHECK: UnaryOperator {{.*}} 'T' lvalue prefix '*' cannot overflow - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - *pt; +} - // CHECK: UnaryOperator {{.*}} 'T *' prefix '+' cannot overflow - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - +pt; - // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - !pt; - - // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - &pt; - - // CHECK: UnaryOperator {{.*}} 'T *' lvalue prefix '++' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - ++pt; - - // CHECK: UnaryOperator {{.*}} 'T *' lvalue prefix '--' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - --pt; - - // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T U::*' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T U::*' lvalue ParmVar {{.*}} 'mpt' 'T U::*' - !mpt; - - // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T U::*' lvalue ParmVar {{.*}} 'mpt' 'T U::*' - &mpt; - - // CHECK: UnaryOperator {{.*}} 'T ()' lvalue prefix '*' cannot overflow - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' - *ft; - - // CHECK: UnaryOperator {{.*}} 'T (*)()' prefix '+' cannot overflow - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' - +ft; - - // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' - !ft; - - // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' - &ft; - - // CHECK: UnaryOperator {{.*}} 'T' lvalue prefix '*' cannot overflow - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' - *at; - - // CHECK: UnaryOperator {{.*}} 'T *' prefix '+' cannot overflow - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' - +at; - - // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' - !at; - - // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow - // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' - &at; - } - - template - void Binary(T* pt, U* pu) { - // CHECK: BinaryOperator {{.*}} '' '+' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3 - pt + 3; - - // CHECK: BinaryOperator {{.*}} '' '-' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - pt - pt; - - // CHECK: BinaryOperator {{.*}} '' '-' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' - pt - pu; - - // CHECK: BinaryOperator {{.*}} '' '==' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' - pt == pu; - } -} // namespace Test diff --git a/clang/test/CXX/over/over.built/p10.cpp b/clang/test/CXX/over/over.built/p10.cpp index 8ff2396d0b6f..678056da5820 100644 --- a/clang/test/CXX/over/over.built/p10.cpp +++ b/clang/test/CXX/over/over.built/p10.cpp @@ -15,6 +15,6 @@ void f(int i, float f, bool b, char c, int* pi, A* pa, T* pt) { (void)-pi; // expected-error {{invalid argument type}} (void)-pa; // expected-error {{invalid argument type}} - (void)-pt; // expected-error {{invalid argument type}} + (void)-pt; // FIXME: we should be able to give an error here. } diff --git a/clang/test/CXX/over/over.built/p11.cpp b/clang/test/CXX/over/over.built/p11.cpp index f7a741db726d..7ebf16b95439 100644 --- a/clang/test/CXX/over/over.built/p11.cpp +++ b/clang/test/CXX/over/over.built/p11.cpp @@ -7,6 +7,6 @@ void f(int i, float f, bool b, char c, int* pi, T* pt) { (void)~b; (void)~c; (void)~pi; // expected-error {{invalid argument type}} - (void)~pt; // expected-error {{invalid argument type}} + (void)~pt; // FIXME: we should be able to give an error here. } diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp index 982e5372f5b0..3ca7c6c7eb8e 100644 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp @@ -357,14 +357,17 @@ namespace N0 { a->A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} a->B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - (*this).x4; // expected-error{{no member named 'x4' in 'B'}} - (*this).B::x4; // expected-error{{no member named 'x4' in 'B'}} - (*this).A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} - (*this).B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} - (*this).f4(); // expected-error{{no member named 'f4' in 'B'}} - (*this).B::f4(); // expected-error{{no member named 'f4' in 'B'}} - (*this).A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - (*this).B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} + // FIXME: An overloaded unary 'operator*' is built for these + // even though the operand is a pointer (to a dependent type). + // Type::isOverloadableType should return false for such cases. + (*this).x4; + (*this).B::x4; + (*this).A::x4; + (*this).B::A::x4; + (*this).f4(); + (*this).B::f4(); + (*this).A::f4(); + (*this).B::A::f4(); b.x4; // expected-error{{no member named 'x4' in 'B'}} b.B::x4; // expected-error{{no member named 'x4' in 'B'}} @@ -396,13 +399,15 @@ namespace N1 { f<0>(); this->f<0>(); a->f<0>(); - (*this).f<0>(); + // FIXME: This should not require 'template'! + (*this).f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} b.f<0>(); x.f<0>(); this->x.f<0>(); a->x.f<0>(); - (*this).x.f<0>(); + // FIXME: This should not require 'template'! + (*this).x.f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} b.x.f<0>(); // FIXME: None of these should require 'template'! diff --git a/clang/test/Frontend/noderef_templates.cpp b/clang/test/Frontend/noderef_templates.cpp index 9e54cd5d7889..5fde6efd87c7 100644 --- a/clang/test/Frontend/noderef_templates.cpp +++ b/clang/test/Frontend/noderef_templates.cpp @@ -3,8 +3,8 @@ #define NODEREF __attribute__((noderef)) template -int func(T NODEREF *a) { // expected-note 3 {{a declared here}} - return *a + 1; // expected-warning 3 {{dereferencing a; was declared with a 'noderef' type}} +int func(T NODEREF *a) { // expected-note 2 {{a declared here}} + return *a + 1; // expected-warning 2 {{dereferencing a; was declared with a 'noderef' type}} } void func() { diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp b/clang/test/SemaCXX/cxx2b-deducing-this.cpp index aa64530bd5be..5f29a955e053 100644 --- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp +++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp @@ -19,7 +19,7 @@ struct S { // new and delete are implicitly static void *operator new(this unsigned long); // expected-error{{an explicit object parameter cannot appear in a static function}} void operator delete(this void*); // expected-error{{an explicit object parameter cannot appear in a static function}} - + void g(this auto) const; // expected-error{{explicit object member function cannot have 'const' qualifier}} void h(this auto) &; // expected-error{{explicit object member function cannot have '&' qualifier}} void i(this auto) &&; // expected-error{{explicit object member function cannot have '&&' qualifier}} @@ -198,7 +198,9 @@ void func(int i) { void TestMutationInLambda() { [i = 0](this auto &&){ i++; }(); [i = 0](this auto){ i++; }(); - [i = 0](this const auto&){ i++; }(); // expected-error {{cannot assign to a variable captured by copy in a non-mutable lambda}} + [i = 0](this const auto&){ i++; }(); + // expected-error@-1 {{cannot assign to a variable captured by copy in a non-mutable lambda}} + // expected-note@-2 {{in instantiation of}} int x; const auto l1 = [x](this auto&) { x = 42; }; // expected-error {{cannot assign to a variable captured by copy in a non-mutable lambda}} diff --git a/clang/test/SemaTemplate/class-template-spec.cpp b/clang/test/SemaTemplate/class-template-spec.cpp index faa54c367538..56b8207bd9a4 100644 --- a/clang/test/SemaTemplate/class-template-spec.cpp +++ b/clang/test/SemaTemplate/class-template-spec.cpp @@ -18,7 +18,7 @@ int test_specs(A *a1, A *a2) { return a1->x + a2->y; } -int test_incomplete_specs(A *a1, +int test_incomplete_specs(A *a1, A *a2) { (void)a1->x; // expected-error{{member access into incomplete type}} @@ -39,7 +39,7 @@ template <> struct X { int foo(); }; // #1 template <> struct X { int bar(); }; // #2 typedef int int_type; -void testme(X *x1, X *x2) { +void testme(X *x1, X *x2) { (void)x1->foo(); // okay: refers to #1 (void)x2->bar(); // okay: refers to #2 } @@ -53,7 +53,7 @@ struct A { A::A() { } // Make sure we can see specializations defined before the primary template. -namespace N{ +namespace N{ template struct A0; } @@ -97,7 +97,7 @@ namespace M { template<> struct ::A; // expected-error{{must occur at global scope}} } -template<> struct N::B { +template<> struct N::B { int testf(int x) { return f(x); } }; @@ -138,9 +138,9 @@ namespace PR18009 { template struct C { template struct S; - template struct S {}; // ok + template struct S {}; // expected-error {{depends on a template parameter of the partial specialization}} }; - C c; + C c; // expected-note {{in instantiation of}} template struct outer { template struct inner {}; diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index f26140675fd4..c08deb903f12 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1572,9 +1572,9 @@ TEST_P(ASTMatchersTest, IsArrow_MatchesMemberVariablesViaArrow) { EXPECT_TRUE( matches("template class Y { void x() { this->m; } int m; };", memberExpr(isArrow()))); - EXPECT_TRUE(notMatches( - "template class Y { void x() { (*this).m; } int m; };", - memberExpr(isArrow()))); + EXPECT_TRUE( + notMatches("template class Y { void x() { (*this).m; } };", + cxxDependentScopeMemberExpr(isArrow()))); } TEST_P(ASTMatchersTest, IsArrow_MatchesStaticMemberVariablesViaArrow) { -- GitLab From 86f655cb4e2f4134d48219a2959a10c90e3396cb Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 14 May 2024 18:27:37 +0100 Subject: [PATCH 259/578] [LAA] Add tests showing unnecessary RT check due to applying loop guards Test courtesy to @bjope showing a regression due to ecae3ed958481cba7d60868cf3504292f7f4fdf5. --- .../is-safe-dep-distance-with-loop-guards.ll | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 llvm/test/Analysis/LoopAccessAnalysis/is-safe-dep-distance-with-loop-guards.ll diff --git a/llvm/test/Analysis/LoopAccessAnalysis/is-safe-dep-distance-with-loop-guards.ll b/llvm/test/Analysis/LoopAccessAnalysis/is-safe-dep-distance-with-loop-guards.ll new file mode 100644 index 000000000000..bfa735df064d --- /dev/null +++ b/llvm/test/Analysis/LoopAccessAnalysis/is-safe-dep-distance-with-loop-guards.ll @@ -0,0 +1,140 @@ +; 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 = "S16-p:16:16-i1:16-i8:8-i32:16-i64:16-i128:16" + +define void @safe_deps_1_due_to_dependence_distance(i16 %n, ptr %p) { +; CHECK-LABEL: 'safe_deps_1_due_to_dependence_distance' +; CHECK-NEXT: loop: +; CHECK-NEXT: Memory dependences are safe with run-time checks +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Check 0: +; CHECK-NEXT: Comparing group ([[GRP1:0x[0-9a-f]+]]): +; CHECK-NEXT: %gep.iv = getelementptr inbounds i32, ptr %p, i16 %iv +; CHECK-NEXT: Against group ([[GRP2:0x[0-9a-f]+]]): +; CHECK-NEXT: %gep.off.iv = getelementptr i32, ptr %gep.off, i16 %iv +; CHECK-NEXT: Grouped accesses: +; CHECK-NEXT: Group [[GRP1]]: +; CHECK-NEXT: (Low: %p High: ((4 * %n) + %p)) +; CHECK-NEXT: Member: {%p,+,4}<%loop> +; CHECK-NEXT: Group [[GRP2]]: +; CHECK-NEXT: (Low: ((4 * %n) + %p) High: ((8 * %n) + %p)) +; CHECK-NEXT: Member: {((4 * %n) + %p),+,4}<%loop> +; 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: + %cmp42 = icmp sgt i16 %n, 0 + br i1 %cmp42, label %ph, label %exit + +ph: + %gep.off = getelementptr i32, ptr %p, i16 %n + br label %loop + +loop: + %iv = phi i16 [ 0, %ph ], [ %iv.next, %loop ] + %gep.iv = getelementptr inbounds i32, ptr %p, i16 %iv + store i32 0, ptr %gep.iv, align 1 + %gep.off.iv = getelementptr i32, ptr %gep.off, i16 %iv + store i32 1, ptr %gep.off.iv, align 1 + %iv.next = add i16 %iv, 1 + %exitcond.not = icmp eq i16 %iv.next, %n + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @safe_deps_2_due_to_dependence_distance(i16 %n, ptr %p3, i16 noundef %q, ptr %p1, ptr %p2) { +; CHECK-LABEL: 'safe_deps_2_due_to_dependence_distance' +; CHECK-NEXT: loop: +; CHECK-NEXT: Memory dependences are safe with run-time checks +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Check 0: +; CHECK-NEXT: Comparing group ([[GRP3:0x[0-9a-f]+]]): +; CHECK-NEXT: %arrayidx22 = getelementptr inbounds [2 x i32], ptr %alloca, i16 %iv +; CHECK-NEXT: Against group ([[GRP4:0x[0-9a-f]+]]): +; CHECK-NEXT: %arrayidx33 = getelementptr inbounds i8, ptr %arrayidx22, i16 4 +; CHECK-NEXT: Check 1: +; CHECK-NEXT: Comparing group ([[GRP3]]): +; CHECK-NEXT: %arrayidx22 = getelementptr inbounds [2 x i32], ptr %alloca, i16 %iv +; CHECK-NEXT: Against group ([[GRP5:0x[0-9a-f]+]]): +; CHECK-NEXT: %arrayidx42 = getelementptr inbounds [2 x i32], ptr %arrayidx40, i16 %iv +; CHECK-NEXT: Check 2: +; CHECK-NEXT: Comparing group ([[GRP3]]): +; CHECK-NEXT: %arrayidx22 = getelementptr inbounds [2 x i32], ptr %alloca, i16 %iv +; CHECK-NEXT: Against group ([[GRP6:0x[0-9a-f]+]]): +; CHECK-NEXT: %arrayidx53 = getelementptr inbounds i8, ptr %arrayidx42, i16 4 +; CHECK-NEXT: Check 3: +; CHECK-NEXT: Comparing group ([[GRP4]]): +; CHECK-NEXT: %arrayidx33 = getelementptr inbounds i8, ptr %arrayidx22, i16 4 +; CHECK-NEXT: Against group ([[GRP5]]): +; CHECK-NEXT: %arrayidx42 = getelementptr inbounds [2 x i32], ptr %arrayidx40, i16 %iv +; CHECK-NEXT: Check 4: +; CHECK-NEXT: Comparing group ([[GRP4]]): +; CHECK-NEXT: %arrayidx33 = getelementptr inbounds i8, ptr %arrayidx22, i16 4 +; CHECK-NEXT: Against group ([[GRP6]]): +; CHECK-NEXT: %arrayidx53 = getelementptr inbounds i8, ptr %arrayidx42, i16 4 +; CHECK-NEXT: Check 5: +; CHECK-NEXT: Comparing group ([[GRP5]]): +; CHECK-NEXT: %arrayidx42 = getelementptr inbounds [2 x i32], ptr %arrayidx40, i16 %iv +; CHECK-NEXT: Against group ([[GRP6]]): +; CHECK-NEXT: %arrayidx53 = getelementptr inbounds i8, ptr %arrayidx42, i16 4 +; CHECK-NEXT: Grouped accesses: +; CHECK-NEXT: Group [[GRP3]]: +; CHECK-NEXT: (Low: %alloca High: (-4 + (8 * %n) + %alloca)) +; CHECK-NEXT: Member: {%alloca,+,8}<%loop> +; CHECK-NEXT: Group [[GRP4]]: +; CHECK-NEXT: (Low: (4 + %alloca) High: ((8 * %n) + %alloca)) +; CHECK-NEXT: Member: {(4 + %alloca),+,8}<%loop> +; CHECK-NEXT: Group [[GRP5]]: +; CHECK-NEXT: (Low: ((8 * %n) + %alloca) High: (-4 + (16 * %n) + %alloca)) +; CHECK-NEXT: Member: {((8 * %n) + %alloca),+,8}<%loop> +; CHECK-NEXT: Group [[GRP6]]: +; CHECK-NEXT: (Low: (4 + (8 * %n) + %alloca) High: ((16 * %n) + %alloca)) +; CHECK-NEXT: Member: {(4 + (8 * %n) + %alloca),+,8}<%loop> +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-NEXT: {((8 * %n) + %alloca),+,8}<%loop> Added Flags: +; CHECK-NEXT: {(4 + (8 * %n) + %alloca),+,8}<%loop> Added Flags: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; +entry: + %0 = shl i16 %n, 1 + %alloca = alloca [2 x i32], i16 %0 + %arrayidx1 = getelementptr inbounds i32, ptr %p1, i16 %q + %arrayidx2 = getelementptr inbounds i8, ptr %p3, i16 2 + %arrayidx4 = getelementptr inbounds i32, ptr %p2, i16 %q + %cmp42 = icmp sgt i16 %n, 0 + br i1 %cmp42, label %ph, label %exit + +ph: + %arrayidx40 = getelementptr inbounds [2 x i32], ptr %alloca, i16 %n + br label %loop + +loop: + %iv = phi i16 [ 0, %ph ], [ %iv.next, %loop ] + %arrayidx6 = getelementptr inbounds i32, ptr %arrayidx1, i16 %iv + %arrayidx11 = getelementptr inbounds i32, ptr %arrayidx4, i16 %iv + %arrayidx22 = getelementptr inbounds [2 x i32], ptr %alloca, i16 %iv + store i32 10, ptr %arrayidx22 + %arrayidx33 = getelementptr inbounds i8, ptr %arrayidx22, i16 4 + store i32 16, ptr %arrayidx33 + %arrayidx42 = getelementptr inbounds [2 x i32], ptr %arrayidx40, i16 %iv + store i32 19, ptr %arrayidx42 + %arrayidx53 = getelementptr inbounds i8, ptr %arrayidx42, i16 4 + store i32 23, ptr %arrayidx53 + %iv.next = add nuw nsw i16 %iv, 1 + %exitcond.not = icmp eq i16 %iv.next, %n + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} -- GitLab From 39d123f58a0e3c5f1a928940244b8dfd827fd4e5 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Tue, 14 May 2024 10:39:05 -0700 Subject: [PATCH 260/578] [nfc] const-ify `IntOrString::equalsLower` (#92152) --- llvm/tools/llvm-rc/ResourceScriptStmt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.h b/llvm/tools/llvm-rc/ResourceScriptStmt.h index 05865e582859..0d8ec3e5b787 100644 --- a/llvm/tools/llvm-rc/ResourceScriptStmt.h +++ b/llvm/tools/llvm-rc/ResourceScriptStmt.h @@ -145,7 +145,7 @@ public: IntOrString(const RCToken &Token) : Data(Token), IsInt(Token.kind() == RCToken::Kind::Int) {} - bool equalsLower(const char *Str) { + bool equalsLower(const char *Str) const { return !IsInt && Data.String.equals_insensitive(Str); } -- GitLab From de14b749fee41d4ded711e771e43043ae3100cb3 Mon Sep 17 00:00:00 2001 From: Alex Bradbury Date: Tue, 14 May 2024 13:44:25 +0100 Subject: [PATCH 261/578] [RISCV][test] Precommit tests for byte store of -1 Although we can't reduce the number of instructions, if we selected `li rd, -1` instead then this could be encoded in a 16-bit instruction. --- llvm/test/CodeGen/RISCV/imm.ll | 74 +++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/llvm/test/CodeGen/RISCV/imm.ll b/llvm/test/CodeGen/RISCV/imm.ll index c5c1657b526a..344ed0d2b083 100644 --- a/llvm/test/CodeGen/RISCV/imm.ll +++ b/llvm/test/CodeGen/RISCV/imm.ll @@ -1558,6 +1558,60 @@ define i64 @imm_2reg_1() nounwind { ret i64 -1152921504301427080 ; 0xF000_0000_1234_5678 } +; TODO: Selecting -1 would be better in this case as it can be loaded with a +; 16 bit instruction when the compressed extension is enabled. +define void @imm_store_i8_neg1(ptr %p) nounwind { +; RV32I-LABEL: imm_store_i8_neg1: +; RV32I: # %bb.0: +; RV32I-NEXT: li a1, 255 +; RV32I-NEXT: sb a1, 0(a0) +; RV32I-NEXT: ret +; +; RV64I-LABEL: imm_store_i8_neg1: +; RV64I: # %bb.0: +; RV64I-NEXT: li a1, 255 +; RV64I-NEXT: sb a1, 0(a0) +; RV64I-NEXT: ret +; +; RV64IZBA-LABEL: imm_store_i8_neg1: +; RV64IZBA: # %bb.0: +; RV64IZBA-NEXT: li a1, 255 +; RV64IZBA-NEXT: sb a1, 0(a0) +; RV64IZBA-NEXT: ret +; +; RV64IZBB-LABEL: imm_store_i8_neg1: +; RV64IZBB: # %bb.0: +; RV64IZBB-NEXT: li a1, 255 +; RV64IZBB-NEXT: sb a1, 0(a0) +; RV64IZBB-NEXT: ret +; +; RV64IZBS-LABEL: imm_store_i8_neg1: +; RV64IZBS: # %bb.0: +; RV64IZBS-NEXT: li a1, 255 +; RV64IZBS-NEXT: sb a1, 0(a0) +; RV64IZBS-NEXT: ret +; +; RV64IXTHEADBB-LABEL: imm_store_i8_neg1: +; RV64IXTHEADBB: # %bb.0: +; RV64IXTHEADBB-NEXT: li a1, 255 +; RV64IXTHEADBB-NEXT: sb a1, 0(a0) +; RV64IXTHEADBB-NEXT: ret +; +; RV32-REMAT-LABEL: imm_store_i8_neg1: +; RV32-REMAT: # %bb.0: +; RV32-REMAT-NEXT: li a1, 255 +; RV32-REMAT-NEXT: sb a1, 0(a0) +; RV32-REMAT-NEXT: ret +; +; RV64-REMAT-LABEL: imm_store_i8_neg1: +; RV64-REMAT: # %bb.0: +; RV64-REMAT-NEXT: li a1, 255 +; RV64-REMAT-NEXT: sb a1, 0(a0) +; RV64-REMAT-NEXT: ret + store i8 -1, ptr %p + ret void +} + define void @imm_store_i16_neg1(ptr %p) nounwind { ; RV32I-LABEL: imm_store_i16_neg1: ; RV32I: # %bb.0: @@ -2121,8 +2175,8 @@ define i64 @imm_70370820078523() { ; ; RV64I-POOL-LABEL: imm_70370820078523: ; RV64I-POOL: # %bb.0: -; RV64I-POOL-NEXT: lui a0, %hi(.LCPI37_0) -; RV64I-POOL-NEXT: ld a0, %lo(.LCPI37_0)(a0) +; RV64I-POOL-NEXT: lui a0, %hi(.LCPI38_0) +; RV64I-POOL-NEXT: ld a0, %lo(.LCPI38_0)(a0) ; RV64I-POOL-NEXT: ret ; ; RV64IZBA-LABEL: imm_70370820078523: @@ -2266,8 +2320,8 @@ define i64 @imm_neg_9223301666034697285() { ; ; RV64I-POOL-LABEL: imm_neg_9223301666034697285: ; RV64I-POOL: # %bb.0: -; RV64I-POOL-NEXT: lui a0, %hi(.LCPI39_0) -; RV64I-POOL-NEXT: ld a0, %lo(.LCPI39_0)(a0) +; RV64I-POOL-NEXT: lui a0, %hi(.LCPI40_0) +; RV64I-POOL-NEXT: ld a0, %lo(.LCPI40_0)(a0) ; RV64I-POOL-NEXT: ret ; ; RV64IZBA-LABEL: imm_neg_9223301666034697285: @@ -2544,8 +2598,8 @@ define i64 @imm_neg_9223354442718100411() { ; ; RV64I-POOL-LABEL: imm_neg_9223354442718100411: ; RV64I-POOL: # %bb.0: -; RV64I-POOL-NEXT: lui a0, %hi(.LCPI43_0) -; RV64I-POOL-NEXT: ld a0, %lo(.LCPI43_0)(a0) +; RV64I-POOL-NEXT: lui a0, %hi(.LCPI44_0) +; RV64I-POOL-NEXT: ld a0, %lo(.LCPI44_0)(a0) ; RV64I-POOL-NEXT: ret ; ; RV64IZBA-LABEL: imm_neg_9223354442718100411: @@ -3855,8 +3909,8 @@ define i64 @imm64_same_lo_hi_optsize() nounwind optsize { ; ; RV64I-POOL-LABEL: imm64_same_lo_hi_optsize: ; RV64I-POOL: # %bb.0: -; RV64I-POOL-NEXT: lui a0, %hi(.LCPI64_0) -; RV64I-POOL-NEXT: ld a0, %lo(.LCPI64_0)(a0) +; RV64I-POOL-NEXT: lui a0, %hi(.LCPI65_0) +; RV64I-POOL-NEXT: ld a0, %lo(.LCPI65_0)(a0) ; RV64I-POOL-NEXT: ret ; ; RV64IZBA-LABEL: imm64_same_lo_hi_optsize: @@ -3930,8 +3984,8 @@ define i64 @imm64_same_lo_hi_negative() nounwind { ; ; RV64I-POOL-LABEL: imm64_same_lo_hi_negative: ; RV64I-POOL: # %bb.0: -; RV64I-POOL-NEXT: lui a0, %hi(.LCPI65_0) -; RV64I-POOL-NEXT: ld a0, %lo(.LCPI65_0)(a0) +; RV64I-POOL-NEXT: lui a0, %hi(.LCPI66_0) +; RV64I-POOL-NEXT: ld a0, %lo(.LCPI66_0)(a0) ; RV64I-POOL-NEXT: ret ; ; RV64IZBA-LABEL: imm64_same_lo_hi_negative: -- GitLab From 90109d444839683b09f0aafdc50b749cb4b3203b Mon Sep 17 00:00:00 2001 From: Alex Bradbury Date: Tue, 14 May 2024 19:08:04 +0100 Subject: [PATCH 262/578] [RISCV] Improve constant materialisation for stores of i8 negative constants (#92131) This follows the same pattern as 20e62658735a1b03ecadc. Although we can't reduce the number of instructions used, if we are able to use a sign-extended 6-bit immediate then the 16-bit c.li instruction can be selected (thus saving code size). Although this _could_ be gated so it only happens if C is enabled, I've opted not to because at worst it's neutral and it doesn't seem helpful to add unnecessary divergence between the RVC and non-RVC paths. --- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 5 +++++ llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h | 1 + llvm/test/CodeGen/RISCV/imm.ll | 18 ++++++++---------- .../RISCV/rvv/fixed-vectors-fp-shuffles.ll | 2 +- .../RISCV/rvv/fixed-vectors-int-buildvec.ll | 2 +- .../RISCV/rvv/fixed-vectors-int-shuffles.ll | 6 +++--- .../rvv/fixed-vectors-reduction-formation.ll | 8 ++++---- .../test/CodeGen/RISCV/unaligned-load-store.ll | 2 +- 8 files changed, 24 insertions(+), 20 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index 3c4646b95715..d965dd4fc9a9 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -902,6 +902,11 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { return; } int64_t Imm = ConstNode->getSExtValue(); + // If only the lower 8 bits are used, try to convert this to a simm6 by + // sign-extending bit 7. This is neutral without the C extension, and + // allows C.LI to be used if C is present. + if (isUInt<8>(Imm) && isInt<6>(SignExtend64<8>(Imm)) && hasAllBUsers(Node)) + Imm = SignExtend64<8>(Imm); // If the upper XLen-16 bits are not used, try to convert this to a simm12 // by sign extending bit 15. if (isUInt<16>(Imm) && isInt<12>(SignExtend64<16>(Imm)) && diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h index 7d4aec2dfdc9..ece04dd7f4b7 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h @@ -121,6 +121,7 @@ public: bool hasAllNBitUsers(SDNode *Node, unsigned Bits, const unsigned Depth = 0) const; + bool hasAllBUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 8); } bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 16); } bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 32); } diff --git a/llvm/test/CodeGen/RISCV/imm.ll b/llvm/test/CodeGen/RISCV/imm.ll index 344ed0d2b083..5fd25ab60db0 100644 --- a/llvm/test/CodeGen/RISCV/imm.ll +++ b/llvm/test/CodeGen/RISCV/imm.ll @@ -1558,54 +1558,52 @@ define i64 @imm_2reg_1() nounwind { ret i64 -1152921504301427080 ; 0xF000_0000_1234_5678 } -; TODO: Selecting -1 would be better in this case as it can be loaded with a -; 16 bit instruction when the compressed extension is enabled. define void @imm_store_i8_neg1(ptr %p) nounwind { ; RV32I-LABEL: imm_store_i8_neg1: ; RV32I: # %bb.0: -; RV32I-NEXT: li a1, 255 +; RV32I-NEXT: li a1, -1 ; RV32I-NEXT: sb a1, 0(a0) ; RV32I-NEXT: ret ; ; RV64I-LABEL: imm_store_i8_neg1: ; RV64I: # %bb.0: -; RV64I-NEXT: li a1, 255 +; RV64I-NEXT: li a1, -1 ; RV64I-NEXT: sb a1, 0(a0) ; RV64I-NEXT: ret ; ; RV64IZBA-LABEL: imm_store_i8_neg1: ; RV64IZBA: # %bb.0: -; RV64IZBA-NEXT: li a1, 255 +; RV64IZBA-NEXT: li a1, -1 ; RV64IZBA-NEXT: sb a1, 0(a0) ; RV64IZBA-NEXT: ret ; ; RV64IZBB-LABEL: imm_store_i8_neg1: ; RV64IZBB: # %bb.0: -; RV64IZBB-NEXT: li a1, 255 +; RV64IZBB-NEXT: li a1, -1 ; RV64IZBB-NEXT: sb a1, 0(a0) ; RV64IZBB-NEXT: ret ; ; RV64IZBS-LABEL: imm_store_i8_neg1: ; RV64IZBS: # %bb.0: -; RV64IZBS-NEXT: li a1, 255 +; RV64IZBS-NEXT: li a1, -1 ; RV64IZBS-NEXT: sb a1, 0(a0) ; RV64IZBS-NEXT: ret ; ; RV64IXTHEADBB-LABEL: imm_store_i8_neg1: ; RV64IXTHEADBB: # %bb.0: -; RV64IXTHEADBB-NEXT: li a1, 255 +; RV64IXTHEADBB-NEXT: li a1, -1 ; RV64IXTHEADBB-NEXT: sb a1, 0(a0) ; RV64IXTHEADBB-NEXT: ret ; ; RV32-REMAT-LABEL: imm_store_i8_neg1: ; RV32-REMAT: # %bb.0: -; RV32-REMAT-NEXT: li a1, 255 +; RV32-REMAT-NEXT: li a1, -1 ; RV32-REMAT-NEXT: sb a1, 0(a0) ; RV32-REMAT-NEXT: ret ; ; RV64-REMAT-LABEL: imm_store_i8_neg1: ; RV64-REMAT: # %bb.0: -; RV64-REMAT-NEXT: li a1, 255 +; RV64-REMAT-NEXT: li a1, -1 ; RV64-REMAT-NEXT: sb a1, 0(a0) ; RV64-REMAT-NEXT: ret store i8 -1, ptr %p diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp-shuffles.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp-shuffles.ll index b0f6bebea038..8dc32d13e4a3 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp-shuffles.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp-shuffles.ll @@ -17,7 +17,7 @@ define <4 x half> @shuffle_v4f16(<4 x half> %x, <4 x half> %y) { define <8 x float> @shuffle_v8f32(<8 x float> %x, <8 x float> %y) { ; CHECK-LABEL: shuffle_v8f32: ; CHECK: # %bb.0: -; CHECK-NEXT: li a0, 236 +; CHECK-NEXT: li a0, -20 ; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma ; CHECK-NEXT: vmv.s.x v0, a0 ; CHECK-NEXT: vmerge.vvm v8, v10, v8, v0 diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll index ed6c01aaf7fe..592ce6fc5be0 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll @@ -260,7 +260,7 @@ define <4 x i8> @buildvec_vid_stepn3_add3_v4i8() { ; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma ; CHECK-NEXT: vmv.v.i v9, 3 ; CHECK-NEXT: vid.v v8 -; CHECK-NEXT: li a0, 253 +; CHECK-NEXT: li a0, -3 ; CHECK-NEXT: vmadd.vx v8, a0, v9 ; CHECK-NEXT: ret ret <4 x i8> diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll index 58af6ac246d1..aba69dc84620 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll @@ -611,7 +611,7 @@ define <8 x i8> @concat_4xi8_start_undef(<8 x i8> %v, <8 x i8> %w) { define <8 x i8> @concat_4xi8_start_undef_at_start(<8 x i8> %v, <8 x i8> %w) { ; CHECK-LABEL: concat_4xi8_start_undef_at_start: ; CHECK: # %bb.0: -; CHECK-NEXT: li a0, 224 +; CHECK-NEXT: li a0, -32 ; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, mu ; CHECK-NEXT: vmv.s.x v0, a0 ; CHECK-NEXT: vslideup.vi v8, v9, 4, v0.t @@ -682,7 +682,7 @@ define <8 x i8> @merge_non_contiguous_slideup_slidedown(<8 x i8> %v, <8 x i8> %w ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, mu ; CHECK-NEXT: vslidedown.vi v8, v8, 2 -; CHECK-NEXT: li a0, 234 +; CHECK-NEXT: li a0, -22 ; CHECK-NEXT: vmv.s.x v0, a0 ; CHECK-NEXT: vslideup.vi v8, v9, 1, v0.t ; CHECK-NEXT: ret @@ -699,7 +699,7 @@ define <8 x i8> @unmergable(<8 x i8> %v, <8 x i8> %w) { ; CHECK-NEXT: lui a0, %hi(.LCPI46_0) ; CHECK-NEXT: addi a0, a0, %lo(.LCPI46_0) ; CHECK-NEXT: vle8.v v10, (a0) -; CHECK-NEXT: li a0, 234 +; CHECK-NEXT: li a0, -22 ; CHECK-NEXT: vmv.s.x v0, a0 ; CHECK-NEXT: vrgather.vv v8, v9, v10, v0.t ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-reduction-formation.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-reduction-formation.ll index 5f456c782431..03624113a826 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-reduction-formation.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-reduction-formation.ll @@ -160,7 +160,7 @@ define i32 @reduce_sum_16xi32_prefix4(ptr %p) { define i32 @reduce_sum_16xi32_prefix5(ptr %p) { ; CHECK-LABEL: reduce_sum_16xi32_prefix5: ; CHECK: # %bb.0: -; CHECK-NEXT: li a1, 224 +; CHECK-NEXT: li a1, -32 ; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma ; CHECK-NEXT: vmv.s.x v0, a1 ; CHECK-NEXT: vmv.v.i v8, -1 @@ -532,7 +532,7 @@ define i32 @reduce_xor_16xi32_prefix2(ptr %p) { define i32 @reduce_xor_16xi32_prefix5(ptr %p) { ; CHECK-LABEL: reduce_xor_16xi32_prefix5: ; CHECK: # %bb.0: -; CHECK-NEXT: li a1, 224 +; CHECK-NEXT: li a1, -32 ; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma ; CHECK-NEXT: vmv.s.x v0, a1 ; CHECK-NEXT: vmv.v.i v8, -1 @@ -620,7 +620,7 @@ define i32 @reduce_or_16xi32_prefix2(ptr %p) { define i32 @reduce_or_16xi32_prefix5(ptr %p) { ; CHECK-LABEL: reduce_or_16xi32_prefix5: ; CHECK: # %bb.0: -; CHECK-NEXT: li a1, 224 +; CHECK-NEXT: li a1, -32 ; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma ; CHECK-NEXT: vmv.s.x v0, a1 ; CHECK-NEXT: vmv.v.i v8, -1 @@ -757,7 +757,7 @@ define i32 @reduce_umax_16xi32_prefix2(ptr %p) { define i32 @reduce_umax_16xi32_prefix5(ptr %p) { ; CHECK-LABEL: reduce_umax_16xi32_prefix5: ; CHECK: # %bb.0: -; CHECK-NEXT: li a1, 224 +; CHECK-NEXT: li a1, -32 ; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma ; CHECK-NEXT: vmv.s.x v0, a1 ; CHECK-NEXT: vmv.v.i v8, -1 diff --git a/llvm/test/CodeGen/RISCV/unaligned-load-store.ll b/llvm/test/CodeGen/RISCV/unaligned-load-store.ll index ce0d8fedbfb8..10497db6edc4 100644 --- a/llvm/test/CodeGen/RISCV/unaligned-load-store.ll +++ b/llvm/test/CodeGen/RISCV/unaligned-load-store.ll @@ -419,7 +419,7 @@ define void @merge_stores_i32_i64(ptr %p) { define void @store_large_constant(ptr %x) { ; SLOW-LABEL: store_large_constant: ; SLOW: # %bb.0: -; SLOW-NEXT: li a1, 254 +; SLOW-NEXT: li a1, -2 ; SLOW-NEXT: sb a1, 7(a0) ; SLOW-NEXT: li a1, 220 ; SLOW-NEXT: sb a1, 6(a0) -- GitLab From 67d840b60fbd75ca1b52d77bd3353771ec853735 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 14 May 2024 19:10:48 +0100 Subject: [PATCH 263/578] [VPlan] Relax over-aggressive assertion in VPTransformState::get(). There are cases where a vector value has some users that demand the the single scalar value only (NeedsScalar), while other users demand the vector value (see attached test cases). In those cases, the NeedsScalar users should only demand the first lane. Fixes https://github.com/llvm/llvm-project/issues/91883. --- llvm/lib/Transforms/Vectorize/VPlan.cpp | 2 +- ...ned-value-used-as-scalar-and-first-lane.ll | 226 ++++++++++++++++++ 2 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/LoopVectorize/X86/widened-value-used-as-scalar-and-first-lane.ll diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp index 999236ae8489..27f8e239b1c0 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp @@ -246,7 +246,7 @@ Value *VPTransformState::get(VPValue *Def, const VPIteration &Instance) { Value *VPTransformState::get(VPValue *Def, unsigned Part, bool NeedsScalar) { if (NeedsScalar) { - assert((VF.isScalar() || Def->isLiveIn() || + assert((VF.isScalar() || Def->isLiveIn() || hasVectorValue(Def, Part) || (hasScalarValue(Def, VPIteration(Part, 0)) && Data.PerPartScalars[Def][Part].size() == 1)) && "Trying to access a single scalar per part but has multiple scalars " diff --git a/llvm/test/Transforms/LoopVectorize/X86/widened-value-used-as-scalar-and-first-lane.ll b/llvm/test/Transforms/LoopVectorize/X86/widened-value-used-as-scalar-and-first-lane.ll new file mode 100644 index 000000000000..b22801ba9208 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/X86/widened-value-used-as-scalar-and-first-lane.ll @@ -0,0 +1,226 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes=loop-vectorize -mcpu=skylake-avx512 -mtriple=x86_64-apple-macosx -S %s | FileCheck %s + +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" + +; Test cases based on https://github.com/llvm/llvm-project/issues/91883. +define void @iv.4_used_as_vector_and_first_lane(ptr %src, ptr noalias %dst) { +; CHECK-LABEL: define void @iv.4_used_as_vector_and_first_lane( +; CHECK-SAME: ptr [[SRC:%.*]], ptr noalias [[DST:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ , [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[STEP_ADD:%.*]] = add <4 x i64> [[VEC_IND]], +; CHECK-NEXT: [[STEP_ADD1:%.*]] = add <4 x i64> [[STEP_ADD]], +; CHECK-NEXT: [[STEP_ADD2:%.*]] = add <4 x i64> [[STEP_ADD1]], +; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 12 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP0]] +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP1]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP2]] +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP3]] +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i64, ptr [[TMP4]], i32 0 +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, ptr [[TMP4]], i32 4 +; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i64, ptr [[TMP4]], i32 8 +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i64, ptr [[TMP4]], i32 12 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i64>, ptr [[TMP8]], align 8 +; CHECK-NEXT: [[WIDE_LOAD4:%.*]] = load <4 x i64>, ptr [[TMP9]], align 8 +; CHECK-NEXT: [[WIDE_LOAD5:%.*]] = load <4 x i64>, ptr [[TMP10]], align 8 +; CHECK-NEXT: [[WIDE_LOAD6:%.*]] = load <4 x i64>, ptr [[TMP11]], align 8 +; CHECK-NEXT: [[TMP12:%.*]] = add <4 x i64> [[VEC_IND]], +; CHECK-NEXT: [[TMP13:%.*]] = add <4 x i64> [[STEP_ADD]], +; CHECK-NEXT: [[TMP14:%.*]] = add <4 x i64> [[STEP_ADD1]], +; CHECK-NEXT: [[TMP15:%.*]] = add <4 x i64> [[STEP_ADD2]], +; CHECK-NEXT: [[TMP16:%.*]] = icmp ule <4 x i64> [[WIDE_LOAD]], +; CHECK-NEXT: [[TMP17:%.*]] = icmp ule <4 x i64> [[WIDE_LOAD4]], +; CHECK-NEXT: [[TMP18:%.*]] = icmp ule <4 x i64> [[WIDE_LOAD5]], +; CHECK-NEXT: [[TMP19:%.*]] = icmp ule <4 x i64> [[WIDE_LOAD6]], +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <4 x i64> [[TMP12]], i32 0 +; CHECK-NEXT: [[TMP21:%.*]] = add i64 [[TMP20]], 1 +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <4 x i64> [[TMP13]], i32 0 +; CHECK-NEXT: [[TMP23:%.*]] = add i64 [[TMP22]], 1 +; CHECK-NEXT: [[TMP24:%.*]] = extractelement <4 x i64> [[TMP14]], i32 0 +; CHECK-NEXT: [[TMP25:%.*]] = add i64 [[TMP24]], 1 +; CHECK-NEXT: [[TMP26:%.*]] = extractelement <4 x i64> [[TMP15]], i32 0 +; CHECK-NEXT: [[TMP27:%.*]] = add i64 [[TMP26]], 1 +; CHECK-NEXT: [[TMP28:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP21]] +; CHECK-NEXT: [[TMP29:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP23]] +; CHECK-NEXT: [[TMP30:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP25]] +; CHECK-NEXT: [[TMP31:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP27]] +; CHECK-NEXT: [[TMP32:%.*]] = getelementptr i64, ptr [[TMP28]], i32 0 +; CHECK-NEXT: [[TMP33:%.*]] = getelementptr i64, ptr [[TMP28]], i32 4 +; CHECK-NEXT: [[TMP34:%.*]] = getelementptr i64, ptr [[TMP28]], i32 8 +; CHECK-NEXT: [[TMP35:%.*]] = getelementptr i64, ptr [[TMP28]], i32 12 +; CHECK-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[TMP12]], ptr [[TMP32]], i32 4, <4 x i1> [[TMP16]]) +; CHECK-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[TMP13]], ptr [[TMP33]], i32 4, <4 x i1> [[TMP17]]) +; CHECK-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[TMP14]], ptr [[TMP34]], i32 4, <4 x i1> [[TMP18]]) +; CHECK-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[TMP15]], ptr [[TMP35]], i32 4, <4 x i1> [[TMP19]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 +; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[STEP_ADD2]], +; CHECK-NEXT: [[TMP36:%.*]] = icmp eq i64 [[INDEX_NEXT]], 32 +; CHECK-NEXT: br i1 [[TMP36]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 32, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[G_SRC:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV]] +; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[G_SRC]], align 8 +; CHECK-NEXT: [[IV_4:%.*]] = add nuw nsw i64 [[IV]], 4 +; CHECK-NEXT: [[C:%.*]] = icmp ule i64 [[L]], 128 +; CHECK-NEXT: br i1 [[C]], label [[LOOP_THEN:%.*]], label [[LOOP_LATCH]] +; CHECK: loop.then: +; CHECK-NEXT: [[OR:%.*]] = or disjoint i64 [[IV_4]], 1 +; CHECK-NEXT: [[G_DST:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[OR]] +; CHECK-NEXT: store i64 [[IV_4]], ptr [[G_DST]], align 4 +; CHECK-NEXT: br label [[LOOP_LATCH]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 32 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP3:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %g.src = getelementptr inbounds i64, ptr %src, i64 %iv + %l = load i64, ptr %g.src + %iv.4 = add nuw nsw i64 %iv, 4 + %c = icmp ule i64 %l, 128 + br i1 %c, label %loop.then, label %loop.latch + +loop.then: + %or = or disjoint i64 %iv.4, 1 + %g.dst = getelementptr inbounds i64, ptr %dst, i64 %or + store i64 %iv.4, ptr %g.dst, align 4 + br label %loop.latch + +loop.latch: + %iv.next = add nuw nsw i64 %iv, 1 + %exitcond = icmp eq i64 %iv.next, 32 + br i1 %exitcond, label %exit, label %loop.header + +exit: + ret void +} + +define void @iv.4_used_as_first_lane(ptr %src, ptr noalias %dst) { +; CHECK-LABEL: define void @iv.4_used_as_first_lane( +; CHECK-SAME: ptr [[SRC:%.*]], ptr noalias [[DST:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 12 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP0]] +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP1]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP2]] +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[TMP3]] +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i64, ptr [[TMP4]], i32 0 +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, ptr [[TMP4]], i32 4 +; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i64, ptr [[TMP4]], i32 8 +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i64, ptr [[TMP4]], i32 12 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i64>, ptr [[TMP8]], align 8 +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i64>, ptr [[TMP9]], align 8 +; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <4 x i64>, ptr [[TMP10]], align 8 +; CHECK-NEXT: [[WIDE_LOAD3:%.*]] = load <4 x i64>, ptr [[TMP11]], align 8 +; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[TMP0]], 4 +; CHECK-NEXT: [[TMP13:%.*]] = add i64 [[TMP1]], 4 +; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[TMP2]], 4 +; CHECK-NEXT: [[TMP15:%.*]] = add i64 [[TMP3]], 4 +; CHECK-NEXT: [[TMP16:%.*]] = icmp ule <4 x i64> [[WIDE_LOAD]], +; CHECK-NEXT: [[TMP17:%.*]] = icmp ule <4 x i64> [[WIDE_LOAD1]], +; CHECK-NEXT: [[TMP18:%.*]] = icmp ule <4 x i64> [[WIDE_LOAD2]], +; CHECK-NEXT: [[TMP19:%.*]] = icmp ule <4 x i64> [[WIDE_LOAD3]], +; CHECK-NEXT: [[TMP20:%.*]] = add i64 [[TMP12]], 1 +; CHECK-NEXT: [[TMP21:%.*]] = add i64 [[TMP13]], 1 +; CHECK-NEXT: [[TMP22:%.*]] = add i64 [[TMP14]], 1 +; CHECK-NEXT: [[TMP23:%.*]] = add i64 [[TMP15]], 1 +; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP20]] +; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP21]] +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP22]] +; CHECK-NEXT: [[TMP27:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP23]] +; CHECK-NEXT: [[TMP28:%.*]] = getelementptr i64, ptr [[TMP24]], i32 0 +; CHECK-NEXT: [[TMP29:%.*]] = getelementptr i64, ptr [[TMP24]], i32 4 +; CHECK-NEXT: [[TMP30:%.*]] = getelementptr i64, ptr [[TMP24]], i32 8 +; CHECK-NEXT: [[TMP31:%.*]] = getelementptr i64, ptr [[TMP24]], i32 12 +; CHECK-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[WIDE_LOAD]], ptr [[TMP28]], i32 4, <4 x i1> [[TMP16]]) +; CHECK-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[WIDE_LOAD1]], ptr [[TMP29]], i32 4, <4 x i1> [[TMP17]]) +; CHECK-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[WIDE_LOAD2]], ptr [[TMP30]], i32 4, <4 x i1> [[TMP18]]) +; CHECK-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[WIDE_LOAD3]], ptr [[TMP31]], i32 4, <4 x i1> [[TMP19]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 +; CHECK-NEXT: [[TMP32:%.*]] = icmp eq i64 [[INDEX_NEXT]], 32 +; CHECK-NEXT: br i1 [[TMP32]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 32, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[G_SRC:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV]] +; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[G_SRC]], align 8 +; CHECK-NEXT: [[IV_4:%.*]] = add nuw nsw i64 [[IV]], 4 +; CHECK-NEXT: [[C:%.*]] = icmp ule i64 [[L]], 128 +; CHECK-NEXT: br i1 [[C]], label [[LOOP_THEN:%.*]], label [[LOOP_LATCH]] +; CHECK: loop.then: +; CHECK-NEXT: [[OR:%.*]] = or disjoint i64 [[IV_4]], 1 +; CHECK-NEXT: [[G_DST:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[OR]] +; CHECK-NEXT: store i64 [[L]], ptr [[G_DST]], align 4 +; CHECK-NEXT: br label [[LOOP_LATCH]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 32 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %g.src = getelementptr inbounds i64, ptr %src, i64 %iv + %l = load i64, ptr %g.src + %iv.4 = add nuw nsw i64 %iv, 4 + %c = icmp ule i64 %l, 128 + br i1 %c, label %loop.then, label %loop.latch + +loop.then: + %or = or disjoint i64 %iv.4, 1 + %g.dst = getelementptr inbounds i64, ptr %dst, i64 %or + store i64 %l, ptr %g.dst, align 4 + br label %loop.latch + +loop.latch: + %iv.next = add nuw nsw i64 %iv, 1 + %exitcond = icmp eq i64 %iv.next, 32 + br i1 %exitcond, label %exit, label %loop.header + +exit: + ret void +} +;. +; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} +; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} +; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"} +; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]} +; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]} +; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META2]], [[META1]]} +;. -- GitLab From f89b1b8a68065c4b880417abb0563bce21399b52 Mon Sep 17 00:00:00 2001 From: Oleg Shyshkov Date: Tue, 14 May 2024 20:14:13 +0200 Subject: [PATCH 264/578] [mlir][bazel] Fix bazel build. --- 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 a3171287a84b..751cd94d5ff1 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -2102,6 +2102,7 @@ cc_library( ":ArmSMEOpInterfacesIncGen", ":IR", ":Support", + ":VectorDialect", "//llvm:Support", ], ) -- GitLab From 19008d32182ebbe421aaa222ee8af5c3e134e550 Mon Sep 17 00:00:00 2001 From: PiJoules <6019989+PiJoules@users.noreply.github.com> Date: Tue, 14 May 2024 11:23:45 -0700 Subject: [PATCH 265/578] [llvm] Support fixed point multiplication on AArch64 (#84237) Prior to this, fixed point multiplication would lead to this assertion error on AArhc64, armv8, and armv7. ``` _Accum f(_Accum x, _Accum y) { return x * y; } // ./bin/clang++ -ffixed-point /tmp/test2.cc -c -S -o - -target aarch64 -O3 clang++: llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp:10245: void llvm::TargetLowering::forceExpandWideMUL(SelectionDAG &, const SDLoc &, bool, EVT, const SDValue, const SDValue, const SDValue, const SDValue, SDValue &, SDValue &) const: Assertion `Ret.getOpcode() == ISD::MERGE_VALUES && "Ret value is a collection of constituent nodes holding result."' failed. ``` This path into forceExpandWideMUL should only be taken if we don't support [US]MUL_LOHI or MULH[US] for the operand size (32 in this case). But we should also check if we can just leverage regular wide multiplication. That is, extend the operands from 32 to 64, do a regular 64-bit mul, then trunc and shift. These ops are certainly available on aarch64 but for wider types. --- .../CodeGen/SelectionDAG/TargetLowering.cpp | 12 + llvm/test/CodeGen/AArch64/smul_fix.ll | 139 +++++++++ llvm/test/CodeGen/AArch64/smul_fix_sat.ll | 271 ++++++++++++++++++ llvm/test/CodeGen/AArch64/umul_fix.ll | 147 ++++++++++ llvm/test/CodeGen/AArch64/umul_fix_sat.ll | 206 +++++++++++++ 5 files changed, 775 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/smul_fix.ll create mode 100644 llvm/test/CodeGen/AArch64/smul_fix_sat.ll create mode 100644 llvm/test/CodeGen/AArch64/umul_fix.ll create mode 100644 llvm/test/CodeGen/AArch64/umul_fix_sat.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 7beaeb9b7a17..9ddb14e11dab 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -10500,6 +10500,7 @@ TargetLowering::expandFixedPointMul(SDNode *Node, SelectionDAG &DAG) const { SDValue Lo, Hi; unsigned LoHiOp = Signed ? ISD::SMUL_LOHI : ISD::UMUL_LOHI; unsigned HiOp = Signed ? ISD::MULHS : ISD::MULHU; + EVT WideVT = EVT::getIntegerVT(*DAG.getContext(), VTSize * 2); if (isOperationLegalOrCustom(LoHiOp, VT)) { SDValue Result = DAG.getNode(LoHiOp, dl, DAG.getVTList(VT, VT), LHS, RHS); Lo = Result.getValue(0); @@ -10507,6 +10508,17 @@ TargetLowering::expandFixedPointMul(SDNode *Node, SelectionDAG &DAG) const { } else if (isOperationLegalOrCustom(HiOp, VT)) { Lo = DAG.getNode(ISD::MUL, dl, VT, LHS, RHS); Hi = DAG.getNode(HiOp, dl, VT, LHS, RHS); + } else if (isOperationLegalOrCustom(ISD::MUL, WideVT)) { + // Try for a multiplication using a wider type. + unsigned Ext = Signed ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + SDValue LHSExt = DAG.getNode(Ext, dl, WideVT, LHS); + SDValue RHSExt = DAG.getNode(Ext, dl, WideVT, RHS); + SDValue Res = DAG.getNode(ISD::MUL, dl, WideVT, LHSExt, RHSExt); + Lo = DAG.getNode(ISD::TRUNCATE, dl, VT, Res); + SDValue Shifted = + DAG.getNode(ISD::SRA, dl, WideVT, Res, + DAG.getShiftAmountConstant(VTSize, WideVT, dl)); + Hi = DAG.getNode(ISD::TRUNCATE, dl, VT, Shifted); } else if (VT.isVector()) { return SDValue(); } else { diff --git a/llvm/test/CodeGen/AArch64/smul_fix.ll b/llvm/test/CodeGen/AArch64/smul_fix.ll new file mode 100644 index 000000000000..7bd80a00ec81 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/smul_fix.ll @@ -0,0 +1,139 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s + +define i32 @func(i32 %x, i32 %y) nounwind { +; CHECK-LABEL: func: +; CHECK: // %bb.0: +; CHECK-NEXT: smull x8, w0, w1 +; CHECK-NEXT: lsr x9, x8, #32 +; CHECK-NEXT: extr w0, w9, w8, #2 +; CHECK-NEXT: ret + %tmp = call i32 @llvm.smul.fix.i32(i32 %x, i32 %y, i32 2) + ret i32 %tmp +} + +define i64 @func2(i64 %x, i64 %y) { +; CHECK-LABEL: func2: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x8, x0, x1 +; CHECK-NEXT: smulh x9, x0, x1 +; CHECK-NEXT: extr x0, x9, x8, #2 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.smul.fix.i64(i64 %x, i64 %y, i32 2) + ret i64 %tmp +} + +define i4 @func3(i4 %x, i4 %y) nounwind { +; CHECK-LABEL: func3: +; CHECK: // %bb.0: +; CHECK-NEXT: sbfx w8, w1, #0, #4 +; CHECK-NEXT: sbfx w9, w0, #0, #4 +; CHECK-NEXT: smull x8, w9, w8 +; CHECK-NEXT: lsr x9, x8, #32 +; CHECK-NEXT: extr w0, w9, w8, #2 +; CHECK-NEXT: ret + %tmp = call i4 @llvm.smul.fix.i4(i4 %x, i4 %y, i32 2) + ret i4 %tmp +} + +;; These result in regular integer multiplication +define i32 @func4(i32 %x, i32 %y) nounwind { +; CHECK-LABEL: func4: +; CHECK: // %bb.0: +; CHECK-NEXT: mul w0, w0, w1 +; CHECK-NEXT: ret + %tmp = call i32 @llvm.smul.fix.i32(i32 %x, i32 %y, i32 0) + ret i32 %tmp +} + +define i64 @func5(i64 %x, i64 %y) { +; CHECK-LABEL: func5: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x0, x0, x1 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.smul.fix.i64(i64 %x, i64 %y, i32 0) + ret i64 %tmp +} + +define i4 @func6(i4 %x, i4 %y) nounwind { +; CHECK-LABEL: func6: +; CHECK: // %bb.0: +; CHECK-NEXT: sbfx w8, w1, #0, #4 +; CHECK-NEXT: sbfx w9, w0, #0, #4 +; CHECK-NEXT: mul w0, w9, w8 +; CHECK-NEXT: ret + %tmp = call i4 @llvm.smul.fix.i4(i4 %x, i4 %y, i32 0) + ret i4 %tmp +} + +define i64 @func7(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func7: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x8, x0, x1 +; CHECK-NEXT: smulh x9, x0, x1 +; CHECK-NEXT: extr x0, x9, x8, #32 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.smul.fix.i64(i64 %x, i64 %y, i32 32) + ret i64 %tmp +} + +define i64 @func8(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func8: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x8, x0, x1 +; CHECK-NEXT: smulh x9, x0, x1 +; CHECK-NEXT: extr x0, x9, x8, #63 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.smul.fix.i64(i64 %x, i64 %y, i32 63) + ret i64 %tmp +} + +define <2 x i32> @vec(<2 x i32> %x, <2 x i32> %y) nounwind { +; CHECK-LABEL: vec: +; CHECK: // %bb.0: +; CHECK-NEXT: mul v0.2s, v0.2s, v1.2s +; CHECK-NEXT: ret + %tmp = call <2 x i32> @llvm.smul.fix.v2i32(<2 x i32> %x, <2 x i32> %y, i32 0) + ret <2 x i32> %tmp +} + +define <4 x i32> @vec2(<4 x i32> %x, <4 x i32> %y) nounwind { +; CHECK-LABEL: vec2: +; CHECK: // %bb.0: +; CHECK-NEXT: mul v0.4s, v0.4s, v1.4s +; CHECK-NEXT: ret + %tmp = call <4 x i32> @llvm.smul.fix.v4i32(<4 x i32> %x, <4 x i32> %y, i32 0) + ret <4 x i32> %tmp +} + +define <4 x i64> @vec3(<4 x i64> %x, <4 x i64> %y) nounwind { +; CHECK-LABEL: vec3: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x8, v2.d[1] +; CHECK-NEXT: mov x9, v0.d[1] +; CHECK-NEXT: fmov x10, d2 +; CHECK-NEXT: fmov x11, d0 +; CHECK-NEXT: mov x14, v3.d[1] +; CHECK-NEXT: mov x15, v1.d[1] +; CHECK-NEXT: mul x12, x11, x10 +; CHECK-NEXT: mul x13, x9, x8 +; CHECK-NEXT: smulh x8, x9, x8 +; CHECK-NEXT: smulh x9, x11, x10 +; CHECK-NEXT: fmov x10, d3 +; CHECK-NEXT: fmov x11, d1 +; CHECK-NEXT: mul x16, x11, x10 +; CHECK-NEXT: extr x8, x8, x13, #32 +; CHECK-NEXT: smulh x10, x11, x10 +; CHECK-NEXT: extr x9, x9, x12, #32 +; CHECK-NEXT: mul x11, x15, x14 +; CHECK-NEXT: fmov d0, x9 +; CHECK-NEXT: smulh x14, x15, x14 +; CHECK-NEXT: extr x10, x10, x16, #32 +; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: fmov d1, x10 +; CHECK-NEXT: extr x11, x14, x11, #32 +; CHECK-NEXT: mov v1.d[1], x11 +; CHECK-NEXT: ret + %tmp = call <4 x i64> @llvm.smul.fix.v4i64(<4 x i64> %x, <4 x i64> %y, i32 32) + ret <4 x i64> %tmp +} diff --git a/llvm/test/CodeGen/AArch64/smul_fix_sat.ll b/llvm/test/CodeGen/AArch64/smul_fix_sat.ll new file mode 100644 index 000000000000..c2d8d34b9305 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/smul_fix_sat.ll @@ -0,0 +1,271 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s + +define i32 @func(i32 %x, i32 %y) nounwind { +; CHECK-LABEL: func: +; CHECK: // %bb.0: +; CHECK-NEXT: smull x9, w0, w1 +; CHECK-NEXT: mov w8, #2147483647 // =0x7fffffff +; CHECK-NEXT: lsr x10, x9, #32 +; CHECK-NEXT: extr w9, w10, w9, #2 +; CHECK-NEXT: cmp w10, #1 +; CHECK-NEXT: csel w8, w8, w9, gt +; CHECK-NEXT: cmn w10, #2 +; CHECK-NEXT: mov w9, #-2147483648 // =0x80000000 +; CHECK-NEXT: csel w0, w9, w8, lt +; CHECK-NEXT: ret + %tmp = call i32 @llvm.smul.fix.sat.i32(i32 %x, i32 %y, i32 2) + ret i32 %tmp +} + +define i64 @func2(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func2: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x9, x0, x1 +; CHECK-NEXT: mov x8, #9223372036854775807 // =0x7fffffffffffffff +; CHECK-NEXT: smulh x10, x0, x1 +; CHECK-NEXT: extr x9, x10, x9, #2 +; CHECK-NEXT: cmp x10, #1 +; CHECK-NEXT: csel x8, x8, x9, gt +; CHECK-NEXT: cmn x10, #2 +; CHECK-NEXT: mov x9, #-9223372036854775808 // =0x8000000000000000 +; CHECK-NEXT: csel x0, x9, x8, lt +; CHECK-NEXT: ret + %tmp = call i64 @llvm.smul.fix.sat.i64(i64 %x, i64 %y, i32 2) + ret i64 %tmp +} + +define i4 @func3(i4 %x, i4 %y) nounwind { +; CHECK-LABEL: func3: +; CHECK: // %bb.0: +; CHECK-NEXT: sbfx w9, w1, #0, #4 +; CHECK-NEXT: lsl w10, w0, #28 +; CHECK-NEXT: mov w8, #2147483647 // =0x7fffffff +; CHECK-NEXT: smull x9, w10, w9 +; CHECK-NEXT: lsr x10, x9, #32 +; CHECK-NEXT: extr w9, w10, w9, #2 +; CHECK-NEXT: cmp w10, #1 +; CHECK-NEXT: csel w8, w8, w9, gt +; CHECK-NEXT: cmn w10, #2 +; CHECK-NEXT: mov w9, #-2147483648 // =0x80000000 +; CHECK-NEXT: csel w8, w9, w8, lt +; CHECK-NEXT: asr w0, w8, #28 +; CHECK-NEXT: ret + %tmp = call i4 @llvm.smul.fix.sat.i4(i4 %x, i4 %y, i32 2) + ret i4 %tmp +} + +;; These result in regular integer multiplication with a saturation check. +define i32 @func4(i32 %x, i32 %y) nounwind { +; CHECK-LABEL: func4: +; CHECK: // %bb.0: +; CHECK-NEXT: smull x9, w0, w1 +; CHECK-NEXT: eor w10, w0, w1 +; CHECK-NEXT: mov w8, #-2147483648 // =0x80000000 +; CHECK-NEXT: cmp w10, #0 +; CHECK-NEXT: cinv w8, w8, ge +; CHECK-NEXT: cmp x9, w9, sxtw +; CHECK-NEXT: csel w0, w8, w9, ne +; CHECK-NEXT: ret + %tmp = call i32 @llvm.smul.fix.sat.i32(i32 %x, i32 %y, i32 0) + ret i32 %tmp +} + +define i64 @func5(i64 %x, i64 %y) { +; CHECK-LABEL: func5: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x9, x0, x1 +; CHECK-NEXT: eor x11, x0, x1 +; CHECK-NEXT: mov x8, #-9223372036854775808 // =0x8000000000000000 +; CHECK-NEXT: cmp x11, #0 +; CHECK-NEXT: smulh x10, x0, x1 +; CHECK-NEXT: cinv x8, x8, ge +; CHECK-NEXT: cmp x10, x9, asr #63 +; CHECK-NEXT: csel x0, x8, x9, ne +; CHECK-NEXT: ret + %tmp = call i64 @llvm.smul.fix.sat.i64(i64 %x, i64 %y, i32 0) + ret i64 %tmp +} + +define i4 @func6(i4 %x, i4 %y) nounwind { +; CHECK-LABEL: func6: +; CHECK: // %bb.0: +; CHECK-NEXT: sbfx w9, w1, #0, #4 +; CHECK-NEXT: lsl w10, w0, #28 +; CHECK-NEXT: mov w8, #-2147483648 // =0x80000000 +; CHECK-NEXT: smull x11, w10, w9 +; CHECK-NEXT: eor w9, w10, w9 +; CHECK-NEXT: cmp w9, #0 +; CHECK-NEXT: cinv w8, w8, ge +; CHECK-NEXT: cmp x11, w11, sxtw +; CHECK-NEXT: csel w8, w8, w11, ne +; CHECK-NEXT: asr w0, w8, #28 +; CHECK-NEXT: ret + %tmp = call i4 @llvm.smul.fix.sat.i4(i4 %x, i4 %y, i32 0) + ret i4 %tmp +} + +define i64 @func7(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func7: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x9, x0, x1 +; CHECK-NEXT: mov w8, #2147483647 // =0x7fffffff +; CHECK-NEXT: mov x11, #-2147483648 // =0xffffffff80000000 +; CHECK-NEXT: smulh x10, x0, x1 +; CHECK-NEXT: extr x9, x10, x9, #32 +; CHECK-NEXT: cmp x10, x8 +; CHECK-NEXT: mov x8, #9223372036854775807 // =0x7fffffffffffffff +; CHECK-NEXT: csel x8, x8, x9, gt +; CHECK-NEXT: cmp x10, x11 +; CHECK-NEXT: mov x9, #-9223372036854775808 // =0x8000000000000000 +; CHECK-NEXT: csel x0, x9, x8, lt +; CHECK-NEXT: ret + %tmp = call i64 @llvm.smul.fix.sat.i64(i64 %x, i64 %y, i32 32) + ret i64 %tmp +} + +define i64 @func8(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func8: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x9, x0, x1 +; CHECK-NEXT: mov x8, #4611686018427387903 // =0x3fffffffffffffff +; CHECK-NEXT: mov x11, #-4611686018427387904 // =0xc000000000000000 +; CHECK-NEXT: smulh x10, x0, x1 +; CHECK-NEXT: extr x9, x10, x9, #63 +; CHECK-NEXT: cmp x10, x8 +; CHECK-NEXT: mov x8, #9223372036854775807 // =0x7fffffffffffffff +; CHECK-NEXT: csel x8, x8, x9, gt +; CHECK-NEXT: cmp x10, x11 +; CHECK-NEXT: mov x9, #-9223372036854775808 // =0x8000000000000000 +; CHECK-NEXT: csel x0, x9, x8, lt +; CHECK-NEXT: ret + %tmp = call i64 @llvm.smul.fix.sat.i64(i64 %x, i64 %y, i32 63) + ret i64 %tmp +} + +define <2 x i32> @vec(<2 x i32> %x, <2 x i32> %y) nounwind { +; CHECK-LABEL: vec: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: mov w9, v1.s[1] +; CHECK-NEXT: mov w10, v0.s[1] +; CHECK-NEXT: mov w8, #-2147483648 // =0x80000000 +; CHECK-NEXT: fmov w12, s0 +; CHECK-NEXT: smull x11, w10, w9 +; CHECK-NEXT: eor w9, w10, w9 +; CHECK-NEXT: fmov w10, s1 +; CHECK-NEXT: cmp w9, #0 +; CHECK-NEXT: smull x9, w12, w10 +; CHECK-NEXT: eor w10, w12, w10 +; CHECK-NEXT: cinv w12, w8, ge +; CHECK-NEXT: cmp x11, w11, sxtw +; CHECK-NEXT: csel w11, w12, w11, ne +; CHECK-NEXT: cmp w10, #0 +; CHECK-NEXT: cinv w8, w8, ge +; CHECK-NEXT: cmp x9, w9, sxtw +; CHECK-NEXT: csel w8, w8, w9, ne +; CHECK-NEXT: fmov s0, w8 +; CHECK-NEXT: mov v0.s[1], w11 +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: ret + %tmp = call <2 x i32> @llvm.smul.fix.sat.v2i32(<2 x i32> %x, <2 x i32> %y, i32 0) + ret <2 x i32> %tmp +} + +define <4 x i32> @vec2(<4 x i32> %x, <4 x i32> %y) nounwind { +; CHECK-LABEL: vec2: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w9, v1.s[1] +; CHECK-NEXT: mov w10, v0.s[1] +; CHECK-NEXT: mov w8, #-2147483648 // =0x80000000 +; CHECK-NEXT: fmov w12, s1 +; CHECK-NEXT: fmov w13, s0 +; CHECK-NEXT: mov w14, v0.s[2] +; CHECK-NEXT: eor w11, w10, w9 +; CHECK-NEXT: smull x9, w10, w9 +; CHECK-NEXT: mov w10, v1.s[2] +; CHECK-NEXT: cmp w11, #0 +; CHECK-NEXT: smull x11, w13, w12 +; CHECK-NEXT: eor w12, w13, w12 +; CHECK-NEXT: cinv w13, w8, ge +; CHECK-NEXT: cmp x9, w9, sxtw +; CHECK-NEXT: csel w9, w13, w9, ne +; CHECK-NEXT: cmp w12, #0 +; CHECK-NEXT: mov w13, v1.s[3] +; CHECK-NEXT: cinv w12, w8, ge +; CHECK-NEXT: cmp x11, w11, sxtw +; CHECK-NEXT: csel w11, w12, w11, ne +; CHECK-NEXT: mov w12, v0.s[3] +; CHECK-NEXT: fmov s0, w11 +; CHECK-NEXT: smull x11, w14, w10 +; CHECK-NEXT: mov v0.s[1], w9 +; CHECK-NEXT: eor w9, w14, w10 +; CHECK-NEXT: smull x10, w12, w13 +; CHECK-NEXT: cmp w9, #0 +; CHECK-NEXT: cinv w9, w8, ge +; CHECK-NEXT: cmp x11, w11, sxtw +; CHECK-NEXT: csel w9, w9, w11, ne +; CHECK-NEXT: mov v0.s[2], w9 +; CHECK-NEXT: eor w9, w12, w13 +; CHECK-NEXT: cmp w9, #0 +; CHECK-NEXT: cinv w8, w8, ge +; CHECK-NEXT: cmp x10, w10, sxtw +; CHECK-NEXT: csel w8, w8, w10, ne +; CHECK-NEXT: mov v0.s[3], w8 +; CHECK-NEXT: ret + %tmp = call <4 x i32> @llvm.smul.fix.sat.v4i32(<4 x i32> %x, <4 x i32> %y, i32 0) + ret <4 x i32> %tmp +} + +define <4 x i64> @vec3(<4 x i64> %x, <4 x i64> %y) nounwind { +; CHECK-LABEL: vec3: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x8, v2.d[1] +; CHECK-NEXT: mov x9, v0.d[1] +; CHECK-NEXT: mov w16, #2147483647 // =0x7fffffff +; CHECK-NEXT: fmov x10, d2 +; CHECK-NEXT: fmov x11, d0 +; CHECK-NEXT: mov x18, #9223372036854775807 // =0x7fffffffffffffff +; CHECK-NEXT: mov x14, v3.d[1] +; CHECK-NEXT: mov x15, v1.d[1] +; CHECK-NEXT: mul x13, x9, x8 +; CHECK-NEXT: smulh x8, x9, x8 +; CHECK-NEXT: mul x12, x11, x10 +; CHECK-NEXT: smulh x9, x11, x10 +; CHECK-NEXT: extr x13, x8, x13, #32 +; CHECK-NEXT: cmp x8, x16 +; CHECK-NEXT: mul x10, x15, x14 +; CHECK-NEXT: csel x13, x18, x13, gt +; CHECK-NEXT: smulh x11, x15, x14 +; CHECK-NEXT: fmov x14, d3 +; CHECK-NEXT: fmov x15, d1 +; CHECK-NEXT: extr x12, x9, x12, #32 +; CHECK-NEXT: mul x17, x15, x14 +; CHECK-NEXT: smulh x14, x15, x14 +; CHECK-NEXT: mov x15, #-2147483648 // =0xffffffff80000000 +; CHECK-NEXT: cmp x8, x15 +; CHECK-NEXT: mov x8, #-9223372036854775808 // =0x8000000000000000 +; CHECK-NEXT: csel x13, x8, x13, lt +; CHECK-NEXT: cmp x9, x16 +; CHECK-NEXT: csel x12, x18, x12, gt +; CHECK-NEXT: cmp x9, x15 +; CHECK-NEXT: extr x9, x11, x10, #32 +; CHECK-NEXT: csel x10, x8, x12, lt +; CHECK-NEXT: cmp x11, x16 +; CHECK-NEXT: csel x9, x18, x9, gt +; CHECK-NEXT: cmp x11, x15 +; CHECK-NEXT: extr x11, x14, x17, #32 +; CHECK-NEXT: csel x9, x8, x9, lt +; CHECK-NEXT: cmp x14, x16 +; CHECK-NEXT: fmov d0, x10 +; CHECK-NEXT: csel x11, x18, x11, gt +; CHECK-NEXT: cmp x14, x15 +; CHECK-NEXT: csel x8, x8, x11, lt +; CHECK-NEXT: fmov d1, x8 +; CHECK-NEXT: mov v0.d[1], x13 +; CHECK-NEXT: mov v1.d[1], x9 +; CHECK-NEXT: ret + %tmp = call <4 x i64> @llvm.smul.fix.sat.v4i64(<4 x i64> %x, <4 x i64> %y, i32 32) + ret <4 x i64> %tmp +} diff --git a/llvm/test/CodeGen/AArch64/umul_fix.ll b/llvm/test/CodeGen/AArch64/umul_fix.ll new file mode 100644 index 000000000000..6ec683299384 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/umul_fix.ll @@ -0,0 +1,147 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s + +define i32 @func(i32 %x, i32 %y) nounwind { +; CHECK-LABEL: func: +; CHECK: // %bb.0: +; CHECK-NEXT: umull x8, w0, w1 +; CHECK-NEXT: lsr x9, x8, #32 +; CHECK-NEXT: extr w0, w9, w8, #2 +; CHECK-NEXT: ret + %tmp = call i32 @llvm.umul.fix.i32(i32 %x, i32 %y, i32 2) + ret i32 %tmp +} + +define i64 @func2(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func2: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x8, x0, x1 +; CHECK-NEXT: umulh x9, x0, x1 +; CHECK-NEXT: extr x0, x9, x8, #2 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 2) + ret i64 %tmp +} + +define i4 @func3(i4 %x, i4 %y) nounwind { +; CHECK-LABEL: func3: +; CHECK: // %bb.0: +; CHECK-NEXT: and w8, w1, #0xf +; CHECK-NEXT: and w9, w0, #0xf +; CHECK-NEXT: mul w8, w9, w8 +; CHECK-NEXT: lsr w0, w8, #2 +; CHECK-NEXT: ret + %tmp = call i4 @llvm.umul.fix.i4(i4 %x, i4 %y, i32 2) + ret i4 %tmp +} + +;; These result in regular integer multiplication +define i32 @func4(i32 %x, i32 %y) nounwind { +; CHECK-LABEL: func4: +; CHECK: // %bb.0: +; CHECK-NEXT: mul w0, w0, w1 +; CHECK-NEXT: ret + %tmp = call i32 @llvm.umul.fix.i32(i32 %x, i32 %y, i32 0) + ret i32 %tmp +} + +define i64 @func5(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func5: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x0, x0, x1 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 0) + ret i64 %tmp +} + +define i4 @func6(i4 %x, i4 %y) nounwind { +; CHECK-LABEL: func6: +; CHECK: // %bb.0: +; CHECK-NEXT: and w8, w1, #0xf +; CHECK-NEXT: and w9, w0, #0xf +; CHECK-NEXT: mul w0, w9, w8 +; CHECK-NEXT: ret + %tmp = call i4 @llvm.umul.fix.i4(i4 %x, i4 %y, i32 0) + ret i4 %tmp +} + +define i64 @func7(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func7: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x8, x0, x1 +; CHECK-NEXT: umulh x9, x0, x1 +; CHECK-NEXT: extr x0, x9, x8, #32 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 32) + ret i64 %tmp +} + +define i64 @func8(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func8: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x8, x0, x1 +; CHECK-NEXT: umulh x9, x0, x1 +; CHECK-NEXT: extr x0, x9, x8, #63 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 63) + ret i64 %tmp +} + +define i64 @func9(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func9: +; CHECK: // %bb.0: +; CHECK-NEXT: umulh x0, x0, x1 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 64) + ret i64 %tmp +} + +define <2 x i32> @vec(<2 x i32> %x, <2 x i32> %y) nounwind { +; CHECK-LABEL: vec: +; CHECK: // %bb.0: +; CHECK-NEXT: mul v0.2s, v0.2s, v1.2s +; CHECK-NEXT: ret + %tmp = call <2 x i32> @llvm.umul.fix.v2i32(<2 x i32> %x, <2 x i32> %y, i32 0) + ret <2 x i32> %tmp +} + +define <4 x i32> @vec2(<4 x i32> %x, <4 x i32> %y) nounwind { +; CHECK-LABEL: vec2: +; CHECK: // %bb.0: +; CHECK-NEXT: mul v0.4s, v0.4s, v1.4s +; CHECK-NEXT: ret + %tmp = call <4 x i32> @llvm.umul.fix.v4i32(<4 x i32> %x, <4 x i32> %y, i32 0) + ret <4 x i32> %tmp +} + +define <4 x i64> @vec3(<4 x i64> %x, <4 x i64> %y) nounwind { +; CHECK-LABEL: vec3: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x8, v2.d[1] +; CHECK-NEXT: mov x9, v0.d[1] +; CHECK-NEXT: fmov x10, d2 +; CHECK-NEXT: fmov x11, d0 +; CHECK-NEXT: mov x14, v3.d[1] +; CHECK-NEXT: mov x15, v1.d[1] +; CHECK-NEXT: mul x12, x11, x10 +; CHECK-NEXT: mul x13, x9, x8 +; CHECK-NEXT: umulh x8, x9, x8 +; CHECK-NEXT: umulh x9, x11, x10 +; CHECK-NEXT: fmov x10, d3 +; CHECK-NEXT: fmov x11, d1 +; CHECK-NEXT: mul x16, x11, x10 +; CHECK-NEXT: extr x8, x8, x13, #32 +; CHECK-NEXT: umulh x10, x11, x10 +; CHECK-NEXT: extr x9, x9, x12, #32 +; CHECK-NEXT: mul x11, x15, x14 +; CHECK-NEXT: fmov d0, x9 +; CHECK-NEXT: umulh x14, x15, x14 +; CHECK-NEXT: extr x10, x10, x16, #32 +; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: fmov d1, x10 +; CHECK-NEXT: extr x11, x14, x11, #32 +; CHECK-NEXT: mov v1.d[1], x11 +; CHECK-NEXT: ret + %tmp = call <4 x i64> @llvm.umul.fix.v4i64(<4 x i64> %x, <4 x i64> %y, i32 32) + ret <4 x i64> %tmp +} diff --git a/llvm/test/CodeGen/AArch64/umul_fix_sat.ll b/llvm/test/CodeGen/AArch64/umul_fix_sat.ll new file mode 100644 index 000000000000..e9965fd5319b --- /dev/null +++ b/llvm/test/CodeGen/AArch64/umul_fix_sat.ll @@ -0,0 +1,206 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s + +define i32 @func(i32 %x, i32 %y) nounwind { +; CHECK-LABEL: func: +; CHECK: // %bb.0: +; CHECK-NEXT: umull x8, w0, w1 +; CHECK-NEXT: lsr x9, x8, #32 +; CHECK-NEXT: extr w8, w9, w8, #2 +; CHECK-NEXT: cmp w9, #3 +; CHECK-NEXT: csinv w0, w8, wzr, ls +; CHECK-NEXT: ret + %tmp = call i32 @llvm.umul.fix.sat.i32(i32 %x, i32 %y, i32 2) + ret i32 %tmp +} + +define i64 @func2(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func2: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x8, x0, x1 +; CHECK-NEXT: umulh x9, x0, x1 +; CHECK-NEXT: extr x8, x9, x8, #2 +; CHECK-NEXT: cmp x9, #3 +; CHECK-NEXT: csinv x0, x8, xzr, ls +; CHECK-NEXT: ret + %tmp = call i64 @llvm.umul.fix.sat.i64(i64 %x, i64 %y, i32 2) + ret i64 %tmp +} + +define i4 @func3(i4 %x, i4 %y) nounwind { +; CHECK-LABEL: func3: +; CHECK: // %bb.0: +; CHECK-NEXT: lsl w8, w0, #28 +; CHECK-NEXT: and w9, w1, #0xf +; CHECK-NEXT: umull x8, w8, w9 +; CHECK-NEXT: lsr x9, x8, #32 +; CHECK-NEXT: extr w8, w9, w8, #2 +; CHECK-NEXT: cmp w9, #3 +; CHECK-NEXT: csinv w8, w8, wzr, ls +; CHECK-NEXT: lsr w0, w8, #28 +; CHECK-NEXT: ret + %tmp = call i4 @llvm.umul.fix.sat.i4(i4 %x, i4 %y, i32 2) + ret i4 %tmp +} + +;; These result in regular integer multiplication with a saturation check. +define i32 @func4(i32 %x, i32 %y) nounwind { +; CHECK-LABEL: func4: +; CHECK: // %bb.0: +; CHECK-NEXT: umull x8, w0, w1 +; CHECK-NEXT: tst x8, #0xffffffff00000000 +; CHECK-NEXT: csinv w0, w8, wzr, eq +; CHECK-NEXT: ret + %tmp = call i32 @llvm.umul.fix.sat.i32(i32 %x, i32 %y, i32 0) + ret i32 %tmp +} + +define i64 @func5(i64 %x, i64 %y) { +; CHECK-LABEL: func5: +; CHECK: // %bb.0: +; CHECK-NEXT: umulh x8, x0, x1 +; CHECK-NEXT: mul x9, x0, x1 +; CHECK-NEXT: cmp xzr, x8 +; CHECK-NEXT: csinv x0, x9, xzr, eq +; CHECK-NEXT: ret + %tmp = call i64 @llvm.umul.fix.sat.i64(i64 %x, i64 %y, i32 0) + ret i64 %tmp +} + +define i4 @func6(i4 %x, i4 %y) nounwind { +; CHECK-LABEL: func6: +; CHECK: // %bb.0: +; CHECK-NEXT: lsl w8, w0, #28 +; CHECK-NEXT: and w9, w1, #0xf +; CHECK-NEXT: umull x8, w8, w9 +; CHECK-NEXT: tst x8, #0xffffffff00000000 +; CHECK-NEXT: csinv w8, w8, wzr, eq +; CHECK-NEXT: lsr w0, w8, #28 +; CHECK-NEXT: ret + %tmp = call i4 @llvm.umul.fix.sat.i4(i4 %x, i4 %y, i32 0) + ret i4 %tmp +} + +define <2 x i32> @vec(<2 x i32> %x, <2 x i32> %y) nounwind { +; CHECK-LABEL: vec: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: mov w8, v1.s[1] +; CHECK-NEXT: mov w9, v0.s[1] +; CHECK-NEXT: fmov w10, s0 +; CHECK-NEXT: umull x8, w9, w8 +; CHECK-NEXT: fmov w9, s1 +; CHECK-NEXT: umull x9, w10, w9 +; CHECK-NEXT: tst x8, #0xffffffff00000000 +; CHECK-NEXT: csinv w8, w8, wzr, eq +; CHECK-NEXT: tst x9, #0xffffffff00000000 +; CHECK-NEXT: csinv w9, w9, wzr, eq +; CHECK-NEXT: fmov s0, w9 +; CHECK-NEXT: mov v0.s[1], w8 +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: ret + %tmp = call <2 x i32> @llvm.umul.fix.sat.v2i32(<2 x i32> %x, <2 x i32> %y, i32 0) + ret <2 x i32> %tmp +} + +define <4 x i32> @vec2(<4 x i32> %x, <4 x i32> %y) nounwind { +; CHECK-LABEL: vec2: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, v1.s[1] +; CHECK-NEXT: mov w9, v0.s[1] +; CHECK-NEXT: fmov w10, s0 +; CHECK-NEXT: mov w11, v0.s[2] +; CHECK-NEXT: mov w13, v0.s[3] +; CHECK-NEXT: mov w12, v1.s[3] +; CHECK-NEXT: umull x8, w9, w8 +; CHECK-NEXT: fmov w9, s1 +; CHECK-NEXT: umull x9, w10, w9 +; CHECK-NEXT: tst x8, #0xffffffff00000000 +; CHECK-NEXT: mov w10, v1.s[2] +; CHECK-NEXT: csinv w8, w8, wzr, eq +; CHECK-NEXT: tst x9, #0xffffffff00000000 +; CHECK-NEXT: csinv w9, w9, wzr, eq +; CHECK-NEXT: fmov s0, w9 +; CHECK-NEXT: umull x9, w11, w10 +; CHECK-NEXT: mov v0.s[1], w8 +; CHECK-NEXT: tst x9, #0xffffffff00000000 +; CHECK-NEXT: csinv w8, w9, wzr, eq +; CHECK-NEXT: umull x9, w13, w12 +; CHECK-NEXT: mov v0.s[2], w8 +; CHECK-NEXT: tst x9, #0xffffffff00000000 +; CHECK-NEXT: csinv w8, w9, wzr, eq +; CHECK-NEXT: mov v0.s[3], w8 +; CHECK-NEXT: ret + %tmp = call <4 x i32> @llvm.umul.fix.sat.v4i32(<4 x i32> %x, <4 x i32> %y, i32 0) + ret <4 x i32> %tmp +} + +define <4 x i64> @vec3(<4 x i64> %x, <4 x i64> %y) nounwind { +; CHECK-LABEL: vec3: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x8, v2.d[1] +; CHECK-NEXT: mov x9, v0.d[1] +; CHECK-NEXT: mov x14, v3.d[1] +; CHECK-NEXT: mov x15, v1.d[1] +; CHECK-NEXT: fmov x10, d2 +; CHECK-NEXT: fmov x11, d0 +; CHECK-NEXT: mul x12, x11, x10 +; CHECK-NEXT: mul x13, x9, x8 +; CHECK-NEXT: umulh x8, x9, x8 +; CHECK-NEXT: umulh x9, x11, x10 +; CHECK-NEXT: mul x10, x15, x14 +; CHECK-NEXT: extr x13, x8, x13, #32 +; CHECK-NEXT: umulh x11, x15, x14 +; CHECK-NEXT: fmov x14, d3 +; CHECK-NEXT: fmov x15, d1 +; CHECK-NEXT: mul x16, x15, x14 +; CHECK-NEXT: umulh x14, x15, x14 +; CHECK-NEXT: mov w15, #-1 // =0xffffffff +; CHECK-NEXT: cmp x8, x15 +; CHECK-NEXT: extr x8, x9, x12, #32 +; CHECK-NEXT: csinv x12, x13, xzr, ls +; CHECK-NEXT: cmp x9, x15 +; CHECK-NEXT: extr x9, x11, x10, #32 +; CHECK-NEXT: csinv x8, x8, xzr, ls +; CHECK-NEXT: cmp x11, x15 +; CHECK-NEXT: csinv x9, x9, xzr, ls +; CHECK-NEXT: fmov d0, x8 +; CHECK-NEXT: extr x10, x14, x16, #32 +; CHECK-NEXT: cmp x14, x15 +; CHECK-NEXT: csinv x10, x10, xzr, ls +; CHECK-NEXT: mov v0.d[1], x12 +; CHECK-NEXT: fmov d1, x10 +; CHECK-NEXT: mov v1.d[1], x9 +; CHECK-NEXT: ret + %tmp = call <4 x i64> @llvm.umul.fix.sat.v4i64(<4 x i64> %x, <4 x i64> %y, i32 32) + ret <4 x i64> %tmp +} + +define i64 @func7(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func7: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x9, x0, x1 +; CHECK-NEXT: mov w8, #-1 // =0xffffffff +; CHECK-NEXT: umulh x10, x0, x1 +; CHECK-NEXT: extr x9, x10, x9, #32 +; CHECK-NEXT: cmp x10, x8 +; CHECK-NEXT: csinv x0, x9, xzr, ls +; CHECK-NEXT: ret + %tmp = call i64 @llvm.umul.fix.sat.i64(i64 %x, i64 %y, i32 32) + ret i64 %tmp +} + +define i64 @func8(i64 %x, i64 %y) nounwind { +; CHECK-LABEL: func8: +; CHECK: // %bb.0: +; CHECK-NEXT: mul x9, x0, x1 +; CHECK-NEXT: mov x8, #9223372036854775807 // =0x7fffffffffffffff +; CHECK-NEXT: umulh x10, x0, x1 +; CHECK-NEXT: extr x9, x10, x9, #63 +; CHECK-NEXT: cmp x10, x8 +; CHECK-NEXT: csinv x0, x9, xzr, ls +; CHECK-NEXT: ret + %tmp = call i64 @llvm.umul.fix.sat.i64(i64 %x, i64 %y, i32 63) + ret i64 %tmp +} -- GitLab From acd100747fff85e7cfb67caa6c0f1053e820c1ac Mon Sep 17 00:00:00 2001 From: Felix Schneider Date: Tue, 14 May 2024 20:33:16 +0200 Subject: [PATCH 266/578] [mlir][test] Extend `InferIntRangeInterface` test Ops to arbitrary ints (#91850) This PR is in preparation to some extensions to the `InferIntRangeInterface` around the `nsw` and `nuw` flags supported in the `arith` dialect and LLVM. We provide some common inference logic for `index` and `arith` in `InferIntRangeCommon.h` but our Test Ops are currently fixed to `Index` Types. As we test the range inference for arith Ops, especially around the overflow behaviour, it's handy to have native support for the typical integer types in the test Ops. This patch 1. Changes the Attributes of `test.with_bounds` ops from `Index` to `APInt` which matches the internal representation in `ConstantIntRanges`. 2. Allows the use of `AnyInteger` in addition to `Index` for the operands and results of the test Ops. This now requires explicit specification of the type in the IR, where before `Index` was implicit. 3. Requires bounds Attrs to be specified in the precision of the SSA value, eliminating any implicit truncation or extension. (*Could this lead to problems?*) --- .../Dialect/Arith/int-range-interface.mlir | 10 ++ mlir/test/Dialect/Arith/int-range-opts.mlir | 36 +++--- .../test/Dialect/GPU/int-range-interface.mlir | 106 +++++++++--------- .../infer-int-range-test-ops.mlir | 56 ++++----- mlir/test/lib/Dialect/Test/TestOpDefs.cpp | 14 +-- mlir/test/lib/Dialect/Test/TestOps.td | 50 +++++---- 6 files changed, 140 insertions(+), 132 deletions(-) diff --git a/mlir/test/Dialect/Arith/int-range-interface.mlir b/mlir/test/Dialect/Arith/int-range-interface.mlir index 02a9827d19d8..16524b363472 100644 --- a/mlir/test/Dialect/Arith/int-range-interface.mlir +++ b/mlir/test/Dialect/Arith/int-range-interface.mlir @@ -756,3 +756,13 @@ func.func private @callee(%arg0: memref) { } return } + +// CHECK-LABEL: func @test_i8_bounds +// CHECK: test.reflect_bounds {smax = 127 : i8, smin = -128 : i8, umax = -1 : i8, umin = 0 : i8} +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 + %1 = arith.addi %0, %cst1 : 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 4c3c0854ed02..6179003ab4e7 100644 --- a/mlir/test/Dialect/Arith/int-range-opts.mlir +++ b/mlir/test/Dialect/Arith/int-range-opts.mlir @@ -5,7 +5,7 @@ // CHECK: return %[[C]] func.func @test() -> i1 { %cst1 = arith.constant -1 : index - %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } + %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } : index %1 = arith.cmpi eq, %0, %cst1 : index return %1: i1 } @@ -17,7 +17,7 @@ func.func @test() -> i1 { // CHECK: return %[[C]] func.func @test() -> i1 { %cst1 = arith.constant -1 : index - %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } + %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } : index %1 = arith.cmpi ne, %0, %cst1 : index return %1: i1 } @@ -30,7 +30,7 @@ func.func @test() -> i1 { // CHECK: return %[[C]] func.func @test() -> i1 { %cst = arith.constant 0 : index - %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } + %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } : index %1 = arith.cmpi sge, %0, %cst : index return %1: i1 } @@ -42,7 +42,7 @@ func.func @test() -> i1 { // CHECK: return %[[C]] func.func @test() -> i1 { %cst = arith.constant 0 : index - %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } + %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } : index %1 = arith.cmpi slt, %0, %cst : index return %1: i1 } @@ -55,7 +55,7 @@ func.func @test() -> i1 { // CHECK: return %[[C]] func.func @test() -> i1 { %cst1 = arith.constant -1 : index - %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } + %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } : index %1 = arith.cmpi sgt, %0, %cst1 : index return %1: i1 } @@ -67,7 +67,7 @@ func.func @test() -> i1 { // CHECK: return %[[C]] func.func @test() -> i1 { %cst1 = arith.constant -1 : index - %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } + %0 = test.with_bounds { umin = 0 : index, umax = 0x7fffffffffffffff : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } : index %1 = arith.cmpi sle, %0, %cst1 : index return %1: i1 } @@ -75,28 +75,24 @@ func.func @test() -> i1 { // ----- // CHECK-LABEL: func @test -// CHECK: test.reflect_bounds {smax = 24 : index, smin = 0 : index, umax = 24 : index, umin = 0 : index} -func.func @test() -> index { +// CHECK: test.reflect_bounds {smax = 24 : i8, smin = 0 : i8, umax = 24 : i8, umin = 0 : i8} +func.func @test() -> i8 { %cst1 = arith.constant 1 : i8 - %0 = test.with_bounds { umin = 0 : index, umax = 12 : index, smin = 0 : index, smax = 12 : index } - %i8val = arith.index_cast %0 : index to i8 + %i8val = test.with_bounds { umin = 0 : i8, umax = 12 : i8, smin = 0 : i8, smax = 12 : i8 } : i8 %shifted = arith.shli %i8val, %cst1 : i8 - %si = arith.index_cast %shifted : i8 to index - %1 = test.reflect_bounds %si - return %1: index + %1 = test.reflect_bounds %shifted : i8 + return %1: i8 } // ----- // CHECK-LABEL: func @test -// CHECK: test.reflect_bounds {smax = 127 : index, smin = -128 : index, umax = -1 : index, umin = 0 : index} -func.func @test() -> index { +// CHECK: test.reflect_bounds {smax = 127 : i8, smin = -128 : i8, umax = -1 : i8, umin = 0 : i8} +func.func @test() -> i8 { %cst1 = arith.constant 1 : i8 - %0 = test.with_bounds { umin = 0 : index, umax = 127 : index, smin = 0 : index, smax = 127 : index } - %i8val = arith.index_cast %0 : index to i8 + %i8val = test.with_bounds { umin = 0 : i8, umax = 127 : i8, smin = 0 : i8, smax = 127 : i8 } : i8 %shifted = arith.shli %i8val, %cst1 : i8 - %si = arith.index_cast %shifted : i8 to index - %1 = test.reflect_bounds %si - return %1: index + %1 = test.reflect_bounds %shifted : i8 + return %1: i8 } diff --git a/mlir/test/Dialect/GPU/int-range-interface.mlir b/mlir/test/Dialect/GPU/int-range-interface.mlir index 02aec9dc0476..980f7e5873e0 100644 --- a/mlir/test/Dialect/GPU/int-range-interface.mlir +++ b/mlir/test/Dialect/GPU/int-range-interface.mlir @@ -5,46 +5,46 @@ func.func @launch_func(%arg0 : index) { %0 = test.with_bounds { umin = 3 : index, umax = 5 : index, smin = 3 : index, smax = 5 : index - } + } : index %1 = test.with_bounds { umin = 7 : index, umax = 11 : index, smin = 7 : index, smax = 11 : index - } + } : index gpu.launch blocks(%block_id_x, %block_id_y, %block_id_z) in (%grid_dim_x = %0, %grid_dim_y = %1, %grid_dim_z = %arg0) threads(%thread_id_x, %thread_id_y, %thread_id_z) in (%block_dim_x = %arg0, %block_dim_y = %0, %block_dim_z = %1) { // CHECK: test.reflect_bounds {smax = 5 : index, smin = 3 : index, umax = 5 : index, umin = 3 : index} // CHECK: test.reflect_bounds {smax = 11 : index, smin = 7 : index, umax = 11 : index, umin = 7 : index} // CHECK: test.reflect_bounds {smax = 4294967295 : index, smin = 1 : index, umax = 4294967295 : index, umin = 1 : index} - %grid_dim_x0 = test.reflect_bounds %grid_dim_x - %grid_dim_y0 = test.reflect_bounds %grid_dim_y - %grid_dim_z0 = test.reflect_bounds %grid_dim_z + %grid_dim_x0 = test.reflect_bounds %grid_dim_x : index + %grid_dim_y0 = test.reflect_bounds %grid_dim_y : index + %grid_dim_z0 = test.reflect_bounds %grid_dim_z : index // CHECK: test.reflect_bounds {smax = 4 : index, smin = 0 : index, umax = 4 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 10 : index, smin = 0 : index, umax = 10 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 4294967294 : index, smin = 0 : index, umax = 4294967294 : index, umin = 0 : index} - %block_id_x0 = test.reflect_bounds %block_id_x - %block_id_y0 = test.reflect_bounds %block_id_y - %block_id_z0 = test.reflect_bounds %block_id_z + %block_id_x0 = test.reflect_bounds %block_id_x : index + %block_id_y0 = test.reflect_bounds %block_id_y : index + %block_id_z0 = test.reflect_bounds %block_id_z : index // CHECK: test.reflect_bounds {smax = 4294967295 : index, smin = 1 : index, umax = 4294967295 : index, umin = 1 : index} // CHECK: test.reflect_bounds {smax = 5 : index, smin = 3 : index, umax = 5 : index, umin = 3 : index} // CHECK: test.reflect_bounds {smax = 11 : index, smin = 7 : index, umax = 11 : index, umin = 7 : index} - %block_dim_x0 = test.reflect_bounds %block_dim_x - %block_dim_y0 = test.reflect_bounds %block_dim_y - %block_dim_z0 = test.reflect_bounds %block_dim_z + %block_dim_x0 = test.reflect_bounds %block_dim_x : index + %block_dim_y0 = test.reflect_bounds %block_dim_y : index + %block_dim_z0 = test.reflect_bounds %block_dim_z : index // CHECK: test.reflect_bounds {smax = 4294967294 : index, smin = 0 : index, umax = 4294967294 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 4 : index, smin = 0 : index, umax = 4 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 10 : index, smin = 0 : index, umax = 10 : index, umin = 0 : index} - %thread_id_x0 = test.reflect_bounds %thread_id_x - %thread_id_y0 = test.reflect_bounds %thread_id_y - %thread_id_z0 = test.reflect_bounds %thread_id_z + %thread_id_x0 = test.reflect_bounds %thread_id_x : index + %thread_id_y0 = test.reflect_bounds %thread_id_y : index + %thread_id_z0 = test.reflect_bounds %thread_id_z : index // The launch bounds are not constant, and so this can't infer anything // CHECK: test.reflect_bounds {smax = 4294967294 : index, smin = 0 : index, umax = 4294967294 : index, umin = 0 : index} %thread_id_op = gpu.thread_id y - %thread_id_op0 = test.reflect_bounds %thread_id_op + %thread_id_op0 = test.reflect_bounds %thread_id_op : index gpu.terminator } @@ -65,9 +65,9 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 4294967295 : index, smin = 1 : index, umax = 4294967295 : index, umin = 1 : index} // CHECK: test.reflect_bounds {smax = 4294967295 : index, smin = 1 : index, umax = 4294967295 : index, umin = 1 : index} // CHECK: test.reflect_bounds {smax = 4294967295 : index, smin = 1 : index, umax = 4294967295 : index, umin = 1 : index} - %grid_dim_x0 = test.reflect_bounds %grid_dim_x - %grid_dim_y0 = test.reflect_bounds %grid_dim_y - %grid_dim_z0 = test.reflect_bounds %grid_dim_z + %grid_dim_x0 = test.reflect_bounds %grid_dim_x : index + %grid_dim_y0 = test.reflect_bounds %grid_dim_y : index + %grid_dim_z0 = test.reflect_bounds %grid_dim_z : index %block_id_x = gpu.block_id x %block_id_y = gpu.block_id y @@ -76,9 +76,9 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 4294967294 : index, smin = 0 : index, umax = 4294967294 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 4294967294 : index, smin = 0 : index, umax = 4294967294 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 4294967294 : index, smin = 0 : index, umax = 4294967294 : index, umin = 0 : index} - %block_id_x0 = test.reflect_bounds %block_id_x - %block_id_y0 = test.reflect_bounds %block_id_y - %block_id_z0 = test.reflect_bounds %block_id_z + %block_id_x0 = test.reflect_bounds %block_id_x : index + %block_id_y0 = test.reflect_bounds %block_id_y : index + %block_id_z0 = test.reflect_bounds %block_id_z : index %block_dim_x = gpu.block_dim x %block_dim_y = gpu.block_dim y @@ -87,9 +87,9 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 4294967295 : index, smin = 1 : index, umax = 4294967295 : index, umin = 1 : index} // CHECK: test.reflect_bounds {smax = 4294967295 : index, smin = 1 : index, umax = 4294967295 : index, umin = 1 : index} // CHECK: test.reflect_bounds {smax = 4294967295 : index, smin = 1 : index, umax = 4294967295 : index, umin = 1 : index} - %block_dim_x0 = test.reflect_bounds %block_dim_x - %block_dim_y0 = test.reflect_bounds %block_dim_y - %block_dim_z0 = test.reflect_bounds %block_dim_z + %block_dim_x0 = test.reflect_bounds %block_dim_x : index + %block_dim_y0 = test.reflect_bounds %block_dim_y : index + %block_dim_z0 = test.reflect_bounds %block_dim_z : index %thread_id_x = gpu.thread_id x %thread_id_y = gpu.thread_id y @@ -98,9 +98,9 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 4294967294 : index, smin = 0 : index, umax = 4294967294 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 4294967294 : index, smin = 0 : index, umax = 4294967294 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 4294967294 : index, smin = 0 : index, umax = 4294967294 : index, umin = 0 : index} - %thread_id_x0 = test.reflect_bounds %thread_id_x - %thread_id_y0 = test.reflect_bounds %thread_id_y - %thread_id_z0 = test.reflect_bounds %thread_id_z + %thread_id_x0 = test.reflect_bounds %thread_id_x : index + %thread_id_y0 = test.reflect_bounds %thread_id_y : index + %thread_id_z0 = test.reflect_bounds %thread_id_z : index %global_id_x = gpu.global_id x %global_id_y = gpu.global_id y @@ -109,9 +109,9 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 9223372036854775807 : index, smin = -9223372036854775808 : index, umax = -8589934592 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 9223372036854775807 : index, smin = -9223372036854775808 : index, umax = -8589934592 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 9223372036854775807 : index, smin = -9223372036854775808 : index, umax = -8589934592 : index, umin = 0 : index} - %global_id_x0 = test.reflect_bounds %global_id_x - %global_id_y0 = test.reflect_bounds %global_id_y - %global_id_z0 = test.reflect_bounds %global_id_z + %global_id_x0 = test.reflect_bounds %global_id_x : index + %global_id_y0 = test.reflect_bounds %global_id_y : index + %global_id_z0 = test.reflect_bounds %global_id_z : index %subgroup_size = gpu.subgroup_size : index %lane_id = gpu.lane_id @@ -122,10 +122,10 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 127 : index, smin = 0 : index, umax = 127 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 4294967295 : index, smin = 1 : index, umax = 4294967295 : index, umin = 1 : index} // CHECK: test.reflect_bounds {smax = 4294967294 : index, smin = 0 : index, umax = 4294967294 : index, umin = 0 : index} - %subgroup_size0 = test.reflect_bounds %subgroup_size - %lane_id0 = test.reflect_bounds %lane_id - %num_subgroups0 = test.reflect_bounds %num_subgroups - %subgroup_id0 = test.reflect_bounds %subgroup_id + %subgroup_size0 = test.reflect_bounds %subgroup_size : index + %lane_id0 = test.reflect_bounds %lane_id : index + %num_subgroups0 = test.reflect_bounds %num_subgroups : index + %subgroup_id0 = test.reflect_bounds %subgroup_id : index llvm.return } @@ -148,9 +148,9 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 20 : index, smin = 20 : index, umax = 20 : index, umin = 20 : index} // CHECK: test.reflect_bounds {smax = 24 : index, smin = 24 : index, umax = 24 : index, umin = 24 : index} // CHECK: test.reflect_bounds {smax = 28 : index, smin = 28 : index, umax = 28 : index, umin = 28 : index} - %grid_dim_x0 = test.reflect_bounds %grid_dim_x - %grid_dim_y0 = test.reflect_bounds %grid_dim_y - %grid_dim_z0 = test.reflect_bounds %grid_dim_z + %grid_dim_x0 = test.reflect_bounds %grid_dim_x : index + %grid_dim_y0 = test.reflect_bounds %grid_dim_y : index + %grid_dim_z0 = test.reflect_bounds %grid_dim_z : index %block_id_x = gpu.block_id x %block_id_y = gpu.block_id y @@ -159,9 +159,9 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 19 : index, smin = 0 : index, umax = 19 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 23 : index, smin = 0 : index, umax = 23 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 27 : index, smin = 0 : index, umax = 27 : index, umin = 0 : index} - %block_id_x0 = test.reflect_bounds %block_id_x - %block_id_y0 = test.reflect_bounds %block_id_y - %block_id_z0 = test.reflect_bounds %block_id_z + %block_id_x0 = test.reflect_bounds %block_id_x : index + %block_id_y0 = test.reflect_bounds %block_id_y : index + %block_id_z0 = test.reflect_bounds %block_id_z : index %block_dim_x = gpu.block_dim x %block_dim_y = gpu.block_dim y @@ -170,9 +170,9 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 8 : index, smin = 8 : index, umax = 8 : index, umin = 8 : index} // CHECK: test.reflect_bounds {smax = 12 : index, smin = 12 : index, umax = 12 : index, umin = 12 : index} // CHECK: test.reflect_bounds {smax = 16 : index, smin = 16 : index, umax = 16 : index, umin = 16 : index} - %block_dim_x0 = test.reflect_bounds %block_dim_x - %block_dim_y0 = test.reflect_bounds %block_dim_y - %block_dim_z0 = test.reflect_bounds %block_dim_z + %block_dim_x0 = test.reflect_bounds %block_dim_x : index + %block_dim_y0 = test.reflect_bounds %block_dim_y : index + %block_dim_z0 = test.reflect_bounds %block_dim_z : index %thread_id_x = gpu.thread_id x %thread_id_y = gpu.thread_id y @@ -181,9 +181,9 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 7 : index, smin = 0 : index, umax = 7 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 11 : index, smin = 0 : index, umax = 11 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 15 : index, smin = 0 : index, umax = 15 : index, umin = 0 : index} - %thread_id_x0 = test.reflect_bounds %thread_id_x - %thread_id_y0 = test.reflect_bounds %thread_id_y - %thread_id_z0 = test.reflect_bounds %thread_id_z + %thread_id_x0 = test.reflect_bounds %thread_id_x : index + %thread_id_y0 = test.reflect_bounds %thread_id_y : index + %thread_id_z0 = test.reflect_bounds %thread_id_z : index %global_id_x = gpu.global_id x %global_id_y = gpu.global_id y @@ -192,9 +192,9 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 159 : index, smin = 0 : index, umax = 159 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 287 : index, smin = 0 : index, umax = 287 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 447 : index, smin = 0 : index, umax = 447 : index, umin = 0 : index} - %global_id_x0 = test.reflect_bounds %global_id_x - %global_id_y0 = test.reflect_bounds %global_id_y - %global_id_z0 = test.reflect_bounds %global_id_z + %global_id_x0 = test.reflect_bounds %global_id_x : index + %global_id_y0 = test.reflect_bounds %global_id_y : index + %global_id_z0 = test.reflect_bounds %global_id_z : index %subgroup_size = gpu.subgroup_size : index %lane_id = gpu.lane_id @@ -205,10 +205,10 @@ module attributes {gpu.container_module} { // CHECK: test.reflect_bounds {smax = 127 : index, smin = 0 : index, umax = 127 : index, umin = 0 : index} // CHECK: test.reflect_bounds {smax = 4294967295 : index, smin = 1 : index, umax = 4294967295 : index, umin = 1 : index} // CHECK: test.reflect_bounds {smax = 4294967294 : index, smin = 0 : index, umax = 4294967294 : index, umin = 0 : index} - %subgroup_size0 = test.reflect_bounds %subgroup_size - %lane_id0 = test.reflect_bounds %lane_id - %num_subgroups0 = test.reflect_bounds %num_subgroups - %subgroup_id0 = test.reflect_bounds %subgroup_id + %subgroup_size0 = test.reflect_bounds %subgroup_size : index + %lane_id0 = test.reflect_bounds %lane_id : index + %num_subgroups0 = test.reflect_bounds %num_subgroups : index + %subgroup_id0 = test.reflect_bounds %subgroup_id : index gpu.return } diff --git a/mlir/test/Interfaces/InferIntRangeInterface/infer-int-range-test-ops.mlir b/mlir/test/Interfaces/InferIntRangeInterface/infer-int-range-test-ops.mlir index c74af447d1b1..2106eeefdca4 100644 --- a/mlir/test/Interfaces/InferIntRangeInterface/infer-int-range-test-ops.mlir +++ b/mlir/test/Interfaces/InferIntRangeInterface/infer-int-range-test-ops.mlir @@ -5,7 +5,7 @@ // CHECK: return %[[cst]] func.func @constant() -> index { %0 = test.with_bounds { umin = 3 : index, umax = 3 : index, - smin = 3 : index, smax = 3 : index} + smin = 3 : index, smax = 3 : index} : index func.return %0 : index } @@ -13,8 +13,8 @@ func.func @constant() -> index { // CHECK: %[[cst:.*]] = "test.constant"() <{value = 4 : index} // CHECK: return %[[cst]] func.func @increment() -> index { - %0 = test.with_bounds { umin = 3 : index, umax = 3 : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } - %1 = test.increment %0 + %0 = test.with_bounds { umin = 3 : index, umax = 3 : index, smin = 0 : index, smax = 0x7fffffffffffffff : index } : index + %1 = test.increment %0 : index func.return %1 : index } @@ -22,14 +22,14 @@ func.func @increment() -> index { // CHECK: test.reflect_bounds {smax = 4 : index, smin = 3 : index, umax = 4 : index, umin = 3 : index} func.func @maybe_increment(%arg0 : i1) -> index { %0 = test.with_bounds { umin = 3 : index, umax = 3 : index, - smin = 3 : index, smax = 3 : index} + smin = 3 : index, smax = 3 : index} : index %1 = scf.if %arg0 -> index { scf.yield %0 : index } else { - %2 = test.increment %0 + %2 = test.increment %0 : index scf.yield %2 : index } - %3 = test.reflect_bounds %1 + %3 = test.reflect_bounds %1 : index func.return %3 : index } @@ -37,15 +37,15 @@ func.func @maybe_increment(%arg0 : i1) -> index { // CHECK: test.reflect_bounds {smax = 4 : index, smin = 3 : index, umax = 4 : index, umin = 3 : index} func.func @maybe_increment_br(%arg0 : i1) -> index { %0 = test.with_bounds { umin = 3 : index, umax = 3 : index, - smin = 3 : index, smax = 3 : index} + smin = 3 : index, smax = 3 : index} : index cf.cond_br %arg0, ^bb0, ^bb1 ^bb0: - %1 = test.increment %0 + %1 = test.increment %0 : index cf.br ^bb2(%1 : index) ^bb1: cf.br ^bb2(%0 : index) ^bb2(%2 : index): - %3 = test.reflect_bounds %2 + %3 = test.reflect_bounds %2 : index func.return %3 : index } @@ -53,16 +53,16 @@ func.func @maybe_increment_br(%arg0 : i1) -> index { // CHECK: test.reflect_bounds {smax = 1 : index, smin = 0 : index, umax = 1 : index, umin = 0 : index} func.func @for_bounds() -> index { %c0 = test.with_bounds { umin = 0 : index, umax = 0 : index, - smin = 0 : index, smax = 0 : index} + smin = 0 : index, smax = 0 : index} : index %c1 = test.with_bounds { umin = 1 : index, umax = 1 : index, - smin = 1 : index, smax = 1 : index} + smin = 1 : index, smax = 1 : index} : index %c2 = test.with_bounds { umin = 2 : index, umax = 2 : index, - smin = 2 : index, smax = 2 : index} + smin = 2 : index, smax = 2 : index} : index %0 = scf.for %arg0 = %c0 to %c2 step %c1 iter_args(%arg2 = %c0) -> index { scf.yield %arg0 : index } - %1 = test.reflect_bounds %0 + %1 = test.reflect_bounds %0 : index func.return %1 : index } @@ -70,17 +70,17 @@ func.func @for_bounds() -> index { // CHECK: test.reflect_bounds {smax = 9223372036854775807 : index, smin = -9223372036854775808 : index, umax = -1 : index, umin = 0 : index} func.func @no_analysis_of_loop_variants() -> index { %c0 = test.with_bounds { umin = 0 : index, umax = 0 : index, - smin = 0 : index, smax = 0 : index} + smin = 0 : index, smax = 0 : index} : index %c1 = test.with_bounds { umin = 1 : index, umax = 1 : index, - smin = 1 : index, smax = 1 : index} + smin = 1 : index, smax = 1 : index} : index %c2 = test.with_bounds { umin = 2 : index, umax = 2 : index, - smin = 2 : index, smax = 2 : index} + smin = 2 : index, smax = 2 : index} : index %0 = scf.for %arg0 = %c0 to %c2 step %c1 iter_args(%arg2 = %c0) -> index { - %1 = test.increment %arg2 + %1 = test.increment %arg2 : index scf.yield %1 : index } - %2 = test.reflect_bounds %0 + %2 = test.reflect_bounds %0 : index func.return %2 : index } @@ -88,8 +88,8 @@ func.func @no_analysis_of_loop_variants() -> index { // CHECK: test.reflect_bounds {smax = 4 : index, smin = 3 : index, umax = 4 : index, umin = 3 : index} func.func @region_args() { test.with_bounds_region { umin = 3 : index, umax = 4 : index, - smin = 3 : index, smax = 4 : index } %arg0 { - %0 = test.reflect_bounds %arg0 + smin = 3 : index, smax = 4 : index } %arg0 : index { + %0 = test.reflect_bounds %arg0 : index } func.return } @@ -97,7 +97,7 @@ func.func @region_args() { // CHECK-LABEL: func @func_args_unbound // CHECK: test.reflect_bounds {smax = 9223372036854775807 : index, smin = -9223372036854775808 : index, umax = -1 : index, umin = 0 : index} func.func @func_args_unbound(%arg0 : index) -> index { - %0 = test.reflect_bounds %arg0 + %0 = test.reflect_bounds %arg0 : index func.return %0 : index } @@ -106,7 +106,7 @@ func.func @propagate_across_while_loop_false() -> index { // CHECK-DAG: %[[C0:.*]] = "test.constant"() <{value = 0 // CHECK-DAG: %[[C1:.*]] = "test.constant"() <{value = 1 %0 = test.with_bounds { umin = 0 : index, umax = 0 : index, - smin = 0 : index, smax = 0 : index } + smin = 0 : index, smax = 0 : index } : index %1 = scf.while : () -> index { %false = arith.constant false // CHECK: scf.condition(%{{.*}}) %[[C0]] @@ -116,7 +116,7 @@ func.func @propagate_across_while_loop_false() -> index { scf.yield } // CHECK: return %[[C1]] - %2 = test.increment %1 + %2 = test.increment %1 : index return %2 : index } @@ -125,7 +125,7 @@ func.func @propagate_across_while_loop(%arg0 : i1) -> index { // CHECK-DAG: %[[C0:.*]] = "test.constant"() <{value = 0 // CHECK-DAG: %[[C1:.*]] = "test.constant"() <{value = 1 %0 = test.with_bounds { umin = 0 : index, umax = 0 : index, - smin = 0 : index, smax = 0 : index } + smin = 0 : index, smax = 0 : index } : index %1 = scf.while : () -> index { // CHECK: scf.condition(%{{.*}}) %[[C0]] scf.condition(%arg0) %0 : index @@ -134,7 +134,7 @@ func.func @propagate_across_while_loop(%arg0 : i1) -> index { scf.yield } // CHECK: return %[[C1]] - %2 = test.increment %1 + %2 = test.increment %1 : index return %2 : index } @@ -142,7 +142,7 @@ func.func @propagate_across_while_loop(%arg0 : i1) -> index { func.func @dont_propagate_across_infinite_loop() -> index { // CHECK: %[[C0:.*]] = "test.constant"() <{value = 0 %0 = test.with_bounds { umin = 0 : index, umax = 0 : index, - smin = 0 : index, smax = 0 : index } + smin = 0 : index, smax = 0 : index } : index // CHECK: %[[loopRes:.*]] = scf.while %1 = scf.while : () -> index { %true = arith.constant true @@ -152,8 +152,8 @@ func.func @dont_propagate_across_infinite_loop() -> index { ^bb0(%i1: index): scf.yield } - // CHECK: %[[ret:.*]] = test.reflect_bounds %[[loopRes]] - %2 = test.reflect_bounds %1 + // CHECK: %[[ret:.*]] = test.reflect_bounds %[[loopRes]] : index + %2 = test.reflect_bounds %1 : index // CHECK: return %[[ret]] return %2 : index } diff --git a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp index 0b676db18af4..bfee0391f670 100644 --- a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp +++ b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp @@ -663,8 +663,7 @@ ParseResult TestWithBoundsRegionOp::parse(OpAsmParser &parser, // Parse the input argument OpAsmParser::Argument argInfo; - argInfo.type = parser.getBuilder().getIndexType(); - if (failed(parser.parseArgument(argInfo))) + if (failed(parser.parseArgument(argInfo, true))) return failure(); // Parse the body region, and reuse the operand info as the argument info. @@ -676,7 +675,7 @@ void TestWithBoundsRegionOp::print(OpAsmPrinter &p) { p.printOptionalAttrDict((*this)->getAttrs()); p << ' '; p.printRegionArgument(getRegion().getArgument(0), /*argAttrs=*/{}, - /*omitType=*/true); + /*omitType=*/false); p << ' '; p.printRegion(getRegion(), /*printEntryBlockArgs=*/false); } @@ -707,10 +706,11 @@ void TestReflectBoundsOp::inferResultRanges( const ConstantIntRanges &range = argRanges[0]; MLIRContext *ctx = getContext(); Builder b(ctx); - setUminAttr(b.getIndexAttr(range.umin().getZExtValue())); - setUmaxAttr(b.getIndexAttr(range.umax().getZExtValue())); - setSminAttr(b.getIndexAttr(range.smin().getSExtValue())); - setSmaxAttr(b.getIndexAttr(range.smax().getSExtValue())); + 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())); setResultRanges(getResult(), range); } diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td index 7fc3d22d1895..befe6aa6cede 100644 --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -2734,49 +2734,51 @@ def TestGraphLoopOp : TEST_Op<"graph_loop", //===----------------------------------------------------------------------===// // Test InferIntRangeInterface //===----------------------------------------------------------------------===// +def InferIntRangeType : AnyTypeOf<[AnyInteger, Index]>; + def TestWithBoundsOp : TEST_Op<"with_bounds", [DeclareOpInterfaceMethods, NoMemoryEffect]> { - let arguments = (ins IndexAttr:$umin, - IndexAttr:$umax, - IndexAttr:$smin, - IndexAttr:$smax); - let results = (outs Index:$fakeVal); + let arguments = (ins APIntAttr:$umin, + APIntAttr:$umax, + APIntAttr:$smin, + APIntAttr:$smax); + let results = (outs InferIntRangeType:$fakeVal); - let assemblyFormat = "attr-dict"; + let assemblyFormat = "attr-dict `:` type($fakeVal)"; } def TestWithBoundsRegionOp : TEST_Op<"with_bounds_region", [DeclareOpInterfaceMethods, SingleBlock, NoTerminator]> { - let arguments = (ins IndexAttr:$umin, - IndexAttr:$umax, - IndexAttr:$smin, - IndexAttr:$smax); - // The region has one argument of index type + let arguments = (ins APIntAttr:$umin, + APIntAttr:$umax, + APIntAttr:$smin, + APIntAttr:$smax); + // The region has one argument of any integer type let regions = (region SizedRegion<1>:$region); let hasCustomAssemblyFormat = 1; } def TestIncrementOp : TEST_Op<"increment", [DeclareOpInterfaceMethods, - NoMemoryEffect]> { - let arguments = (ins Index:$value); - let results = (outs Index:$result); + NoMemoryEffect, AllTypesMatch<["value", "result"]>]> { + let arguments = (ins InferIntRangeType:$value); + let results = (outs InferIntRangeType:$result); - let assemblyFormat = "attr-dict $value"; + let assemblyFormat = "attr-dict $value `:` type($result)"; } def TestReflectBoundsOp : TEST_Op<"reflect_bounds", - [DeclareOpInterfaceMethods]> { - let arguments = (ins Index:$value, - OptionalAttr:$umin, - OptionalAttr:$umax, - OptionalAttr:$smin, - OptionalAttr:$smax); - let results = (outs Index:$result); - - let assemblyFormat = "attr-dict $value"; + [DeclareOpInterfaceMethods, AllTypesMatch<["value", "result"]>]> { + let arguments = (ins InferIntRangeType:$value, + OptionalAttr:$umin, + OptionalAttr:$umax, + OptionalAttr:$smin, + OptionalAttr:$smax); + let results = (outs InferIntRangeType:$result); + + let assemblyFormat = "attr-dict $value `:` type($result)"; } //===----------------------------------------------------------------------===// -- GitLab From 80f8ae3f8485b62529c32683ca48822d700c7716 Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Tue, 14 May 2024 11:34:27 -0700 Subject: [PATCH 267/578] [NFC] add explanation to register flags doc (#91803) --- llvm/docs/MIRLangRef.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/llvm/docs/MIRLangRef.rst b/llvm/docs/MIRLangRef.rst index e248a14636a8..ec29870128c1 100644 --- a/llvm/docs/MIRLangRef.rst +++ b/llvm/docs/MIRLangRef.rst @@ -540,41 +540,55 @@ Register Flags The table below shows all of the possible register flags along with the corresponding internal ``llvm::RegState`` representation: +.. + Keep this in sync with MachineInstrBuilder.h + .. list-table:: :header-rows: 1 * - Flag - Internal Value + - Meaning * - ``implicit`` - ``RegState::Implicit`` + - Not emitted register (e.g. carry, or temporary result). * - ``implicit-def`` - ``RegState::ImplicitDefine`` + - ``implicit`` and ``def`` * - ``def`` - ``RegState::Define`` + - Register definition. * - ``dead`` - ``RegState::Dead`` + - Unused definition. * - ``killed`` - ``RegState::Kill`` + - The last use of a register. * - ``undef`` - ``RegState::Undef`` + - Value of the register doesn't matter. * - ``internal`` - ``RegState::InternalRead`` + - Register reads a value that is defined inside the same instruction or bundle. * - ``early-clobber`` - ``RegState::EarlyClobber`` + - Register definition happens before uses. * - ``debug-use`` - ``RegState::Debug`` + - Register 'use' is for debugging purpose. * - ``renamable`` - ``RegState::Renamable`` + - Register that may be renamed. .. _subregister-indices: -- GitLab From 5adfcb07501f1d128e6517e60d30f2e3a0dc8eaa Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Tue, 14 May 2024 14:40:33 -0400 Subject: [PATCH 268/578] Allow passing creduce options through creduce-clang-crash.py (#92141) This change allows us to pass creduce options to creduce-clang-crash.py script. With this, `--n` is no longer needed to specify the number of cores, so removed the flag. The motivation is https://github.com/llvm/llvm-project/pull/87933#issuecomment-2109463497 suggests that disabling creduce renaming passes helps people to further reduce crash manually. --- clang/utils/creduce-clang-crash.py | 32 ++++++++++++------------------ 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/clang/utils/creduce-clang-crash.py b/clang/utils/creduce-clang-crash.py index 4d0c8224d8b4..db4a3435a3ae 100755 --- a/clang/utils/creduce-clang-crash.py +++ b/clang/utils/creduce-clang-crash.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Calls C-Reduce to create a minimal reproducer for clang crashes. +Unknown arguments are treated at creduce options. Output files: *.reduced.sh -- crash reproducer with minimal arguments @@ -70,7 +71,7 @@ def write_to_script(text, filename): class Reduce(object): - def __init__(self, crash_script, file_to_reduce, core_number): + def __init__(self, crash_script, file_to_reduce, creduce_flags): crash_script_name, crash_script_ext = os.path.splitext(crash_script) file_reduce_name, file_reduce_ext = os.path.splitext(file_to_reduce) @@ -83,8 +84,7 @@ class Reduce(object): self.clang_args = [] self.expected_output = [] self.needs_stack_trace = False - self.creduce_flags = ["--tidy"] - self.creduce_flags = ["--n", str(core_number)] + self.creduce_flags = ["--tidy"] + creduce_flags self.read_clang_args(crash_script, file_to_reduce) self.read_expected_output() @@ -412,13 +412,13 @@ fi print("Reduced command:", reduced_cmd) def run_creduce(self): + full_creduce_cmd = ( + [creduce_cmd] + self.creduce_flags + [self.testfile, self.file_to_reduce] + ) print("\nRunning C-Reduce...") + verbose_print(quote_cmd(full_creduce_cmd)) try: - p = subprocess.Popen( - [creduce_cmd] - + self.creduce_flags - + [self.testfile, self.file_to_reduce] - ) + p = subprocess.Popen(full_creduce_cmd) p.communicate() except KeyboardInterrupt: # Hack to kill C-Reduce because it jumps into its own pgid @@ -458,26 +458,20 @@ def main(): help="The path to the `creduce` executable. " "Required if `creduce` is not in PATH environment.", ) - parser.add_argument( - "--n", - dest="core_number", - type=int, - default=max(4, multiprocessing.cpu_count() // 2), - help="Number of cores to use.", - ) parser.add_argument("-v", "--verbose", action="store_true") - args = parser.parse_args() - + args, creduce_flags = parser.parse_known_args() verbose = args.verbose llvm_bin = os.path.abspath(args.llvm_bin) if args.llvm_bin else None creduce_cmd = check_cmd("creduce", None, args.creduce) clang_cmd = check_cmd("clang", llvm_bin, args.clang) - core_number = args.core_number crash_script = check_file(args.crash_script[0]) file_to_reduce = check_file(args.file_to_reduce[0]) - r = Reduce(crash_script, file_to_reduce, core_number) + if "--n" not in creduce_flags: + creduce_flags += ["--n", str(max(4, multiprocessing.cpu_count() // 2))] + + r = Reduce(crash_script, file_to_reduce, creduce_flags) r.simplify_clang_args() r.write_interestingness_test() -- GitLab From 179efe5abc745b5646efeb33fef86c55aa4fd7dc Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 14 May 2024 19:47:24 +0100 Subject: [PATCH 269/578] [LAA] Delay applying loop guards until after isSafeDependenceDistance. Applying the loop guards to the distance may prevent isSafeDependenceDistance from determining NoDep, unless loop guards are also applied to the backedge-taken-count. Instead of applying the guards to both Dist and the backedge-taken-count, just apply them after handling isSafeDependenceDistance and constant distances; there is no benefit to applying the guards before then. This fixes a regression flagged by @bjope due to ecae3ed958481cba7d60868cf3504292f7f4fdf5. --- llvm/lib/Analysis/LoopAccessAnalysis.cpp | 8 +-- .../is-safe-dep-distance-with-loop-guards.ll | 59 +------------------ 2 files changed, 5 insertions(+), 62 deletions(-) diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index e92aa0265a1f..4ba2e1522210 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -1991,9 +1991,6 @@ getDependenceDistanceStrideAndSize( return MemoryDepChecker::Dependence::Unknown; } - if (!isa(Dist)) - Dist = SE.applyLoopGuards(Dist, InnermostLoop); - uint64_t TypeByteSize = DL.getTypeAllocSize(ATy); bool HasSameSize = DL.getTypeStoreSizeInBits(ATy) == DL.getTypeStoreSizeInBits(BTy); @@ -2019,7 +2016,7 @@ MemoryDepChecker::Dependence::DepType MemoryDepChecker::isDependent( if (std::holds_alternative(Res)) return std::get(Res); - const auto &[Dist, StrideA, StrideB, TypeByteSize, AIsWrite, BIsWrite] = + auto &[Dist, StrideA, StrideB, TypeByteSize, AIsWrite, BIsWrite] = std::get(Res); bool HasSameSize = TypeByteSize > 0; @@ -2062,7 +2059,8 @@ MemoryDepChecker::Dependence::DepType MemoryDepChecker::isDependent( LLVM_DEBUG(dbgs() << "LAA: Strided accesses are independent\n"); return Dependence::NoDep; } - } + } else + Dist = SE.applyLoopGuards(Dist, InnermostLoop); // Negative distances are not plausible dependencies. if (SE.isKnownNonPositive(Dist)) { diff --git a/llvm/test/Analysis/LoopAccessAnalysis/is-safe-dep-distance-with-loop-guards.ll b/llvm/test/Analysis/LoopAccessAnalysis/is-safe-dep-distance-with-loop-guards.ll index bfa735df064d..9cc0a976c900 100644 --- a/llvm/test/Analysis/LoopAccessAnalysis/is-safe-dep-distance-with-loop-guards.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/is-safe-dep-distance-with-loop-guards.ll @@ -6,21 +6,10 @@ target datalayout = "S16-p:16:16-i1:16-i8:8-i32:16-i64:16-i128:16" define void @safe_deps_1_due_to_dependence_distance(i16 %n, ptr %p) { ; CHECK-LABEL: 'safe_deps_1_due_to_dependence_distance' ; CHECK-NEXT: loop: -; CHECK-NEXT: Memory dependences are safe with run-time checks +; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Run-time memory checks: -; CHECK-NEXT: Check 0: -; CHECK-NEXT: Comparing group ([[GRP1:0x[0-9a-f]+]]): -; CHECK-NEXT: %gep.iv = getelementptr inbounds i32, ptr %p, i16 %iv -; CHECK-NEXT: Against group ([[GRP2:0x[0-9a-f]+]]): -; CHECK-NEXT: %gep.off.iv = getelementptr i32, ptr %gep.off, i16 %iv ; CHECK-NEXT: Grouped accesses: -; CHECK-NEXT: Group [[GRP1]]: -; CHECK-NEXT: (Low: %p High: ((4 * %n) + %p)) -; CHECK-NEXT: Member: {%p,+,4}<%loop> -; CHECK-NEXT: Group [[GRP2]]: -; CHECK-NEXT: (Low: ((4 * %n) + %p) High: ((8 * %n) + %p)) -; CHECK-NEXT: Member: {((4 * %n) + %p),+,4}<%loop> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: @@ -52,57 +41,13 @@ exit: define void @safe_deps_2_due_to_dependence_distance(i16 %n, ptr %p3, i16 noundef %q, ptr %p1, ptr %p2) { ; CHECK-LABEL: 'safe_deps_2_due_to_dependence_distance' ; CHECK-NEXT: loop: -; CHECK-NEXT: Memory dependences are safe with run-time checks +; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Run-time memory checks: -; CHECK-NEXT: Check 0: -; CHECK-NEXT: Comparing group ([[GRP3:0x[0-9a-f]+]]): -; CHECK-NEXT: %arrayidx22 = getelementptr inbounds [2 x i32], ptr %alloca, i16 %iv -; CHECK-NEXT: Against group ([[GRP4:0x[0-9a-f]+]]): -; CHECK-NEXT: %arrayidx33 = getelementptr inbounds i8, ptr %arrayidx22, i16 4 -; CHECK-NEXT: Check 1: -; CHECK-NEXT: Comparing group ([[GRP3]]): -; CHECK-NEXT: %arrayidx22 = getelementptr inbounds [2 x i32], ptr %alloca, i16 %iv -; CHECK-NEXT: Against group ([[GRP5:0x[0-9a-f]+]]): -; CHECK-NEXT: %arrayidx42 = getelementptr inbounds [2 x i32], ptr %arrayidx40, i16 %iv -; CHECK-NEXT: Check 2: -; CHECK-NEXT: Comparing group ([[GRP3]]): -; CHECK-NEXT: %arrayidx22 = getelementptr inbounds [2 x i32], ptr %alloca, i16 %iv -; CHECK-NEXT: Against group ([[GRP6:0x[0-9a-f]+]]): -; CHECK-NEXT: %arrayidx53 = getelementptr inbounds i8, ptr %arrayidx42, i16 4 -; CHECK-NEXT: Check 3: -; CHECK-NEXT: Comparing group ([[GRP4]]): -; CHECK-NEXT: %arrayidx33 = getelementptr inbounds i8, ptr %arrayidx22, i16 4 -; CHECK-NEXT: Against group ([[GRP5]]): -; CHECK-NEXT: %arrayidx42 = getelementptr inbounds [2 x i32], ptr %arrayidx40, i16 %iv -; CHECK-NEXT: Check 4: -; CHECK-NEXT: Comparing group ([[GRP4]]): -; CHECK-NEXT: %arrayidx33 = getelementptr inbounds i8, ptr %arrayidx22, i16 4 -; CHECK-NEXT: Against group ([[GRP6]]): -; CHECK-NEXT: %arrayidx53 = getelementptr inbounds i8, ptr %arrayidx42, i16 4 -; CHECK-NEXT: Check 5: -; CHECK-NEXT: Comparing group ([[GRP5]]): -; CHECK-NEXT: %arrayidx42 = getelementptr inbounds [2 x i32], ptr %arrayidx40, i16 %iv -; CHECK-NEXT: Against group ([[GRP6]]): -; CHECK-NEXT: %arrayidx53 = getelementptr inbounds i8, ptr %arrayidx42, i16 4 ; CHECK-NEXT: Grouped accesses: -; CHECK-NEXT: Group [[GRP3]]: -; CHECK-NEXT: (Low: %alloca High: (-4 + (8 * %n) + %alloca)) -; CHECK-NEXT: Member: {%alloca,+,8}<%loop> -; CHECK-NEXT: Group [[GRP4]]: -; CHECK-NEXT: (Low: (4 + %alloca) High: ((8 * %n) + %alloca)) -; CHECK-NEXT: Member: {(4 + %alloca),+,8}<%loop> -; CHECK-NEXT: Group [[GRP5]]: -; CHECK-NEXT: (Low: ((8 * %n) + %alloca) High: (-4 + (16 * %n) + %alloca)) -; CHECK-NEXT: Member: {((8 * %n) + %alloca),+,8}<%loop> -; CHECK-NEXT: Group [[GRP6]]: -; CHECK-NEXT: (Low: (4 + (8 * %n) + %alloca) High: ((16 * %n) + %alloca)) -; CHECK-NEXT: Member: {(4 + (8 * %n) + %alloca),+,8}<%loop> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: -; CHECK-NEXT: {((8 * %n) + %alloca),+,8}<%loop> Added Flags: -; CHECK-NEXT: {(4 + (8 * %n) + %alloca),+,8}<%loop> Added Flags: ; CHECK-EMPTY: ; CHECK-NEXT: Expressions re-written: ; -- GitLab From 302db1ab5a054103e411997fd75b2bf6ef7f448c Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Tue, 14 May 2024 13:57:34 -0500 Subject: [PATCH 270/578] [Offload] Do not link every target for JIT (#92013) Summary: The offload library supports basic JIT functionality, however we currently link against every single target even though only AMDGPU and NVPTX are supported. This somewhat bloats the dynamic library list, so we should constrain it to what's actually used. --- offload/plugins-nextgen/CMakeLists.txt | 1 - offload/plugins-nextgen/common/CMakeLists.txt | 10 +++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/offload/plugins-nextgen/CMakeLists.txt b/offload/plugins-nextgen/CMakeLists.txt index d1079f8a3e9c..79f1c6dc66e8 100644 --- a/offload/plugins-nextgen/CMakeLists.txt +++ b/offload/plugins-nextgen/CMakeLists.txt @@ -16,7 +16,6 @@ add_subdirectory(common) function(add_target_library target_name lib_name) add_llvm_library(${target_name} STATIC LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} AggressiveInstCombine Analysis BinaryFormat diff --git a/offload/plugins-nextgen/common/CMakeLists.txt b/offload/plugins-nextgen/common/CMakeLists.txt index a470dcee6d85..6064468ea5b5 100644 --- a/offload/plugins-nextgen/common/CMakeLists.txt +++ b/offload/plugins-nextgen/common/CMakeLists.txt @@ -22,9 +22,13 @@ add_library(PluginCommon OBJECT add_dependencies(PluginCommon intrinsics_gen) # Only enable JIT for those targets that LLVM can support. -string(TOUPPER "${LLVM_TARGETS_TO_BUILD}" TargetsSupported) -foreach(Target ${TargetsSupported}) - target_compile_definitions(PluginCommon PRIVATE "LIBOMPTARGET_JIT_${Target}") +set(supported_jit_targets AMDGPU NVPTX) +foreach(target IN LISTS supported_jit_targets) + if("${target}" IN_LIST LLVM_TARGETS_TO_BUILD) + target_compile_definitions(PluginCommon PRIVATE "LIBOMPTARGET_JIT_${target}") + llvm_map_components_to_libnames(llvm_libs ${target}) + target_link_libraries(PluginCommon PRIVATE ${llvm_libs}) + endif() endforeach() # Include the RPC server from the `libc` project if availible. -- GitLab From 332f5e7113c409982e6429b135bb1a7055c11e77 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Tue, 14 May 2024 12:24:12 -0700 Subject: [PATCH 271/578] [compiler-rt][ORC] Remove unused cmake variables (NFC) (#87742) --- compiler-rt/lib/orc/CMakeLists.txt | 36 ------------------------------ 1 file changed, 36 deletions(-) diff --git a/compiler-rt/lib/orc/CMakeLists.txt b/compiler-rt/lib/orc/CMakeLists.txt index 6bcbf05f0d8b..36f4349a240e 100644 --- a/compiler-rt/lib/orc/CMakeLists.txt +++ b/compiler-rt/lib/orc/CMakeLists.txt @@ -9,24 +9,6 @@ set(ORC_COMMON_SOURCES dlfcn_wrapper.cpp ) -# ORC runtime library implementation files for all ORC architectures.s -set(ALL_ORC_SOURCES - ${ORC_COMMON_SOURCES} - coff_platform.cpp - coff_platform.per_jd.cpp - elfnix_platform.cpp - macho_platform.cpp - ) - -# Implementation files for all ORC architectures. -set(ALL_ORC_ASM_SOURCES - macho_tlv.x86-64.S - macho_tlv.arm64.S - elfnix_tls.x86-64.S - elfnix_tls.aarch64.S - elfnix_tls.ppc64.S - ) - # Common implementation headers will go here. set(ORC_COMMON_IMPL_HEADERS adt.h @@ -41,24 +23,6 @@ set(ORC_COMMON_IMPL_HEADERS wrapper_function_utils.h ) -# Implementation headers for all ORC architectures. -set(ALL_ORC_IMPL_HEADERS - ${ORC_COMMON_IMPL_HEADERS} - macho_platform.h - coff_platform.h - elfnix_platform.h - ) - -# Create list of all source files for -# consumption by tests. -set(ORC_ALL_SOURCE_FILES - ${ALL_ORC_SOURCES} - ${ALL_ORC_ASM_SOURCES} - ${ALL_ORC_IMPL_HEADERS} - ) - -list(REMOVE_DUPLICATES ORC_ALL_SOURCE_FILES) - # Now put it all together... include_directories(..) include_directories(../../include) -- GitLab From 18ba0cc26e079c7150feb5eaf631d1834e49ca1a Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Tue, 14 May 2024 12:24:32 -0700 Subject: [PATCH 272/578] [github] Add keith to bazel owners (NFC) (#92164) I'm interested in being CC'd on these changes --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e25b2f50b1b4..6adae58832e1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -132,7 +132,7 @@ clang/test/AST/Interp/ @tbaederr /bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci # Bazel build system. -/utils/bazel/ @rupprecht +/utils/bazel/ @rupprecht @keith # InstallAPI and TextAPI /llvm/**/TextAPI/ @cyndyishida -- GitLab From cf5db39907f7ec66c084a07c6eb9a83eef506b3c Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 14 May 2024 20:26:14 +0100 Subject: [PATCH 273/578] [LV] Add tests with trip counts containing UDIV expressions. Add test cases for https://github.com/llvm/llvm-project/issues/89958. --- .../trip-count-expansion-may-introduce-ub.ll | 368 ++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll diff --git a/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll b/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll new file mode 100644 index 000000000000..85fad6fb3632 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll @@ -0,0 +1,368 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -p loop-vectorize -force-vector-width=4 -S %s | FileCheck %s + +; Test cases with trip counts containing UDIV expressions for +; https://github.com/llvm/llvm-project/issues/89958. + +define i64 @multi_exit_1_exit_count_with_udiv_in_header(ptr %dst, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_1_exit_count_with_udiv_in_header( +; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) +; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 42, [[N]] +; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[TMP0]]) +; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 +; CHECK-NEXT: store <4 x i32> , ptr [[TMP6]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP3:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %dst, i64 %iv + store i32 1, ptr %gep + %d = udiv i64 42, %N + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.latch, label %exit + +loop.latch: + %iv.next = add i64 %iv, 1 + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] + ret i64 %p +} + +define i64 @multi_exit_2_exit_count_with_udiv_in_block_executed_unconditionally(ptr %A, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_2_exit_count_with_udiv_in_block_executed_unconditionally( +; CHECK-SAME: ptr [[A:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) +; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 42, [[N]] +; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[TMP0]]) +; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE6:%.*]] ] +; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP6]], align 4 +; CHECK-NEXT: [[TMP7:%.*]] = icmp eq <4 x i32> [[WIDE_LOAD]], +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP7]], i32 0 +; CHECK-NEXT: br i1 [[TMP8]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] +; CHECK: pred.store.if: +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP4]] +; CHECK-NEXT: store i32 1, ptr [[TMP9]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]] +; CHECK: pred.store.continue: +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i1> [[TMP7]], i32 1 +; CHECK-NEXT: br i1 [[TMP10]], label [[PRED_STORE_IF1:%.*]], label [[PRED_STORE_CONTINUE2:%.*]] +; CHECK: pred.store.if1: +; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[INDEX]], 1 +; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP11]] +; CHECK-NEXT: store i32 1, ptr [[TMP12]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE2]] +; CHECK: pred.store.continue2: +; CHECK-NEXT: [[TMP13:%.*]] = extractelement <4 x i1> [[TMP7]], i32 2 +; CHECK-NEXT: br i1 [[TMP13]], label [[PRED_STORE_IF3:%.*]], label [[PRED_STORE_CONTINUE4:%.*]] +; CHECK: pred.store.if3: +; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP14]] +; CHECK-NEXT: store i32 1, ptr [[TMP15]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE4]] +; CHECK: pred.store.continue4: +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[TMP7]], i32 3 +; CHECK-NEXT: br i1 [[TMP16]], label [[PRED_STORE_IF5:%.*]], label [[PRED_STORE_CONTINUE6]] +; CHECK: pred.store.if5: +; CHECK-NEXT: [[TMP17:%.*]] = add i64 [[INDEX]], 3 +; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP17]] +; CHECK-NEXT: store i32 1, ptr [[TMP18]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE6]] +; CHECK: pred.store.continue6: +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP19:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP19]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]] +; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP]], align 4 +; CHECK-NEXT: [[C_2:%.*]] = icmp eq i32 [[L]], 10 +; CHECK-NEXT: br i1 [[C_2]], label [[THEN:%.*]], label [[CONTINUE:%.*]] +; CHECK: then: +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: br label [[CONTINUE]] +; CHECK: continue: +; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[CONTINUE]] ], [ 0, [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %A, i64 %iv + %l = load i32, ptr %gep + %c.2 = icmp eq i32 %l, 10 + br i1 %c.2, label %then, label %continue + +then: + store i32 1, ptr %gep + br label %continue + +continue: + %d = udiv i64 42, %N + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.latch, label %exit + +loop.latch: + %iv.next = add i64 %iv, 1 + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %continue ], [ 0, %loop.latch] + ret i64 %p +} + +define i64 @multi_exit_3_exit_count_with_udiv_in_block_executed_conditionally(ptr %A, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_3_exit_count_with_udiv_in_block_executed_conditionally( +; CHECK-SAME: ptr [[A:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]] +; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP]], align 4 +; CHECK-NEXT: [[C_2:%.*]] = icmp eq i32 [[L]], 10 +; CHECK-NEXT: br i1 [[C_2]], label [[THEN:%.*]], label [[LOOP_LATCH]] +; CHECK: then: +; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[THEN]] ], [ 0, [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %A, i64 %iv + %l = load i32, ptr %gep + %c.2 = icmp eq i32 %l, 10 + br i1 %c.2, label %then, label %loop.latch + +then: + %d = udiv i64 42, %N + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.latch, label %exit + +loop.latch: + store i32 1, ptr %gep + %iv.next = add i64 %iv, 1 + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %then ], [ 0, %loop.latch] + ret i64 %p +} + +; FIXME: Currently miscompiled as we unconditionally execute udiv after +; vectorization. +define i64 @multi_exit_4_exit_count_with_udiv_in_latch(ptr %dst, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_udiv_in_latch( +; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) +; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 42, [[N]] +; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[TMP0]]) +; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 +; CHECK-NEXT: store <4 x i32> , ptr [[TMP6]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP7:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %dst, i64 %iv + store i32 1, ptr %gep + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.latch, label %exit + +loop.latch: + %iv.next = add i64 %iv, 1 + %d = udiv i64 42, %N + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] + ret i64 %p +} + +define void @single_exit_tc_with_udiv(ptr %dst, i64 %N) { +; CHECK-LABEL: define void @single_exit_tc_with_udiv( +; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 42, [[N]] +; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[TMP0]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP1]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP2]] +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i32 0 +; CHECK-NEXT: store <4 x i32> , ptr [[TMP4]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP1]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP]], label [[EXIT]], !llvm.loop [[LOOP9:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr inbounds i32, ptr %dst, i64 %iv + store i32 1, ptr %gep + %iv.next = add i64 %iv, 1 + %d = udiv i64 42, %N + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop, label %exit + +exit: + ret void +} + +;. +; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} +; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} +; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"} +; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]} +; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]} +; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META2]], [[META1]]} +; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]]} +; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META1]]} +; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META1]], [[META2]]} +; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META2]], [[META1]]} +;. -- GitLab From 4cfe347c107485aab6bd003f99ab06aac242b0fd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 14 May 2024 12:58:49 -0700 Subject: [PATCH 274/578] [clangd] Fix -Wunused-but-set-variable after #82396 --- clang-tools-extra/clangd/refactor/Rename.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp index 75b30e66d637..c0fc4453a3fc 100644 --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -1090,11 +1090,10 @@ llvm::Expected rename(const RenameInputs &RInputs) { return MainFileRenameEdit.takeError(); llvm::DenseSet RenamedRanges; - if (const auto *MD = dyn_cast(&RenameDecl)) { + if (!isa(RenameDecl)) { // TODO: Insert the ranges from the ObjCMethodDecl/ObjCMessageExpr selector // pieces which are being renamed. This will require us to make changes to // locateDeclAt to preserve this AST node. - } else { RenamedRanges.insert(CurrentIdentifier); } -- GitLab From d4c86e7f3ea298b259e673142470a7b838f5f302 Mon Sep 17 00:00:00 2001 From: Amara Emerson Date: Tue, 14 May 2024 13:00:19 -0700 Subject: [PATCH 275/578] [AArch64][SME] Fix frame lowering not using a base pointer for SME functions. (#91643) The existing code is checking for the presence of the +sve subtarget feature when deciding to use a base pointer for the function, but this check doesn't work when only +sme is used. rdar://126878490 --- .../Target/AArch64/AArch64RegisterInfo.cpp | 3 +- .../AArch64/framelayout-sve-basepointer.mir | 31 +- .../CodeGen/AArch64/sme-framelower-use-bp.ll | 1049 +++++++++++++++++ 3 files changed, 1081 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index ad29003f1e81..5a5a18edb12e 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -552,7 +552,8 @@ bool AArch64RegisterInfo::hasBasePointer(const MachineFunction &MF) const { if (hasStackRealignment(MF)) return true; - if (MF.getSubtarget().hasSVE()) { + auto &ST = MF.getSubtarget(); + if (ST.hasSVE() || ST.isStreaming()) { const AArch64FunctionInfo *AFI = MF.getInfo(); // Frames that have variable sized objects and scalable SVE objects, // should always use a basepointer. diff --git a/llvm/test/CodeGen/AArch64/framelayout-sve-basepointer.mir b/llvm/test/CodeGen/AArch64/framelayout-sve-basepointer.mir index 265c474fbc5d..26b7ca3bf8c0 100644 --- a/llvm/test/CodeGen/AArch64/framelayout-sve-basepointer.mir +++ b/llvm/test/CodeGen/AArch64/framelayout-sve-basepointer.mir @@ -1,4 +1,11 @@ -# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog -mattr=+sve %s -o - | FileCheck %s +# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog %s -o - | FileCheck %s +--- | + define void @hasBasepointer() #0 { ret void } + define void @hasBasepointer_sme_streaming() #1 { ret void } + + attributes #0 = { "target-features"="+sve" } + attributes #1 = { "target-features"="+sme" "aarch64_pstate_sm_enabled" } +... --- # This test verifies that the basepointer is available in presence of SVE stack objects. name: hasBasepointer @@ -21,3 +28,25 @@ body: | STRXui $x0, %stack.1, 0 RET_ReallyLR ... +--- +# Likewise with only SME with a streaming function. +name: hasBasepointer_sme_streaming +# CHECK-LABEL: name: hasBasepointer_sme_streaming +# CHECK: bb.0: +# CHECK: $sp = frame-setup SUBXri $sp, 16, 0 +# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1 +# CHECK-NEXT: $x19 = ADDXri $sp, 0, 0 +# CHECK: STRXui $x0, $x19, 0 +tracksRegLiveness: true +frameInfo: + isFrameAddressTaken: true +stack: + - { id: 0, type: variable-sized, alignment: 1 } + - { id: 1, name: '', size: 16, alignment: 8 } + - { id: 2, stack-id: scalable-vector, size: 16, alignment: 16 } +body: | + bb.0: + liveins: $x0 + STRXui $x0, %stack.1, 0 + RET_ReallyLR +... diff --git a/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll b/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll new file mode 100644 index 000000000000..7db0cf7f18c5 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sme-framelower-use-bp.ll @@ -0,0 +1,1049 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=aarch64 -O0 -mattr=+sme < %s | FileCheck %s + +target triple = "aarch64-linux-gnu" + +declare void @llvm.trap() #0 + +; This test checks that we don't assert/crash due to not being able to reach the +; emergency spill slot by ensuring that we use a BP for streaming functions. + +define void @quux() #1 { +; CHECK-LABEL: quux: +; CHECK: // %bb.0: // %prelude +; CHECK-NEXT: stp x29, x30, [sp, #-96]! // 16-byte Folded Spill +; CHECK-NEXT: stp x28, x27, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: stp x26, x25, [sp, #32] // 16-byte Folded Spill +; CHECK-NEXT: stp x24, x23, [sp, #48] // 16-byte Folded Spill +; CHECK-NEXT: stp x22, x21, [sp, #64] // 16-byte Folded Spill +; CHECK-NEXT: stp x20, x19, [sp, #80] // 16-byte Folded Spill +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: sub sp, sp, #400 +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: mov x19, sp +; CHECK-NEXT: .cfi_def_cfa w29, 96 +; CHECK-NEXT: .cfi_offset w19, -8 +; CHECK-NEXT: .cfi_offset w20, -16 +; CHECK-NEXT: .cfi_offset w21, -24 +; CHECK-NEXT: .cfi_offset w22, -32 +; CHECK-NEXT: .cfi_offset w23, -40 +; CHECK-NEXT: .cfi_offset w24, -48 +; CHECK-NEXT: .cfi_offset w25, -56 +; CHECK-NEXT: .cfi_offset w26, -64 +; CHECK-NEXT: .cfi_offset w27, -72 +; CHECK-NEXT: .cfi_offset w28, -80 +; CHECK-NEXT: .cfi_offset w30, -88 +; CHECK-NEXT: .cfi_offset w29, -96 +; CHECK-NEXT: rdsvl x8, #1 +; CHECK-NEXT: mul x9, x8, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: subs x8, x8, x9 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: str x8, [x19, #384] +; CHECK-NEXT: mov w8, wzr +; CHECK-NEXT: strh w8, [x19, #394] +; CHECK-NEXT: str w8, [x19, #396] +; CHECK-NEXT: mrs x8, TPIDR2_EL0 +; CHECK-NEXT: cbz x8, .LBB0_2 +; CHECK-NEXT: b .LBB0_1 +; CHECK-NEXT: .LBB0_1: // %save.za +; CHECK-NEXT: bl __arm_tpidr2_save +; CHECK-NEXT: mov x8, xzr +; CHECK-NEXT: msr TPIDR2_EL0, x8 +; CHECK-NEXT: b .LBB0_2 +; CHECK-NEXT: .LBB0_2: // %bb +; CHECK-NEXT: smstart za +; CHECK-NEXT: zero {za} +; CHECK-NEXT: mov w9, #15 // =0xf +; CHECK-NEXT: // implicit-def: $x8 +; CHECK-NEXT: mov w8, w9 +; CHECK-NEXT: mov x9, x8 +; CHECK-NEXT: incd x9 +; CHECK-NEXT: mov w0, w9 +; CHECK-NEXT: // implicit-def: $x9 +; CHECK-NEXT: mov w9, w0 +; CHECK-NEXT: and x14, x9, #0x70 +; CHECK-NEXT: str x14, [x19, #16] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x14 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #24] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x14 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #32] // 8-byte Folded Spill +; CHECK-NEXT: addvl x9, x8, #1 +; CHECK-NEXT: mov w0, w9 +; CHECK-NEXT: // implicit-def: $x9 +; CHECK-NEXT: mov w9, w0 +; CHECK-NEXT: and x10, x9, #0x3f0 +; CHECK-NEXT: str x10, [x19, #40] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x10 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #48] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x10 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #56] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x14 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #64] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x14 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #72] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x10 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #80] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x10 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #88] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x14 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #96] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x14 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #104] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x10 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #112] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x10 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #120] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x14 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #128] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x14 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #136] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x10 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #144] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x10 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: str x9, [x19, #152] // 8-byte Folded Spill +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, #16 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, #16 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, #16 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, #16 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, #16 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, x14 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x9, x9, #16 +; CHECK-NEXT: mov sp, x9 +; CHECK-NEXT: addvl x9, x8, #2 +; CHECK-NEXT: mov w0, w9 +; CHECK-NEXT: // implicit-def: $x9 +; CHECK-NEXT: mov w9, w0 +; CHECK-NEXT: and x9, x9, #0x7f0 +; CHECK-NEXT: mov x10, sp +; CHECK-NEXT: subs x10, x10, x9 +; CHECK-NEXT: and x10, x10, #0xffffffffffffffe0 +; CHECK-NEXT: mov sp, x10 +; CHECK-NEXT: mov x2, sp +; CHECK-NEXT: subs x10, x2, #16 +; CHECK-NEXT: mov sp, x10 +; CHECK-NEXT: str x10, [x19, #160] // 8-byte Folded Spill +; CHECK-NEXT: mov x10, sp +; CHECK-NEXT: subs x11, x10, x14 +; CHECK-NEXT: mov sp, x11 +; CHECK-NEXT: mov x10, x11 +; CHECK-NEXT: str x10, [x19, #168] // 8-byte Folded Spill +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: subs x10, x0, #16 +; CHECK-NEXT: mov sp, x10 +; CHECK-NEXT: str x10, [x19, #176] // 8-byte Folded Spill +; CHECK-NEXT: mov x17, sp +; CHECK-NEXT: subs x10, x17, #16 +; CHECK-NEXT: mov sp, x10 +; CHECK-NEXT: str x10, [x19, #184] // 8-byte Folded Spill +; CHECK-NEXT: mov x10, sp +; CHECK-NEXT: subs x10, x10, x14 +; CHECK-NEXT: str x10, [x19, #360] // 8-byte Folded Spill +; CHECK-NEXT: mov sp, x10 +; CHECK-NEXT: str x10, [x19, #192] // 8-byte Folded Spill +; CHECK-NEXT: mov x15, sp +; CHECK-NEXT: subs x10, x15, #16 +; CHECK-NEXT: mov sp, x10 +; CHECK-NEXT: str x10, [x19, #200] // 8-byte Folded Spill +; CHECK-NEXT: mov x13, sp +; CHECK-NEXT: subs x10, x13, #16 +; CHECK-NEXT: mov sp, x10 +; CHECK-NEXT: str x10, [x19, #208] // 8-byte Folded Spill +; CHECK-NEXT: incw x8 +; CHECK-NEXT: mov w1, w8 +; CHECK-NEXT: // implicit-def: $x8 +; CHECK-NEXT: mov w8, w1 +; CHECK-NEXT: and x12, x8, #0xf0 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: subs x10, x8, x12 +; CHECK-NEXT: mov sp, x10 +; CHECK-NEXT: mov x8, x10 +; CHECK-NEXT: str x8, [x19, #216] // 8-byte Folded Spill +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: subs x8, x8, x12 +; CHECK-NEXT: str x8, [x19, #368] // 8-byte Folded Spill +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: str x8, [x19, #224] // 8-byte Folded Spill +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: subs x8, x8, x9 +; CHECK-NEXT: and x8, x8, #0xffffffffffffffe0 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: str x8, [x19, #232] // 8-byte Folded Spill +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: subs x8, x8, x9 +; CHECK-NEXT: and x8, x8, #0xffffffffffffffe0 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: str x8, [x19, #240] // 8-byte Folded Spill +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #336] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #344] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x24, sp +; CHECK-NEXT: subs x8, x24, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x7, sp +; CHECK-NEXT: subs x8, x7, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x27, sp +; CHECK-NEXT: subs x8, x27, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x26, sp +; CHECK-NEXT: subs x8, x26, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x1, sp +; CHECK-NEXT: subs x8, x1, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: subs x8, x9, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x20, sp +; CHECK-NEXT: subs x8, x20, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x16, sp +; CHECK-NEXT: subs x8, x16, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #248] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x5, sp +; CHECK-NEXT: subs x8, x5, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x12, sp +; CHECK-NEXT: subs x8, x12, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x22, sp +; CHECK-NEXT: subs x8, x22, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x25, sp +; CHECK-NEXT: subs x8, x25, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x30, sp +; CHECK-NEXT: subs x8, x30, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #296] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #328] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #264] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #256] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #272] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #312] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #280] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #304] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x6, sp +; CHECK-NEXT: subs x8, x6, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x21, sp +; CHECK-NEXT: subs x8, x21, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: str x8, [x19, #352] // 8-byte Folded Spill +; CHECK-NEXT: subs x8, x8, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x28, sp +; CHECK-NEXT: subs x8, x28, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: subs x4, x8, x14 +; CHECK-NEXT: mov sp, x4 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: subs x3, x8, x14 +; CHECK-NEXT: mov sp, x3 +; CHECK-NEXT: mov x23, sp +; CHECK-NEXT: subs x8, x23, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x18, sp +; CHECK-NEXT: subs x8, x18, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov x14, sp +; CHECK-NEXT: subs x8, x14, #16 +; CHECK-NEXT: mov sp, x8 +; CHECK-NEXT: mov w8, wzr +; CHECK-NEXT: sturb w8, [x9, #-16] +; CHECK-NEXT: ldr x9, [x19, #248] // 8-byte Folded Reload +; CHECK-NEXT: sturb w8, [x9, #-16] +; CHECK-NEXT: ldr x9, [x19, #296] // 8-byte Folded Reload +; CHECK-NEXT: sturb w8, [x30, #-16] +; CHECK-NEXT: mov x8, xzr +; CHECK-NEXT: str x8, [x19, #376] // 8-byte Folded Spill +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldur x8, [x20, #-16] +; CHECK-NEXT: ldur x9, [x27, #-16] +; CHECK-NEXT: add x30, x8, x9, lsl #2 +; CHECK-NEXT: ldur x8, [x1, #-16] +; CHECK-NEXT: subs x8, x8, #1 +; CHECK-NEXT: ldur x9, [x16, #-16] +; CHECK-NEXT: mul x8, x8, x9 +; CHECK-NEXT: ldr x9, [x19, #328] // 8-byte Folded Reload +; CHECK-NEXT: add x30, x30, x8, lsl #2 +; CHECK-NEXT: ldr x8, [x19, #296] // 8-byte Folded Reload +; CHECK-NEXT: stur x30, [x8, #-16] +; CHECK-NEXT: ldr x8, [x19, #376] // 8-byte Folded Reload +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldur x8, [x5, #-16] +; CHECK-NEXT: ldur x9, [x26, #-16] +; CHECK-NEXT: add x30, x8, x9, lsl #2 +; CHECK-NEXT: ldur x8, [x1, #-16] +; CHECK-NEXT: subs x8, x8, #1 +; CHECK-NEXT: ldur x9, [x12, #-16] +; CHECK-NEXT: mul x8, x8, x9 +; CHECK-NEXT: ldr x9, [x19, #264] // 8-byte Folded Reload +; CHECK-NEXT: add x30, x30, x8, lsl #2 +; CHECK-NEXT: ldr x8, [x19, #328] // 8-byte Folded Reload +; CHECK-NEXT: stur x30, [x8, #-16] +; CHECK-NEXT: ldr x8, [x19, #376] // 8-byte Folded Reload +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldur x8, [x22, #-16] +; CHECK-NEXT: ldur x9, [x27, #-16] +; CHECK-NEXT: add x30, x8, x9, lsl #2 +; CHECK-NEXT: ldur x8, [x26, #-16] +; CHECK-NEXT: subs x8, x8, #1 +; CHECK-NEXT: ldur x9, [x25, #-16] +; CHECK-NEXT: mul x8, x8, x9 +; CHECK-NEXT: ldr x9, [x19, #256] // 8-byte Folded Reload +; CHECK-NEXT: add x30, x30, x8, lsl #2 +; CHECK-NEXT: ldr x8, [x19, #264] // 8-byte Folded Reload +; CHECK-NEXT: stur x30, [x8, #-16] +; CHECK-NEXT: ldr x8, [x19, #272] // 8-byte Folded Reload +; CHECK-NEXT: mov w30, #32 // =0x20 +; CHECK-NEXT: // kill: def $lr killed $w30 +; CHECK-NEXT: stur x30, [x9, #-16] +; CHECK-NEXT: ldr x9, [x19, #312] // 8-byte Folded Reload +; CHECK-NEXT: stur x30, [x8, #-16] +; CHECK-NEXT: ldr x8, [x19, #376] // 8-byte Folded Reload +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldur x8, [x1, #-16] +; CHECK-NEXT: lsl x8, x8, #5 +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldr x9, [x19, #280] // 8-byte Folded Reload +; CHECK-NEXT: ldr x8, [x19, #376] // 8-byte Folded Reload +; CHECK-NEXT: stur x30, [x16, #-16] +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldur x8, [x27, #-16] +; CHECK-NEXT: subs x8, x8, #1 +; CHECK-NEXT: lsr x8, x8, #5 +; CHECK-NEXT: add x8, x8, #1 +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldur x8, [x20, #-16] +; CHECK-NEXT: str x8, [x19, #288] // 8-byte Folded Spill +; CHECK-NEXT: ldr x8, [x19, #312] // 8-byte Folded Reload +; CHECK-NEXT: ldur x9, [x9, #-16] +; CHECK-NEXT: ldur x8, [x8, #-16] +; CHECK-NEXT: mul x9, x9, x8 +; CHECK-NEXT: ldr x8, [x19, #288] // 8-byte Folded Reload +; CHECK-NEXT: add x8, x8, x9, lsl #2 +; CHECK-NEXT: ldr x9, [x19, #296] // 8-byte Folded Reload +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldr x9, [x19, #304] // 8-byte Folded Reload +; CHECK-NEXT: ldr x8, [x19, #376] // 8-byte Folded Reload +; CHECK-NEXT: stur x30, [x12, #-16] +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldur x8, [x26, #-16] +; CHECK-NEXT: subs x8, x8, #1 +; CHECK-NEXT: lsr x8, x8, #5 +; CHECK-NEXT: add x8, x8, #1 +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldur x8, [x5, #-16] +; CHECK-NEXT: str x8, [x19, #320] // 8-byte Folded Spill +; CHECK-NEXT: ldr x8, [x19, #312] // 8-byte Folded Reload +; CHECK-NEXT: ldur x9, [x9, #-16] +; CHECK-NEXT: ldur x8, [x8, #-16] +; CHECK-NEXT: mul x9, x9, x8 +; CHECK-NEXT: ldr x8, [x19, #320] // 8-byte Folded Reload +; CHECK-NEXT: add x8, x8, x9, lsl #2 +; CHECK-NEXT: ldr x9, [x19, #328] // 8-byte Folded Reload +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldr x9, [x19, #352] // 8-byte Folded Reload +; CHECK-NEXT: ldr x8, [x19, #376] // 8-byte Folded Reload +; CHECK-NEXT: stur x8, [x6, #-16] +; CHECK-NEXT: stur x8, [x6, #-16] +; CHECK-NEXT: stur x8, [x21, #-16] +; CHECK-NEXT: stur x8, [x21, #-16] +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldur x8, [x27, #-16] +; CHECK-NEXT: ldur x9, [x21, #-16] +; CHECK-NEXT: subs x8, x8, x9 +; CHECK-NEXT: ldr x9, [x19, #336] // 8-byte Folded Reload +; CHECK-NEXT: stur x8, [x9, #-16] +; CHECK-NEXT: ldr x8, [x19, #344] // 8-byte Folded Reload +; CHECK-NEXT: stur x30, [x8, #-16] +; CHECK-NEXT: ldr x8, [x19, #352] // 8-byte Folded Reload +; CHECK-NEXT: ldur x9, [x9, #-16] +; CHECK-NEXT: stur x9, [x8, #-16] +; CHECK-NEXT: ldr x8, [x19, #376] // 8-byte Folded Reload +; CHECK-NEXT: stur x8, [x28, #-16] +; CHECK-NEXT: ldur x8, [x26, #-16] +; CHECK-NEXT: ldur x9, [x6, #-16] +; CHECK-NEXT: subs x8, x8, x9 +; CHECK-NEXT: ldr x9, [x19, #360] // 8-byte Folded Reload +; CHECK-NEXT: stur x8, [x24, #-16] +; CHECK-NEXT: ldr x8, [x19, #368] // 8-byte Folded Reload +; CHECK-NEXT: stur x30, [x7, #-16] +; CHECK-NEXT: ldr x7, [x19, #376] // 8-byte Folded Reload +; CHECK-NEXT: ldur x24, [x24, #-16] +; CHECK-NEXT: stur x24, [x28, #-16] +; CHECK-NEXT: ldur x24, [x21, #-16] +; CHECK-NEXT: ldur x27, [x27, #-16] +; CHECK-NEXT: whilelt pn8.s, x24, x27, vlx2 +; CHECK-NEXT: str pn8, [x4] +; CHECK-NEXT: ldur x24, [x6, #-16] +; CHECK-NEXT: ldur x26, [x26, #-16] +; CHECK-NEXT: whilelt pn8.s, x24, x26, vlx2 +; CHECK-NEXT: str pn8, [x3] +; CHECK-NEXT: stur x7, [x23, #-16] +; CHECK-NEXT: ldur x22, [x22, #-16] +; CHECK-NEXT: ldur x24, [x21, #-16] +; CHECK-NEXT: add x22, x22, x24, lsl #2 +; CHECK-NEXT: ldur x24, [x6, #-16] +; CHECK-NEXT: ldur x25, [x25, #-16] +; CHECK-NEXT: mul x24, x24, x25 +; CHECK-NEXT: add x22, x22, x24, lsl #2 +; CHECK-NEXT: stur x22, [x23, #-16] +; CHECK-NEXT: zero {za} +; CHECK-NEXT: stur x7, [x18, #-16] +; CHECK-NEXT: ldur x20, [x20, #-16] +; CHECK-NEXT: ldur x21, [x21, #-16] +; CHECK-NEXT: ldur x22, [x1, #-16] +; CHECK-NEXT: mul x21, x21, x22 +; CHECK-NEXT: add x20, x20, x21, lsl #2 +; CHECK-NEXT: stur x20, [x18, #-16] +; CHECK-NEXT: stur x7, [x14, #-16] +; CHECK-NEXT: ldur x5, [x5, #-16] +; CHECK-NEXT: ldur x6, [x6, #-16] +; CHECK-NEXT: ldur x7, [x1, #-16] +; CHECK-NEXT: mul x6, x6, x7 +; CHECK-NEXT: add x5, x5, x6, lsl #2 +; CHECK-NEXT: stur x5, [x14, #-16] +; CHECK-NEXT: ldur x1, [x1, #-16] +; CHECK-NEXT: ldr p1, [x4] +; CHECK-NEXT: ldur x18, [x18, #-16] +; CHECK-NEXT: ldur x16, [x16, #-16] +; CHECK-NEXT: lsr x16, x16, #2 +; CHECK-NEXT: ldr p0, [x3] +; CHECK-NEXT: ldur x14, [x14, #-16] +; CHECK-NEXT: ldur x12, [x12, #-16] +; CHECK-NEXT: lsr x12, x12, #2 +; CHECK-NEXT: stur x1, [x2, #-16] +; CHECK-NEXT: str p1, [x11] +; CHECK-NEXT: stur x18, [x0, #-16] +; CHECK-NEXT: stur x16, [x17, #-16] +; CHECK-NEXT: str p0, [x9] +; CHECK-NEXT: stur x14, [x15, #-16] +; CHECK-NEXT: stur x12, [x13, #-16] +; CHECK-NEXT: ldr p0, [x11] +; CHECK-NEXT: mov p8.b, p0.b +; CHECK-NEXT: pext { p3.s, p4.s }, pn8[0] +; CHECK-NEXT: mov p0.b, p3.b +; CHECK-NEXT: ptrue p2.s +; CHECK-NEXT: and p0.b, p0/z, p0.b, p2.b +; CHECK-NEXT: mov p1.b, p4.b +; CHECK-NEXT: and p1.b, p1/z, p1.b, p2.b +; CHECK-NEXT: mov x11, x10 +; CHECK-NEXT: incd x11 +; CHECK-NEXT: str p1, [x11] +; CHECK-NEXT: str p0, [x10] +; CHECK-NEXT: ldr p0, [x9] +; CHECK-NEXT: mov p8.b, p0.b +; CHECK-NEXT: pext { p3.s, p4.s }, pn8[0] +; CHECK-NEXT: mov p0.b, p3.b +; CHECK-NEXT: and p0.b, p0/z, p0.b, p2.b +; CHECK-NEXT: mov p1.b, p4.b +; CHECK-NEXT: and p1.b, p1/z, p1.b, p2.b +; CHECK-NEXT: mov x9, x8 +; CHECK-NEXT: incd x9 +; CHECK-NEXT: str p1, [x9] +; CHECK-NEXT: str p0, [x8] +; CHECK-NEXT: b .LBB0_3 +; CHECK-NEXT: .LBB0_3: // %bb178 +; CHECK-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: ldr x9, [x19, #160] // 8-byte Folded Reload +; CHECK-NEXT: ldr x8, [x19, #56] // 8-byte Folded Reload +; CHECK-NEXT: ldr x10, [x19, #48] // 8-byte Folded Reload +; CHECK-NEXT: ldr x11, [x19, #32] // 8-byte Folded Reload +; CHECK-NEXT: ldr x12, [x19, #24] // 8-byte Folded Reload +; CHECK-NEXT: ldr x13, [x19, #240] // 8-byte Folded Reload +; CHECK-NEXT: ldr x14, [x19, #232] // 8-byte Folded Reload +; CHECK-NEXT: ldr x17, [x19, #88] // 8-byte Folded Reload +; CHECK-NEXT: ldr x18, [x19, #80] // 8-byte Folded Reload +; CHECK-NEXT: ldr x0, [x19, #72] // 8-byte Folded Reload +; CHECK-NEXT: ldr x1, [x19, #64] // 8-byte Folded Reload +; CHECK-NEXT: ldr x2, [x19, #216] // 8-byte Folded Reload +; CHECK-NEXT: ldr x3, [x19, #120] // 8-byte Folded Reload +; CHECK-NEXT: ldr x4, [x19, #112] // 8-byte Folded Reload +; CHECK-NEXT: ldr x5, [x19, #104] // 8-byte Folded Reload +; CHECK-NEXT: ldr x6, [x19, #96] // 8-byte Folded Reload +; CHECK-NEXT: ldr x7, [x19, #224] // 8-byte Folded Reload +; CHECK-NEXT: ldr x20, [x19, #152] // 8-byte Folded Reload +; CHECK-NEXT: ldr x21, [x19, #144] // 8-byte Folded Reload +; CHECK-NEXT: ldr x22, [x19, #136] // 8-byte Folded Reload +; CHECK-NEXT: ldr x23, [x19, #128] // 8-byte Folded Reload +; CHECK-NEXT: ldr x16, [x19, #200] // 8-byte Folded Reload +; CHECK-NEXT: ldr x15, [x19, #208] // 8-byte Folded Reload +; CHECK-NEXT: ldr x24, [x19, #192] // 8-byte Folded Reload +; CHECK-NEXT: ldr x26, [x19, #176] // 8-byte Folded Reload +; CHECK-NEXT: ldr x25, [x19, #184] // 8-byte Folded Reload +; CHECK-NEXT: ldr x27, [x19, #168] // 8-byte Folded Reload +; CHECK-NEXT: ldr p0, [x27] +; CHECK-NEXT: ldr x27, [x26] +; CHECK-NEXT: mov p8.b, p0.b +; CHECK-NEXT: ld1w { z16.s, z24.s }, pn8/z, [x27] +; CHECK-NEXT: mov z0.d, z16.d +; CHECK-NEXT: mov z1.d, z24.d +; CHECK-NEXT: ptrue p2.s +; CHECK-NEXT: str p2, [x29, #-1, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: st1w { z1.s }, p2, [x14, #1, mul vl] +; CHECK-NEXT: st1w { z0.s }, p2, [x14] +; CHECK-NEXT: ldr x27, [x25] +; CHECK-NEXT: ldr x25, [x26] +; CHECK-NEXT: add x25, x25, x27, lsl #2 +; CHECK-NEXT: str x25, [x26] +; CHECK-NEXT: ldr p0, [x24] +; CHECK-NEXT: ldr x24, [x16] +; CHECK-NEXT: mov p8.b, p0.b +; CHECK-NEXT: ld1w { z16.s, z24.s }, pn8/z, [x24] +; CHECK-NEXT: mov z0.d, z16.d +; CHECK-NEXT: mov z1.d, z24.d +; CHECK-NEXT: st1w { z1.s }, p2, [x13, #1, mul vl] +; CHECK-NEXT: st1w { z0.s }, p2, [x13] +; CHECK-NEXT: ldr x24, [x15] +; CHECK-NEXT: ldr x15, [x16] +; CHECK-NEXT: add x15, x15, x24, lsl #2 +; CHECK-NEXT: str x15, [x16] +; CHECK-NEXT: mov x16, x2 +; CHECK-NEXT: incd x16 +; CHECK-NEXT: ldr p1, [x2] +; CHECK-NEXT: mov x15, x7 +; CHECK-NEXT: incd x15 +; CHECK-NEXT: ldr p0, [x7] +; CHECK-NEXT: ld1w { z1.s }, p2/z, [x14] +; CHECK-NEXT: ld1w { z0.s }, p2/z, [x13] +; CHECK-NEXT: str p1, [x23] +; CHECK-NEXT: str p0, [x22] +; CHECK-NEXT: st1w { z1.s }, p2, [x21] +; CHECK-NEXT: st1w { z0.s }, p2, [x20] +; CHECK-NEXT: ldr p0, [x23] +; CHECK-NEXT: ldr p1, [x22] +; CHECK-NEXT: ld1w { z0.s }, p2/z, [x21] +; CHECK-NEXT: ld1w { z1.s }, p2/z, [x20] +; CHECK-NEXT: fmopa za0.s, p0/m, p1/m, z0.s, z1.s +; CHECK-NEXT: ldr p1, [x16] +; CHECK-NEXT: ldr p0, [x7] +; CHECK-NEXT: ld1w { z1.s }, p2/z, [x14, #1, mul vl] +; CHECK-NEXT: ld1w { z0.s }, p2/z, [x13] +; CHECK-NEXT: str p1, [x6] +; CHECK-NEXT: str p0, [x5] +; CHECK-NEXT: st1w { z1.s }, p2, [x4] +; CHECK-NEXT: st1w { z0.s }, p2, [x3] +; CHECK-NEXT: ldr p0, [x6] +; CHECK-NEXT: ldr p1, [x5] +; CHECK-NEXT: ld1w { z0.s }, p2/z, [x4] +; CHECK-NEXT: ld1w { z1.s }, p2/z, [x3] +; CHECK-NEXT: fmopa za1.s, p0/m, p1/m, z0.s, z1.s +; CHECK-NEXT: ldr p1, [x2] +; CHECK-NEXT: ldr p0, [x15] +; CHECK-NEXT: ld1w { z1.s }, p2/z, [x14] +; CHECK-NEXT: ld1w { z0.s }, p2/z, [x13, #1, mul vl] +; CHECK-NEXT: str p1, [x1] +; CHECK-NEXT: str p0, [x0] +; CHECK-NEXT: st1w { z1.s }, p2, [x18] +; CHECK-NEXT: st1w { z0.s }, p2, [x17] +; CHECK-NEXT: ldr p0, [x1] +; CHECK-NEXT: ldr p1, [x0] +; CHECK-NEXT: ld1w { z0.s }, p2/z, [x18] +; CHECK-NEXT: ld1w { z1.s }, p2/z, [x17] +; CHECK-NEXT: fmopa za2.s, p0/m, p1/m, z0.s, z1.s +; CHECK-NEXT: ldr p1, [x16] +; CHECK-NEXT: ldr p0, [x15] +; CHECK-NEXT: ld1w { z1.s }, p2/z, [x14, #1, mul vl] +; CHECK-NEXT: ld1w { z0.s }, p2/z, [x13, #1, mul vl] +; CHECK-NEXT: str p1, [x12] +; CHECK-NEXT: str p0, [x11] +; CHECK-NEXT: st1w { z1.s }, p2, [x10] +; CHECK-NEXT: st1w { z0.s }, p2, [x8] +; CHECK-NEXT: ldr p0, [x12] +; CHECK-NEXT: ldr p1, [x11] +; CHECK-NEXT: ld1w { z0.s }, p2/z, [x10] +; CHECK-NEXT: ld1w { z1.s }, p2/z, [x8] +; CHECK-NEXT: fmopa za3.s, p0/m, p1/m, z0.s, z1.s +; CHECK-NEXT: ldr x8, [x9] +; CHECK-NEXT: subs x8, x8, #1 +; CHECK-NEXT: str x8, [x9] +; CHECK-NEXT: b .LBB0_3 +bb: + %alloca = alloca , align 2 + %alloca1 = alloca , align 2 + %alloca2 = alloca , align 16 + %alloca3 = alloca , align 16 + %alloca4 = alloca , align 2 + %alloca5 = alloca , align 2 + %alloca6 = alloca , align 16 + %alloca7 = alloca , align 16 + %alloca8 = alloca , align 2 + %alloca9 = alloca , align 2 + %alloca10 = alloca , align 16 + %alloca11 = alloca , align 16 + %alloca12 = alloca , align 2 + %alloca13 = alloca , align 2 + %alloca14 = alloca , align 16 + %alloca15 = alloca , align 16 + %alloca16 = alloca i64, align 8 + %alloca17 = alloca i64, align 8 + %alloca18 = alloca ptr, align 8 + %alloca19 = alloca i64, align 8 + %alloca20 = alloca i64, align 8 + %alloca21 = alloca target("aarch64.svcount"), align 2 + %alloca22 = alloca i32, align 4 + %alloca23 = alloca , align 16 + %alloca24 = alloca i64, align 8 + %alloca25 = alloca target("aarch64.svcount"), align 2 + %alloca26 = alloca ptr, align 8 + %alloca27 = alloca i64, align 8 + %alloca28 = alloca target("aarch64.svcount"), align 2 + %alloca29 = alloca ptr, align 8 + %alloca30 = alloca i64, align 8 + %alloca31 = alloca , align 2 + %alloca32 = alloca , align 2 + %alloca33 = alloca , align 16 + %alloca34 = alloca , align 16 + %alloca35 = alloca i64, align 8 + %alloca36 = alloca i64, align 8 + %alloca37 = alloca i64, align 8 + %alloca38 = alloca i64, align 8 + %alloca39 = alloca i64, align 8 + %alloca40 = alloca i64, align 8 + %alloca41 = alloca i64, align 8 + %alloca42 = alloca i8, align 1 + %alloca43 = alloca ptr, align 8 + %alloca44 = alloca i64, align 8 + %alloca45 = alloca i8, align 1 + %alloca46 = alloca ptr, align 8 + %alloca47 = alloca i64, align 8 + %alloca48 = alloca ptr, align 8 + %alloca49 = alloca i64, align 8 + %alloca50 = alloca i8, align 1 + %alloca51 = alloca ptr, align 8 + %alloca52 = alloca ptr, align 8 + %alloca53 = alloca ptr, align 8 + %alloca54 = alloca i64, align 8 + %alloca55 = alloca i64, align 8 + %alloca56 = alloca i64, align 8 + %alloca57 = alloca i64, align 8 + %alloca58 = alloca i64, align 8 + %alloca59 = alloca i64, align 8 + %alloca60 = alloca i64, align 8 + %alloca61 = alloca i64, align 8 + %alloca62 = alloca i64, align 8 + %alloca63 = alloca target("aarch64.svcount"), align 2 + %alloca64 = alloca target("aarch64.svcount"), align 2 + %alloca65 = alloca ptr, align 8 + %alloca66 = alloca ptr, align 8 + %alloca67 = alloca ptr, align 8 + store i8 0, ptr %alloca42, align 1 + store i8 0, ptr %alloca45, align 1 + store i8 0, ptr %alloca50, align 1 + store ptr null, ptr %alloca51, align 8 + %load = load ptr, ptr %alloca43, align 8 + %load68 = load i64, ptr %alloca39, align 8 + %getelementptr = getelementptr inbounds float, ptr %load, i64 %load68 + %load69 = load i64, ptr %alloca41, align 8 + %sub = sub i64 %load69, 1 + %load70 = load i64, ptr %alloca44, align 8 + %mul = mul i64 %sub, %load70 + %getelementptr71 = getelementptr inbounds float, ptr %getelementptr, i64 %mul + store ptr %getelementptr71, ptr %alloca51, align 8 + store ptr null, ptr %alloca52, align 8 + %load72 = load ptr, ptr %alloca46, align 8 + %load73 = load i64, ptr %alloca40, align 8 + %getelementptr74 = getelementptr inbounds float, ptr %load72, i64 %load73 + %load75 = load i64, ptr %alloca41, align 8 + %sub76 = sub i64 %load75, 1 + %load77 = load i64, ptr %alloca47, align 8 + %mul78 = mul i64 %sub76, %load77 + %getelementptr79 = getelementptr inbounds float, ptr %getelementptr74, i64 %mul78 + store ptr %getelementptr79, ptr %alloca52, align 8 + store ptr null, ptr %alloca53, align 8 + %load80 = load ptr, ptr %alloca48, align 8 + %load81 = load i64, ptr %alloca39, align 8 + %getelementptr82 = getelementptr inbounds float, ptr %load80, i64 %load81 + %load83 = load i64, ptr %alloca40, align 8 + %sub84 = sub i64 %load83, 1 + %load85 = load i64, ptr %alloca49, align 8 + %mul86 = mul i64 %sub84, %load85 + %getelementptr87 = getelementptr inbounds float, ptr %getelementptr82, i64 %mul86 + store ptr %getelementptr87, ptr %alloca53, align 8 + store i64 32, ptr %alloca54, align 8 + store i64 32, ptr %alloca55, align 8 + store i64 0, ptr %alloca56, align 8 + %load88 = load i64, ptr %alloca41, align 8 + %mul89 = mul i64 32, %load88 + store i64 %mul89, ptr %alloca56, align 8 + %load90 = load i8, ptr %alloca42, align 1 + %trunc = trunc i8 %load90 to i1 + store i64 32, ptr %alloca44, align 8 + store i64 0, ptr %alloca57, align 8 + %load91 = load i64, ptr %alloca39, align 8 + %sub92 = sub i64 %load91, 1 + %udiv = udiv i64 %sub92, 32 + %add = add i64 %udiv, 1 + store i64 %add, ptr %alloca57, align 8 + %load93 = load ptr, ptr %alloca43, align 8 + %load94 = load i64, ptr %alloca57, align 8 + %load95 = load i64, ptr %alloca56, align 8 + %mul96 = mul i64 %load94, %load95 + %getelementptr97 = getelementptr inbounds float, ptr %load93, i64 %mul96 + store ptr %getelementptr97, ptr %alloca51, align 8 + %load98 = load i8, ptr %alloca45, align 1 + %trunc99 = trunc i8 %load98 to i1 + store i64 32, ptr %alloca47, align 8 + store i64 0, ptr %alloca58, align 8 + %load100 = load i64, ptr %alloca40, align 8 + %sub101 = sub i64 %load100, 1 + %udiv102 = udiv i64 %sub101, 32 + %add103 = add i64 %udiv102, 1 + store i64 %add103, ptr %alloca58, align 8 + %load104 = load ptr, ptr %alloca46, align 8 + %load105 = load i64, ptr %alloca58, align 8 + %load106 = load i64, ptr %alloca56, align 8 + %mul107 = mul i64 %load105, %load106 + %getelementptr108 = getelementptr inbounds float, ptr %load104, i64 %mul107 + store ptr %getelementptr108, ptr %alloca52, align 8 + store i64 0, ptr %alloca59, align 8 + store i64 0, ptr %alloca59, align 8 + %load109 = load i64, ptr %alloca59, align 8 + %load110 = load i64, ptr %alloca40, align 8 + %icmp = icmp ult i64 %load109, %load110 + store i64 0, ptr %alloca60, align 8 + store i64 0, ptr %alloca60, align 8 + %load111 = load i64, ptr %alloca60, align 8 + %load112 = load i64, ptr %alloca39, align 8 + %icmp113 = icmp ult i64 %load111, %load112 + store i64 0, ptr %alloca61, align 8 + %load114 = load i64, ptr %alloca39, align 8 + %load115 = load i64, ptr %alloca60, align 8 + %sub116 = sub i64 %load114, %load115 + store i64 %sub116, ptr %alloca35, align 8 + store i64 32, ptr %alloca36, align 8 + %load117 = load i64, ptr %alloca35, align 8 + %load118 = load i64, ptr %alloca36, align 8 + %icmp119 = icmp ult i64 %load117, %load118 + %load120 = load i64, ptr %alloca35, align 8 + store i64 %load120, ptr %alloca61, align 8 + store i64 0, ptr %alloca62, align 8 + %load121 = load i64, ptr %alloca40, align 8 + %load122 = load i64, ptr %alloca59, align 8 + %sub123 = sub i64 %load121, %load122 + store i64 %sub123, ptr %alloca37, align 8 + store i64 32, ptr %alloca38, align 8 + %load124 = load i64, ptr %alloca37, align 8 + %load125 = load i64, ptr %alloca38, align 8 + %icmp126 = icmp ult i64 %load124, %load125 + %load127 = load i64, ptr %alloca37, align 8 + store i64 %load127, ptr %alloca62, align 8 + %load128 = load i64, ptr %alloca60, align 8 + %load129 = load i64, ptr %alloca39, align 8 + %call = call target("aarch64.svcount") @llvm.aarch64.sve.whilelt.c32(i64 %load128, i64 %load129, i32 2) + store target("aarch64.svcount") %call, ptr %alloca63, align 2 + %load130 = load i64, ptr %alloca59, align 8 + %load131 = load i64, ptr %alloca40, align 8 + %call132 = call target("aarch64.svcount") @llvm.aarch64.sve.whilelt.c32(i64 %load130, i64 %load131, i32 2) + store target("aarch64.svcount") %call132, ptr %alloca64, align 2 + store ptr null, ptr %alloca65, align 8 + %load133 = load ptr, ptr %alloca48, align 8 + %load134 = load i64, ptr %alloca60, align 8 + %getelementptr135 = getelementptr inbounds float, ptr %load133, i64 %load134 + %load136 = load i64, ptr %alloca59, align 8 + %load137 = load i64, ptr %alloca49, align 8 + %mul138 = mul i64 %load136, %load137 + %getelementptr139 = getelementptr inbounds float, ptr %getelementptr135, i64 %mul138 + store ptr %getelementptr139, ptr %alloca65, align 8 + call void @llvm.aarch64.sme.zero(i32 255) + store ptr null, ptr %alloca66, align 8 + %load140 = load i8, ptr %alloca42, align 1 + %trunc141 = trunc i8 %load140 to i1 + %load142 = load ptr, ptr %alloca43, align 8 + %load143 = load i64, ptr %alloca60, align 8 + %load144 = load i64, ptr %alloca41, align 8 + %mul145 = mul i64 %load143, %load144 + %getelementptr146 = getelementptr inbounds float, ptr %load142, i64 %mul145 + store ptr %getelementptr146, ptr %alloca66, align 8 + store ptr null, ptr %alloca67, align 8 + %load147 = load i8, ptr %alloca45, align 1 + %trunc148 = trunc i8 %load147 to i1 + %load149 = load ptr, ptr %alloca46, align 8 + %load150 = load i64, ptr %alloca59, align 8 + %load151 = load i64, ptr %alloca41, align 8 + %mul152 = mul i64 %load150, %load151 + %getelementptr153 = getelementptr inbounds float, ptr %load149, i64 %mul152 + store ptr %getelementptr153, ptr %alloca67, align 8 + %load154 = load i64, ptr %alloca41, align 8 + %load155 = load target("aarch64.svcount"), ptr %alloca63, align 2 + %load156 = load ptr, ptr %alloca66, align 8 + %load157 = load i64, ptr %alloca44, align 8 + %udiv158 = udiv i64 %load157, 4 + %load159 = load target("aarch64.svcount"), ptr %alloca64, align 2 + %load160 = load ptr, ptr %alloca67, align 8 + %load161 = load i64, ptr %alloca47, align 8 + %udiv162 = udiv i64 %load161, 4 + store i64 %load154, ptr %alloca24, align 8 + store target("aarch64.svcount") %load155, ptr %alloca25, align 2 + store ptr %load156, ptr %alloca26, align 8 + store i64 %udiv158, ptr %alloca27, align 8 + store target("aarch64.svcount") %load159, ptr %alloca28, align 2 + store ptr %load160, ptr %alloca29, align 8 + store i64 %udiv162, ptr %alloca30, align 8 + %load163 = load target("aarch64.svcount"), ptr %alloca25, align 2 + %call164 = call { , } @llvm.aarch64.sve.pext.x2.nxv4i1(target("aarch64.svcount") %load163, i32 0) + %extractvalue = extractvalue { , } %call164, 0 + %call165 = call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( %extractvalue) + %call166 = call @llvm.vector.insert.nxv32i1.nxv16i1( poison, %call165, i64 0) + %extractvalue167 = extractvalue { , } %call164, 1 + %call168 = call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( %extractvalue167) + %call169 = call @llvm.vector.insert.nxv32i1.nxv16i1( %call166, %call168, i64 16) + store %call169, ptr %alloca31, align 2 + %load170 = load target("aarch64.svcount"), ptr %alloca28, align 2 + %call171 = call { , } @llvm.aarch64.sve.pext.x2.nxv4i1(target("aarch64.svcount") %load170, i32 0) + %extractvalue172 = extractvalue { , } %call171, 0 + %call173 = call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( %extractvalue172) + %call174 = call @llvm.vector.insert.nxv32i1.nxv16i1( poison, %call173, i64 0) + %extractvalue175 = extractvalue { , } %call171, 1 + %call176 = call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( %extractvalue175) + %call177 = call @llvm.vector.insert.nxv32i1.nxv16i1( %call174, %call176, i64 16) + store %call177, ptr %alloca32, align 2 + br label %bb178 + +bb178: ; preds = %bb178, %bb + %load179 = load i64, ptr %alloca24, align 8 + %icmp180 = icmp ugt i64 %load179, 0 + %load181 = load target("aarch64.svcount"), ptr %alloca25, align 2 + %load182 = load ptr, ptr %alloca26, align 8 + %call183 = call { , } @llvm.aarch64.sve.ld1.pn.x2.nxv4f32(target("aarch64.svcount") %load181, ptr %load182) + %extractvalue184 = extractvalue { , } %call183, 0 + %call185 = call @llvm.vector.insert.nxv8f32.nxv4f32( poison, %extractvalue184, i64 0) + %extractvalue186 = extractvalue { , } %call183, 1 + %call187 = call @llvm.vector.insert.nxv8f32.nxv4f32( %call185, %extractvalue186, i64 4) + store %call187, ptr %alloca33, align 16 + %load188 = load i64, ptr %alloca27, align 8 + %load189 = load ptr, ptr %alloca26, align 8 + %getelementptr190 = getelementptr inbounds float, ptr %load189, i64 %load188 + store ptr %getelementptr190, ptr %alloca26, align 8 + %load191 = load target("aarch64.svcount"), ptr %alloca28, align 2 + %load192 = load ptr, ptr %alloca29, align 8 + %call193 = call { , } @llvm.aarch64.sve.ld1.pn.x2.nxv4f32(target("aarch64.svcount") %load191, ptr %load192) + %extractvalue194 = extractvalue { , } %call193, 0 + %call195 = call @llvm.vector.insert.nxv8f32.nxv4f32( poison, %extractvalue194, i64 0) + %extractvalue196 = extractvalue { , } %call193, 1 + %call197 = call @llvm.vector.insert.nxv8f32.nxv4f32( %call195, %extractvalue196, i64 4) + store %call197, ptr %alloca34, align 16 + %load198 = load i64, ptr %alloca30, align 8 + %load199 = load ptr, ptr %alloca29, align 8 + %getelementptr200 = getelementptr inbounds float, ptr %load199, i64 %load198 + store ptr %getelementptr200, ptr %alloca29, align 8 + %load201 = load , ptr %alloca31, align 2 + %call202 = call @llvm.vector.extract.nxv16i1.nxv32i1( %load201, i64 0) + %load203 = load , ptr %alloca32, align 2 + %call204 = call @llvm.vector.extract.nxv16i1.nxv32i1( %load203, i64 0) + %load205 = load , ptr %alloca33, align 16 + %call206 = call @llvm.vector.extract.nxv4f32.nxv8f32( %load205, i64 0) + %load207 = load , ptr %alloca34, align 16 + %call208 = call @llvm.vector.extract.nxv4f32.nxv8f32( %load207, i64 0) + store %call202, ptr %alloca12, align 2 + store %call204, ptr %alloca13, align 2 + store %call206, ptr %alloca14, align 16 + store %call208, ptr %alloca15, align 16 + %load209 = load , ptr %alloca12, align 2 + %load210 = load , ptr %alloca13, align 2 + %load211 = load , ptr %alloca14, align 16 + %load212 = load , ptr %alloca15, align 16 + %call213 = call @llvm.aarch64.sve.convert.from.svbool.nxv4i1( %load209) + %call214 = call @llvm.aarch64.sve.convert.from.svbool.nxv4i1( %load210) + call void @llvm.aarch64.sme.mopa.nxv4f32(i32 0, %call213, %call214, %load211, %load212) + %load215 = load , ptr %alloca31, align 2 + %call216 = call @llvm.vector.extract.nxv16i1.nxv32i1( %load215, i64 16) + %load217 = load , ptr %alloca32, align 2 + %call218 = call @llvm.vector.extract.nxv16i1.nxv32i1( %load217, i64 0) + %load219 = load , ptr %alloca33, align 16 + %call220 = call @llvm.vector.extract.nxv4f32.nxv8f32( %load219, i64 4) + %load221 = load , ptr %alloca34, align 16 + %call222 = call @llvm.vector.extract.nxv4f32.nxv8f32( %load221, i64 0) + store %call216, ptr %alloca8, align 2 + store %call218, ptr %alloca9, align 2 + store %call220, ptr %alloca10, align 16 + store %call222, ptr %alloca11, align 16 + %load223 = load , ptr %alloca8, align 2 + %load224 = load , ptr %alloca9, align 2 + %load225 = load , ptr %alloca10, align 16 + %load226 = load , ptr %alloca11, align 16 + %call227 = call @llvm.aarch64.sve.convert.from.svbool.nxv4i1( %load223) + %call228 = call @llvm.aarch64.sve.convert.from.svbool.nxv4i1( %load224) + call void @llvm.aarch64.sme.mopa.nxv4f32(i32 1, %call227, %call228, %load225, %load226) + %load229 = load , ptr %alloca31, align 2 + %call230 = call @llvm.vector.extract.nxv16i1.nxv32i1( %load229, i64 0) + %load231 = load , ptr %alloca32, align 2 + %call232 = call @llvm.vector.extract.nxv16i1.nxv32i1( %load231, i64 16) + %load233 = load , ptr %alloca33, align 16 + %call234 = call @llvm.vector.extract.nxv4f32.nxv8f32( %load233, i64 0) + %load235 = load , ptr %alloca34, align 16 + %call236 = call @llvm.vector.extract.nxv4f32.nxv8f32( %load235, i64 4) + store %call230, ptr %alloca4, align 2 + store %call232, ptr %alloca5, align 2 + store %call234, ptr %alloca6, align 16 + store %call236, ptr %alloca7, align 16 + %load237 = load , ptr %alloca4, align 2 + %load238 = load , ptr %alloca5, align 2 + %load239 = load , ptr %alloca6, align 16 + %load240 = load , ptr %alloca7, align 16 + %call241 = call @llvm.aarch64.sve.convert.from.svbool.nxv4i1( %load237) + %call242 = call @llvm.aarch64.sve.convert.from.svbool.nxv4i1( %load238) + call void @llvm.aarch64.sme.mopa.nxv4f32(i32 2, %call241, %call242, %load239, %load240) + %load243 = load , ptr %alloca31, align 2 + %call244 = call @llvm.vector.extract.nxv16i1.nxv32i1( %load243, i64 16) + %load245 = load , ptr %alloca32, align 2 + %call246 = call @llvm.vector.extract.nxv16i1.nxv32i1( %load245, i64 16) + %load247 = load , ptr %alloca33, align 16 + %call248 = call @llvm.vector.extract.nxv4f32.nxv8f32( %load247, i64 4) + %load249 = load , ptr %alloca34, align 16 + %call250 = call @llvm.vector.extract.nxv4f32.nxv8f32( %load249, i64 4) + store %call244, ptr %alloca, align 2 + store %call246, ptr %alloca1, align 2 + store %call248, ptr %alloca2, align 16 + store %call250, ptr %alloca3, align 16 + %load251 = load , ptr %alloca, align 2 + %load252 = load , ptr %alloca1, align 2 + %load253 = load , ptr %alloca2, align 16 + %load254 = load , ptr %alloca3, align 16 + %call255 = call @llvm.aarch64.sve.convert.from.svbool.nxv4i1( %load251) + %call256 = call @llvm.aarch64.sve.convert.from.svbool.nxv4i1( %load252) + call void @llvm.aarch64.sme.mopa.nxv4f32(i32 3, %call255, %call256, %load253, %load254) + %load257 = load i64, ptr %alloca24, align 8 + %add258 = add i64 %load257, -1 + store i64 %add258, ptr %alloca24, align 8 + br label %bb178 +} + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare target("aarch64.svcount") @llvm.aarch64.sve.whilelt.c32(i64, i64, i32 immarg) #2 + +; Function Attrs: nocallback nofree nosync nounwind willreturn +declare void @llvm.aarch64.sme.zero(i32 immarg) #3 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare { , } @llvm.aarch64.sve.pext.x2.nxv4i1(target("aarch64.svcount"), i32 immarg) #2 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare @llvm.aarch64.sve.convert.to.svbool.nxv4i1() #2 + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare @llvm.vector.insert.nxv32i1.nxv16i1(, , i64 immarg) #4 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: read) +declare { , } @llvm.aarch64.sve.ld1.pn.x2.nxv4f32(target("aarch64.svcount"), ptr) #5 + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare @llvm.vector.insert.nxv8f32.nxv4f32(, , i64 immarg) #4 + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare @llvm.vector.extract.nxv16i1.nxv32i1(, i64 immarg) #4 + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare @llvm.vector.extract.nxv4f32.nxv8f32(, i64 immarg) #4 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare @llvm.aarch64.sve.convert.from.svbool.nxv4i1() #2 + +; Function Attrs: nocallback nofree nosync nounwind willreturn +declare void @llvm.aarch64.sme.mopa.nxv4f32(i32 immarg, , , , ) #3 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare target("aarch64.svcount") @llvm.aarch64.sve.whilelt.c8(i64, i64, i32 immarg) #2 + +; Function Attrs: nocallback nofree nosync nounwind willreturn +declare { , } @llvm.aarch64.sme.read.hor.vg2.nxv16i8(i32, i32) #3 + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare @llvm.vector.insert.nxv32i8.nxv16i8(, , i64 immarg) #4 + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare @llvm.vector.extract.nxv16i8.nxv32i8(, i64 immarg) #4 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: write) +declare void @llvm.aarch64.sve.st1.pn.x2.nxv16i8(, , target("aarch64.svcount"), ptr) #6 + +attributes #0 = { cold noreturn nounwind } +attributes #1 = { mustprogress noinline optnone ssp uwtable(sync) vscale_range(1,16) "aarch64_new_za" "aarch64_pstate_sm_enabled" "frame-pointer"="non-leaf" "target-features"="+fp-armv8,+fullfp16,+sme,+sme-f64f64,+sme2" } +attributes #2 = { nocallback nofree nosync nounwind willreturn memory(none) } +attributes #3 = { nocallback nofree nosync nounwind willreturn } +attributes #4 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } +attributes #5 = { nocallback nofree nosync nounwind willreturn memory(argmem: read) } +attributes #6 = { nocallback nofree nosync nounwind willreturn memory(argmem: write) } -- GitLab From 12028373020739b388eb2b8141742509f1764e3c Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 14 May 2024 16:09:57 -0400 Subject: [PATCH 276/578] Reapply "[Clang] Unify interface for accessing template arguments as written for class/variable template specializations (#81642)" (#91393) Reapplies #81642, fixing the crash which occurs when running the lldb test suite. --- clang-tools-extra/clangd/AST.cpp | 37 +- .../clangd/SemanticHighlighting.cpp | 13 +- .../include-cleaner/lib/WalkAST.cpp | 13 +- clang/docs/LibASTMatchersReference.html | 364 +++++++++++++----- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/AST/DeclTemplate.h | 226 +++++------ clang/include/clang/AST/RecursiveASTVisitor.h | 27 +- clang/include/clang/ASTMatchers/ASTMatchers.h | 74 ++-- .../clang/ASTMatchers/ASTMatchersInternal.h | 50 ++- .../include/clang/Serialization/ASTBitCodes.h | 2 +- clang/lib/AST/ASTImporter.cpp | 68 ++-- clang/lib/AST/DeclPrinter.cpp | 18 +- clang/lib/AST/DeclTemplate.cpp | 266 ++++++++----- clang/lib/AST/TypePrinter.cpp | 25 +- clang/lib/Index/IndexDecl.cpp | 9 +- clang/lib/Sema/Sema.cpp | 2 +- clang/lib/Sema/SemaTemplate.cpp | 58 ++- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 163 +++----- clang/lib/Serialization/ASTReaderDecl.cpp | 28 +- clang/lib/Serialization/ASTWriterDecl.cpp | 36 +- clang/lib/Tooling/Syntax/BuildTree.cpp | 3 +- clang/test/AST/ast-dump-decl.cpp | 12 +- clang/test/AST/ast-dump-template-decls.cpp | 18 +- clang/test/Index/Core/index-source.cpp | 24 +- clang/test/Index/index-refs.cpp | 1 - clang/tools/libclang/CIndex.cpp | 29 +- .../ASTMatchers/ASTMatchersNodeTest.cpp | 12 - .../ASTMatchers/ASTMatchersTraversalTest.cpp | 92 ++--- 28 files changed, 914 insertions(+), 759 deletions(-) diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index 1b86ea19cf28..fda1e5fdf8d8 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -50,16 +50,11 @@ getTemplateSpecializationArgLocs(const NamedDecl &ND) { if (const ASTTemplateArgumentListInfo *Args = Func->getTemplateSpecializationArgsAsWritten()) return Args->arguments(); - } else if (auto *Cls = - llvm::dyn_cast(&ND)) { + } else if (auto *Cls = llvm::dyn_cast(&ND)) { if (auto *Args = Cls->getTemplateArgsAsWritten()) return Args->arguments(); - } else if (auto *Var = - llvm::dyn_cast(&ND)) { - if (auto *Args = Var->getTemplateArgsAsWritten()) - return Args->arguments(); } else if (auto *Var = llvm::dyn_cast(&ND)) { - if (auto *Args = Var->getTemplateArgsInfo()) + if (auto *Args = Var->getTemplateArgsAsWritten()) return Args->arguments(); } // We return std::nullopt for ClassTemplateSpecializationDecls because it does @@ -270,22 +265,10 @@ std::string printTemplateSpecializationArgs(const NamedDecl &ND) { getTemplateSpecializationArgLocs(ND)) { printTemplateArgumentList(OS, *Args, Policy); } else if (auto *Cls = llvm::dyn_cast(&ND)) { - if (const TypeSourceInfo *TSI = Cls->getTypeAsWritten()) { - // ClassTemplateSpecializationDecls do not contain - // TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we - // create a new argument location list from TypeSourceInfo. - auto STL = TSI->getTypeLoc().getAs(); - llvm::SmallVector ArgLocs; - ArgLocs.reserve(STL.getNumArgs()); - for (unsigned I = 0; I < STL.getNumArgs(); ++I) - ArgLocs.push_back(STL.getArgLoc(I)); - printTemplateArgumentList(OS, ArgLocs, Policy); - } else { - // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST, - // e.g. friend decls. Currently we fallback to Template Arguments without - // location information. - printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy); - } + // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST, + // e.g. friend decls. Currently we fallback to Template Arguments without + // location information. + printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy); } OS.flush(); return TemplateArgs; @@ -453,10 +436,12 @@ bool hasReservedScope(const DeclContext &DC) { } QualType declaredType(const TypeDecl *D) { + ASTContext &Context = D->getASTContext(); if (const auto *CTSD = llvm::dyn_cast(D)) - if (const auto *TSI = CTSD->getTypeAsWritten()) - return TSI->getType(); - return D->getASTContext().getTypeDeclType(D); + if (const auto *Args = CTSD->getTemplateArgsAsWritten()) + return Context.getTemplateSpecializationType( + TemplateName(CTSD->getSpecializedTemplate()), Args->arguments()); + return Context.getTypeDeclType(D); } namespace { diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index 08f99e11ac9b..eb025f21f361 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -693,17 +693,22 @@ public: return true; } + bool + VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D) { + if (auto *Args = D->getTemplateArgsAsWritten()) + H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc()); + return true; + } + bool VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { if (auto *TPL = D->getTemplateParameters()) H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc()); - if (auto *Args = D->getTemplateArgsAsWritten()) - H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc()); return true; } bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) { - if (auto *Args = D->getTemplateArgsInfo()) + if (auto *Args = D->getTemplateArgsAsWritten()) H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc()); return true; } @@ -712,8 +717,6 @@ public: VarTemplatePartialSpecializationDecl *D) { if (auto *TPL = D->getTemplateParameters()) H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc()); - if (auto *Args = D->getTemplateArgsAsWritten()) - H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc()); return true; } diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp index 878067aca017..f7cc9d191236 100644 --- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -267,18 +267,21 @@ public: return true; } - // Report a reference from explicit specializations to the specialized - // template. Implicit ones are filtered out by RAV and explicit instantiations - // are already traversed through typelocs. + // Report a reference from explicit specializations/instantiations to the + // specialized template. Implicit ones are filtered out by RAV. bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) { - if (CTSD->isExplicitSpecialization()) + // if (CTSD->isExplicitSpecialization()) + if (clang::isTemplateExplicitInstantiationOrSpecialization( + CTSD->getTemplateSpecializationKind())) report(CTSD->getLocation(), CTSD->getSpecializedTemplate()->getTemplatedDecl()); return true; } bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) { - if (VTSD->isExplicitSpecialization()) + // if (VTSD->isExplicitSpecialization()) + if (clang::isTemplateExplicitInstantiationOrSpecialization( + VTSD->getTemplateSpecializationKind())) report(VTSD->getLocation(), VTSD->getSpecializedTemplate()->getTemplatedDecl()); return true; diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index bb1b68f6671b..a16b9c44ef0e 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -3546,33 +3546,35 @@ cxxMethodDecl(isConst()) matches A::foo() but not A::bar() -Matcher<CXXMethodDecl>isExplicitObjectMemberFunction -
Matches if the given method declaration declares a member function with an explicit object parameter.
+Matcher<CXXMethodDecl>isCopyAssignmentOperator
+
Matches if the given method declaration declares a copy assignment
+operator.
 
 Given
 struct A {
-  int operator-(this A, int);
-  void fun(this A &&self);
-  static int operator()(int);
-  int operator+(int);
+  A &operator=(const A &);
+  A &operator=(A &&);
 };
 
-cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two methods but not the last two.
+cxxMethodDecl(isCopyAssignmentOperator()) matches the first method but not
+the second one.
 
-Matcher<CXXMethodDecl>isCopyAssignmentOperator -
Matches if the given method declaration declares a copy assignment
-operator.
+Matcher<CXXMethodDecl>isExplicitObjectMemberFunction
+
Matches if the given method declaration declares a member function with an
+explicit object parameter.
 
 Given
 struct A {
-  A &operator=(const A &);
-  A &operator=(A &&);
+ int operator-(this A, int);
+ void fun(this A &&self);
+ static int operator()(int);
+ int operator+(int);
 };
 
-cxxMethodDecl(isCopyAssignmentOperator()) matches the first method but not
-the second one.
+cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two
+methods but not the last two.
 
@@ -6713,7 +6715,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, - Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, + Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -6757,7 +6759,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, - Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, + Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -6985,7 +6987,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, - Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, + Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -7219,7 +7221,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, - Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, + Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -7416,7 +7418,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, - Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, + Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -7620,7 +7622,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, - Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, + Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -7677,7 +7679,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, - Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, + Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -7875,9 +7877,10 @@ int a = b ?: 1; Matcher<ClassTemplateSpecializationDecl>forEachTemplateArgumentMatcher<TemplateArgument> InnerMatcher -
Matches classTemplateSpecialization, templateSpecializationType and
-functionDecl nodes where the template argument matches the inner matcher.
-This matcher may produce multiple matches.
+
Matches templateSpecializationType, class template specialization,
+variable template specialization, and function template specialization
+nodes where the template argument matches the inner matcher. This matcher
+may produce multiple matches.
 
 Given
   template <typename T, unsigned N, unsigned M>
@@ -7899,10 +7902,25 @@ functionDecl(forEachTemplateArgument(refersToType(builtinType())))
 
+Matcher<ClassTemplateSpecializationDecl>hasAnyTemplateArgumentLocMatcher<TemplateArgumentLoc> InnerMatcher +
Matches template specialization `TypeLoc`s, class template specializations,
+variable template specializations, and function template specializations
+that have at least one `TemplateArgumentLoc` matching the given
+`InnerMatcher`.
+
+Given
+  template<typename T> class A {};
+  A<int> a;
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+  hasTypeLoc(loc(asString("int")))))))
+  matches `A<int> a`.
+
+ + Matcher<ClassTemplateSpecializationDecl>hasAnyTemplateArgumentMatcher<TemplateArgument> InnerMatcher -
Matches classTemplateSpecializations, templateSpecializationType and
-functionDecl that have at least one TemplateArgument matching the given
-InnerMatcher.
+
Matches templateSpecializationTypes, class template specializations,
+variable template specializations, and function template specializations
+that have at least one TemplateArgument matching the given InnerMatcher.
 
 Given
   template<typename T> class A {};
@@ -7933,9 +7951,25 @@ classTemplateSpecializationDecl(hasSpecializedTemplate(classTemplateDecl()))
 
+Matcher<ClassTemplateSpecializationDecl>hasTemplateArgumentLocunsigned Index, Matcher<TemplateArgumentLoc> InnerMatcher +
Matches template specialization `TypeLoc`s, class template specializations,
+variable template specializations, and function template specializations
+where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`.
+
+Given
+  template<typename T, typename U> class A {};
+  A<double, int> b;
+  A<int, double> c;
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
+  hasTypeLoc(loc(asString("double")))))))
+  matches `A<double, int> b`, but not `A<int, double> c`.
+
+ + Matcher<ClassTemplateSpecializationDecl>hasTemplateArgumentunsigned N, Matcher<TemplateArgument> InnerMatcher -
Matches classTemplateSpecializations, templateSpecializationType and
-functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
+
Matches templateSpecializationType, class template specializations,
+variable template specializations, and function template specializations
+where the n'th TemplateArgument matches the given InnerMatcher.
 
 Given
   template<typename T, typename U> class A {};
@@ -7953,34 +7987,6 @@ functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
 
-Matcher<ClassTemplateSpecializationDecl>hasTypeLocMatcher<TypeLoc> Inner -
Matches if the type location of a node matches the inner matcher.
-
-Examples:
-  int x;
-declaratorDecl(hasTypeLoc(loc(asString("int"))))
-  matches int x
-
-auto x = int(3);
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
-  matches int(3)
-
-struct Foo { Foo(int, int); };
-auto x = Foo(1, 2);
-cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
-  matches Foo(1, 2)
-
-Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>,
-  Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
-  Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
-  Matcher<CXXUnresolvedConstructExpr>,
-  Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
-  Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
-  Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
-  Matcher<TypedefNameDecl>
-
- - Matcher<ComplexType>hasElementTypeMatcher<Type>
Matches arrays and C99 complex types that have a specific element
 type.
@@ -7996,8 +8002,8 @@ Usable as: Matcher<CompoundLiteralExpr>hasTypeLocMatcher<TypeLoc> Inner
-
Matches if the type location of a node matches the inner matcher.
+Matcher<CompoundLiteralExpr>hasTypeLocMatcher<TypeLoc> Inner
+
Matches if the type location of a node matches the inner matcher.
 
 Examples:
   int x;
@@ -8017,7 +8023,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
   Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
   Matcher<CXXUnresolvedConstructExpr>,
-  Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
+  Matcher<CompoundLiteralExpr>,
   Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
   Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
   Matcher<TypedefNameDecl>
@@ -8066,6 +8072,21 @@ with compoundStmt()
 
+Matcher<DeclRefExpr>hasAnyTemplateArgumentLocMatcher<TemplateArgumentLoc> InnerMatcher +
Matches template specialization `TypeLoc`s, class template specializations,
+variable template specializations, and function template specializations
+that have at least one `TemplateArgumentLoc` matching the given
+`InnerMatcher`.
+
+Given
+  template<typename T> class A {};
+  A<int> a;
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+  hasTypeLoc(loc(asString("int")))))))
+  matches `A<int> a`.
+
+ + Matcher<DeclRefExpr>hasDeclarationMatcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
@@ -8100,9 +8121,10 @@ Usable as: Matcher<DeclRefExpr>hasTemplateArgumentLocunsigned Index, Matcher<TemplateArgumentLoc> InnerMatcher
-
Matches template specialization `TypeLoc`s where the n'th
-`TemplateArgumentLoc` matches the given `InnerMatcher`.
+Matcher<DeclRefExpr>hasTemplateArgumentLocunsigned Index, Matcher<TemplateArgumentLoc> InnerMatcher
+
Matches template specialization `TypeLoc`s, class template specializations,
+variable template specializations, and function template specializations
+where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`.
 
 Given
   template<typename T, typename U> class A {};
@@ -8176,8 +8198,8 @@ declStmt(hasSingleDecl(anything()))
 
-Matcher<DeclaratorDecl>hasTypeLocMatcher<TypeLoc> Inner -
Matches if the type location of a node matches the inner matcher.
+Matcher<DeclaratorDecl>hasTypeLocMatcher<TypeLoc> Inner
+
Matches if the type location of a node matches the inner matcher.
 
 Examples:
   int x;
@@ -8197,7 +8219,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
   Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
   Matcher<CXXUnresolvedConstructExpr>,
-  Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
+  Matcher<CompoundLiteralExpr>,
   Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
   Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
   Matcher<TypedefNameDecl>
@@ -8393,8 +8415,8 @@ actual casts "explicit" casts.)
 
-Matcher<ExplicitCastExpr>hasTypeLocMatcher<TypeLoc> Inner -
Matches if the type location of a node matches the inner matcher.
+Matcher<ExplicitCastExpr>hasTypeLocMatcher<TypeLoc> Inner
+
Matches if the type location of a node matches the inner matcher.
 
 Examples:
   int x;
@@ -8414,7 +8436,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
   Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
   Matcher<CXXUnresolvedConstructExpr>,
-  Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
+  Matcher<CompoundLiteralExpr>,
   Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
   Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
   Matcher<TypedefNameDecl>
@@ -8707,9 +8729,10 @@ Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
 
 
 Matcher<FunctionDecl>forEachTemplateArgumentMatcher<TemplateArgument> InnerMatcher
-
Matches classTemplateSpecialization, templateSpecializationType and
-functionDecl nodes where the template argument matches the inner matcher.
-This matcher may produce multiple matches.
+
Matches templateSpecializationType, class template specialization,
+variable template specialization, and function template specialization
+nodes where the template argument matches the inner matcher. This matcher
+may produce multiple matches.
 
 Given
   template <typename T, unsigned N, unsigned M>
@@ -8778,10 +8801,25 @@ matching y.
 
+Matcher<FunctionDecl>hasAnyTemplateArgumentLocMatcher<TemplateArgumentLoc> InnerMatcher +
Matches template specialization `TypeLoc`s, class template specializations,
+variable template specializations, and function template specializations
+that have at least one `TemplateArgumentLoc` matching the given
+`InnerMatcher`.
+
+Given
+  template<typename T> class A {};
+  A<int> a;
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+  hasTypeLoc(loc(asString("int")))))))
+  matches `A<int> a`.
+
+ + Matcher<FunctionDecl>hasAnyTemplateArgumentMatcher<TemplateArgument> InnerMatcher -
Matches classTemplateSpecializations, templateSpecializationType and
-functionDecl that have at least one TemplateArgument matching the given
-InnerMatcher.
+
Matches templateSpecializationTypes, class template specializations,
+variable template specializations, and function template specializations
+that have at least one TemplateArgument matching the given InnerMatcher.
 
 Given
   template<typename T> class A {};
@@ -8878,9 +8916,25 @@ functionDecl(hasReturnTypeLoc(loc(asString("int"))))
 
+Matcher<FunctionDecl>hasTemplateArgumentLocunsigned Index, Matcher<TemplateArgumentLoc> InnerMatcher +
Matches template specialization `TypeLoc`s, class template specializations,
+variable template specializations, and function template specializations
+where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`.
+
+Given
+  template<typename T, typename U> class A {};
+  A<double, int> b;
+  A<int, double> c;
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
+  hasTypeLoc(loc(asString("double")))))))
+  matches `A<double, int> b`, but not `A<int, double> c`.
+
+ + Matcher<FunctionDecl>hasTemplateArgumentunsigned N, Matcher<TemplateArgument> InnerMatcher -
Matches classTemplateSpecializations, templateSpecializationType and
-functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
+
Matches templateSpecializationType, class template specializations,
+variable template specializations, and function template specializations
+where the n'th TemplateArgument matches the given InnerMatcher.
 
 Given
   template<typename T, typename U> class A {};
@@ -9473,8 +9527,8 @@ matching y.
 
-Matcher<ObjCPropertyDecl>hasTypeLocMatcher<TypeLoc> Inner -
Matches if the type location of a node matches the inner matcher.
+Matcher<ObjCPropertyDecl>hasTypeLocMatcher<TypeLoc> Inner
+
Matches if the type location of a node matches the inner matcher.
 
 Examples:
   int x;
@@ -9494,7 +9548,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
   Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
   Matcher<CXXUnresolvedConstructExpr>,
-  Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
+  Matcher<CompoundLiteralExpr>,
   Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
   Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
   Matcher<TypedefNameDecl>
@@ -9919,8 +9973,8 @@ Usable as: Matcher<TemplateArgumentLoc>hasTypeLocMatcher<TypeLoc> Inner
-
Matches if the type location of a node matches the inner matcher.
+Matcher<TemplateArgumentLoc>hasTypeLocMatcher<TypeLoc> Inner
+
Matches if the type location of a node matches the inner matcher.
 
 Examples:
   int x;
@@ -9940,7 +9994,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
   Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
   Matcher<CXXUnresolvedConstructExpr>,
-  Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
+  Matcher<CompoundLiteralExpr>,
   Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
   Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
   Matcher<TypedefNameDecl>
@@ -10014,9 +10068,11 @@ matches the specialization of struct A generated by A<X>.
 
-Matcher<TemplateSpecializationTypeLoc>hasAnyTemplateArgumentLocMatcher<TemplateArgumentLoc> InnerMatcher -
Matches template specialization `TypeLoc`s that have at least one
-`TemplateArgumentLoc` matching the given `InnerMatcher`.
+Matcher<TemplateSpecializationTypeLoc>hasAnyTemplateArgumentLocMatcher<TemplateArgumentLoc> InnerMatcher
+
Matches template specialization `TypeLoc`s, class template specializations,
+variable template specializations, and function template specializations
+that have at least one `TemplateArgumentLoc` matching the given
+`InnerMatcher`.
 
 Given
   template<typename T> class A {};
@@ -10027,9 +10083,10 @@ varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
 
-Matcher<TemplateSpecializationTypeLoc>hasTemplateArgumentLocunsigned Index, Matcher<TemplateArgumentLoc> InnerMatcher -
Matches template specialization `TypeLoc`s where the n'th
-`TemplateArgumentLoc` matches the given `InnerMatcher`.
+Matcher<TemplateSpecializationTypeLoc>hasTemplateArgumentLocunsigned Index, Matcher<TemplateArgumentLoc> InnerMatcher
+
Matches template specialization `TypeLoc`s, class template specializations,
+variable template specializations, and function template specializations
+where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`.
 
 Given
   template<typename T, typename U> class A {};
@@ -10041,10 +10098,11 @@ varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
 
-Matcher<TemplateSpecializationType>forEachTemplateArgumentMatcher<TemplateArgument> InnerMatcher -
Matches classTemplateSpecialization, templateSpecializationType and
-functionDecl nodes where the template argument matches the inner matcher.
-This matcher may produce multiple matches.
+Matcher<TemplateSpecializationType>forEachTemplateArgumentMatcher<TemplateArgument> InnerMatcher
+
Matches templateSpecializationType, class template specialization,
+variable template specialization, and function template specialization
+nodes where the template argument matches the inner matcher. This matcher
+may produce multiple matches.
 
 Given
   template <typename T, unsigned N, unsigned M>
@@ -10066,10 +10124,10 @@ functionDecl(forEachTemplateArgument(refersToType(builtinType())))
 
-Matcher<TemplateSpecializationType>hasAnyTemplateArgumentMatcher<TemplateArgument> InnerMatcher -
Matches classTemplateSpecializations, templateSpecializationType and
-functionDecl that have at least one TemplateArgument matching the given
-InnerMatcher.
+Matcher<TemplateSpecializationType>hasAnyTemplateArgumentMatcher<TemplateArgument> InnerMatcher
+
Matches templateSpecializationTypes, class template specializations,
+variable template specializations, and function template specializations
+that have at least one TemplateArgument matching the given InnerMatcher.
 
 Given
   template<typename T> class A {};
@@ -10122,9 +10180,10 @@ Usable as: Matcher<TemplateSpecializationType>hasTemplateArgumentunsigned N, Matcher<TemplateArgument> InnerMatcher
-
Matches classTemplateSpecializations, templateSpecializationType and
-functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
+Matcher<TemplateSpecializationType>hasTemplateArgumentunsigned N, Matcher<TemplateArgument> InnerMatcher
+
Matches templateSpecializationType, class template specializations,
+variable template specializations, and function template specializations
+where the n'th TemplateArgument matches the given InnerMatcher.
 
 Given
   template<typename T, typename U> class A {};
@@ -10182,8 +10241,8 @@ QualType-matcher matches.
 
-Matcher<TypedefNameDecl>hasTypeLocMatcher<TypeLoc> Inner -
Matches if the type location of a node matches the inner matcher.
+Matcher<TypedefNameDecl>hasTypeLocMatcher<TypeLoc> Inner
+
Matches if the type location of a node matches the inner matcher.
 
 Examples:
   int x;
@@ -10203,7 +10262,7 @@ Usable as: Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
   Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
   Matcher<CXXUnresolvedConstructExpr>,
-  Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
+  Matcher<CompoundLiteralExpr>,
   Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
   Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
   Matcher<TypedefNameDecl>
@@ -10449,6 +10508,105 @@ Example matches x (matcher = varDecl(hasInitializer(callExpr())))
 
+Matcher<VarTemplateSpecializationDecl>forEachTemplateArgumentMatcher<TemplateArgument> InnerMatcher +
Matches templateSpecializationType, class template specialization,
+variable template specialization, and function template specialization
+nodes where the template argument matches the inner matcher. This matcher
+may produce multiple matches.
+
+Given
+  template <typename T, unsigned N, unsigned M>
+  struct Matrix {};
+
+  constexpr unsigned R = 2;
+  Matrix<int, R * 2, R * 4> M;
+
+  template <typename T, typename U>
+  void f(T&& t, U&& u) {}
+
+  bool B = false;
+  f(R, B);
+templateSpecializationType(forEachTemplateArgument(isExpr(expr())))
+  matches twice, with expr() matching 'R * 2' and 'R * 4'
+functionDecl(forEachTemplateArgument(refersToType(builtinType())))
+  matches the specialization f<unsigned, bool> twice, for 'unsigned'
+  and 'bool'
+
+ + +Matcher<VarTemplateSpecializationDecl>hasAnyTemplateArgumentLocMatcher<TemplateArgumentLoc> InnerMatcher +
Matches template specialization `TypeLoc`s, class template specializations,
+variable template specializations, and function template specializations
+that have at least one `TemplateArgumentLoc` matching the given
+`InnerMatcher`.
+
+Given
+  template<typename T> class A {};
+  A<int> a;
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+  hasTypeLoc(loc(asString("int")))))))
+  matches `A<int> a`.
+
+ + +Matcher<VarTemplateSpecializationDecl>hasAnyTemplateArgumentMatcher<TemplateArgument> InnerMatcher +
Matches templateSpecializationTypes, class template specializations,
+variable template specializations, and function template specializations
+that have at least one TemplateArgument matching the given InnerMatcher.
+
+Given
+  template<typename T> class A {};
+  template<> class A<double> {};
+  A<int> a;
+
+  template<typename T> f() {};
+  void func() { f<int>(); };
+
+classTemplateSpecializationDecl(hasAnyTemplateArgument(
+    refersToType(asString("int"))))
+  matches the specialization A<int>
+
+functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+  matches the specialization f<int>
+
+ + +Matcher<VarTemplateSpecializationDecl>hasTemplateArgumentLocunsigned Index, Matcher<TemplateArgumentLoc> InnerMatcher +
Matches template specialization `TypeLoc`s, class template specializations,
+variable template specializations, and function template specializations
+where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`.
+
+Given
+  template<typename T, typename U> class A {};
+  A<double, int> b;
+  A<int, double> c;
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
+  hasTypeLoc(loc(asString("double")))))))
+  matches `A<double, int> b`, but not `A<int, double> c`.
+
+ + +Matcher<VarTemplateSpecializationDecl>hasTemplateArgumentunsigned N, Matcher<TemplateArgument> InnerMatcher +
Matches templateSpecializationType, class template specializations,
+variable template specializations, and function template specializations
+where the n'th TemplateArgument matches the given InnerMatcher.
+
+Given
+  template<typename T, typename U> class A {};
+  A<bool, int> b;
+  A<int, bool> c;
+
+  template<typename T> void f() {}
+  void func() { f<int>(); };
+classTemplateSpecializationDecl(hasTemplateArgument(
+    1, refersToType(asString("int"))))
+  matches the specialization A<bool, int>
+
+functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+  matches the specialization f<int>
+
+ + Matcher<VariableArrayType>hasSizeExprMatcher<Expr> InnerMatcher
Matches VariableArrayType nodes that have a specific size
 expression.
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 49ab222bec40..ae699ebfc603 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -114,6 +114,9 @@ Clang Frontend Potentially Breaking Changes
     $ clang --target= -print-target-triple
     
 
+- The ``hasTypeLoc`` AST matcher will no longer match a ``classTemplateSpecializationDecl``;
+  existing uses should switch to ``templateArgumentLoc`` or ``hasAnyTemplateArgumentLoc`` instead.
+
 What's New in Clang |release|?
 ==============================
 Some of the major new features and improvements to Clang are listed
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 3ee03eebdb8c..268aeacf2f20 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1776,6 +1776,25 @@ public:
   BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; }
 };
 
+/// Provides information about an explicit instantiation of a variable or class
+/// template.
+struct ExplicitInstantiationInfo {
+  /// The template arguments as written..
+  const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr;
+
+  /// The location of the extern keyword.
+  SourceLocation ExternKeywordLoc;
+
+  /// The location of the template keyword.
+  SourceLocation TemplateKeywordLoc;
+
+  ExplicitInstantiationInfo() = default;
+};
+
+using SpecializationOrInstantiationInfo =
+    llvm::PointerUnion;
+
 /// Represents a class template specialization, which refers to
 /// a class template with a given set of template arguments.
 ///
@@ -1789,8 +1808,8 @@ public:
 /// template<>
 /// class array { }; // class template specialization array
 /// \endcode
-class ClassTemplateSpecializationDecl
-  : public CXXRecordDecl, public llvm::FoldingSetNode {
+class ClassTemplateSpecializationDecl : public CXXRecordDecl,
+                                        public llvm::FoldingSetNode {
   /// Structure that stores information about a class template
   /// specialization that was instantiated from a class template partial
   /// specialization.
@@ -1808,23 +1827,9 @@ class ClassTemplateSpecializationDecl
   llvm::PointerUnion
     SpecializedTemplate;
 
-  /// Further info for explicit template specialization/instantiation.
-  struct ExplicitSpecializationInfo {
-    /// The type-as-written.
-    TypeSourceInfo *TypeAsWritten = nullptr;
-
-    /// The location of the extern keyword.
-    SourceLocation ExternLoc;
-
-    /// The location of the template keyword.
-    SourceLocation TemplateKeywordLoc;
-
-    ExplicitSpecializationInfo() = default;
-  };
-
   /// Further info for explicit template specialization/instantiation.
   /// Does not apply to implicit specializations.
-  ExplicitSpecializationInfo *ExplicitInfo = nullptr;
+  SpecializationOrInstantiationInfo ExplicitInfo = nullptr;
 
   /// The template arguments used to describe this specialization.
   const TemplateArgumentList *TemplateArgs;
@@ -2001,44 +2006,49 @@ public:
     SpecializedTemplate = TemplDecl;
   }
 
-  /// Sets the type of this specialization as it was written by
-  /// the user. This will be a class template specialization type.
-  void setTypeAsWritten(TypeSourceInfo *T) {
-    if (!ExplicitInfo)
-      ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-    ExplicitInfo->TypeAsWritten = T;
+  /// Retrieve the template argument list as written in the sources,
+  /// if any.
+  const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+    if (auto *Info = ExplicitInfo.dyn_cast())
+      return Info->TemplateArgsAsWritten;
+    return ExplicitInfo.get();
   }
 
-  /// Gets the type of this specialization as it was written by
-  /// the user, if it was so written.
-  TypeSourceInfo *getTypeAsWritten() const {
-    return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
+  /// Set the template argument list as written in the sources.
+  void
+  setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) {
+    if (auto *Info = ExplicitInfo.dyn_cast())
+      Info->TemplateArgsAsWritten = ArgsWritten;
+    else
+      ExplicitInfo = ArgsWritten;
   }
 
-  /// Gets the location of the extern keyword, if present.
-  SourceLocation getExternLoc() const {
-    return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
+  /// Set the template argument list as written in the sources.
+  void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) {
+    setTemplateArgsAsWritten(
+        ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo));
   }
 
-  /// Sets the location of the extern keyword.
-  void setExternLoc(SourceLocation Loc) {
-    if (!ExplicitInfo)
-      ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-    ExplicitInfo->ExternLoc = Loc;
+  /// Gets the location of the extern keyword, if present.
+  SourceLocation getExternKeywordLoc() const {
+    if (auto *Info = ExplicitInfo.dyn_cast())
+      return Info->ExternKeywordLoc;
+    return SourceLocation();
   }
 
-  /// Sets the location of the template keyword.
-  void setTemplateKeywordLoc(SourceLocation Loc) {
-    if (!ExplicitInfo)
-      ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-    ExplicitInfo->TemplateKeywordLoc = Loc;
-  }
+  /// Sets the location of the extern keyword.
+  void setExternKeywordLoc(SourceLocation Loc);
 
   /// Gets the location of the template keyword, if present.
   SourceLocation getTemplateKeywordLoc() const {
-    return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
+    if (auto *Info = ExplicitInfo.dyn_cast())
+      return Info->TemplateKeywordLoc;
+    return SourceLocation();
   }
 
+  /// Sets the location of the template keyword.
+  void setTemplateKeywordLoc(SourceLocation Loc);
+
   SourceRange getSourceRange() const override LLVM_READONLY;
 
   void Profile(llvm::FoldingSetNodeID &ID) const {
@@ -2066,10 +2076,6 @@ class ClassTemplatePartialSpecializationDecl
   /// The list of template parameters
   TemplateParameterList* TemplateParams = nullptr;
 
-  /// The source info for the template arguments as written.
-  /// FIXME: redundant with TypeAsWritten?
-  const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
-
   /// The class template partial specialization from which this
   /// class template partial specialization was instantiated.
   ///
@@ -2078,15 +2084,11 @@ class ClassTemplatePartialSpecializationDecl
   llvm::PointerIntPair
       InstantiatedFromMember;
 
-  ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
-                                         DeclContext *DC,
-                                         SourceLocation StartLoc,
-                                         SourceLocation IdLoc,
-                                         TemplateParameterList *Params,
-                                         ClassTemplateDecl *SpecializedTemplate,
-                                         ArrayRef Args,
-                               const ASTTemplateArgumentListInfo *ArgsAsWritten,
-                               ClassTemplatePartialSpecializationDecl *PrevDecl);
+  ClassTemplatePartialSpecializationDecl(
+      ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
+      SourceLocation IdLoc, TemplateParameterList *Params,
+      ClassTemplateDecl *SpecializedTemplate, ArrayRef Args,
+      ClassTemplatePartialSpecializationDecl *PrevDecl);
 
   ClassTemplatePartialSpecializationDecl(ASTContext &C)
     : ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization),
@@ -2101,11 +2103,8 @@ public:
   static ClassTemplatePartialSpecializationDecl *
   Create(ASTContext &Context, TagKind TK, DeclContext *DC,
          SourceLocation StartLoc, SourceLocation IdLoc,
-         TemplateParameterList *Params,
-         ClassTemplateDecl *SpecializedTemplate,
-         ArrayRef Args,
-         const TemplateArgumentListInfo &ArgInfos,
-         QualType CanonInjectedType,
+         TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate,
+         ArrayRef Args, QualType CanonInjectedType,
          ClassTemplatePartialSpecializationDecl *PrevDecl);
 
   static ClassTemplatePartialSpecializationDecl *
@@ -2136,11 +2135,6 @@ public:
     return TemplateParams->hasAssociatedConstraints();
   }
 
-  /// Get the template arguments as written.
-  const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
-    return ArgsAsWritten;
-  }
-
   /// Retrieve the member class template partial specialization from
   /// which this particular class template partial specialization was
   /// instantiated.
@@ -2193,7 +2187,7 @@ public:
   /// template<> template
   /// struct X::Inner { /* ... */ };
   /// \endcode
-  bool isMemberSpecialization() {
+  bool isMemberSpecialization() const {
     const auto *First =
         cast(getFirstDecl());
     return First->InstantiatedFromMember.getInt();
@@ -2216,6 +2210,8 @@ public:
              ->getInjectedSpecializationType();
   }
 
+  SourceRange getSourceRange() const override LLVM_READONLY;
+
   void Profile(llvm::FoldingSetNodeID &ID) const {
     Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(),
             getASTContext());
@@ -2613,27 +2609,12 @@ class VarTemplateSpecializationDecl : public VarDecl,
   llvm::PointerUnion
   SpecializedTemplate;
 
-  /// Further info for explicit template specialization/instantiation.
-  struct ExplicitSpecializationInfo {
-    /// The type-as-written.
-    TypeSourceInfo *TypeAsWritten = nullptr;
-
-    /// The location of the extern keyword.
-    SourceLocation ExternLoc;
-
-    /// The location of the template keyword.
-    SourceLocation TemplateKeywordLoc;
-
-    ExplicitSpecializationInfo() = default;
-  };
-
   /// Further info for explicit template specialization/instantiation.
   /// Does not apply to implicit specializations.
-  ExplicitSpecializationInfo *ExplicitInfo = nullptr;
+  SpecializationOrInstantiationInfo ExplicitInfo = nullptr;
 
   /// The template arguments used to describe this specialization.
   const TemplateArgumentList *TemplateArgs;
-  const ASTTemplateArgumentListInfo *TemplateArgsInfo = nullptr;
 
   /// The point where this template was instantiated (if any).
   SourceLocation PointOfInstantiation;
@@ -2687,14 +2668,6 @@ public:
   /// specialization.
   const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; }
 
-  // TODO: Always set this when creating the new specialization?
-  void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo);
-  void setTemplateArgsInfo(const ASTTemplateArgumentListInfo *ArgsInfo);
-
-  const ASTTemplateArgumentListInfo *getTemplateArgsInfo() const {
-    return TemplateArgsInfo;
-  }
-
   /// Determine the kind of specialization that this
   /// declaration represents.
   TemplateSpecializationKind getSpecializationKind() const {
@@ -2798,44 +2771,49 @@ public:
     SpecializedTemplate = TemplDecl;
   }
 
-  /// Sets the type of this specialization as it was written by
-  /// the user.
-  void setTypeAsWritten(TypeSourceInfo *T) {
-    if (!ExplicitInfo)
-      ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-    ExplicitInfo->TypeAsWritten = T;
+  /// Retrieve the template argument list as written in the sources,
+  /// if any.
+  const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+    if (auto *Info = ExplicitInfo.dyn_cast())
+      return Info->TemplateArgsAsWritten;
+    return ExplicitInfo.get();
+  }
+
+  /// Set the template argument list as written in the sources.
+  void
+  setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) {
+    if (auto *Info = ExplicitInfo.dyn_cast())
+      Info->TemplateArgsAsWritten = ArgsWritten;
+    else
+      ExplicitInfo = ArgsWritten;
   }
 
-  /// Gets the type of this specialization as it was written by
-  /// the user, if it was so written.
-  TypeSourceInfo *getTypeAsWritten() const {
-    return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
+  /// Set the template argument list as written in the sources.
+  void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) {
+    setTemplateArgsAsWritten(
+        ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo));
   }
 
   /// Gets the location of the extern keyword, if present.
-  SourceLocation getExternLoc() const {
-    return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
+  SourceLocation getExternKeywordLoc() const {
+    if (auto *Info = ExplicitInfo.dyn_cast())
+      return Info->ExternKeywordLoc;
+    return SourceLocation();
   }
 
   /// Sets the location of the extern keyword.
-  void setExternLoc(SourceLocation Loc) {
-    if (!ExplicitInfo)
-      ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-    ExplicitInfo->ExternLoc = Loc;
-  }
-
-  /// Sets the location of the template keyword.
-  void setTemplateKeywordLoc(SourceLocation Loc) {
-    if (!ExplicitInfo)
-      ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-    ExplicitInfo->TemplateKeywordLoc = Loc;
-  }
+  void setExternKeywordLoc(SourceLocation Loc);
 
   /// Gets the location of the template keyword, if present.
   SourceLocation getTemplateKeywordLoc() const {
-    return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
+    if (auto *Info = ExplicitInfo.dyn_cast())
+      return Info->TemplateKeywordLoc;
+    return SourceLocation();
   }
 
+  /// Sets the location of the template keyword.
+  void setTemplateKeywordLoc(SourceLocation Loc);
+
   SourceRange getSourceRange() const override LLVM_READONLY;
 
   void Profile(llvm::FoldingSetNodeID &ID) const {
@@ -2863,10 +2841,6 @@ class VarTemplatePartialSpecializationDecl
   /// The list of template parameters
   TemplateParameterList *TemplateParams = nullptr;
 
-  /// The source info for the template arguments as written.
-  /// FIXME: redundant with TypeAsWritten?
-  const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
-
   /// The variable template partial specialization from which this
   /// variable template partial specialization was instantiated.
   ///
@@ -2879,8 +2853,7 @@ class VarTemplatePartialSpecializationDecl
       ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
       SourceLocation IdLoc, TemplateParameterList *Params,
       VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
-      StorageClass S, ArrayRef Args,
-      const ASTTemplateArgumentListInfo *ArgInfos);
+      StorageClass S, ArrayRef Args);
 
   VarTemplatePartialSpecializationDecl(ASTContext &Context)
       : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization,
@@ -2897,8 +2870,8 @@ public:
   Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
          SourceLocation IdLoc, TemplateParameterList *Params,
          VarTemplateDecl *SpecializedTemplate, QualType T,
-         TypeSourceInfo *TInfo, StorageClass S, ArrayRef Args,
-         const TemplateArgumentListInfo &ArgInfos);
+         TypeSourceInfo *TInfo, StorageClass S,
+         ArrayRef Args);
 
   static VarTemplatePartialSpecializationDecl *
   CreateDeserialized(ASTContext &C, GlobalDeclID ID);
@@ -2914,11 +2887,6 @@ public:
     return TemplateParams;
   }
 
-  /// Get the template arguments as written.
-  const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
-    return ArgsAsWritten;
-  }
-
   /// \brief All associated constraints of this partial specialization,
   /// including the requires clause and any constraints derived from
   /// constrained-parameters.
@@ -2981,7 +2949,7 @@ public:
   /// template<> template
   /// U* X::Inner = (T*)(0) + 1;
   /// \endcode
-  bool isMemberSpecialization() {
+  bool isMemberSpecialization() const {
     const auto *First =
         cast(getFirstDecl());
     return First->InstantiatedFromMember.getInt();
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index f9b145b4e86a..782f60844506 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2030,6 +2030,15 @@ DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); })
 
 DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
 
+template 
+bool RecursiveASTVisitor::TraverseTemplateArgumentLocsHelper(
+    const TemplateArgumentLoc *TAL, unsigned Count) {
+  for (unsigned I = 0; I < Count; ++I) {
+    TRY_TO(TraverseTemplateArgumentLoc(TAL[I]));
+  }
+  return true;
+}
+
 #define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND)                    \
   DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, {                \
     /* For implicit instantiations ("set x;"), we don't want to           \
@@ -2039,9 +2048,12 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
        TemplateSpecializationType).  For explicit instantiations               \
        ("template set;"), we do need a callback, since this               \
        is the only callback that's made for this instantiation.                \
-       We use getTypeAsWritten() to distinguish. */                            \
-    if (TypeSourceInfo *TSI = D->getTypeAsWritten())                           \
-      TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));                              \
+       We use getTemplateArgsAsWritten() to distinguish. */                    \
+    if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) {             \
+      /* The args that remains unspecialized. */                               \
+      TRY_TO(TraverseTemplateArgumentLocsHelper(                               \
+          ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs));      \
+    }                                                                          \
                                                                                \
     if (getDerived().shouldVisitTemplateInstantiations() ||                    \
         D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {    \
@@ -2061,15 +2073,6 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
 DEF_TRAVERSE_TMPL_SPEC_DECL(Class, CXXRecord)
 DEF_TRAVERSE_TMPL_SPEC_DECL(Var, Var)
 
-template 
-bool RecursiveASTVisitor::TraverseTemplateArgumentLocsHelper(
-    const TemplateArgumentLoc *TAL, unsigned Count) {
-  for (unsigned I = 0; I < Count; ++I) {
-    TRY_TO(TraverseTemplateArgumentLoc(TAL[I]));
-  }
-  return true;
-}
-
 #define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND)               \
   DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, {         \
     /* The partial specialization. */                                          \
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 8a2bbfff9e9e..0f3257db6f41 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -764,9 +764,9 @@ AST_POLYMORPHIC_MATCHER(isImplicit,
   return Node.isImplicit();
 }
 
-/// Matches classTemplateSpecializations, templateSpecializationType and
-/// functionDecl that have at least one TemplateArgument matching the given
-/// InnerMatcher.
+/// Matches templateSpecializationTypes, class template specializations,
+/// variable template specializations, and function template specializations
+/// that have at least one TemplateArgument matching the given InnerMatcher.
 ///
 /// Given
 /// \code
@@ -788,8 +788,8 @@ AST_POLYMORPHIC_MATCHER(isImplicit,
 AST_POLYMORPHIC_MATCHER_P(
     hasAnyTemplateArgument,
     AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
-                                    TemplateSpecializationType,
-                                    FunctionDecl),
+                                    VarTemplateSpecializationDecl, FunctionDecl,
+                                    TemplateSpecializationType),
     internal::Matcher, InnerMatcher) {
   ArrayRef List =
       internal::getTemplateSpecializationArgs(Node);
@@ -1047,8 +1047,9 @@ AST_MATCHER(Expr, isTypeDependent) { return Node.isTypeDependent(); }
 /// expr(isValueDependent()) matches return Size
 AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); }
 
-/// Matches classTemplateSpecializations, templateSpecializationType and
-/// functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
+/// Matches templateSpecializationType, class template specializations,
+/// variable template specializations, and function template specializations
+/// where the n'th TemplateArgument matches the given InnerMatcher.
 ///
 /// Given
 /// \code
@@ -1068,8 +1069,8 @@ AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); }
 AST_POLYMORPHIC_MATCHER_P2(
     hasTemplateArgument,
     AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
-                                    TemplateSpecializationType,
-                                    FunctionDecl),
+                                    VarTemplateSpecializationDecl, FunctionDecl,
+                                    TemplateSpecializationType),
     unsigned, N, internal::Matcher, InnerMatcher) {
   ArrayRef List =
       internal::getTemplateSpecializationArgs(Node);
@@ -4066,7 +4067,7 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
 ///   Matcher, Matcher,
 ///   Matcher, Matcher,
 ///   Matcher,
-///   Matcher, Matcher,
+///   Matcher,
 ///   Matcher, Matcher,
 ///   Matcher, Matcher,
 ///   Matcher
@@ -4075,9 +4076,8 @@ AST_POLYMORPHIC_MATCHER_P(
     AST_POLYMORPHIC_SUPPORTED_TYPES(
         BlockDecl, CXXBaseSpecifier, CXXCtorInitializer, CXXFunctionalCastExpr,
         CXXNewExpr, CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr,
-        ClassTemplateSpecializationDecl, CompoundLiteralExpr, DeclaratorDecl,
-        ExplicitCastExpr, ObjCPropertyDecl, TemplateArgumentLoc,
-        TypedefNameDecl),
+        CompoundLiteralExpr, DeclaratorDecl, ExplicitCastExpr, ObjCPropertyDecl,
+        TemplateArgumentLoc, TypedefNameDecl),
     internal::Matcher, Inner) {
   TypeSourceInfo *source = internal::GetTypeSourceInfo(Node);
   if (source == nullptr) {
@@ -5304,9 +5304,10 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs,
   return Node.getNumParams() == N;
 }
 
-/// Matches classTemplateSpecialization, templateSpecializationType and
-/// functionDecl nodes where the template argument matches the inner matcher.
-/// This matcher may produce multiple matches.
+/// Matches templateSpecializationType, class template specialization,
+/// variable template specialization, and function template specialization
+/// nodes where the template argument matches the inner matcher. This matcher
+/// may produce multiple matches.
 ///
 /// Given
 /// \code
@@ -5330,7 +5331,8 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs,
 AST_POLYMORPHIC_MATCHER_P(
     forEachTemplateArgument,
     AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
-                                    TemplateSpecializationType, FunctionDecl),
+                                    VarTemplateSpecializationDecl, FunctionDecl,
+                                    TemplateSpecializationType),
     internal::Matcher, InnerMatcher) {
   ArrayRef TemplateArgs =
       clang::ast_matchers::internal::getTemplateSpecializationArgs(Node);
@@ -6905,8 +6907,10 @@ extern const internal::VariadicDynCastAllOfMatcher<
     TypeLoc, TemplateSpecializationTypeLoc>
     templateSpecializationTypeLoc;
 
-/// Matches template specialization `TypeLoc`s that have at least one
-/// `TemplateArgumentLoc` matching the given `InnerMatcher`.
+/// Matches template specialization `TypeLoc`s, class template specializations,
+/// variable template specializations, and function template specializations
+/// that have at least one `TemplateArgumentLoc` matching the given
+/// `InnerMatcher`.
 ///
 /// Given
 /// \code
@@ -6916,20 +6920,21 @@ extern const internal::VariadicDynCastAllOfMatcher<
 /// varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
 ///   hasTypeLoc(loc(asString("int")))))))
 ///   matches `A a`.
-AST_MATCHER_P(TemplateSpecializationTypeLoc, hasAnyTemplateArgumentLoc,
-              internal::Matcher, InnerMatcher) {
-  for (unsigned Index = 0, N = Node.getNumArgs(); Index < N; ++Index) {
-    clang::ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
-    if (InnerMatcher.matches(Node.getArgLoc(Index), Finder, &Result)) {
-      *Builder = std::move(Result);
-      return true;
-    }
-  }
+AST_POLYMORPHIC_MATCHER_P(
+    hasAnyTemplateArgumentLoc,
+    AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
+                                    VarTemplateSpecializationDecl, FunctionDecl,
+                                    DeclRefExpr, TemplateSpecializationTypeLoc),
+    internal::Matcher, InnerMatcher) {
+  auto Args = internal::getTemplateArgsWritten(Node);
+  return matchesFirstInRange(InnerMatcher, Args.begin(), Args.end(), Finder,
+                             Builder) != Args.end();
   return false;
 }
 
-/// Matches template specialization `TypeLoc`s where the n'th
-/// `TemplateArgumentLoc` matches the given `InnerMatcher`.
+/// Matches template specialization `TypeLoc`s, class template specializations,
+/// variable template specializations, and function template specializations
+/// where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`.
 ///
 /// Given
 /// \code
@@ -6942,10 +6947,13 @@ AST_MATCHER_P(TemplateSpecializationTypeLoc, hasAnyTemplateArgumentLoc,
 ///   matches `A b`, but not `A c`.
 AST_POLYMORPHIC_MATCHER_P2(
     hasTemplateArgumentLoc,
-    AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr, TemplateSpecializationTypeLoc),
+    AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
+                                    VarTemplateSpecializationDecl, FunctionDecl,
+                                    DeclRefExpr, TemplateSpecializationTypeLoc),
     unsigned, Index, internal::Matcher, InnerMatcher) {
-  return internal::MatchTemplateArgLocAt(Node, Index, InnerMatcher, Finder,
-                                         Builder);
+  auto Args = internal::getTemplateArgsWritten(Node);
+  return Index < Args.size() &&
+         InnerMatcher.matches(Args[Index], Finder, Builder);
 }
 
 /// Matches C or C++ elaborated `TypeLoc`s.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 47d912c73dd7..c1cc63fdb743 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -186,10 +186,6 @@ inline TypeSourceInfo *GetTypeSourceInfo(const BlockDecl &Node) {
 inline TypeSourceInfo *GetTypeSourceInfo(const CXXNewExpr &Node) {
   return Node.getAllocatedTypeSourceInfo();
 }
-inline TypeSourceInfo *
-GetTypeSourceInfo(const ClassTemplateSpecializationDecl &Node) {
-  return Node.getTypeAsWritten();
-}
 
 /// Unifies obtaining the FunctionProtoType pointer from both
 /// FunctionProtoType and FunctionDecl nodes..
@@ -1939,6 +1935,11 @@ getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) {
   return D.getTemplateArgs().asArray();
 }
 
+inline ArrayRef
+getTemplateSpecializationArgs(const VarTemplateSpecializationDecl &D) {
+  return D.getTemplateArgs().asArray();
+}
+
 inline ArrayRef
 getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
   return T.template_arguments();
@@ -1948,7 +1949,46 @@ inline ArrayRef
 getTemplateSpecializationArgs(const FunctionDecl &FD) {
   if (const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
     return TemplateArgs->asArray();
-  return ArrayRef();
+  return std::nullopt;
+}
+
+inline ArrayRef
+getTemplateArgsWritten(const ClassTemplateSpecializationDecl &D) {
+  if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
+    return Args->arguments();
+  return std::nullopt;
+}
+
+inline ArrayRef
+getTemplateArgsWritten(const VarTemplateSpecializationDecl &D) {
+  if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
+    return Args->arguments();
+  return std::nullopt;
+}
+
+inline ArrayRef
+getTemplateArgsWritten(const FunctionDecl &FD) {
+  if (const auto *Args = FD.getTemplateSpecializationArgsAsWritten())
+    return Args->arguments();
+  return std::nullopt;
+}
+
+inline ArrayRef
+getTemplateArgsWritten(const DeclRefExpr &DRE) {
+  if (const auto *Args = DRE.getTemplateArgs())
+    return {Args, DRE.getNumTemplateArgs()};
+  return std::nullopt;
+}
+
+inline SmallVector
+getTemplateArgsWritten(const TemplateSpecializationTypeLoc &T) {
+  SmallVector Args;
+  if (!T.isNull()) {
+    Args.reserve(T.getNumArgs());
+    for (unsigned I = 0; I < T.getNumArgs(); ++I)
+      Args.emplace_back(T.getArgLoc(I));
+  }
+  return Args;
 }
 
 struct NotEqualsBoundNodePredicate {
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index d3538e43d3d7..fe1bd47348be 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -43,7 +43,7 @@ namespace serialization {
 /// Version 4 of AST files also requires that the version control branch and
 /// revision match exactly, since there is no backward compatibility of
 /// AST files at this time.
-const unsigned VERSION_MAJOR = 30;
+const unsigned VERSION_MAJOR = 31;
 
 /// AST file minor version number supported by this version of
 /// Clang.
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 60f213322b34..9ff8e1ea78d8 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -443,8 +443,9 @@ namespace clang {
     Expected
     ImportFunctionTemplateWithTemplateArgsFromSpecialization(
         FunctionDecl *FromFD);
-    Error ImportTemplateParameterLists(const DeclaratorDecl *FromD,
-                                       DeclaratorDecl *ToD);
+
+    template 
+    Error ImportTemplateParameterLists(const DeclTy *FromD, DeclTy *ToD);
 
     Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD);
 
@@ -3322,8 +3323,9 @@ ExpectedDecl ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
   return ToEnumerator;
 }
 
-Error ASTNodeImporter::ImportTemplateParameterLists(const DeclaratorDecl *FromD,
-                                                    DeclaratorDecl *ToD) {
+template 
+Error ASTNodeImporter::ImportTemplateParameterLists(const DeclTy *FromD,
+                                                    DeclTy *ToD) {
   unsigned int Num = FromD->getNumTemplateParameterLists();
   if (Num == 0)
     return Error::success();
@@ -6210,15 +6212,16 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
   if (!IdLocOrErr)
     return IdLocOrErr.takeError();
 
+  // Import TemplateArgumentListInfo.
+  TemplateArgumentListInfo ToTAInfo;
+  if (const auto *ASTTemplateArgs = D->getTemplateArgsAsWritten()) {
+    if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, ToTAInfo))
+      return std::move(Err);
+  }
+
   // Create the specialization.
   ClassTemplateSpecializationDecl *D2 = nullptr;
   if (PartialSpec) {
-    // Import TemplateArgumentListInfo.
-    TemplateArgumentListInfo ToTAInfo;
-    const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten();
-    if (Error Err = ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo))
-      return std::move(Err);
-
     QualType CanonInjType;
     if (Error Err = importInto(
         CanonInjType, PartialSpec->getInjectedSpecializationType()))
@@ -6228,7 +6231,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
     if (GetImportedOrCreateDecl(
             D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr,
             *IdLocOrErr, ToTPList, ClassTemplate,
-            llvm::ArrayRef(TemplateArgs.data(), TemplateArgs.size()), ToTAInfo,
+            llvm::ArrayRef(TemplateArgs.data(), TemplateArgs.size()),
             CanonInjType,
             cast_or_null(PrevDecl)))
       return D2;
@@ -6276,28 +6279,27 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
   else
     return BraceRangeOrErr.takeError();
 
+  if (Error Err = ImportTemplateParameterLists(D, D2))
+    return std::move(Err);
+
   // Import the qualifier, if any.
   if (auto LocOrErr = import(D->getQualifierLoc()))
     D2->setQualifierInfo(*LocOrErr);
   else
     return LocOrErr.takeError();
 
-  if (auto *TSI = D->getTypeAsWritten()) {
-    if (auto TInfoOrErr = import(TSI))
-      D2->setTypeAsWritten(*TInfoOrErr);
-    else
-      return TInfoOrErr.takeError();
+  if (D->getTemplateArgsAsWritten())
+    D2->setTemplateArgsAsWritten(ToTAInfo);
 
-    if (auto LocOrErr = import(D->getTemplateKeywordLoc()))
-      D2->setTemplateKeywordLoc(*LocOrErr);
-    else
-      return LocOrErr.takeError();
+  if (auto LocOrErr = import(D->getTemplateKeywordLoc()))
+    D2->setTemplateKeywordLoc(*LocOrErr);
+  else
+    return LocOrErr.takeError();
 
-    if (auto LocOrErr = import(D->getExternLoc()))
-      D2->setExternLoc(*LocOrErr);
-    else
-      return LocOrErr.takeError();
-  }
+  if (auto LocOrErr = import(D->getExternKeywordLoc()))
+    D2->setExternKeywordLoc(*LocOrErr);
+  else
+    return LocOrErr.takeError();
 
   if (D->getPointOfInstantiation().isValid()) {
     if (auto POIOrErr = import(D->getPointOfInstantiation()))
@@ -6517,7 +6519,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
   VarTemplateSpecializationDecl *D2 = nullptr;
 
   TemplateArgumentListInfo ToTAInfo;
-  if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) {
+  if (const auto *Args = D->getTemplateArgsAsWritten()) {
     if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo))
       return std::move(Err);
   }
@@ -6525,14 +6527,6 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
   using PartVarSpecDecl = VarTemplatePartialSpecializationDecl;
   // Create a new specialization.
   if (auto *FromPartial = dyn_cast(D)) {
-    // Import TemplateArgumentListInfo
-    TemplateArgumentListInfo ArgInfos;
-    const auto *FromTAArgsAsWritten = FromPartial->getTemplateArgsAsWritten();
-    // NOTE: FromTAArgsAsWritten and template parameter list are non-null.
-    if (Error Err =
-            ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ArgInfos))
-      return std::move(Err);
-
     auto ToTPListOrErr = import(FromPartial->getTemplateParameters());
     if (!ToTPListOrErr)
       return ToTPListOrErr.takeError();
@@ -6541,7 +6535,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
     if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC,
                                 *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr,
                                 VarTemplate, QualType(), nullptr,
-                                D->getStorageClass(), TemplateArgs, ArgInfos))
+                                D->getStorageClass(), TemplateArgs))
       return ToPartial;
 
     if (Expected ToInstOrErr =
@@ -6584,7 +6578,9 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
   }
 
   D2->setSpecializationKind(D->getSpecializationKind());
-  D2->setTemplateArgsInfo(ToTAInfo);
+
+  if (D->getTemplateArgsAsWritten())
+    D2->setTemplateArgsAsWritten(ToTAInfo);
 
   if (auto LocOrErr = import(D->getQualifierLoc()))
     D2->setQualifierInfo(*LocOrErr);
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 599d379340ab..c5868256b440 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -1083,15 +1083,15 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
       NNS->print(Out, Policy);
     Out << *D;
 
-    if (auto S = dyn_cast(D)) {
-      ArrayRef Args = S->getTemplateArgs().asArray();
-      if (!Policy.PrintCanonicalTypes)
-        if (const auto* TSI = S->getTypeAsWritten())
-          if (const auto *TST =
-                  dyn_cast(TSI->getType()))
-            Args = TST->template_arguments();
-      printTemplateArguments(
-          Args, S->getSpecializedTemplate()->getTemplateParameters());
+    if (auto *S = dyn_cast(D)) {
+      const TemplateParameterList *TParams =
+          S->getSpecializedTemplate()->getTemplateParameters();
+      const ASTTemplateArgumentListInfo *TArgAsWritten =
+          S->getTemplateArgsAsWritten();
+      if (TArgAsWritten && !Policy.PrintCanonicalTypes)
+        printTemplateArguments(TArgAsWritten->arguments(), TParams);
+      else
+        printTemplateArguments(S->getTemplateArgs().asArray(), TParams);
     }
   }
 
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index d27a30e0c5fc..d22ecc3c032e 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -985,41 +985,67 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
 
 SourceRange
 ClassTemplateSpecializationDecl::getSourceRange() const {
-  if (ExplicitInfo) {
-    SourceLocation Begin = getTemplateKeywordLoc();
-    if (Begin.isValid()) {
-      // Here we have an explicit (partial) specialization or instantiation.
-      assert(getSpecializationKind() == TSK_ExplicitSpecialization ||
-             getSpecializationKind() == TSK_ExplicitInstantiationDeclaration ||
-             getSpecializationKind() == TSK_ExplicitInstantiationDefinition);
-      if (getExternLoc().isValid())
-        Begin = getExternLoc();
-      SourceLocation End = getBraceRange().getEnd();
-      if (End.isInvalid())
-        End = getTypeAsWritten()->getTypeLoc().getEndLoc();
-      return SourceRange(Begin, End);
-    }
-    // An implicit instantiation of a class template partial specialization
-    // uses ExplicitInfo to record the TypeAsWritten, but the source
-    // locations should be retrieved from the instantiation pattern.
-    using CTPSDecl = ClassTemplatePartialSpecializationDecl;
-    auto *ctpsd = const_cast(cast(this));
-    CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember();
-    assert(inst_from != nullptr);
-    return inst_from->getSourceRange();
-  }
-  else {
-    // No explicit info available.
+  switch (getSpecializationKind()) {
+  case TSK_Undeclared:
+  case TSK_ImplicitInstantiation: {
     llvm::PointerUnion
-      inst_from = getInstantiatedFrom();
-    if (inst_from.isNull())
-      return getSpecializedTemplate()->getSourceRange();
-    if (const auto *ctd = inst_from.dyn_cast())
-      return ctd->getSourceRange();
-    return inst_from.get()
-      ->getSourceRange();
+        Pattern = getSpecializedTemplateOrPartial();
+    assert(!Pattern.isNull() &&
+           "Class template specialization without pattern?");
+    if (const auto *CTPSD =
+            Pattern.dyn_cast())
+      return CTPSD->getSourceRange();
+    return Pattern.get()->getSourceRange();
+  }
+  case TSK_ExplicitSpecialization: {
+    SourceRange Range = CXXRecordDecl::getSourceRange();
+    if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
+        !isThisDeclarationADefinition() && Args)
+      Range.setEnd(Args->getRAngleLoc());
+    return Range;
+  }
+  case TSK_ExplicitInstantiationDeclaration:
+  case TSK_ExplicitInstantiationDefinition: {
+    SourceRange Range = CXXRecordDecl::getSourceRange();
+    if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
+      Range.setBegin(ExternKW);
+    else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
+             TemplateKW.isValid())
+      Range.setBegin(TemplateKW);
+    if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
+      Range.setEnd(Args->getRAngleLoc());
+    return Range;
+  }
   }
+  llvm_unreachable("unhandled template specialization kind");
+}
+
+void ClassTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
+  auto *Info = ExplicitInfo.dyn_cast();
+  if (!Info) {
+    // Don't allocate if the location is invalid.
+    if (Loc.isInvalid())
+      return;
+    Info = new (getASTContext()) ExplicitInstantiationInfo;
+    Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
+    ExplicitInfo = Info;
+  }
+  Info->ExternKeywordLoc = Loc;
+}
+
+void ClassTemplateSpecializationDecl::setTemplateKeywordLoc(
+    SourceLocation Loc) {
+  auto *Info = ExplicitInfo.dyn_cast();
+  if (!Info) {
+    // Don't allocate if the location is invalid.
+    if (Loc.isInvalid())
+      return;
+    Info = new (getASTContext()) ExplicitInstantiationInfo;
+    Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
+    ExplicitInfo = Info;
+  }
+  Info->TemplateKeywordLoc = Loc;
 }
 
 //===----------------------------------------------------------------------===//
@@ -1087,43 +1113,29 @@ void ImplicitConceptSpecializationDecl::setTemplateArguments(
 //===----------------------------------------------------------------------===//
 void ClassTemplatePartialSpecializationDecl::anchor() {}
 
-ClassTemplatePartialSpecializationDecl::
-ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
-                                       DeclContext *DC,
-                                       SourceLocation StartLoc,
-                                       SourceLocation IdLoc,
-                                       TemplateParameterList *Params,
-                                       ClassTemplateDecl *SpecializedTemplate,
-                                       ArrayRef Args,
-                               const ASTTemplateArgumentListInfo *ArgInfos,
-                               ClassTemplatePartialSpecializationDecl *PrevDecl)
-    : ClassTemplateSpecializationDecl(Context,
-                                      ClassTemplatePartialSpecialization,
-                                      TK, DC, StartLoc, IdLoc,
-                                      SpecializedTemplate, Args, PrevDecl),
-      TemplateParams(Params), ArgsAsWritten(ArgInfos),
-      InstantiatedFromMember(nullptr, false) {
+ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl(
+    ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
+    SourceLocation IdLoc, TemplateParameterList *Params,
+    ClassTemplateDecl *SpecializedTemplate, ArrayRef Args,
+    ClassTemplatePartialSpecializationDecl *PrevDecl)
+    : ClassTemplateSpecializationDecl(
+          Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc,
+          SpecializedTemplate, Args, PrevDecl),
+      TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
   if (AdoptTemplateParameterList(Params, this))
     setInvalidDecl();
 }
 
 ClassTemplatePartialSpecializationDecl *
-ClassTemplatePartialSpecializationDecl::
-Create(ASTContext &Context, TagKind TK,DeclContext *DC,
-       SourceLocation StartLoc, SourceLocation IdLoc,
-       TemplateParameterList *Params,
-       ClassTemplateDecl *SpecializedTemplate,
-       ArrayRef Args,
-       const TemplateArgumentListInfo &ArgInfos,
-       QualType CanonInjectedType,
-       ClassTemplatePartialSpecializationDecl *PrevDecl) {
-  const ASTTemplateArgumentListInfo *ASTArgInfos =
-    ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
-
-  auto *Result = new (Context, DC)
-      ClassTemplatePartialSpecializationDecl(Context, TK, DC, StartLoc, IdLoc,
-                                             Params, SpecializedTemplate, Args,
-                                             ASTArgInfos, PrevDecl);
+ClassTemplatePartialSpecializationDecl::Create(
+    ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
+    SourceLocation IdLoc, TemplateParameterList *Params,
+    ClassTemplateDecl *SpecializedTemplate, ArrayRef Args,
+    QualType CanonInjectedType,
+    ClassTemplatePartialSpecializationDecl *PrevDecl) {
+  auto *Result = new (Context, DC) ClassTemplatePartialSpecializationDecl(
+      Context, TK, DC, StartLoc, IdLoc, Params, SpecializedTemplate, Args,
+      PrevDecl);
   Result->setSpecializationKind(TSK_ExplicitSpecialization);
   Result->setMayHaveOutOfDateDef(false);
 
@@ -1139,6 +1151,18 @@ ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
   return Result;
 }
 
+SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
+  if (const ClassTemplatePartialSpecializationDecl *MT =
+          getInstantiatedFromMember();
+      MT && !isMemberSpecialization())
+    return MT->getSourceRange();
+  SourceRange Range = ClassTemplateSpecializationDecl::getSourceRange();
+  if (const TemplateParameterList *TPL = getTemplateParameters();
+      TPL && !getNumTemplateParameterLists())
+    Range.setBegin(TPL->getTemplateLoc());
+  return Range;
+}
+
 //===----------------------------------------------------------------------===//
 // FriendTemplateDecl Implementation
 //===----------------------------------------------------------------------===//
@@ -1371,27 +1395,74 @@ VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
   return SpecializedTemplate.get();
 }
 
-void VarTemplateSpecializationDecl::setTemplateArgsInfo(
-    const TemplateArgumentListInfo &ArgsInfo) {
-  TemplateArgsInfo =
-      ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo);
-}
-
-void VarTemplateSpecializationDecl::setTemplateArgsInfo(
-    const ASTTemplateArgumentListInfo *ArgsInfo) {
-  TemplateArgsInfo =
-      ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo);
-}
-
 SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
-  if (isExplicitSpecialization() && !hasInit()) {
-    if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsInfo())
-      return SourceRange(getOuterLocStart(), Info->getRAngleLoc());
+  switch (getSpecializationKind()) {
+  case TSK_Undeclared:
+  case TSK_ImplicitInstantiation: {
+    llvm::PointerUnion
+        Pattern = getSpecializedTemplateOrPartial();
+    assert(!Pattern.isNull() &&
+           "Variable template specialization without pattern?");
+    if (const auto *VTPSD =
+            Pattern.dyn_cast())
+      return VTPSD->getSourceRange();
+    VarTemplateDecl *VTD = Pattern.get();
+    if (hasInit()) {
+      if (VarTemplateDecl *Definition = VTD->getDefinition())
+        return Definition->getSourceRange();
+    }
+    return VTD->getCanonicalDecl()->getSourceRange();
+  }
+  case TSK_ExplicitSpecialization: {
+    SourceRange Range = VarDecl::getSourceRange();
+    if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
+        !hasInit() && Args)
+      Range.setEnd(Args->getRAngleLoc());
+    return Range;
+  }
+  case TSK_ExplicitInstantiationDeclaration:
+  case TSK_ExplicitInstantiationDefinition: {
+    SourceRange Range = VarDecl::getSourceRange();
+    if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
+      Range.setBegin(ExternKW);
+    else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
+             TemplateKW.isValid())
+      Range.setBegin(TemplateKW);
+    if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
+      Range.setEnd(Args->getRAngleLoc());
+    return Range;
   }
-  return VarDecl::getSourceRange();
+  }
+  llvm_unreachable("unhandled template specialization kind");
+}
+
+void VarTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
+  auto *Info = ExplicitInfo.dyn_cast();
+  if (!Info) {
+    // Don't allocate if the location is invalid.
+    if (Loc.isInvalid())
+      return;
+    Info = new (getASTContext()) ExplicitInstantiationInfo;
+    Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
+    ExplicitInfo = Info;
+  }
+  Info->ExternKeywordLoc = Loc;
+}
+
+void VarTemplateSpecializationDecl::setTemplateKeywordLoc(SourceLocation Loc) {
+  auto *Info = ExplicitInfo.dyn_cast();
+  if (!Info) {
+    // Don't allocate if the location is invalid.
+    if (Loc.isInvalid())
+      return;
+    Info = new (getASTContext()) ExplicitInstantiationInfo;
+    Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
+    ExplicitInfo = Info;
+  }
+  Info->TemplateKeywordLoc = Loc;
 }
 
-
 //===----------------------------------------------------------------------===//
 // VarTemplatePartialSpecializationDecl Implementation
 //===----------------------------------------------------------------------===//
@@ -1402,13 +1473,11 @@ VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl(
     ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
     SourceLocation IdLoc, TemplateParameterList *Params,
     VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
-    StorageClass S, ArrayRef Args,
-    const ASTTemplateArgumentListInfo *ArgInfos)
+    StorageClass S, ArrayRef Args)
     : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context,
                                     DC, StartLoc, IdLoc, SpecializedTemplate, T,
                                     TInfo, S, Args),
-      TemplateParams(Params), ArgsAsWritten(ArgInfos),
-      InstantiatedFromMember(nullptr, false) {
+      TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
   if (AdoptTemplateParameterList(Params, DC))
     setInvalidDecl();
 }
@@ -1418,15 +1487,10 @@ VarTemplatePartialSpecializationDecl::Create(
     ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
     SourceLocation IdLoc, TemplateParameterList *Params,
     VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
-    StorageClass S, ArrayRef Args,
-    const TemplateArgumentListInfo &ArgInfos) {
-  const ASTTemplateArgumentListInfo *ASTArgInfos
-    = ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
-
-  auto *Result =
-      new (Context, DC) VarTemplatePartialSpecializationDecl(
-          Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo,
-          S, Args, ASTArgInfos);
+    StorageClass S, ArrayRef Args) {
+  auto *Result = new (Context, DC) VarTemplatePartialSpecializationDecl(
+      Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, S,
+      Args);
   Result->setSpecializationKind(TSK_ExplicitSpecialization);
   return Result;
 }
@@ -1438,11 +1502,15 @@ VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
 }
 
 SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
-  if (isExplicitSpecialization() && !hasInit()) {
-    if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten())
-      return SourceRange(getOuterLocStart(), Info->getRAngleLoc());
-  }
-  return VarDecl::getSourceRange();
+  if (const VarTemplatePartialSpecializationDecl *MT =
+          getInstantiatedFromMember();
+      MT && !isMemberSpecialization())
+    return MT->getSourceRange();
+  SourceRange Range = VarTemplateSpecializationDecl::getSourceRange();
+  if (const TemplateParameterList *TPL = getTemplateParameters();
+      TPL && !getNumTemplateParameterLists())
+    Range.setBegin(TPL->getTemplateLoc());
+  return Range;
 }
 
 static TemplateParameterList *
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 9602f448e942..87f0a8728d85 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1472,21 +1472,18 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
 
   // If this is a class template specialization, print the template
   // arguments.
-  if (const auto *Spec = dyn_cast(D)) {
-    ArrayRef Args;
-    TypeSourceInfo *TAW = Spec->getTypeAsWritten();
-    if (!Policy.PrintCanonicalTypes && TAW) {
-      const TemplateSpecializationType *TST =
-        cast(TAW->getType());
-      Args = TST->template_arguments();
-    } else {
-      const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
-      Args = TemplateArgs.asArray();
-    }
+  if (auto *S = dyn_cast(D)) {
+    const TemplateParameterList *TParams =
+        S->getSpecializedTemplate()->getTemplateParameters();
+    const ASTTemplateArgumentListInfo *TArgAsWritten =
+        S->getTemplateArgsAsWritten();
     IncludeStrongLifetimeRAII Strong(Policy);
-    printTemplateArgumentList(
-        OS, Args, Policy,
-        Spec->getSpecializedTemplate()->getTemplateParameters());
+    if (TArgAsWritten && !Policy.PrintCanonicalTypes)
+      printTemplateArgumentList(OS, TArgAsWritten->arguments(), Policy,
+                                TParams);
+    else
+      printTemplateArgumentList(OS, S->getTemplateArgs().asArray(), Policy,
+                                TParams);
   }
 
   spaceBeforePlaceHolder(OS);
diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp
index 1c04aa17d53f..8eb88f5a1e94 100644
--- a/clang/lib/Index/IndexDecl.cpp
+++ b/clang/lib/Index/IndexDecl.cpp
@@ -673,9 +673,12 @@ public:
     IndexCtx.indexTagDecl(
         D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
                           SpecializationOf));
-    if (TypeSourceInfo *TSI = D->getTypeAsWritten())
-      IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
-                                   D->getLexicalDeclContext());
+    // Template specialization arguments.
+    if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
+            D->getTemplateArgsAsWritten()) {
+      for (const auto &Arg : TemplateArgInfo->arguments())
+        handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
+    }
     return true;
   }
 
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 7585f1c367be..5d6ce233c775 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1406,7 +1406,7 @@ void Sema::ActOnEndOfTranslationUnit() {
         SourceRange DiagRange = DiagD->getLocation();
         if (const auto *VTSD = dyn_cast(DiagD)) {
           if (const ASTTemplateArgumentListInfo *ASTTAL =
-                  VTSD->getTemplateArgsInfo())
+                  VTSD->getTemplateArgsAsWritten())
             DiagRange.setEnd(ASTTAL->RAngleLoc);
         }
         if (DiagD->isReferenced()) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 8219d5eed8db..c7aac068e264 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5300,7 +5300,8 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
         VarTemplatePartialSpecializationDecl::Create(
             Context, VarTemplate->getDeclContext(), TemplateKWLoc,
             TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC,
-            CanonicalConverted, TemplateArgs);
+            CanonicalConverted);
+    Partial->setTemplateArgsAsWritten(TemplateArgs);
 
     if (!PrevPartial)
       VarTemplate->AddPartialSpecialization(Partial, InsertPos);
@@ -5318,7 +5319,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
     Specialization = VarTemplateSpecializationDecl::Create(
         Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc,
         VarTemplate, DI->getType(), DI, SC, CanonicalConverted);
-    Specialization->setTemplateArgsInfo(TemplateArgs);
+    Specialization->setTemplateArgsAsWritten(TemplateArgs);
 
     if (!PrevDecl)
       VarTemplate->AddSpecialization(Specialization, InsertPos);
@@ -5353,7 +5354,6 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
     }
   }
 
-  Specialization->setTemplateKeywordLoc(TemplateKWLoc);
   Specialization->setLexicalDeclContext(CurContext);
 
   // Add the specialization into its lexical context, so that it can
@@ -9414,10 +9414,6 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
     MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) {
   assert(TUK != TUK_Reference && "References are not specializations");
 
-  // NOTE: KWLoc is the location of the tag keyword. This will instead
-  // store the location of the outermost template keyword in the declaration.
-  SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0
-    ? TemplateParameterLists[0]->getTemplateLoc() : KWLoc;
   SourceLocation TemplateNameLoc = TemplateId.TemplateNameLoc;
   SourceLocation LAngleLoc = TemplateId.LAngleLoc;
   SourceLocation RAngleLoc = TemplateId.RAngleLoc;
@@ -9629,7 +9625,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
         ClassTemplatePartialSpecializationDecl::Create(
             Context, Kind, ClassTemplate->getDeclContext(), KWLoc,
             TemplateNameLoc, TemplateParams, ClassTemplate, CanonicalConverted,
-            TemplateArgs, CanonType, PrevPartial);
+            CanonType, PrevPartial);
+    Partial->setTemplateArgsAsWritten(TemplateArgs);
     SetNestedNameSpecifier(*this, Partial, SS);
     if (TemplateParameterLists.size() > 1 && SS.isSet()) {
       Partial->setTemplateParameterListsInfo(
@@ -9652,6 +9649,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
     Specialization = ClassTemplateSpecializationDecl::Create(
         Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
         ClassTemplate, CanonicalConverted, PrevDecl);
+    Specialization->setTemplateArgsAsWritten(TemplateArgs);
     SetNestedNameSpecifier(*this, Specialization, SS);
     if (TemplateParameterLists.size() > 0) {
       Specialization->setTemplateParameterListsInfo(Context,
@@ -9735,21 +9733,6 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
       << (isPartialSpecialization? 1 : 0)
       << FixItHint::CreateRemoval(ModulePrivateLoc);
 
-  // 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
-  // from the specialization's declaration the way that the user
-  // actually wrote the specialization, rather than formatting the
-  // name based on the "canonical" representation used to store the
-  // template arguments in the specialization.
-  TypeSourceInfo *WrittenTy
-    = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
-                                                TemplateArgs, CanonType);
-  if (TUK != TUK_Friend) {
-    Specialization->setTypeAsWritten(WrittenTy);
-    Specialization->setTemplateKeywordLoc(TemplateKWLoc);
-  }
-
   // C++ [temp.expl.spec]p9:
   //   A template explicit specialization is in the scope of the
   //   namespace in which the template was defined.
@@ -9765,6 +9748,15 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
     Specialization->startDefinition();
 
   if (TUK == TUK_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
+    // from the specialization's declaration the way that the user
+    // actually wrote the specialization, rather than formatting the
+    // name based on the "canonical" representation used to store the
+    // template arguments in the specialization.
+    TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo(
+        Name, TemplateNameLoc, TemplateArgs, CanonType);
     FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
                                             TemplateNameLoc,
                                             WrittenTy,
@@ -10999,21 +10991,10 @@ DeclResult Sema::ActOnExplicitInstantiation(
     }
   }
 
-  // Build the fully-sugared type for this explicit instantiation as
-  // the user wrote in the explicit instantiation itself. This means
-  // that we'll pretty-print the type retrieved from the
-  // specialization's declaration the way that the user actually wrote
-  // the explicit instantiation, rather than formatting the name based
-  // on the "canonical" representation used to store the template
-  // arguments in the specialization.
-  TypeSourceInfo *WrittenTy
-    = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
-                                                TemplateArgs,
-                                  Context.getTypeDeclType(Specialization));
-  Specialization->setTypeAsWritten(WrittenTy);
+  Specialization->setTemplateArgsAsWritten(TemplateArgs);
 
   // Set source locations for keywords.
-  Specialization->setExternLoc(ExternLoc);
+  Specialization->setExternKeywordLoc(ExternLoc);
   Specialization->setTemplateKeywordLoc(TemplateLoc);
   Specialization->setBraceRange(SourceRange());
 
@@ -11426,6 +11407,11 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
     if (!HasNoEffect) {
       // Instantiate static data member or variable template.
       Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+      if (auto *VTSD = dyn_cast(Prev)) {
+        VTSD->setExternKeywordLoc(ExternLoc);
+        VTSD->setTemplateKeywordLoc(TemplateLoc);
+      }
+
       // Merge attributes.
       ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes());
       if (PrevTemplate)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e0c1f814f852..381d79b2fcd4 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3861,15 +3861,16 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
 
   // Substitute into the template arguments of the class template explicit
   // specialization.
-  TemplateSpecializationTypeLoc Loc = D->getTypeAsWritten()->getTypeLoc().
-                                        castAs();
-  TemplateArgumentListInfo InstTemplateArgs(Loc.getLAngleLoc(),
-                                            Loc.getRAngleLoc());
-  SmallVector ArgLocs;
-  for (unsigned I = 0; I != Loc.getNumArgs(); ++I)
-    ArgLocs.push_back(Loc.getArgLoc(I));
-  if (SemaRef.SubstTemplateArguments(ArgLocs, TemplateArgs, InstTemplateArgs))
-    return nullptr;
+  TemplateArgumentListInfo InstTemplateArgs;
+  if (const ASTTemplateArgumentListInfo *TemplateArgsInfo =
+          D->getTemplateArgsAsWritten()) {
+    InstTemplateArgs.setLAngleLoc(TemplateArgsInfo->getLAngleLoc());
+    InstTemplateArgs.setRAngleLoc(TemplateArgsInfo->getRAngleLoc());
+
+    if (SemaRef.SubstTemplateArguments(TemplateArgsInfo->arguments(),
+                                       TemplateArgs, InstTemplateArgs))
+      return nullptr;
+  }
 
   // Check that the template argument list is well-formed for this
   // class template.
@@ -3923,6 +3924,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
       ClassTemplateSpecializationDecl::Create(
           SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(),
           D->getLocation(), InstClassTemplate, CanonicalConverted, PrevDecl);
+  InstD->setTemplateArgsAsWritten(InstTemplateArgs);
 
   // Add this partial specialization to the set of class template partial
   // specializations.
@@ -3933,28 +3935,10 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
   if (SubstQualifier(D, InstD))
     return nullptr;
 
-  // Build the canonical type that describes the converted template
-  // arguments of the class template explicit specialization.
-  QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
-      TemplateName(InstClassTemplate), CanonicalConverted,
-      SemaRef.Context.getRecordType(InstD));
-
-  // 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
-  // from the specialization's declaration the way that the user
-  // actually wrote the specialization, rather than formatting the
-  // name based on the "canonical" representation used to store the
-  // template arguments in the specialization.
-  TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo(
-      TemplateName(InstClassTemplate), D->getLocation(), InstTemplateArgs,
-      CanonType);
-
   InstD->setAccess(D->getAccess());
   InstD->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation);
   InstD->setSpecializationKind(D->getSpecializationKind());
-  InstD->setTypeAsWritten(WrittenTy);
-  InstD->setExternLoc(D->getExternLoc());
+  InstD->setExternKeywordLoc(D->getExternKeywordLoc());
   InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc());
 
   Owner->addDecl(InstD);
@@ -3988,7 +3972,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
 
   // Substitute the current template arguments.
   if (const ASTTemplateArgumentListInfo *TemplateArgsInfo =
-          D->getTemplateArgsInfo()) {
+          D->getTemplateArgsAsWritten()) {
     VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo->getLAngleLoc());
     VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo->getRAngleLoc());
 
@@ -4046,7 +4030,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
   VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create(
       SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(),
       VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted);
-  Var->setTemplateArgsInfo(TemplateArgsInfo);
+  Var->setTemplateArgsAsWritten(TemplateArgsInfo);
   if (!PrevDecl) {
     void *InsertPos = nullptr;
     VarTemplate->findSpecialization(Converted, InsertPos);
@@ -4288,19 +4272,21 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
   QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
       TemplateName(ClassTemplate), CanonicalConverted);
 
-  // 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
-  // from the specialization's declaration the way that the user
-  // actually wrote the specialization, rather than formatting the
-  // name based on the "canonical" representation used to store the
-  // template arguments in the specialization.
-  TypeSourceInfo *WrittenTy
-    = SemaRef.Context.getTemplateSpecializationTypeInfo(
-                                                    TemplateName(ClassTemplate),
-                                                    PartialSpec->getLocation(),
-                                                    InstTemplateArgs,
-                                                    CanonType);
+  // Create the class template partial specialization declaration.
+  ClassTemplatePartialSpecializationDecl *InstPartialSpec =
+      ClassTemplatePartialSpecializationDecl::Create(
+          SemaRef.Context, PartialSpec->getTagKind(), Owner,
+          PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams,
+          ClassTemplate, CanonicalConverted, CanonType,
+          /*PrevDecl=*/nullptr);
+
+  InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs);
+
+  // Substitute the nested name specifier, if any.
+  if (SubstQualifier(PartialSpec, InstPartialSpec))
+    return nullptr;
+
+  InstPartialSpec->setInstantiatedFromMember(PartialSpec);
 
   if (PrevDecl) {
     // We've already seen a partial specialization with the same template
@@ -4318,28 +4304,14 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
     //
     //   Outer outer; // error: the partial specializations of Inner
     //                          // have the same signature.
-    SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared)
-      << WrittenTy->getType();
+    SemaRef.Diag(InstPartialSpec->getLocation(),
+                 diag::err_partial_spec_redeclared)
+        << InstPartialSpec;
     SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here)
       << SemaRef.Context.getTypeDeclType(PrevDecl);
     return nullptr;
   }
 
-
-  // Create the class template partial specialization declaration.
-  ClassTemplatePartialSpecializationDecl *InstPartialSpec =
-      ClassTemplatePartialSpecializationDecl::Create(
-          SemaRef.Context, PartialSpec->getTagKind(), Owner,
-          PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams,
-          ClassTemplate, CanonicalConverted, InstTemplateArgs, CanonType,
-          nullptr);
-  // Substitute the nested name specifier, if any.
-  if (SubstQualifier(PartialSpec, InstPartialSpec))
-    return nullptr;
-
-  InstPartialSpec->setInstantiatedFromMember(PartialSpec);
-  InstPartialSpec->setTypeAsWritten(WrittenTy);
-
   // Check the completed partial specialization.
   SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec);
 
@@ -4408,46 +4380,6 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
       VarTemplate->findPartialSpecialization(CanonicalConverted, InstParams,
                                              InsertPos);
 
-  // Build the canonical type that describes the converted template
-  // arguments of the variable template partial specialization.
-  QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
-      TemplateName(VarTemplate), CanonicalConverted);
-
-  // Build the fully-sugared type for this variable template
-  // specialization as the user wrote in the specialization
-  // itself. This means that we'll pretty-print the type retrieved
-  // from the specialization's declaration the way that the user
-  // actually wrote the specialization, rather than formatting the
-  // name based on the "canonical" representation used to store the
-  // template arguments in the specialization.
-  TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo(
-      TemplateName(VarTemplate), PartialSpec->getLocation(), InstTemplateArgs,
-      CanonType);
-
-  if (PrevDecl) {
-    // We've already seen a partial specialization with the same template
-    // parameters and template arguments. This can happen, for example, when
-    // substituting the outer template arguments ends up causing two
-    // variable template partial specializations of a member variable template
-    // to have identical forms, e.g.,
-    //
-    //   template
-    //   struct Outer {
-    //     template pair p;
-    //     template pair p;
-    //     template pair p;
-    //   };
-    //
-    //   Outer outer; // error: the partial specializations of Inner
-    //                          // have the same signature.
-    SemaRef.Diag(PartialSpec->getLocation(),
-                 diag::err_var_partial_spec_redeclared)
-        << WrittenTy->getType();
-    SemaRef.Diag(PrevDecl->getLocation(),
-                 diag::note_var_prev_partial_spec_here);
-    return nullptr;
-  }
-
   // Do substitution on the type of the declaration
   TypeSourceInfo *DI = SemaRef.SubstType(
       PartialSpec->getTypeSourceInfo(), TemplateArgs,
@@ -4467,16 +4399,39 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
       VarTemplatePartialSpecializationDecl::Create(
           SemaRef.Context, Owner, PartialSpec->getInnerLocStart(),
           PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(),
-          DI, PartialSpec->getStorageClass(), CanonicalConverted,
-          InstTemplateArgs);
+          DI, PartialSpec->getStorageClass(), CanonicalConverted);
+
+  InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs);
 
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(PartialSpec, InstPartialSpec))
     return nullptr;
 
   InstPartialSpec->setInstantiatedFromMember(PartialSpec);
-  InstPartialSpec->setTypeAsWritten(WrittenTy);
 
+  if (PrevDecl) {
+    // We've already seen a partial specialization with the same template
+    // parameters and template arguments. This can happen, for example, when
+    // substituting the outer template arguments ends up causing two
+    // variable template partial specializations of a member variable template
+    // to have identical forms, e.g.,
+    //
+    //   template
+    //   struct Outer {
+    //     template pair p;
+    //     template pair p;
+    //     template pair p;
+    //   };
+    //
+    //   Outer outer; // error: the partial specializations of Inner
+    //                          // have the same signature.
+    SemaRef.Diag(PartialSpec->getLocation(),
+                 diag::err_var_partial_spec_redeclared)
+        << InstPartialSpec;
+    SemaRef.Diag(PrevDecl->getLocation(),
+                 diag::note_var_prev_partial_spec_here);
+    return nullptr;
+  }
   // Check the completed partial specialization.
   SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec);
 
@@ -5738,7 +5693,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
 
     TemplateArgumentListInfo TemplateArgInfo;
     if (const ASTTemplateArgumentListInfo *ArgInfo =
-            VarSpec->getTemplateArgsInfo()) {
+            VarSpec->getTemplateArgsAsWritten()) {
       TemplateArgInfo.setLAngleLoc(ArgInfo->getLAngleLoc());
       TemplateArgInfo.setRAngleLoc(ArgInfo->getRAngleLoc());
       for (const TemplateArgumentLoc &Arg : ArgInfo->arguments())
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 089ede4f4926..0c647086e304 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2548,16 +2548,17 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
     }
   }
 
-  // Explicit info.
-  if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) {
-    auto *ExplicitInfo =
-        new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo;
-    ExplicitInfo->TypeAsWritten = TyInfo;
-    ExplicitInfo->ExternLoc = readSourceLocation();
+  // extern/template keyword locations for explicit instantiations
+  if (Record.readBool()) {
+    auto *ExplicitInfo = new (C) ExplicitInstantiationInfo;
+    ExplicitInfo->ExternKeywordLoc = readSourceLocation();
     ExplicitInfo->TemplateKeywordLoc = readSourceLocation();
     D->ExplicitInfo = ExplicitInfo;
   }
 
+  if (Record.readBool())
+    D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo());
+
   return Redecl;
 }
 
@@ -2567,7 +2568,6 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
   // need them for profiling
   TemplateParameterList *Params = Record.readTemplateParameterList();
   D->TemplateParams = Params;
-  D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
 
   RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
 
@@ -2617,16 +2617,17 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
     }
   }
 
-  // Explicit info.
-  if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) {
-    auto *ExplicitInfo =
-        new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo;
-    ExplicitInfo->TypeAsWritten = TyInfo;
-    ExplicitInfo->ExternLoc = readSourceLocation();
+  // extern/template keyword locations for explicit instantiations
+  if (Record.readBool()) {
+    auto *ExplicitInfo = new (C) ExplicitInstantiationInfo;
+    ExplicitInfo->ExternKeywordLoc = readSourceLocation();
     ExplicitInfo->TemplateKeywordLoc = readSourceLocation();
     D->ExplicitInfo = ExplicitInfo;
   }
 
+  if (Record.readBool())
+    D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo());
+
   SmallVector TemplArgs;
   Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
   D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
@@ -2666,7 +2667,6 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
     VarTemplatePartialSpecializationDecl *D) {
   TemplateParameterList *Params = Record.readTemplateParameterList();
   D->TemplateParams = Params;
-  D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
 
   RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
 
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 6201d284f0e0..c2f1d1b44241 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1765,20 +1765,28 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
     Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl());
   }
 
-  // Explicit info.
-  Record.AddTypeSourceInfo(D->getTypeAsWritten());
-  if (D->getTypeAsWritten()) {
-    Record.AddSourceLocation(D->getExternLoc());
+  bool ExplicitInstantiation =
+      D->getTemplateSpecializationKind() ==
+          TSK_ExplicitInstantiationDeclaration ||
+      D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition;
+  Record.push_back(ExplicitInstantiation);
+  if (ExplicitInstantiation) {
+    Record.AddSourceLocation(D->getExternKeywordLoc());
     Record.AddSourceLocation(D->getTemplateKeywordLoc());
   }
 
+  const ASTTemplateArgumentListInfo *ArgsWritten =
+      D->getTemplateArgsAsWritten();
+  Record.push_back(!!ArgsWritten);
+  if (ArgsWritten)
+    Record.AddASTTemplateArgumentListInfo(ArgsWritten);
+
   Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION;
 }
 
 void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl(
                                     ClassTemplatePartialSpecializationDecl *D) {
   Record.AddTemplateParameterList(D->getTemplateParameters());
-  Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten());
 
   VisitClassTemplateSpecializationDecl(D);
 
@@ -1812,13 +1820,22 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
     Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs());
   }
 
-  // Explicit info.
-  Record.AddTypeSourceInfo(D->getTypeAsWritten());
-  if (D->getTypeAsWritten()) {
-    Record.AddSourceLocation(D->getExternLoc());
+  bool ExplicitInstantiation =
+      D->getTemplateSpecializationKind() ==
+          TSK_ExplicitInstantiationDeclaration ||
+      D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition;
+  Record.push_back(ExplicitInstantiation);
+  if (ExplicitInstantiation) {
+    Record.AddSourceLocation(D->getExternKeywordLoc());
     Record.AddSourceLocation(D->getTemplateKeywordLoc());
   }
 
+  const ASTTemplateArgumentListInfo *ArgsWritten =
+      D->getTemplateArgsAsWritten();
+  Record.push_back(!!ArgsWritten);
+  if (ArgsWritten)
+    Record.AddASTTemplateArgumentListInfo(ArgsWritten);
+
   Record.AddTemplateArgumentList(&D->getTemplateArgs());
   Record.AddSourceLocation(D->getPointOfInstantiation());
   Record.push_back(D->getSpecializationKind());
@@ -1839,7 +1856,6 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
 void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl(
     VarTemplatePartialSpecializationDecl *D) {
   Record.AddTemplateParameterList(D->getTemplateParameters());
-  Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten());
 
   VisitVarTemplateSpecializationDecl(D);
 
diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp
index cd0261989495..3e50d67f4d6e 100644
--- a/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -735,7 +735,8 @@ public:
     auto *Declaration =
         cast(handleFreeStandingTagDecl(C));
     foldExplicitTemplateInstantiation(
-        Builder.getTemplateRange(C), Builder.findToken(C->getExternLoc()),
+        Builder.getTemplateRange(C),
+        Builder.findToken(C->getExternKeywordLoc()),
         Builder.findToken(C->getTemplateKeywordLoc()), Declaration, C);
     return true;
   }
diff --git a/clang/test/AST/ast-dump-decl.cpp b/clang/test/AST/ast-dump-decl.cpp
index d74aa9045532..554cdcf83fcd 100644
--- a/clang/test/AST/ast-dump-decl.cpp
+++ b/clang/test/AST/ast-dump-decl.cpp
@@ -613,15 +613,15 @@ namespace testCanonicalTemplate {
   // CHECK:      VarTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-11]]:7, col:43> col:43 TestVarTemplate{{$}}
   // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}}  col:25 referenced typename depth 0 index 0 T{{$}}
   // CHECK-NEXT: |-VarDecl 0x{{.+}}  col:43 TestVarTemplate 'const T' static{{$}}
-  // CHECK-NEXT: |-VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}}  col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit{{$}}
+  // CHECK-NEXT: |-VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}}  col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit{{$}}
   // CHECK-NEXT: | |-NestedNameSpecifier TypeSpec 'testCanonicalTemplate::S'{{$}}
   // CHECK-NEXT: | |-TemplateArgument type 'int'{{$}}
   // CHECK-NEXT: | | `-BuiltinType 0x{{.+}} 'int'{{$}}
   // CHECK-NEXT: | `-InitListExpr 0x{{.+}}  'int'{{$}}
-  // CHECK-NEXT: `-VarTemplateSpecializationDecl 0x{{.+}}  col:43 referenced TestVarTemplate 'const int' implicit_instantiation static{{$}}
+  // CHECK-NEXT: `-VarTemplateSpecializationDecl 0x{{.+}}  col:43 referenced TestVarTemplate 'const int' implicit_instantiation static{{$}}
   // CHECK-NEXT:   `-TemplateArgument type 'int'{{$}}
 
-  // CHECK:     VarTemplateSpecializationDecl 0x{{.+}} <{{.+}}:[[@LINE-22]]:28, col:43> col:43 referenced TestVarTemplate 'const int' implicit_instantiation static{{$}}
+  // CHECK:     VarTemplateSpecializationDecl 0x{{.+}} <{{.+}}:[[@LINE-22]]:7, col:43> col:43 referenced TestVarTemplate 'const int' implicit_instantiation static{{$}}
   // CHECK-NEXT:`-TemplateArgument type 'int'{{$}}
   // CHECK-NEXT:  `-BuiltinType 0x{{.+}} 'int'{{$}}
 
@@ -632,13 +632,13 @@ namespace testCanonicalTemplate {
   // CHECK-NEXT: | `-InitListExpr 0x{{.+}}  'void'{{$}}
   // CHECK-NEXT: |-VarTemplateSpecialization 0x{{.+}} 'TestVarTemplate' 'const int'{{$}}
   // CHECK-NEXT: `-VarTemplateSpecialization 0x{{.+}} 'TestVarTemplate' 'const int'{{$}}
-    
-  // CHECK:      VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-31]]:3, col:34> col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit{{$}}
+
+  // CHECK:      VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-32]]:3, line:[[@LINE-31]]:34> col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit{{$}}
   // CHECK-NEXT: |-NestedNameSpecifier TypeSpec 'testCanonicalTemplate::S'{{$}}
   // CHECK-NEXT: |-TemplateArgument type 'int'{{$}}
   // CHECK-NEXT: | `-BuiltinType 0x{{.+}} 'int'{{$}}
   // CHECK-NEXT: `-InitListExpr 0x{{.+}}  'int'{{$}}
-} 
+}
 
 template 
 class TestClassScopeFunctionSpecialization {
diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp
index 142bc9e6ad9a..37f6d8a0472d 100644
--- a/clang/test/AST/ast-dump-template-decls.cpp
+++ b/clang/test/AST/ast-dump-template-decls.cpp
@@ -1,12 +1,12 @@
 // Test without serialization:
 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -ast-dump %s \
-// RUN: | FileCheck -strict-whitespace %s --check-prefix=DIRECT
+// RUN: | FileCheck -strict-whitespace %s
 //
 // Test with serialization:
 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -emit-pch -o %t %s
 // RUN: %clang_cc1 -x c++ -std=c++17 -triple x86_64-unknown-unknown -include-pch %t -ast-dump-all /dev/null \
 // RUN: | sed -e "s/ //" -e "s/ imported//" \
-// RUN: | FileCheck --strict-whitespace %s --check-prefix=SERIALIZED
+// RUN: | FileCheck --strict-whitespace %s
 
 template 
 // CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <{{.*}}:1, line:[[@LINE+2]]:10> col:6 a
@@ -189,15 +189,13 @@ T unTempl = 1;
 
 template<>
 int unTempl;
-// FIXME (#61680) - serializing and loading AST should not affect reported source range
-// DIRECT:     VarTemplateSpecializationDecl 0x{{[^ ]*}}  col:5 unTempl 'int'
-// SERIALIZED: VarTemplateSpecializationDecl 0x{{[^ ]*}}  col:5 unTempl 'int'
+// CHECK:      VarTemplateSpecializationDecl 0x{{[^ ]*}}  col:5 unTempl 'int'
 // CHECK-NEXT: `-TemplateArgument type 'int'
 // CHECK-NEXT: `-BuiltinType 0x{{[^ ]*}} 'int'
 
 template<>
 float unTempl = 1;
-// CHECK:      VarTemplateSpecializationDecl 0x{{[^ ]*}}  col:7 unTempl 'float' cinit
+// CHECK:      VarTemplateSpecializationDecl 0x{{[^ ]*}}  col:7 unTempl 'float'
 // CHECK-NEXT: |-TemplateArgument type 'float'
 // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'float'
 // CHECK-NEXT: `-ImplicitCastExpr 0x{{[^ ]*}}  'float' 
@@ -222,7 +220,7 @@ int binTempl;
 
 template
 float binTempl = 1;
-// CHECK:      VarTemplatePartialSpecializationDecl 0x{{[^ ]*}}  col:7 binTempl 'float' cinit
+// CHECK:      VarTemplatePartialSpecializationDecl 0x{{[^ ]*}}  col:7 binTempl 'float'
 // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{[^ ]*}}  col:16 referenced class depth 0 index 0 U
 // CHECK-NEXT: |-TemplateArgument type 'float'
 // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'float'
@@ -233,9 +231,7 @@ float binTempl = 1;
 
 template<>
 int binTempl;
-// FIXME (#61680) - serializing and loading AST should not affect reported source range
-// DIRECT:     VarTemplateSpecializationDecl 0x{{[^ ]*}}  col:5 binTempl 'int'
-// SERIALIZED: VarTemplateSpecializationDecl 0x{{[^ ]*}}  col:5 binTempl 'int'
+// CHECK:      VarTemplateSpecializationDecl 0x{{[^ ]*}}  col:5 binTempl 'int'
 // CHECK-NEXT: |-TemplateArgument type 'int'
 // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int'
 // CHECK-NEXT: `-TemplateArgument type 'int'
@@ -243,7 +239,7 @@ int binTempl;
 
 template<>
 float binTempl = 1;
-// CHECK:     VarTemplateSpecializationDecl 0x{{[^ ]*}}  col:7 binTempl 'float' cinit
+// CHECK:      VarTemplateSpecializationDecl 0x{{[^ ]*}}  col:7 binTempl 'float'
 // CHECK-NEXT: |-TemplateArgument type 'float'
 // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'float'
 // CHECK-NEXT: |-TemplateArgument type 'float'
diff --git a/clang/test/Index/Core/index-source.cpp b/clang/test/Index/Core/index-source.cpp
index 8f9fbc4c8d29..043e616a1d36 100644
--- a/clang/test/Index/Core/index-source.cpp
+++ b/clang/test/Index/Core/index-source.cpp
@@ -285,20 +285,17 @@ template<>
 class SpecializationDecl;
 // CHECK: [[@LINE-1]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I |  | Decl,RelSpecialization | rel: 1
 // CHECK-NEXT: RelSpecialization | SpecializationDecl | c:@ST>1#T@SpecializationDecl
-// CHECK: [[@LINE-3]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I |  | Ref | rel: 0
 
 template<>
 class SpecializationDecl { };
 // CHECK: [[@LINE-1]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I |  | Def,RelSpecialization | rel: 1
 // CHECK-NEXT: RelSpecialization | SpecializationDecl | c:@ST>1#T@SpecializationDecl
-// CHECK-NEXT: [[@LINE-3]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I |  | Ref | rel: 0
 
 template
 class PartialSpecilizationClass;
 // CHECK: [[@LINE-1]]:7 | class(Gen,TPS)/C++ | PartialSpecilizationClass | c:@SP>1#T@PartialSpecilizationClass>#$@S@Cls#t0.0 |  | Decl,RelSpecialization | rel: 1
 // CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass
-// CHECK: [[@LINE-3]]:7 | class(Gen)/C++ | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass |  | Ref | rel: 0
-// CHECK-NEXT: [[@LINE-4]]:33 | class/C++ | Cls | c:@S@Cls |  | Ref | rel: 0
+// CHECK-NEXT: [[@LINE-3]]:33 | class/C++ | Cls | c:@S@Cls |  | Ref,RelCont | rel: 1
 
 template<>
 class PartialSpecilizationClass : Cls { };
@@ -306,9 +303,10 @@ class PartialSpecilizationClass : Cls { };
 // CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass
 // CHECK-NEXT: [[@LINE-3]]:45 | class/C++ | Cls | c:@S@Cls |  | Ref,RelBase,RelCont | rel: 1
 // CHECK-NEXT: RelBase,RelCont | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_
-// CHECK-NEXT: [[@LINE-5]]:7 | class(Gen,TS)/C++ | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_ |  | Ref | rel: 0
-// CHECK-NEXT: [[@LINE-6]]:33 | class/C++ | Cls | c:@S@Cls |  | Ref | rel: 0
-// CHECK-NEXT: [[@LINE-7]]:38 | class/C++ | Cls | c:@S@Cls |  | Ref | rel: 0
+// CHECK-NEXT: [[@LINE-5]]:33 | class/C++ | Cls | c:@S@Cls |  | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_
+// CHECK-NEXT: [[@LINE-7]]:38 | class/C++ | Cls | c:@S@Cls |  | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_
 
 template
 void functionSp() { }
@@ -332,10 +330,14 @@ class ClassWithCorrectSpecialization { };
 
 template<>
 class ClassWithCorrectSpecialization, Record::C> { };
-// CHECK: [[@LINE-1]]:38 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl |  | Ref | rel: 0
-// CHECK: [[@LINE-2]]:57 | class/C++ | Cls | c:@S@Cls |  | Ref | rel: 0
-// CHECK: [[@LINE-3]]:71 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read | rel: 0
-// CHECK: [[@LINE-4]]:63 | struct/C++ | Record | c:@S@Record |  | Ref | rel: 0
+// CHECK: [[@LINE-1]]:38 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl |  | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2
+// CHECK-NEXT: [[@LINE-3]]:57 | class/C++ | Cls | c:@S@Cls |  | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2
+// CHECK-NEXT: [[@LINE-5]]:71 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read,RelCont | rel: 1
+// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2
+// CHECK-NEXT: [[@LINE-7]]:63 | struct/C++ | Record | c:@S@Record |  | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2
 
 namespace ns {
 // CHECK: [[@LINE-1]]:11 | namespace/C++ | ns | c:@N@ns |  | Decl | rel: 0
diff --git a/clang/test/Index/index-refs.cpp b/clang/test/Index/index-refs.cpp
index 0e613e48522b..14946849777d 100644
--- a/clang/test/Index/index-refs.cpp
+++ b/clang/test/Index/index-refs.cpp
@@ -108,7 +108,6 @@ int ginitlist[] = {EnumVal};
 // CHECK:      [indexDeclaration]: kind: c++-class-template | name: TS | {{.*}} | loc: 47:8
 // CHECK-NEXT: [indexDeclaration]: kind: struct-template-partial-spec | name: TS | USR: c:@SP>1#T@TS>#t0.0#I | {{.*}} | loc: 50:8
 // CHECK-NEXT: [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@SP>1#T@TS>#t0.0#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8]
-// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: TS | USR: c:@ST>2#T#T@TS | lang: C++ | cursor: TemplateRef=TS:47:8 | loc: 50:8 | :: <> | container: [TU] | refkind: direct | role: ref
 /* when indexing implicit instantiations
   [indexDeclaration]: kind: struct-template-spec | name: TS | USR: c:@S@TS>#I | {{.*}} | loc: 50:8
   [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@593@S@TS>#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8]
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 8b9417f985b5..bfbdb5be9ff2 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -743,14 +743,10 @@ bool CursorVisitor::VisitClassTemplateSpecializationDecl(
   }
 
   // Visit the template arguments used in the specialization.
-  if (TypeSourceInfo *SpecType = D->getTypeAsWritten()) {
-    TypeLoc TL = SpecType->getTypeLoc();
-    if (TemplateSpecializationTypeLoc TSTLoc =
-            TL.getAs()) {
-      for (unsigned I = 0, N = TSTLoc.getNumArgs(); I != N; ++I)
-        if (VisitTemplateArgumentLoc(TSTLoc.getArgLoc(I)))
-          return true;
-    }
+  if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) {
+    for (const TemplateArgumentLoc &Arg : ArgsWritten->arguments())
+      if (VisitTemplateArgumentLoc(Arg))
+        return true;
   }
 
   return ShouldVisitBody && VisitCXXRecordDecl(D);
@@ -5667,16 +5663,19 @@ CXString clang_getCursorDisplayName(CXCursor C) {
 
   if (const ClassTemplateSpecializationDecl *ClassSpec =
           dyn_cast(D)) {
-    // If the type was explicitly written, use that.
-    if (TypeSourceInfo *TSInfo = ClassSpec->getTypeAsWritten())
-      return cxstring::createDup(TSInfo->getType().getAsString(Policy));
-
     SmallString<128> Str;
     llvm::raw_svector_ostream OS(Str);
     OS << *ClassSpec;
-    printTemplateArgumentList(
-        OS, ClassSpec->getTemplateArgs().asArray(), Policy,
-        ClassSpec->getSpecializedTemplate()->getTemplateParameters());
+    // If the template arguments were written explicitly, use them..
+    if (const auto *ArgsWritten = ClassSpec->getTemplateArgsAsWritten()) {
+      printTemplateArgumentList(
+          OS, ArgsWritten->arguments(), Policy,
+          ClassSpec->getSpecializedTemplate()->getTemplateParameters());
+    } else {
+      printTemplateArgumentList(
+          OS, ClassSpec->getTemplateArgs().asArray(), Policy,
+          ClassSpec->getSpecializedTemplate()->getTemplateParameters());
+    }
     return cxstring::createDup(OS.str());
   }
 
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index b76627cb9be6..65df513d2713 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2213,18 +2213,6 @@ TEST_P(ASTMatchersTest, ReferenceTypeLocTest_BindsToAnyRvalueReferenceTypeLoc) {
   EXPECT_TRUE(matches("float&& r = 3.0;", matcher));
 }
 
-TEST_P(
-    ASTMatchersTest,
-    TemplateSpecializationTypeLocTest_BindsToTemplateSpecializationExplicitInstantiation) {
-  if (!GetParam().isCXX()) {
-    return;
-  }
-  EXPECT_TRUE(
-      matches("template  class C {}; template class C;",
-              classTemplateSpecializationDecl(
-                  hasName("C"), hasTypeLoc(templateSpecializationTypeLoc()))));
-}
-
 TEST_P(ASTMatchersTest,
        TemplateSpecializationTypeLocTest_BindsToVarDeclTemplateSpecialization) {
   if (!GetParam().isCXX()) {
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index f198dc71eb83..af99c73f1945 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -430,12 +430,6 @@ TEST(HasTypeLoc, MatchesCXXUnresolvedConstructExpr) {
               cxxUnresolvedConstructExpr(hasTypeLoc(loc(asString("T"))))));
 }
 
-TEST(HasTypeLoc, MatchesClassTemplateSpecializationDecl) {
-  EXPECT_TRUE(matches(
-      "template  class Foo; template <> class Foo {};",
-      classTemplateSpecializationDecl(hasTypeLoc(loc(asString("Foo"))))));
-}
-
 TEST(HasTypeLoc, MatchesCompoundLiteralExpr) {
   EXPECT_TRUE(
       matches("int* x = (int[2]) { 0, 1 };",
@@ -6384,8 +6378,7 @@ TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {
       "template class A {}; template<> class A {};",
       classTemplateSpecializationDecl(
           hasName("A"),
-          hasTypeLoc(templateSpecializationTypeLoc(
-              hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))))));
+          hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));
 }
 
 TEST(HasAnyTemplateArgumentLoc,
@@ -6394,8 +6387,7 @@ TEST(HasAnyTemplateArgumentLoc,
       "template class A {}; template<> class A {};",
       classTemplateSpecializationDecl(
           hasName("A"),
-          hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
-              hasTypeLoc(loc(asString("double")))))))));
+          hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));
 }
 
 TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
@@ -6405,24 +6397,20 @@ TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
   )";
   EXPECT_TRUE(
       matches(code, classTemplateSpecializationDecl(
-                        hasName("A"), hasTypeLoc(templateSpecializationTypeLoc(
-                                          hasAnyTemplateArgumentLoc(hasTypeLoc(
-                                              loc(asString("double")))))))));
+                        hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(
+                                          loc(asString("double")))))));
+
   EXPECT_TRUE(matches(
-      code,
-      classTemplateSpecializationDecl(
-          hasName("A"),
-          hasTypeLoc(templateSpecializationTypeLoc(
-              hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))))));
+      code, classTemplateSpecializationDecl(
+                hasName("A"),
+                hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));
 }
 
 TEST(HasAnyTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
-  EXPECT_TRUE(notMatches(
-      "template class A {}; A a;",
-      classTemplateSpecializationDecl(
-          hasName("A"),
-          hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
-              hasTypeLoc(loc(asString("double")))))))));
+  EXPECT_TRUE(notMatches("template class A {}; A a;",
+                         classTemplateSpecializationDecl(
+                             hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(
+                                               loc(asString("double")))))));
 }
 
 TEST(HasAnyTemplateArgumentLoc,
@@ -6431,8 +6419,7 @@ TEST(HasAnyTemplateArgumentLoc,
       "template class A {}; template<> class A {};",
       classTemplateSpecializationDecl(
           hasName("A"),
-          hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
-              hasTypeLoc(loc(asString("double")))))))));
+          hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));
 }
 
 TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {
@@ -6453,13 +6440,21 @@ TEST(HasTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {
                               0, hasTypeLoc(loc(asString("double")))))))))));
 }
 
+TEST(HasTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
+  EXPECT_TRUE(notMatches(
+      "template class A {}; A a;",
+      varDecl(hasName("a"),
+              hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
+                  templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+                      0, hasTypeLoc(loc(asString("double")))))))))));
+}
+
 TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {
   EXPECT_TRUE(matches(
       "template class A {}; template<> class A {};",
       classTemplateSpecializationDecl(
           hasName("A"),
-          hasTypeLoc(templateSpecializationTypeLoc(
-              hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))))));
+          hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
 }
 
 TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) {
@@ -6467,8 +6462,7 @@ TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) {
       "template class A {}; template<> class A {};",
       classTemplateSpecializationDecl(
           hasName("A"),
-          hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
-              0, hasTypeLoc(loc(asString("double")))))))));
+          hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
 }
 
 TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
@@ -6478,23 +6472,12 @@ TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
   )";
   EXPECT_TRUE(matches(
       code, classTemplateSpecializationDecl(
-                hasName("A"),
-                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
-                    0, hasTypeLoc(loc(asString("double")))))))));
+                hasName("A"), hasTemplateArgumentLoc(
+                                  0, hasTypeLoc(loc(asString("double")))))));
   EXPECT_TRUE(matches(
       code, classTemplateSpecializationDecl(
                 hasName("A"),
-                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
-                    1, hasTypeLoc(loc(asString("int")))))))));
-}
-
-TEST(HasTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
-  EXPECT_TRUE(notMatches(
-      "template class A {}; A a;",
-      classTemplateSpecializationDecl(
-          hasName("A"),
-          hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
-              0, hasTypeLoc(loc(asString("double")))))))));
+                hasTemplateArgumentLoc(1, hasTypeLoc(loc(asString("int")))))));
 }
 
 TEST(HasTemplateArgumentLoc,
@@ -6503,8 +6486,7 @@ TEST(HasTemplateArgumentLoc,
       "template class A {}; template<> class A {};",
       classTemplateSpecializationDecl(
           hasName("A"),
-          hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
-              0, hasTypeLoc(loc(asString("double")))))))));
+          hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
 }
 
 TEST(HasTemplateArgumentLoc,
@@ -6515,14 +6497,12 @@ TEST(HasTemplateArgumentLoc,
   )";
   EXPECT_TRUE(notMatches(
       code, classTemplateSpecializationDecl(
-                hasName("A"),
-                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
-                    1, hasTypeLoc(loc(asString("double")))))))));
+                hasName("A"), hasTemplateArgumentLoc(
+                                  1, hasTypeLoc(loc(asString("double")))))));
   EXPECT_TRUE(notMatches(
       code, classTemplateSpecializationDecl(
                 hasName("A"),
-                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
-                    0, hasTypeLoc(loc(asString("int")))))))));
+                hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
 }
 
 TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) {
@@ -6532,14 +6512,12 @@ TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) {
   )";
   EXPECT_TRUE(notMatches(
       code, classTemplateSpecializationDecl(
-                hasName("A"),
-                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
-                    -1, hasTypeLoc(loc(asString("double")))))))));
+                hasName("A"), hasTemplateArgumentLoc(
+                                  -1, hasTypeLoc(loc(asString("double")))))));
   EXPECT_TRUE(notMatches(
       code, classTemplateSpecializationDecl(
-                hasName("A"),
-                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
-                    100, hasTypeLoc(loc(asString("int")))))))));
+                hasName("A"), hasTemplateArgumentLoc(
+                                  100, hasTypeLoc(loc(asString("int")))))));
 }
 
 TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithIntArgument) {
-- 
GitLab


From fb8f492a1ccb2236a82701c76f82960fd6cdb725 Mon Sep 17 00:00:00 2001
From: Peiming Liu 
Date: Tue, 14 May 2024 13:26:49 -0700
Subject: [PATCH 277/578] =?UTF-8?q?[mlir][sparse]=20clone=20a=20empty=20sp?=
 =?UTF-8?q?arse=20tensor=20when=20fuse=20convert=20into=20pro=E2=80=A6=20(?=
 =?UTF-8?q?#92158)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

…ducer.
---
 .../Transforms/SparseTensorRewriting.cpp      | 14 +++---
 .../fuse_sparse_convert_into_producer.mlir    | 44 +++++++++++++++++++
 2 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp
index da635c257888..5fb009e3eebe 100644
--- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp
+++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp
@@ -302,17 +302,17 @@ public:
         !producer.getResult(0).hasOneUse()) {
       return failure();
     }
+    // Clone the materialization operation, but update the result to sparse.
+    rewriter.setInsertionPoint(producer);
+    Operation *init = producer.getDpsInitOperand(0)->get().getDefiningOp();
+    Operation *cloned = rewriter.clone(*init);
+    cloned->getResult(0).setType(op.getResult().getType());
+
     rewriter.modifyOpInPlace(producer, [&]() {
+      producer.getDpsInitsMutable().assign(cloned->getResults());
       producer.getResult(0).setType(op.getResult().getType());
     });
 
-    Operation *materializeOp =
-        producer.getDpsInitOperand(0)->get().getDefiningOp();
-
-    rewriter.modifyOpInPlace(materializeOp, [&]() {
-      materializeOp->getResult(0).setType(op.getResult().getType());
-    });
-
     rewriter.replaceAllOpUsesWith(op, producer);
     op->erase();
 
diff --git a/mlir/test/Dialect/SparseTensor/fuse_sparse_convert_into_producer.mlir b/mlir/test/Dialect/SparseTensor/fuse_sparse_convert_into_producer.mlir
index efa92e565ba5..4e4d2c27b096 100644
--- a/mlir/test/Dialect/SparseTensor/fuse_sparse_convert_into_producer.mlir
+++ b/mlir/test/Dialect/SparseTensor/fuse_sparse_convert_into_producer.mlir
@@ -54,6 +54,50 @@ func.func @fold_convert(%arg0: tensor<128x32x32x1xf32>, %arg1: tensor<128x32x32x
   return %2 : tensor<128x32x32x1xf32, #CCCD>
 }
 
+#trait_bin = {
+  indexing_maps = [
+      affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)>,
+      affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)>,
+      affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)>
+  ],
+  iterator_types = ["parallel", "parallel", "parallel", "parallel"]
+}
+
+// CHECK-FOLD-LABEL:   func.func @fold_convert_multi_use(
+// CHECK-FOLD:           tensor.empty() : tensor<128x32x32x1xf32>
+// CHECK-FOLD:           linalg.generic
+// CHECK-FOLD:           tensor.empty() : tensor<128x32x32x1xf32, #sparse>
+// CHECK-FOLD:           linalg.generic
+// CHECK-FOLD-NOT:       sparse_tensor.convert
+func.func @fold_convert_multi_use(%arg0: tensor<128x32x32x1xf32>, %arg1: tensor<128x32x32x1xf32>,
+                        %arg2: tensor<128x32x32x1xf32>, %arg3: tensor<128x32x32x1xf32>) -> (tensor<128x32x32x1xf32>, tensor<128x32x32x1xf32, #CCCD>) {
+  %cst = arith.constant 0.000000e+00 : f32
+  %cst_0 = arith.constant 1.000000e+00 : f32
+  %cst_1 = arith.constant 1.000000e+00 : f32
+
+  %0 = tensor.empty() : tensor<128x32x32x1xf32>
+  %1 = linalg.generic #trait_bin
+  ins(%arg0, %arg1 : tensor<128x32x32x1xf32>, tensor<128x32x32x1xf32>)
+  outs(%0 : tensor<128x32x32x1xf32>) {
+    ^bb0(%in: f32, %in_1: f32, %out: f32):
+      %3 = arith.mulf %in, %in_1 : f32
+      linalg.yield %3 : f32
+    } -> tensor<128x32x32x1xf32>
+
+  // A second kernel that uses %0 as the init operand.
+  %3 = linalg.generic #trait_bin
+  ins(%arg2, %arg3 : tensor<128x32x32x1xf32>, tensor<128x32x32x1xf32>)
+  outs(%0 : tensor<128x32x32x1xf32>) {
+    ^bb0(%in: f32, %in_1: f32, %out: f32):
+      %3 = arith.mulf %in, %in_1 : f32
+      linalg.yield %3 : f32
+    } -> tensor<128x32x32x1xf32>
+  %4 = sparse_tensor.convert %3 : tensor<128x32x32x1xf32> to tensor<128x32x32x1xf32, #CCCD>
+
+  return %1, %4 : tensor<128x32x32x1xf32>, tensor<128x32x32x1xf32, #CCCD>
+}
+
+
 
 // FIXME: The following kernel is not sparsifiable because `arith.select`
 // operations is not handled by the sparse compiler at the moment.
-- 
GitLab


From baca93fc83ee3b9ef32cd328dc4275a06177c8c7 Mon Sep 17 00:00:00 2001
From: Philip Reames 
Date: Tue, 14 May 2024 13:33:31 -0700
Subject: [PATCH 278/578] [LSR] Tweak debug output to always print initial cost

---
 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp             | 4 ++--
 .../LoopStrengthReduce/RISCV/lsr-drop-solution-dbg-msg.ll     | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index eb1904ccaff3..35a17d6060c9 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -5251,8 +5251,6 @@ void LSRInstance::Solve(SmallVectorImpl &Solution) const {
   assert(Solution.size() == Uses.size() && "Malformed solution!");
 
   if (BaselineCost.isLess(SolutionCost)) {
-    LLVM_DEBUG(dbgs() << "The baseline solution requires ";
-               BaselineCost.print(dbgs()); dbgs() << "\n");
     if (!AllowDropSolutionIfLessProfitable)
       LLVM_DEBUG(
           dbgs() << "Baseline is more profitable than chosen solution, "
@@ -5931,6 +5929,8 @@ LSRInstance::LSRInstance(Loop *L, IVUsers &IU, ScalarEvolution &SE,
 
   LLVM_DEBUG(dbgs() << "LSR found " << Uses.size() << " uses:\n";
              print_uses(dbgs()));
+  LLVM_DEBUG(dbgs() << "The baseline solution requires ";
+             BaselineCost.print(dbgs()); dbgs() << "\n");
 
   // Now use the reuse data to generate a bunch of interesting ways
   // to formulate the values needed for the uses.
diff --git a/llvm/test/Transforms/LoopStrengthReduce/RISCV/lsr-drop-solution-dbg-msg.ll b/llvm/test/Transforms/LoopStrengthReduce/RISCV/lsr-drop-solution-dbg-msg.ll
index 37876a907124..8d9d43202f0d 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/RISCV/lsr-drop-solution-dbg-msg.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/RISCV/lsr-drop-solution-dbg-msg.ll
@@ -6,8 +6,8 @@ target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
 target triple = "riscv64-unknown-linux-gnu"
 
 define ptr @foo(ptr %a0, ptr %a1, i64 %a2) {
-;DEBUG: The chosen solution requires 3 instructions 6 regs, with addrec cost 1, plus 2 base adds, plus 5 setup cost
 ;DEBUG: The baseline solution requires 2 instructions 4 regs, with addrec cost 2, plus 3 setup cost
+;DEBUG: The chosen solution requires 3 instructions 6 regs, with addrec cost 1, plus 2 base adds, plus 5 setup cost
 ;DEBUG: Baseline is more profitable than chosen solution, dropping LSR solution.
 
 ;DEBUG2: Baseline is more profitable than chosen solution, add option 'lsr-drop-solution' to drop LSR solution.
-- 
GitLab


From f83df080a817c99e90ed1a0bd5693c5f07ebf567 Mon Sep 17 00:00:00 2001
From: Florian Mayer 
Date: Tue, 14 May 2024 13:35:04 -0700
Subject: [PATCH 279/578] [NFC] add comment to keep RegState in sync with doc
 (#92170)

---
 llvm/include/llvm/CodeGen/MachineInstrBuilder.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
index a5b8d3af3cc9..0a73b0f6b367 100644
--- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -40,6 +40,7 @@ class MDNode;
 
 namespace RegState {
 
+// Keep this in sync with the table in MIRLangRef.rst.
 enum {
   /// Register definition.
   Define = 0x2,
-- 
GitLab


From f918c056f06968763870bc3e6b9f9d7074e1f867 Mon Sep 17 00:00:00 2001
From: Keith Smiley 
Date: Tue, 14 May 2024 13:43:04 -0700
Subject: [PATCH 280/578] [lldb] Allow env override for LLDB_ARGDUMPER_PATH
 (#91688)

This mirrors the LLDB_DEBUGSERVER_PATH environment variable and allows
you to have lldb-argdumper in a non-standard location and still use it
at runtime.
---
 lldb/source/Host/macosx/objcxx/Host.mm | 35 ++++++++++++++++++--------
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/lldb/source/Host/macosx/objcxx/Host.mm b/lldb/source/Host/macosx/objcxx/Host.mm
index 4fba5550ba10..e6f1c0ea3d29 100644
--- a/lldb/source/Host/macosx/objcxx/Host.mm
+++ b/lldb/source/Host/macosx/objcxx/Host.mm
@@ -1387,18 +1387,31 @@ Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) {
 Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
   Status error;
   if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) {
-    FileSpec expand_tool_spec = HostInfo::GetSupportExeDir();
-    if (!expand_tool_spec) {
-      error.SetErrorString(
-          "could not get support executable directory for lldb-argdumper tool");
-      return error;
+    FileSpec expand_tool_spec;
+    Environment host_env = Host::GetEnvironment();
+    std::string env_argdumper_path = host_env.lookup("LLDB_ARGDUMPER_PATH");
+    if (!env_argdumper_path.empty()) {
+      expand_tool_spec.SetFile(env_argdumper_path, FileSpec::Style::native);
+      Log *log(GetLog(LLDBLog::Host | LLDBLog::Process));
+      LLDB_LOGF(log,
+                "lldb-argdumper exe path set from environment variable: %s",
+                env_argdumper_path.c_str());
     }
-    expand_tool_spec.AppendPathComponent("lldb-argdumper");
-    if (!FileSystem::Instance().Exists(expand_tool_spec)) {
-      error.SetErrorStringWithFormat(
-          "could not find the lldb-argdumper tool: %s",
-          expand_tool_spec.GetPath().c_str());
-      return error;
+    bool argdumper_exists = FileSystem::Instance().Exists(env_argdumper_path);
+    if (!argdumper_exists) {
+      expand_tool_spec = HostInfo::GetSupportExeDir();
+      if (!expand_tool_spec) {
+        error.SetErrorString("could not get support executable directory for "
+                             "lldb-argdumper tool");
+        return error;
+      }
+      expand_tool_spec.AppendPathComponent("lldb-argdumper");
+      if (!FileSystem::Instance().Exists(expand_tool_spec)) {
+        error.SetErrorStringWithFormat(
+            "could not find the lldb-argdumper tool: %s",
+            expand_tool_spec.GetPath().c_str());
+        return error;
+      }
     }
 
     StreamString expand_tool_spec_stream;
-- 
GitLab


From 67beebfcb9a267cc1e443aa4d3788adbfcf02639 Mon Sep 17 00:00:00 2001
From: Michael Maitland 
Date: Tue, 14 May 2024 17:15:19 -0400
Subject: [PATCH 281/578] [TableGen][SubtargetEmitter] Refactor hasReadOfWrite
 to CodeGenProcModel (#92032)

SubtargetEmitter::GenSchedClassTables takes a CodeGenProcModel, but
calls hasReadOfWrite which loops over all ProcModels. We move
hasReadOfWrite to CodeGenProcModel and remove the loop over all
ProcModels. This leads to a 144% speedup on the RISC-V backend of our
downstream.
---
 .../utils/TableGen/Common/CodeGenSchedule.cpp | 21 ++++++++-----------
 llvm/utils/TableGen/Common/CodeGenSchedule.h  |  6 +++---
 llvm/utils/TableGen/SubtargetEmitter.cpp      |  4 +---
 3 files changed, 13 insertions(+), 18 deletions(-)

diff --git a/llvm/utils/TableGen/Common/CodeGenSchedule.cpp b/llvm/utils/TableGen/Common/CodeGenSchedule.cpp
index 0e81623a6aa3..2ec0812320d1 100644
--- a/llvm/utils/TableGen/Common/CodeGenSchedule.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenSchedule.cpp
@@ -746,18 +746,6 @@ unsigned CodeGenSchedModels::getSchedRWIdx(const Record *Def,
   return I == RWVec.end() ? 0 : std::distance(RWVec.begin(), I);
 }
 
-bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const {
-  for (auto &ProcModel : ProcModels) {
-    const RecVec &RADefs = ProcModel.ReadAdvanceDefs;
-    for (auto &RADef : RADefs) {
-      RecVec ValidWrites = RADef->getValueAsListOfDefs("ValidWrites");
-      if (is_contained(ValidWrites, WriteDef))
-        return true;
-    }
-  }
-  return false;
-}
-
 static void splitSchedReadWrites(const RecVec &RWDefs, RecVec &WriteDefs,
                                  RecVec &ReadDefs) {
   for (Record *RWDef : RWDefs) {
@@ -2226,6 +2214,15 @@ bool CodeGenProcModel::isUnsupported(const CodeGenInstruction &Inst) const {
   return false;
 }
 
+bool CodeGenProcModel::hasReadOfWrite(Record *WriteDef) const {
+  for (auto &RADef : ReadAdvanceDefs) {
+    RecVec ValidWrites = RADef->getValueAsListOfDefs("ValidWrites");
+    if (is_contained(ValidWrites, WriteDef))
+      return true;
+  }
+  return false;
+}
+
 #ifndef NDEBUG
 void CodeGenProcModel::dump() const {
   dbgs() << Index << ": " << ModelName << " "
diff --git a/llvm/utils/TableGen/Common/CodeGenSchedule.h b/llvm/utils/TableGen/Common/CodeGenSchedule.h
index 61980e7e196e..10ec7f41f56f 100644
--- a/llvm/utils/TableGen/Common/CodeGenSchedule.h
+++ b/llvm/utils/TableGen/Common/CodeGenSchedule.h
@@ -277,6 +277,9 @@ struct CodeGenProcModel {
 
   bool isUnsupported(const CodeGenInstruction &Inst) const;
 
+  // Return true if the given write record is referenced by a ReadAdvance.
+  bool hasReadOfWrite(Record *WriteDef) const;
+
 #ifndef NDEBUG
   void dump() const;
 #endif
@@ -536,9 +539,6 @@ public:
 
   unsigned getSchedRWIdx(const Record *Def, bool IsRead) const;
 
-  // Return true if the given write record is referenced by a ReadAdvance.
-  bool hasReadOfWrite(Record *WriteDef) const;
-
   // Get a SchedClass from its index.
   CodeGenSchedClass &getSchedClass(unsigned Idx) {
     assert(Idx < SchedClasses.size() && "bad SchedClass index");
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index b6b7641cfb92..9e32d2de19b2 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -1122,10 +1122,8 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
       WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name);
       // If this Write is not referenced by a ReadAdvance, don't distinguish it
       // from other WriteLatency entries.
-      if (!SchedModels.hasReadOfWrite(
-              SchedModels.getSchedWrite(WriteID).TheDef)) {
+      if (!ProcModel.hasReadOfWrite(SchedModels.getSchedWrite(WriteID).TheDef))
         WriteID = 0;
-      }
       WLEntry.WriteResourceID = WriteID;
 
       for (unsigned WS : WriteSeq) {
-- 
GitLab


From 536abf827b481f78a0879b02202fb9a3ffe3a908 Mon Sep 17 00:00:00 2001
From: GeorgeHuyubo <113479859+GeorgeHuyubo@users.noreply.github.com>
Date: Tue, 14 May 2024 14:35:35 -0700
Subject: [PATCH 282/578] Read and store gnu build id from loaded core file
 (#92078)

As we have debuginfod as symbol locator available in lldb now, we want
to make full use of it.
In case of post mortem debugging, we don't always have the main
executable available.
However, the .note.gnu.build-id of the main executable(some other
modules too), should be available in the core file, as those binaries
are loaded in memory and dumped in the core file.

We try to iterate through the NT_FILE entries, read and store the gnu
build id if possible. This will be very useful as this id is the unique
key which is needed for querying the debuginfod server.

Test:
Build and run lldb. Breakpoint set to
https://github.com/llvm/llvm-project/blob/main/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp#L147
Verified after this commit, module_uuid is the correct gnu build id of
the main executable which caused the crash(first in the NT_FILE entry)
---
 lldb/include/lldb/Target/Process.h            | 50 +++++++++++++++
 lldb/source/Commands/CommandObjectMemory.cpp  | 61 +------------------
 .../Process/elf-core/ProcessElfCore.cpp       | 50 +++++++++++++++
 .../Plugins/Process/elf-core/ProcessElfCore.h | 11 ++++
 lldb/source/Target/Process.cpp                | 27 ++++++++
 5 files changed, 140 insertions(+), 59 deletions(-)

diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index aac0cf51680a..c8a49edc5c78 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -406,6 +406,36 @@ public:
                                   lldb::StateType state);
   } Notifications;
 
+  class ProcessMemoryIterator {
+  public:
+    ProcessMemoryIterator(lldb::ProcessSP process_sp, lldb::addr_t base)
+        : m_process_sp(process_sp), m_base_addr(base) {
+      lldbassert(process_sp.get() != nullptr);
+    }
+
+    bool IsValid() { return m_is_valid; }
+
+    uint8_t operator[](lldb::addr_t offset) {
+      if (!IsValid())
+        return 0;
+
+      uint8_t retval = 0;
+      Status error;
+      if (0 ==
+          m_process_sp->ReadMemory(m_base_addr + offset, &retval, 1, error)) {
+        m_is_valid = false;
+        return 0;
+      }
+
+      return retval;
+    }
+
+  private:
+    lldb::ProcessSP m_process_sp;
+    lldb::addr_t m_base_addr;
+    bool m_is_valid = true;
+  };
+
   class ProcessEventData : public EventData {
     friend class Process;
 
@@ -1649,6 +1679,26 @@ public:
 
   lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status &error);
 
+  /// Find a string within a memory region.
+  ///
+  /// This function searches for the string represented by the provided buffer
+  /// within the memory range specified by the low and high addresses. It uses
+  /// a bad character heuristic to optimize the search process.
+  ///
+  /// \param[in] low The starting address of the memory region to be searched.
+  ///
+  /// \param[in] high The ending address of the memory region to be searched.
+  ///
+  /// \param[in] buffer A pointer to the buffer containing the string to be
+  /// searched.
+  ///
+  /// \param[in] buffer_size The size of the buffer in bytes.
+  ///
+  /// \return The address where the string was found or LLDB_INVALID_ADDRESS if
+  /// not found.
+  lldb::addr_t FindInMemory(lldb::addr_t low, lldb::addr_t high,
+                            uint8_t *buffer, size_t buffer_size);
+
   bool WritePointerToMemory(lldb::addr_t vm_addr, lldb::addr_t ptr_value,
                             Status &error);
 
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index b78a0492cca5..1c13484dede6 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -977,35 +977,6 @@ public:
   Options *GetOptions() override { return &m_option_group; }
 
 protected:
-  class ProcessMemoryIterator {
-  public:
-    ProcessMemoryIterator(ProcessSP process_sp, lldb::addr_t base)
-        : m_process_sp(process_sp), m_base_addr(base) {
-      lldbassert(process_sp.get() != nullptr);
-    }
-
-    bool IsValid() { return m_is_valid; }
-
-    uint8_t operator[](lldb::addr_t offset) {
-      if (!IsValid())
-        return 0;
-
-      uint8_t retval = 0;
-      Status error;
-      if (0 ==
-          m_process_sp->ReadMemory(m_base_addr + offset, &retval, 1, error)) {
-        m_is_valid = false;
-        return 0;
-      }
-
-      return retval;
-    }
-
-  private:
-    ProcessSP m_process_sp;
-    lldb::addr_t m_base_addr;
-    bool m_is_valid = true;
-  };
   void DoExecute(Args &command, CommandReturnObject &result) override {
     // No need to check "process" for validity as eCommandRequiresProcess
     // ensures it is valid
@@ -1106,8 +1077,8 @@ protected:
     found_location = low_addr;
     bool ever_found = false;
     while (count) {
-      found_location = FastSearch(found_location, high_addr, buffer.GetBytes(),
-                                  buffer.GetByteSize());
+      found_location = process->FindInMemory(
+          found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
       if (found_location == LLDB_INVALID_ADDRESS) {
         if (!ever_found) {
           result.AppendMessage("data not found within the range.\n");
@@ -1144,34 +1115,6 @@ protected:
     result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
   }
 
-  lldb::addr_t FastSearch(lldb::addr_t low, lldb::addr_t high, uint8_t *buffer,
-                          size_t buffer_size) {
-    const size_t region_size = high - low;
-
-    if (region_size < buffer_size)
-      return LLDB_INVALID_ADDRESS;
-
-    std::vector bad_char_heuristic(256, buffer_size);
-    ProcessSP process_sp = m_exe_ctx.GetProcessSP();
-    ProcessMemoryIterator iterator(process_sp, low);
-
-    for (size_t idx = 0; idx < buffer_size - 1; idx++) {
-      decltype(bad_char_heuristic)::size_type bcu_idx = buffer[idx];
-      bad_char_heuristic[bcu_idx] = buffer_size - idx - 1;
-    }
-    for (size_t s = 0; s <= (region_size - buffer_size);) {
-      int64_t j = buffer_size - 1;
-      while (j >= 0 && buffer[j] == iterator[s + j])
-        j--;
-      if (j < 0)
-        return low + s;
-      else
-        s += bad_char_heuristic[iterator[s + buffer_size - 1]];
-    }
-
-    return LLDB_INVALID_ADDRESS;
-  }
-
   OptionGroupOptions m_option_group;
   OptionGroupFindMemory m_memory_options;
   OptionGroupMemoryTag m_memory_tag_options;
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 36812c27a5b6..4ff03eb8ab48 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -6,10 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include 
 #include 
 
 #include 
 #include 
+#include 
 
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
@@ -210,6 +212,9 @@ Status ProcessElfCore::DoLoadCore() {
     }
   }
 
+  // We need to update uuid after address range is populated.
+  UpdateBuildIdForNTFileEntries();
+
   if (!ranges_are_sorted) {
     m_core_aranges.Sort();
     m_core_range_infos.Sort();
@@ -258,6 +263,7 @@ Status ProcessElfCore::DoLoadCore() {
     if (!m_nt_file_entries.empty()) {
       ModuleSpec exe_module_spec;
       exe_module_spec.GetArchitecture() = arch;
+      exe_module_spec.GetUUID() = m_nt_file_entries[0].uuid;
       exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path,
                                             FileSpec::Style::native);
       if (exe_module_spec.GetFileSpec()) {
@@ -271,6 +277,16 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {
+    for (NT_FILE_Entry &entry : m_nt_file_entries) {
+      std::optional uuid = FindBuildId(entry);
+      if (uuid)
+        entry.uuid = uuid.value();
+    }
+  }
+}
+
 lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {
   if (m_dyld_up.get() == nullptr)
     m_dyld_up.reset(DynamicLoader::FindPlugin(
@@ -983,6 +999,40 @@ llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(const NT_FILE_Entry entry) {
+  size_t size = strlen(llvm::ELF::ElfMagic);
+  uint8_t buf[size];
+  Status error;
+  size_t byte_read = ReadMemory(entry.start, buf, size, error);
+  if (byte_read == size)
+    return memcmp(llvm::ELF::ElfMagic, buf, size) == 0;
+  else
+    return false;
+}
+
+std::optional ProcessElfCore::FindBuildId(const NT_FILE_Entry entry) {
+  if (!IsElf(entry))
+    return std::nullopt;
+  // Build ID is stored in the ELF file as a section named ".note.gnu.build-id"
+  uint8_t gnu_build_id_bytes[8] = {0x03, 0x00, 0x00, 0x00,
+                                   0x47, 0x4e, 0x55, 0x00};
+  lldb::addr_t gnu_build_id_addr =
+      FindInMemory(entry.start, entry.end, gnu_build_id_bytes, 8);
+  if (gnu_build_id_addr == LLDB_INVALID_ADDRESS)
+    return std::nullopt;
+  uint8_t buf[36];
+  Status error;
+  size_t byte_read = ReadMemory(gnu_build_id_addr - 8, buf, 36, error);
+  // .note.gnu.build-id starts with 04 00 00 00 {id_byte_size} 00 00 00 03 00 00
+  // 00 47 4e 55 00
+  if (byte_read == 36) {
+    if (buf[0] == 0x04) {
+      return UUID(llvm::ArrayRef(buf + 16, buf[4] /*byte size*/));
+    }
+  }
+  return std::nullopt;
+}
+
 uint32_t ProcessElfCore::GetNumThreadContexts() {
   if (!m_thread_data_valid)
     DoLoadCore();
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
index 2cec635bbacf..ae827f3df002 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -117,6 +117,8 @@ private:
     lldb::addr_t end;
     lldb::addr_t file_ofs;
     std::string path;
+    lldb_private::UUID
+        uuid; // extracted from .note.gnu.build-id section from core file
   };
 
   // For ProcessElfCore only
@@ -158,6 +160,15 @@ private:
   // Returns number of thread contexts stored in the core file
   uint32_t GetNumThreadContexts();
 
+  // Populate gnu uuid for each NT_FILE entry
+  void UpdateBuildIdForNTFileEntries();
+
+  // Returns the UUID of a given NT_FILE entry
+  std::optional FindBuildId(const NT_FILE_Entry entry);
+
+  // Returns true if the given NT_FILE entry is an ELF file
+  bool IsElf(const NT_FILE_Entry entry);
+
   // Parse a contiguous address range of the process from LOAD segment
   lldb::addr_t
   AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader &header);
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 25afade9a827..6f5c43bc4108 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -3191,6 +3191,33 @@ Status Process::Halt(bool clear_thread_plans, bool use_run_lock) {
   return Status();
 }
 
+lldb::addr_t Process::FindInMemory(lldb::addr_t low, lldb::addr_t high,
+                                   uint8_t *buffer, size_t buffer_size) {
+  const size_t region_size = high - low;
+
+  if (region_size < buffer_size)
+    return LLDB_INVALID_ADDRESS;
+
+  std::vector bad_char_heuristic(256, buffer_size);
+  ProcessMemoryIterator iterator(shared_from_this(), low);
+
+  for (size_t idx = 0; idx < buffer_size - 1; idx++) {
+    decltype(bad_char_heuristic)::size_type bcu_idx = buffer[idx];
+    bad_char_heuristic[bcu_idx] = buffer_size - idx - 1;
+  }
+  for (size_t s = 0; s <= (region_size - buffer_size);) {
+    int64_t j = buffer_size - 1;
+    while (j >= 0 && buffer[j] == iterator[s + j])
+      j--;
+    if (j < 0)
+      return low + s;
+    else
+      s += bad_char_heuristic[iterator[s + buffer_size - 1]];
+  }
+
+  return LLDB_INVALID_ADDRESS;
+}
+
 Status Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) {
   Status error;
 
-- 
GitLab


From 5bf653ca42dceb8266a0ff70634292ccd2ad4c43 Mon Sep 17 00:00:00 2001
From: GeorgeHuyubo <113479859+GeorgeHuyubo@users.noreply.github.com>
Date: Tue, 14 May 2024 14:36:17 -0700
Subject: [PATCH 283/578] Revert "Read and store gnu build id from loaded core
 file" (#92181)

Reverts llvm/llvm-project#92078
---
 lldb/include/lldb/Target/Process.h            | 50 ---------------
 lldb/source/Commands/CommandObjectMemory.cpp  | 61 ++++++++++++++++++-
 .../Process/elf-core/ProcessElfCore.cpp       | 50 ---------------
 .../Plugins/Process/elf-core/ProcessElfCore.h | 11 ----
 lldb/source/Target/Process.cpp                | 27 --------
 5 files changed, 59 insertions(+), 140 deletions(-)

diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index c8a49edc5c78..aac0cf51680a 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -406,36 +406,6 @@ public:
                                   lldb::StateType state);
   } Notifications;
 
-  class ProcessMemoryIterator {
-  public:
-    ProcessMemoryIterator(lldb::ProcessSP process_sp, lldb::addr_t base)
-        : m_process_sp(process_sp), m_base_addr(base) {
-      lldbassert(process_sp.get() != nullptr);
-    }
-
-    bool IsValid() { return m_is_valid; }
-
-    uint8_t operator[](lldb::addr_t offset) {
-      if (!IsValid())
-        return 0;
-
-      uint8_t retval = 0;
-      Status error;
-      if (0 ==
-          m_process_sp->ReadMemory(m_base_addr + offset, &retval, 1, error)) {
-        m_is_valid = false;
-        return 0;
-      }
-
-      return retval;
-    }
-
-  private:
-    lldb::ProcessSP m_process_sp;
-    lldb::addr_t m_base_addr;
-    bool m_is_valid = true;
-  };
-
   class ProcessEventData : public EventData {
     friend class Process;
 
@@ -1679,26 +1649,6 @@ public:
 
   lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status &error);
 
-  /// Find a string within a memory region.
-  ///
-  /// This function searches for the string represented by the provided buffer
-  /// within the memory range specified by the low and high addresses. It uses
-  /// a bad character heuristic to optimize the search process.
-  ///
-  /// \param[in] low The starting address of the memory region to be searched.
-  ///
-  /// \param[in] high The ending address of the memory region to be searched.
-  ///
-  /// \param[in] buffer A pointer to the buffer containing the string to be
-  /// searched.
-  ///
-  /// \param[in] buffer_size The size of the buffer in bytes.
-  ///
-  /// \return The address where the string was found or LLDB_INVALID_ADDRESS if
-  /// not found.
-  lldb::addr_t FindInMemory(lldb::addr_t low, lldb::addr_t high,
-                            uint8_t *buffer, size_t buffer_size);
-
   bool WritePointerToMemory(lldb::addr_t vm_addr, lldb::addr_t ptr_value,
                             Status &error);
 
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index 1c13484dede6..b78a0492cca5 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -977,6 +977,35 @@ public:
   Options *GetOptions() override { return &m_option_group; }
 
 protected:
+  class ProcessMemoryIterator {
+  public:
+    ProcessMemoryIterator(ProcessSP process_sp, lldb::addr_t base)
+        : m_process_sp(process_sp), m_base_addr(base) {
+      lldbassert(process_sp.get() != nullptr);
+    }
+
+    bool IsValid() { return m_is_valid; }
+
+    uint8_t operator[](lldb::addr_t offset) {
+      if (!IsValid())
+        return 0;
+
+      uint8_t retval = 0;
+      Status error;
+      if (0 ==
+          m_process_sp->ReadMemory(m_base_addr + offset, &retval, 1, error)) {
+        m_is_valid = false;
+        return 0;
+      }
+
+      return retval;
+    }
+
+  private:
+    ProcessSP m_process_sp;
+    lldb::addr_t m_base_addr;
+    bool m_is_valid = true;
+  };
   void DoExecute(Args &command, CommandReturnObject &result) override {
     // No need to check "process" for validity as eCommandRequiresProcess
     // ensures it is valid
@@ -1077,8 +1106,8 @@ protected:
     found_location = low_addr;
     bool ever_found = false;
     while (count) {
-      found_location = process->FindInMemory(
-          found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
+      found_location = FastSearch(found_location, high_addr, buffer.GetBytes(),
+                                  buffer.GetByteSize());
       if (found_location == LLDB_INVALID_ADDRESS) {
         if (!ever_found) {
           result.AppendMessage("data not found within the range.\n");
@@ -1115,6 +1144,34 @@ protected:
     result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
   }
 
+  lldb::addr_t FastSearch(lldb::addr_t low, lldb::addr_t high, uint8_t *buffer,
+                          size_t buffer_size) {
+    const size_t region_size = high - low;
+
+    if (region_size < buffer_size)
+      return LLDB_INVALID_ADDRESS;
+
+    std::vector bad_char_heuristic(256, buffer_size);
+    ProcessSP process_sp = m_exe_ctx.GetProcessSP();
+    ProcessMemoryIterator iterator(process_sp, low);
+
+    for (size_t idx = 0; idx < buffer_size - 1; idx++) {
+      decltype(bad_char_heuristic)::size_type bcu_idx = buffer[idx];
+      bad_char_heuristic[bcu_idx] = buffer_size - idx - 1;
+    }
+    for (size_t s = 0; s <= (region_size - buffer_size);) {
+      int64_t j = buffer_size - 1;
+      while (j >= 0 && buffer[j] == iterator[s + j])
+        j--;
+      if (j < 0)
+        return low + s;
+      else
+        s += bad_char_heuristic[iterator[s + buffer_size - 1]];
+    }
+
+    return LLDB_INVALID_ADDRESS;
+  }
+
   OptionGroupOptions m_option_group;
   OptionGroupFindMemory m_memory_options;
   OptionGroupMemoryTag m_memory_tag_options;
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 4ff03eb8ab48..36812c27a5b6 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -6,12 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include 
 #include 
 
 #include 
 #include 
-#include 
 
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
@@ -212,9 +210,6 @@ Status ProcessElfCore::DoLoadCore() {
     }
   }
 
-  // We need to update uuid after address range is populated.
-  UpdateBuildIdForNTFileEntries();
-
   if (!ranges_are_sorted) {
     m_core_aranges.Sort();
     m_core_range_infos.Sort();
@@ -263,7 +258,6 @@ Status ProcessElfCore::DoLoadCore() {
     if (!m_nt_file_entries.empty()) {
       ModuleSpec exe_module_spec;
       exe_module_spec.GetArchitecture() = arch;
-      exe_module_spec.GetUUID() = m_nt_file_entries[0].uuid;
       exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path,
                                             FileSpec::Style::native);
       if (exe_module_spec.GetFileSpec()) {
@@ -277,16 +271,6 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
-void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
-  if (!m_nt_file_entries.empty()) {
-    for (NT_FILE_Entry &entry : m_nt_file_entries) {
-      std::optional uuid = FindBuildId(entry);
-      if (uuid)
-        entry.uuid = uuid.value();
-    }
-  }
-}
-
 lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {
   if (m_dyld_up.get() == nullptr)
     m_dyld_up.reset(DynamicLoader::FindPlugin(
@@ -999,40 +983,6 @@ llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
-bool ProcessElfCore::IsElf(const NT_FILE_Entry entry) {
-  size_t size = strlen(llvm::ELF::ElfMagic);
-  uint8_t buf[size];
-  Status error;
-  size_t byte_read = ReadMemory(entry.start, buf, size, error);
-  if (byte_read == size)
-    return memcmp(llvm::ELF::ElfMagic, buf, size) == 0;
-  else
-    return false;
-}
-
-std::optional ProcessElfCore::FindBuildId(const NT_FILE_Entry entry) {
-  if (!IsElf(entry))
-    return std::nullopt;
-  // Build ID is stored in the ELF file as a section named ".note.gnu.build-id"
-  uint8_t gnu_build_id_bytes[8] = {0x03, 0x00, 0x00, 0x00,
-                                   0x47, 0x4e, 0x55, 0x00};
-  lldb::addr_t gnu_build_id_addr =
-      FindInMemory(entry.start, entry.end, gnu_build_id_bytes, 8);
-  if (gnu_build_id_addr == LLDB_INVALID_ADDRESS)
-    return std::nullopt;
-  uint8_t buf[36];
-  Status error;
-  size_t byte_read = ReadMemory(gnu_build_id_addr - 8, buf, 36, error);
-  // .note.gnu.build-id starts with 04 00 00 00 {id_byte_size} 00 00 00 03 00 00
-  // 00 47 4e 55 00
-  if (byte_read == 36) {
-    if (buf[0] == 0x04) {
-      return UUID(llvm::ArrayRef(buf + 16, buf[4] /*byte size*/));
-    }
-  }
-  return std::nullopt;
-}
-
 uint32_t ProcessElfCore::GetNumThreadContexts() {
   if (!m_thread_data_valid)
     DoLoadCore();
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
index ae827f3df002..2cec635bbacf 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -117,8 +117,6 @@ private:
     lldb::addr_t end;
     lldb::addr_t file_ofs;
     std::string path;
-    lldb_private::UUID
-        uuid; // extracted from .note.gnu.build-id section from core file
   };
 
   // For ProcessElfCore only
@@ -160,15 +158,6 @@ private:
   // Returns number of thread contexts stored in the core file
   uint32_t GetNumThreadContexts();
 
-  // Populate gnu uuid for each NT_FILE entry
-  void UpdateBuildIdForNTFileEntries();
-
-  // Returns the UUID of a given NT_FILE entry
-  std::optional FindBuildId(const NT_FILE_Entry entry);
-
-  // Returns true if the given NT_FILE entry is an ELF file
-  bool IsElf(const NT_FILE_Entry entry);
-
   // Parse a contiguous address range of the process from LOAD segment
   lldb::addr_t
   AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader &header);
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 6f5c43bc4108..25afade9a827 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -3191,33 +3191,6 @@ Status Process::Halt(bool clear_thread_plans, bool use_run_lock) {
   return Status();
 }
 
-lldb::addr_t Process::FindInMemory(lldb::addr_t low, lldb::addr_t high,
-                                   uint8_t *buffer, size_t buffer_size) {
-  const size_t region_size = high - low;
-
-  if (region_size < buffer_size)
-    return LLDB_INVALID_ADDRESS;
-
-  std::vector bad_char_heuristic(256, buffer_size);
-  ProcessMemoryIterator iterator(shared_from_this(), low);
-
-  for (size_t idx = 0; idx < buffer_size - 1; idx++) {
-    decltype(bad_char_heuristic)::size_type bcu_idx = buffer[idx];
-    bad_char_heuristic[bcu_idx] = buffer_size - idx - 1;
-  }
-  for (size_t s = 0; s <= (region_size - buffer_size);) {
-    int64_t j = buffer_size - 1;
-    while (j >= 0 && buffer[j] == iterator[s + j])
-      j--;
-    if (j < 0)
-      return low + s;
-    else
-      s += bad_char_heuristic[iterator[s + buffer_size - 1]];
-  }
-
-  return LLDB_INVALID_ADDRESS;
-}
-
 Status Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) {
   Status error;
 
-- 
GitLab


From 99fad7ebd85e37d3e25500b3411f6b332f68f108 Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <43973793+ayermolo@users.noreply.github.com>
Date: Tue, 14 May 2024 15:08:45 -0700
Subject: [PATCH 284/578] [BOLT][DWARF] Update DW_AT_comp_dir/DW_AT_dwo_name
 for DWO TUs (#91486)

Type unit DIE generated by clang contains DW_AT_comp_dir/DW_AT_dwo_name.
This was added to clang to help LLDB to figure out where type unit come
from when accessing an entry in a .debug_names accelerator table and
type units in .dwp file.

When BOLT writes out .dwo files it changes the name of them. User can
also specify directory of where they can be written out. Added support
to BOLT to update those attributes.
---
 bolt/include/bolt/Core/DIEBuilder.h           |  14 ++
 bolt/include/bolt/Core/DebugData.h            |  14 +-
 bolt/include/bolt/Rewrite/DWARFRewriter.h     |   8 +-
 bolt/lib/Core/DIEBuilder.cpp                  |  85 ++++++++
 bolt/lib/Core/DebugData.cpp                   |  20 +-
 bolt/lib/Rewrite/DWARFRewriter.cpp            | 159 ++++++--------
 .../Inputs/dwarf5-df-types-debug-names-main.s |  22 +-
 ...dwarf5-df-types-modify-dwo-name-mixed.test | 198 ++++++++++++++++++
 .../X86/dwarf5-df-types-modify-dwo-name.test  | 175 ++++++++++++++++
 9 files changed, 575 insertions(+), 120 deletions(-)
 create mode 100644 bolt/test/X86/dwarf5-df-types-modify-dwo-name-mixed.test
 create mode 100644 bolt/test/X86/dwarf5-df-types-modify-dwo-name.test

diff --git a/bolt/include/bolt/Core/DIEBuilder.h b/bolt/include/bolt/Core/DIEBuilder.h
index 06084819ec0b..c5ad0ac18339 100644
--- a/bolt/include/bolt/Core/DIEBuilder.h
+++ b/bolt/include/bolt/Core/DIEBuilder.h
@@ -129,6 +129,9 @@ private:
   uint64_t UnitSize{0};
   llvm::DenseSet AllProcessed;
   DWARF5AcceleratorTable &DebugNamesTable;
+  // Unordered map to handle name collision if output DWO directory is
+  // specified.
+  std::unordered_map NameToIndexMap;
 
   /// Returns current state of the DIEBuilder
   State &getState() { return *BuilderState.get(); }
@@ -384,6 +387,17 @@ public:
   bool deleteValue(DIEValueList *Die, dwarf::Attribute Attribute) {
     return Die->deleteValue(Attribute);
   }
+  /// Updates DWO Name and Compilation directory for Skeleton CU \p Unit.
+  std::string updateDWONameCompDir(DebugStrOffsetsWriter &StrOffstsWriter,
+                                   DebugStrWriter &StrWriter,
+                                   DWARFUnit &SkeletonCU,
+                                   std::optional DwarfOutputPath,
+                                   std::optional DWONameToUse);
+  /// Updates DWO Name and Compilation directory for Type Units.
+  void updateDWONameCompDirForTypes(DebugStrOffsetsWriter &StrOffstsWriter,
+                                    DebugStrWriter &StrWriter, DWARFUnit &Unit,
+                                    std::optional DwarfOutputPath,
+                                    const StringRef DWOName);
 };
 } // namespace bolt
 } // namespace llvm
diff --git a/bolt/include/bolt/Core/DebugData.h b/bolt/include/bolt/Core/DebugData.h
index 166bb3617e57..585bafa08884 100644
--- a/bolt/include/bolt/Core/DebugData.h
+++ b/bolt/include/bolt/Core/DebugData.h
@@ -430,7 +430,7 @@ protected:
 using DebugStrOffsetsBufferVector = SmallVector;
 class DebugStrOffsetsWriter {
 public:
-  DebugStrOffsetsWriter() {
+  DebugStrOffsetsWriter(BinaryContext &BC) : BC(BC) {
     StrOffsetsBuffer = std::make_unique();
     StrOffsetsStream = std::make_unique(*StrOffsetsBuffer);
   }
@@ -460,6 +460,10 @@ public:
     StrOffsets.clear();
   }
 
+  bool isStrOffsetsSectionModified() const {
+    return StrOffsetSectionWasModified;
+  }
+
 private:
   std::unique_ptr StrOffsetsBuffer;
   std::unique_ptr StrOffsetsStream;
@@ -467,13 +471,16 @@ private:
   SmallVector StrOffsets;
   std::unordered_map ProcessedBaseOffsets;
   bool StrOffsetSectionWasModified = false;
+  BinaryContext &BC;
 };
 
 using DebugStrBufferVector = SmallVector;
 class DebugStrWriter {
 public:
   DebugStrWriter() = delete;
-  DebugStrWriter(BinaryContext &BC) : BC(BC) { create(); }
+  DebugStrWriter(DWARFContext &DwCtx, bool IsDWO) : DwCtx(DwCtx), IsDWO(IsDWO) {
+    create();
+  }
   std::unique_ptr releaseBuffer() {
     return std::move(StrBuffer);
   }
@@ -495,7 +502,8 @@ private:
   void create();
   std::unique_ptr StrBuffer;
   std::unique_ptr StrStream;
-  BinaryContext &BC;
+  DWARFContext &DwCtx;
+  bool IsDWO;
 };
 
 enum class LocWriterKind { DebugLocWriter, DebugLoclistWriter };
diff --git a/bolt/include/bolt/Rewrite/DWARFRewriter.h b/bolt/include/bolt/Rewrite/DWARFRewriter.h
index 12e0813d089d..8dec32de9008 100644
--- a/bolt/include/bolt/Rewrite/DWARFRewriter.h
+++ b/bolt/include/bolt/Rewrite/DWARFRewriter.h
@@ -203,13 +203,16 @@ public:
   using OverriddenSectionsMap = std::unordered_map;
   /// Output .dwo files.
   void writeDWOFiles(DWARFUnit &, const OverriddenSectionsMap &,
-                     const std::string &, DebugLocWriter &);
+                     const std::string &, DebugLocWriter &,
+                     DebugStrOffsetsWriter &, DebugStrWriter &);
   using KnownSectionsEntry = std::pair;
   struct DWPState {
     std::unique_ptr Out;
     std::unique_ptr TmpBC;
     std::unique_ptr Streamer;
     std::unique_ptr Strings;
+    /// Used to store String sections for .dwo files if they are being modified.
+    std::vector> StrSections;
     const MCObjectFileInfo *MCOFI = nullptr;
     const DWARFUnitIndex *CUIndex = nullptr;
     std::deque> UncompressedSections;
@@ -230,7 +233,8 @@ public:
 
   /// add content of dwo to .dwp file.
   void updateDWP(DWARFUnit &, const OverriddenSectionsMap &, const UnitMeta &,
-                 UnitMetaVectorType &, DWPState &, DebugLocWriter &);
+                 UnitMetaVectorType &, DWPState &, DebugLocWriter &,
+                 DebugStrOffsetsWriter &, DebugStrWriter &);
 };
 
 } // namespace bolt
diff --git a/bolt/lib/Core/DIEBuilder.cpp b/bolt/lib/Core/DIEBuilder.cpp
index c4b0b251c120..34c455a36cce 100644
--- a/bolt/lib/Core/DIEBuilder.cpp
+++ b/bolt/lib/Core/DIEBuilder.cpp
@@ -22,6 +22,7 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/LEB128.h"
 
 #include 
@@ -41,6 +42,90 @@ extern cl::opt Verbosity;
 namespace llvm {
 namespace bolt {
 
+/// Returns DWO Name to be used to update DW_AT_dwo_name/DW_AT_GNU_dwo_name
+/// either in CU or TU unit die. Handles case where user specifies output DWO
+/// directory, and there are duplicate names. Assumes DWO ID is unique.
+static std::string
+getDWOName(llvm::DWARFUnit &CU,
+           std::unordered_map &NameToIndexMap,
+           std::optional &DwarfOutputPath) {
+  assert(CU.getDWOId() && "DWO ID not found.");
+  std::string DWOName = dwarf::toString(
+      CU.getUnitDIE().find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
+      "");
+  assert(!DWOName.empty() &&
+         "DW_AT_dwo_name/DW_AT_GNU_dwo_name does not exist.");
+  if (DwarfOutputPath) {
+    DWOName = std::string(sys::path::filename(DWOName));
+    auto Iter = NameToIndexMap.find(DWOName);
+    if (Iter == NameToIndexMap.end())
+      Iter = NameToIndexMap.insert({DWOName, 0}).first;
+    DWOName.append(std::to_string(Iter->second));
+    ++Iter->second;
+  }
+  DWOName.append(".dwo");
+  return DWOName;
+}
+
+/// Adds a \p Str to .debug_str section.
+/// Uses \p AttrInfoVal to either update entry in a DIE for legacy DWARF using
+/// \p DebugInfoPatcher, or for DWARF5 update an index in .debug_str_offsets
+/// for this contribution of \p Unit.
+static void addStringHelper(DebugStrOffsetsWriter &StrOffstsWriter,
+                            DebugStrWriter &StrWriter, DIEBuilder &DIEBldr,
+                            DIE &Die, const DWARFUnit &Unit,
+                            DIEValue &DIEAttrInfo, StringRef Str) {
+  uint32_t NewOffset = StrWriter.addString(Str);
+  if (Unit.getVersion() >= 5) {
+    StrOffstsWriter.updateAddressMap(DIEAttrInfo.getDIEInteger().getValue(),
+                                     NewOffset);
+    return;
+  }
+  DIEBldr.replaceValue(&Die, DIEAttrInfo.getAttribute(), DIEAttrInfo.getForm(),
+                       DIEInteger(NewOffset));
+}
+
+std::string DIEBuilder::updateDWONameCompDir(
+    DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter,
+    DWARFUnit &SkeletonCU, std::optional DwarfOutputPath,
+    std::optional DWONameToUse) {
+  DIE &UnitDIE = *getUnitDIEbyUnit(SkeletonCU);
+  DIEValue DWONameAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_dwo_name);
+  if (!DWONameAttrInfo)
+    DWONameAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_GNU_dwo_name);
+  if (!DWONameAttrInfo)
+    return "";
+  std::string ObjectName;
+  if (DWONameToUse)
+    ObjectName = *DWONameToUse;
+  else
+    ObjectName = getDWOName(SkeletonCU, NameToIndexMap, DwarfOutputPath);
+  addStringHelper(StrOffstsWriter, StrWriter, *this, UnitDIE, SkeletonCU,
+                  DWONameAttrInfo, ObjectName);
+
+  DIEValue CompDirAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_comp_dir);
+  assert(CompDirAttrInfo && "DW_AT_comp_dir is not in Skeleton CU.");
+
+  if (DwarfOutputPath) {
+    if (!sys::fs::exists(*DwarfOutputPath))
+      sys::fs::create_directory(*DwarfOutputPath);
+    addStringHelper(StrOffstsWriter, StrWriter, *this, UnitDIE, SkeletonCU,
+                    CompDirAttrInfo, *DwarfOutputPath);
+  }
+  return ObjectName;
+}
+
+void DIEBuilder::updateDWONameCompDirForTypes(
+    DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter,
+    DWARFUnit &Unit, std::optional DwarfOutputPath,
+    const StringRef DWOName) {
+  for (DWARFUnit *DU : getState().DWARF5TUVector)
+    updateDWONameCompDir(StrOffstsWriter, StrWriter, *DU, DwarfOutputPath,
+                         DWOName);
+  if (StrOffstsWriter.isStrOffsetsSectionModified())
+    StrOffstsWriter.finalizeSection(Unit, *this);
+}
+
 void DIEBuilder::updateReferences() {
   for (auto &[SrcDIEInfo, ReferenceInfo] : getState().AddrReferences) {
     DIEInfo *DstDIEInfo = ReferenceInfo.Dst;
diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp
index a987a103a08b..f502a5031247 100644
--- a/bolt/lib/Core/DebugData.cpp
+++ b/bolt/lib/Core/DebugData.cpp
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -867,10 +868,17 @@ void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
                                             DIEBuilder &DIEBldr) {
   std::optional AttrVal =
       findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base);
-  if (!AttrVal)
+  if (!AttrVal && !Unit.isDWOUnit())
     return;
-  std::optional Val = AttrVal->V.getAsSectionOffset();
-  assert(Val && "DW_AT_str_offsets_base Value not present.");
+  std::optional Val = std::nullopt;
+  if (AttrVal) {
+    Val = AttrVal->V.getAsSectionOffset();
+  } else {
+    if (!Unit.isDWOUnit())
+      BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: "
+                   "DW_AT_str_offsets_base Value not present\n";
+    Val = 0;
+  }
   DIE &Die = *DIEBldr.getUnitDIEbyUnit(Unit);
   DIEValue StrListBaseAttrInfo =
       Die.findAttribute(dwarf::DW_AT_str_offsets_base);
@@ -915,7 +923,11 @@ void DebugStrWriter::create() {
 }
 
 void DebugStrWriter::initialize() {
-  auto StrSection = BC.DwCtx->getDWARFObj().getStrSection();
+  StringRef StrSection;
+  if (IsDWO)
+    StrSection = DwCtx.getDWARFObj().getStrDWOSection();
+  else
+    StrSection = DwCtx.getDWARFObj().getStrSection();
   (*StrStream) << StrSection;
 }
 
diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp
index 9d4297f913f3..d582ce7b33a2 100644
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -458,32 +458,6 @@ static std::optional getAsAddress(const DWARFUnit &DU,
   return std::nullopt;
 }
 
-/// Returns DWO Name to be used. Handles case where user specifies output DWO
-/// directory, and there are duplicate names. Assumes DWO ID is unique.
-static std::string
-getDWOName(llvm::DWARFUnit &CU,
-           std::unordered_map &NameToIndexMap) {
-  std::optional DWOId = CU.getDWOId();
-  assert(DWOId && "DWO ID not found.");
-  (void)DWOId;
-
-  std::string DWOName = dwarf::toString(
-      CU.getUnitDIE().find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
-      "");
-  assert(!DWOName.empty() &&
-         "DW_AT_dwo_name/DW_AT_GNU_dwo_name does not exists.");
-  if (!opts::DwarfOutputPath.empty()) {
-    DWOName = std::string(sys::path::filename(DWOName));
-    auto Iter = NameToIndexMap.find(DWOName);
-    if (Iter == NameToIndexMap.end())
-      Iter = NameToIndexMap.insert({DWOName, 0}).first;
-    DWOName.append(std::to_string(Iter->second));
-    ++Iter->second;
-  }
-  DWOName.append(".dwo");
-  return DWOName;
-}
-
 static std::unique_ptr
 createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile,
                   StringRef Swift5ReflectionSegmentName, DIEBuilder &DIEBldr,
@@ -515,7 +489,9 @@ static void emitDWOBuilder(const std::string &DWOName,
                            DIEBuilder &DWODIEBuilder, DWARFRewriter &Rewriter,
                            DWARFUnit &SplitCU, DWARFUnit &CU,
                            DWARFRewriter::DWPState &State,
-                           DebugLocWriter &LocWriter) {
+                           DebugLocWriter &LocWriter,
+                           DebugStrOffsetsWriter &StrOffstsWriter,
+                           DebugStrWriter &StrWriter) {
   // Populate debug_info and debug_abbrev for current dwo into StringRef.
   DWODIEBuilder.generateAbbrevs();
   DWODIEBuilder.finish();
@@ -577,54 +553,10 @@ static void emitDWOBuilder(const std::string &DWOName,
   }
   if (opts::WriteDWP)
     Rewriter.updateDWP(CU, OverriddenSections, CUMI, TUMetaVector, State,
-                       LocWriter);
+                       LocWriter, StrOffstsWriter, StrWriter);
   else
-    Rewriter.writeDWOFiles(CU, OverriddenSections, DWOName, LocWriter);
-}
-
-/// Adds a \p Str to .debug_str section.
-/// Uses \p AttrInfoVal to either update entry in a DIE for legacy DWARF using
-/// \p DebugInfoPatcher, or for DWARF5 update an index in .debug_str_offsets
-/// for this contribution of \p Unit.
-static void addStringHelper(DebugStrOffsetsWriter &StrOffstsWriter,
-                            DebugStrWriter &StrWriter, DIEBuilder &DIEBldr,
-                            DIE &Die, const DWARFUnit &Unit,
-                            DIEValue &DIEAttrInfo, StringRef Str) {
-  uint32_t NewOffset = StrWriter.addString(Str);
-  if (Unit.getVersion() >= 5) {
-    StrOffstsWriter.updateAddressMap(DIEAttrInfo.getDIEInteger().getValue(),
-                                     NewOffset);
-    return;
-  }
-  DIEBldr.replaceValue(&Die, DIEAttrInfo.getAttribute(), DIEAttrInfo.getForm(),
-                       DIEInteger(NewOffset));
-}
-
-static std::string
-updateDWONameCompDir(DebugStrOffsetsWriter &StrOffstsWriter,
-                     DebugStrWriter &StrWriter,
-                     std::unordered_map &NameToIndexMap,
-                     DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &UnitDIE) {
-  DIEValue DWONameAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_dwo_name);
-  if (!DWONameAttrInfo)
-    DWONameAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_GNU_dwo_name);
-  assert(DWONameAttrInfo && "DW_AT_dwo_name is not in Skeleton CU.");
-  std::string ObjectName;
-
-  ObjectName = getDWOName(Unit, NameToIndexMap);
-  addStringHelper(StrOffstsWriter, StrWriter, DIEBldr, UnitDIE, Unit,
-                  DWONameAttrInfo, ObjectName.c_str());
-
-  DIEValue CompDirAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_comp_dir);
-  assert(CompDirAttrInfo && "DW_AT_comp_dir is not in Skeleton CU.");
-
-  if (!opts::DwarfOutputPath.empty()) {
-    if (!sys::fs::exists(opts::DwarfOutputPath))
-      sys::fs::create_directory(opts::DwarfOutputPath);
-    addStringHelper(StrOffstsWriter, StrWriter, DIEBldr, UnitDIE, Unit,
-                    CompDirAttrInfo, opts::DwarfOutputPath.c_str());
-  }
-  return ObjectName;
+    Rewriter.writeDWOFiles(CU, OverriddenSections, DWOName, LocWriter,
+                           StrOffstsWriter, StrWriter);
 }
 
 using DWARFUnitVec = std::vector;
@@ -673,9 +605,8 @@ void DWARFRewriter::updateDebugInfo() {
     return;
 
   ARangesSectionWriter = std::make_unique();
-  StrWriter = std::make_unique(BC);
-
-  StrOffstsWriter = std::make_unique();
+  StrWriter = std::make_unique(*BC.DwCtx, false);
+  StrOffstsWriter = std::make_unique(BC);
 
   if (!opts::DeterministicDebugInfo) {
     opts::DeterministicDebugInfo = true;
@@ -720,10 +651,6 @@ void DWARFRewriter::updateDebugInfo() {
     return LocListWritersByCU[CUIndex++].get();
   };
 
-  // Unordered maps to handle name collision if output DWO directory is
-  // specified.
-  std::unordered_map NameToIndexMap;
-
   DWARF5AcceleratorTable DebugNamesTable(opts::CreateDebugNames, BC,
                                          *StrWriter);
   DWPState State;
@@ -747,13 +674,20 @@ void DWARFRewriter::updateDebugInfo() {
                                Unit);
       DWODIEBuilder.buildDWOUnit(**SplitCU);
       std::string DWOName = "";
+      std::optional DwarfOutputPath =
+          opts::DwarfOutputPath.empty()
+              ? std::nullopt
+              : std::optional(opts::DwarfOutputPath.c_str());
       {
         std::lock_guard Lock(AccessMutex);
-        DWOName = updateDWONameCompDir(*StrOffstsWriter, *StrWriter,
-                                       NameToIndexMap, *Unit, *DIEBlder,
-                                       *DIEBlder->getUnitDIEbyUnit(*Unit));
+        DWOName = DIEBlder->updateDWONameCompDir(
+            *StrOffstsWriter, *StrWriter, *Unit, DwarfOutputPath, std::nullopt);
       }
-
+      DebugStrOffsetsWriter DWOStrOffstsWriter(BC);
+      DebugStrWriter DWOStrWriter((*SplitCU)->getContext(), true);
+      DWODIEBuilder.updateDWONameCompDirForTypes(DWOStrOffstsWriter,
+                                                 DWOStrWriter, **SplitCU,
+                                                 DwarfOutputPath, DWOName);
       DebugLoclistWriter DebugLocDWoWriter(*Unit, Unit->getVersion(), true);
       DebugRangesSectionWriter *TempRangesSectionWriter = RangesSectionWriter;
       if (Unit->getVersion() >= 5) {
@@ -771,7 +705,7 @@ void DWARFRewriter::updateDebugInfo() {
         TempRangesSectionWriter->finalizeSection();
 
       emitDWOBuilder(DWOName, DWODIEBuilder, *this, **SplitCU, *Unit, State,
-                     DebugLocDWoWriter);
+                     DebugLocDWoWriter, DWOStrOffstsWriter, DWOStrWriter);
     }
 
     if (Unit->getVersion() >= 5) {
@@ -1736,6 +1670,7 @@ std::optional updateDebugData(
     const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId,
     std::unique_ptr &OutputBuffer,
     DebugRangeListsSectionWriter *RangeListsWriter, DebugLocWriter &LocWriter,
+    DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter,
     const llvm::bolt::DWARFRewriter::OverriddenSectionsMap &OverridenSections) {
 
   using DWOSectionContribution =
@@ -1774,6 +1709,11 @@ std::optional updateDebugData(
     if (SectionName != "debug_str.dwo")
       errs() << "BOLT-WARNING: unsupported debug section: " << SectionName
              << "\n";
+    if (StrWriter.isInitialized()) {
+      OutputBuffer = StrWriter.releaseBuffer();
+      return StringRef(reinterpret_cast(OutputBuffer->data()),
+                       OutputBuffer->size());
+    }
     return SectionContents;
   }
   case DWARFSectionKind::DW_SECT_INFO: {
@@ -1783,6 +1723,11 @@ std::optional updateDebugData(
     return getOverridenSection(DWARFSectionKind::DW_SECT_EXT_TYPES);
   }
   case DWARFSectionKind::DW_SECT_STR_OFFSETS: {
+    if (StrOffstsWriter.isFinalized()) {
+      OutputBuffer = StrOffstsWriter.releaseBuffer();
+      return StringRef(reinterpret_cast(OutputBuffer->data()),
+                       OutputBuffer->size());
+    }
     return getSliceData(CUDWOEntry, SectionContents,
                         DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset);
   }
@@ -1884,7 +1829,9 @@ void DWARFRewriter::updateDWP(DWARFUnit &CU,
                               const OverriddenSectionsMap &OverridenSections,
                               const DWARFRewriter::UnitMeta &CUMI,
                               DWARFRewriter::UnitMetaVectorType &TUMetaVector,
-                              DWPState &State, DebugLocWriter &LocWriter) {
+                              DWPState &State, DebugLocWriter &LocWriter,
+                              DebugStrOffsetsWriter &StrOffstsWriter,
+                              DebugStrWriter &StrWriter) {
   const uint64_t DWOId = *CU.getDWOId();
   MCSection *const StrOffsetSection = State.MCOFI->getDwarfStrOffDWOSection();
   assert(StrOffsetSection && "StrOffsetSection does not exist.");
@@ -1941,15 +1888,18 @@ void DWARFRewriter::updateDWP(DWARFUnit &CU,
         TUEntry.Contributions[Index].getLength32();
     State.TypeIndexEntries.insert(std::make_pair(Hash, TUEntry));
   };
+  std::unique_ptr StrOffsetsOutputData;
+  std::unique_ptr StrOutputData;
   for (const SectionRef &Section : DWOFile->sections()) {
-    std::unique_ptr OutputData;
+    std::unique_ptr OutputData = nullptr;
     StringRef SectionName = getSectionName(Section);
     Expected ContentsExp = Section.getContents();
     assert(ContentsExp && "Invalid contents.");
-    std::optional TOutData = updateDebugData(
-        (*DWOCU)->getContext(), SectionName, *ContentsExp, State.KnownSections,
-        *State.Streamer, *this, CUDWOEntry, DWOId, OutputData,
-        RangeListssWriter, LocWriter, OverridenSections);
+    std::optional TOutData =
+        updateDebugData((*DWOCU)->getContext(), SectionName, *ContentsExp,
+                        State.KnownSections, *State.Streamer, *this, CUDWOEntry,
+                        DWOId, OutputData, RangeListssWriter, LocWriter,
+                        StrOffstsWriter, StrWriter, OverridenSections);
     if (!TOutData)
       continue;
 
@@ -1961,14 +1911,17 @@ void DWARFRewriter::updateDWP(DWARFUnit &CU,
 
     if (SectionName == "debug_str.dwo") {
       CurStrSection = OutData;
+      StrOutputData = std::move(OutputData);
     } else {
       // Since handleDebugDataPatching returned true, we already know this is
       // a known section.
       auto SectionIter = State.KnownSections.find(SectionName);
-      if (SectionIter->second.second == DWARFSectionKind::DW_SECT_STR_OFFSETS)
+      if (SectionIter->second.second == DWARFSectionKind::DW_SECT_STR_OFFSETS) {
         CurStrOffsetSection = OutData;
-      else
+        StrOffsetsOutputData = std::move(OutputData);
+      } else {
         State.Streamer->emitBytes(OutData);
+      }
       unsigned int Index =
           getContributionIndex(SectionIter->second.second, State.IndexVersion);
       uint64_t Offset = State.ContributionOffsets[Index];
@@ -1992,6 +1945,10 @@ void DWARFRewriter::updateDWP(DWARFUnit &CU,
     // based on hash.
     if (!StrSectionWrittenOut && !CurStrOffsetSection.empty() &&
         !CurStrSection.empty()) {
+      // If debug_str.dwo section was modified storing it until dwp is written
+      // out. DWPStringPool stores raw pointers to strings.
+      if (StrOutputData)
+        State.StrSections.push_back(std::move(StrOutputData));
       writeStringsAndOffsets(*State.Streamer.get(), *State.Strings.get(),
                              StrOffsetSection, CurStrSection,
                              CurStrOffsetSection, CU.getVersion());
@@ -2017,7 +1974,8 @@ void DWARFRewriter::updateDWP(DWARFUnit &CU,
 
 void DWARFRewriter::writeDWOFiles(
     DWARFUnit &CU, const OverriddenSectionsMap &OverridenSections,
-    const std::string &DWOName, DebugLocWriter &LocWriter) {
+    const std::string &DWOName, DebugLocWriter &LocWriter,
+    DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter) {
   // Setup DWP code once.
   DWARFContext *DWOCtx = BC.getDWOContext();
   const uint64_t DWOId = *CU.getDWOId();
@@ -2072,10 +2030,11 @@ void DWARFRewriter::writeDWOFiles(
     // have .debug_rnglists so won't be part of the loop below.
     if (!RangeListssWriter->empty()) {
       std::unique_ptr OutputData;
-      if (std::optional OutData = updateDebugData(
-              (*DWOCU)->getContext(), "debug_rnglists.dwo", "", KnownSections,
-              *Streamer, *this, CUDWOEntry, DWOId, OutputData,
-              RangeListssWriter, LocWriter, OverridenSections))
+      if (std::optional OutData =
+              updateDebugData((*DWOCU)->getContext(), "debug_rnglists.dwo", "",
+                              KnownSections, *Streamer, *this, CUDWOEntry,
+                              DWOId, OutputData, RangeListssWriter, LocWriter,
+                              StrOffstsWriter, StrWriter, OverridenSections))
         Streamer->emitBytes(*OutData);
     }
   }
@@ -2090,7 +2049,7 @@ void DWARFRewriter::writeDWOFiles(
     if (std::optional OutData = updateDebugData(
             (*DWOCU)->getContext(), SectionName, *ContentsExp, KnownSections,
             *Streamer, *this, CUDWOEntry, DWOId, OutputData, RangeListssWriter,
-            LocWriter, OverridenSections))
+            LocWriter, StrOffstsWriter, StrWriter, OverridenSections))
       Streamer->emitBytes(*OutData);
   }
   Streamer->finish();
diff --git a/bolt/test/X86/Inputs/dwarf5-df-types-debug-names-main.s b/bolt/test/X86/Inputs/dwarf5-df-types-debug-names-main.s
index f89f28ec13f4..34ba21f69517 100644
--- a/bolt/test/X86/Inputs/dwarf5-df-types-debug-names-main.s
+++ b/bolt/test/X86/Inputs/dwarf5-df-types-debug-names-main.s
@@ -207,7 +207,7 @@ main:                                   # @main
 .Linfo_string5:
 	.asciz	"f2"                            # string offset=24
 .Linfo_string6:
-	.asciz	"/home/ayermolo/local/tasks/T138552329/typeDedupSplit" # string offset=27
+	.asciz	"." # string offset=27
 .Linfo_string7:
 	.asciz	"main.dwo"                      # string offset=80
 .Linfo_string8:
@@ -234,15 +234,15 @@ main:                                   # @main
 	.long	19
 	.long	24
 	.long	27
-	.long	80
-	.long	89
-	.long	92
-	.long	97
-	.long	100
-	.long	103
-	.long	106
-	.long	112
-	.long	220
+	.long	29
+	.long	38
+	.long	41
+	.long	46
+	.long	49
+	.long	52
+	.long	55
+	.long	61
+	.long	169
 	.section	.debug_info.dwo,"e",@progbits
 	.long	.Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit
 .Ldebug_info_dwo_start2:
@@ -474,7 +474,7 @@ main:                                   # @main
 	.byte	1
 	.byte	8
 	.byte	2
-	.ascii	"/home/ayermolo/local/tasks/T138552329/typeDedupSplit"
+	.ascii	"."
 	.byte	0
 	.byte	46
 	.byte	0
diff --git a/bolt/test/X86/dwarf5-df-types-modify-dwo-name-mixed.test b/bolt/test/X86/dwarf5-df-types-modify-dwo-name-mixed.test
new file mode 100644
index 000000000000..a4f5ee77ab56
--- /dev/null
+++ b/bolt/test/X86/dwarf5-df-types-modify-dwo-name-mixed.test
@@ -0,0 +1,198 @@
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-types-debug-names-main.s \
+; RUN: -split-dwarf-file=main.dwo -o main.o
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-types-dup-helper.s \
+; RUN: -split-dwarf-file=helper.dwo -o helper.o
+; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o helper.o -o main.exe
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections
+; RUN: llvm-dwarfdump --debug-info -r 0 main.exe.bolt > log.txt
+; RUN: llvm-dwarfdump --debug-info -r 0 main.dwo.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-info -r 0 helper.dwo.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-str-offsets main.dwo.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-str-offsets helper.dwo.dwo >> log.txt
+; RUN: cat log.txt | FileCheck -check-prefix=BOLT %s
+
+;; Test is a mix of DWARF5 TUs where one has DW_AT_comp_dir/DW_AT_dwo_name, and another one doesn't.
+;; Tests that BOLT correctly updates DW_AT_dwo_name for TUs.
+
+; BOLT: DW_TAG_skeleton_unit
+; BOLT: DW_AT_comp_dir  (".")
+; BOLT: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT: DW_TAG_skeleton_unit
+; BOLT: DW_AT_comp_dir  (".")
+; BOLT: DW_AT_dwo_name  ("helper.dwo.dwo")
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_AT_comp_dir  (".")
+; BOLT: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_AT_comp_dir  (".")
+; BOLT: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT: DW_TAG_type_unit
+; BOLT-NOT: DW_AT_dwo_name
+; BOLT: DW_TAG_type_unit
+; BOLT-NOT: DW_AT_dwo_name
+; BOLT: DW_TAG_compile_unit
+; BOLT:      .debug_str_offsets.dwo contents:
+; BOLT-NEXT: 0x00000000: Contribution size = 68, Format = DWARF32, Version = 5
+; BOLT-NEXT: "main"
+; BOLT-NEXT: "int"
+; BOLT-NEXT: "argc"
+; BOLT-NEXT: "argv"
+; BOLT-NEXT: "char"
+; BOLT-NEXT: "f2"
+; BOLT-NEXT: "."
+; BOLT-NEXT: "main.dwo.dwo"
+; BOLT-NEXT: "c1"
+; BOLT-NEXT: "Foo2"
+; BOLT-NEXT: "f3"
+; BOLT-NEXT: "c2"
+; BOLT-NEXT: "c3"
+; BOLT-NEXT: "Foo2a"
+; BOLT-NEXT: "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)"
+; BOLT-NEXT: "main.cpp"
+; BOLT-NEXT: helper.dwo.dwo: file format elf64-x86-64
+
+; BOLT:      .debug_str_offsets.dwo contents:
+; BOLT-NEXT: 0x00000000: Contribution size = 64, Format = DWARF32, Version = 5
+; BOLT-NEXT: "fooint"
+; BOLT-NEXT: "int"
+; BOLT-NEXT: "_Z3foov"
+; BOLT-NEXT: "foo"
+; BOLT-NEXT: "fint"
+; BOLT-NEXT: "c1"
+; BOLT-NEXT: "c2"
+; BOLT-NEXT: "Foo2Int"
+; BOLT-NEXT: "f"
+; BOLT-NEXT: "char"
+; BOLT-NEXT: "c3"
+; BOLT-NEXT: "Foo2a"
+; BOLT-NEXT: "clang version 18.0.0"
+; BOLT-NEXT: "helper.cpp"
+; BOLT-NEXT: "helper.dwo"
+
+
+;; Tests that BOLT correctly handles updating DW_AT_dwo_name when it outputs a DWP file.
+;; Currently skipping one of Type units because it is not being de-dupped.
+;; In the tu-index this TU is not present.
+; RUN: rm main.exe.bolt
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections --write-dwp
+; RUN: llvm-dwarfdump --debug-info -r 0 main.exe.bolt.dwp > logDWP.txt
+; RUN: llvm-dwarfdump --debug-str-offsets main.exe.bolt.dwp >> logDWP.txt
+; RUN: cat logDWP.txt | FileCheck -check-prefix=BOLT-DWP %s
+; BOLT-DWP: DW_TAG_type_unit
+; BOLT-DWP: DW_AT_comp_dir  (".")
+; BOLT-DWP: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT-DWP: DW_TAG_type_unit
+; BOLT-DWP: DW_AT_comp_dir  (".")
+; BOLT-DWP: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT-DWP: DW_TAG_compile_unit
+; BOLT-DWP: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT-DWP: DW_TAG_type_unit
+; BOLT-DW-NOT: DW_AT_dwo_name
+; BOLT-DWP:       Contribution size = 68, Format = DWARF32, Version = 5
+; BOLT-DWP-NEXT: "main"
+; BOLT-DWP-NEXT: "int"
+; BOLT-DWP-NEXT: "argc"
+; BOLT-DWP-NEXT: "argv"
+; BOLT-DWP-NEXT: "char"
+; BOLT-DWP-NEXT: "f2"
+; BOLT-DWP-NEXT: "."
+; BOLT-DWP-NEXT: "main.dwo.dwo"
+; BOLT-DWP-NEXT: "c1"
+; BOLT-DWP-NEXT: "Foo2"
+; BOLT-DWP-NEXT: "f3"
+; BOLT-DWP-NEXT: "c2"
+; BOLT-DWP-NEXT: "c3"
+; BOLT-DWP-NEXT: "Foo2a"
+; BOLT-DWP-NEXT: "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)"
+; BOLT-DWP-NEXT: "main.cpp"
+; BOLT-DWP-NEXT: Contribution size = 64, Format = DWARF32, Version = 5
+; BOLT-DWP-NEXT: "fooint"
+; BOLT-DWP-NEXT: "int"
+; BOLT-DWP-NEXT: "_Z3foov"
+; BOLT-DWP-NEXT: "foo"
+; BOLT-DWP-NEXT: "fint"
+; BOLT-DWP-NEXT: "c1"
+; BOLT-DWP-NEXT: "c2"
+; BOLT-DWP-NEXT: "Foo2Int"
+; BOLT-DWP-NEXT: "f"
+; BOLT-DWP-NEXT: "char"
+; BOLT-DWP-NEXT: "c3"
+; BOLT-DWP-NEXT: "Foo2a"
+; BOLT-DWP-NEXT: "clang version 18.0.0"
+; BOLT-DWP-NEXT: "helper.cpp"
+; BOLT-DWP-NEXT: "helper.dwo
+
+;; Tests that BOLT correctly handles updating DW_AT_comp_dir/DW_AT_dwo_name when outptut directory is specified.
+
+; RUN: mkdir DWOOut
+; RUN: rm main.exe.bolt
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections --dwarf-output-path=%t/DWOOut
+; RUN: cd DWOOut
+; RUN: llvm-dwarfdump --debug-info -r 0 ../main.exe.bolt > log.txt
+; RUN: llvm-dwarfdump --debug-info -r 0 main.dwo0.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-info -r 0 helper.dwo0.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-str-offsets main.dwo0.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-str-offsets helper.dwo0.dwo >> log.txt
+; RUN: cat log.txt | FileCheck -check-prefix=BOLT-PATH %s
+
+; BOLT-PATH: DW_TAG_skeleton_unit
+; BOLT-PATH: DW_AT_comp_dir  ("
+; BOLT-PATH-SAME: dwarf5-df-types-modify-dwo-name-mixed.test.tmp/DWOOut
+; BOLT-PATH: DW_AT_dwo_name  ("main.dwo0.dwo")
+; BOLT-PATH: DW_TAG_skeleton_unit
+; BOLT-PATH: DW_AT_comp_dir  ("
+; BOLT-PATH-SAME: dwarf5-df-types-modify-dwo-name-mixed.test.tmp/DWOOut
+; BOLT-PATH: DW_AT_dwo_name  ("helper.dwo0.dwo")
+; BOLT-PATH: DW_TAG_type_unit
+; BOLT-PATH: DW_AT_comp_dir  ("
+; BOLT-PATH-SAME: dwarf5-df-types-modify-dwo-name-mixed.test.tmp/DWOOut
+; BOLT-PATH: DW_AT_dwo_name  ("main.dwo0.dwo")
+; BOLT-PATH: DW_TAG_type_unit
+; BOLT-PATH: DW_AT_comp_dir  ("
+; BOLT-PATH-SAME: dwarf5-df-types-modify-dwo-name-mixed.test.tmp/DWOOut
+; BOLT-PATH: DW_AT_dwo_name  ("main.dwo0.dwo")
+; BOLT-PATH: DW_TAG_type_unit
+; BOLT-PATH-NOT: DW_AT_comp_dir
+; BOLT-PATH: DW_TAG_type_unit
+; BOLT-PATH-NOT: DW_AT_comp_dir
+; BOLT-PATH: DW_TAG_compile_unit
+; BOLT-PATH:      .debug_str_offsets.dwo contents:
+; BOLT-PATH-NEXT: 0x00000000: Contribution size = 68, Format = DWARF32, Version = 5
+; BOLT-PATH-NEXT: "main"
+; BOLT-PATH-NEXT: "int"
+; BOLT-PATH-NEXT: "argc"
+; BOLT-PATH-NEXT: "argv"
+; BOLT-PATH-NEXT: "char"
+; BOLT-PATH-NEXT: "f2"
+; BOLT-PATH-NEXT: dwarf5-df-types-modify-dwo-name-mixed.test.tmp/DWOOut"
+; BOLT-PATH-NEXT: "main.dwo0.dwo"
+; BOLT-PATH-NEXT: "c1"
+; BOLT-PATH-NEXT: "Foo2"
+; BOLT-PATH-NEXT: "f3"
+; BOLT-PATH-NEXT: "c2"
+; BOLT-PATH-NEXT: "c3"
+; BOLT-PATH-NEXT: "Foo2a"
+; BOLT-PATH-NEXT: "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)"
+; BOLT-PATH-NEXT: "main.cpp"
+; BOLT-PATH-NEXT: helper.dwo0.dwo: file format elf64-x86-64
+
+; BOLT-PATH:      .debug_str_offsets.dwo contents:
+; BOLT-PATH-NEXT: Contribution size = 64, Format = DWARF32, Version = 5
+; BOLT-PATH-NEXT: "fooint"
+; BOLT-PATH-NEXT: "int"
+; BOLT-PATH-NEXT: "_Z3foov"
+; BOLT-PATH-NEXT: "foo"
+; BOLT-PATH-NEXT: "fint"
+; BOLT-PATH-NEXT: "c1"
+; BOLT-PATH-NEXT: "c2"
+; BOLT-PATH-NEXT: "Foo2Int"
+; BOLT-PATH-NEXT: "f"
+; BOLT-PATH-NEXT: "char"
+; BOLT-PATH-NEXT: "c3"
+; BOLT-PATH-NEXT: "Foo2a"
+; BOLT-PATH-NEXT: "clang version 18.0.0"
+; BOLT-PATH-NEXT: "helper.cpp"
+; BOLT-PATH-NEXT: "helper.dwo"
diff --git a/bolt/test/X86/dwarf5-df-types-modify-dwo-name.test b/bolt/test/X86/dwarf5-df-types-modify-dwo-name.test
new file mode 100644
index 000000000000..086f8f813962
--- /dev/null
+++ b/bolt/test/X86/dwarf5-df-types-modify-dwo-name.test
@@ -0,0 +1,175 @@
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-types-debug-names-main.s \
+; RUN: -split-dwarf-file=main.dwo -o main.o
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-types-debug-names-helper.s \
+; RUN: -split-dwarf-file=helper.dwo -o helper.o
+; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o helper.o -o main.exe
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections
+; RUN: llvm-dwarfdump --debug-info -r 0 main.exe.bolt > log.txt
+; RUN: llvm-dwarfdump --debug-info -r 0 main.dwo.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-info -r 0 helper.dwo.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-str-offsets main.dwo.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-str-offsets helper.dwo.dwo >> log.txt
+; RUN: cat log.txt | FileCheck -check-prefix=BOLT %s
+
+;; Tests that BOLT correctly updates DW_AT_dwo_name for TU Untis.
+
+; BOLT: DW_TAG_skeleton_unit
+; BOLT: DW_AT_comp_dir  (".")
+; BOLT: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT: DW_TAG_skeleton_unit
+; BOLT: DW_AT_comp_dir  (".")
+; BOLT: DW_AT_dwo_name  ("helper.dwo.dwo")
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_AT_comp_dir  (".")
+; BOLT: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_AT_comp_dir  (".")
+; BOLT: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_AT_comp_dir  (".")
+; BOLT: DW_AT_dwo_name  ("helper.dwo.dwo")
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_AT_comp_dir  (".")
+; BOLT: DW_AT_dwo_name  ("helper.dwo.dwo")
+; BOLT:      .debug_str_offsets.dwo contents:
+; BOLT-NEXT: 0x00000000: Contribution size = 68, Format = DWARF32, Version = 5
+; BOLT-NEXT: "main"
+; BOLT-NEXT: "int"
+; BOLT-NEXT: "argc"
+; BOLT-NEXT: "argv"
+; BOLT-NEXT: "char"
+; BOLT-NEXT: "f2"
+; BOLT-NEXT: "."
+; BOLT-NEXT: "main.dwo.dwo"
+; BOLT-NEXT: "c1"
+; BOLT-NEXT: "Foo2"
+; BOLT-NEXT: "f3"
+; BOLT-NEXT: "c2"
+; BOLT-NEXT: "c3"
+; BOLT-NEXT: "Foo2a"
+; BOLT-NEXT: "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)"
+; BOLT-NEXT: "main.cpp"
+; BOLT-NEXT: helper.dwo.dwo: file format elf64-x86-64
+
+; BOLT:      .debug_str_offsets.dwo contents:
+; BOLT-NEXT: 0x00000000: Contribution size = 68, Format = DWARF32, Version = 5
+; BOLT-NEXT: "fooint"
+; BOLT-NEXT: "int"
+; BOLT-NEXT: "_Z3foov"
+; BOLT-NEXT: "foo"
+; BOLT-NEXT: "fint"
+; BOLT-NEXT: "."
+; BOLT-NEXT: "helper.dwo.dwo"
+; BOLT-NEXT: "c1"
+; BOLT-NEXT: "c2"
+; BOLT-NEXT: "Foo2Int"
+; BOLT-NEXT: "f"
+; BOLT-NEXT: "char"
+; BOLT-NEXT: "c3"
+; BOLT-NEXT: "Foo2a"
+; BOLT-NEXT: "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)"
+; BOLT-NEXT: "helper.cpp"
+
+
+;; Tests that BOLT correctly handles updating DW_AT_dwo_name when it outputs a DWP file.
+;; Currently skipping one of Type units because it is not being de-dupped.
+;; In the tu-index this TU is not present.
+; RUN: rm main.exe.bolt
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections --write-dwp
+; RUN: llvm-dwarfdump --debug-info -r 0 main.exe.bolt.dwp > logDWP.txt
+; RUN: llvm-dwarfdump --debug-str-offsets main.exe.bolt.dwp >> logDWP.txt
+; RUN: cat logDWP.txt | FileCheck -check-prefix=BOLT-DWP %s
+; BOLT-DWP: DW_TAG_type_unit
+; BOLT-DWP: DW_AT_comp_dir  (".")
+; BOLT-DWP: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT-DWP: DW_TAG_type_unit
+; BOLT-DWP: DW_AT_comp_dir  (".")
+; BOLT-DWP: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT-DWP: DW_TAG_compile_unit
+; BOLT-DWP: DW_AT_dwo_name  ("main.dwo.dwo")
+; BOLT-DWP: DW_TAG_type_unit
+; BOLT-DWP: DW_AT_comp_dir  (".")
+; BOLT-DWP: DW_AT_dwo_name  ("helper.dwo.dwo")
+; BOLT-DWP: DW_TAG_type_unit
+; BOLT-DWP: DW_TAG_compile_unit
+; BOLT-DWP: DW_AT_name  ("helper.cpp")
+; BOLT-DWP: DW_AT_dwo_name  ("helper.dwo.dwo")
+
+;; Tests that BOLT correctly handles updating DW_AT_comp_dir/DW_AT_dwo_name when outptut directory is specified.
+
+; RUN: mkdir DWOOut
+; RUN: rm main.exe.bolt
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections --dwarf-output-path=%t/DWOOut
+; RUN: cd DWOOut
+; RUN: llvm-dwarfdump --debug-info -r 0 ../main.exe.bolt > log.txt
+; RUN: llvm-dwarfdump --debug-info -r 0 main.dwo0.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-info -r 0 helper.dwo0.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-str-offsets main.dwo0.dwo >> log.txt
+; RUN: llvm-dwarfdump --debug-str-offsets helper.dwo0.dwo >> log.txt
+; RUN: cat log.txt | FileCheck -check-prefix=BOLT-PATH %s
+
+; BOLT-PATH: DW_TAG_skeleton_unit
+; BOLT-PATH: DW_AT_comp_dir  ("
+; BOLT-PATH-SAME: dwarf5-df-types-modify-dwo-name.test.tmp/DWOOut
+; BOLT-PATH: DW_AT_dwo_name  ("main.dwo0.dwo")
+; BOLT-PATH: DW_TAG_skeleton_unit
+; BOLT-PATH: DW_AT_comp_dir  ("
+; BOLT-PATH-SAME: dwarf5-df-types-modify-dwo-name.test.tmp/DWOOut
+; BOLT-PATH: DW_AT_dwo_name  ("helper.dwo0.dwo")
+; BOLT-PATH: DW_TAG_type_unit
+; BOLT-PATH: DW_AT_comp_dir  ("
+; BOLT-PATH-SAME: dwarf5-df-types-modify-dwo-name.test.tmp/DWOOut
+; BOLT-PATH: DW_AT_dwo_name  ("main.dwo0.dwo")
+; BOLT-PATH: DW_TAG_type_unit
+; BOLT-PATH: DW_AT_comp_dir  ("
+; BOLT-PATH-SAME: dwarf5-df-types-modify-dwo-name.test.tmp/DWOOut
+; BOLT-PATH: DW_AT_dwo_name  ("main.dwo0.dwo")
+; BOLT-PATH: DW_TAG_type_unit
+; BOLT-PATH: DW_AT_comp_dir  ("
+; BOLT-PATH-SAME: dwarf5-df-types-modify-dwo-name.test.tmp/DWOOut
+; BOLT-PATH: DW_AT_dwo_name  ("helper.dwo0.dwo")
+; BOLT-PATH: DW_TAG_type_unit
+; BOLT-PATH: DW_AT_comp_dir  ("
+; BOLT-PATH-SAME: dwarf5-df-types-modify-dwo-name.test.tmp/DWOOut
+; BOLT-PATH: DW_AT_dwo_name  ("helper.dwo0.dwo")
+; BOLT-PATH:      .debug_str_offsets.dwo contents:
+; BOLT-PATH-NEXT: 0x00000000: Contribution size = 68, Format = DWARF32, Version = 5
+; BOLT-PATH-NEXT: "main"
+; BOLT-PATH-NEXT: "int"
+; BOLT-PATH-NEXT: "argc"
+; BOLT-PATH-NEXT: "argv"
+; BOLT-PATH-NEXT: "char"
+; BOLT-PATH-NEXT: "f2"
+; BOLT-PATH-NEXT: dwarf5-df-types-modify-dwo-name.test.tmp/DWOOut"
+; BOLT-PATH-NEXT: "main.dwo0.dwo"
+; BOLT-PATH-NEXT: "c1"
+; BOLT-PATH-NEXT: "Foo2"
+; BOLT-PATH-NEXT: "f3"
+; BOLT-PATH-NEXT: "c2"
+; BOLT-PATH-NEXT: "c3"
+; BOLT-PATH-NEXT: "Foo2a"
+; BOLT-PATH-NEXT: "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)"
+; BOLT-PATH-NEXT: "main.cpp"
+; BOLT-PATH-NEXT: helper.dwo0.dwo: file format elf64-x86-64
+
+; BOLT-PATH:      .debug_str_offsets.dwo contents:
+; BOLT-PATH-NEXT: 0x00000000: Contribution size = 68, Format = DWARF32, Version = 5
+; BOLT-PATH-NEXT: "fooint"
+; BOLT-PATH-NEXT: "int"
+; BOLT-PATH-NEXT: "_Z3foov"
+; BOLT-PATH-NEXT: "foo"
+; BOLT-PATH-NEXT: "fint"
+; BOLT-PATH-NEXT: dwarf5-df-types-modify-dwo-name.test.tmp/DWOOut"
+; BOLT-PATH-NEXT: "helper.dwo0.dwo"
+; BOLT-PATH-NEXT: "c1"
+; BOLT-PATH-NEXT: "c2"
+; BOLT-PATH-NEXT: "Foo2Int"
+; BOLT-PATH-NEXT: "f"
+; BOLT-PATH-NEXT: "char"
+; BOLT-PATH-NEXT: "c3"
+; BOLT-PATH-NEXT: "Foo2a"
+; BOLT-PATH-NEXT: "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)"
+; BOLT-PATH-NEXT: "helper.cpp"
-- 
GitLab


From 844355a8cb4b4fa4a6fa39ac47e1169233bb7130 Mon Sep 17 00:00:00 2001
From: VincentWu <43398706+Xinlong-Wu@users.noreply.github.com>
Date: Wed, 15 May 2024 08:26:45 +1000
Subject: [PATCH 285/578] [RISC-V] remove I ext when E ext has been enabled
 (#92070)

After patch https://github.com/llvm/llvm-project/pull/88805

`I` Ext will be added automatically when we running the command like
`./build/bin/llc -mtriple=riscv32 -mattr=+e -target-abi ilp32e
-verify-machineinstrs llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll`

it will generate
```
	.text
	.attribute	4, 16
	.attribute	5, "rv32i2p1_e2pe"
	.file	"zcmp-additional-stack.ll"
	.globl	func                            # -- Begin function func
	.p2align	1
	.type	func,@function
```

This patch reset the I ext in FeatureBit when `+e` has been specify
---
 llvm/lib/TargetParser/RISCVISAInfo.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index e22dd6032cb0..575c9dbad515 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -758,6 +758,8 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
 }
 
 Error RISCVISAInfo::checkDependency() {
+  bool HasE = Exts.count("e") != 0;
+  bool HasI = Exts.count("i") != 0;
   bool HasC = Exts.count("c") != 0;
   bool HasF = Exts.count("f") != 0;
   bool HasZfinx = Exts.count("zfinx") != 0;
@@ -765,6 +767,10 @@ Error RISCVISAInfo::checkDependency() {
   bool HasZvl = MinVLen != 0;
   bool HasZcmt = Exts.count("zcmt") != 0;
 
+  if (HasI && HasE)
+    return createStringError(errc::invalid_argument,
+                             "'I' and 'E' extensions are incompatible");
+
   if (HasF && HasZfinx)
     return createStringError(errc::invalid_argument,
                              "'f' and 'zfinx' extensions are incompatible");
@@ -852,6 +858,9 @@ void RISCVISAInfo::updateImplication() {
     addExtension("i", Version.value());
   }
 
+  if (HasE && HasI)
+    Exts.erase("i");
+
   assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name");
 
   // This loop may execute over 1 iteration since implication can be layered
-- 
GitLab


From 3ca428c090624d3cfc530144da6dcd3abfd9ea63 Mon Sep 17 00:00:00 2001
From: Joe Nash 
Date: Tue, 14 May 2024 18:29:16 -0400
Subject: [PATCH 286/578] [AMDGPU][True16] Add VOP1Inst_t16_with_profiles class
 (#92184)

NFC. Makes the VOP1Inst_t16 interface more generic to support future
instructions cleanly.
---
 llvm/lib/Target/AMDGPU/VOP1Instructions.td | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/VOP1Instructions.td b/llvm/lib/Target/AMDGPU/VOP1Instructions.td
index 4a56fad0cd60..b875ddc62a7a 100644
--- a/llvm/lib/Target/AMDGPU/VOP1Instructions.td
+++ b/llvm/lib/Target/AMDGPU/VOP1Instructions.td
@@ -153,20 +153,26 @@ multiclass VOP1Inst ;
 }
 
-multiclass VOP1Inst_t16 {
   let OtherPredicates = [NotHasTrue16BitInsts, Has16BitInsts]  in {
     defm NAME : VOP1Inst;
   }
   let OtherPredicates = [UseRealTrue16Insts] in {
-    defm _t16 : VOP1Inst, node>;
+    defm _t16 : VOP1Inst;
   }
   let OtherPredicates = [UseFakeTrue16Insts] in {
-    defm _fake16 : VOP1Inst, node>;
+    defm _fake16 : VOP1Inst;
   }
 }
 
+multiclass VOP1Inst_t16 :
+  VOP1Inst_t16_with_profiles, VOPProfile_Fake16

, node>; + // Special profile for instructions which have clamp // and output modifiers (but have no input modifiers) class VOPProfileI2F : -- GitLab From e417e61532ac373e7b0708262dedefcdaf6ced9c Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 14 May 2024 12:52:48 -0700 Subject: [PATCH 287/578] [RISCV][LegalizeTypes] Add additional test coverage for type promotion of VP_FSHL/FSHR. NFC There's a special path when the promoted type has an element size more than twice the size of the original type. --- llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll | 53 +++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll b/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll index f9f085dcc161..277cd7dcdabc 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll @@ -1370,3 +1370,56 @@ define @fshl_v1i9( %a, %b, %res = call @llvm.vp.fshl.nxv1i9( %a, %b, %c, %m, i32 %evl) ret %res } + +declare @llvm.vp.trunc.nxv1i4.nxv1i8(, , i32) +declare @llvm.vp.zext.nxv1i8.nxv1i4(, , i32) +declare @llvm.vp.fshr.nxv1i4(, , , , i32) +define @fshr_v1i4( %a, %b, %c, %m, i32 zeroext %evl) { +; CHECK-LABEL: fshr_v1i4: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma +; CHECK-NEXT: vand.vi v10, v10, 15 +; CHECK-NEXT: li a1, 4 +; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, ma +; CHECK-NEXT: vremu.vx v10, v10, a1, v0.t +; CHECK-NEXT: vsll.vi v8, v8, 4, v0.t +; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma +; CHECK-NEXT: vand.vi v9, v9, 15 +; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, ma +; CHECK-NEXT: vor.vv v8, v8, v9, v0.t +; CHECK-NEXT: vsrl.vv v8, v8, v10, v0.t +; CHECK-NEXT: vand.vi v8, v8, 15, v0.t +; CHECK-NEXT: ret + %trunca = call @llvm.vp.trunc.nxv1i4.nxv1i8( %a, %m, i32 zeroext %evl) + %truncb = call @llvm.vp.trunc.nxv1i4.nxv1i8( %b, %m, i32 zeroext %evl) + %truncc = call @llvm.vp.trunc.nxv1i4.nxv1i8( %c, %m, i32 zeroext %evl) + %fshr = call @llvm.vp.fshr.nxv1i4( %trunca, %truncb, %truncc, %m, i32 %evl) + %res = call @llvm.vp.zext.nxv1i8.nxv1i4( %fshr, %m, i32 zeroext %evl) + ret %res +} + +declare @llvm.vp.fshl.nxv1i4(, , , , i32) +define @fshl_v1i4( %a, %b, %c, %m, i32 zeroext %evl) { +; CHECK-LABEL: fshl_v1i4: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma +; CHECK-NEXT: vand.vi v10, v10, 15 +; CHECK-NEXT: li a1, 4 +; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, ma +; CHECK-NEXT: vremu.vx v10, v10, a1, v0.t +; CHECK-NEXT: vsll.vi v8, v8, 4, v0.t +; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma +; CHECK-NEXT: vand.vi v9, v9, 15 +; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, ma +; CHECK-NEXT: vor.vv v8, v8, v9, v0.t +; CHECK-NEXT: vsll.vv v8, v8, v10, v0.t +; CHECK-NEXT: vsrl.vi v8, v8, 4, v0.t +; CHECK-NEXT: vand.vi v8, v8, 15, v0.t +; CHECK-NEXT: ret + %trunca = call @llvm.vp.trunc.nxv1i4.nxv1i8( %a, %m, i32 zeroext %evl) + %truncb = call @llvm.vp.trunc.nxv1i4.nxv1i8( %b, %m, i32 zeroext %evl) + %truncc = call @llvm.vp.trunc.nxv1i4.nxv1i8( %c, %m, i32 zeroext %evl) + %fshl = call @llvm.vp.fshl.nxv1i4( %trunca, %truncb, %truncc, %m, i32 %evl) + %res = call @llvm.vp.zext.nxv1i8.nxv1i4( %fshl, %m, i32 zeroext %evl) + ret %res +} -- GitLab From 4a17e86f27a0a527ef5316f14fa0e5a60546d9ec Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Tue, 14 May 2024 18:39:48 -0500 Subject: [PATCH 288/578] [LinkerWrapper] Add an overriding option for debugging (#91984) Summary: One of the downsides of the linker wrapper is that it made debugging more difficult. It is very powerful in that it can resolve a lot of input matching and library handling that could not be done before. However, the old method allowed users to simply copy-paste the script files to modify the output and test it. This patch attempts to make it easier to debug changes by letting the user override all the linker inputs. That is, we provide a user-created binary that is treated like the final output of the device link step. The intended use-case is for using `-save-temps` to get some IR, then modifying the IR and sticking it back in to see if it exhibits the old failures. --- clang/docs/ClangLinkerWrapper.rst | 38 ++++++++++++++++ clang/test/Driver/linker-wrapper.c | 7 +++ .../ClangLinkerWrapper.cpp | 43 +++++++++++++++++++ .../clang-linker-wrapper/LinkerWrapperOpts.td | 4 ++ 4 files changed, 92 insertions(+) diff --git a/clang/docs/ClangLinkerWrapper.rst b/clang/docs/ClangLinkerWrapper.rst index 3bef55847573..99352863b477 100644 --- a/clang/docs/ClangLinkerWrapper.rst +++ b/clang/docs/ClangLinkerWrapper.rst @@ -46,6 +46,8 @@ only for the linker wrapper will be forwarded to the wrapped linker job. -l Search for library --opt-level= Optimization level for LTO + --override-image= + Uses the provided file as if it were the output of the device link step -o Path to file to write output --pass-remarks-analysis= Pass remarks for LTO @@ -87,6 +89,42 @@ other. Generally, this requires that the target triple and architecture match. An exception is made when the architecture is listed as ``generic``, which will cause it be linked with any other device code with the same target triple. +Debugging +========= + +The linker wrapper performs a lot of steps internally, such as input matching, +symbol resolution, and image registration. This makes it difficult to debug in +some scenarios. The behavior of the linker-wrapper is controlled mostly through +metadata, described in `clang documentation +`_. Intermediate output can +be obtained from the linker-wrapper using the ``--save-temps`` flag. These files +can then be modified. + +.. code-block:: sh + + $> clang openmp.c -fopenmp --offload-arch=gfx90a -c + $> clang openmp.o -fopenmp --offload-arch=gfx90a -Wl,--save-temps + $> ; Modify temp files. + $> llvm-objcopy --update-section=.llvm.offloading=out.bc openmp.o + +Doing this will allow you to override one of the input files by replacing its +embedded offloading metadata with a user-modified version. However, this will be +more difficult when there are multiple input files. For a very large hammer, the +``--override-image==`` flag can be used. + +In the following example, we use the ``--save-temps`` to obtain the LLVM-IR just +before running the backend. We then modify it to test altered behavior, and then +compile it to a binary. This can then be passed to the linker-wrapper which will +then ignore all embedded metadata and use the provided image as if it were the +result of the device linking phase. + +.. code-block:: sh + + $> clang openmp.c -fopenmp --offload-arch=gfx90a -Wl,--save-temps + $> ; Modify temp files. + $> clang --target=amdgcn-amd-amdhsa -mcpu=gfx90a -nogpulib out.bc -o a.out + $> clang openmp.c -fopenmp --offload-arch=gfx90a -Wl,--override-image=openmp=a.out + Example ======= diff --git a/clang/test/Driver/linker-wrapper.c b/clang/test/Driver/linker-wrapper.c index 51bf98b2ed39..0d05f913aad6 100644 --- a/clang/test/Driver/linker-wrapper.c +++ b/clang/test/Driver/linker-wrapper.c @@ -226,3 +226,10 @@ __attribute__((visibility("protected"), used)) int x; // RELOCATABLE-LINK-CUDA: fatbinary{{.*}} -64 --create {{.*}}.fatbin --image=profile=sm_89,file={{.*}}.img // RELOCATABLE-LINK-CUDA: /usr/bin/ld.lld{{.*}}-r // RELOCATABLE-LINK-CUDA: llvm-objcopy{{.*}}a.out --remove-section .llvm.offloading + +// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o +// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \ +// RUN: --linker-path=/usr/bin/ld --override=image=openmp=%t.o %t.o -o a.out 2>&1 \ +// RUN: | FileCheck %s --check-prefix=OVERRIDE +// OVERRIDE-NOT: clang +// OVERRIDE: /usr/bin/ld diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 69d8cb446fad..aee98c5a524a 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -1149,6 +1149,39 @@ DerivedArgList getLinkerArgs(ArrayRef Input, return DAL; } +Error handleOverrideImages( + const InputArgList &Args, + DenseMap> &Images) { + for (StringRef Arg : Args.getAllArgValues(OPT_override_image)) { + OffloadKind Kind = getOffloadKind(Arg.split("=").first); + StringRef Filename = Arg.split("=").second; + + ErrorOr> BufferOrErr = + MemoryBuffer::getFileOrSTDIN(Filename); + if (std::error_code EC = BufferOrErr.getError()) + return createFileError(Filename, EC); + + Expected> ElfOrErr = + ObjectFile::createELFObjectFile(**BufferOrErr, + /*InitContent=*/false); + if (!ElfOrErr) + return ElfOrErr.takeError(); + ObjectFile &Elf = **ElfOrErr; + + OffloadingImage TheImage{}; + TheImage.TheImageKind = IMG_Object; + TheImage.TheOffloadKind = Kind; + TheImage.StringData["triple"] = + Args.MakeArgString(Elf.makeTriple().getTriple()); + if (std::optional CPU = Elf.tryGetCPUName()) + TheImage.StringData["arch"] = Args.MakeArgString(*CPU); + TheImage.Image = std::move(*BufferOrErr); + + Images[Kind].emplace_back(std::move(TheImage)); + } + return Error::success(); +} + /// Transforms all the extracted offloading input files into an image that can /// be registered by the runtime. Expected> linkAndWrapDeviceFiles( @@ -1158,6 +1191,12 @@ Expected> linkAndWrapDeviceFiles( std::mutex ImageMtx; DenseMap> Images; + + // Initialize the images with any overriding inputs. + if (Args.hasArg(OPT_override_image)) + if (Error Err = handleOverrideImages(Args, Images)) + return Err; + auto Err = parallelForEachError(LinkerInputFiles, [&](auto &Input) -> Error { llvm::TimeTraceScope TimeScope("Link device input"); @@ -1439,6 +1478,10 @@ Expected>> getDeviceInput(const ArgList &Args) { llvm::TimeTraceScope TimeScope("ExtractDeviceCode"); + // Skip all the input if the user is overriding the output. + if (Args.hasArg(OPT_override_image)) + return SmallVector>(); + StringRef Root = Args.getLastArgValue(OPT_sysroot_EQ); SmallVector LibraryPaths; for (const opt::Arg *Arg : Args.filtered(OPT_library_path, OPT_libpath)) diff --git a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td index 0a8bd541c452..eb31b98a3f54 100644 --- a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td +++ b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td @@ -74,6 +74,10 @@ def wrapper_jobs : Joined<["--"], "wrapper-jobs=">, Flags<[WrapperOnlyOption]>, MetaVarName<"">, HelpText<"Sets the number of parallel jobs to use for device linking">; +def override_image : Joined<["--"], "override-image=">, + Flags<[WrapperOnlyOption]>, MetaVarName<"">, + HelpText<"Uses the provided file as if it were the output of the device link step">; + // Flags passed to the device linker. def arch_EQ : Joined<["--"], "arch=">, Flags<[DeviceOnlyOption, HelpHidden]>, MetaVarName<"">, -- GitLab From c5cd049566a795ba5de88dfbb2eb563cad4a9d8a Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Tue, 14 May 2024 18:43:42 -0500 Subject: [PATCH 289/578] [Clang][Fixup] Fix deleted constructor on older compilers --- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index aee98c5a524a..07a8d53c04b1 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -1195,7 +1195,7 @@ Expected> linkAndWrapDeviceFiles( // Initialize the images with any overriding inputs. if (Args.hasArg(OPT_override_image)) if (Error Err = handleOverrideImages(Args, Images)) - return Err; + return std::move(Err); auto Err = parallelForEachError(LinkerInputFiles, [&](auto &Input) -> Error { llvm::TimeTraceScope TimeScope("Link device input"); -- GitLab From dfdc3dcbe7f38bde64bc83a74b9c3451c50e1ad4 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Tue, 14 May 2024 18:01:23 -0700 Subject: [PATCH 290/578] [ctx_profile] Profile reader and writer (#91859) Utility converting a profile coming from `compiler_rt` to bitstream, and a reader. `PGOCtxProfileWriter::write` would be used as the `Writer` parameter for `__llvm_ctx_profile_fetch` API. This is expected to happen in user code, for example in the RPC hanler tasked with collecting a profile, and would look like this: ``` // set up an output stream "Out", which could contain other stuff { // constructing the Writer will start the section, in Out, containing // the collected contextual profiles. PGOCtxProfWriter Writer(Out); __llvm_ctx_profile_fetch(&Writer, +[](void* W, const ContextNode &N) { reinterpret_cast(W)->write(N); }); // Writer going out of scope will finish up the section. } ``` The reader produces a data structure suitable for maintenance during IPO transformations. --- .../llvm/ProfileData/PGOCtxProfReader.h | 92 +++++++ .../llvm/ProfileData/PGOCtxProfWriter.h | 91 +++++++ llvm/lib/ProfileData/CMakeLists.txt | 2 + llvm/lib/ProfileData/PGOCtxProfReader.cpp | 173 ++++++++++++ llvm/lib/ProfileData/PGOCtxProfWriter.cpp | 49 ++++ llvm/unittests/ProfileData/CMakeLists.txt | 1 + .../PGOCtxProfReaderWriterTest.cpp | 255 ++++++++++++++++++ 7 files changed, 663 insertions(+) create mode 100644 llvm/include/llvm/ProfileData/PGOCtxProfReader.h create mode 100644 llvm/include/llvm/ProfileData/PGOCtxProfWriter.h create mode 100644 llvm/lib/ProfileData/PGOCtxProfReader.cpp create mode 100644 llvm/lib/ProfileData/PGOCtxProfWriter.cpp create mode 100644 llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp diff --git a/llvm/include/llvm/ProfileData/PGOCtxProfReader.h b/llvm/include/llvm/ProfileData/PGOCtxProfReader.h new file mode 100644 index 000000000000..a19b3f51d642 --- /dev/null +++ b/llvm/include/llvm/ProfileData/PGOCtxProfReader.h @@ -0,0 +1,92 @@ +//===--- PGOCtxProfReader.h - Contextual profile reader ---------*- 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 +/// +/// Reader for contextual iFDO profile, which comes in bitstream format. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H +#define LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Bitstream/BitstreamReader.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Support/Error.h" +#include +#include + +namespace llvm { +/// The loaded contextual profile, suitable for mutation during IPO passes. We +/// generally expect a fraction of counters and of callsites to be populated. +/// We continue to model counters as vectors, but callsites are modeled as a map +/// of a map. The expectation is that, typically, there is a small number of +/// indirect targets (usually, 1 for direct calls); but potentially a large +/// number of callsites, and, as inlining progresses, the callsite count of a +/// caller will grow. +class PGOContextualProfile final { +public: + using CallTargetMapTy = std::map; + using CallsiteMapTy = DenseMap; + +private: + friend class PGOCtxProfileReader; + GlobalValue::GUID GUID = 0; + SmallVector Counters; + CallsiteMapTy Callsites; + + PGOContextualProfile(GlobalValue::GUID G, + SmallVectorImpl &&Counters) + : GUID(G), Counters(std::move(Counters)) {} + + Expected + getOrEmplace(uint32_t Index, GlobalValue::GUID G, + SmallVectorImpl &&Counters); + +public: + PGOContextualProfile(const PGOContextualProfile &) = delete; + PGOContextualProfile &operator=(const PGOContextualProfile &) = delete; + PGOContextualProfile(PGOContextualProfile &&) = default; + PGOContextualProfile &operator=(PGOContextualProfile &&) = default; + + GlobalValue::GUID guid() const { return GUID; } + const SmallVectorImpl &counters() const { return Counters; } + const CallsiteMapTy &callsites() const { return Callsites; } + CallsiteMapTy &callsites() { return Callsites; } + + bool hasCallsite(uint32_t I) const { + return Callsites.find(I) != Callsites.end(); + } + + const CallTargetMapTy &callsite(uint32_t I) const { + assert(hasCallsite(I) && "Callsite not found"); + return Callsites.find(I)->second; + } + void getContainedGuids(DenseSet &Guids) const; +}; + +class PGOCtxProfileReader final { + BitstreamCursor &Cursor; + Expected advance(); + Error readMetadata(); + Error wrongValue(const Twine &); + Error unsupported(const Twine &); + + Expected, PGOContextualProfile>> + readContext(bool ExpectIndex); + bool canReadContext(); + +public: + PGOCtxProfileReader(BitstreamCursor &Cursor) : Cursor(Cursor) {} + + Expected> loadContexts(); +}; +} // namespace llvm +#endif diff --git a/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h b/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h new file mode 100644 index 000000000000..15578c51a495 --- /dev/null +++ b/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h @@ -0,0 +1,91 @@ +//===- PGOCtxProfWriter.h - Contextual Profile Writer -----------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares a utility for writing a contextual profile to bitstream. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ +#define LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ + +#include "llvm/Bitstream/BitstreamWriter.h" +#include "llvm/ProfileData/CtxInstrContextNode.h" + +namespace llvm { +enum PGOCtxProfileRecords { Invalid = 0, Version, Guid, CalleeIndex, Counters }; + +enum PGOCtxProfileBlockIDs { + ProfileMetadataBlockID = 100, + ContextNodeBlockID = ProfileMetadataBlockID + 1 +}; + +/// Write one or more ContextNodes to the provided raw_fd_stream. +/// The caller must destroy the PGOCtxProfileWriter object before closing the +/// stream. +/// The design allows serializing a bunch of contexts embedded in some other +/// file. The overall format is: +/// +/// [... other data written to the stream...] +/// SubBlock(ProfileMetadataBlockID) +/// Version +/// SubBlock(ContextNodeBlockID) +/// [RECORDS] +/// SubBlock(ContextNodeBlockID) +/// [RECORDS] +/// [... more SubBlocks] +/// EndBlock +/// EndBlock +/// +/// The "RECORDS" are bitsream records. The IDs are in CtxProfileCodes (except) +/// for Version, which is just for metadata). All contexts will have Guid and +/// Counters, and all but the roots have CalleeIndex. The order in which the +/// records appear does not matter, but they must precede any subcontexts, +/// because that helps keep the reader code simpler. +/// +/// Subblock containment captures the context->subcontext relationship. The +/// "next()" relationship in the raw profile, between call targets of indirect +/// calls, are just modeled as peer subblocks where the callee index is the +/// same. +/// +/// Versioning: the writer may produce additional records not known by the +/// reader. The version number indicates a more structural change. +/// The current version, in particular, is set up to expect optional extensions +/// like value profiling - which would appear as additional records. For +/// example, value profiling would produce a new record with a new record ID, +/// containing the profiled values (much like the counters) +class PGOCtxProfileWriter final { + SmallVector Buff; + BitstreamWriter Writer; + + void writeCounters(const ctx_profile::ContextNode &Node); + void writeImpl(std::optional CallerIndex, + const ctx_profile::ContextNode &Node); + +public: + PGOCtxProfileWriter(raw_fd_stream &Out, + std::optional VersionOverride = std::nullopt) + : Writer(Buff, &Out, 0) { + Writer.EnterSubblock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID, + CodeLen); + const auto Version = VersionOverride ? *VersionOverride : CurrentVersion; + Writer.EmitRecord(PGOCtxProfileRecords::Version, + SmallVector({Version})); + } + + ~PGOCtxProfileWriter() { Writer.ExitBlock(); } + + void write(const ctx_profile::ContextNode &); + + // constants used in writing which a reader may find useful. + static constexpr unsigned CodeLen = 2; + static constexpr uint32_t CurrentVersion = 1; + static constexpr unsigned VBREncodingBits = 6; +}; + +} // namespace llvm +#endif diff --git a/llvm/lib/ProfileData/CMakeLists.txt b/llvm/lib/ProfileData/CMakeLists.txt index 408f9ff01ec8..2397eebaf7b1 100644 --- a/llvm/lib/ProfileData/CMakeLists.txt +++ b/llvm/lib/ProfileData/CMakeLists.txt @@ -7,6 +7,8 @@ add_llvm_component_library(LLVMProfileData ItaniumManglingCanonicalizer.cpp MemProf.cpp MemProfReader.cpp + PGOCtxProfReader.cpp + PGOCtxProfWriter.cpp ProfileSummaryBuilder.cpp SampleProf.cpp SampleProfReader.cpp diff --git a/llvm/lib/ProfileData/PGOCtxProfReader.cpp b/llvm/lib/ProfileData/PGOCtxProfReader.cpp new file mode 100644 index 000000000000..3710f2e4b818 --- /dev/null +++ b/llvm/lib/ProfileData/PGOCtxProfReader.cpp @@ -0,0 +1,173 @@ +//===- PGOCtxProfReader.cpp - Contextual Instrumentation profile reader ---===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Read a contextual profile into a datastructure suitable for maintenance +// throughout IPO +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/PGOCtxProfReader.h" +#include "llvm/Bitstream/BitCodeEnums.h" +#include "llvm/Bitstream/BitstreamReader.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" + +using namespace llvm; + +// FIXME(#92054) - these Error handling macros are (re-)invented in a few +// places. +#define EXPECT_OR_RET(LHS, RHS) \ + auto LHS = RHS; \ + if (!LHS) \ + return LHS.takeError(); + +#define RET_ON_ERR(EXPR) \ + if (auto Err = (EXPR)) \ + return Err; + +Expected +PGOContextualProfile::getOrEmplace(uint32_t Index, GlobalValue::GUID G, + SmallVectorImpl &&Counters) { + auto [Iter, Inserted] = Callsites[Index].insert( + {G, PGOContextualProfile(G, std::move(Counters))}); + if (!Inserted) + return make_error(instrprof_error::invalid_prof, + "Duplicate GUID for same callsite."); + return Iter->second; +} + +void PGOContextualProfile::getContainedGuids( + DenseSet &Guids) const { + Guids.insert(GUID); + for (const auto &[_, Callsite] : Callsites) + for (const auto &[_, Callee] : Callsite) + Callee.getContainedGuids(Guids); +} + +Expected PGOCtxProfileReader::advance() { + return Cursor.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); +} + +Error PGOCtxProfileReader::wrongValue(const Twine &Msg) { + return make_error(instrprof_error::invalid_prof, Msg); +} + +Error PGOCtxProfileReader::unsupported(const Twine &Msg) { + return make_error(instrprof_error::unsupported_version, Msg); +} + +bool PGOCtxProfileReader::canReadContext() { + auto Blk = advance(); + if (!Blk) { + consumeError(Blk.takeError()); + return false; + } + return Blk->Kind == BitstreamEntry::SubBlock && + Blk->ID == PGOCtxProfileBlockIDs::ContextNodeBlockID; +} + +Expected, PGOContextualProfile>> +PGOCtxProfileReader::readContext(bool ExpectIndex) { + RET_ON_ERR(Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ContextNodeBlockID)); + + std::optional Guid; + std::optional> Counters; + std::optional CallsiteIndex; + + SmallVector RecordValues; + + // We don't prescribe the order in which the records come in, and we are ok + // if other unsupported records appear. We seek in the current subblock until + // we get all we know. + auto GotAllWeNeed = [&]() { + return Guid.has_value() && Counters.has_value() && + (!ExpectIndex || CallsiteIndex.has_value()); + }; + while (!GotAllWeNeed()) { + RecordValues.clear(); + EXPECT_OR_RET(Entry, advance()); + if (Entry->Kind != BitstreamEntry::Record) + return wrongValue( + "Expected records before encountering more subcontexts"); + EXPECT_OR_RET(ReadRecord, + Cursor.readRecord(bitc::UNABBREV_RECORD, RecordValues)); + switch (*ReadRecord) { + case PGOCtxProfileRecords::Guid: + if (RecordValues.size() != 1) + return wrongValue("The GUID record should have exactly one value"); + Guid = RecordValues[0]; + break; + case PGOCtxProfileRecords::Counters: + Counters = std::move(RecordValues); + if (Counters->empty()) + return wrongValue("Empty counters. At least the entry counter (one " + "value) was expected"); + break; + case PGOCtxProfileRecords::CalleeIndex: + if (!ExpectIndex) + return wrongValue("The root context should not have a callee index"); + if (RecordValues.size() != 1) + return wrongValue("The callee index should have exactly one value"); + CallsiteIndex = RecordValues[0]; + break; + default: + // OK if we see records we do not understand, like records (profile + // components) introduced later. + break; + } + } + + PGOContextualProfile Ret(*Guid, std::move(*Counters)); + + while (canReadContext()) { + EXPECT_OR_RET(SC, readContext(true)); + auto &Targets = Ret.callsites()[*SC->first]; + auto [_, Inserted] = + Targets.insert({SC->second.guid(), std::move(SC->second)}); + if (!Inserted) + return wrongValue( + "Unexpected duplicate target (callee) at the same callsite."); + } + return std::make_pair(CallsiteIndex, std::move(Ret)); +} + +Error PGOCtxProfileReader::readMetadata() { + EXPECT_OR_RET(Blk, advance()); + if (Blk->Kind != BitstreamEntry::SubBlock) + return unsupported("Expected Version record"); + RET_ON_ERR( + Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID)); + EXPECT_OR_RET(MData, advance()); + if (MData->Kind != BitstreamEntry::Record) + return unsupported("Expected Version record"); + + SmallVector Ver; + EXPECT_OR_RET(Code, Cursor.readRecord(bitc::UNABBREV_RECORD, Ver)); + if (*Code != PGOCtxProfileRecords::Version) + return unsupported("Expected Version record"); + if (Ver.size() != 1 || Ver[0] > PGOCtxProfileWriter::CurrentVersion) + return unsupported("Version " + Twine(*Code) + + " is higher than supported version " + + Twine(PGOCtxProfileWriter::CurrentVersion)); + return Error::success(); +} + +Expected> +PGOCtxProfileReader::loadContexts() { + std::map Ret; + RET_ON_ERR(readMetadata()); + while (canReadContext()) { + EXPECT_OR_RET(E, readContext(false)); + auto Key = E->second.guid(); + if (!Ret.insert({Key, std::move(E->second)}).second) + return wrongValue("Duplicate roots"); + } + return Ret; +} diff --git a/llvm/lib/ProfileData/PGOCtxProfWriter.cpp b/llvm/lib/ProfileData/PGOCtxProfWriter.cpp new file mode 100644 index 000000000000..508179756446 --- /dev/null +++ b/llvm/lib/ProfileData/PGOCtxProfWriter.cpp @@ -0,0 +1,49 @@ +//===- PGOCtxProfWriter.cpp - Contextual Instrumentation profile writer ---===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Write a contextual profile to bitstream. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Bitstream/BitCodeEnums.h" + +using namespace llvm; +using namespace llvm::ctx_profile; + +void PGOCtxProfileWriter::writeCounters(const ContextNode &Node) { + Writer.EmitCode(bitc::UNABBREV_RECORD); + Writer.EmitVBR(PGOCtxProfileRecords::Counters, VBREncodingBits); + Writer.EmitVBR(Node.counters_size(), VBREncodingBits); + for (uint32_t I = 0U; I < Node.counters_size(); ++I) + Writer.EmitVBR64(Node.counters()[I], VBREncodingBits); +} + +// recursively write all the subcontexts. We do need to traverse depth first to +// model the context->subcontext implicitly, and since this captures call +// stacks, we don't really need to be worried about stack overflow and we can +// keep the implementation simple. +void PGOCtxProfileWriter::writeImpl(std::optional CallerIndex, + const ContextNode &Node) { + Writer.EnterSubblock(PGOCtxProfileBlockIDs::ContextNodeBlockID, CodeLen); + Writer.EmitRecord(PGOCtxProfileRecords::Guid, + SmallVector{Node.guid()}); + if (CallerIndex) + Writer.EmitRecord(PGOCtxProfileRecords::CalleeIndex, + SmallVector{*CallerIndex}); + writeCounters(Node); + for (uint32_t I = 0U; I < Node.callsites_size(); ++I) + for (const auto *Subcontext = Node.subContexts()[I]; Subcontext; + Subcontext = Subcontext->next()) + writeImpl(I, *Subcontext); + Writer.ExitBlock(); +} + +void PGOCtxProfileWriter::write(const ContextNode &RootNode) { + writeImpl(std::nullopt, RootNode); +} diff --git a/llvm/unittests/ProfileData/CMakeLists.txt b/llvm/unittests/ProfileData/CMakeLists.txt index ce3a0a45ccf1..c92642ded828 100644 --- a/llvm/unittests/ProfileData/CMakeLists.txt +++ b/llvm/unittests/ProfileData/CMakeLists.txt @@ -13,6 +13,7 @@ add_llvm_unittest(ProfileDataTests InstrProfTest.cpp ItaniumManglingCanonicalizerTest.cpp MemProfTest.cpp + PGOCtxProfReaderWriterTest.cpp SampleProfTest.cpp SymbolRemappingReaderTest.cpp ) diff --git a/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp b/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp new file mode 100644 index 000000000000..d2cdbb28e2fc --- /dev/null +++ b/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp @@ -0,0 +1,255 @@ +//===-------------- PGOCtxProfReadWriteTest.cpp ---------------------------===// +// +// 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 "llvm/Bitstream/BitstreamReader.h" +#include "llvm/ProfileData/CtxInstrContextNode.h" +#include "llvm/ProfileData/PGOCtxProfReader.h" +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Testing/Support/SupportHelpers.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::ctx_profile; + +class PGOCtxProfRWTest : public ::testing::Test { + std::vector> Nodes; + std::map Roots; + +public: + ContextNode *createNode(GUID Guid, uint32_t NrCounters, uint32_t NrCallsites, + ContextNode *Next = nullptr) { + auto AllocSize = ContextNode::getAllocSize(NrCounters, NrCallsites); + auto *Mem = Nodes.emplace_back(std::make_unique(AllocSize)).get(); + std::memset(Mem, 0, AllocSize); + auto *Ret = new (Mem) ContextNode(Guid, NrCounters, NrCallsites, Next); + return Ret; + } + + void SetUp() override { + // Root (guid 1) has 2 callsites, one used for an indirect call to either + // guid 2 or 4. + // guid 2 calls guid 5 + // guid 5 calls guid 2 + // there's also a second root, guid3. + auto *Root1 = createNode(1, 2, 2); + Root1->counters()[0] = 10; + Root1->counters()[1] = 11; + Roots.insert({1, Root1}); + auto *L1 = createNode(2, 1, 1); + L1->counters()[0] = 12; + Root1->subContexts()[1] = createNode(4, 3, 1, L1); + Root1->subContexts()[1]->counters()[0] = 13; + Root1->subContexts()[1]->counters()[1] = 14; + Root1->subContexts()[1]->counters()[2] = 15; + + auto *L3 = createNode(5, 6, 3); + for (auto I = 0; I < 6; ++I) + L3->counters()[I] = 16 + I; + L1->subContexts()[0] = L3; + L3->subContexts()[2] = createNode(2, 1, 1); + L3->subContexts()[2]->counters()[0] = 30; + auto *Root2 = createNode(3, 1, 0); + Root2->counters()[0] = 40; + Roots.insert({3, Root2}); + } + + const std::map &roots() const { return Roots; } +}; + +void checkSame(const ContextNode &Raw, const PGOContextualProfile &Profile) { + EXPECT_EQ(Raw.guid(), Profile.guid()); + ASSERT_EQ(Raw.counters_size(), Profile.counters().size()); + for (auto I = 0U; I < Raw.counters_size(); ++I) + EXPECT_EQ(Raw.counters()[I], Profile.counters()[I]); + + for (auto I = 0U; I < Raw.callsites_size(); ++I) { + if (Raw.subContexts()[I] == nullptr) + continue; + EXPECT_TRUE(Profile.hasCallsite(I)); + const auto &ProfileTargets = Profile.callsite(I); + + std::map Targets; + for (const auto *N = Raw.subContexts()[I]; N; N = N->next()) + EXPECT_TRUE(Targets.insert({N->guid(), N}).second); + + EXPECT_EQ(Targets.size(), ProfileTargets.size()); + for (auto It : Targets) { + auto PIt = ProfileTargets.find(It.second->guid()); + EXPECT_NE(PIt, ProfileTargets.end()); + checkSame(*It.second, PIt->second); + } + } +} + +TEST_F(PGOCtxProfRWTest, RoundTrip) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + for (auto &[_, R] : roots()) + Writer.write(*R); + } + } + { + ErrorOr> MB = + MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + ASSERT_TRUE(!!Expected); + auto &Ctxes = *Expected; + EXPECT_EQ(Ctxes.size(), roots().size()); + EXPECT_EQ(Ctxes.size(), 2U); + for (auto &[G, R] : roots()) + checkSame(*R, Ctxes.find(G)->second); + } +} + +TEST_F(PGOCtxProfRWTest, InvalidCounters) { + auto *R = createNode(1, 0, 1); + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + Writer.write(*R); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} + +TEST_F(PGOCtxProfRWTest, Empty) { + BitstreamCursor Cursor(""); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); +} + +TEST_F(PGOCtxProfRWTest, Invalid) { + BitstreamCursor Cursor("Surely this is not valid"); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); +} + +TEST_F(PGOCtxProfRWTest, ValidButEmpty) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + // don't write anything - this will just produce the metadata subblock. + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_TRUE(!!Expected); + EXPECT_TRUE(Expected->empty()); + } +} + +TEST_F(PGOCtxProfRWTest, WrongVersion) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out, PGOCtxProfileWriter::CurrentVersion + 1); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} + +TEST_F(PGOCtxProfRWTest, DuplicateRoots) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + Writer.write(*createNode(1, 1, 1)); + Writer.write(*createNode(1, 1, 1)); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} + +TEST_F(PGOCtxProfRWTest, DuplicateTargets) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + auto *R = createNode(1, 1, 1); + auto *L1 = createNode(2, 1, 0); + auto *L2 = createNode(2, 1, 0, L1); + R->subContexts()[0] = L2; + PGOCtxProfileWriter Writer(Out); + Writer.write(*R); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} -- GitLab From 03c7458a3603396d2d0e1dee43399d3d1664a264 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Tue, 14 May 2024 18:07:58 -0700 Subject: [PATCH 291/578] Revert "[ctx_profile] Profile reader and writer" (#92199) Reverts llvm/llvm-project#91859 Buildbot failures. --- .../llvm/ProfileData/PGOCtxProfReader.h | 92 ------- .../llvm/ProfileData/PGOCtxProfWriter.h | 91 ------- llvm/lib/ProfileData/CMakeLists.txt | 2 - llvm/lib/ProfileData/PGOCtxProfReader.cpp | 173 ------------ llvm/lib/ProfileData/PGOCtxProfWriter.cpp | 49 ---- llvm/unittests/ProfileData/CMakeLists.txt | 1 - .../PGOCtxProfReaderWriterTest.cpp | 255 ------------------ 7 files changed, 663 deletions(-) delete mode 100644 llvm/include/llvm/ProfileData/PGOCtxProfReader.h delete mode 100644 llvm/include/llvm/ProfileData/PGOCtxProfWriter.h delete mode 100644 llvm/lib/ProfileData/PGOCtxProfReader.cpp delete mode 100644 llvm/lib/ProfileData/PGOCtxProfWriter.cpp delete mode 100644 llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp diff --git a/llvm/include/llvm/ProfileData/PGOCtxProfReader.h b/llvm/include/llvm/ProfileData/PGOCtxProfReader.h deleted file mode 100644 index a19b3f51d642..000000000000 --- a/llvm/include/llvm/ProfileData/PGOCtxProfReader.h +++ /dev/null @@ -1,92 +0,0 @@ -//===--- PGOCtxProfReader.h - Contextual profile reader ---------*- 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 -/// -/// Reader for contextual iFDO profile, which comes in bitstream format. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H -#define LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/Bitstream/BitstreamReader.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/ProfileData/PGOCtxProfWriter.h" -#include "llvm/Support/Error.h" -#include -#include - -namespace llvm { -/// The loaded contextual profile, suitable for mutation during IPO passes. We -/// generally expect a fraction of counters and of callsites to be populated. -/// We continue to model counters as vectors, but callsites are modeled as a map -/// of a map. The expectation is that, typically, there is a small number of -/// indirect targets (usually, 1 for direct calls); but potentially a large -/// number of callsites, and, as inlining progresses, the callsite count of a -/// caller will grow. -class PGOContextualProfile final { -public: - using CallTargetMapTy = std::map; - using CallsiteMapTy = DenseMap; - -private: - friend class PGOCtxProfileReader; - GlobalValue::GUID GUID = 0; - SmallVector Counters; - CallsiteMapTy Callsites; - - PGOContextualProfile(GlobalValue::GUID G, - SmallVectorImpl &&Counters) - : GUID(G), Counters(std::move(Counters)) {} - - Expected - getOrEmplace(uint32_t Index, GlobalValue::GUID G, - SmallVectorImpl &&Counters); - -public: - PGOContextualProfile(const PGOContextualProfile &) = delete; - PGOContextualProfile &operator=(const PGOContextualProfile &) = delete; - PGOContextualProfile(PGOContextualProfile &&) = default; - PGOContextualProfile &operator=(PGOContextualProfile &&) = default; - - GlobalValue::GUID guid() const { return GUID; } - const SmallVectorImpl &counters() const { return Counters; } - const CallsiteMapTy &callsites() const { return Callsites; } - CallsiteMapTy &callsites() { return Callsites; } - - bool hasCallsite(uint32_t I) const { - return Callsites.find(I) != Callsites.end(); - } - - const CallTargetMapTy &callsite(uint32_t I) const { - assert(hasCallsite(I) && "Callsite not found"); - return Callsites.find(I)->second; - } - void getContainedGuids(DenseSet &Guids) const; -}; - -class PGOCtxProfileReader final { - BitstreamCursor &Cursor; - Expected advance(); - Error readMetadata(); - Error wrongValue(const Twine &); - Error unsupported(const Twine &); - - Expected, PGOContextualProfile>> - readContext(bool ExpectIndex); - bool canReadContext(); - -public: - PGOCtxProfileReader(BitstreamCursor &Cursor) : Cursor(Cursor) {} - - Expected> loadContexts(); -}; -} // namespace llvm -#endif diff --git a/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h b/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h deleted file mode 100644 index 15578c51a495..000000000000 --- a/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h +++ /dev/null @@ -1,91 +0,0 @@ -//===- PGOCtxProfWriter.h - Contextual Profile Writer -----------*- 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares a utility for writing a contextual profile to bitstream. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ -#define LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ - -#include "llvm/Bitstream/BitstreamWriter.h" -#include "llvm/ProfileData/CtxInstrContextNode.h" - -namespace llvm { -enum PGOCtxProfileRecords { Invalid = 0, Version, Guid, CalleeIndex, Counters }; - -enum PGOCtxProfileBlockIDs { - ProfileMetadataBlockID = 100, - ContextNodeBlockID = ProfileMetadataBlockID + 1 -}; - -/// Write one or more ContextNodes to the provided raw_fd_stream. -/// The caller must destroy the PGOCtxProfileWriter object before closing the -/// stream. -/// The design allows serializing a bunch of contexts embedded in some other -/// file. The overall format is: -/// -/// [... other data written to the stream...] -/// SubBlock(ProfileMetadataBlockID) -/// Version -/// SubBlock(ContextNodeBlockID) -/// [RECORDS] -/// SubBlock(ContextNodeBlockID) -/// [RECORDS] -/// [... more SubBlocks] -/// EndBlock -/// EndBlock -/// -/// The "RECORDS" are bitsream records. The IDs are in CtxProfileCodes (except) -/// for Version, which is just for metadata). All contexts will have Guid and -/// Counters, and all but the roots have CalleeIndex. The order in which the -/// records appear does not matter, but they must precede any subcontexts, -/// because that helps keep the reader code simpler. -/// -/// Subblock containment captures the context->subcontext relationship. The -/// "next()" relationship in the raw profile, between call targets of indirect -/// calls, are just modeled as peer subblocks where the callee index is the -/// same. -/// -/// Versioning: the writer may produce additional records not known by the -/// reader. The version number indicates a more structural change. -/// The current version, in particular, is set up to expect optional extensions -/// like value profiling - which would appear as additional records. For -/// example, value profiling would produce a new record with a new record ID, -/// containing the profiled values (much like the counters) -class PGOCtxProfileWriter final { - SmallVector Buff; - BitstreamWriter Writer; - - void writeCounters(const ctx_profile::ContextNode &Node); - void writeImpl(std::optional CallerIndex, - const ctx_profile::ContextNode &Node); - -public: - PGOCtxProfileWriter(raw_fd_stream &Out, - std::optional VersionOverride = std::nullopt) - : Writer(Buff, &Out, 0) { - Writer.EnterSubblock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID, - CodeLen); - const auto Version = VersionOverride ? *VersionOverride : CurrentVersion; - Writer.EmitRecord(PGOCtxProfileRecords::Version, - SmallVector({Version})); - } - - ~PGOCtxProfileWriter() { Writer.ExitBlock(); } - - void write(const ctx_profile::ContextNode &); - - // constants used in writing which a reader may find useful. - static constexpr unsigned CodeLen = 2; - static constexpr uint32_t CurrentVersion = 1; - static constexpr unsigned VBREncodingBits = 6; -}; - -} // namespace llvm -#endif diff --git a/llvm/lib/ProfileData/CMakeLists.txt b/llvm/lib/ProfileData/CMakeLists.txt index 2397eebaf7b1..408f9ff01ec8 100644 --- a/llvm/lib/ProfileData/CMakeLists.txt +++ b/llvm/lib/ProfileData/CMakeLists.txt @@ -7,8 +7,6 @@ add_llvm_component_library(LLVMProfileData ItaniumManglingCanonicalizer.cpp MemProf.cpp MemProfReader.cpp - PGOCtxProfReader.cpp - PGOCtxProfWriter.cpp ProfileSummaryBuilder.cpp SampleProf.cpp SampleProfReader.cpp diff --git a/llvm/lib/ProfileData/PGOCtxProfReader.cpp b/llvm/lib/ProfileData/PGOCtxProfReader.cpp deleted file mode 100644 index 3710f2e4b818..000000000000 --- a/llvm/lib/ProfileData/PGOCtxProfReader.cpp +++ /dev/null @@ -1,173 +0,0 @@ -//===- PGOCtxProfReader.cpp - Contextual Instrumentation profile reader ---===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Read a contextual profile into a datastructure suitable for maintenance -// throughout IPO -// -//===----------------------------------------------------------------------===// - -#include "llvm/ProfileData/PGOCtxProfReader.h" -#include "llvm/Bitstream/BitCodeEnums.h" -#include "llvm/Bitstream/BitstreamReader.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/ProfileData/PGOCtxProfWriter.h" -#include "llvm/Support/Errc.h" -#include "llvm/Support/Error.h" - -using namespace llvm; - -// FIXME(#92054) - these Error handling macros are (re-)invented in a few -// places. -#define EXPECT_OR_RET(LHS, RHS) \ - auto LHS = RHS; \ - if (!LHS) \ - return LHS.takeError(); - -#define RET_ON_ERR(EXPR) \ - if (auto Err = (EXPR)) \ - return Err; - -Expected -PGOContextualProfile::getOrEmplace(uint32_t Index, GlobalValue::GUID G, - SmallVectorImpl &&Counters) { - auto [Iter, Inserted] = Callsites[Index].insert( - {G, PGOContextualProfile(G, std::move(Counters))}); - if (!Inserted) - return make_error(instrprof_error::invalid_prof, - "Duplicate GUID for same callsite."); - return Iter->second; -} - -void PGOContextualProfile::getContainedGuids( - DenseSet &Guids) const { - Guids.insert(GUID); - for (const auto &[_, Callsite] : Callsites) - for (const auto &[_, Callee] : Callsite) - Callee.getContainedGuids(Guids); -} - -Expected PGOCtxProfileReader::advance() { - return Cursor.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); -} - -Error PGOCtxProfileReader::wrongValue(const Twine &Msg) { - return make_error(instrprof_error::invalid_prof, Msg); -} - -Error PGOCtxProfileReader::unsupported(const Twine &Msg) { - return make_error(instrprof_error::unsupported_version, Msg); -} - -bool PGOCtxProfileReader::canReadContext() { - auto Blk = advance(); - if (!Blk) { - consumeError(Blk.takeError()); - return false; - } - return Blk->Kind == BitstreamEntry::SubBlock && - Blk->ID == PGOCtxProfileBlockIDs::ContextNodeBlockID; -} - -Expected, PGOContextualProfile>> -PGOCtxProfileReader::readContext(bool ExpectIndex) { - RET_ON_ERR(Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ContextNodeBlockID)); - - std::optional Guid; - std::optional> Counters; - std::optional CallsiteIndex; - - SmallVector RecordValues; - - // We don't prescribe the order in which the records come in, and we are ok - // if other unsupported records appear. We seek in the current subblock until - // we get all we know. - auto GotAllWeNeed = [&]() { - return Guid.has_value() && Counters.has_value() && - (!ExpectIndex || CallsiteIndex.has_value()); - }; - while (!GotAllWeNeed()) { - RecordValues.clear(); - EXPECT_OR_RET(Entry, advance()); - if (Entry->Kind != BitstreamEntry::Record) - return wrongValue( - "Expected records before encountering more subcontexts"); - EXPECT_OR_RET(ReadRecord, - Cursor.readRecord(bitc::UNABBREV_RECORD, RecordValues)); - switch (*ReadRecord) { - case PGOCtxProfileRecords::Guid: - if (RecordValues.size() != 1) - return wrongValue("The GUID record should have exactly one value"); - Guid = RecordValues[0]; - break; - case PGOCtxProfileRecords::Counters: - Counters = std::move(RecordValues); - if (Counters->empty()) - return wrongValue("Empty counters. At least the entry counter (one " - "value) was expected"); - break; - case PGOCtxProfileRecords::CalleeIndex: - if (!ExpectIndex) - return wrongValue("The root context should not have a callee index"); - if (RecordValues.size() != 1) - return wrongValue("The callee index should have exactly one value"); - CallsiteIndex = RecordValues[0]; - break; - default: - // OK if we see records we do not understand, like records (profile - // components) introduced later. - break; - } - } - - PGOContextualProfile Ret(*Guid, std::move(*Counters)); - - while (canReadContext()) { - EXPECT_OR_RET(SC, readContext(true)); - auto &Targets = Ret.callsites()[*SC->first]; - auto [_, Inserted] = - Targets.insert({SC->second.guid(), std::move(SC->second)}); - if (!Inserted) - return wrongValue( - "Unexpected duplicate target (callee) at the same callsite."); - } - return std::make_pair(CallsiteIndex, std::move(Ret)); -} - -Error PGOCtxProfileReader::readMetadata() { - EXPECT_OR_RET(Blk, advance()); - if (Blk->Kind != BitstreamEntry::SubBlock) - return unsupported("Expected Version record"); - RET_ON_ERR( - Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID)); - EXPECT_OR_RET(MData, advance()); - if (MData->Kind != BitstreamEntry::Record) - return unsupported("Expected Version record"); - - SmallVector Ver; - EXPECT_OR_RET(Code, Cursor.readRecord(bitc::UNABBREV_RECORD, Ver)); - if (*Code != PGOCtxProfileRecords::Version) - return unsupported("Expected Version record"); - if (Ver.size() != 1 || Ver[0] > PGOCtxProfileWriter::CurrentVersion) - return unsupported("Version " + Twine(*Code) + - " is higher than supported version " + - Twine(PGOCtxProfileWriter::CurrentVersion)); - return Error::success(); -} - -Expected> -PGOCtxProfileReader::loadContexts() { - std::map Ret; - RET_ON_ERR(readMetadata()); - while (canReadContext()) { - EXPECT_OR_RET(E, readContext(false)); - auto Key = E->second.guid(); - if (!Ret.insert({Key, std::move(E->second)}).second) - return wrongValue("Duplicate roots"); - } - return Ret; -} diff --git a/llvm/lib/ProfileData/PGOCtxProfWriter.cpp b/llvm/lib/ProfileData/PGOCtxProfWriter.cpp deleted file mode 100644 index 508179756446..000000000000 --- a/llvm/lib/ProfileData/PGOCtxProfWriter.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===- PGOCtxProfWriter.cpp - Contextual Instrumentation profile writer ---===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Write a contextual profile to bitstream. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ProfileData/PGOCtxProfWriter.h" -#include "llvm/Bitstream/BitCodeEnums.h" - -using namespace llvm; -using namespace llvm::ctx_profile; - -void PGOCtxProfileWriter::writeCounters(const ContextNode &Node) { - Writer.EmitCode(bitc::UNABBREV_RECORD); - Writer.EmitVBR(PGOCtxProfileRecords::Counters, VBREncodingBits); - Writer.EmitVBR(Node.counters_size(), VBREncodingBits); - for (uint32_t I = 0U; I < Node.counters_size(); ++I) - Writer.EmitVBR64(Node.counters()[I], VBREncodingBits); -} - -// recursively write all the subcontexts. We do need to traverse depth first to -// model the context->subcontext implicitly, and since this captures call -// stacks, we don't really need to be worried about stack overflow and we can -// keep the implementation simple. -void PGOCtxProfileWriter::writeImpl(std::optional CallerIndex, - const ContextNode &Node) { - Writer.EnterSubblock(PGOCtxProfileBlockIDs::ContextNodeBlockID, CodeLen); - Writer.EmitRecord(PGOCtxProfileRecords::Guid, - SmallVector{Node.guid()}); - if (CallerIndex) - Writer.EmitRecord(PGOCtxProfileRecords::CalleeIndex, - SmallVector{*CallerIndex}); - writeCounters(Node); - for (uint32_t I = 0U; I < Node.callsites_size(); ++I) - for (const auto *Subcontext = Node.subContexts()[I]; Subcontext; - Subcontext = Subcontext->next()) - writeImpl(I, *Subcontext); - Writer.ExitBlock(); -} - -void PGOCtxProfileWriter::write(const ContextNode &RootNode) { - writeImpl(std::nullopt, RootNode); -} diff --git a/llvm/unittests/ProfileData/CMakeLists.txt b/llvm/unittests/ProfileData/CMakeLists.txt index c92642ded828..ce3a0a45ccf1 100644 --- a/llvm/unittests/ProfileData/CMakeLists.txt +++ b/llvm/unittests/ProfileData/CMakeLists.txt @@ -13,7 +13,6 @@ add_llvm_unittest(ProfileDataTests InstrProfTest.cpp ItaniumManglingCanonicalizerTest.cpp MemProfTest.cpp - PGOCtxProfReaderWriterTest.cpp SampleProfTest.cpp SymbolRemappingReaderTest.cpp ) diff --git a/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp b/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp deleted file mode 100644 index d2cdbb28e2fc..000000000000 --- a/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp +++ /dev/null @@ -1,255 +0,0 @@ -//===-------------- PGOCtxProfReadWriteTest.cpp ---------------------------===// -// -// 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 "llvm/Bitstream/BitstreamReader.h" -#include "llvm/ProfileData/CtxInstrContextNode.h" -#include "llvm/ProfileData/PGOCtxProfReader.h" -#include "llvm/ProfileData/PGOCtxProfWriter.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Testing/Support/SupportHelpers.h" -#include "gtest/gtest.h" - -using namespace llvm; -using namespace llvm::ctx_profile; - -class PGOCtxProfRWTest : public ::testing::Test { - std::vector> Nodes; - std::map Roots; - -public: - ContextNode *createNode(GUID Guid, uint32_t NrCounters, uint32_t NrCallsites, - ContextNode *Next = nullptr) { - auto AllocSize = ContextNode::getAllocSize(NrCounters, NrCallsites); - auto *Mem = Nodes.emplace_back(std::make_unique(AllocSize)).get(); - std::memset(Mem, 0, AllocSize); - auto *Ret = new (Mem) ContextNode(Guid, NrCounters, NrCallsites, Next); - return Ret; - } - - void SetUp() override { - // Root (guid 1) has 2 callsites, one used for an indirect call to either - // guid 2 or 4. - // guid 2 calls guid 5 - // guid 5 calls guid 2 - // there's also a second root, guid3. - auto *Root1 = createNode(1, 2, 2); - Root1->counters()[0] = 10; - Root1->counters()[1] = 11; - Roots.insert({1, Root1}); - auto *L1 = createNode(2, 1, 1); - L1->counters()[0] = 12; - Root1->subContexts()[1] = createNode(4, 3, 1, L1); - Root1->subContexts()[1]->counters()[0] = 13; - Root1->subContexts()[1]->counters()[1] = 14; - Root1->subContexts()[1]->counters()[2] = 15; - - auto *L3 = createNode(5, 6, 3); - for (auto I = 0; I < 6; ++I) - L3->counters()[I] = 16 + I; - L1->subContexts()[0] = L3; - L3->subContexts()[2] = createNode(2, 1, 1); - L3->subContexts()[2]->counters()[0] = 30; - auto *Root2 = createNode(3, 1, 0); - Root2->counters()[0] = 40; - Roots.insert({3, Root2}); - } - - const std::map &roots() const { return Roots; } -}; - -void checkSame(const ContextNode &Raw, const PGOContextualProfile &Profile) { - EXPECT_EQ(Raw.guid(), Profile.guid()); - ASSERT_EQ(Raw.counters_size(), Profile.counters().size()); - for (auto I = 0U; I < Raw.counters_size(); ++I) - EXPECT_EQ(Raw.counters()[I], Profile.counters()[I]); - - for (auto I = 0U; I < Raw.callsites_size(); ++I) { - if (Raw.subContexts()[I] == nullptr) - continue; - EXPECT_TRUE(Profile.hasCallsite(I)); - const auto &ProfileTargets = Profile.callsite(I); - - std::map Targets; - for (const auto *N = Raw.subContexts()[I]; N; N = N->next()) - EXPECT_TRUE(Targets.insert({N->guid(), N}).second); - - EXPECT_EQ(Targets.size(), ProfileTargets.size()); - for (auto It : Targets) { - auto PIt = ProfileTargets.find(It.second->guid()); - EXPECT_NE(PIt, ProfileTargets.end()); - checkSame(*It.second, PIt->second); - } - } -} - -TEST_F(PGOCtxProfRWTest, RoundTrip) { - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - PGOCtxProfileWriter Writer(Out); - for (auto &[_, R] : roots()) - Writer.write(*R); - } - } - { - ErrorOr> MB = - MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - ASSERT_TRUE(!!Expected); - auto &Ctxes = *Expected; - EXPECT_EQ(Ctxes.size(), roots().size()); - EXPECT_EQ(Ctxes.size(), 2U); - for (auto &[G, R] : roots()) - checkSame(*R, Ctxes.find(G)->second); - } -} - -TEST_F(PGOCtxProfRWTest, InvalidCounters) { - auto *R = createNode(1, 0, 1); - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - PGOCtxProfileWriter Writer(Out); - Writer.write(*R); - } - } - { - auto MB = MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); - } -} - -TEST_F(PGOCtxProfRWTest, Empty) { - BitstreamCursor Cursor(""); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); -} - -TEST_F(PGOCtxProfRWTest, Invalid) { - BitstreamCursor Cursor("Surely this is not valid"); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); -} - -TEST_F(PGOCtxProfRWTest, ValidButEmpty) { - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - PGOCtxProfileWriter Writer(Out); - // don't write anything - this will just produce the metadata subblock. - } - } - { - auto MB = MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_TRUE(!!Expected); - EXPECT_TRUE(Expected->empty()); - } -} - -TEST_F(PGOCtxProfRWTest, WrongVersion) { - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - PGOCtxProfileWriter Writer(Out, PGOCtxProfileWriter::CurrentVersion + 1); - } - } - { - auto MB = MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); - } -} - -TEST_F(PGOCtxProfRWTest, DuplicateRoots) { - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - PGOCtxProfileWriter Writer(Out); - Writer.write(*createNode(1, 1, 1)); - Writer.write(*createNode(1, 1, 1)); - } - } - { - auto MB = MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); - } -} - -TEST_F(PGOCtxProfRWTest, DuplicateTargets) { - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - auto *R = createNode(1, 1, 1); - auto *L1 = createNode(2, 1, 0); - auto *L2 = createNode(2, 1, 0, L1); - R->subContexts()[0] = L2; - PGOCtxProfileWriter Writer(Out); - Writer.write(*R); - } - } - { - auto MB = MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); - } -} -- GitLab From 4d1ecf192313b612090d60181937eff03c1a966b Mon Sep 17 00:00:00 2001 From: AtariDreams Date: Tue, 14 May 2024 21:26:23 -0400 Subject: [PATCH 292/578] [Transforms] Preserve inbounds attribute of transformed GEPs when flattening loops (#86961) When flattening the loop, if the GEP was inbound, it should stay inbound, because the only thing that changed is how the pointers are calculated, not the elements being accessed. Proof: https://alive2.llvm.org/ce/z/dApMpQ --- llvm/lib/Transforms/Scalar/LoopFlatten.cpp | 6 ++++-- llvm/test/Transforms/LoopFlatten/loop-flatten-gep.ll | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LoopFlatten.cpp b/llvm/lib/Transforms/Scalar/LoopFlatten.cpp index a7f8a22ece27..bb9632ff73a4 100644 --- a/llvm/lib/Transforms/Scalar/LoopFlatten.cpp +++ b/llvm/lib/Transforms/Scalar/LoopFlatten.cpp @@ -808,8 +808,10 @@ static bool DoFlattenLoopPair(FlattenInfo &FI, DominatorTree *DT, LoopInfo *LI, // we need to insert the new GEP where the old GEP was. if (!DT->dominates(Base, &*Builder.GetInsertPoint())) Builder.SetInsertPoint(cast(V)); - OuterValue = Builder.CreateGEP(GEP->getSourceElementType(), Base, - OuterValue, "flatten." + V->getName()); + OuterValue = + Builder.CreateGEP(GEP->getSourceElementType(), Base, OuterValue, + "flatten." + V->getName(), + GEP->isInBounds() && InnerGEP->isInBounds()); } LLVM_DEBUG(dbgs() << "Replacing: "; V->dump(); dbgs() << "with: "; diff --git a/llvm/test/Transforms/LoopFlatten/loop-flatten-gep.ll b/llvm/test/Transforms/LoopFlatten/loop-flatten-gep.ll index f4b8ea97237f..e30001670b1e 100644 --- a/llvm/test/Transforms/LoopFlatten/loop-flatten-gep.ll +++ b/llvm/test/Transforms/LoopFlatten/loop-flatten-gep.ll @@ -15,7 +15,7 @@ for.outer.preheader: br label %for.inner.preheader ; CHECK-LABEL: for.inner.preheader: -; CHECK: %flatten.arrayidx = getelementptr i32, ptr %A, i32 %i +; CHECK: %flatten.arrayidx = getelementptr inbounds i32, ptr %A, i32 %i for.inner.preheader: %i = phi i32 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ] br label %for.inner @@ -61,13 +61,13 @@ for.outer.preheader: br label %for.inner.preheader ; CHECK-LABEL: for.inner.preheader: -; CHECK-NOT: getelementptr i32, ptr %ptr, i32 %i +; CHECK-NOT: getelementptr inbounds i32, ptr %ptr, i32 %i for.inner.preheader: %i = phi i32 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ] br label %for.inner ; CHECK-LABEL: for.inner: -; CHECK: %flatten.arrayidx = getelementptr i32, ptr %ptr, i32 %i +; CHECK: %flatten.arrayidx = getelementptr inbounds i32, ptr %ptr, i32 %i ; CHECK: store i32 0, ptr %flatten.arrayidx, align 4 ; CHECK: br label %for.outer for.inner: -- GitLab From 71fbbb69d63c461f391cbabf1e32cd9977c4ce68 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 15 May 2024 10:13:42 +0900 Subject: [PATCH 293/578] [IR] Move GlobalValue::getGUID() out of line (NFC) Avoid including MD5.h in a core IR header. --- llvm/include/llvm/IR/GlobalValue.h | 3 +-- llvm/lib/IR/Globals.cpp | 5 +++++ llvm/lib/Target/NVPTX/NVPTXCtorDtorLowering.cpp | 1 + llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp | 1 + llvm/lib/Transforms/Utils/ModuleUtils.cpp | 1 + 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h index c61d502aa332..b1262b27f022 100644 --- a/llvm/include/llvm/IR/GlobalValue.h +++ b/llvm/include/llvm/IR/GlobalValue.h @@ -24,7 +24,6 @@ #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MD5.h" #include #include #include @@ -588,7 +587,7 @@ public: /// Return a 64-bit global unique ID constructed from global value name /// (i.e. returned by getGlobalIdentifier()). - static GUID getGUID(StringRef GlobalName) { return MD5Hash(GlobalName); } + static GUID getGUID(StringRef GlobalName); /// Return a 64-bit global unique ID constructed from global value name /// (i.e. returned by getGlobalIdentifier()). diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index 40f854a2c906..6f071847bb58 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -21,6 +21,7 @@ #include "llvm/IR/Module.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MD5.h" #include "llvm/TargetParser/Triple.h" using namespace llvm; @@ -71,6 +72,10 @@ void GlobalValue::copyAttributesFrom(const GlobalValue *Src) { removeSanitizerMetadata(); } +GlobalValue::GUID GlobalValue::getGUID(StringRef GlobalName) { + return MD5Hash(GlobalName); +} + void GlobalValue::removeFromParent() { switch (getValueID()) { #define HANDLE_GLOBAL_VALUE(NAME) \ diff --git a/llvm/lib/Target/NVPTX/NVPTXCtorDtorLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXCtorDtorLowering.cpp index f77a1f0272c8..f940dc05948b 100644 --- a/llvm/lib/Target/NVPTX/NVPTXCtorDtorLowering.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXCtorDtorLowering.cpp @@ -22,6 +22,7 @@ #include "llvm/IR/Value.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/MD5.h" #include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index fca1824165e7..8d39217992c7 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -53,6 +53,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/MD5.h" #include "llvm/Support/RandomNumberGenerator.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp index 209a6a34a3c9..122279160cc7 100644 --- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/Support/MD5.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/xxhash.h" -- GitLab From 6642cc60a21f857bddde8ec2c81008a83a54b4d3 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 15 May 2024 11:07:40 +0900 Subject: [PATCH 294/578] [SCEV] Add tests for ule/sle exit counts (NFC) --- .../ScalarEvolution/exit-count-non-strict.ll | 228 ++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 llvm/test/Analysis/ScalarEvolution/exit-count-non-strict.ll diff --git a/llvm/test/Analysis/ScalarEvolution/exit-count-non-strict.ll b/llvm/test/Analysis/ScalarEvolution/exit-count-non-strict.ll new file mode 100644 index 000000000000..2117c779f4b3 --- /dev/null +++ b/llvm/test/Analysis/ScalarEvolution/exit-count-non-strict.ll @@ -0,0 +1,228 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -disable-output "-passes=print" -scalar-evolution-classify-expressions=0 < %s 2>&1 | FileCheck %s + +define void @ule_from_zero(i32 %M, i32 %N) { +; CHECK-LABEL: 'ule_from_zero' +; CHECK-NEXT: Determining loop execution counts for: @ule_from_zero +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: exit count for latch: %N +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i32 -1 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is %N +; CHECK-NEXT: symbolic max exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: symbolic max exit count for latch: %N +; +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %latch ] + %cmp1 = icmp ule i32 %iv, %M + br i1 %cmp1, label %latch, label %exit + +latch: + %iv.next = add nuw i32 %iv, 1 + %exitcond.not = icmp eq i32 %iv, %N + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @ule_from_one(i32 %M, i32 %N) { +; CHECK-LABEL: 'ule_from_one' +; CHECK-NEXT: Determining loop execution counts for: @ule_from_one +; CHECK-NEXT: Loop %loop: backedge-taken count is (%M umin_seq (-1 + %N)) +; CHECK-NEXT: exit count for loop: %M +; CHECK-NEXT: exit count for latch: (-1 + %N) +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i32 -1 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is (%M umin_seq (-1 + %N)) +; CHECK-NEXT: symbolic max exit count for loop: %M +; CHECK-NEXT: symbolic max exit count for latch: (-1 + %N) +; CHECK-NEXT: Loop %loop: Trip multiple is 1 +; +entry: + br label %loop + +loop: + %iv = phi i32 [ 1, %entry ], [ %iv.next, %latch ] + %cmp1 = icmp ule i32 %iv, %M + br i1 %cmp1, label %latch, label %exit + +latch: + %iv.next = add nuw i32 %iv, 1 + %exitcond.not = icmp eq i32 %iv, %N + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @ule_from_unknown(i32 %M, i32 %N, i32 %S) { +; CHECK-LABEL: 'ule_from_unknown' +; CHECK-NEXT: Determining loop execution counts for: @ule_from_unknown +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: exit count for latch: ((-1 * %S) + %N) +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i32 -1 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is ((-1 * %S) + %N) +; CHECK-NEXT: symbolic max exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: symbolic max exit count for latch: ((-1 * %S) + %N) +; +entry: + br label %loop + +loop: + %iv = phi i32 [ %S, %entry ], [ %iv.next, %latch ] + %cmp1 = icmp ule i32 %iv, %M + br i1 %cmp1, label %latch, label %exit + +latch: + %iv.next = add nuw i32 %iv, 1 + %exitcond.not = icmp eq i32 %iv, %N + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @ule_from_zero_no_nuw(i32 %M, i32 %N) { +; CHECK-LABEL: 'ule_from_zero_no_nuw' +; CHECK-NEXT: Determining loop execution counts for: @ule_from_zero_no_nuw +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: exit count for latch: %N +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i32 -1 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is %N +; CHECK-NEXT: symbolic max exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: symbolic max exit count for latch: %N +; +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %latch ] + %cmp1 = icmp ule i32 %iv, %M + br i1 %cmp1, label %latch, label %exit + +latch: + %iv.next = add i32 %iv, 1 + %exitcond.not = icmp eq i32 %iv, %N + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @sle_from_int_min(i32 %M, i32 %N) { +; CHECK-LABEL: 'sle_from_int_min' +; CHECK-NEXT: Determining loop execution counts for: @sle_from_int_min +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: exit count for latch: (-2147483648 + %N) +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i32 -1 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is (-2147483648 + %N) +; CHECK-NEXT: symbolic max exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: symbolic max exit count for latch: (-2147483648 + %N) +; +entry: + br label %loop + +loop: + %iv = phi i32 [ u0x80000000, %entry ], [ %iv.next, %latch ] + %cmp1 = icmp sle i32 %iv, %M + br i1 %cmp1, label %latch, label %exit + +latch: + %iv.next = add nsw i32 %iv, 1 + %exitcond.not = icmp eq i32 %iv, %N + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @sle_from_int_min_plus_one(i32 %M, i32 %N) { +; CHECK-LABEL: 'sle_from_int_min_plus_one' +; CHECK-NEXT: Determining loop execution counts for: @sle_from_int_min_plus_one +; CHECK-NEXT: Loop %loop: backedge-taken count is ((-2147483648 + %M) umin_seq (2147483647 + %N)) +; CHECK-NEXT: exit count for loop: (-2147483648 + %M) +; CHECK-NEXT: exit count for latch: (2147483647 + %N) +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i32 -1 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is ((-2147483648 + %M) umin_seq (2147483647 + %N)) +; CHECK-NEXT: symbolic max exit count for loop: (-2147483648 + %M) +; CHECK-NEXT: symbolic max exit count for latch: (2147483647 + %N) +; CHECK-NEXT: Loop %loop: Trip multiple is 1 +; +entry: + br label %loop + +loop: + %iv = phi i32 [ u0x80000001, %entry ], [ %iv.next, %latch ] + %cmp1 = icmp sle i32 %iv, %M + br i1 %cmp1, label %latch, label %exit + +latch: + %iv.next = add nsw i32 %iv, 1 + %exitcond.not = icmp eq i32 %iv, %N + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @sle_from_unknown(i32 %M, i32 %N, i32 %S) { +; CHECK-LABEL: 'sle_from_unknown' +; CHECK-NEXT: Determining loop execution counts for: @sle_from_unknown +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: exit count for latch: ((-1 * %S) + %N) +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i32 -1 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is ((-1 * %S) + %N) +; CHECK-NEXT: symbolic max exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: symbolic max exit count for latch: ((-1 * %S) + %N) +; +entry: + br label %loop + +loop: + %iv = phi i32 [ %S, %entry ], [ %iv.next, %latch ] + %cmp1 = icmp sle i32 %iv, %M + br i1 %cmp1, label %latch, label %exit + +latch: + %iv.next = add nsw i32 %iv, 1 + %exitcond.not = icmp eq i32 %iv, %N + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @sle_from_int_min_no_nsw(i32 %M, i32 %N) { +; CHECK-LABEL: 'sle_from_int_min_no_nsw' +; CHECK-NEXT: Determining loop execution counts for: @sle_from_int_min_no_nsw +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: exit count for latch: (-2147483648 + %N) +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i32 -1 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is (-2147483648 + %N) +; CHECK-NEXT: symbolic max exit count for loop: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: symbolic max exit count for latch: (-2147483648 + %N) +; +entry: + br label %loop + +loop: + %iv = phi i32 [ u0x80000000, %entry ], [ %iv.next, %latch ] + %cmp1 = icmp sle i32 %iv, %M + br i1 %cmp1, label %latch, label %exit + +latch: + %iv.next = add i32 %iv, 1 + %exitcond.not = icmp eq i32 %iv, %N + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} -- GitLab From 11b059145d177ee287c7ada9864addf8d083c160 Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Tue, 14 May 2024 17:53:17 +0800 Subject: [PATCH 295/578] [Serialization] Read the initializer for interesting static variables before consuming it Close https://github.com/llvm/llvm-project/issues/91418 Since we load the variable's initializers lazily, it'd be problematic if the initializers dependent on each other. So here we try to load the initializers of static variables to make sure they are passed to code generator by order. If we read any thing interesting, we would consume that before emitting the current declaration. --- clang/lib/Serialization/ASTReaderDecl.cpp | 29 +++++++++- clang/test/Modules/pr91418.cppm | 67 +++++++++++++++++++++++ 2 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 clang/test/Modules/pr91418.cppm diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 0c647086e304..a6254b70560c 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -4186,12 +4186,35 @@ void ASTReader::PassInterestingDeclsToConsumer() { GetDecl(ID); EagerlyDeserializedDecls.clear(); - while (!PotentiallyInterestingDecls.empty()) { - Decl *D = PotentiallyInterestingDecls.front(); - PotentiallyInterestingDecls.pop_front(); + auto ConsumingPotentialInterestingDecls = [this]() { + while (!PotentiallyInterestingDecls.empty()) { + Decl *D = PotentiallyInterestingDecls.front(); + PotentiallyInterestingDecls.pop_front(); + if (isConsumerInterestedIn(D)) + PassInterestingDeclToConsumer(D); + } + }; + std::deque MaybeInterestingDecls = + std::move(PotentiallyInterestingDecls); + assert(PotentiallyInterestingDecls.empty()); + while (!MaybeInterestingDecls.empty()) { + Decl *D = MaybeInterestingDecls.front(); + MaybeInterestingDecls.pop_front(); + // Since we load the variable's initializers lazily, it'd be problematic + // if the initializers dependent on each other. So here we try to load the + // initializers of static variables to make sure they are passed to code + // generator by order. If we read anything interesting, we would consume + // that before emitting the current declaration. + if (auto *VD = dyn_cast(D); + VD && VD->isFileVarDecl() && !VD->isExternallyVisible()) + VD->getInit(); + ConsumingPotentialInterestingDecls(); if (isConsumerInterestedIn(D)) PassInterestingDeclToConsumer(D); } + + // If we add any new potential interesting decl in the last call, consume it. + ConsumingPotentialInterestingDecls(); } void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { diff --git a/clang/test/Modules/pr91418.cppm b/clang/test/Modules/pr91418.cppm new file mode 100644 index 000000000000..33fec992439d --- /dev/null +++ b/clang/test/Modules/pr91418.cppm @@ -0,0 +1,67 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -x c++-header %t/foo.h \ +// RUN: -emit-pch -o %t/foo.pch +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/use.cpp -include-pch \ +// RUN: %t/foo.pch -emit-llvm -o - | FileCheck %t/use.cpp + +//--- foo.h +#ifndef FOO_H +#define FOO_H +typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16))); + +static __inline__ __m128 __attribute__((__always_inline__, __min_vector_width__(128))) +_mm_setr_ps(float __z, float __y, float __x, float __w) +{ + return __extension__ (__m128){ __z, __y, __x, __w }; +} + +typedef __m128 VR; + +inline VR MakeVR( float X, float Y, float Z, float W ) +{ + return _mm_setr_ps( X, Y, Z, W ); +} + +extern "C" float sqrtf(float); + +namespace VectorSinConstantsSSE +{ + float a = (16 * sqrtf(0.225f)); + VR A = MakeVR(a, a, a, a); + static const float b = (16 * sqrtf(0.225f)); + static const VR B = MakeVR(b, b, b, b); +} + +#endif // FOO_H + +//--- use.cpp +#include "foo.h" +float use() { + return VectorSinConstantsSSE::A[0] + VectorSinConstantsSSE::A[1] + + VectorSinConstantsSSE::A[2] + VectorSinConstantsSSE::A[3] + + VectorSinConstantsSSE::B[0] + VectorSinConstantsSSE::B[1] + + VectorSinConstantsSSE::B[2] + VectorSinConstantsSSE::B[3]; +} + +// CHECK: define{{.*}}@__cxx_global_var_init( +// CHECK: store{{.*}}[[a_RESULT:%[a-zA-Z0-9]+]], ptr @_ZN21VectorSinConstantsSSE1aE + +// CHECK: define{{.*}}@__cxx_global_var_init.1( +// CHECK: [[A_CALL:%[a-zA-Z0-9]+]] = call{{.*}}@_Z6MakeVRffff( +// CHECK: store{{.*}}[[A_CALL]], ptr @_ZN21VectorSinConstantsSSE1AE + +// CHECK: define{{.*}}@__cxx_global_var_init.2( +// CHECK: [[B_CALL:%[a-zA-Z0-9]+]] = call{{.*}}@_Z6MakeVRffff( +// CHECK: store{{.*}}[[B_CALL]], ptr @_ZN21VectorSinConstantsSSEL1BE + +// CHECK: define{{.*}}@__cxx_global_var_init.3( +// CHECK: store{{.*}}[[b_RESULT:%[a-zA-Z0-9]+]], ptr @_ZN21VectorSinConstantsSSEL1bE + +// CHECK: @_GLOBAL__sub_I_use.cpp +// CHECK: call{{.*}}@__cxx_global_var_init( +// CHECK: call{{.*}}@__cxx_global_var_init.1( +// CHECK: call{{.*}}@__cxx_global_var_init.3( +// CHECK: call{{.*}}@__cxx_global_var_init.2( -- GitLab From 13b265c7b5c6a989427639e33893c158f737480b Mon Sep 17 00:00:00 2001 From: Freddy Ye Date: Wed, 15 May 2024 10:40:16 +0800 Subject: [PATCH 296/578] [X86][MC] Support Intel FRED and LKGS instructions. (#91909) Spec reference: https://cdrdv2.intel.com/v1/dl/getContent/678938 --- llvm/lib/Target/X86/X86InstrSystem.td | 16 +++++++++++ llvm/test/MC/Disassembler/X86/fred.txt | 8 ++++++ llvm/test/MC/Disassembler/X86/lkgs.txt | 35 ++++++++++++++++++++++++ llvm/test/MC/X86/fred-att.s | 14 ++++++++++ llvm/test/MC/X86/fred-intel.s | 10 +++++++ llvm/test/MC/X86/lkgs-att.s | 38 ++++++++++++++++++++++++++ llvm/test/MC/X86/lkgs-intel.s | 34 +++++++++++++++++++++++ llvm/test/TableGen/x86-fold-tables.inc | 1 + 8 files changed, 156 insertions(+) create mode 100644 llvm/test/MC/Disassembler/X86/fred.txt create mode 100644 llvm/test/MC/Disassembler/X86/lkgs.txt create mode 100644 llvm/test/MC/X86/fred-att.s create mode 100644 llvm/test/MC/X86/fred-intel.s create mode 100644 llvm/test/MC/X86/lkgs-att.s create mode 100644 llvm/test/MC/X86/lkgs-intel.s diff --git a/llvm/lib/Target/X86/X86InstrSystem.td b/llvm/lib/Target/X86/X86InstrSystem.td index 56293e20567e..e1573b37d4dc 100644 --- a/llvm/lib/Target/X86/X86InstrSystem.td +++ b/llvm/lib/Target/X86/X86InstrSystem.td @@ -68,6 +68,14 @@ def SYSENTER : I<0x34, RawFrm, (outs), (ins), "sysenter", []>, TB; def SYSEXIT : I<0x35, RawFrm, (outs), (ins), "sysexit{l}", []>, TB; def SYSEXIT64 :RI<0x35, RawFrm, (outs), (ins), "sysexitq", []>, TB, Requires<[In64BitMode]>; + +// FRED Instructions +let hasSideEffects = 1, Defs = [RSP, EFLAGS] in { + def ERETS: I<0x01, MRM_CA, (outs), (ins), "erets", + []>, TB, XD, Requires<[In64BitMode]>; + def ERETU: I<0x01, MRM_CA, (outs), (ins), "eretu", + []>, TB, XS, Requires<[In64BitMode]>; +} // hasSideEffects = 1, Defs = [RSP, EFLAGS] } // SchedRW def : Pat<(debugtrap), @@ -212,6 +220,14 @@ def MOV16sm : I<0x8E, MRMSrcMem, (outs SEGMENT_REG:$dst), (ins i16mem:$src), let SchedRW = [WriteSystem] in { def SWAPGS : I<0x01, MRM_F8, (outs), (ins), "swapgs", []>, TB; +// LKGS instructions +let hasSideEffects = 1 in { + let mayLoad = 1 in + def LKGS16m : I<0x00, MRM6m, (outs), (ins i16mem:$src), "lkgs\t$src", + []>, TB, XD, Requires<[In64BitMode]>; + def LKGS16r : I<0x00, MRM6r, (outs), (ins GR16:$src), "lkgs\t$src", + []>, TB, XD, Requires<[In64BitMode]>; +} // hasSideEffects let Defs = [EFLAGS] in { let mayLoad = 1 in diff --git a/llvm/test/MC/Disassembler/X86/fred.txt b/llvm/test/MC/Disassembler/X86/fred.txt new file mode 100644 index 000000000000..7a0762e6e4a2 --- /dev/null +++ b/llvm/test/MC/Disassembler/X86/fred.txt @@ -0,0 +1,8 @@ +# RUN: llvm-mc --disassemble %s -triple=x86_64 + +# CHECK: erets +0xf2,0x0f,0x01,0xca + +# CHECK: eretu +0xf3,0x0f,0x01,0xca + diff --git a/llvm/test/MC/Disassembler/X86/lkgs.txt b/llvm/test/MC/Disassembler/X86/lkgs.txt new file mode 100644 index 000000000000..1ad04e5c2ccb --- /dev/null +++ b/llvm/test/MC/Disassembler/X86/lkgs.txt @@ -0,0 +1,35 @@ +# RUN: llvm-mc --disassemble %s -triple=x86_64 | FileCheck %s --check-prefixes=ATT +# RUN: llvm-mc --disassemble %s -triple=x86_64 --output-asm-variant=1 | FileCheck %s --check-prefixes=INTEL + +# ATT: lkgs %ax +# INTEL: lkgs ax +0xf2,0x0f,0x00,0xf0 + +# ATT: lkgs %r12w +# INTEL: lkgs r12w +0xf2,0x41,0x0f,0x00,0xf4 + +# ATT: lkgs 268435456(%rbp,%r14,8) +# INTEL: lkgs word ptr [rbp + 8*r14 + 268435456] +0xf2,0x42,0x0f,0x00,0xb4,0xf5,0x00,0x00,0x00,0x10 + +# ATT: lkgs 291(%r8,%rax,4) +# INTEL: lkgs word ptr [r8 + 4*rax + 291] +0xf2,0x41,0x0f,0x00,0xb4,0x80,0x23,0x01,0x00,0x00 + +# ATT: lkgs (%rip) +# INTEL: lkgs word ptr [rip] +0xf2,0x0f,0x00,0x35,0x00,0x00,0x00,0x00 + +# ATT: lkgs -64(,%rbp,2) +# INTEL: lkgs word ptr [2*rbp - 64] +0xf2,0x0f,0x00,0x34,0x6d,0xc0,0xff,0xff,0xff + +# ATT: lkgs 254(%rcx) +# INTEL: lkgs word ptr [rcx + 254] +0xf2,0x0f,0x00,0xb1,0xfe,0x00,0x00,0x00 + +# ATT: lkgs -256(%rdx) +# INTEL: lkgs word ptr [rdx - 256] +0xf2,0x0f,0x00,0xb2,0x00,0xff,0xff,0xff + diff --git a/llvm/test/MC/X86/fred-att.s b/llvm/test/MC/X86/fred-att.s new file mode 100644 index 000000000000..9eb2aa7555f6 --- /dev/null +++ b/llvm/test/MC/X86/fred-att.s @@ -0,0 +1,14 @@ +// RUN: llvm-mc -triple x86_64 --show-encoding %s | FileCheck %s +// RUN: not llvm-mc -triple i386 -show-encoding %s 2>&1 | FileCheck %s --check-prefix=ERROR + +// ERROR-COUNT-2: error: +// ERROR-NOT: error: + +// CHECK: erets +// CHECK: encoding: [0xf2,0x0f,0x01,0xca] + erets + +// CHECK: eretu +// CHECK: encoding: [0xf3,0x0f,0x01,0xca] + eretu + diff --git a/llvm/test/MC/X86/fred-intel.s b/llvm/test/MC/X86/fred-intel.s new file mode 100644 index 000000000000..f9175e3c3bba --- /dev/null +++ b/llvm/test/MC/X86/fred-intel.s @@ -0,0 +1,10 @@ +// RUN: llvm-mc -triple x86_64 -x86-asm-syntax=intel -output-asm-variant=1 --show-encoding %s | FileCheck %s + +// CHECK: erets +// CHECK: encoding: [0xf2,0x0f,0x01,0xca] + erets + +// CHECK: eretu +// CHECK: encoding: [0xf3,0x0f,0x01,0xca] + eretu + diff --git a/llvm/test/MC/X86/lkgs-att.s b/llvm/test/MC/X86/lkgs-att.s new file mode 100644 index 000000000000..e948e2ce559d --- /dev/null +++ b/llvm/test/MC/X86/lkgs-att.s @@ -0,0 +1,38 @@ +// RUN: llvm-mc -triple x86_64 --show-encoding %s | FileCheck %s +// RUN: not llvm-mc -triple i386 -show-encoding %s 2>&1 | FileCheck %s --check-prefix=ERROR + +// ERROR-COUNT-8: error: +// ERROR-NOT: error: + +// CHECK: lkgs %ax +// CHECK: encoding: [0xf2,0x0f,0x00,0xf0] + lkgs %ax + +// CHECK: lkgs %r12w +// CHECK: encoding: [0xf2,0x41,0x0f,0x00,0xf4] + lkgs %r12w + +// CHECK: lkgs 268435456(%rbp,%r14,8) +// CHECK: encoding: [0xf2,0x42,0x0f,0x00,0xb4,0xf5,0x00,0x00,0x00,0x10] + lkgs 268435456(%rbp,%r14,8) + +// CHECK: lkgs 291(%r8,%rax,4) +// CHECK: encoding: [0xf2,0x41,0x0f,0x00,0xb4,0x80,0x23,0x01,0x00,0x00] + lkgs 291(%r8,%rax,4) + +// CHECK: lkgs (%rip) +// CHECK: encoding: [0xf2,0x0f,0x00,0x35,0x00,0x00,0x00,0x00] + lkgs (%rip) + +// CHECK: lkgs -64(,%rbp,2) +// CHECK: encoding: [0xf2,0x0f,0x00,0x34,0x6d,0xc0,0xff,0xff,0xff] + lkgs -64(,%rbp,2) + +// CHECK: lkgs 254(%rcx) +// CHECK: encoding: [0xf2,0x0f,0x00,0xb1,0xfe,0x00,0x00,0x00] + lkgs 254(%rcx) + +// CHECK: lkgs -256(%rdx) +// CHECK: encoding: [0xf2,0x0f,0x00,0xb2,0x00,0xff,0xff,0xff] + lkgs -256(%rdx) + diff --git a/llvm/test/MC/X86/lkgs-intel.s b/llvm/test/MC/X86/lkgs-intel.s new file mode 100644 index 000000000000..bb94eda2b2b9 --- /dev/null +++ b/llvm/test/MC/X86/lkgs-intel.s @@ -0,0 +1,34 @@ +// RUN: llvm-mc -triple x86_64 -x86-asm-syntax=intel -output-asm-variant=1 --show-encoding %s | FileCheck %s + +// CHECK: lkgs ax +// CHECK: encoding: [0xf2,0x0f,0x00,0xf0] + lkgs ax + +// CHECK: lkgs r12w +// CHECK: encoding: [0xf2,0x41,0x0f,0x00,0xf4] + lkgs r12w + +// CHECK: lkgs word ptr [rbp + 8*r14 + 268435456] +// CHECK: encoding: [0xf2,0x42,0x0f,0x00,0xb4,0xf5,0x00,0x00,0x00,0x10] + lkgs word ptr [rbp + 8*r14 + 268435456] + +// CHECK: lkgs word ptr [r8 + 4*rax + 291] +// CHECK: encoding: [0xf2,0x41,0x0f,0x00,0xb4,0x80,0x23,0x01,0x00,0x00] + lkgs word ptr [r8 + 4*rax + 291] + +// CHECK: lkgs word ptr [rip] +// CHECK: encoding: [0xf2,0x0f,0x00,0x35,0x00,0x00,0x00,0x00] + lkgs word ptr [rip] + +// CHECK: lkgs word ptr [2*rbp - 64] +// CHECK: encoding: [0xf2,0x0f,0x00,0x34,0x6d,0xc0,0xff,0xff,0xff] + lkgs word ptr [2*rbp - 64] + +// CHECK: lkgs word ptr [rcx + 254] +// CHECK: encoding: [0xf2,0x0f,0x00,0xb1,0xfe,0x00,0x00,0x00] + lkgs word ptr [rcx + 254] + +// CHECK: lkgs word ptr [rdx - 256] +// CHECK: encoding: [0xf2,0x0f,0x00,0xb2,0x00,0xff,0xff,0xff] + lkgs word ptr [rdx - 256] + diff --git a/llvm/test/TableGen/x86-fold-tables.inc b/llvm/test/TableGen/x86-fold-tables.inc index c8f382d45bf6..4a52a58f2de1 100644 --- a/llvm/test/TableGen/x86-fold-tables.inc +++ b/llvm/test/TableGen/x86-fold-tables.inc @@ -426,6 +426,7 @@ static const X86FoldTableEntry Table0[] = { {X86::JMP64r, X86::JMP64m, TB_FOLDED_LOAD}, {X86::JMP64r_NT, X86::JMP64m_NT, TB_FOLDED_LOAD}, {X86::JMP64r_REX, X86::JMP64m_REX, TB_FOLDED_LOAD}, + {X86::LKGS16r, X86::LKGS16m, TB_FOLDED_LOAD}, {X86::MMX_MOVD64from64rr, X86::MMX_MOVQ64mr, TB_FOLDED_STORE}, {X86::MMX_MOVD64grr, X86::MMX_MOVD64mr, TB_FOLDED_STORE}, {X86::MOV16ri, X86::MOV16mi, TB_FOLDED_STORE}, -- GitLab From eb103104ef08ebc2d0de63db0592e76b294cf8bb Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Tue, 14 May 2024 19:53:28 -0700 Subject: [PATCH 297/578] Revert "[Serialization] Read the initializer for interesting static variables before consuming it" This reverts commit 11b059145d177ee287c7ada9864addf8d083c160. The premerge bot is broken. --- clang/lib/Serialization/ASTReaderDecl.cpp | 29 +--------- clang/test/Modules/pr91418.cppm | 67 ----------------------- 2 files changed, 3 insertions(+), 93 deletions(-) delete mode 100644 clang/test/Modules/pr91418.cppm diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index a6254b70560c..0c647086e304 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -4186,35 +4186,12 @@ void ASTReader::PassInterestingDeclsToConsumer() { GetDecl(ID); EagerlyDeserializedDecls.clear(); - auto ConsumingPotentialInterestingDecls = [this]() { - while (!PotentiallyInterestingDecls.empty()) { - Decl *D = PotentiallyInterestingDecls.front(); - PotentiallyInterestingDecls.pop_front(); - if (isConsumerInterestedIn(D)) - PassInterestingDeclToConsumer(D); - } - }; - std::deque MaybeInterestingDecls = - std::move(PotentiallyInterestingDecls); - assert(PotentiallyInterestingDecls.empty()); - while (!MaybeInterestingDecls.empty()) { - Decl *D = MaybeInterestingDecls.front(); - MaybeInterestingDecls.pop_front(); - // Since we load the variable's initializers lazily, it'd be problematic - // if the initializers dependent on each other. So here we try to load the - // initializers of static variables to make sure they are passed to code - // generator by order. If we read anything interesting, we would consume - // that before emitting the current declaration. - if (auto *VD = dyn_cast(D); - VD && VD->isFileVarDecl() && !VD->isExternallyVisible()) - VD->getInit(); - ConsumingPotentialInterestingDecls(); + while (!PotentiallyInterestingDecls.empty()) { + Decl *D = PotentiallyInterestingDecls.front(); + PotentiallyInterestingDecls.pop_front(); if (isConsumerInterestedIn(D)) PassInterestingDeclToConsumer(D); } - - // If we add any new potential interesting decl in the last call, consume it. - ConsumingPotentialInterestingDecls(); } void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { diff --git a/clang/test/Modules/pr91418.cppm b/clang/test/Modules/pr91418.cppm deleted file mode 100644 index 33fec992439d..000000000000 --- a/clang/test/Modules/pr91418.cppm +++ /dev/null @@ -1,67 +0,0 @@ -// RUN: rm -rf %t -// RUN: mkdir -p %t -// RUN: split-file %s %t -// -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -x c++-header %t/foo.h \ -// RUN: -emit-pch -o %t/foo.pch -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/use.cpp -include-pch \ -// RUN: %t/foo.pch -emit-llvm -o - | FileCheck %t/use.cpp - -//--- foo.h -#ifndef FOO_H -#define FOO_H -typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16))); - -static __inline__ __m128 __attribute__((__always_inline__, __min_vector_width__(128))) -_mm_setr_ps(float __z, float __y, float __x, float __w) -{ - return __extension__ (__m128){ __z, __y, __x, __w }; -} - -typedef __m128 VR; - -inline VR MakeVR( float X, float Y, float Z, float W ) -{ - return _mm_setr_ps( X, Y, Z, W ); -} - -extern "C" float sqrtf(float); - -namespace VectorSinConstantsSSE -{ - float a = (16 * sqrtf(0.225f)); - VR A = MakeVR(a, a, a, a); - static const float b = (16 * sqrtf(0.225f)); - static const VR B = MakeVR(b, b, b, b); -} - -#endif // FOO_H - -//--- use.cpp -#include "foo.h" -float use() { - return VectorSinConstantsSSE::A[0] + VectorSinConstantsSSE::A[1] + - VectorSinConstantsSSE::A[2] + VectorSinConstantsSSE::A[3] + - VectorSinConstantsSSE::B[0] + VectorSinConstantsSSE::B[1] + - VectorSinConstantsSSE::B[2] + VectorSinConstantsSSE::B[3]; -} - -// CHECK: define{{.*}}@__cxx_global_var_init( -// CHECK: store{{.*}}[[a_RESULT:%[a-zA-Z0-9]+]], ptr @_ZN21VectorSinConstantsSSE1aE - -// CHECK: define{{.*}}@__cxx_global_var_init.1( -// CHECK: [[A_CALL:%[a-zA-Z0-9]+]] = call{{.*}}@_Z6MakeVRffff( -// CHECK: store{{.*}}[[A_CALL]], ptr @_ZN21VectorSinConstantsSSE1AE - -// CHECK: define{{.*}}@__cxx_global_var_init.2( -// CHECK: [[B_CALL:%[a-zA-Z0-9]+]] = call{{.*}}@_Z6MakeVRffff( -// CHECK: store{{.*}}[[B_CALL]], ptr @_ZN21VectorSinConstantsSSEL1BE - -// CHECK: define{{.*}}@__cxx_global_var_init.3( -// CHECK: store{{.*}}[[b_RESULT:%[a-zA-Z0-9]+]], ptr @_ZN21VectorSinConstantsSSEL1bE - -// CHECK: @_GLOBAL__sub_I_use.cpp -// CHECK: call{{.*}}@__cxx_global_var_init( -// CHECK: call{{.*}}@__cxx_global_var_init.1( -// CHECK: call{{.*}}@__cxx_global_var_init.3( -// CHECK: call{{.*}}@__cxx_global_var_init.2( -- GitLab From 2ece5cc2bb1b4cc787e33e24a6582043d441a572 Mon Sep 17 00:00:00 2001 From: epitavy <32581827+epitavy@users.noreply.github.com> Date: Wed, 15 May 2024 05:09:11 +0200 Subject: [PATCH 298/578] [ExceptionDemo] Correct and update example ExceptionDemo (#69485) The ExceptionDemo example was no longer compiling (since llvm 14 at least). The PR makes the example work with the current API and also transition from MCJIT to ORC. Fixes #63702 --- llvm/examples/ExceptionDemo/CMakeLists.txt | 4 +- llvm/examples/ExceptionDemo/ExceptionDemo.cpp | 181 ++++++++---------- 2 files changed, 77 insertions(+), 108 deletions(-) diff --git a/llvm/examples/ExceptionDemo/CMakeLists.txt b/llvm/examples/ExceptionDemo/CMakeLists.txt index 793cf291ca6f..0a60ad848dd4 100644 --- a/llvm/examples/ExceptionDemo/CMakeLists.txt +++ b/llvm/examples/ExceptionDemo/CMakeLists.txt @@ -1,9 +1,7 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine - MC - MCJIT - RuntimeDyld + ORCJIT Support Target nativecodegen diff --git a/llvm/examples/ExceptionDemo/ExceptionDemo.cpp b/llvm/examples/ExceptionDemo/ExceptionDemo.cpp index 0afc6b30d140..41fa0cf626bf 100644 --- a/llvm/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/llvm/examples/ExceptionDemo/ExceptionDemo.cpp @@ -49,8 +49,9 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/ExecutionEngine/MCJIT.h" -#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" +#include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" @@ -84,6 +85,8 @@ #define USE_GLOBAL_STR_CONSTS true #endif +llvm::ExitOnError ExitOnErr; + // // Example types // @@ -142,6 +145,7 @@ static llvm::ConstantInt *ourExceptionCaughtState; typedef std::vector ArgNames; typedef std::vector ArgTypes; +typedef llvm::ArrayRef TypeArray; // // Code Generation Utilities @@ -892,13 +896,10 @@ void generateStringPrint(llvm::LLVMContext &context, /// generated, and is used to hold the constant string. A value of /// false indicates that the constant string will be stored on the /// stack. -void generateIntegerPrint(llvm::LLVMContext &context, - llvm::Module &module, +void generateIntegerPrint(llvm::LLVMContext &context, llvm::Module &module, llvm::IRBuilder<> &builder, - llvm::Function &printFunct, - llvm::Value &toPrint, - std::string format, - bool useGlobal = true) { + llvm::Function &printFunct, llvm::Value *toPrint, + std::string format, bool useGlobal = true) { llvm::Constant *stringConstant = llvm::ConstantDataArray::getString(context, format); llvm::Value *stringVar; @@ -920,10 +921,9 @@ void generateIntegerPrint(llvm::LLVMContext &context, llvm::Value *cast = builder.CreateBitCast(stringVar, builder.getPtrTy()); - builder.CreateCall(&printFunct, {&toPrint, cast}); + builder.CreateCall(&printFunct, {toPrint, cast}); } - /// Generates code to handle finally block type semantics: always runs /// regardless of whether a thrown exception is passing through or the /// parent function is simply exiting. In addition to printing some state @@ -997,10 +997,10 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context, bufferToPrint.str(), USE_GLOBAL_STR_CONSTS); - llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad( - *exceptionCaughtFlag), - &terminatorBlock, - 2); + llvm::SwitchInst *theSwitch = builder.CreateSwitch( + builder.CreateLoad(ourExceptionNotThrownState->getType(), + *exceptionCaughtFlag), + &terminatorBlock, 2); theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock); theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock); @@ -1186,7 +1186,7 @@ static llvm::Function *createCatchWrappedInvokeFunction( // Note: function handles NULL exceptions builder.CreateCall(deleteOurException, - builder.CreateLoad(exceptionStorage)); + builder.CreateLoad(builder.getPtrTy(), exceptionStorage)); builder.CreateRetVoid(); // Normal Block @@ -1206,7 +1206,8 @@ static llvm::Function *createCatchWrappedInvokeFunction( builder.SetInsertPoint(unwindResumeBlock); - builder.CreateResume(builder.CreateLoad(caughtResultStorage)); + builder.CreateResume( + builder.CreateLoad(ourCaughtResultType, caughtResultStorage)); // Exception Block @@ -1241,8 +1242,9 @@ static llvm::Function *createCatchWrappedInvokeFunction( // Retrieve exception_class member from thrown exception // (_Unwind_Exception instance). This member tells us whether or not // the exception is foreign. - llvm::Value *unwindExceptionClass = - builder.CreateLoad(builder.CreateStructGEP( + llvm::Value *unwindExceptionClass = builder.CreateLoad( + builder.getInt64Ty(), + builder.CreateStructGEP( ourUnwindExceptionType, builder.CreatePointerCast(unwindException, ourUnwindExceptionType->getPointerTo()), @@ -1278,9 +1280,9 @@ static llvm::Function *createCatchWrappedInvokeFunction( // // Note: ourBaseFromUnwindOffset is usually negative llvm::Value *typeInfoThrown = builder.CreatePointerCast( - builder.CreateConstGEP1_64(unwindException, - ourBaseFromUnwindOffset), - ourExceptionType->getPointerTo()); + builder.CreateConstGEP1_64(builder.getPtrTy(), unwindException, + ourBaseFromUnwindOffset), + ourExceptionType->getPointerTo()); // Retrieve thrown exception type info type // @@ -1289,17 +1291,15 @@ static llvm::Function *createCatchWrappedInvokeFunction( typeInfoThrown = builder.CreateStructGEP(ourExceptionType, typeInfoThrown, 0); llvm::Value *typeInfoThrownType = - builder.CreateStructGEP(builder.getPtrTy(), typeInfoThrown, 0); + builder.CreateStructGEP(ourTypeInfoType, typeInfoThrown, 0); - generateIntegerPrint(context, - module, - builder, - *toPrint32Int, - *(builder.CreateLoad(typeInfoThrownType)), + llvm::Value *ti8 = + builder.CreateLoad(builder.getInt8Ty(), typeInfoThrownType); + generateIntegerPrint(context, module, builder, *toPrint32Int, + builder.CreateZExt(ti8, builder.getInt32Ty()), "Gen: Exception type <%d> received (stack unwound) " " in " + - ourId + - ".\n", + ourId + ".\n", USE_GLOBAL_STR_CONSTS); // Route to matched type info catch block or run cleanup finally block @@ -1311,8 +1311,7 @@ static llvm::Function *createCatchWrappedInvokeFunction( for (unsigned i = 1; i <= numExceptionsToCatch; ++i) { nextTypeToCatch = i - 1; - switchToCatchBlock->addCase(llvm::ConstantInt::get( - llvm::Type::getInt32Ty(context), i), + switchToCatchBlock->addCase(llvm::ConstantInt::get(builder.getInt32Ty(), i), catchBlocks[nextTypeToCatch]); } @@ -1387,14 +1386,10 @@ createThrowExceptionFunction(llvm::Module &module, llvm::IRBuilder<> &builder, builder.SetInsertPoint(entryBlock); llvm::Function *toPrint32Int = module.getFunction("print32Int"); - generateIntegerPrint(context, - module, - builder, - *toPrint32Int, - *exceptionType, - "\nGen: About to throw exception type <%d> in " + - ourId + - ".\n", + generateIntegerPrint(context, module, builder, *toPrint32Int, + builder.CreateZExt(exceptionType, builder.getInt32Ty()), + "\nGen: About to throw exception type <%d> in " + ourId + + ".\n", USE_GLOBAL_STR_CONSTS); // Switches on runtime type info type value to determine whether or not @@ -1546,15 +1541,13 @@ typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow); /// @param function generated test function to run /// @param typeToThrow type info type of generated exception to throw, or /// indicator to cause foreign exception to be thrown. -static -void runExceptionThrow(llvm::ExecutionEngine *engine, - llvm::Function *function, - int32_t typeToThrow) { +static void runExceptionThrow(llvm::orc::LLJIT *JIT, std::string function, + int32_t typeToThrow) { // Find test's function pointer OurExceptionThrowFunctType functPtr = - reinterpret_cast( - reinterpret_cast(engine->getPointerToFunction(function))); + reinterpret_cast(reinterpret_cast( + ExitOnErr(JIT->lookup(function)).getValue())); try { // Run test @@ -1583,8 +1576,6 @@ void runExceptionThrow(llvm::ExecutionEngine *engine, // End test functions // -typedef llvm::ArrayRef TypeArray; - /// This initialization routine creates type info globals and /// adds external function declarations to module. /// @param numTypeInfos number of linear type info associated type info types @@ -1894,93 +1885,73 @@ int main(int argc, char *argv[]) { return(0); } - // If not set, exception handling will not be turned on - llvm::TargetOptions Opts; - llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); - llvm::LLVMContext Context; - llvm::IRBuilder<> theBuilder(Context); + auto Context = std::make_unique(); + llvm::IRBuilder<> theBuilder(*Context); // Make the module, which holds all the code. std::unique_ptr Owner = - std::make_unique("my cool jit", Context); + std::make_unique("my cool jit", *Context); llvm::Module *module = Owner.get(); - std::unique_ptr MemMgr(new llvm::SectionMemoryManager()); + // Build LLJIT + std::unique_ptr JIT = + ExitOnErr(llvm::orc::LLJITBuilder().create()); - // Build engine with JIT - llvm::EngineBuilder factory(std::move(Owner)); - factory.setEngineKind(llvm::EngineKind::JIT); - factory.setTargetOptions(Opts); - factory.setMCJITMemoryManager(std::move(MemMgr)); - llvm::ExecutionEngine *executionEngine = factory.create(); + // Set up the optimizer pipeline. + llvm::legacy::FunctionPassManager fpm(module); - { - llvm::legacy::FunctionPassManager fpm(module); - - // Set up the optimizer pipeline. - // Start with registering info about how the - // target lays out data structures. - module->setDataLayout(executionEngine->getDataLayout()); - - // Optimizations turned on + // Optimizations turned on #ifdef ADD_OPT_PASSES - // Basic AliasAnslysis support for GVN. - fpm.add(llvm::createBasicAliasAnalysisPass()); + // Basic AliasAnslysis support for GVN. + fpm.add(llvm::createBasicAliasAnalysisPass()); - // Promote allocas to registers. - fpm.add(llvm::createPromoteMemoryToRegisterPass()); + // Promote allocas to registers. + fpm.add(llvm::createPromoteMemoryToRegisterPass()); - // Do simple "peephole" optimizations and bit-twiddling optzns. - fpm.add(llvm::createInstructionCombiningPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + fpm.add(llvm::createInstructionCombiningPass()); - // Reassociate expressions. - fpm.add(llvm::createReassociatePass()); + // Reassociate expressions. + fpm.add(llvm::createReassociatePass()); - // Eliminate Common SubExpressions. - fpm.add(llvm::createGVNPass()); + // Eliminate Common SubExpressions. + fpm.add(llvm::createGVNPass()); - // Simplify the control flow graph (deleting unreachable - // blocks, etc). - fpm.add(llvm::createCFGSimplificationPass()); + // Simplify the control flow graph (deleting unreachable + // blocks, etc). + fpm.add(llvm::createCFGSimplificationPass()); #endif // ADD_OPT_PASSES - fpm.doInitialization(); + fpm.doInitialization(); - // Generate test code using function throwCppException(...) as - // the function which throws foreign exceptions. - llvm::Function *toRun = - createUnwindExceptionTest(*module, - theBuilder, - fpm, - "throwCppException"); + // Generate test code using function throwCppException(...) as + // the function which throws foreign exceptions. + createUnwindExceptionTest(*module, theBuilder, fpm, "throwCppException"); - executionEngine->finalizeObject(); + ExitOnErr(JIT->addIRModule( + llvm::orc::ThreadSafeModule(std::move(Owner), std::move(Context)))); #ifndef NDEBUG - fprintf(stderr, "\nBegin module dump:\n\n"); + fprintf(stderr, "\nBegin module dump:\n\n"); - module->dump(); + module->print(llvm::errs(), nullptr); - fprintf(stderr, "\nEnd module dump:\n"); + fprintf(stderr, "\nEnd module dump:\n"); #endif - fprintf(stderr, "\n\nBegin Test:\n"); - - for (int i = 1; i < argc; ++i) { - // Run test for each argument whose value is the exception - // type to throw. - runExceptionThrow(executionEngine, - toRun, - (unsigned) strtoul(argv[i], NULL, 10)); - } + fprintf(stderr, "\n\nBegin Test:\n"); + std::string toRun = "outerCatchFunct"; - fprintf(stderr, "\nEnd Test:\n\n"); + for (int i = 1; i < argc; ++i) { + // Run test for each argument whose value is the exception + // type to throw. + runExceptionThrow(JIT.get(), toRun, (unsigned)strtoul(argv[i], NULL, 10)); } - delete executionEngine; + fprintf(stderr, "\nEnd Test:\n\n"); return 0; } -- GitLab From 72b2c37de6a4bbc2b2d2cda49293684b7cc71508 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Tue, 14 May 2024 20:29:36 -0700 Subject: [PATCH 299/578] [clang-format][NFC] Clean up TokenAnnotator::mustBreakBefore() --- clang/lib/Format/TokenAnnotator.cpp | 35 +++++++++++++++-------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 478cae23d3c8..d0aa0838423e 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -5405,6 +5405,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, return true; } + const auto *BeforeLeft = Left.Previous; + const auto *AfterRight = Right.Next; + if (Style.isCSharp()) { if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) && Style.BraceWrapping.AfterFunction) { @@ -5416,7 +5419,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, } if (Right.is(TT_CSharpGenericTypeConstraint)) return true; - if (Right.Next && Right.Next->is(TT_FatArrow) && + if (AfterRight && AfterRight->is(TT_FatArrow) && (Right.is(tok::numeric_constant) || (Right.is(tok::identifier) && Right.TokenText == "_"))) { return true; @@ -5433,15 +5436,14 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, Left.is(tok::r_square) && Right.is(tok::l_square)) { return true; } - } else if (Style.isJavaScript()) { // FIXME: This might apply to other languages and token kinds. - if (Right.is(tok::string_literal) && Left.is(tok::plus) && Left.Previous && - Left.Previous->is(tok::string_literal)) { + if (Right.is(tok::string_literal) && Left.is(tok::plus) && BeforeLeft && + BeforeLeft->is(tok::string_literal)) { return true; } if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && Line.Level == 0 && - Left.Previous && Left.Previous->is(tok::equal) && + BeforeLeft && BeforeLeft->is(tok::equal) && Line.First->isOneOf(tok::identifier, Keywords.kw_import, tok::kw_export, tok::kw_const) && // kw_var/kw_let are pseudo-tokens that are tok::identifier, so match @@ -5460,8 +5462,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // instead of bin-packing. return true; } - if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && Left.Previous && - Left.Previous->is(TT_FatArrow)) { + if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && BeforeLeft && + BeforeLeft->is(TT_FatArrow)) { // JS arrow function (=> {...}). switch (Style.AllowShortLambdasOnASingleLine) { case FormatStyle::SLS_All: @@ -5489,8 +5491,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, FormatStyle::SFS_InlineOnly); } } else if (Style.Language == FormatStyle::LK_Java) { - if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next && - Right.Next->is(tok::string_literal)) { + if (Right.is(tok::plus) && Left.is(tok::string_literal) && AfterRight && + AfterRight->is(tok::string_literal)) { return true; } } else if (Style.isVerilog()) { @@ -5543,8 +5545,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, } return Style.BreakArrays; } - } - if (Style.isTableGen()) { + } else if (Style.isTableGen()) { // Break the comma in side cond operators. // !cond(case1:1, // case2:0); @@ -5600,8 +5601,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, return true; if (Left.IsUnterminatedLiteral) return true; - if (Right.is(tok::lessless) && Right.Next && Left.is(tok::string_literal) && - Right.Next->is(tok::string_literal)) { + if (Right.is(tok::lessless) && AfterRight && Left.is(tok::string_literal) && + AfterRight->is(tok::string_literal)) { return true; } if (Right.is(TT_RequiresClause)) { @@ -5678,8 +5679,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // string literal accordingly. Thus, we try keep existing line breaks. return Right.IsMultiline && Right.NewlinesBefore > 0; } - if ((Left.is(tok::l_brace) || (Left.is(tok::less) && Left.Previous && - Left.Previous->is(tok::equal))) && + if ((Left.is(tok::l_brace) || + (Left.is(tok::less) && BeforeLeft && BeforeLeft->is(tok::equal))) && Right.NestingLevel == 1 && Style.Language == FormatStyle::LK_Proto) { // Don't put enums or option definitions onto single lines in protocol // buffers. @@ -5793,7 +5794,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // // We ensure elsewhere that extensions are always on their own line. if (Style.isProto() && Right.is(TT_SelectorName) && - Right.isNot(tok::r_square) && Right.Next) { + Right.isNot(tok::r_square) && AfterRight) { // Keep `@submessage` together in: // @submessage { key: value } if (Left.is(tok::at)) @@ -5802,7 +5803,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // selector { ... // selector: { ... // selector: @base { ... - FormatToken *LBrace = Right.Next; + const auto *LBrace = AfterRight; if (LBrace && LBrace->is(tok::colon)) { LBrace = LBrace->Next; if (LBrace && LBrace->is(tok::at)) { -- GitLab From 1a58e88690c1a48d1082b4ee6b759f5dc49a7144 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Wed, 15 May 2024 11:44:32 +0800 Subject: [PATCH 300/578] [RISCV] Move RISCVInsertVSETVLI to after phi elimination (#91440) Split off from #70549, this patch moves RISCVInsertVSETVLI to after phi elimination where we exit SSA and need to move to LiveVariables. The motivation for splitting this off is to avoid the large scheduling diffs from moving completely to after regalloc, and instead focus on converting the pass to work on LiveIntervals. The two main changes required are updating VSETVLIInfo to store VNInfos instead of MachineInstrs, which allows us to still check for PHI defs in needVSETVLIPHI, and fixing up the live intervals of any AVL operands after inserting new instructions. On O3 the pass is inserted after the register coalescer, otherwise we end up with a bunch of COPYs around eliminated PHIs that trip up needVSETVLIPHI. Co-authored-by: Piyou Chen --- llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp | 262 +++++++++++------- llvm/lib/Target/RISCV/RISCVTargetMachine.cpp | 9 +- llvm/test/CodeGen/RISCV/O0-pipeline.ll | 6 +- llvm/test/CodeGen/RISCV/O3-pipeline.ll | 2 +- llvm/test/CodeGen/RISCV/rvv/combine-vmv.ll | 2 +- .../rvv/concat-vectors-constant-stride.ll | 2 +- .../RISCV/rvv/dont-sink-splat-operands.ll | 8 +- .../CodeGen/RISCV/rvv/fixed-vectors-int.ll | 2 +- .../RISCV/rvv/fixed-vectors-masked-gather.ll | 2 +- .../rvv/fixed-vectors-shuffle-vslide1up.ll | 2 +- .../rvv/fixed-vectors-strided-load-combine.ll | 2 +- .../fixed-vectors-strided-load-store-asm.ll | 2 +- .../RISCV/rvv/fixed-vectors-trunc-vp.ll | 2 +- .../RISCV/rvv/fold-scalar-load-crash.ll | 4 +- .../CodeGen/RISCV/rvv/fpclamptosat_vec.ll | 12 +- .../RISCV/rvv/rv32-spill-vector-csr.ll | 4 +- .../CodeGen/RISCV/rvv/rv32-spill-zvlsseg.ll | 10 +- .../RISCV/rvv/rv64-spill-vector-csr.ll | 4 +- .../CodeGen/RISCV/rvv/rv64-spill-zvlsseg.ll | 10 +- .../RISCV/rvv/rvv-peephole-vmerge-vops.ll | 8 +- .../CodeGen/RISCV/rvv/sink-splat-operands.ll | 44 +-- .../RISCV/rvv/undef-earlyclobber-chain.ll | 2 +- llvm/test/CodeGen/RISCV/rvv/unmasked-tu.ll | 4 +- .../RISCV/rvv/vector-reassociations.ll | 8 +- llvm/test/CodeGen/RISCV/rvv/vfwmacc-vp.ll | 2 +- .../RISCV/rvv/vrgatherei16-subreg-liveness.ll | 8 +- .../RISCV/rvv/vsetvli-insert-crossbb.ll | 2 - .../RISCV/rvv/vsetvli-insert-crossbb.mir | 136 ++++----- llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll | 12 +- 29 files changed, 312 insertions(+), 261 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp index 7a8ff84995ea..1c815424bdfa 100644 --- a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp +++ b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp @@ -47,6 +47,18 @@ static cl::opt DisableInsertVSETVLPHIOpt( namespace { +/// Given a virtual register \p Reg, return the corresponding VNInfo for it. +/// This should never return nullptr. +static VNInfo *getVNInfoFromReg(Register Reg, const MachineInstr &MI, + const LiveIntervals *LIS) { + assert(Reg.isVirtual()); + auto &LI = LIS->getInterval(Reg); + SlotIndex SI = LIS->getSlotIndexes()->getInstructionIndex(MI); + VNInfo *VNI = LI.getVNInfoBefore(SI); + assert(VNI); + return VNI; +} + static unsigned getVLOpNum(const MachineInstr &MI) { return RISCVII::getVLOpNum(MI.getDesc()); } @@ -426,7 +438,8 @@ DemandedFields getDemanded(const MachineInstr &MI, const RISCVSubtarget *ST) { /// values of the VL and VTYPE registers after insertion. class VSETVLIInfo { struct AVLDef { - const MachineInstr *DefMI; + // Every AVLDef should have a VNInfo. + const VNInfo *ValNo; Register DefReg; }; union { @@ -465,9 +478,9 @@ public: void setUnknown() { State = Unknown; } bool isUnknown() const { return State == Unknown; } - void setAVLRegDef(const MachineInstr *DefMI, Register AVLReg) { - assert(DefMI && AVLReg.isVirtual()); - AVLRegDef.DefMI = DefMI; + void setAVLRegDef(const VNInfo *VNInfo, Register AVLReg) { + assert(VNInfo && AVLReg.isVirtual()); + AVLRegDef.ValNo = VNInfo; AVLRegDef.DefReg = AVLReg; State = AVLIsReg; } @@ -493,9 +506,18 @@ public: assert(hasAVLImm()); return AVLImm; } - const MachineInstr &getAVLDefMI() const { - assert(hasAVLReg() && AVLRegDef.DefMI); - return *AVLRegDef.DefMI; + const VNInfo *getAVLVNInfo() const { + assert(hasAVLReg()); + return AVLRegDef.ValNo; + } + // Most AVLIsReg infos will have a single defining MachineInstr, unless it was + // a PHI node. In that case getAVLVNInfo()->def will point to the block + // boundary slot. + const MachineInstr *getAVLDefMI(const LiveIntervals *LIS) const { + assert(hasAVLReg()); + auto *MI = LIS->getInstructionFromIndex(getAVLVNInfo()->def); + assert(!(getAVLVNInfo()->isPHIDef() && MI)); + return MI; } void setAVL(VSETVLIInfo Info) { @@ -503,7 +525,7 @@ public: if (Info.isUnknown()) setUnknown(); else if (Info.hasAVLReg()) - setAVLRegDef(&Info.getAVLDefMI(), Info.getAVLReg()); + setAVLRegDef(Info.getAVLVNInfo(), Info.getAVLReg()); else if (Info.hasAVLVLMAX()) setAVLVLMAX(); else if (Info.hasAVLIgnored()) @@ -519,11 +541,13 @@ public: bool getTailAgnostic() const { return TailAgnostic; } bool getMaskAgnostic() const { return MaskAgnostic; } - bool hasNonZeroAVL() const { + bool hasNonZeroAVL(const LiveIntervals *LIS) const { if (hasAVLImm()) return getAVLImm() > 0; - if (hasAVLReg()) - return isNonZeroLoadImmediate(getAVLDefMI()); + if (hasAVLReg()) { + if (auto *DefMI = getAVLDefMI(LIS)) + return isNonZeroLoadImmediate(*DefMI); + } if (hasAVLVLMAX()) return true; if (hasAVLIgnored()) @@ -531,16 +555,17 @@ public: return false; } - bool hasEquallyZeroAVL(const VSETVLIInfo &Other) const { + bool hasEquallyZeroAVL(const VSETVLIInfo &Other, + const LiveIntervals *LIS) const { if (hasSameAVL(Other)) return true; - return (hasNonZeroAVL() && Other.hasNonZeroAVL()); + return (hasNonZeroAVL(LIS) && Other.hasNonZeroAVL(LIS)); } bool hasSameAVL(const VSETVLIInfo &Other) const { if (hasAVLReg() && Other.hasAVLReg()) - return AVLRegDef.DefMI == Other.AVLRegDef.DefMI && - AVLRegDef.DefReg == Other.AVLRegDef.DefReg; + return getAVLVNInfo()->id == Other.getAVLVNInfo()->id && + getAVLReg() == Other.getAVLReg(); if (hasAVLImm() && Other.hasAVLImm()) return getAVLImm() == Other.getAVLImm(); @@ -620,7 +645,7 @@ public: // Require are compatible with the previous vsetvli instruction represented // by this. MI is the instruction whose requirements we're considering. bool isCompatible(const DemandedFields &Used, const VSETVLIInfo &Require, - const MachineRegisterInfo &MRI) const { + const LiveIntervals *LIS) const { assert(isValid() && Require.isValid() && "Can't compare invalid VSETVLIInfos"); assert(!Require.SEWLMULRatioOnly && @@ -636,7 +661,7 @@ public: if (Used.VLAny && !(hasSameAVL(Require) && hasSameVLMAX(Require))) return false; - if (Used.VLZeroness && !hasEquallyZeroAVL(Require)) + if (Used.VLZeroness && !hasEquallyZeroAVL(Require, LIS)) return false; return hasCompatibleVTYPE(Used, Require); @@ -765,6 +790,7 @@ class RISCVInsertVSETVLI : public MachineFunctionPass { const RISCVSubtarget *ST; const TargetInstrInfo *TII; MachineRegisterInfo *MRI; + LiveIntervals *LIS; std::vector BlockInfo; std::queue WorkList; @@ -777,6 +803,14 @@ public: void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); + + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); } @@ -848,7 +882,7 @@ INITIALIZE_PASS(RISCVCoalesceVSETVLI, "riscv-coalesce-vsetvli", // Return a VSETVLIInfo representing the changes made by this VSETVLI or // VSETIVLI instruction. static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI, - const MachineRegisterInfo &MRI) { + const LiveIntervals *LIS) { VSETVLIInfo NewInfo; if (MI.getOpcode() == RISCV::PseudoVSETIVLI) { NewInfo.setAVLImm(MI.getOperand(1).getImm()); @@ -861,7 +895,7 @@ static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI, if (AVLReg == RISCV::X0) NewInfo.setAVLVLMAX(); else - NewInfo.setAVLRegDef(MRI.getUniqueVRegDef(AVLReg), AVLReg); + NewInfo.setAVLRegDef(getVNInfoFromReg(AVLReg, MI, LIS), AVLReg); } NewInfo.setVTYPE(MI.getOperand(2).getImm()); @@ -880,7 +914,7 @@ static unsigned computeVLMAX(unsigned VLEN, unsigned SEW, static VSETVLIInfo computeInfoForInstr(const MachineInstr &MI, uint64_t TSFlags, const RISCVSubtarget &ST, - const MachineRegisterInfo *MRI) { + const LiveIntervals *LIS) { VSETVLIInfo InstrInfo; bool TailAgnostic = true; @@ -933,7 +967,7 @@ static VSETVLIInfo computeInfoForInstr(const MachineInstr &MI, uint64_t TSFlags, else InstrInfo.setAVLImm(Imm); } else { - InstrInfo.setAVLRegDef(MRI->getUniqueVRegDef(VLOp.getReg()), + InstrInfo.setAVLRegDef(getVNInfoFromReg(VLOp.getReg(), MI, LIS), VLOp.getReg()); } } else { @@ -955,9 +989,9 @@ static VSETVLIInfo computeInfoForInstr(const MachineInstr &MI, uint64_t TSFlags, // register AVLs to avoid extending live ranges without being sure we can // kill the original source reg entirely. if (InstrInfo.hasAVLReg()) { - const MachineInstr &DefMI = InstrInfo.getAVLDefMI(); - if (isVectorConfigInstr(DefMI)) { - VSETVLIInfo DefInstrInfo = getInfoForVSETVLI(DefMI, *MRI); + if (const MachineInstr *DefMI = InstrInfo.getAVLDefMI(LIS); + DefMI && isVectorConfigInstr(*DefMI)) { + VSETVLIInfo DefInstrInfo = getInfoForVSETVLI(*DefMI, LIS); if (DefInstrInfo.hasSameVLMAX(InstrInfo) && (DefInstrInfo.hasAVLImm() || DefInstrInfo.hasAVLVLMAX())) InstrInfo.setAVL(DefInstrInfo); @@ -983,11 +1017,12 @@ void RISCVInsertVSETVLI::insertVSETVLI(MachineBasicBlock &MBB, // Use X0, X0 form if the AVL is the same and the SEW+LMUL gives the same // VLMAX. if (Info.hasSameAVL(PrevInfo) && Info.hasSameVLMAX(PrevInfo)) { - BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0)) - .addReg(RISCV::X0, RegState::Define | RegState::Dead) - .addReg(RISCV::X0, RegState::Kill) - .addImm(Info.encodeVTYPE()) - .addReg(RISCV::VL, RegState::Implicit); + auto MI = BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0)) + .addReg(RISCV::X0, RegState::Define | RegState::Dead) + .addReg(RISCV::X0, RegState::Kill) + .addImm(Info.encodeVTYPE()) + .addReg(RISCV::VL, RegState::Implicit); + LIS->InsertMachineInstrInMaps(*MI); return; } @@ -995,15 +1030,16 @@ void RISCVInsertVSETVLI::insertVSETVLI(MachineBasicBlock &MBB, // it has the same VLMAX we want and the last VL/VTYPE we observed is the // same, we can use the X0, X0 form. if (Info.hasSameVLMAX(PrevInfo) && Info.hasAVLReg()) { - const MachineInstr &DefMI = Info.getAVLDefMI(); - if (isVectorConfigInstr(DefMI)) { - VSETVLIInfo DefInfo = getInfoForVSETVLI(DefMI, *MRI); + if (const MachineInstr *DefMI = Info.getAVLDefMI(LIS); + DefMI && isVectorConfigInstr(*DefMI)) { + VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI, LIS); if (DefInfo.hasSameAVL(PrevInfo) && DefInfo.hasSameVLMAX(PrevInfo)) { - BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0)) - .addReg(RISCV::X0, RegState::Define | RegState::Dead) - .addReg(RISCV::X0, RegState::Kill) - .addImm(Info.encodeVTYPE()) - .addReg(RISCV::VL, RegState::Implicit); + auto MI = BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0)) + .addReg(RISCV::X0, RegState::Define | RegState::Dead) + .addReg(RISCV::X0, RegState::Kill) + .addImm(Info.encodeVTYPE()) + .addReg(RISCV::VL, RegState::Implicit); + LIS->InsertMachineInstrInMaps(*MI); return; } } @@ -1011,10 +1047,11 @@ void RISCVInsertVSETVLI::insertVSETVLI(MachineBasicBlock &MBB, } if (Info.hasAVLImm()) { - BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETIVLI)) - .addReg(RISCV::X0, RegState::Define | RegState::Dead) - .addImm(Info.getAVLImm()) - .addImm(Info.encodeVTYPE()); + auto MI = BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETIVLI)) + .addReg(RISCV::X0, RegState::Define | RegState::Dead) + .addImm(Info.getAVLImm()) + .addImm(Info.encodeVTYPE()); + LIS->InsertMachineInstrInMaps(*MI); return; } @@ -1023,36 +1060,46 @@ void RISCVInsertVSETVLI::insertVSETVLI(MachineBasicBlock &MBB, // the previous vl to become invalid. if (PrevInfo.isValid() && !PrevInfo.isUnknown() && Info.hasSameVLMAX(PrevInfo)) { - BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0)) - .addReg(RISCV::X0, RegState::Define | RegState::Dead) - .addReg(RISCV::X0, RegState::Kill) - .addImm(Info.encodeVTYPE()) - .addReg(RISCV::VL, RegState::Implicit); + auto MI = BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0)) + .addReg(RISCV::X0, RegState::Define | RegState::Dead) + .addReg(RISCV::X0, RegState::Kill) + .addImm(Info.encodeVTYPE()) + .addReg(RISCV::VL, RegState::Implicit); + LIS->InsertMachineInstrInMaps(*MI); return; } // Otherwise use an AVL of 1 to avoid depending on previous vl. - BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETIVLI)) - .addReg(RISCV::X0, RegState::Define | RegState::Dead) - .addImm(1) - .addImm(Info.encodeVTYPE()); + auto MI = BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETIVLI)) + .addReg(RISCV::X0, RegState::Define | RegState::Dead) + .addImm(1) + .addImm(Info.encodeVTYPE()); + LIS->InsertMachineInstrInMaps(*MI); return; } if (Info.hasAVLVLMAX()) { Register DestReg = MRI->createVirtualRegister(&RISCV::GPRRegClass); - BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0)) - .addReg(DestReg, RegState::Define | RegState::Dead) - .addReg(RISCV::X0, RegState::Kill) - .addImm(Info.encodeVTYPE()); + auto MI = BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0)) + .addReg(DestReg, RegState::Define | RegState::Dead) + .addReg(RISCV::X0, RegState::Kill) + .addImm(Info.encodeVTYPE()); + LIS->InsertMachineInstrInMaps(*MI); + LIS->createAndComputeVirtRegInterval(DestReg); return; } Register AVLReg = Info.getAVLReg(); MRI->constrainRegClass(AVLReg, &RISCV::GPRNoX0RegClass); - BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLI)) - .addReg(RISCV::X0, RegState::Define | RegState::Dead) - .addReg(AVLReg) - .addImm(Info.encodeVTYPE()); + auto MI = BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLI)) + .addReg(RISCV::X0, RegState::Define | RegState::Dead) + .addReg(AVLReg) + .addImm(Info.encodeVTYPE()); + LIS->InsertMachineInstrInMaps(*MI); + // Normally the AVL's live range will already extend past the inserted vsetvli + // because the pseudos below will already use the AVL. But this isn't always + // the case, e.g. PseudoVMV_X_S doesn't have an AVL operand. + LIS->getInterval(AVLReg).extendInBlock( + LIS->getMBBStartIdx(&MBB), LIS->getInstructionIndex(*MI).getRegSlot()); } static bool isLMUL1OrSmaller(RISCVII::VLMUL LMUL) { @@ -1065,7 +1112,7 @@ static bool isLMUL1OrSmaller(RISCVII::VLMUL LMUL) { bool RISCVInsertVSETVLI::needVSETVLI(const MachineInstr &MI, const VSETVLIInfo &Require, const VSETVLIInfo &CurInfo) const { - assert(Require == computeInfoForInstr(MI, MI.getDesc().TSFlags, *ST, MRI)); + assert(Require == computeInfoForInstr(MI, MI.getDesc().TSFlags, *ST, LIS)); if (!CurInfo.isValid() || CurInfo.isUnknown() || CurInfo.hasSEWLMULRatioOnly()) return true; @@ -1106,7 +1153,7 @@ bool RISCVInsertVSETVLI::needVSETVLI(const MachineInstr &MI, Used.TailPolicy = false; } - if (CurInfo.isCompatible(Used, Require, *MRI)) + if (CurInfo.isCompatible(Used, Require, LIS)) return false; // We didn't find a compatible value. If our AVL is a virtual register, @@ -1114,9 +1161,9 @@ bool RISCVInsertVSETVLI::needVSETVLI(const MachineInstr &MI, // and the last VL/VTYPE we observed is the same, we don't need a // VSETVLI here. if (Require.hasAVLReg() && CurInfo.hasCompatibleVTYPE(Used, Require)) { - const MachineInstr &DefMI = Require.getAVLDefMI(); - if (isVectorConfigInstr(DefMI)) { - VSETVLIInfo DefInfo = getInfoForVSETVLI(DefMI, *MRI); + if (const MachineInstr *DefMI = Require.getAVLDefMI(LIS); + DefMI && isVectorConfigInstr(*DefMI)) { + VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI, LIS); if (DefInfo.hasSameAVL(CurInfo) && DefInfo.hasSameVLMAX(CurInfo)) return false; } @@ -1152,7 +1199,7 @@ void RISCVInsertVSETVLI::transferBefore(VSETVLIInfo &Info, if (!RISCVII::hasSEWOp(TSFlags)) return; - const VSETVLIInfo NewInfo = computeInfoForInstr(MI, TSFlags, *ST, MRI); + const VSETVLIInfo NewInfo = computeInfoForInstr(MI, TSFlags, *ST, LIS); assert(NewInfo.isValid() && !NewInfo.isUnknown()); if (Info.isValid() && !needVSETVLI(MI, NewInfo, Info)) return; @@ -1171,7 +1218,7 @@ void RISCVInsertVSETVLI::transferBefore(VSETVLIInfo &Info, // variant, so we avoid the transform to prevent extending live range of an // avl register operand. // TODO: We can probably relax this for immediates. - bool EquallyZero = IncomingInfo.hasEquallyZeroAVL(PrevInfo) && + bool EquallyZero = IncomingInfo.hasEquallyZeroAVL(PrevInfo, LIS) && IncomingInfo.hasSameVLMAX(PrevInfo); if (Demanded.VLAny || (Demanded.VLZeroness && !EquallyZero)) Info.setAVL(IncomingInfo); @@ -1202,14 +1249,17 @@ void RISCVInsertVSETVLI::transferBefore(VSETVLIInfo &Info, void RISCVInsertVSETVLI::transferAfter(VSETVLIInfo &Info, const MachineInstr &MI) const { if (isVectorConfigInstr(MI)) { - Info = getInfoForVSETVLI(MI, *MRI); + Info = getInfoForVSETVLI(MI, LIS); return; } if (RISCV::isFaultFirstLoad(MI)) { // Update AVL to vl-output of the fault first load. - Info.setAVLRegDef(MRI->getUniqueVRegDef(MI.getOperand(1).getReg()), - MI.getOperand(1).getReg()); + assert(MI.getOperand(1).getReg().isVirtual()); + auto &LI = LIS->getInterval(MI.getOperand(1).getReg()); + SlotIndex SI = LIS->getSlotIndexes()->getInstructionIndex(MI).getRegSlot(); + VNInfo *VNI = LI.getVNInfoAt(SI); + Info.setAVLRegDef(VNI, MI.getOperand(1).getReg()); return; } @@ -1293,7 +1343,7 @@ void RISCVInsertVSETVLI::computeIncomingVLVTYPE(const MachineBasicBlock &MBB) { } // If we weren't able to prove a vsetvli was directly unneeded, it might still -// be unneeded if the AVL is a phi node where all incoming values are VL +// be unneeded if the AVL was a phi node where all incoming values are VL // outputs from the last VSETVLI in their respective basic blocks. bool RISCVInsertVSETVLI::needVSETVLIPHI(const VSETVLIInfo &Require, const MachineBasicBlock &MBB) const { @@ -1303,26 +1353,27 @@ bool RISCVInsertVSETVLI::needVSETVLIPHI(const VSETVLIInfo &Require, if (!Require.hasAVLReg()) return true; - // We need the AVL to be produce by a PHI node in this basic block. - const MachineInstr *PHI = &Require.getAVLDefMI(); - if (PHI->getOpcode() != RISCV::PHI || PHI->getParent() != &MBB) + // We need the AVL to have been produced by a PHI node in this basic block. + const VNInfo *Valno = Require.getAVLVNInfo(); + if (!Valno->isPHIDef() || LIS->getMBBFromIndex(Valno->def) != &MBB) return true; - for (unsigned PHIOp = 1, NumOps = PHI->getNumOperands(); PHIOp != NumOps; - PHIOp += 2) { - Register InReg = PHI->getOperand(PHIOp).getReg(); - MachineBasicBlock *PBB = PHI->getOperand(PHIOp + 1).getMBB(); + const LiveRange &LR = LIS->getInterval(Require.getAVLReg()); + + for (auto *PBB : MBB.predecessors()) { const VSETVLIInfo &PBBExit = BlockInfo[PBB->getNumber()].Exit; // We need the PHI input to the be the output of a VSET(I)VLI. - MachineInstr *DefMI = MRI->getUniqueVRegDef(InReg); - assert(DefMI); - if (!isVectorConfigInstr(*DefMI)) + const VNInfo *Value = LR.getVNInfoBefore(LIS->getMBBEndIdx(PBB)); + if (!Value) + return true; + MachineInstr *DefMI = LIS->getInstructionFromIndex(Value->def); + if (!DefMI || !isVectorConfigInstr(*DefMI)) return true; // We found a VSET(I)VLI make sure it matches the output of the // predecessor block. - VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI, *MRI); + VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI, LIS); if (DefInfo != PBBExit) return true; @@ -1377,19 +1428,28 @@ void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock &MBB) { MachineOperand &VLOp = MI.getOperand(getVLOpNum(MI)); if (VLOp.isReg()) { Register Reg = VLOp.getReg(); - MachineInstr *VLOpDef = MRI->getUniqueVRegDef(Reg); - assert(VLOpDef); + LiveInterval &LI = LIS->getInterval(Reg); // Erase the AVL operand from the instruction. VLOp.setReg(RISCV::NoRegister); VLOp.setIsKill(false); + SmallVector DeadMIs; + LIS->shrinkToUses(&LI, &DeadMIs); + // We might have separate components that need split due to + // needVSETVLIPHI causing us to skip inserting a new VL def. + SmallVector SplitLIs; + LIS->splitSeparateComponents(LI, SplitLIs); // If the AVL was an immediate > 31, then it would have been emitted // as an ADDI. However, the ADDI might not have been used in the // vsetvli, or a vsetvli might not have been emitted, so it may be // dead now. - if (TII->isAddImmediate(*VLOpDef, Reg) && MRI->use_nodbg_empty(Reg)) - VLOpDef->eraseFromParent(); + for (MachineInstr *DeadMI : DeadMIs) { + if (!TII->isAddImmediate(*DeadMI, Reg)) + continue; + LIS->RemoveMachineInstrFromMaps(*DeadMI); + DeadMI->eraseFromParent(); + } } MI.addOperand(MachineOperand::CreateReg(RISCV::VL, /*isDef*/ false, /*isImp*/ true)); @@ -1458,14 +1518,14 @@ void RISCVInsertVSETVLI::doPRE(MachineBasicBlock &MBB) { // we need to prove the value is available at the point we're going // to insert the vsetvli at. if (AvailableInfo.hasAVLReg()) { - const MachineInstr *AVLDefMI = &AvailableInfo.getAVLDefMI(); + SlotIndex SI = AvailableInfo.getAVLVNInfo()->def; // This is an inline dominance check which covers the case of // UnavailablePred being the preheader of a loop. - if (AVLDefMI->getParent() != UnavailablePred) + if (LIS->getMBBFromIndex(SI) != UnavailablePred) + return; + if (!UnavailablePred->terminators().empty() && + SI >= LIS->getInstructionIndex(*UnavailablePred->getFirstTerminator())) return; - for (auto &TermMI : UnavailablePred->terminators()) - if (&TermMI == AVLDefMI) - return; } // If the AVL isn't used in its predecessors then bail, since we have no AVL @@ -1526,7 +1586,8 @@ void RISCVInsertVSETVLI::doPRE(MachineBasicBlock &MBB) { static bool canMutatePriorConfig(const MachineInstr &PrevMI, const MachineInstr &MI, const DemandedFields &Used, - const MachineRegisterInfo &MRI) { + const MachineRegisterInfo &MRI, + const LiveIntervals *LIS) { // If the VL values aren't equal, return false if either a) the former is // demanded, or b) we can't rewrite the former to be the later for // implementation reasons. @@ -1537,8 +1598,8 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI, if (Used.VLZeroness) { if (isVLPreservingConfig(PrevMI)) return false; - if (!getInfoForVSETVLI(PrevMI, MRI) - .hasEquallyZeroAVL(getInfoForVSETVLI(MI, MRI))) + if (!getInfoForVSETVLI(PrevMI, LIS) + .hasEquallyZeroAVL(getInfoForVSETVLI(MI, LIS), LIS)) return false; } @@ -1588,7 +1649,7 @@ bool RISCVCoalesceVSETVLI::coalesceVSETVLIs(MachineBasicBlock &MBB) { continue; } - if (canMutatePriorConfig(MI, *NextMI, Used, *MRI)) { + if (canMutatePriorConfig(MI, *NextMI, Used, *MRI, LIS)) { if (!isVLPreservingConfig(*NextMI)) { Register DefReg = NextMI->getOperand(0).getReg(); @@ -1661,9 +1722,17 @@ void RISCVInsertVSETVLI::insertReadVL(MachineBasicBlock &MBB) { if (RISCV::isFaultFirstLoad(MI)) { Register VLOutput = MI.getOperand(1).getReg(); assert(VLOutput.isVirtual()); - if (!MRI->use_nodbg_empty(VLOutput)) - BuildMI(MBB, I, MI.getDebugLoc(), TII->get(RISCV::PseudoReadVL), - VLOutput); + if (!MI.getOperand(1).isDead()) { + auto ReadVLMI = BuildMI(MBB, I, MI.getDebugLoc(), + TII->get(RISCV::PseudoReadVL), VLOutput); + // Move the LiveInterval's definition down to PseudoReadVL. + SlotIndex NewDefSI = + LIS->InsertMachineInstrInMaps(*ReadVLMI).getRegSlot(); + LiveInterval &DefLI = LIS->getInterval(VLOutput); + VNInfo *DefVNI = DefLI.getVNInfoAt(DefLI.beginIndex()); + DefLI.removeSegment(DefLI.beginIndex(), NewDefSI); + DefVNI->def = NewDefSI; + } // We don't use the vl output of the VLEFF/VLSEGFF anymore. MI.getOperand(1).setReg(RISCV::X0); } @@ -1680,6 +1749,7 @@ bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) { TII = ST->getInstrInfo(); MRI = &MF.getRegInfo(); + LIS = &getAnalysis(); assert(BlockInfo.empty() && "Expect empty block infos"); BlockInfo.resize(MF.getNumBlockIDs()); diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp index 7b2dcadc4191..5d598a275a00 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -541,9 +541,16 @@ void RISCVPassConfig::addPreRegAlloc() { addPass(createRISCVPreRAExpandPseudoPass()); if (TM->getOptLevel() != CodeGenOptLevel::None) addPass(createRISCVMergeBaseOffsetOptPass()); + addPass(createRISCVInsertReadWriteCSRPass()); addPass(createRISCVInsertWriteVXRMPass()); - addPass(createRISCVInsertVSETVLIPass()); + + // Run RISCVInsertVSETVLI after PHI elimination. On O1 and above do it after + // register coalescing so needVSETVLIPHI doesn't need to look through COPYs. + if (TM->getOptLevel() == CodeGenOptLevel::None) + insertPass(&PHIEliminationID, createRISCVInsertVSETVLIPass()); + else + insertPass(&RegisterCoalescerID, createRISCVInsertVSETVLIPass()); } void RISCVPassConfig::addFastRegAlloc() { diff --git a/llvm/test/CodeGen/RISCV/O0-pipeline.ll b/llvm/test/CodeGen/RISCV/O0-pipeline.ll index c4a7f9562534..3aaa5dc03a7d 100644 --- a/llvm/test/CodeGen/RISCV/O0-pipeline.ll +++ b/llvm/test/CodeGen/RISCV/O0-pipeline.ll @@ -42,12 +42,14 @@ ; CHECK-NEXT: RISC-V Pre-RA pseudo instruction expansion pass ; CHECK-NEXT: RISC-V Insert Read/Write CSR Pass ; CHECK-NEXT: RISC-V Insert Write VXRM Pass -; CHECK-NEXT: RISC-V Insert VSETVLI pass ; CHECK-NEXT: Init Undef Pass ; CHECK-NEXT: Eliminate PHI nodes for register allocation +; CHECK-NEXT: MachineDominator Tree Construction +; CHECK-NEXT: Slot index numbering +; CHECK-NEXT: Live Interval Analysis +; CHECK-NEXT: RISC-V Insert VSETVLI pass ; CHECK-NEXT: Two-Address instruction pass ; CHECK-NEXT: Fast Register Allocator -; CHECK-NEXT: MachineDominator Tree Construction ; CHECK-NEXT: Slot index numbering ; CHECK-NEXT: Live Interval Analysis ; CHECK-NEXT: RISC-V Coalesce VSETVLI pass diff --git a/llvm/test/CodeGen/RISCV/O3-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-pipeline.ll index 4a71d3276d26..52634b2a8162 100644 --- a/llvm/test/CodeGen/RISCV/O3-pipeline.ll +++ b/llvm/test/CodeGen/RISCV/O3-pipeline.ll @@ -117,7 +117,6 @@ ; CHECK-NEXT: RISC-V Merge Base Offset ; CHECK-NEXT: RISC-V Insert Read/Write CSR Pass ; CHECK-NEXT: RISC-V Insert Write VXRM Pass -; CHECK-NEXT: RISC-V Insert VSETVLI pass ; CHECK-NEXT: Detect Dead Lanes ; CHECK-NEXT: Init Undef Pass ; CHECK-NEXT: Process Implicit Definitions @@ -129,6 +128,7 @@ ; CHECK-NEXT: Slot index numbering ; CHECK-NEXT: Live Interval Analysis ; CHECK-NEXT: Register Coalescer +; CHECK-NEXT: RISC-V Insert VSETVLI pass ; CHECK-NEXT: Rename Disconnected Subregister Components ; CHECK-NEXT: Machine Instruction Scheduler ; CHECK-NEXT: Machine Block Frequency Analysis diff --git a/llvm/test/CodeGen/RISCV/rvv/combine-vmv.ll b/llvm/test/CodeGen/RISCV/rvv/combine-vmv.ll index 682ad5768672..61acf1afa94d 100644 --- a/llvm/test/CodeGen/RISCV/rvv/combine-vmv.ll +++ b/llvm/test/CodeGen/RISCV/rvv/combine-vmv.ll @@ -36,8 +36,8 @@ define @vadd_undef( %a, define @vadd_same_passthru( %passthru, %a, %b, iXLen %vl1, iXLen %vl2) { ; CHECK-LABEL: vadd_same_passthru: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli zero, a0, e32, m2, tu, ma ; CHECK-NEXT: vmv2r.v v14, v8 +; CHECK-NEXT: vsetvli zero, a0, e32, m2, tu, ma ; CHECK-NEXT: vadd.vv v14, v10, v12 ; CHECK-NEXT: vsetvli zero, a1, e32, m2, tu, ma ; CHECK-NEXT: vmv.v.v v8, v14 diff --git a/llvm/test/CodeGen/RISCV/rvv/concat-vectors-constant-stride.ll b/llvm/test/CodeGen/RISCV/rvv/concat-vectors-constant-stride.ll index ff35043dbd7e..c6b84209a875 100644 --- a/llvm/test/CodeGen/RISCV/rvv/concat-vectors-constant-stride.ll +++ b/llvm/test/CodeGen/RISCV/rvv/concat-vectors-constant-stride.ll @@ -149,8 +149,8 @@ define void @constant_zero_stride(ptr %s, ptr %d) { ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 2, e8, mf8, ta, ma ; CHECK-NEXT: vle8.v v8, (a0) -; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma ; CHECK-NEXT: vmv1r.v v9, v8 +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma ; CHECK-NEXT: vslideup.vi v9, v8, 2 ; CHECK-NEXT: vse8.v v9, (a1) ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/RISCV/rvv/dont-sink-splat-operands.ll b/llvm/test/CodeGen/RISCV/rvv/dont-sink-splat-operands.ll index dc4d28819bbb..2b4b8e979f3d 100644 --- a/llvm/test/CodeGen/RISCV/rvv/dont-sink-splat-operands.ll +++ b/llvm/test/CodeGen/RISCV/rvv/dont-sink-splat-operands.ll @@ -141,9 +141,9 @@ define void @sink_splat_add_scalable(ptr nocapture %a, i32 signext %x) { ; SINK-NEXT: andi a4, a3, 1024 ; SINK-NEXT: xori a3, a4, 1024 ; SINK-NEXT: slli a5, a5, 1 -; SINK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; SINK-NEXT: mv a6, a0 ; SINK-NEXT: mv a7, a3 +; SINK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; SINK-NEXT: .LBB1_3: # %vector.body ; SINK-NEXT: # =>This Inner Loop Header: Depth=1 ; SINK-NEXT: vl2re32.v v8, (a6) @@ -183,9 +183,9 @@ define void @sink_splat_add_scalable(ptr nocapture %a, i32 signext %x) { ; DEFAULT-NEXT: andi a4, a3, 1024 ; DEFAULT-NEXT: xori a3, a4, 1024 ; DEFAULT-NEXT: slli a5, a5, 1 -; DEFAULT-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; DEFAULT-NEXT: mv a6, a0 ; DEFAULT-NEXT: mv a7, a3 +; DEFAULT-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; DEFAULT-NEXT: .LBB1_3: # %vector.body ; DEFAULT-NEXT: # =>This Inner Loop Header: Depth=1 ; DEFAULT-NEXT: vl2re32.v v8, (a6) @@ -459,9 +459,9 @@ define void @sink_splat_fadd_scalable(ptr nocapture %a, float %x) { ; SINK-NEXT: addi a3, a2, -1 ; SINK-NEXT: andi a4, a3, 1024 ; SINK-NEXT: xori a3, a4, 1024 -; SINK-NEXT: vsetvli a5, zero, e32, m1, ta, ma ; SINK-NEXT: mv a5, a0 ; SINK-NEXT: mv a6, a3 +; SINK-NEXT: vsetvli a7, zero, e32, m1, ta, ma ; SINK-NEXT: .LBB4_3: # %vector.body ; SINK-NEXT: # =>This Inner Loop Header: Depth=1 ; SINK-NEXT: vl1re32.v v8, (a5) @@ -500,9 +500,9 @@ define void @sink_splat_fadd_scalable(ptr nocapture %a, float %x) { ; DEFAULT-NEXT: addi a3, a2, -1 ; DEFAULT-NEXT: andi a4, a3, 1024 ; DEFAULT-NEXT: xori a3, a4, 1024 -; DEFAULT-NEXT: vsetvli a5, zero, e32, m1, ta, ma ; DEFAULT-NEXT: mv a5, a0 ; DEFAULT-NEXT: mv a6, a3 +; DEFAULT-NEXT: vsetvli a7, zero, e32, m1, ta, ma ; DEFAULT-NEXT: .LBB4_3: # %vector.body ; DEFAULT-NEXT: # =>This Inner Loop Header: Depth=1 ; DEFAULT-NEXT: vl1re32.v v8, (a5) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int.ll index 03e99baf91c0..635869904832 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int.ll @@ -1155,8 +1155,8 @@ define void @mulhu_v8i16(ptr %x) { ; CHECK-NEXT: vle16.v v8, (a0) ; CHECK-NEXT: vmv.v.i v9, 0 ; CHECK-NEXT: lui a1, 1048568 -; CHECK-NEXT: vsetvli zero, zero, e16, m1, tu, ma ; CHECK-NEXT: vmv.v.i v10, 0 +; CHECK-NEXT: vsetvli zero, zero, e16, m1, tu, ma ; CHECK-NEXT: vmv.s.x v10, a1 ; CHECK-NEXT: vsetvli zero, zero, e16, m1, ta, ma ; CHECK-NEXT: vmv.v.i v11, 1 diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll index 539a8403c935..f42f32e24658 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll @@ -12092,8 +12092,8 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 x i8> %idxs, <32 x i1> %m ; RV64V: # %bb.0: ; RV64V-NEXT: vsetivli zero, 16, e64, m8, ta, ma ; RV64V-NEXT: vsext.vf8 v16, v8 -; RV64V-NEXT: vsetvli zero, zero, e8, m1, ta, mu ; RV64V-NEXT: vmv1r.v v12, v10 +; RV64V-NEXT: vsetvli zero, zero, e8, m1, ta, mu ; RV64V-NEXT: vluxei64.v v12, (a0), v16, v0.t ; RV64V-NEXT: vsetivli zero, 16, e8, m2, ta, ma ; RV64V-NEXT: vslidedown.vi v10, v10, 16 diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-vslide1up.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-vslide1up.ll index 175a3ee43f33..d1fb30c7daa3 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-vslide1up.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-vslide1up.ll @@ -369,8 +369,8 @@ define <4 x i8> @vslide1up_4xi8_neg_incorrect_insert3(<4 x i8> %v, i8 %b) { define <2 x i8> @vslide1up_4xi8_neg_length_changing(<4 x i8> %v, i8 %b) { ; CHECK-LABEL: vslide1up_4xi8_neg_length_changing: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 4, e8, m1, tu, ma ; CHECK-NEXT: vmv1r.v v9, v8 +; CHECK-NEXT: vsetivli zero, 4, e8, m1, tu, ma ; CHECK-NEXT: vmv.s.x v9, a0 ; CHECK-NEXT: vsetivli zero, 2, e8, mf8, ta, ma ; CHECK-NEXT: vslideup.vi v9, v8, 1 diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-combine.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-combine.ll index f0fcc482e220..0e6b03bf1632 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-combine.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-combine.ll @@ -168,8 +168,8 @@ define void @strided_constant_0(ptr %x, ptr %z) { ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma ; CHECK-NEXT: vle16.v v8, (a0) -; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma ; CHECK-NEXT: vmv1r.v v9, v8 +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma ; CHECK-NEXT: vslideup.vi v9, v8, 4 ; CHECK-NEXT: vse16.v v9, (a1) ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-store-asm.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-store-asm.ll index c38406bafa8a..64ad86db0495 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-store-asm.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-store-asm.ll @@ -62,8 +62,8 @@ define void @gather_masked(ptr noalias nocapture %A, ptr noalias nocapture reado ; CHECK-NEXT: li a4, 5 ; CHECK-NEXT: .LBB1_1: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: vsetvli zero, a3, e8, m1, ta, mu ; CHECK-NEXT: vmv1r.v v9, v8 +; CHECK-NEXT: vsetvli zero, a3, e8, m1, ta, mu ; CHECK-NEXT: vlse8.v v9, (a1), a4, v0.t ; CHECK-NEXT: vle8.v v10, (a0) ; CHECK-NEXT: vadd.vv v9, v10, v9 diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-trunc-vp.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-trunc-vp.ll index 4f16ce28bbb7..9fa8ab39723f 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-trunc-vp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-trunc-vp.ll @@ -394,7 +394,6 @@ define <128 x i32> @vtrunc_v128i32_v128i64(<128 x i64> %a, <128 x i1> %m, i32 ze ; CHECK-NEXT: # %bb.11: ; CHECK-NEXT: li a1, 32 ; CHECK-NEXT: .LBB16_12: -; CHECK-NEXT: vsetvli zero, a3, e32, m8, ta, ma ; CHECK-NEXT: csrr a4, vlenb ; CHECK-NEXT: li a5, 24 ; CHECK-NEXT: mul a4, a4, a5 @@ -402,6 +401,7 @@ define <128 x i32> @vtrunc_v128i32_v128i64(<128 x i64> %a, <128 x i1> %m, i32 ze ; CHECK-NEXT: addi a4, a4, 16 ; CHECK-NEXT: vl8r.v v8, (a4) # Unknown-size Folded Reload ; CHECK-NEXT: vmv4r.v v24, v8 +; CHECK-NEXT: vsetvli zero, a3, e32, m8, ta, ma ; CHECK-NEXT: csrr a4, vlenb ; CHECK-NEXT: li a5, 56 ; CHECK-NEXT: mul a4, a4, a5 diff --git a/llvm/test/CodeGen/RISCV/rvv/fold-scalar-load-crash.ll b/llvm/test/CodeGen/RISCV/rvv/fold-scalar-load-crash.ll index 79b1e14b774a..c8bed2de754b 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fold-scalar-load-crash.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fold-scalar-load-crash.ll @@ -15,8 +15,8 @@ define i32 @test(i32 %size, ptr %add.ptr, i64 %const) { ; RV32-NEXT: .LBB0_1: # %for.body ; RV32-NEXT: # =>This Inner Loop Header: Depth=1 ; RV32-NEXT: vmv.s.x v9, zero -; RV32-NEXT: vsetvli zero, a1, e8, mf2, tu, ma ; RV32-NEXT: vmv1r.v v10, v8 +; RV32-NEXT: vsetvli zero, a1, e8, mf2, tu, ma ; RV32-NEXT: vslideup.vx v10, v9, a2 ; RV32-NEXT: vsetivli zero, 8, e8, mf2, tu, ma ; RV32-NEXT: vmv.s.x v10, a0 @@ -40,8 +40,8 @@ define i32 @test(i32 %size, ptr %add.ptr, i64 %const) { ; RV64-NEXT: .LBB0_1: # %for.body ; RV64-NEXT: # =>This Inner Loop Header: Depth=1 ; RV64-NEXT: vmv.s.x v9, zero -; RV64-NEXT: vsetvli zero, a1, e8, mf2, tu, ma ; RV64-NEXT: vmv1r.v v10, v8 +; RV64-NEXT: vsetvli zero, a1, e8, mf2, tu, ma ; RV64-NEXT: vslideup.vx v10, v9, a2 ; RV64-NEXT: vsetivli zero, 8, e8, mf2, tu, ma ; RV64-NEXT: vmv.s.x v10, a0 diff --git a/llvm/test/CodeGen/RISCV/rvv/fpclamptosat_vec.ll b/llvm/test/CodeGen/RISCV/rvv/fpclamptosat_vec.ll index a6b2d3141f22..bb28ff5c6dc4 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fpclamptosat_vec.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fpclamptosat_vec.ll @@ -479,11 +479,11 @@ define <4 x i32> @stest_f16i32(<4 x half> %x) { ; CHECK-V-NEXT: addi a0, sp, 16 ; CHECK-V-NEXT: vl1r.v v8, (a0) # Unknown-size Folded Reload ; CHECK-V-NEXT: vslideup.vi v10, v8, 1 -; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: csrr a0, vlenb ; CHECK-V-NEXT: add a0, sp, a0 ; CHECK-V-NEXT: addi a0, a0, 16 ; CHECK-V-NEXT: vl2r.v v8, (a0) # Unknown-size Folded Reload +; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: vslideup.vi v10, v8, 2 ; CHECK-V-NEXT: vsetvli zero, zero, e32, m1, ta, ma ; CHECK-V-NEXT: vnclip.wi v8, v10, 0 @@ -640,11 +640,11 @@ define <4 x i32> @utesth_f16i32(<4 x half> %x) { ; CHECK-V-NEXT: addi a0, sp, 16 ; CHECK-V-NEXT: vl1r.v v8, (a0) # Unknown-size Folded Reload ; CHECK-V-NEXT: vslideup.vi v10, v8, 1 -; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: csrr a0, vlenb ; CHECK-V-NEXT: add a0, sp, a0 ; CHECK-V-NEXT: addi a0, a0, 16 ; CHECK-V-NEXT: vl2r.v v8, (a0) # Unknown-size Folded Reload +; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: vslideup.vi v10, v8, 2 ; CHECK-V-NEXT: vsetvli zero, zero, e32, m1, ta, ma ; CHECK-V-NEXT: vnclipu.wi v8, v10, 0 @@ -811,11 +811,11 @@ define <4 x i32> @ustest_f16i32(<4 x half> %x) { ; CHECK-V-NEXT: addi a0, sp, 16 ; CHECK-V-NEXT: vl1r.v v9, (a0) # Unknown-size Folded Reload ; CHECK-V-NEXT: vslideup.vi v8, v9, 1 -; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: csrr a0, vlenb ; CHECK-V-NEXT: add a0, sp, a0 ; CHECK-V-NEXT: addi a0, a0, 16 ; CHECK-V-NEXT: vl2r.v v10, (a0) # Unknown-size Folded Reload +; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: vslideup.vi v8, v10, 2 ; CHECK-V-NEXT: li a0, -1 ; CHECK-V-NEXT: srli a0, a0, 32 @@ -3850,11 +3850,11 @@ define <4 x i32> @stest_f16i32_mm(<4 x half> %x) { ; CHECK-V-NEXT: addi a0, sp, 16 ; CHECK-V-NEXT: vl1r.v v8, (a0) # Unknown-size Folded Reload ; CHECK-V-NEXT: vslideup.vi v10, v8, 1 -; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: csrr a0, vlenb ; CHECK-V-NEXT: add a0, sp, a0 ; CHECK-V-NEXT: addi a0, a0, 16 ; CHECK-V-NEXT: vl2r.v v8, (a0) # Unknown-size Folded Reload +; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: vslideup.vi v10, v8, 2 ; CHECK-V-NEXT: vsetvli zero, zero, e32, m1, ta, ma ; CHECK-V-NEXT: vnclip.wi v8, v10, 0 @@ -4009,11 +4009,11 @@ define <4 x i32> @utesth_f16i32_mm(<4 x half> %x) { ; CHECK-V-NEXT: addi a0, sp, 16 ; CHECK-V-NEXT: vl1r.v v8, (a0) # Unknown-size Folded Reload ; CHECK-V-NEXT: vslideup.vi v10, v8, 1 -; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: csrr a0, vlenb ; CHECK-V-NEXT: add a0, sp, a0 ; CHECK-V-NEXT: addi a0, a0, 16 ; CHECK-V-NEXT: vl2r.v v8, (a0) # Unknown-size Folded Reload +; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: vslideup.vi v10, v8, 2 ; CHECK-V-NEXT: vsetvli zero, zero, e32, m1, ta, ma ; CHECK-V-NEXT: vnclipu.wi v8, v10, 0 @@ -4179,11 +4179,11 @@ define <4 x i32> @ustest_f16i32_mm(<4 x half> %x) { ; CHECK-V-NEXT: addi a0, sp, 16 ; CHECK-V-NEXT: vl1r.v v9, (a0) # Unknown-size Folded Reload ; CHECK-V-NEXT: vslideup.vi v8, v9, 1 -; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: csrr a0, vlenb ; CHECK-V-NEXT: add a0, sp, a0 ; CHECK-V-NEXT: addi a0, a0, 16 ; CHECK-V-NEXT: vl2r.v v10, (a0) # Unknown-size Folded Reload +; CHECK-V-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-V-NEXT: vslideup.vi v8, v10, 2 ; CHECK-V-NEXT: li a0, -1 ; CHECK-V-NEXT: srli a0, a0, 32 diff --git a/llvm/test/CodeGen/RISCV/rvv/rv32-spill-vector-csr.ll b/llvm/test/CodeGen/RISCV/rvv/rv32-spill-vector-csr.ll index 129fbcfb8832..e73415ac0085 100644 --- a/llvm/test/CodeGen/RISCV/rvv/rv32-spill-vector-csr.ll +++ b/llvm/test/CodeGen/RISCV/rvv/rv32-spill-vector-csr.ll @@ -21,8 +21,8 @@ define @foo( %a, @foo( %a, @spill_zvlsseg_nxv1i32(ptr %base, i32 %vl) nounwind { ; SPILL-O0-NEXT: csrr a2, vlenb ; SPILL-O0-NEXT: slli a2, a2, 1 ; SPILL-O0-NEXT: sub sp, sp, a2 -; SPILL-O0-NEXT: vsetvli zero, a1, e32, mf2, ta, ma ; SPILL-O0-NEXT: # implicit-def: $v8_v9 +; SPILL-O0-NEXT: vsetvli zero, a1, e32, mf2, tu, ma ; SPILL-O0-NEXT: vlseg2e32.v v8, (a0) ; SPILL-O0-NEXT: vmv1r.v v8, v9 ; SPILL-O0-NEXT: addi a0, sp, 16 @@ -90,8 +90,8 @@ define @spill_zvlsseg_nxv2i32(ptr %base, i32 %vl) nounwind { ; SPILL-O0-NEXT: csrr a2, vlenb ; SPILL-O0-NEXT: slli a2, a2, 1 ; SPILL-O0-NEXT: sub sp, sp, a2 -; SPILL-O0-NEXT: vsetvli zero, a1, e32, m1, ta, ma ; SPILL-O0-NEXT: # implicit-def: $v8_v9 +; SPILL-O0-NEXT: vsetvli zero, a1, e32, m1, tu, ma ; SPILL-O0-NEXT: vlseg2e32.v v8, (a0) ; SPILL-O0-NEXT: vmv1r.v v8, v9 ; SPILL-O0-NEXT: addi a0, sp, 16 @@ -167,8 +167,8 @@ define @spill_zvlsseg_nxv4i32(ptr %base, i32 %vl) nounwind { ; SPILL-O0-NEXT: csrr a2, vlenb ; SPILL-O0-NEXT: slli a2, a2, 1 ; SPILL-O0-NEXT: sub sp, sp, a2 -; SPILL-O0-NEXT: vsetvli zero, a1, e32, m2, ta, ma ; SPILL-O0-NEXT: # implicit-def: $v8m2_v10m2 +; SPILL-O0-NEXT: vsetvli zero, a1, e32, m2, tu, ma ; SPILL-O0-NEXT: vlseg2e32.v v8, (a0) ; SPILL-O0-NEXT: vmv2r.v v8, v10 ; SPILL-O0-NEXT: addi a0, sp, 16 @@ -247,8 +247,8 @@ define @spill_zvlsseg_nxv8i32(ptr %base, i32 %vl) nounwind { ; SPILL-O0-NEXT: csrr a2, vlenb ; SPILL-O0-NEXT: slli a2, a2, 2 ; SPILL-O0-NEXT: sub sp, sp, a2 -; SPILL-O0-NEXT: vsetvli zero, a1, e32, m4, ta, ma ; SPILL-O0-NEXT: # implicit-def: $v8m4_v12m4 +; SPILL-O0-NEXT: vsetvli zero, a1, e32, m4, tu, ma ; SPILL-O0-NEXT: vlseg2e32.v v8, (a0) ; SPILL-O0-NEXT: vmv4r.v v8, v12 ; SPILL-O0-NEXT: addi a0, sp, 16 @@ -327,8 +327,8 @@ define @spill_zvlsseg3_nxv4i32(ptr %base, i32 %vl) nounwind { ; SPILL-O0-NEXT: csrr a2, vlenb ; SPILL-O0-NEXT: slli a2, a2, 1 ; SPILL-O0-NEXT: sub sp, sp, a2 -; SPILL-O0-NEXT: vsetvli zero, a1, e32, m2, ta, ma ; SPILL-O0-NEXT: # implicit-def: $v8m2_v10m2_v12m2 +; SPILL-O0-NEXT: vsetvli zero, a1, e32, m2, tu, ma ; SPILL-O0-NEXT: vlseg3e32.v v8, (a0) ; SPILL-O0-NEXT: vmv2r.v v8, v10 ; SPILL-O0-NEXT: addi a0, sp, 16 diff --git a/llvm/test/CodeGen/RISCV/rvv/rv64-spill-vector-csr.ll b/llvm/test/CodeGen/RISCV/rvv/rv64-spill-vector-csr.ll index 34eb58ee4d1c..483f689cf633 100644 --- a/llvm/test/CodeGen/RISCV/rvv/rv64-spill-vector-csr.ll +++ b/llvm/test/CodeGen/RISCV/rvv/rv64-spill-vector-csr.ll @@ -24,8 +24,8 @@ define @foo( %a, @foo( %a, @spill_zvlsseg_nxv1i32(ptr %base, i64 %vl) nounwind { ; SPILL-O0-NEXT: csrr a2, vlenb ; SPILL-O0-NEXT: slli a2, a2, 1 ; SPILL-O0-NEXT: sub sp, sp, a2 -; SPILL-O0-NEXT: vsetvli zero, a1, e32, mf2, ta, ma ; SPILL-O0-NEXT: # implicit-def: $v8_v9 +; SPILL-O0-NEXT: vsetvli zero, a1, e32, mf2, tu, ma ; SPILL-O0-NEXT: vlseg2e32.v v8, (a0) ; SPILL-O0-NEXT: vmv1r.v v8, v9 ; SPILL-O0-NEXT: addi a0, sp, 16 @@ -90,8 +90,8 @@ define @spill_zvlsseg_nxv2i32(ptr %base, i64 %vl) nounwind { ; SPILL-O0-NEXT: csrr a2, vlenb ; SPILL-O0-NEXT: slli a2, a2, 1 ; SPILL-O0-NEXT: sub sp, sp, a2 -; SPILL-O0-NEXT: vsetvli zero, a1, e32, m1, ta, ma ; SPILL-O0-NEXT: # implicit-def: $v8_v9 +; SPILL-O0-NEXT: vsetvli zero, a1, e32, m1, tu, ma ; SPILL-O0-NEXT: vlseg2e32.v v8, (a0) ; SPILL-O0-NEXT: vmv1r.v v8, v9 ; SPILL-O0-NEXT: addi a0, sp, 16 @@ -167,8 +167,8 @@ define @spill_zvlsseg_nxv4i32(ptr %base, i64 %vl) nounwind { ; SPILL-O0-NEXT: csrr a2, vlenb ; SPILL-O0-NEXT: slli a2, a2, 1 ; SPILL-O0-NEXT: sub sp, sp, a2 -; SPILL-O0-NEXT: vsetvli zero, a1, e32, m2, ta, ma ; SPILL-O0-NEXT: # implicit-def: $v8m2_v10m2 +; SPILL-O0-NEXT: vsetvli zero, a1, e32, m2, tu, ma ; SPILL-O0-NEXT: vlseg2e32.v v8, (a0) ; SPILL-O0-NEXT: vmv2r.v v8, v10 ; SPILL-O0-NEXT: addi a0, sp, 16 @@ -247,8 +247,8 @@ define @spill_zvlsseg_nxv8i32(ptr %base, i64 %vl) nounwind { ; SPILL-O0-NEXT: csrr a2, vlenb ; SPILL-O0-NEXT: slli a2, a2, 2 ; SPILL-O0-NEXT: sub sp, sp, a2 -; SPILL-O0-NEXT: vsetvli zero, a1, e32, m4, ta, ma ; SPILL-O0-NEXT: # implicit-def: $v8m4_v12m4 +; SPILL-O0-NEXT: vsetvli zero, a1, e32, m4, tu, ma ; SPILL-O0-NEXT: vlseg2e32.v v8, (a0) ; SPILL-O0-NEXT: vmv4r.v v8, v12 ; SPILL-O0-NEXT: addi a0, sp, 16 @@ -327,8 +327,8 @@ define @spill_zvlsseg3_nxv4i32(ptr %base, i64 %vl) nounwind { ; SPILL-O0-NEXT: csrr a2, vlenb ; SPILL-O0-NEXT: slli a2, a2, 1 ; SPILL-O0-NEXT: sub sp, sp, a2 -; SPILL-O0-NEXT: vsetvli zero, a1, e32, m2, ta, ma ; SPILL-O0-NEXT: # implicit-def: $v8m2_v10m2_v12m2 +; SPILL-O0-NEXT: vsetvli zero, a1, e32, m2, tu, ma ; SPILL-O0-NEXT: vlseg3e32.v v8, (a0) ; SPILL-O0-NEXT: vmv2r.v v8, v10 ; SPILL-O0-NEXT: addi a0, sp, 16 diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll index 1a3a1a6c1ee6..743016a7cbcd 100644 --- a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll @@ -893,10 +893,10 @@ define void @test_dag_loop() { ; CHECK-LABEL: test_dag_loop: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vsetvli a0, zero, e8, m4, ta, ma -; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: vmv.v.i v8, 0 +; CHECK-NEXT: vmclr.m v0 +; CHECK-NEXT: vmv.v.i v12, 0 ; CHECK-NEXT: vsetivli zero, 0, e8, m4, tu, mu -; CHECK-NEXT: vmv4r.v v12, v8 ; CHECK-NEXT: vssubu.vx v12, v8, zero, v0.t ; CHECK-NEXT: vsetvli zero, zero, e8, m4, ta, ma ; CHECK-NEXT: vmseq.vv v0, v12, v8 @@ -942,8 +942,8 @@ declare @llvm.riscv.vredsum.nxv2i32.nxv2i32( define @vredsum( %passthru, %x, %y, %m, i64 %vl) { ; CHECK-LABEL: vredsum: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli zero, a0, e32, m1, ta, ma ; CHECK-NEXT: vmv1r.v v11, v8 +; CHECK-NEXT: vsetvli zero, a0, e32, m1, ta, ma ; CHECK-NEXT: vredsum.vs v11, v9, v10 ; CHECK-NEXT: vsetvli zero, zero, e32, m1, tu, ma ; CHECK-NEXT: vmerge.vvm v8, v8, v11, v0 @@ -967,8 +967,8 @@ define @vfredusum( %passthru, This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -346,9 +346,9 @@ define void @sink_splat_add_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB8_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -437,9 +437,9 @@ define void @sink_splat_sub_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB9_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -528,9 +528,9 @@ define void @sink_splat_rsub_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB10_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -619,9 +619,9 @@ define void @sink_splat_and_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB11_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -710,9 +710,9 @@ define void @sink_splat_or_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB12_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -801,9 +801,9 @@ define void @sink_splat_xor_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB13_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -994,9 +994,9 @@ define void @sink_splat_shl_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB17_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -1085,9 +1085,9 @@ define void @sink_splat_lshr_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB18_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -1176,9 +1176,9 @@ define void @sink_splat_ashr_scalable(ptr nocapture %a) { ; CHECK-NEXT: andi a3, a1, 1024 ; CHECK-NEXT: xori a1, a3, 1024 ; CHECK-NEXT: slli a4, a4, 1 -; CHECK-NEXT: vsetvli a5, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a5, a0 ; CHECK-NEXT: mv a6, a1 +; CHECK-NEXT: vsetvli a7, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB19_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a5) @@ -1468,9 +1468,9 @@ define void @sink_splat_fmul_scalable(ptr nocapture %a, float %x) { ; CHECK-NEXT: addi a3, a2, -1 ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 -; CHECK-NEXT: vsetvli a5, zero, e32, m1, ta, ma ; CHECK-NEXT: mv a5, a0 ; CHECK-NEXT: mv a6, a3 +; CHECK-NEXT: vsetvli a7, zero, e32, m1, ta, ma ; CHECK-NEXT: .LBB26_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl1re32.v v8, (a5) @@ -1558,9 +1558,9 @@ define void @sink_splat_fdiv_scalable(ptr nocapture %a, float %x) { ; CHECK-NEXT: addi a3, a2, -1 ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 -; CHECK-NEXT: vsetvli a5, zero, e32, m1, ta, ma ; CHECK-NEXT: mv a5, a0 ; CHECK-NEXT: mv a6, a3 +; CHECK-NEXT: vsetvli a7, zero, e32, m1, ta, ma ; CHECK-NEXT: .LBB27_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl1re32.v v8, (a5) @@ -1648,9 +1648,9 @@ define void @sink_splat_frdiv_scalable(ptr nocapture %a, float %x) { ; CHECK-NEXT: addi a3, a2, -1 ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 -; CHECK-NEXT: vsetvli a5, zero, e32, m1, ta, ma ; CHECK-NEXT: mv a5, a0 ; CHECK-NEXT: mv a6, a3 +; CHECK-NEXT: vsetvli a7, zero, e32, m1, ta, ma ; CHECK-NEXT: .LBB28_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl1re32.v v8, (a5) @@ -1738,9 +1738,9 @@ define void @sink_splat_fadd_scalable(ptr nocapture %a, float %x) { ; CHECK-NEXT: addi a3, a2, -1 ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 -; CHECK-NEXT: vsetvli a5, zero, e32, m1, ta, ma ; CHECK-NEXT: mv a5, a0 ; CHECK-NEXT: mv a6, a3 +; CHECK-NEXT: vsetvli a7, zero, e32, m1, ta, ma ; CHECK-NEXT: .LBB29_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl1re32.v v8, (a5) @@ -1828,9 +1828,9 @@ define void @sink_splat_fsub_scalable(ptr nocapture %a, float %x) { ; CHECK-NEXT: addi a3, a2, -1 ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 -; CHECK-NEXT: vsetvli a5, zero, e32, m1, ta, ma ; CHECK-NEXT: mv a5, a0 ; CHECK-NEXT: mv a6, a3 +; CHECK-NEXT: vsetvli a7, zero, e32, m1, ta, ma ; CHECK-NEXT: .LBB30_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl1re32.v v8, (a5) @@ -1918,9 +1918,9 @@ define void @sink_splat_frsub_scalable(ptr nocapture %a, float %x) { ; CHECK-NEXT: addi a3, a2, -1 ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 -; CHECK-NEXT: vsetvli a5, zero, e32, m1, ta, ma ; CHECK-NEXT: mv a5, a0 ; CHECK-NEXT: mv a6, a3 +; CHECK-NEXT: vsetvli a7, zero, e32, m1, ta, ma ; CHECK-NEXT: .LBB31_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl1re32.v v8, (a5) @@ -2084,10 +2084,10 @@ define void @sink_splat_fma_scalable(ptr noalias nocapture %a, ptr noalias nocap ; CHECK-NEXT: addi a4, a3, -1 ; CHECK-NEXT: andi a5, a4, 1024 ; CHECK-NEXT: xori a4, a5, 1024 -; CHECK-NEXT: vsetvli a6, zero, e32, m1, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a1 ; CHECK-NEXT: mv t0, a4 +; CHECK-NEXT: vsetvli t1, zero, e32, m1, ta, ma ; CHECK-NEXT: .LBB34_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl1re32.v v8, (a6) @@ -2184,10 +2184,10 @@ define void @sink_splat_fma_commute_scalable(ptr noalias nocapture %a, ptr noali ; CHECK-NEXT: addi a4, a3, -1 ; CHECK-NEXT: andi a5, a4, 1024 ; CHECK-NEXT: xori a4, a5, 1024 -; CHECK-NEXT: vsetvli a6, zero, e32, m1, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a1 ; CHECK-NEXT: mv t0, a4 +; CHECK-NEXT: vsetvli t1, zero, e32, m1, ta, ma ; CHECK-NEXT: .LBB35_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl1re32.v v8, (a6) @@ -2498,9 +2498,9 @@ define void @sink_splat_udiv_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB42_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -2589,9 +2589,9 @@ define void @sink_splat_sdiv_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB43_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -2680,9 +2680,9 @@ define void @sink_splat_urem_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB44_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) @@ -2771,9 +2771,9 @@ define void @sink_splat_srem_scalable(ptr nocapture %a, i32 signext %x) { ; CHECK-NEXT: andi a4, a3, 1024 ; CHECK-NEXT: xori a3, a4, 1024 ; CHECK-NEXT: slli a5, a5, 1 -; CHECK-NEXT: vsetvli a6, zero, e32, m2, ta, ma ; CHECK-NEXT: mv a6, a0 ; CHECK-NEXT: mv a7, a3 +; CHECK-NEXT: vsetvli t0, zero, e32, m2, ta, ma ; CHECK-NEXT: .LBB45_3: # %vector.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vl2re32.v v8, (a6) diff --git a/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.ll b/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.ll index f41a3ec72aed..48c30596ad51 100644 --- a/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.ll +++ b/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.ll @@ -161,8 +161,8 @@ declare @llvm.riscv.vrgatherei16.vv.nxv8i8.i64( %v, ptr noalias %q) { ; CHECK-LABEL: repeat_shuffle: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-NEXT: vmv2r.v v10, v8 +; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma ; CHECK-NEXT: vslideup.vi v10, v8, 2 ; CHECK-NEXT: vse64.v v10, (a0) ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/RISCV/rvv/unmasked-tu.ll b/llvm/test/CodeGen/RISCV/rvv/unmasked-tu.ll index 25e3468dcb62..439301ff4011 100644 --- a/llvm/test/CodeGen/RISCV/rvv/unmasked-tu.ll +++ b/llvm/test/CodeGen/RISCV/rvv/unmasked-tu.ll @@ -711,8 +711,8 @@ define @intrinsic_vslide1down_vx_nxv1i64_nxv1i64_i64( @intrinsic_vslide1up_vx_nxv1i64_nxv1i64_i64( @vadd_vv_passthru( %0, %1, i32 %2) nounwind { ; CHECK-LABEL: vadd_vv_passthru: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: vsetvli zero, a0, e8, mf8, tu, ma ; CHECK-NEXT: vmv1r.v v10, v8 +; CHECK-NEXT: vsetvli zero, a0, e8, mf8, tu, ma ; CHECK-NEXT: vadd.vv v10, v8, v9 ; CHECK-NEXT: vmv1r.v v9, v8 ; CHECK-NEXT: vadd.vv v9, v8, v8 @@ -152,8 +152,8 @@ entry: define @vadd_vv_passthru_negative( %0, %1, i32 %2) nounwind { ; CHECK-LABEL: vadd_vv_passthru_negative: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: vsetvli zero, a0, e8, mf8, tu, ma ; CHECK-NEXT: vmv1r.v v10, v8 +; CHECK-NEXT: vsetvli zero, a0, e8, mf8, tu, ma ; CHECK-NEXT: vadd.vv v10, v8, v9 ; CHECK-NEXT: vadd.vv v9, v8, v10 ; CHECK-NEXT: vadd.vv v8, v8, v9 @@ -183,8 +183,8 @@ entry: define @vadd_vv_mask( %0, %1, i32 %2, %m) nounwind { ; CHECK-LABEL: vadd_vv_mask: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, mu ; CHECK-NEXT: vmv1r.v v10, v8 +; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, mu ; CHECK-NEXT: vadd.vv v10, v8, v9, v0.t ; CHECK-NEXT: vmv1r.v v9, v8 ; CHECK-NEXT: vadd.vv v9, v8, v8, v0.t @@ -218,8 +218,8 @@ entry: define @vadd_vv_mask_negative( %0, %1, i32 %2, %m, %m2) nounwind { ; CHECK-LABEL: vadd_vv_mask_negative: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, mu ; CHECK-NEXT: vmv1r.v v11, v8 +; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, mu ; CHECK-NEXT: vadd.vv v11, v8, v9, v0.t ; CHECK-NEXT: vmv1r.v v9, v8 ; CHECK-NEXT: vadd.vv v9, v8, v11, v0.t diff --git a/llvm/test/CodeGen/RISCV/rvv/vfwmacc-vp.ll b/llvm/test/CodeGen/RISCV/rvv/vfwmacc-vp.ll index fab76ac56458..78f3792dbaf0 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vfwmacc-vp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vfwmacc-vp.ll @@ -85,8 +85,8 @@ define @vfmacc_vv_nxv1f32_tu( %a, @vfmacc_vv_nxv1f32_masked__tu( %a, %b, %c, %m, i32 zeroext %evl) { ; ZVFH-LABEL: vfmacc_vv_nxv1f32_masked__tu: ; ZVFH: # %bb.0: -; ZVFH-NEXT: vsetvli zero, a0, e16, mf4, ta, ma ; ZVFH-NEXT: vmv1r.v v11, v10 +; ZVFH-NEXT: vsetvli zero, a0, e16, mf4, ta, ma ; ZVFH-NEXT: vfwmacc.vv v11, v8, v9, v0.t ; ZVFH-NEXT: vsetvli zero, zero, e32, mf2, tu, ma ; ZVFH-NEXT: vmerge.vvm v10, v10, v11, v0 diff --git a/llvm/test/CodeGen/RISCV/rvv/vrgatherei16-subreg-liveness.ll b/llvm/test/CodeGen/RISCV/rvv/vrgatherei16-subreg-liveness.ll index 0c0a3dc9675b..462d49991ae4 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vrgatherei16-subreg-liveness.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vrgatherei16-subreg-liveness.ll @@ -16,14 +16,14 @@ define internal void @foo( %v15, %0, This Inner Loop Header: Depth=1 ; NOSUBREG-NEXT: vl1r.v v9, (zero) -; NOSUBREG-NEXT: vsetivli zero, 4, e8, m1, tu, ma ; NOSUBREG-NEXT: vmv1r.v v13, v12 +; NOSUBREG-NEXT: vsetivli zero, 4, e8, m1, tu, ma ; NOSUBREG-NEXT: vrgatherei16.vv v13, v9, v10 ; NOSUBREG-NEXT: vsetvli a0, zero, e8, m1, ta, ma ; NOSUBREG-NEXT: vand.vv v9, v8, v13 @@ -36,14 +36,14 @@ define internal void @foo( %v15, %0, This Inner Loop Header: Depth=1 ; SUBREG-NEXT: vl1r.v v9, (zero) -; SUBREG-NEXT: vsetivli zero, 4, e8, m1, tu, ma ; SUBREG-NEXT: vmv1r.v v13, v12 +; SUBREG-NEXT: vsetivli zero, 4, e8, m1, tu, ma ; SUBREG-NEXT: vrgatherei16.vv v13, v9, v10 ; SUBREG-NEXT: vsetvli a0, zero, e8, m1, ta, ma ; SUBREG-NEXT: vand.vv v9, v8, v13 diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-crossbb.ll b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-crossbb.ll index 088d121564bc..25aa3a7081a1 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-crossbb.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-crossbb.ll @@ -91,13 +91,11 @@ define @test3(i64 %avl, i8 zeroext %cond, @test18( %a, double %b) nounwind { ; CHECK-LABEL: test18: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: vsetivli zero, 6, e64, m1, tu, ma -; CHECK-NEXT: vmv1r.v v9, v8 -; CHECK-NEXT: vfmv.s.f v9, fa0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vfadd.vv v8, v8, v8 +; CHECK-NEXT: vsetivli zero, 6, e64, m1, ta, ma +; CHECK-NEXT: vfadd.vv v9, v8, v8 ; CHECK-NEXT: vsetvli zero, zero, e64, m1, tu, ma ; CHECK-NEXT: vfmv.s.f v8, fa0 +; CHECK-NEXT: vfmv.s.f v9, fa0 ; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vfadd.vv v8, v9, v8 +; CHECK-NEXT: vfadd.vv v8, v8, v9 ; CHECK-NEXT: ret entry: %x = tail call i64 @llvm.riscv.vsetvli(i64 6, i64 3, i64 0) @@ -380,8 +378,8 @@ entry: define @test19( %a, double %b) nounwind { ; CHECK-LABEL: test19: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: vsetivli zero, 2, e64, m1, tu, ma ; CHECK-NEXT: vmv1r.v v9, v8 +; CHECK-NEXT: vsetivli zero, 2, e64, m1, tu, ma ; CHECK-NEXT: vfmv.s.f v9, fa0 ; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma ; CHECK-NEXT: vfadd.vv v8, v9, v8 -- GitLab From a71e2b9d0f287e4927e51d6764f90e492ba136e1 Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Wed, 15 May 2024 06:02:46 +0200 Subject: [PATCH 301/578] [libc][errno] Remove non asm generic error number (#92172) The following small thing caught my eye: 1) `EILSEQ` is not part of the generic asm error number macros. See the [full list of generic asm errno codes](https://github.com/torvalds/linux/blob/4b95dc87362aa57bdd0dcbad109ca5e5ef3cbb6c/include/uapi/asm-generic/errno-base.h). AFAIK the generic asm errno numbers are common between different operating systems and architectures. `EILSEQ` is not part of this common set of errno's. 2) `EILSEQ`'s value is wrong. During the addition of `EILSEQ` in https://reviews.llvm.org/D151129, the value `35` was probably chosen as its the consecutive number. This is not correct. The actual values can be looked up for example here: * [For Linux kernel](https://github.com/search?q=repo%3Atorvalds%2Flinux+EILSEQ&type=code&p=1): `EILSEQ = 84` (uapi; i.e. x86_64), `EILSEQ = 88` (mips), `EILSEQ = 47` (parisc) * [For Darwin kernel](https://github.com/apple-oss-distributions/xnu/blob/main/bsd/sys/errno.h#L237): `EILSEQ = 92` --- libc/include/llvm-libc-macros/generic-error-number-macros.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libc/include/llvm-libc-macros/generic-error-number-macros.h b/libc/include/llvm-libc-macros/generic-error-number-macros.h index b5b1b676dacc..cb4411fbac66 100644 --- a/libc/include/llvm-libc-macros/generic-error-number-macros.h +++ b/libc/include/llvm-libc-macros/generic-error-number-macros.h @@ -43,7 +43,6 @@ #define EPIPE 32 #define EDOM 33 #define ERANGE 34 -#define EILSEQ 35 #define ENAMETOOLONG 36 #define EOVERFLOW 75 -- GitLab From d3455f4ddd16811401fa153298fadd2f59f6914e Mon Sep 17 00:00:00 2001 From: Cyuria <55673467+cyuria@users.noreply.github.com> Date: Wed, 15 May 2024 14:13:05 +1000 Subject: [PATCH 302/578] [libc][docs] Fix outdated code review section, as per #91934 (#92051) As in the title, fixes #91934 --- libc/src/math/docs/add_math_function.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libc/src/math/docs/add_math_function.md b/libc/src/math/docs/add_math_function.md index d1bca222b428..9c23b8ca789b 100644 --- a/libc/src/math/docs/add_math_function.md +++ b/libc/src/math/docs/add_math_function.md @@ -196,7 +196,8 @@ implementation (which is very often glibc). ## Code reviews -We follow the code review process of LLVM with Phabricator: +We use GitHub's inbuilt pull request system for code review: ``` - https://llvm.org/docs/Phabricator.html + https://docs.github.com/articles/about-collaborative-development-models + https://docs.github.com/articles/about-pull-requests ``` -- GitLab From 77047e3cd2edd2b870982fc92f505cbb7fd764cd Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Wed, 15 May 2024 12:32:26 +0800 Subject: [PATCH 303/578] [RISCV] Make vsetvli in test not loop invariant. NFC (#92094) The middle end will remove the inner vsetvli otherwise, and it's more typical to set the AVL to the remaining VL. This also prevents the test from showing up as a regression in #91319 --- llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll index 5b09aaedd975..12bb4d27b0f9 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll @@ -102,23 +102,23 @@ declare @llvm.riscv.vmand.nxv1i1.i64(, This Inner Loop Header: Depth=1 -; CHECK-NEXT: slli a3, a4, 2 -; CHECK-NEXT: add a5, a0, a3 +; CHECK-NEXT: slli a4, a3, 2 +; CHECK-NEXT: add a5, a0, a4 ; CHECK-NEXT: vle32.v v8, (a5) ; CHECK-NEXT: vmsle.vi v9, v8, -3 ; CHECK-NEXT: vmsgt.vi v10, v8, 2 ; CHECK-NEXT: vmor.mm v0, v9, v10 -; CHECK-NEXT: add a3, a3, a1 -; CHECK-NEXT: vse32.v v8, (a3), v0.t -; CHECK-NEXT: add a4, a4, a6 -; CHECK-NEXT: vsetvli a6, a2, e32, m1, ta, ma -; CHECK-NEXT: bnez a6, .LBB5_2 +; CHECK-NEXT: add a4, a4, a1 +; CHECK-NEXT: vse32.v v8, (a4), v0.t +; CHECK-NEXT: add a3, a3, a2 +; CHECK-NEXT: vsetvli a2, a2, e32, m1, ta, ma +; CHECK-NEXT: bnez a2, .LBB5_2 ; CHECK-NEXT: .LBB5_3: # %for.cond.cleanup ; CHECK-NEXT: ret entry: @@ -142,7 +142,7 @@ for.body: ; preds = %entry, %for.body %7 = bitcast ptr %add.ptr1 to ptr tail call void @llvm.riscv.vse.mask.nxv2i32.i64( %3, ptr %7, %6, i64 %1) %add = add i64 %1, %i.012 - %8 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %n, i64 2, i64 0) + %8 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %1, i64 2, i64 0) %cmp.not = icmp eq i64 %8, 0 br i1 %cmp.not, label %for.cond.cleanup, label %for.body } -- GitLab From 74d91d9acebdbc81306c8a0ee547002e7e8084f9 Mon Sep 17 00:00:00 2001 From: rahulana-quic Date: Wed, 15 May 2024 10:17:31 +0530 Subject: [PATCH 304/578] [polly] Port polly tests to use NPM (#90632) Even as the NPM has been in use by Polly for a while now, the majority of the tests continue using the LPM passes. This patch ports the tests to use the NPM passes (for example, by replacing a flag such as -polly-detect with -passes=polly-detect following the NPM syntax for specifying passes) with some exceptions for some missing features in the new passes. Additionally, the lit substitution %loadPolly is replaced by the substitution of what was %loadNPMPolly and %loadNPMPolly is removed. --- polly/test/CodeGen/20100617.ll | 2 +- polly/test/CodeGen/20100622.ll | 4 +- polly/test/CodeGen/20100707.ll | 2 +- polly/test/CodeGen/20100707_2.ll | 2 +- polly/test/CodeGen/20100708.ll | 2 +- polly/test/CodeGen/20100708_2.ll | 2 +- polly/test/CodeGen/20100713.ll | 2 +- polly/test/CodeGen/20100713_2.ll | 2 +- polly/test/CodeGen/20100717.ll | 2 +- polly/test/CodeGen/20100718-DomInfo-2.ll | 2 +- polly/test/CodeGen/20100718-DomInfo.ll | 2 +- .../CodeGen/20100720-MultipleConditions.ll | 2 +- .../test/CodeGen/20100809-IndependentBlock.ll | 2 +- ...0100811-ScalarDependencyBetweenBrAndCnd.ll | 2 +- polly/test/CodeGen/20101030-Overflow.ll | 2 +- polly/test/CodeGen/20101103-Overflow3.ll | 2 +- polly/test/CodeGen/20101103-signmissmatch.ll | 2 +- .../test/CodeGen/20110226-Ignore-Dead-Code.ll | 2 +- .../test/CodeGen/20110226-PHI-Node-removed.ll | 2 +- polly/test/CodeGen/20120316-InvalidCast.ll | 2 +- .../CodeGen/20120403-RHS-type-mismatch.ll | 2 +- polly/test/CodeGen/20130221.ll | 2 +- .../20150328-SCEVExpanderIntroducesNewIV.ll | 2 +- polly/test/CodeGen/Intrinsics/llvm-expect.ll | 2 +- .../do_not_mutate_debug_info.ll | 2 +- .../loop_nest_param_parallel.ll | 2 +- .../single_loop_param_parallel.ll | 4 +- polly/test/CodeGen/MemAccess/bad_alignment.ll | 2 +- .../MemAccess/codegen_address_space.ll | 2 +- .../MemAccess/codegen_constant_offset.ll | 2 +- .../test/CodeGen/MemAccess/codegen_simple.ll | 2 +- .../CodeGen/MemAccess/codegen_simple_float.ll | 2 +- .../CodeGen/MemAccess/codegen_simple_md.ll | 4 +- .../MemAccess/codegen_simple_md_float.ll | 4 +- .../test/CodeGen/MemAccess/different_types.ll | 4 +- polly/test/CodeGen/MemAccess/generate-all.ll | 4 +- .../CodeGen/MemAccess/invariant_base_ptr.ll | 4 +- .../test/CodeGen/MemAccess/multiple_types.ll | 4 +- polly/test/CodeGen/MemAccess/simple.ll | 2 +- .../MemAccess/update_access_functions.ll | 4 +- polly/test/CodeGen/OpenMP/alias-metadata.ll | 2 +- .../floord-as-argument-to-subfunction.ll | 2 +- polly/test/CodeGen/OpenMP/inlineasm.ll | 2 +- .../invariant_base_pointer_preloaded.ll | 2 +- ...ant_base_pointer_preloaded_different_bb.ll | 2 +- ...base_pointer_preloaded_pass_only_needed.ll | 2 +- .../invariant_base_pointers_preloaded.ll | 2 +- .../OpenMP/loop-body-references-outer-iv.ll | 4 +- .../loop-body-references-outer-values-2.ll | 4 +- .../loop-body-references-outer-values-3.ll | 4 +- .../loop-body-references-outer-values.ll | 4 +- .../OpenMP/loop-bounds-reference-outer-ids.ll | 4 +- .../test/CodeGen/OpenMP/mapped-phi-access.ll | 2 +- polly/test/CodeGen/OpenMP/matmul-parallel.ll | 4 +- polly/test/CodeGen/OpenMP/recomputed-srem.ll | 2 +- ...ference-argument-from-non-affine-region.ll | 6 +- .../test/CodeGen/OpenMP/reference-other-bb.ll | 2 +- .../OpenMP/reference-preceeding-loop.ll | 4 +- polly/test/CodeGen/OpenMP/reference_latest.ll | 2 +- polly/test/CodeGen/OpenMP/scev-rewriting.ll | 2 +- polly/test/CodeGen/OpenMP/single_loop.ll | 18 ++--- ...single_loop_with_loop_invariant_baseptr.ll | 4 +- .../CodeGen/OpenMP/single_loop_with_param.ll | 6 +- ...o-parallel-loops-reference-outer-indvar.ll | 4 +- polly/test/CodeGen/PHIInExit.ll | 2 +- .../combine_different_values.ll | 2 +- .../RuntimeDebugBuilder/stmt_tracing.ll | 2 +- polly/test/CodeGen/alias-check-multi-dim.ll | 2 +- .../CodeGen/alias_metadata_too_many_arrays.ll | 2 +- ...aliasing_different_base_and_access_type.ll | 2 +- .../aliasing_different_pointer_types.ll | 2 +- .../aliasing_multidimensional_access.ll | 2 +- .../CodeGen/aliasing_parametric_simple_1.ll | 2 +- .../CodeGen/aliasing_parametric_simple_2.ll | 2 +- polly/test/CodeGen/aliasing_struct_element.ll | 2 +- polly/test/CodeGen/alignment.ll | 2 +- polly/test/CodeGen/annotated_alias_scopes.ll | 2 +- polly/test/CodeGen/blas_sscal_simplified.ll | 2 +- ...code-hosting-and-escape-map-computation.ll | 2 +- polly/test/CodeGen/constant_condition.ll | 2 +- polly/test/CodeGen/create-conditional-scop.ll | 2 +- ...d_instruction_referenced_by_parameter_1.ll | 2 +- ...d_instruction_referenced_by_parameter_2.ll | 2 +- polly/test/CodeGen/debug-intrinsics.ll | 4 +- ...nce_problem_after_early_codegen_bailout.ll | 2 +- polly/test/CodeGen/empty_domain_in_context.ll | 2 +- polly/test/CodeGen/entry_with_trivial_phi.ll | 2 +- .../entry_with_trivial_phi_other_bb.ll | 2 +- .../error-stmt-in-non-affine-region.ll | 2 +- ...or_block_contains_invalid_memory_access.ll | 2 +- polly/test/CodeGen/exprModDiv.ll | 8 +- .../hoisted_load_escapes_through_phi.ll | 4 +- polly/test/CodeGen/hoisting_1.ll | 2 +- polly/test/CodeGen/hoisting_2.ll | 2 +- polly/test/CodeGen/inner_scev_sdiv_1.ll | 2 +- polly/test/CodeGen/inner_scev_sdiv_2.ll | 2 +- polly/test/CodeGen/inner_scev_sdiv_3.ll | 2 +- polly/test/CodeGen/inner_scev_sdiv_in_lb.ll | 4 +- .../inner_scev_sdiv_in_lb_invariant.ll | 2 +- polly/test/CodeGen/inner_scev_sdiv_in_rtc.ll | 2 +- polly/test/CodeGen/intrinsics_lifetime.ll | 2 +- polly/test/CodeGen/intrinsics_misc.ll | 2 +- .../inv-load-lnt-crash-wrong-order-2.ll | 2 +- .../inv-load-lnt-crash-wrong-order-3.ll | 2 +- .../CodeGen/inv-load-lnt-crash-wrong-order.ll | 2 +- .../test/CodeGen/invariant-load-dimension.ll | 4 +- ...-load-preload-base-pointer-origin-first.ll | 2 +- .../CodeGen/invariant_cannot_handle_void.ll | 4 +- polly/test/CodeGen/invariant_load.ll | 2 +- .../CodeGen/invariant_load_address_space.ll | 2 +- .../CodeGen/invariant_load_alias_metadata.ll | 2 +- .../CodeGen/invariant_load_base_pointer.ll | 2 +- ...invariant_load_base_pointer_conditional.ll | 2 +- ...variant_load_base_pointer_conditional_2.ll | 6 +- ...ariant_load_canonicalize_array_baseptrs.ll | 2 +- .../test/CodeGen/invariant_load_condition.ll | 2 +- .../invariant_load_different_sized_types.ll | 2 +- polly/test/CodeGen/invariant_load_escaping.ll | 2 +- .../invariant_load_escaping_second_scop.ll | 2 +- .../invariant_load_in_non_affine_subregion.ll | 2 +- polly/test/CodeGen/invariant_load_loop_ub.ll | 2 +- ...ant_load_not_executed_but_in_parameters.ll | 2 +- .../test/CodeGen/invariant_load_outermost.ll | 2 +- ...riant_load_parameters_cyclic_dependence.ll | 4 +- .../CodeGen/invariant_load_ptr_ptr_noalias.ll | 2 +- .../test/CodeGen/invariant_load_scalar_dep.ll | 2 +- ...riant_load_scalar_escape_alloca_sharing.ll | 2 +- ...oads_from_struct_with_different_types_1.ll | 2 +- ...oads_from_struct_with_different_types_2.ll | 2 +- ...invariant_loads_ignore_parameter_bounds.ll | 2 +- .../invariant_verify_function_failed.ll | 2 +- .../invariant_verify_function_failed_2.ll | 4 +- polly/test/CodeGen/issue56692.ll | 2 +- .../large-numbers-in-boundary-context.ll | 2 +- .../test/CodeGen/load_subset_with_context.ll | 2 +- .../loop-invariant-load-type-mismatch.ll | 2 +- polly/test/CodeGen/loop_with_condition.ll | 2 +- polly/test/CodeGen/loop_with_condition_2.ll | 2 +- .../test/CodeGen/loop_with_condition_ineq.ll | 2 +- .../CodeGen/loop_with_condition_nested.ll | 4 +- ..._conditional_entry_edge_split_hard_case.ll | 2 +- polly/test/CodeGen/memcpy_annotations.ll | 2 +- .../multidim-non-matching-typesize-2.ll | 2 +- .../CodeGen/multidim-non-matching-typesize.ll | 2 +- ..._2d_parametric_array_static_loop_bounds.ll | 2 +- polly/test/CodeGen/multidim_alias_check.ll | 2 +- polly/test/CodeGen/multiple-codegens.ll | 5 +- polly/test/CodeGen/multiple-scops-in-a-row.ll | 2 +- .../multiple-types-invariant-load-2.ll | 2 +- .../CodeGen/multiple-types-invariant-load.ll | 2 +- .../multiple_sai_fro_same_base_address.ll | 4 +- polly/test/CodeGen/no-overflow-tracking.ll | 4 +- polly/test/CodeGen/no_guard_bb.ll | 2 +- ...non-affine-dominance-generated-entering.ll | 2 +- .../CodeGen/non-affine-exit-node-dominance.ll | 2 +- .../non-affine-phi-node-expansion-2.ll | 2 +- .../non-affine-phi-node-expansion-3.ll | 2 +- .../non-affine-phi-node-expansion-4.ll | 2 +- .../CodeGen/non-affine-phi-node-expansion.ll | 2 +- ...e-region-exit-phi-incoming-synthesize-2.ll | 2 +- ...ine-region-exit-phi-incoming-synthesize.ll | 2 +- .../non-affine-region-implicit-store.ll | 2 +- ...ine-region-phi-references-in-scop-value.ll | 2 +- .../non-affine-subregion-dominance-reuse.ll | 2 +- polly/test/CodeGen/non-affine-switch.ll | 2 +- .../non-affine-synthesized-in-branch.ll | 2 +- polly/test/CodeGen/non-affine-update.ll | 4 +- .../non-hoisted-load-needed-as-base-ptr.ll | 2 +- .../test/CodeGen/non_affine_float_compare.ll | 2 +- .../CodeGen/only_non_affine_error_region.ll | 2 +- polly/test/CodeGen/openmp_limit_threads.ll | 12 +-- .../test/CodeGen/out-of-scop-phi-node-use.ll | 2 +- polly/test/CodeGen/param_div_div_div_2.ll | 4 +- polly/test/CodeGen/partial_write_array.ll | 2 +- polly/test/CodeGen/partial_write_emptyset.ll | 2 +- ...l_write_full_write_that_appears_partial.ll | 2 +- .../partial_write_impossible_restriction.ll | 2 +- polly/test/CodeGen/partial_write_in_region.ll | 4 +- .../partial_write_in_region_with_loop.ll | 4 +- .../CodeGen/partial_write_mapped_scalar.ll | 2 +- .../partial_write_mapped_scalar_subregion.ll | 2 +- polly/test/CodeGen/perf_monitoring.ll | 2 +- .../perf_monitoring_cycles_per_scop.ll | 2 +- .../perf_monitoring_trip_counts_per_scop.ll | 2 +- polly/test/CodeGen/phi-defined-before-scop.ll | 2 +- .../phi_after_error_block_outside_of_scop.ll | 2 +- .../test/CodeGen/phi_condition_modeling_1.ll | 2 +- .../test/CodeGen/phi_condition_modeling_2.ll | 2 +- .../test/CodeGen/phi_conditional_simple_1.ll | 4 +- .../phi_in_exit_early_lnt_failure_1.ll | 2 +- .../phi_in_exit_early_lnt_failure_2.ll | 2 +- .../phi_in_exit_early_lnt_failure_3.ll | 2 +- .../phi_in_exit_early_lnt_failure_5.ll | 2 +- polly/test/CodeGen/phi_loop_carried_float.ll | 2 +- .../CodeGen/phi_loop_carried_float_escape.ll | 4 +- polly/test/CodeGen/phi_scalar_simple_1.ll | 2 +- polly/test/CodeGen/phi_scalar_simple_2.ll | 2 +- .../CodeGen/phi_with_multi_exiting_edges_2.ll | 2 +- polly/test/CodeGen/phi_with_one_exit_edge.ll | 2 +- .../CodeGen/pointer-type-expressions-2.ll | 4 +- .../test/CodeGen/pointer-type-expressions.ll | 4 +- .../pointer-type-pointer-type-comparison.ll | 4 +- polly/test/CodeGen/pointer_rem.ll | 4 +- polly/test/CodeGen/pr25241.ll | 2 +- polly/test/CodeGen/ptrtoint_as_parameter.ll | 2 +- polly/test/CodeGen/read-only-scalars.ll | 4 +- polly/test/CodeGen/reduction.ll | 2 +- polly/test/CodeGen/reduction_2.ll | 2 +- polly/test/CodeGen/reduction_simple_binary.ll | 2 +- .../test/CodeGen/region-with-instructions.ll | 2 +- polly/test/CodeGen/region_exiting-domtree.ll | 2 +- .../CodeGen/region_multiexit_partialwrite.ll | 2 +- ...run-time-condition-with-scev-parameters.ll | 4 +- polly/test/CodeGen/run-time-condition.ll | 2 +- .../scalar-references-used-in-scop-compute.ll | 2 +- .../test/CodeGen/scalar-store-from-same-bb.ll | 2 +- polly/test/CodeGen/scalar_codegen_crash.ll | 2 +- polly/test/CodeGen/scev-backedgetaken.ll | 2 +- .../CodeGen/scev-division-invariant-load.ll | 2 +- polly/test/CodeGen/scev.ll | 2 +- .../CodeGen/scev_expansion_in_nonaffine.ll | 2 +- .../CodeGen/scev_looking_through_bitcasts.ll | 2 +- .../CodeGen/scop_expander_insert_point.ll | 2 +- polly/test/CodeGen/scop_expander_segfault.ll | 2 +- ...p_never_executed_runtime_check_location.ll | 2 +- polly/test/CodeGen/select-base-pointer.ll | 2 +- polly/test/CodeGen/sequential_loops.ll | 2 +- .../CodeGen/simple_loop_non_single_exit.ll | 2 +- .../CodeGen/simple_loop_non_single_exit_2.ll | 2 +- polly/test/CodeGen/simple_non_single_entry.ll | 2 +- polly/test/CodeGen/simple_nonaffine_loop.ll | 2 +- .../single_do_loop_int_max_iterations.ll | 2 +- .../single_do_loop_int_param_iterations.ll | 2 +- .../single_do_loop_ll_max_iterations.ll | 4 +- .../CodeGen/single_do_loop_one_iteration.ll | 2 +- .../CodeGen/single_do_loop_scev_replace.ll | 2 +- polly/test/CodeGen/single_loop.ll | 2 +- .../CodeGen/single_loop_int_max_iterations.ll | 2 +- .../CodeGen/single_loop_ll_max_iterations.ll | 2 +- .../test/CodeGen/single_loop_one_iteration.ll | 2 +- polly/test/CodeGen/single_loop_param.ll | 2 +- .../CodeGen/single_loop_param_less_equal.ll | 6 +- .../CodeGen/single_loop_param_less_than.ll | 4 +- .../CodeGen/single_loop_zero_iterations.ll | 2 +- polly/test/CodeGen/split_edge_of_exit.ll | 4 +- polly/test/CodeGen/split_edges.ll | 2 +- polly/test/CodeGen/split_edges_2.ll | 2 +- polly/test/CodeGen/srem-in-other-bb.ll | 2 +- .../stack-overflow-in-load-hoisting.ll | 2 +- .../test/CodeGen/stmt_split_no_dependence.ll | 2 +- .../CodeGen/switch-in-non-affine-region.ll | 2 +- .../synthesizable_phi_write_after_loop.ll | 2 +- .../test-invalid-operands-for-select-2.ll | 2 +- .../test-invalid-operands-for-select.ll | 2 +- polly/test/CodeGen/test.ll | 2 +- .../two-loops-right-after-each-other-2.ll | 2 +- .../two-scops-in-row-invalidate-scevs.ll | 2 +- polly/test/CodeGen/two-scops-in-row.ll | 4 +- polly/test/CodeGen/udiv_expansion_position.ll | 2 +- .../CodeGen/uninitialized_scalar_memory.ll | 2 +- .../unpredictable-loop-unsynthesizable.ll | 6 +- .../test/CodeGen/variant_load_empty_domain.ll | 2 +- .../whole-scop-non-affine-subregion.ll | 2 +- polly/test/DeLICM/confused_order.ll | 4 +- ...ontradicting_assumed_context_and_domain.ll | 2 +- polly/test/DeLICM/load-in-cond-inf-loop.ll | 2 +- polly/test/DeLICM/map_memset_zero.ll | 4 +- polly/test/DeLICM/nomap_alreadymapped.ll | 2 +- polly/test/DeLICM/nomap_escaping.ll | 2 +- polly/test/DeLICM/nomap_occupied.ll | 2 +- polly/test/DeLICM/nomap_readonly.ll | 2 +- polly/test/DeLICM/nomap_spuriouswrite.ll | 2 +- polly/test/DeLICM/nomap_storagesize.ll | 2 +- polly/test/DeLICM/nomap_writewrite.ll | 2 +- polly/test/DeLICM/outofquota-reverseDomain.ll | 2 +- polly/test/DeLICM/pass_existence.ll | 6 +- polly/test/DeLICM/pr41656.ll | 2 +- polly/test/DeLICM/pr48783.ll | 2 +- polly/test/DeLICM/reduction.ll | 2 +- .../reduction_looprotate_gvnpre_cond1.ll | 2 +- .../reduction_looprotate_gvnpre_cond2.ll | 2 +- ...reduction_looprotate_gvnpre_nopreheader.ll | 2 +- .../reduction_looprotate_licm_nopreheader.ll | 2 +- .../reduction_looprotate_loopguard_gvnpre.ll | 2 +- .../reduction_looprotate_loopguard_licm1.ll | 2 +- .../reduction_looprotate_loopguard_licm2.ll | 2 +- .../reduction_looprotate_loopguard_licm3.ll | 2 +- .../test/DeLICM/reduction_unrelatedunusual.ll | 2 +- polly/test/DeLICM/reject_loadafterstore.ll | 2 +- polly/test/DeLICM/reject_outofquota.ll | 4 +- polly/test/DeLICM/reject_storeafterstore.ll | 2 +- polly/test/DeLICM/reject_storeinsubregion.ll | 2 +- polly/test/DeLICM/reject_unusualstore.ll | 4 +- polly/test/DeLICM/skip_maywrite.ll | 2 +- polly/test/DeLICM/skip_multiaccess.ll | 2 +- polly/test/DeLICM/skip_notinloop.ll | 2 +- polly/test/DeLICM/skip_scalaraccess.ll | 2 +- .../DeadCodeElimination/chained_iterations.ll | 4 +- .../chained_iterations_2.ll | 4 +- polly/test/DeadCodeElimination/computeout.ll | 5 +- .../dead_iteration_elimination.ll | 3 +- .../non-affine-affine-mix.ll | 2 +- polly/test/DeadCodeElimination/non-affine.ll | 2 +- .../test/DeadCodeElimination/null_schedule.ll | 2 +- polly/test/DependenceInfo/computeout.ll | 6 +- .../different_schedule_dimensions.ll | 4 +- polly/test/DependenceInfo/do_pluto_matmult.ll | 6 +- polly/test/DependenceInfo/fine_grain_dep_0.ll | 7 +- .../generate_may_write_dependence_info.ll | 2 +- .../test/DependenceInfo/infeasible_context.ll | 5 +- ...writes_do_not_block_must_writes_for_war.ll | 2 +- .../nonaffine-condition-buildMemoryAccess.ll | 2 +- .../reduction_complex_location.ll | 6 +- ...ndences_equal_non_reduction_dependences.ll | 2 +- .../reduction_dependences_not_null.ll | 2 +- ...reduction_and_non_reduction_dependences.ll | 2 +- .../reduction_multiple_loops_array_sum.ll | 6 +- .../reduction_multiple_loops_array_sum_2.ll | 2 +- .../reduction_multiple_loops_array_sum_3.ll | 2 +- .../reduction_multiple_reductions.ll | 2 +- .../reduction_multiple_reductions_2.ll | 2 +- .../reduction_only_reduction_like_access.ll | 2 +- ...lly_escaping_intermediate_in_other_stmt.ll | 2 +- .../reduction_privatization_deps.ll | 2 +- .../reduction_privatization_deps_2.ll | 2 +- .../reduction_privatization_deps_3.ll | 2 +- .../reduction_privatization_deps_4.ll | 2 +- .../reduction_privatization_deps_5.ll | 2 +- .../test/DependenceInfo/reduction_sequence.ll | 2 +- .../DependenceInfo/reduction_simple_iv.ll | 2 +- ...ion_simple_iv_debug_wrapped_dependences.ll | 2 +- .../reduction_simple_privatization_deps_2.ll | 2 +- ...n_simple_privatization_deps_w_parameter.ll | 2 +- ...duction_two_reductions_different_rloops.ll | 2 +- polly/test/DependenceInfo/sequential_loops.ll | 79 ++++++++----------- polly/test/ForwardOpTree/atax.ll | 2 +- polly/test/ForwardOpTree/changed-kind.ll | 2 +- .../test/ForwardOpTree/forward_from_region.ll | 2 +- polly/test/ForwardOpTree/forward_hoisted.ll | 2 +- .../test/ForwardOpTree/forward_instruction.ll | 2 +- .../test/ForwardOpTree/forward_into_region.ll | 2 +- .../forward_into_region_redundant_use.ll | 2 +- polly/test/ForwardOpTree/forward_load.ll | 3 +- .../forward_load_differentarray.ll | 2 +- .../forward_load_double_write.ll | 2 +- .../ForwardOpTree/forward_load_fromloop.ll | 2 +- .../ForwardOpTree/forward_load_indirect.ll | 2 +- .../forward_load_memset_after.ll | 2 +- .../forward_load_memset_before.ll | 2 +- .../ForwardOpTree/forward_load_tripleuse.ll | 2 +- .../forward_load_unrelatedunusual.ll | 2 +- polly/test/ForwardOpTree/forward_phi_load.ll | 2 +- polly/test/ForwardOpTree/forward_readonly.ll | 4 +- polly/test/ForwardOpTree/forward_reusue.ll | 2 +- polly/test/ForwardOpTree/forward_store.ll | 2 +- .../forward_synthesizable_definloop.ll | 2 +- .../forward_synthesizable_indvar.ll | 2 +- .../forward_synthesizable_useinloop.ll | 2 +- .../test/ForwardOpTree/forward_transitive.ll | 2 +- polly/test/ForwardOpTree/jacobi-1d.ll | 2 +- .../ForwardOpTree/noforward_from_region.ll | 2 +- .../noforward_load_conditional.ll | 2 +- .../noforward_load_writebetween.ll | 2 +- .../ForwardOpTree/noforward_outofquota.ll | 4 +- polly/test/ForwardOpTree/noforward_partial.ll | 2 +- polly/test/ForwardOpTree/noforward_phi.ll | 2 +- .../ForwardOpTree/noforward_selfrefphi.ll | 2 +- .../ForwardOpTree/noforward_sideffects.ll | 2 +- .../noforward_synthesizable_unknownit.ll | 2 +- polly/test/ForwardOpTree/out-of-quota1.ll | 2 +- .../alias_checks_with_empty_context.ll | 2 +- polly/test/IstAstInfo/alias_simple_1.ll | 10 +-- polly/test/IstAstInfo/alias_simple_2.ll | 12 +-- polly/test/IstAstInfo/alias_simple_3.ll | 10 +-- .../aliasing_arrays_with_identical_base.ll | 2 +- .../aliasing_multiple_alias_groups.ll | 4 +- .../aliasing_parametric_simple_1.ll | 2 +- .../aliasing_parametric_simple_2.ll | 2 +- .../IstAstInfo/dependence_distance_minimal.ll | 2 +- .../domain_bounded_only_with_context.ll | 2 +- polly/test/IstAstInfo/non_affine_access.ll | 2 +- ...reduction_clauses_onedimensional_access.ll | 2 +- ...ndences_equal_non_reduction_dependences.ll | 2 +- .../reduction_different_reduction_clauses.ll | 2 +- ...ction_modulo_and_loop_reversal_schedule.ll | 2 +- ...ion_modulo_and_loop_reversal_schedule_2.ll | 2 +- ...ion_modulo_schedule_multiple_dimensions.ll | 2 +- ...n_modulo_schedule_multiple_dimensions_2.ll | 2 +- ...n_modulo_schedule_multiple_dimensions_3.ll | 2 +- ...n_modulo_schedule_multiple_dimensions_4.ll | 2 +- ...n_modulo_schedule_multiple_dimensions_5.ll | 2 +- .../reduction_multiple_dimensions.ll | 2 +- .../reduction_multiple_dimensions_2.ll | 2 +- .../reduction_multiple_dimensions_3.ll | 2 +- .../reduction_multiple_dimensions_4.ll | 2 +- polly/test/IstAstInfo/run-time-condition.ll | 2 +- .../runtime_context_with_error_blocks.ll | 2 +- .../IstAstInfo/simple-run-time-condition.ll | 2 +- .../test/IstAstInfo/single_loop_strip_mine.ll | 4 +- .../single_loop_uint_max_iterations.ll | 2 +- .../single_loop_ull_max_iterations.ll | 2 +- .../ImportAccesses-Bad-relation.ll | 2 +- .../ImportAccesses-No-accesses-key.ll | 2 +- .../ImportAccesses-Not-enough-MemAcc.ll | 2 +- .../ImportAccesses-Not-enough-statements.ll | 2 +- .../ImportAccesses-Relation-mispelled.ll | 2 +- .../ImportAccesses-Statements-mispelled.ll | 2 +- ...ImportAccesses-Undeclared-ScopArrayInfo.ll | 2 +- .../ImportAccesses-Wrong-number-dimensions.ll | 2 +- .../ImportArrays-Mispelled-type.ll | 2 +- .../ImportArrays-Negative-size.ll | 2 +- .../ImportArrays/ImportArrays-No-name.ll | 2 +- .../ImportArrays/ImportArrays-No-sizes-key.ll | 2 +- .../ImportArrays/ImportArrays-No-type-key.ll | 2 +- .../ImportContext-Context-mispelled.ll | 2 +- .../ImportContext-Not-parameter-set.ll | 2 +- .../ImportContext-Unvalid-Context.ll | 2 +- .../ImportContext-Wrong-dimension.ll | 2 +- .../ImportSchedule-No-schedule-key.ll | 2 +- .../ImportSchedule-Schedule-not-valid.ll | 2 +- .../ImportSchedule-Statements-mispelled.ll | 2 +- .../ImportSchedule-Wrong-number-statements.ll | 2 +- .../load_after_store_same_statement.ll | 6 +- .../read_from_original.ll | 6 +- .../MaximalStaticExpansion/too_many_writes.ll | 6 +- .../working_deps_between_inners.ll | 3 +- .../working_deps_between_inners_phi.ll | 6 +- .../working_expansion.ll | 3 +- ...sion_multiple_dependences_per_statement.ll | 3 +- ...sion_multiple_instruction_per_statement.ll | 3 +- .../working_phi_expansion.ll | 6 +- .../working_phi_two_scalars.ll | 6 +- .../working_value_expansion.ll | 3 +- .../prune_only_scalardeps.ll | 3 +- .../2012-03-16-Empty-Domain.ll | 2 +- .../2013-04-11-Empty-Domain-two.ll | 2 +- .../GreedyFuse/fuse-double.ll | 4 +- .../GreedyFuse/fuse-except-first.ll | 4 +- .../GreedyFuse/fuse-except-third.ll | 4 +- .../GreedyFuse/fuse-inner-carried.ll | 4 +- .../GreedyFuse/fuse-inner-third.ll | 4 +- .../GreedyFuse/fuse-inner.ll | 4 +- .../GreedyFuse/fuse-simple.ll | 4 +- .../GreedyFuse/nofuse-simple.ll | 4 +- .../GreedyFuse/nofuse-with-middle.ll | 4 +- .../ManualOptimization/disable_nonforced.ll | 2 +- .../distribute_heuristic.ll | 4 +- .../distribute_illegal_looploc.ll | 2 +- .../distribute_illegal_pragmaloc.ll | 2 +- .../ManualOptimization/unroll_disable.ll | 2 +- .../ManualOptimization/unroll_double.ll | 2 +- .../ManualOptimization/unroll_full.ll | 2 +- .../ManualOptimization/unroll_heuristic.ll | 4 +- .../ManualOptimization/unroll_partial.ll | 4 +- .../unroll_partial_followup.ll | 8 +- .../ScheduleOptimizer/SIMDInParallelFor.ll | 2 +- polly/test/ScheduleOptimizer/computeout.ll | 6 +- .../ensure-correct-tile-sizes.ll | 4 +- .../focaltech_test_detail_threshold-7bc17e.ll | 3 +- .../full_partial_tile_separation.ll | 2 +- polly/test/ScheduleOptimizer/line-tiling-2.ll | 2 +- polly/test/ScheduleOptimizer/line-tiling.ll | 2 +- .../mat_mul_pattern_data_layout.ll | 2 +- .../mat_mul_pattern_data_layout_2.ll | 4 +- .../ScheduleOptimizer/one-dimensional-band.ll | 2 +- .../ScheduleOptimizer/outer_coincidence.ll | 4 +- ...attern-matching-based-opts-after-delicm.ll | 4 +- ...tern-matching-based-opts-after-delicm_2.ll | 2 +- .../pattern-matching-based-opts.ll | 8 +- .../pattern-matching-based-opts_11.ll | 4 +- .../pattern-matching-based-opts_12.ll | 2 +- .../pattern-matching-based-opts_13.ll | 2 +- .../pattern-matching-based-opts_14.ll | 4 +- .../pattern-matching-based-opts_15.ll | 2 +- .../pattern-matching-based-opts_16.ll | 2 +- .../pattern-matching-based-opts_17.ll | 2 +- .../pattern-matching-based-opts_18.ll | 2 +- .../pattern-matching-based-opts_19.ll | 2 +- .../pattern-matching-based-opts_2.ll | 2 +- .../pattern-matching-based-opts_20.ll | 2 +- .../pattern-matching-based-opts_21.ll | 2 +- .../pattern-matching-based-opts_22.ll | 2 +- .../pattern-matching-based-opts_24.ll | 2 +- .../pattern-matching-based-opts_25.ll | 4 +- .../pattern-matching-based-opts_3.ll | 8 +- .../pattern-matching-based-opts_4.ll | 8 +- .../pattern-matching-based-opts_5.ll | 6 +- .../pattern-matching-based-opts_6.ll | 6 +- .../pattern-matching-based-opts_7.ll | 2 +- .../pattern-matching-based-opts_8.ll | 2 +- .../pattern-matching-based-opts_9.ll | 4 +- .../pattern_matching_based_opts_splitmap.ll | 2 +- .../prevectorization-without-tiling.ll | 2 +- .../ScheduleOptimizer/prevectorization.ll | 4 +- .../ScheduleOptimizer/rectangular-tiling.ll | 8 +- .../ScheduleOptimizer/schedule_computeout.ll | 2 +- polly/test/ScheduleOptimizer/statistics.ll | 2 +- .../ScheduleOptimizer/tile_after_fusion.ll | 4 +- ...vivid_vbi_gen_sliced-before-llvmreduced.ll | 2 +- .../aliasing_parametric_simple_1.ll | 2 +- .../aliasing_parametric_simple_2.ll | 2 +- polly/test/ScopDetect/aliasing_simple_1.ll | 2 +- polly/test/ScopDetect/aliasing_simple_2.ll | 2 +- .../base_pointer_load_setNewAccessRelation.ll | 2 +- .../base_pointer_setNewAccessRelation.ll | 2 +- polly/test/ScopDetect/callbr.ll | 4 +- .../ScopDetect/collective_invariant_loads.ll | 2 +- .../ScopDetect/cross_loop_non_single_exit.ll | 2 +- .../cross_loop_non_single_exit_2.ll | 2 +- ...ependency_to_phi_node_outside_of_region.ll | 2 +- polly/test/ScopDetect/dot-scops-npm.ll | 2 +- polly/test/ScopDetect/dot-scops.ll | 2 +- .../ScopDetect/error-block-always-executed.ll | 2 +- .../error-block-referenced-from-scop.ll | 2 +- .../ScopDetect/error-block-unreachable.ll | 2 +- .../ScopDetect/expand-region-correctly-2.ll | 2 +- .../ScopDetect/expand-region-correctly.ll | 2 +- .../test/ScopDetect/ignore_func_flag_regex.ll | 2 +- .../index_from_unpredictable_loop.ll | 4 +- .../index_from_unpredictable_loop2.ll | 4 +- polly/test/ScopDetect/indvars.ll | 2 +- polly/test/ScopDetect/intrinsics_1.ll | 2 +- polly/test/ScopDetect/intrinsics_2.ll | 2 +- polly/test/ScopDetect/intrinsics_3.ll | 2 +- .../ScopDetect/invalid-latch-conditions.ll | 6 +- .../ScopDetect/invalidate_scalar_evolution.ll | 2 +- .../ScopDetect/invariant-load-before-scop.ll | 2 +- polly/test/ScopDetect/keep_going_expansion.ll | 2 +- polly/test/ScopDetect/mod_ref_read_pointer.ll | 4 +- polly/test/ScopDetect/more-than-one-loop.ll | 4 +- .../ScopDetect/multidim-with-undef-size.ll | 2 +- polly/test/ScopDetect/multidim.ll | 2 +- .../ScopDetect/multidim_indirect_access.ll | 2 +- ..._two_accesses_different_delinearization.ll | 2 +- .../ScopDetect/nested_loop_single_exit.ll | 4 +- .../test/ScopDetect/non-affine-conditional.ll | 2 +- .../ScopDetect/non-affine-float-compare.ll | 2 +- ...-affine-loop-condition-dependent-access.ll | 8 +- ...ffine-loop-condition-dependent-access_2.ll | 6 +- ...ffine-loop-condition-dependent-access_3.ll | 6 +- polly/test/ScopDetect/non-affine-loop.ll | 10 +-- .../non-beneficial-loops-small-trip-count.ll | 2 +- .../non-constant-add-rec-start-expr.ll | 2 +- .../ScopDetect/non-simple-memory-accesses.ll | 2 +- .../ScopDetect/non_affine_loop_condition.ll | 4 +- polly/test/ScopDetect/only-one-affine-loop.ll | 2 +- polly/test/ScopDetect/only_func_flag.ll | 2 +- polly/test/ScopDetect/only_func_flag_regex.ll | 2 +- .../parametric-multiply-in-scev-2.ll | 2 +- .../ScopDetect/parametric-multiply-in-scev.ll | 2 +- .../phi_with_multi_exiting_edges.ll | 2 +- .../profitability-large-basic-blocks.ll | 6 +- .../profitability-two-nested-loops.ll | 2 +- polly/test/ScopDetect/remove_all_children.ll | 2 +- polly/test/ScopDetect/report-scop-location.ll | 2 +- .../restrict-undef-size-scopdetect.ll | 2 +- polly/test/ScopDetect/run_time_alias_check.ll | 2 +- polly/test/ScopDetect/scev_remove_max.ll | 2 +- polly/test/ScopDetect/sequential_loops.ll | 6 +- polly/test/ScopDetect/simple_loop.ll | 2 +- .../simple_loop_non_single_entry.ll | 2 +- .../ScopDetect/simple_loop_non_single_exit.ll | 2 +- .../simple_loop_non_single_exit_2.ll | 2 +- .../ScopDetect/simple_loop_two_phi_nodes.ll | 2 +- .../test/ScopDetect/simple_loop_with_param.ll | 2 +- .../ScopDetect/simple_loop_with_param_2.ll | 2 +- .../ScopDetect/simple_non_single_entry.ll | 2 +- .../ScopDetect/skip_function_attribute.ll | 2 +- .../srem_with_parametric_divisor.ll | 2 +- polly/test/ScopDetect/statistics.ll | 2 +- polly/test/ScopDetect/switch-in-loop-patch.ll | 2 +- .../ReportAlias-01.ll | 2 +- .../ScopDetectionDiagnostics/ReportEntry.ll | 2 +- .../ReportFuncCall-01.ll | 2 +- .../ReportIrreducibleRegion.ll | 2 +- .../ReportIrreducibleRegionWithoutDebugLoc.ll | 2 +- .../ReportLoopBound-01.ll | 6 +- .../ReportLoopHasNoExit.ll | 4 +- .../ReportMultipleNonAffineAccesses.ll | 12 +-- .../ReportNonAffineAccess-01.ll | 2 +- .../ReportUnprofitable.ll | 4 +- .../ReportUnreachableInExit.ll | 2 +- .../ReportVariantBasePtr-01.ll | 2 +- .../loop_has_multiple_exits.ll | 2 +- .../loop_partially_in_scop-2.ll | 2 +- .../loop_partially_in_scop.ll | 2 +- .../ScopInfo/20110312-Fail-without-basicaa.ll | 2 +- .../20111108-Parameter-not-detected.ll | 2 +- ...03-16-Crash-because-of-unsigned-in-scev.ll | 2 +- .../2015-10-04-Crash-in-domain-generation.ll | 2 +- polly/test/ScopInfo/Alias-0.ll | 4 +- polly/test/ScopInfo/Alias-1.ll | 4 +- polly/test/ScopInfo/Alias-2.ll | 4 +- polly/test/ScopInfo/Alias-3.ll | 4 +- polly/test/ScopInfo/Alias-4.ll | 4 +- .../test/ScopInfo/BoundChecks/single-loop.ll | 4 +- polly/test/ScopInfo/BoundChecks/two-loops.ll | 4 +- polly/test/ScopInfo/NonAffine/div_backedge.ll | 2 +- polly/test/ScopInfo/NonAffine/div_domain.ll | 2 +- ...nt_loads_dependent_in_non_affine_region.ll | 2 +- .../ScopInfo/NonAffine/modulo_backedge.ll | 2 +- .../test/ScopInfo/NonAffine/modulo_domain.ll | 2 +- ...ffine-loop-condition-dependent-access_1.ll | 4 +- ...ffine-loop-condition-dependent-access_2.ll | 6 +- ...ffine-loop-condition-dependent-access_3.ll | 6 +- .../non_affine_access_with_range_2.ll | 2 +- .../ScopInfo/NonAffine/non_affine_but_sdiv.ll | 2 +- .../ScopInfo/NonAffine/non_affine_but_srem.ll | 2 +- .../non_affine_conditional_nested.ll | 2 +- ...ine_conditional_surrounding_affine_loop.ll | 4 +- ...conditional_surrounding_non_affine_loop.ll | 6 +- .../NonAffine/non_affine_float_compare.ll | 2 +- .../NonAffine/non_affine_loop_condition.ll | 6 +- .../NonAffine/non_affine_loop_used_later.ll | 4 +- .../NonAffine/non_affine_parametric_loop.ll | 2 +- .../non_affine_region_guaranteed_non-entry.ll | 2 +- ...whole-scop-non-affine-subregion-in-loop.ll | 2 +- .../aliasing_conditional_alias_groups_1.ll | 2 +- .../aliasing_conditional_alias_groups_2.ll | 2 +- polly/test/ScopInfo/aliasing_dead_access.ll | 2 +- .../aliasing_many_arrays_to_compare.ll | 8 +- .../aliasing_many_read_only_acesses.ll | 2 +- .../aliasing_multiple_alias_groups.ll | 4 +- .../aliasing_with_non_affine_access.ll | 2 +- .../allow-all-parameters-dereferencable.ll | 6 +- polly/test/ScopInfo/assume_gep_bounds.ll | 4 +- polly/test/ScopInfo/assume_gep_bounds_2.ll | 2 +- polly/test/ScopInfo/assume_gep_bounds_many.ll | 4 +- .../avoid_new_parameters_from_geps.ll | 2 +- polly/test/ScopInfo/bool-addrec.ll | 2 +- .../test/ScopInfo/bounded_loop_assumptions.ll | 2 +- ...ces-loop-scev-with-unknown-iterations-2.ll | 4 +- ...ces-loop-scev-with-unknown-iterations-3.ll | 6 +- ...ences-loop-scev-with-unknown-iterations.ll | 6 +- polly/test/ScopInfo/bug_2010_10_22.ll | 2 +- polly/test/ScopInfo/bug_2011_1_5.ll | 2 +- .../test/ScopInfo/bug_scev_not_fully_eval.ll | 2 +- polly/test/ScopInfo/cfg_consequences.ll | 2 +- .../test/ScopInfo/complex-branch-structure.ll | 2 +- polly/test/ScopInfo/complex-condition.ll | 2 +- polly/test/ScopInfo/complex-expression.ll | 2 +- polly/test/ScopInfo/complex-loop-nesting.ll | 2 +- .../ScopInfo/complex-successor-structure-2.ll | 2 +- .../ScopInfo/complex-successor-structure-3.ll | 4 +- .../ScopInfo/complex-successor-structure.ll | 2 +- .../complex_domain_binary_condition.ll | 2 +- .../ScopInfo/complex_execution_context.ll | 2 +- polly/test/ScopInfo/cond_constant_in_loop.ll | 2 +- polly/test/ScopInfo/cond_in_loop.ll | 2 +- .../ScopInfo/condition-after-error-block-2.ll | 2 +- ...condition-after-error-block-before-scop.ll | 2 +- .../ScopInfo/condtion-after-error-block.ll | 2 +- polly/test/ScopInfo/const_srem_sdiv.ll | 4 +- .../constant-non-integer-branch-condition.ll | 2 +- .../ScopInfo/constant_factor_in_parameter.ll | 4 +- ...stant_functions_outside_scop_as_unknown.ll | 2 +- polly/test/ScopInfo/constant_start_integer.ll | 2 +- polly/test/ScopInfo/debug_call.ll | 2 +- .../delinearize-together-all-data-refs.ll | 2 +- polly/test/ScopInfo/div_by_zero.ll | 2 +- .../do-not-model-error-block-accesses.ll | 2 +- .../eager-binary-and-or-conditions.ll | 4 +- .../early_exit_for_complex_domains.ll | 2 +- polly/test/ScopInfo/error-blocks-1.ll | 2 +- polly/test/ScopInfo/error-blocks-2.ll | 4 +- polly/test/ScopInfo/escaping_empty_scop.ll | 2 +- polly/test/ScopInfo/exit-phi-1.ll | 4 +- polly/test/ScopInfo/exit-phi-2.ll | 2 +- polly/test/ScopInfo/exit_phi_accesses-2.ll | 2 +- polly/test/ScopInfo/exit_phi_accesses.ll | 2 +- .../ScopInfo/expensive-boundary-context.ll | 4 +- ...onstant_factor_introduces_new_parameter.ll | 4 +- polly/test/ScopInfo/full-function.ll | 4 +- polly/test/ScopInfo/granularity_same_name.ll | 8 +- .../test/ScopInfo/granularity_scalar-indep.ll | 2 +- ...ity_scalar-indep_cross-referencing-phi1.ll | 2 +- ...ity_scalar-indep_cross-referencing-phi2.ll | 2 +- .../granularity_scalar-indep_epilogue.ll | 2 +- .../granularity_scalar-indep_epilogue_last.ll | 2 +- .../granularity_scalar-indep_noepilogue.ll | 2 +- .../granularity_scalar-indep_ordered-2.ll | 2 +- .../granularity_scalar-indep_ordered.ll | 2 +- polly/test/ScopInfo/i1_params.ll | 2 +- polly/test/ScopInfo/infeasible-rtc.ll | 4 +- .../ScopInfo/infeasible_invalid_context.ll | 4 +- polly/test/ScopInfo/int2ptr_ptr2int.ll | 4 +- polly/test/ScopInfo/int2ptr_ptr2int_2.ll | 8 +- polly/test/ScopInfo/integers.ll | 2 +- .../ScopInfo/inter-error-bb-dependence.ll | 2 +- polly/test/ScopInfo/inter_bb_scalar_dep.ll | 4 +- .../intra-non-affine-stmt-phi-node.ll | 4 +- .../ScopInfo/intra_and_inter_bb_scalar_dep.ll | 4 +- polly/test/ScopInfo/intra_bb_scalar_dep.ll | 4 +- polly/test/ScopInfo/intrinsics.ll | 2 +- ..._add_rec_after_invariant_load_remapping.ll | 2 +- .../invalidate_iterator_during_MA_removal.ll | 2 +- .../test/ScopInfo/invariant-load-instlist.ll | 2 +- ...ariant-loads-leave-read-only-statements.ll | 4 +- polly/test/ScopInfo/invariant_load.ll | 2 +- ...load_access_classes_different_base_type.ll | 4 +- ...ss_classes_different_base_type_escaping.ll | 4 +- ...lasses_different_base_type_same_pointer.ll | 4 +- ...fferent_base_type_same_pointer_escaping.ll | 4 +- .../ScopInfo/invariant_load_addrec_sum.ll | 2 +- .../ScopInfo/invariant_load_base_pointer.ll | 2 +- ...invariant_load_base_pointer_conditional.ll | 2 +- ...ariant_load_base_pointer_in_conditional.ll | 2 +- .../invariant_load_branch_condition.ll | 4 +- ...ariant_load_canonicalize_array_baseptrs.ll | 2 +- ...iant_load_canonicalize_array_baseptrs_2.ll | 2 +- ...iant_load_canonicalize_array_baseptrs_3.ll | 2 +- ...iant_load_canonicalize_array_baseptrs_4.ll | 2 +- ...ant_load_canonicalize_array_baseptrs_4b.ll | 2 +- ...ant_load_canonicalize_array_baseptrs_4c.ll | 2 +- ...iant_load_canonicalize_array_baseptrs_5.ll | 2 +- .../invariant_load_complex_condition.ll | 4 +- .../test/ScopInfo/invariant_load_condition.ll | 2 +- .../invariant_load_dereferenceable.ll | 4 +- ...iant_load_distinct_parameter_valuations.ll | 2 +- .../ScopInfo/invariant_load_in_non_affine.ll | 4 +- polly/test/ScopInfo/invariant_load_loop_ub.ll | 4 +- .../invariant_load_ptr_ptr_noalias.ll | 4 +- .../ScopInfo/invariant_load_scalar_dep.ll | 2 +- .../ScopInfo/invariant_load_stmt_domain.ll | 2 +- .../invariant_load_zext_parameter-2.ll | 4 +- .../ScopInfo/invariant_load_zext_parameter.ll | 4 +- ...load_zextended_in_own_execution_context.ll | 4 +- ...invariant_loads_complicated_dependences.ll | 2 +- .../invariant_loads_cyclic_dependences.ll | 2 +- polly/test/ScopInfo/invariant_loop_bounds.ll | 2 +- ...ariant_same_loop_bound_multiple_times-1.ll | 2 +- ...ariant_same_loop_bound_multiple_times-2.ll | 2 +- polly/test/ScopInfo/isl_aff_out_of_bounds.ll | 2 +- polly/test/ScopInfo/isl_trip_count_01.ll | 2 +- polly/test/ScopInfo/isl_trip_count_02.ll | 2 +- polly/test/ScopInfo/isl_trip_count_03.ll | 2 +- .../isl_trip_count_multiple_exiting_blocks.ll | 2 +- polly/test/ScopInfo/licm_load.ll | 4 +- polly/test/ScopInfo/licm_potential_store.ll | 4 +- polly/test/ScopInfo/licm_reduction_nested.ll | 4 +- .../long-compile-time-alias-analysis.ll | 2 +- .../long-sequence-of-error-blocks-2.ll | 2 +- .../ScopInfo/long-sequence-of-error-blocks.ll | 4 +- .../test/ScopInfo/loop-multiexit-succ-cond.ll | 4 +- polly/test/ScopInfo/loop_affine_bound_0.ll | 4 +- polly/test/ScopInfo/loop_affine_bound_1.ll | 4 +- polly/test/ScopInfo/loop_affine_bound_2.ll | 4 +- polly/test/ScopInfo/loop_carry.ll | 2 +- .../test/ScopInfo/many-scalar-dependences.ll | 2 +- polly/test/ScopInfo/max-loop-depth.ll | 2 +- polly/test/ScopInfo/memcpy-raw-source.ll | 2 +- polly/test/ScopInfo/memcpy.ll | 4 +- polly/test/ScopInfo/memmove.ll | 4 +- polly/test/ScopInfo/memset.ll | 4 +- polly/test/ScopInfo/memset_null.ll | 4 +- .../ScopInfo/mismatching-array-dimensions.ll | 2 +- .../mod_ref_access_pointee_arguments.ll | 6 +- .../mod_ref_read_pointee_arguments.ll | 6 +- polly/test/ScopInfo/mod_ref_read_pointer.ll | 4 +- polly/test/ScopInfo/mod_ref_read_pointers.ll | 6 +- polly/test/ScopInfo/modulo_zext_1.ll | 2 +- polly/test/ScopInfo/modulo_zext_2.ll | 2 +- polly/test/ScopInfo/modulo_zext_3.ll | 2 +- polly/test/ScopInfo/multi-scop.ll | 2 +- .../ScopInfo/multidim_2d-diagonal-matrix.ll | 4 +- .../multidim_2d_outer_parametric_offset.ll | 2 +- ..._2d_parametric_array_static_loop_bounds.ll | 2 +- .../ScopInfo/multidim_2d_with_modref_call.ll | 8 +- .../multidim_2d_with_modref_call_2.ll | 8 +- ..._3d_parametric_array_static_loop_bounds.ll | 2 +- ...idim_fixedsize_different_dimensionality.ll | 2 +- .../multidim_fixedsize_multi_offset.ll | 2 +- .../ScopInfo/multidim_fold_constant_dim.ll | 2 +- .../multidim_fold_constant_dim_zero.ll | 2 +- polly/test/ScopInfo/multidim_fortran_2d.ll | 4 +- .../ScopInfo/multidim_fortran_2d_params.ll | 4 +- .../multidim_fortran_2d_with_modref_call.ll | 8 +- polly/test/ScopInfo/multidim_fortran_srem.ll | 2 +- .../test/ScopInfo/multidim_gep_pointercast.ll | 2 +- .../ScopInfo/multidim_gep_pointercast2.ll | 2 +- .../multidim_ivs_and_integer_offsets_3d.ll | 2 +- ...multidim_ivs_and_parameteric_offsets_3d.ll | 2 +- .../test/ScopInfo/multidim_many_references.ll | 4 +- .../ScopInfo/multidim_nested_start_integer.ll | 4 +- .../multidim_nested_start_share_parameter.ll | 2 +- polly/test/ScopInfo/multidim_only_ivs_2d.ll | 2 +- polly/test/ScopInfo/multidim_only_ivs_3d.ll | 2 +- .../ScopInfo/multidim_only_ivs_3d_cast.ll | 2 +- .../ScopInfo/multidim_only_ivs_3d_reverse.ll | 2 +- .../ScopInfo/multidim_param_in_subscript-2.ll | 2 +- .../ScopInfo/multidim_param_in_subscript.ll | 2 +- .../multidim_parameter_addrec_product.ll | 2 +- .../multidim_single_and_multidim_array.ll | 16 ++-- polly/test/ScopInfo/multidim_srem.ll | 2 +- polly/test/ScopInfo/multidim_with_bitcast.ll | 2 +- .../ScopInfo/multiple-binary-or-conditions.ll | 4 +- ...ss-offset-not-dividable-by-element-size.ll | 2 +- .../ScopInfo/multiple-types-non-affine-2.ll | 4 +- .../ScopInfo/multiple-types-non-affine.ll | 4 +- .../multiple-types-non-power-of-two-2.ll | 2 +- .../multiple-types-non-power-of-two.ll | 2 +- .../multiple-types-two-dimensional-2.ll | 2 +- .../multiple-types-two-dimensional.ll | 2 +- polly/test/ScopInfo/multiple-types.ll | 4 +- .../test/ScopInfo/multiple_exiting_blocks.ll | 2 +- .../multiple_exiting_blocks_two_loop.ll | 2 +- polly/test/ScopInfo/multiple_latch_blocks.ll | 2 +- polly/test/ScopInfo/nested-loops.ll | 2 +- .../no-scalar-deps-in-non-affine-subregion.ll | 2 +- polly/test/ScopInfo/non-affine-region-phi.ll | 4 +- .../ScopInfo/non-affine-region-with-loop-2.ll | 2 +- .../ScopInfo/non-affine-region-with-loop.ll | 4 +- polly/test/ScopInfo/non-precise-inv-load-1.ll | 2 +- polly/test/ScopInfo/non-precise-inv-load-2.ll | 2 +- polly/test/ScopInfo/non-precise-inv-load-3.ll | 2 +- polly/test/ScopInfo/non-precise-inv-load-4.ll | 2 +- polly/test/ScopInfo/non-precise-inv-load-5.ll | 2 +- polly/test/ScopInfo/non-precise-inv-load-6.ll | 2 +- polly/test/ScopInfo/non-pure-function-call.ll | 2 +- ...-pure-function-calls-causes-dead-blocks.ll | 2 +- .../test/ScopInfo/non-pure-function-calls.ll | 2 +- polly/test/ScopInfo/non_affine_access.ll | 4 +- polly/test/ScopInfo/non_affine_region_1.ll | 2 +- polly/test/ScopInfo/non_affine_region_2.ll | 2 +- polly/test/ScopInfo/non_affine_region_3.ll | 4 +- polly/test/ScopInfo/non_affine_region_4.ll | 2 +- .../ScopInfo/nonaffine-buildMemoryAccess.ll | 2 +- polly/test/ScopInfo/not-a-reduction.ll | 2 +- polly/test/ScopInfo/opaque-struct.ll | 2 +- ...gion-entry-phi-node-nonaffine-subregion.ll | 2 +- ...ut-of-scop-use-in-region-entry-phi-node.ll | 2 +- .../ScopInfo/parameter-constant-division.ll | 4 +- .../ScopInfo/parameter_in_dead_statement.ll | 8 +- polly/test/ScopInfo/parameter_product.ll | 2 +- .../parameter_with_constant_factor_in_add.ll | 2 +- .../ScopInfo/partially_invariant_load_1.ll | 4 +- .../ScopInfo/partially_invariant_load_2.ll | 2 +- .../test/ScopInfo/phi-in-non-affine-region.ll | 2 +- polly/test/ScopInfo/phi_after_error_block.ll | 2 +- .../test/ScopInfo/phi_condition_modeling_1.ll | 2 +- .../test/ScopInfo/phi_condition_modeling_2.ll | 2 +- .../test/ScopInfo/phi_conditional_simple_1.ll | 2 +- polly/test/ScopInfo/phi_loop_carried_float.ll | 2 +- polly/test/ScopInfo/phi_not_grouped_at_top.ll | 2 +- polly/test/ScopInfo/phi_scalar_simple_1.ll | 2 +- polly/test/ScopInfo/phi_scalar_simple_2.ll | 2 +- polly/test/ScopInfo/phi_with_invoke_edge.ll | 2 +- .../ScopInfo/pointer-comparison-no-nsw.ll | 2 +- polly/test/ScopInfo/pointer-comparison.ll | 2 +- .../test/ScopInfo/pointer-type-expressions.ll | 2 +- ...er-used-as-base-pointer-and-scalar-read.ll | 2 +- .../polly-timeout-parameter-bounds.ll | 2 +- ...eserve-equiv-class-order-in-basic_block.ll | 2 +- .../test/ScopInfo/process_added_dimensions.ll | 2 +- .../test/ScopInfo/pwaff-complexity-bailout.ll | 2 +- polly/test/ScopInfo/ranged_parameter.ll | 2 +- polly/test/ScopInfo/ranged_parameter_2.ll | 2 +- polly/test/ScopInfo/ranged_parameter_wrap.ll | 2 +- .../test/ScopInfo/ranged_parameter_wrap_2.ll | 2 +- .../read-only-scalar-used-in-phi-2.ll | 2 +- .../ScopInfo/read-only-scalar-used-in-phi.ll | 2 +- polly/test/ScopInfo/read-only-scalars.ll | 4 +- polly/test/ScopInfo/read-only-statements.ll | 2 +- .../ScopInfo/reduction_alternating_base.ll | 2 +- ...uction_chain_partially_outside_the_scop.ll | 2 +- .../ScopInfo/reduction_different_index.ll | 2 +- .../ScopInfo/reduction_different_index1.ll | 2 +- .../reduction_disabled_multiplicative.ll | 2 +- .../reduction_escaping_intermediate.ll | 2 +- .../reduction_escaping_intermediate_2.ll | 2 +- .../reduction_invalid_different_operators.ll | 2 +- .../reduction_invalid_overlapping_accesses.ll | 2 +- .../reduction_multiple_loops_array_sum.ll | 2 +- .../reduction_multiple_loops_array_sum_1.ll | 2 +- .../reduction_multiple_simple_binary.ll | 2 +- .../reduction_non_overlapping_chains.ll | 2 +- .../reduction_only_reduction_like_access.ll | 2 +- polly/test/ScopInfo/reduction_simple_fp.ll | 2 +- .../ScopInfo/reduction_simple_w_constant.ll | 2 +- polly/test/ScopInfo/reduction_simple_w_iv.ll | 2 +- .../ScopInfo/reduction_two_identical_reads.ll | 4 +- .../redundant_parameter_constraint.ll | 2 +- .../test/ScopInfo/region-with-instructions.ll | 2 +- polly/test/ScopInfo/remarks.ll | 2 +- .../required-invariant-loop-bounds.ll | 4 +- .../ScopInfo/restriction_in_dead_block.ll | 2 +- .../run-time-check-many-array-disjuncts.ll | 4 +- .../run-time-check-many-parameters.ll | 2 +- .../run-time-check-many-piecewise-aliasing.ll | 4 +- .../run-time-check-read-only-arrays.ll | 2 +- .../same-base-address-scalar-and-array.ll | 2 +- polly/test/ScopInfo/scalar.ll | 2 +- .../ScopInfo/scalar_dependence_cond_br.ll | 2 +- polly/test/ScopInfo/scalar_to_array.ll | 4 +- .../scev-div-with-evaluatable-divisor.ll | 2 +- polly/test/ScopInfo/scev-invalidated.ll | 2 +- .../schedule-const-post-dominator-walk-2.ll | 2 +- .../schedule-const-post-dominator-walk.ll | 2 +- .../schedule-constuction-endless-loop1.ll | 2 +- .../schedule-constuction-endless-loop2.ll | 2 +- ...tly-contructed-in-case-of-infinite-loop.ll | 2 +- .../scop-affine-parameter-ordering.ll | 2 +- polly/test/ScopInfo/sign_wrapped_set.ll | 2 +- polly/test/ScopInfo/simple_loop_1.ll | 2 +- polly/test/ScopInfo/simple_loop_2.ll | 2 +- polly/test/ScopInfo/simple_loop_unsigned.ll | 2 +- polly/test/ScopInfo/simple_loop_unsigned_2.ll | 2 +- polly/test/ScopInfo/simple_loop_unsigned_3.ll | 2 +- .../ScopInfo/simple_nonaffine_loop_not.ll | 2 +- polly/test/ScopInfo/smax.ll | 2 +- polly/test/ScopInfo/statistics.ll | 2 +- .../stmt_split_exit_of_region_stmt.ll | 2 +- .../ScopInfo/stmt_split_no_after_split.ll | 2 +- .../test/ScopInfo/stmt_split_no_dependence.ll | 2 +- polly/test/ScopInfo/stmt_split_on_store.ll | 2 +- .../ScopInfo/stmt_split_on_synthesizable.ll | 2 +- .../stmt_split_phi_in_beginning_bb.ll | 2 +- polly/test/ScopInfo/stmt_split_phi_in_stmt.ll | 2 +- .../ScopInfo/stmt_split_scalar_dependence.ll | 2 +- polly/test/ScopInfo/stmt_split_within_loop.ll | 2 +- .../stmt_with_read_but_without_sideffect.ll | 2 +- polly/test/ScopInfo/switch-1.ll | 4 +- polly/test/ScopInfo/switch-2.ll | 4 +- polly/test/ScopInfo/switch-3.ll | 4 +- polly/test/ScopInfo/switch-4.ll | 4 +- polly/test/ScopInfo/switch-5.ll | 4 +- polly/test/ScopInfo/switch-6.ll | 4 +- polly/test/ScopInfo/switch-7.ll | 5 +- polly/test/ScopInfo/tempscop-printing.ll | 2 +- .../ScopInfo/test-wrapping-in-condition.ll | 4 +- polly/test/ScopInfo/truncate-1.ll | 2 +- polly/test/ScopInfo/truncate-2.ll | 2 +- polly/test/ScopInfo/truncate-3.ll | 2 +- polly/test/ScopInfo/two-loops-one-infinite.ll | 2 +- .../two-loops-right-after-each-other.ll | 2 +- polly/test/ScopInfo/undef_in_cond.ll | 2 +- polly/test/ScopInfo/unnamed_nonaffine.ll | 4 +- polly/test/ScopInfo/unnamed_stmts.ll | 2 +- .../ScopInfo/unpredictable_nonscop_loop.ll | 2 +- .../test/ScopInfo/unprofitable_scalar-accs.ll | 4 +- polly/test/ScopInfo/unsigned-condition.ll | 2 +- polly/test/ScopInfo/unsigned-division-1.ll | 2 +- polly/test/ScopInfo/unsigned-division-2.ll | 2 +- polly/test/ScopInfo/unsigned-division-3.ll | 2 +- polly/test/ScopInfo/unsigned-division-4.ll | 2 +- polly/test/ScopInfo/unsigned-division-5.ll | 2 +- polly/test/ScopInfo/unsigned_wrap_uge.ll | 2 +- polly/test/ScopInfo/unsigned_wrap_ugt.ll | 2 +- polly/test/ScopInfo/unsigned_wrap_ule.ll | 2 +- polly/test/ScopInfo/unsigned_wrap_ult.ll | 2 +- polly/test/ScopInfo/user_context.ll | 8 +- ...ed_assumptions-in-bb-signed-conditional.ll | 4 +- .../user_provided_assumptions-in-bb-signed.ll | 2 +- ...ser_provided_assumptions-in-bb-unsigned.ll | 4 +- .../ScopInfo/user_provided_assumptions.ll | 4 +- .../ScopInfo/user_provided_assumptions_2.ll | 4 +- .../ScopInfo/user_provided_assumptions_3.ll | 4 +- ...ser_provided_non_dominating_assumptions.ll | 4 +- polly/test/ScopInfo/variant_base_pointer.ll | 4 +- .../ScopInfo/variant_load_empty_domain.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_0.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_1.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_2.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_3.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_4.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_5.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_6.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_7.ll | 2 +- .../ScopInfo/wraping_signed_expr_slow_1.ll | 2 +- .../ScopInfo/wraping_signed_expr_slow_2.ll | 2 +- polly/test/ScopInfo/zero_ext_of_truncate.ll | 2 +- polly/test/ScopInfo/zero_ext_of_truncate_2.ll | 2 +- .../test/ScopInfo/zero_ext_space_mismatch.ll | 2 +- polly/test/ScopInliner/invariant-load-func.ll | 2 +- polly/test/Simplify/coalesce_3partials.ll | 2 +- .../Simplify/coalesce_disjointelements.ll | 2 +- polly/test/Simplify/coalesce_overlapping.ll | 2 +- polly/test/Simplify/coalesce_partial.ll | 2 +- polly/test/Simplify/dead_access_load.ll | 3 +- polly/test/Simplify/dead_access_phi.ll | 3 +- polly/test/Simplify/dead_access_value.ll | 3 +- polly/test/Simplify/dead_instruction.ll | 3 +- polly/test/Simplify/emptyaccessdomain.ll | 2 +- polly/test/Simplify/exit_phi_accesses-2.ll | 2 +- polly/test/Simplify/func-b320a7.ll | 2 +- polly/test/Simplify/gemm.ll | 2 +- .../Simplify/nocoalesce_differentvalues.ll | 2 +- .../Simplify/nocoalesce_elementmismatch.ll | 2 +- polly/test/Simplify/nocoalesce_readbetween.ll | 2 +- .../test/Simplify/nocoalesce_writebetween.ll | 2 +- polly/test/Simplify/notdead_region_exitphi.ll | 3 +- .../test/Simplify/notdead_region_innerphi.ll | 3 +- .../test/Simplify/notredundant_region_loop.ll | 2 +- .../Simplify/notredundant_region_middle.ll | 3 +- .../notredundant_synthesizable_unknownit.ll | 3 +- ...ut-of-scop-use-in-region-entry-phi-node.ll | 2 +- polly/test/Simplify/overwritten.ll | 3 +- polly/test/Simplify/overwritten_3phi.ll | 2 +- polly/test/Simplify/overwritten_3store.ll | 3 +- .../overwritten_implicit_and_explicit.ll | 2 +- .../test/Simplify/overwritten_loadbetween.ll | 3 +- polly/test/Simplify/overwritten_scalar.ll | 2 +- polly/test/Simplify/pass_existence.ll | 3 +- polly/test/Simplify/phi_in_regionstmt.ll | 3 +- polly/test/Simplify/pr33323.ll | 2 +- polly/test/Simplify/redundant.ll | 3 +- .../test/Simplify/redundant_differentindex.ll | 3 +- polly/test/Simplify/redundant_region.ll | 2 +- .../test/Simplify/redundant_region_scalar.ll | 2 +- polly/test/Simplify/redundant_scalarwrite.ll | 2 +- polly/test/Simplify/redundant_storebetween.ll | 3 +- polly/test/Simplify/scalability1.ll | 2 +- polly/test/Simplify/scalability2.ll | 2 +- polly/test/Simplify/sweep_mapped_phi.ll | 2 +- polly/test/Simplify/sweep_mapped_value.ll | 2 +- .../Simplify/ununsed_read_in_region_entry.ll | 4 +- polly/test/Support/Plugins.ll | 2 +- polly/test/Support/defaultpipelines.ll | 12 +-- polly/test/Support/dumpfunction.ll | 4 +- polly/test/Support/dumpmodule.ll | 4 +- polly/test/Support/exportjson.ll | 2 +- polly/test/Support/isl-args.ll | 8 +- polly/test/Support/pipelineposition.ll | 6 +- polly/test/Support/pollyDebug.ll | 2 +- polly/test/lit.site.cfg.in | 7 +- polly/test/polly.ll | 2 +- 1026 files changed, 1404 insertions(+), 1472 deletions(-) diff --git a/polly/test/CodeGen/20100617.ll b/polly/test/CodeGen/20100617.ll index 71a889f067b8..320c48192a8a 100644 --- a/polly/test/CodeGen/20100617.ll +++ b/polly/test/CodeGen/20100617.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" define void @init_array() nounwind { diff --git a/polly/test/CodeGen/20100622.ll b/polly/test/CodeGen/20100622.ll index 872d6a0d75cf..584107df8971 100644 --- a/polly/test/CodeGen/20100622.ll +++ b/polly/test/CodeGen/20100622.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-codegen -disable-output < %s -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | not FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | not FileCheck %s 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:32:32" diff --git a/polly/test/CodeGen/20100707.ll b/polly/test/CodeGen/20100707.ll index 338198084fc7..1a4d3556bae8 100644 --- a/polly/test/CodeGen/20100707.ll +++ b/polly/test/CodeGen/20100707.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" define void @clause_SetSplitField(i32 %Length) nounwind inlinehint { diff --git a/polly/test/CodeGen/20100707_2.ll b/polly/test/CodeGen/20100707_2.ll index df784c6d7957..96f329ccbfa9 100644 --- a/polly/test/CodeGen/20100707_2.ll +++ b/polly/test/CodeGen/20100707_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" @win193 = external global [4 x [36 x double]], align 32 ; [#uses=3] diff --git a/polly/test/CodeGen/20100708.ll b/polly/test/CodeGen/20100708.ll index 50b8e385df53..00fb6fa694c1 100644 --- a/polly/test/CodeGen/20100708.ll +++ b/polly/test/CodeGen/20100708.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-detect < %s +; RUN: opt %loadPolly '-passes=print' < %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-n8:16:32:64" define fastcc void @execute() nounwind { diff --git a/polly/test/CodeGen/20100708_2.ll b/polly/test/CodeGen/20100708_2.ll index 2f4807d9e4d7..67f3913d69d4 100644 --- a/polly/test/CodeGen/20100708_2.ll +++ b/polly/test/CodeGen/20100708_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" define void @init_array() nounwind { diff --git a/polly/test/CodeGen/20100713.ll b/polly/test/CodeGen/20100713.ll index edd352a4c4cc..73ba0272e5c9 100644 --- a/polly/test/CodeGen/20100713.ll +++ b/polly/test/CodeGen/20100713.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" define void @fft_float(i32 %NumSamples) nounwind { diff --git a/polly/test/CodeGen/20100713_2.ll b/polly/test/CodeGen/20100713_2.ll index 92f8959d91d6..c146e00d4231 100644 --- a/polly/test/CodeGen/20100713_2.ll +++ b/polly/test/CodeGen/20100713_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" define hidden void @luaD_callhook() nounwind { diff --git a/polly/test/CodeGen/20100717.ll b/polly/test/CodeGen/20100717.ll index a400eeaa3370..24114f2c70c6 100644 --- a/polly/test/CodeGen/20100717.ll +++ b/polly/test/CodeGen/20100717.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -disable-output < %s +; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %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-n8:16:32:64" define void @matrixTranspose(ptr %A) nounwind { diff --git a/polly/test/CodeGen/20100718-DomInfo-2.ll b/polly/test/CodeGen/20100718-DomInfo-2.ll index 512b4c5c99af..396a1009a415 100644 --- a/polly/test/CodeGen/20100718-DomInfo-2.ll +++ b/polly/test/CodeGen/20100718-DomInfo-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -verify-dom-info -disable-output < %s +; RUN: opt %loadPolly -passes=polly-codegen -verify-dom-info -disable-output < %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-n8:16:32:64" define void @getNonAffNeighbour() nounwind { diff --git a/polly/test/CodeGen/20100718-DomInfo.ll b/polly/test/CodeGen/20100718-DomInfo.ll index e12334359c33..7a7f4300e107 100644 --- a/polly/test/CodeGen/20100718-DomInfo.ll +++ b/polly/test/CodeGen/20100718-DomInfo.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -verify-dom-info -disable-output < %s +; RUN: opt %loadPolly -passes=polly-codegen -verify-dom-info -disable-output < %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-n8:16:32:64" define void @intrapred_luma_16x16(i32 %predmode) nounwind { diff --git a/polly/test/CodeGen/20100720-MultipleConditions.ll b/polly/test/CodeGen/20100720-MultipleConditions.ll index 9f2268713853..ca3758d95681 100644 --- a/polly/test/CodeGen/20100720-MultipleConditions.ll +++ b/polly/test/CodeGen/20100720-MultipleConditions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-ast -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ;int bar1(); ;int bar2(); diff --git a/polly/test/CodeGen/20100809-IndependentBlock.ll b/polly/test/CodeGen/20100809-IndependentBlock.ll index 8d596689d8ae..849594afa871 100644 --- a/polly/test/CodeGen/20100809-IndependentBlock.ll +++ b/polly/test/CodeGen/20100809-IndependentBlock.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -disable-output < %s +; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %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-n8:16:32:64" define void @cfft2(ptr %x) nounwind { entry: diff --git a/polly/test/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll b/polly/test/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll index 261a205560b5..313dad6fe3f7 100644 --- a/polly/test/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll +++ b/polly/test/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -disable-output < %s +; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %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-n8:16:32:64" diff --git a/polly/test/CodeGen/20101030-Overflow.ll b/polly/test/CodeGen/20101030-Overflow.ll index caaa4851f93e..bf91272399d2 100644 --- a/polly/test/CodeGen/20101030-Overflow.ll +++ b/polly/test/CodeGen/20101030-Overflow.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" define void @compdecomp() nounwind { diff --git a/polly/test/CodeGen/20101103-Overflow3.ll b/polly/test/CodeGen/20101103-Overflow3.ll index b2faf14fba0b..bab00231758f 100644 --- a/polly/test/CodeGen/20101103-Overflow3.ll +++ b/polly/test/CodeGen/20101103-Overflow3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" define void @Reflection_coefficients(ptr %r) nounwind { bb20: diff --git a/polly/test/CodeGen/20101103-signmissmatch.ll b/polly/test/CodeGen/20101103-signmissmatch.ll index e157d292dc8a..d12ed4be4cdf 100644 --- a/polly/test/CodeGen/20101103-signmissmatch.ll +++ b/polly/test/CodeGen/20101103-signmissmatch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" define void @CleanNet() nounwind { diff --git a/polly/test/CodeGen/20110226-Ignore-Dead-Code.ll b/polly/test/CodeGen/20110226-Ignore-Dead-Code.ll index c792d8c3d0bf..1c82d2aba887 100644 --- a/polly/test/CodeGen/20110226-Ignore-Dead-Code.ll +++ b/polly/test/CodeGen/20110226-Ignore-Dead-Code.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" define void @main() nounwind { diff --git a/polly/test/CodeGen/20110226-PHI-Node-removed.ll b/polly/test/CodeGen/20110226-PHI-Node-removed.ll index 3458d75c47a0..d7003882a776 100644 --- a/polly/test/CodeGen/20110226-PHI-Node-removed.ll +++ b/polly/test/CodeGen/20110226-PHI-Node-removed.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" diff --git a/polly/test/CodeGen/20120316-InvalidCast.ll b/polly/test/CodeGen/20120316-InvalidCast.ll index 8355cc51c468..14717dd29b23 100644 --- a/polly/test/CodeGen/20120316-InvalidCast.ll +++ b/polly/test/CodeGen/20120316-InvalidCast.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; CHECK: polly.start diff --git a/polly/test/CodeGen/20120403-RHS-type-mismatch.ll b/polly/test/CodeGen/20120403-RHS-type-mismatch.ll index 1d629e388452..2d3e3b02dd38 100644 --- a/polly/test/CodeGen/20120403-RHS-type-mismatch.ll +++ b/polly/test/CodeGen/20120403-RHS-type-mismatch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %s ; We just check that this compilation does not crash. diff --git a/polly/test/CodeGen/20130221.ll b/polly/test/CodeGen/20130221.ll index 45414671081a..e5f63adabc25 100644 --- a/polly/test/CodeGen/20130221.ll +++ b/polly/test/CodeGen/20130221.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %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-n8:16:32:64-S128" define void @list_sequence(ptr %A) { diff --git a/polly/test/CodeGen/20150328-SCEVExpanderIntroducesNewIV.ll b/polly/test/CodeGen/20150328-SCEVExpanderIntroducesNewIV.ll index d54be5c3f35f..786adc7286e6 100644 --- a/polly/test/CodeGen/20150328-SCEVExpanderIntroducesNewIV.ll +++ b/polly/test/CodeGen/20150328-SCEVExpanderIntroducesNewIV.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/Intrinsics/llvm-expect.ll b/polly/test/CodeGen/Intrinsics/llvm-expect.ll index 84057e276521..ac65f6f439ae 100644 --- a/polly/test/CodeGen/Intrinsics/llvm-expect.ll +++ b/polly/test/CodeGen/Intrinsics/llvm-expect.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; Check that we generate code without crashing. ; diff --git a/polly/test/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll b/polly/test/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll index b04319550938..fb02d7f55e23 100644 --- a/polly/test/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll +++ b/polly/test/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll @@ -1,6 +1,6 @@ ; This test checks that we do not accidently mutate the debug info when ; inserting loop parallel metadata. -; RUN: opt %loadPolly < %s -S -polly -polly-codegen -polly-ast-detect-parallel | FileCheck %s +; RUN: opt %loadPolly < %s -S -polly -passes=polly-codegen -polly-ast-detect-parallel | FileCheck %s ; CHECK-NOT: !7 = !{!7} target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll b/polly/test/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll index 7b131c5ebcbd..c6c27b4a75a8 100644 --- a/polly/test/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll +++ b/polly/test/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-ast-detect-parallel -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-ast-detect-parallel -S < %s | FileCheck %s ; ; Check that we mark multiple parallel loops correctly including the memory instructions. ; diff --git a/polly/test/CodeGen/LoopParallelMD/single_loop_param_parallel.ll b/polly/test/CodeGen/LoopParallelMD/single_loop_param_parallel.ll index ec927acb1ec7..f91bd64a895a 100644 --- a/polly/test/CodeGen/LoopParallelMD/single_loop_param_parallel.ll +++ b/polly/test/CodeGen/LoopParallelMD/single_loop_param_parallel.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=SEQUENTIAL -; RUN: opt %loadPolly -polly-codegen -polly-ast-detect-parallel -S < %s | FileCheck %s -check-prefix=PARALLEL +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=SEQUENTIAL +; RUN: opt %loadPolly -passes=polly-codegen -polly-ast-detect-parallel -S < %s | FileCheck %s -check-prefix=PARALLEL 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-n8:16:32:64" ; This is a trivially parallel loop. We just use it to ensure that we actually diff --git a/polly/test/CodeGen/MemAccess/bad_alignment.ll b/polly/test/CodeGen/MemAccess/bad_alignment.ll index 32f3cfe963b7..2f297384ccdb 100644 --- a/polly/test/CodeGen/MemAccess/bad_alignment.ll +++ b/polly/test/CodeGen/MemAccess/bad_alignment.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -disable-output 2>&1 < %s | FileCheck %s +; RUN: not --crash opt %loadPolly -passes=polly-import-jscop -disable-output 2>&1 < %s | FileCheck %s ; ; Check that we do not allow to access elements not accessed before because the ; alignment information would become invalid. diff --git a/polly/test/CodeGen/MemAccess/codegen_address_space.ll b/polly/test/CodeGen/MemAccess/codegen_address_space.ll index 7c9b12d64f9c..986775ed5717 100644 --- a/polly/test/CodeGen/MemAccess/codegen_address_space.ll +++ b/polly/test/CodeGen/MemAccess/codegen_address_space.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen < %s -S | FileCheck %s +;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed < %s -S | FileCheck %s ;int A[100]; ; diff --git a/polly/test/CodeGen/MemAccess/codegen_constant_offset.ll b/polly/test/CodeGen/MemAccess/codegen_constant_offset.ll index e008a789fe7d..b4168b89267b 100644 --- a/polly/test/CodeGen/MemAccess/codegen_constant_offset.ll +++ b/polly/test/CodeGen/MemAccess/codegen_constant_offset.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen < %s -S | FileCheck %s +;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed < %s -S | FileCheck %s ;int A[100]; ; diff --git a/polly/test/CodeGen/MemAccess/codegen_simple.ll b/polly/test/CodeGen/MemAccess/codegen_simple.ll index 5ba6f3269fb9..cf2a57ad8a1f 100644 --- a/polly/test/CodeGen/MemAccess/codegen_simple.ll +++ b/polly/test/CodeGen/MemAccess/codegen_simple.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen < %s -S | FileCheck %s +;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed < %s -S | FileCheck %s ;int A[100]; ; diff --git a/polly/test/CodeGen/MemAccess/codegen_simple_float.ll b/polly/test/CodeGen/MemAccess/codegen_simple_float.ll index cf8913fc5197..bdd0e56b0a29 100644 --- a/polly/test/CodeGen/MemAccess/codegen_simple_float.ll +++ b/polly/test/CodeGen/MemAccess/codegen_simple_float.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen < %s -S | FileCheck %s +;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed < %s -S | FileCheck %s ; ;float A[100]; ; diff --git a/polly/test/CodeGen/MemAccess/codegen_simple_md.ll b/polly/test/CodeGen/MemAccess/codegen_simple_md.ll index e4afcc8d2243..8f676725146d 100644 --- a/polly/test/CodeGen/MemAccess/codegen_simple_md.ll +++ b/polly/test/CodeGen/MemAccess/codegen_simple_md.ll @@ -1,5 +1,5 @@ -;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed+withconst -polly-codegen < %s -S | FileCheck -check-prefix=WITHCONST %s -;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed+withoutconst -polly-codegen < %s -S | FileCheck -check-prefix=WITHOUTCONST %s +;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed+withconst < %s -S | FileCheck -check-prefix=WITHCONST %s +;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed+withoutconst < %s -S | FileCheck -check-prefix=WITHOUTCONST %s ;int A[1040]; ; diff --git a/polly/test/CodeGen/MemAccess/codegen_simple_md_float.ll b/polly/test/CodeGen/MemAccess/codegen_simple_md_float.ll index c9913f3ed873..1ac1efa2f727 100644 --- a/polly/test/CodeGen/MemAccess/codegen_simple_md_float.ll +++ b/polly/test/CodeGen/MemAccess/codegen_simple_md_float.ll @@ -1,5 +1,5 @@ -;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed+withconst -polly-codegen < %s -S | FileCheck -check-prefix=WITHCONST %s -;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed+withoutconst -polly-codegen < %s -S | FileCheck -check-prefix=WITHOUTCONST %s +;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed+withconst < %s -S | FileCheck -check-prefix=WITHCONST %s +;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed+withoutconst < %s -S | FileCheck -check-prefix=WITHOUTCONST %s ; ;float A[1040]; ; diff --git a/polly/test/CodeGen/MemAccess/different_types.ll b/polly/test/CodeGen/MemAccess/different_types.ll index 624de62911ff..52fca9d87759 100644 --- a/polly/test/CodeGen/MemAccess/different_types.ll +++ b/polly/test/CodeGen/MemAccess/different_types.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-import-jscop \ +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ ; RUN: \ -; RUN: -polly-codegen -S < %s | FileCheck %s +; RUN: -S < %s | FileCheck %s ; ; void foo(float A[], float B[]) { ; for (long i = 0; i < 100; i++) diff --git a/polly/test/CodeGen/MemAccess/generate-all.ll b/polly/test/CodeGen/MemAccess/generate-all.ll index 6f92ba13587e..a64c6db0978c 100644 --- a/polly/test/CodeGen/MemAccess/generate-all.ll +++ b/polly/test/CodeGen/MemAccess/generate-all.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-codegen -polly-codegen-generate-expressions=false \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-codegen-generate-expressions=false \ ; RUN: -S < %s | FileCheck %s -check-prefix=SCEV -; RUN: opt %loadPolly -polly-codegen -polly-codegen-generate-expressions=true \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-codegen-generate-expressions=true \ ; RUN: -S < %s | FileCheck %s -check-prefix=ASTEXPR ; ; void foo(float A[]) { diff --git a/polly/test/CodeGen/MemAccess/invariant_base_ptr.ll b/polly/test/CodeGen/MemAccess/invariant_base_ptr.ll index a6d1de0aac63..12c38b7a66c4 100644 --- a/polly/test/CodeGen/MemAccess/invariant_base_ptr.ll +++ b/polly/test/CodeGen/MemAccess/invariant_base_ptr.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-import-jscop \ -; RUN: -polly-codegen -polly-invariant-load-hoisting -S \ +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ +; RUN: -polly-invariant-load-hoisting -S \ ; RUN: 2>&1 < %s | FileCheck %s ; Setting new access functions where the base pointer of the array that is newly diff --git a/polly/test/CodeGen/MemAccess/multiple_types.ll b/polly/test/CodeGen/MemAccess/multiple_types.ll index 1793bd30fc5b..7c0ddffbd6d1 100644 --- a/polly/test/CodeGen/MemAccess/multiple_types.ll +++ b/polly/test/CodeGen/MemAccess/multiple_types.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,polly-codegen' \ ; RUN: -polly-allow-differing-element-types \ -; RUN: -polly-codegen -S < %s | FileCheck %s +; RUN: -S < %s | FileCheck %s ; ; // Check that accessing one array with different types works. ; void multiple_types(char *Short, char *Float, char *Double) { diff --git a/polly/test/CodeGen/MemAccess/simple.ll b/polly/test/CodeGen/MemAccess/simple.ll index 39e8a2c91b79..8964e189b8a7 100644 --- a/polly/test/CodeGen/MemAccess/simple.ll +++ b/polly/test/CodeGen/MemAccess/simple.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -stats < %s 2>&1 | FileCheck %s +;RUN: opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -stats < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ;int A[100]; diff --git a/polly/test/CodeGen/MemAccess/update_access_functions.ll b/polly/test/CodeGen/MemAccess/update_access_functions.ll index 05d208708a36..00644c52ecd7 100644 --- a/polly/test/CodeGen/MemAccess/update_access_functions.ll +++ b/polly/test/CodeGen/MemAccess/update_access_functions.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-import-jscop \ -; RUN: -polly-import-jscop-postfix=transformed -polly-codegen \ +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ +; RUN: -polly-import-jscop-postfix=transformed \ ; RUN: < %s -S | FileCheck %s ; CHECK-LABEL: polly.stmt.loop1: diff --git a/polly/test/CodeGen/OpenMP/alias-metadata.ll b/polly/test/CodeGen/OpenMP/alias-metadata.ll index 07d79631b2cb..e7ca6abac283 100644 --- a/polly/test/CodeGen/OpenMP/alias-metadata.ll +++ b/polly/test/CodeGen/OpenMP/alias-metadata.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-parallel -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -S < %s | FileCheck %s ; ; void foo(float *A, float *B) { ; for (long i = 0; i < 1000; i++) diff --git a/polly/test/CodeGen/OpenMP/floord-as-argument-to-subfunction.ll b/polly/test/CodeGen/OpenMP/floord-as-argument-to-subfunction.ll index eb9dfcd9e920..40ea62088940 100644 --- a/polly/test/CodeGen/OpenMP/floord-as-argument-to-subfunction.ll +++ b/polly/test/CodeGen/OpenMP/floord-as-argument-to-subfunction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-opt-max-coefficient=-1 -polly-parallel -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-opt-max-coefficient=-1 -polly-parallel -passes=polly-codegen -S < %s | FileCheck %s ; ; Check that we do not crash but generate parallel code ; diff --git a/polly/test/CodeGen/OpenMP/inlineasm.ll b/polly/test/CodeGen/OpenMP/inlineasm.ll index 69b1b0aa53f3..a2ca2f79d649 100644 --- a/polly/test/CodeGen/OpenMP/inlineasm.ll +++ b/polly/test/CodeGen/OpenMP/inlineasm.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-parallel -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-opt-isl,polly-codegen' -polly-parallel -S < %s | FileCheck %s ; llvm.org/PR51960 ; CHECK-LABEL: define internal void @foo_polly_subfn diff --git a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded.ll b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded.ll index 30beef5b0709..9394755254a7 100644 --- a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded.ll +++ b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ ; RUN: -polly-parallel-force -S < %s | FileCheck %s ; ; Test to verify that we hand down the preloaded A[0] to the OpenMP subfunction. diff --git a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_different_bb.ll b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_different_bb.ll index fe5d2ab8c96d..48f075c37d82 100644 --- a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_different_bb.ll +++ b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_different_bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ ; RUN: -polly-parallel-force -S < %s | FileCheck %s ; ; Test to verify that we hand down the preloaded A[0] to the OpenMP subfunction. diff --git a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_pass_only_needed.ll b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_pass_only_needed.ll index 49b9321c40b8..e4273384dd72 100644 --- a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_pass_only_needed.ll +++ b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_pass_only_needed.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ ; RUN: -polly-parallel-force -S < %s | FileCheck %s ; ; Test to verify that we hand down the preloaded A[0] to the OpenMP subfunction but diff --git a/polly/test/CodeGen/OpenMP/invariant_base_pointers_preloaded.ll b/polly/test/CodeGen/OpenMP/invariant_base_pointers_preloaded.ll index 06c4cdab45f1..8400a5594d10 100644 --- a/polly/test/CodeGen/OpenMP/invariant_base_pointers_preloaded.ll +++ b/polly/test/CodeGen/OpenMP/invariant_base_pointers_preloaded.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ ; RUN: -polly-parallel-force -S < %s | FileCheck %s ; ; Test to verify that we hand down the preloaded A[0] to the OpenMP subfunction. diff --git a/polly/test/CodeGen/OpenMP/loop-body-references-outer-iv.ll b/polly/test/CodeGen/OpenMP/loop-body-references-outer-iv.ll index db58c3ab7593..b3297b5b32af 100644 --- a/polly/test/CodeGen/OpenMP/loop-body-references-outer-iv.ll +++ b/polly/test/CodeGen/OpenMP/loop-body-references-outer-iv.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; This code has failed the scev based code generation as the scev in the scop ; contains an AddRecExpr of an outer loop. When generating code, we did not diff --git a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-2.ll b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-2.ll index c2ddc1e26496..c478e91eb9db 100644 --- a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-2.ll +++ b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; AST: #pragma simd ; AST: #pragma omp parallel for diff --git a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-3.ll b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-3.ll index 0f025bb94112..26c2fe6da6ca 100644 --- a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-3.ll +++ b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-parallel -polly-parallel-force -polly-invariant-load-hoisting=true -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -basic-aa -polly-parallel -polly-parallel-force -polly-invariant-load-hoisting=true -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-parallel -polly-parallel-force -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-parallel -polly-parallel-force -polly-invariant-load-hoisting=true -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; The interesting part of this test case is the instruction: ; %tmp = bitcast i8* %call to i64** diff --git a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values.ll b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values.ll index f9612d77533d..debd89ab151d 100644 --- a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values.ll +++ b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=IR ; Make sure we correctly forward the reference to 'A' to the OpenMP subfunction. ; diff --git a/polly/test/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll b/polly/test/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll index da9da18c89b2..db2299e5e73d 100644 --- a/polly/test/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll +++ b/polly/test/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-codegen -S < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=IR ; ; float A[100]; ; diff --git a/polly/test/CodeGen/OpenMP/mapped-phi-access.ll b/polly/test/CodeGen/OpenMP/mapped-phi-access.ll index 1b8433693abf..4b71760ea224 100644 --- a/polly/test/CodeGen/OpenMP/mapped-phi-access.ll +++ b/polly/test/CodeGen/OpenMP/mapped-phi-access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-parallel -polly-delicm -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-parallel '-passes=polly-delicm,polly-codegen' -S < %s | FileCheck %s ; ; Verify that -polly-parallel can handle mapped scalar MemoryAccesses. ; diff --git a/polly/test/CodeGen/OpenMP/matmul-parallel.ll b/polly/test/CodeGen/OpenMP/matmul-parallel.ll index 5ee9a7c7a824..1f3ad5ca8426 100644 --- a/polly/test/CodeGen/OpenMP/matmul-parallel.ll +++ b/polly/test/CodeGen/OpenMP/matmul-parallel.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-opt-isl -polly-ast -disable-output -debug-only=polly-ast < %s 2>&1 | FileCheck --check-prefix=AST %s -; RUN: opt %loadPolly -polly-parallel -polly-opt-isl -polly-codegen -S < %s | FileCheck --check-prefix=CODEGEN %s +; RUN: opt %loadPolly -polly-parallel '-passes=polly-opt-isl,print' -disable-output -debug-only=polly-ast < %s 2>&1 | FileCheck --check-prefix=AST %s +; RUN: opt %loadPolly -polly-parallel '-passes=polly-opt-isl,polly-codegen' -S < %s | FileCheck --check-prefix=CODEGEN %s ; REQUIRES: asserts ; Parallelization of detected matrix-multiplication. diff --git a/polly/test/CodeGen/OpenMP/recomputed-srem.ll b/polly/test/CodeGen/OpenMP/recomputed-srem.ll index cfae8e943cf1..3411308a4b11 100644 --- a/polly/test/CodeGen/OpenMP/recomputed-srem.ll +++ b/polly/test/CodeGen/OpenMP/recomputed-srem.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-codegen -polly-parallel \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -passes=polly-codegen -polly-parallel \ ; RUN: -polly-parallel-force -S < %s | FileCheck %s ; ; Test to verify that we pass %rem96 to the parallel subfunction. diff --git a/polly/test/CodeGen/OpenMP/reference-argument-from-non-affine-region.ll b/polly/test/CodeGen/OpenMP/reference-argument-from-non-affine-region.ll index f243c3a04949..247e89be0027 100644 --- a/polly/test/CodeGen/OpenMP/reference-argument-from-non-affine-region.ll +++ b/polly/test/CodeGen/OpenMP/reference-argument-from-non-affine-region.ll @@ -1,15 +1,15 @@ ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -polly-codegen \ +; RUN: -polly-parallel-force -passes=polly-codegen \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=IR ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -polly-codegen -polly-scheduling=runtime \ +; RUN: -polly-parallel-force -passes=polly-codegen -polly-scheduling=runtime \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=IR ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM \ +; RUN: -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=LIBOMP-IR diff --git a/polly/test/CodeGen/OpenMP/reference-other-bb.ll b/polly/test/CodeGen/OpenMP/reference-other-bb.ll index b7abdc23d258..2c399f12af24 100644 --- a/polly/test/CodeGen/OpenMP/reference-other-bb.ll +++ b/polly/test/CodeGen/OpenMP/reference-other-bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; IR: @foo_polly_subfn target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/OpenMP/reference-preceeding-loop.ll b/polly/test/CodeGen/OpenMP/reference-preceeding-loop.ll index b88589f39a6f..90a95dccbcb1 100644 --- a/polly/test/CodeGen/OpenMP/reference-preceeding-loop.ll +++ b/polly/test/CodeGen/OpenMP/reference-preceeding-loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; - Test the case where scalar evolution references a loop that is outside diff --git a/polly/test/CodeGen/OpenMP/reference_latest.ll b/polly/test/CodeGen/OpenMP/reference_latest.ll index 54875c2630f0..696c3c74ad0e 100644 --- a/polly/test/CodeGen/OpenMP/reference_latest.ll +++ b/polly/test/CodeGen/OpenMP/reference_latest.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-delicm -polly-simplify -polly-parallel -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-delicm,polly-simplify,polly-codegen' -polly-parallel -S < %s | FileCheck %s ; ; Test that parallel codegen handles scalars mapped to other arrays. ; After mapping "store double %add10" references the array "MemRef2". diff --git a/polly/test/CodeGen/OpenMP/scev-rewriting.ll b/polly/test/CodeGen/OpenMP/scev-rewriting.ll index 1b229fc19d25..551946fc698b 100644 --- a/polly/test/CodeGen/OpenMP/scev-rewriting.ll +++ b/polly/test/CodeGen/OpenMP/scev-rewriting.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly < %s -polly-vectorizer=stripmine -polly-parallel -polly-parallel-force -polly-process-unprofitable -polly-codegen -S | FileCheck %s +; RUN: opt %loadPolly < %s -polly-vectorizer=stripmine -polly-parallel -polly-parallel-force -polly-process-unprofitable -passes=polly-codegen -S | FileCheck %s ; CHECK: define internal void @DoStringSort_polly_subfn target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" target triple = "aarch64-unknown-linux-gnueabi" diff --git a/polly/test/CodeGen/OpenMP/single_loop.ll b/polly/test/CodeGen/OpenMP/single_loop.ll index f79653a08d21..7e45ab08080e 100644 --- a/polly/test/CodeGen/OpenMP/single_loop.ll +++ b/polly/test/CodeGen/OpenMP/single_loop.ll @@ -1,14 +1,14 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-import-jscop -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST-STRIDE4 -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-import-jscop -polly-codegen -S < %s | FileCheck %s -check-prefix=IR-STRIDE4 +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=polly-import-jscop,print' -disable-output < %s | FileCheck %s -check-prefix=AST-STRIDE4 +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=polly-import-jscop,polly-codegen' -S < %s | FileCheck %s -check-prefix=IR-STRIDE4 -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM -polly-scheduling=static -polly-scheduling-chunksize=43 -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-STATIC-CHUNKED -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM -polly-scheduling=static -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-STATIC -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM -polly-scheduling=dynamic -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-DYNAMIC -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM -polly-scheduling=dynamic -polly-scheduling-chunksize=4 -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-DYNAMIC-FOUR -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-import-jscop -polly-codegen -polly-omp-backend=LLVM -S < %s | FileCheck %s -check-prefix=LIBOMP-IR-STRIDE4 +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM -polly-scheduling=static -polly-scheduling-chunksize=43 -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-STATIC-CHUNKED +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM -polly-scheduling=static -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-STATIC +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM -polly-scheduling=dynamic -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-DYNAMIC +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM -polly-scheduling=dynamic -polly-scheduling-chunksize=4 -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-DYNAMIC-FOUR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=polly-import-jscop,polly-codegen' -polly-omp-backend=LLVM -S < %s | FileCheck %s -check-prefix=LIBOMP-IR-STRIDE4 ; This extensive test case tests the creation of the full set of OpenMP calls ; as well as the subfunction creation using a trivial loop as example. diff --git a/polly/test/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll b/polly/test/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll index 50da5dd2b7c0..519cbbc496b1 100644 --- a/polly/test/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll +++ b/polly/test/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -tbaa -polly-parallel -polly-parallel-force -polly-parallel-force -polly-invariant-load-hoisting=true -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -tbaa -polly-parallel -polly-parallel-force -polly-parallel-force -polly-invariant-load-hoisting=true -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -aa-pipeline=tbaa -polly-parallel -polly-parallel-force -polly-parallel-force -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -aa-pipeline=tbaa -polly-parallel -polly-parallel-force -polly-parallel-force -polly-invariant-load-hoisting=true -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; #define N 1024 ; float A[N]; diff --git a/polly/test/CodeGen/OpenMP/single_loop_with_param.ll b/polly/test/CodeGen/OpenMP/single_loop_with_param.ll index d01b7a2fdcad..0288d4c8f5e4 100644 --- a/polly/test/CodeGen/OpenMP/single_loop_with_param.ll +++ b/polly/test/CodeGen/OpenMP/single_loop_with_param.ll @@ -1,15 +1,15 @@ ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -polly-codegen \ +; RUN: -polly-parallel-force -passes=polly-codegen \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=IR ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM \ +; RUN: -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=LIBOMP-IR ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM \ +; RUN: -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM \ ; RUN: -polly-scheduling=static \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=LIBOMP-STATIC-IR diff --git a/polly/test/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll b/polly/test/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll index 05c6ed177e9c..133a00c3be71 100644 --- a/polly/test/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll +++ b/polly/test/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; This test case verifies that we create correct code even if two OpenMP loops ; share common outer variables. diff --git a/polly/test/CodeGen/PHIInExit.ll b/polly/test/CodeGen/PHIInExit.ll index eadd6054386b..5617d873e529 100644 --- a/polly/test/CodeGen/PHIInExit.ll +++ b/polly/test/CodeGen/PHIInExit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %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-n8:16:32:64" %struct..0__pthread_mutex_s = type { i32, i32, i32, i32, i32, i32, %struct.__pthread_list_t } diff --git a/polly/test/CodeGen/RuntimeDebugBuilder/combine_different_values.ll b/polly/test/CodeGen/RuntimeDebugBuilder/combine_different_values.ll index 84827dd26049..c7f9186c3777 100644 --- a/polly/test/CodeGen/RuntimeDebugBuilder/combine_different_values.ll +++ b/polly/test/CodeGen/RuntimeDebugBuilder/combine_different_values.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S \ +; RUN: opt %loadPolly -passes=polly-codegen -S \ ; RUN: -polly-codegen-add-debug-printing \ ; RUN: -polly-ignore-aliasing < %s | FileCheck %s diff --git a/polly/test/CodeGen/RuntimeDebugBuilder/stmt_tracing.ll b/polly/test/CodeGen/RuntimeDebugBuilder/stmt_tracing.ll index 822eccc306ef..80fa3ee8d0f2 100644 --- a/polly/test/CodeGen/RuntimeDebugBuilder/stmt_tracing.ll +++ b/polly/test/CodeGen/RuntimeDebugBuilder/stmt_tracing.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen-trace-stmts -polly-codegen-trace-scalars -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen-trace-stmts -polly-codegen-trace-scalars -passes=polly-codegen -S < %s | FileCheck %s ; define void @func(i32 %n, ptr %A) { diff --git a/polly/test/CodeGen/alias-check-multi-dim.ll b/polly/test/CodeGen/alias-check-multi-dim.ll index d923a4cc14fd..821e19290612 100644 --- a/polly/test/CodeGen/alias-check-multi-dim.ll +++ b/polly/test/CodeGen/alias-check-multi-dim.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen \ +; RUN: opt %loadPolly -passes=polly-codegen \ ; RUN: -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/alias_metadata_too_many_arrays.ll b/polly/test/CodeGen/alias_metadata_too_many_arrays.ll index 7c5ca012a378..9207f3015e3a 100644 --- a/polly/test/CodeGen/alias_metadata_too_many_arrays.ll +++ b/polly/test/CodeGen/alias_metadata_too_many_arrays.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-ignore-aliasing -S < %s \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-ignore-aliasing -S < %s \ ; RUN: | FileCheck %s ; ; void manyarrays(float A1[], float A2[], float A3[], float A4[], float A5[], diff --git a/polly/test/CodeGen/aliasing_different_base_and_access_type.ll b/polly/test/CodeGen/aliasing_different_base_and_access_type.ll index a087414b8403..d74f51702f36 100644 --- a/polly/test/CodeGen/aliasing_different_base_and_access_type.ll +++ b/polly/test/CodeGen/aliasing_different_base_and_access_type.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; We have to cast %B to "short *" before we create RTCs. ; diff --git a/polly/test/CodeGen/aliasing_different_pointer_types.ll b/polly/test/CodeGen/aliasing_different_pointer_types.ll index 91f5eab6b2a6..5ba1d1b587bf 100644 --- a/polly/test/CodeGen/aliasing_different_pointer_types.ll +++ b/polly/test/CodeGen/aliasing_different_pointer_types.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; Check that we cast the different pointer types correctly before we compare ; them in the RTC's. We use i8* as max pointer type. diff --git a/polly/test/CodeGen/aliasing_multidimensional_access.ll b/polly/test/CodeGen/aliasing_multidimensional_access.ll index 48768399e850..338ab05e4ad3 100644 --- a/polly/test/CodeGen/aliasing_multidimensional_access.ll +++ b/polly/test/CodeGen/aliasing_multidimensional_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; Check that we calculate the maximal access into array A correctly and track the overflow state. ; diff --git a/polly/test/CodeGen/aliasing_parametric_simple_1.ll b/polly/test/CodeGen/aliasing_parametric_simple_1.ll index 5422da4426e9..281ecf488fd4 100644 --- a/polly/test/CodeGen/aliasing_parametric_simple_1.ll +++ b/polly/test/CodeGen/aliasing_parametric_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; void jd(int *A, int *B, int c) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/CodeGen/aliasing_parametric_simple_2.ll b/polly/test/CodeGen/aliasing_parametric_simple_2.ll index de945d403f92..9ac59f93febb 100644 --- a/polly/test/CodeGen/aliasing_parametric_simple_2.ll +++ b/polly/test/CodeGen/aliasing_parametric_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; void jd(int *A, int *B, int c) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/CodeGen/aliasing_struct_element.ll b/polly/test/CodeGen/aliasing_struct_element.ll index 2219ca9d28bb..32b7c1ac905c 100644 --- a/polly/test/CodeGen/aliasing_struct_element.ll +++ b/polly/test/CodeGen/aliasing_struct_element.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; We should only access (or compute the address of) "the first element" of %S ; as it is a single struct not a struct array. The maximal access to S, thus diff --git a/polly/test/CodeGen/alignment.ll b/polly/test/CodeGen/alignment.ll index a94b1f7e2883..f3c786780f0a 100644 --- a/polly/test/CodeGen/alignment.ll +++ b/polly/test/CodeGen/alignment.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; Check that the special alignment information is kept ; diff --git a/polly/test/CodeGen/annotated_alias_scopes.ll b/polly/test/CodeGen/annotated_alias_scopes.ll index f8d14cd34b62..1dd409edc9a5 100644 --- a/polly/test/CodeGen/annotated_alias_scopes.ll +++ b/polly/test/CodeGen/annotated_alias_scopes.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=SCOPES +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s --check-prefix=SCOPES ; ; Check that we create alias scopes that indicate the accesses to A, B and C cannot alias in any way. ; diff --git a/polly/test/CodeGen/blas_sscal_simplified.ll b/polly/test/CodeGen/blas_sscal_simplified.ll index a370fcff46f8..b2072d3822a2 100644 --- a/polly/test/CodeGen/blas_sscal_simplified.ll +++ b/polly/test/CodeGen/blas_sscal_simplified.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %s ; ; Regression test for a bug in the runtime check generation. diff --git a/polly/test/CodeGen/conflict-between-loop-invariant-code-hosting-and-escape-map-computation.ll b/polly/test/CodeGen/conflict-between-loop-invariant-code-hosting-and-escape-map-computation.ll index e0f8c435879a..e977627ed7be 100644 --- a/polly/test/CodeGen/conflict-between-loop-invariant-code-hosting-and-escape-map-computation.ll +++ b/polly/test/CodeGen/conflict-between-loop-invariant-code-hosting-and-escape-map-computation.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-process-unprofitable -passes=polly-codegen -disable-output < %s ; ; CHECK: store i32 %tmp14_p_scalar_, ptr %tmp14.s2a ; CHECK: %tmp14.final_reload = load i32, ptr %tmp14.s2a diff --git a/polly/test/CodeGen/constant_condition.ll b/polly/test/CodeGen/constant_condition.ll index dad1f6cffd17..e259b5799763 100644 --- a/polly/test/CodeGen/constant_condition.ll +++ b/polly/test/CodeGen/constant_condition.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly -polly-prepare -polly-print-ast -disable-output < %s | FileCheck %s +;RUN: opt %loadPolly '-passes=polly-prepare,scop(print)' -disable-output < %s 2>&1 | FileCheck %s ;#include ;int A[1]; diff --git a/polly/test/CodeGen/create-conditional-scop.ll b/polly/test/CodeGen/create-conditional-scop.ll index f51a2dcc9b3c..235726fdaf15 100644 --- a/polly/test/CodeGen/create-conditional-scop.ll +++ b/polly/test/CodeGen/create-conditional-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-codegen -verify-loop-info < %s -S | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -verify-loop-info < %s -S | FileCheck %s target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-a0:0-n32" diff --git a/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_1.ll b/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_1.ll index 991e3c83eef1..220bdc179158 100644 --- a/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_1.ll +++ b/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %s ; ; Check we do not crash even though the dead %tmp8 is referenced by a parameter ; and we do not pre-load it (as it is dead). diff --git a/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_2.ll b/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_2.ll index 153f6912cea5..4830de888237 100644 --- a/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_2.ll +++ b/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %s ; ; Check we do not crash even though there is a dead load that is referenced by ; a parameter and we do not pre-load it (as it is dead). diff --git a/polly/test/CodeGen/debug-intrinsics.ll b/polly/test/CodeGen/debug-intrinsics.ll index 2feeb7c838b0..c98fae8e2e10 100644 --- a/polly/test/CodeGen/debug-intrinsics.ll +++ b/polly/test/CodeGen/debug-intrinsics.ll @@ -1,9 +1,9 @@ ; RUN: opt %loadPolly \ -; RUN: -polly-analyze-read-only-scalars=false -polly-codegen -S < %s | \ +; RUN: -polly-analyze-read-only-scalars=false -passes=polly-codegen -S < %s | \ ; RUN: FileCheck %s ; RUN: opt %loadPolly \ -; RUN: -polly-analyze-read-only-scalars=true -polly-codegen -S < %s | \ +; RUN: -polly-analyze-read-only-scalars=true -passes=polly-codegen -S < %s | \ ; RUN: FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/dominance_problem_after_early_codegen_bailout.ll b/polly/test/CodeGen/dominance_problem_after_early_codegen_bailout.ll index c9e006a01204..2a3f3bd8a065 100644 --- a/polly/test/CodeGen/dominance_problem_after_early_codegen_bailout.ll +++ b/polly/test/CodeGen/dominance_problem_after_early_codegen_bailout.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -disable-output < %s +; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s ; ; This caused dominance problems at some point as we do bail out during ; code generation. Just verify it runs through. diff --git a/polly/test/CodeGen/empty_domain_in_context.ll b/polly/test/CodeGen/empty_domain_in_context.ll index c67ace9502e1..b7a6b95171cb 100644 --- a/polly/test/CodeGen/empty_domain_in_context.ll +++ b/polly/test/CodeGen/empty_domain_in_context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-optree -polly-opt-isl -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-optree,polly-opt-isl,polly-codegen' -S < %s | FileCheck %s ; ; llvm.org/PR35362 ; isl codegen does not allow to generate isl_ast_expr from pw_aff which have an diff --git a/polly/test/CodeGen/entry_with_trivial_phi.ll b/polly/test/CodeGen/entry_with_trivial_phi.ll index b057690ab29b..99d0776f3aa9 100644 --- a/polly/test/CodeGen/entry_with_trivial_phi.ll +++ b/polly/test/CodeGen/entry_with_trivial_phi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s ; ; The entry of this scop's simple region (entry.split => for.end) has an trivial ; PHI node. LCSSA may create such PHI nodes. This is a breakdown of this case in diff --git a/polly/test/CodeGen/entry_with_trivial_phi_other_bb.ll b/polly/test/CodeGen/entry_with_trivial_phi_other_bb.ll index 5673cc746b5f..ec3967b51049 100644 --- a/polly/test/CodeGen/entry_with_trivial_phi_other_bb.ll +++ b/polly/test/CodeGen/entry_with_trivial_phi_other_bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; The entry of this scop's simple region (entry.split => for.end) has an trivial ; PHI node that is used in a different of the scop region. LCSSA may create such diff --git a/polly/test/CodeGen/error-stmt-in-non-affine-region.ll b/polly/test/CodeGen/error-stmt-in-non-affine-region.ll index 9832afe7a5fd..ab85fbabd3f8 100644 --- a/polly/test/CodeGen/error-stmt-in-non-affine-region.ll +++ b/polly/test/CodeGen/error-stmt-in-non-affine-region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; XFAIL: * ; ; CHECK-LABEL: polly.stmt.if.then: diff --git a/polly/test/CodeGen/error_block_contains_invalid_memory_access.ll b/polly/test/CodeGen/error_block_contains_invalid_memory_access.ll index 048847f3e322..6d1c3f74cc03 100644 --- a/polly/test/CodeGen/error_block_contains_invalid_memory_access.ll +++ b/polly/test/CodeGen/error_block_contains_invalid_memory_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %s ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/exprModDiv.ll b/polly/test/CodeGen/exprModDiv.ll index 936b018bc1ad..625e0e6464d7 100644 --- a/polly/test/CodeGen/exprModDiv.ll +++ b/polly/test/CodeGen/exprModDiv.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-import-jscop \ -; RUN: -polly-codegen -S < %s | FileCheck %s -; RUN: opt %loadPolly -polly-import-jscop \ -; RUN: -polly-codegen -polly-import-jscop-postfix=pow2 \ +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ +; RUN: -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ +; RUN: -polly-import-jscop-postfix=pow2 \ ; RUN: -S < %s | FileCheck %s -check-prefix=POW2 ; ; void exprModDiv(float *A, float *B, float *C, long N, long p) { diff --git a/polly/test/CodeGen/hoisted_load_escapes_through_phi.ll b/polly/test/CodeGen/hoisted_load_escapes_through_phi.ll index d7588b3b8e00..ad7d84648a09 100644 --- a/polly/test/CodeGen/hoisted_load_escapes_through_phi.ll +++ b/polly/test/CodeGen/hoisted_load_escapes_through_phi.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -S -polly-codegen \ +; RUN: opt %loadPolly -S -passes=polly-codegen \ ; RUN: -polly-invariant-load-hoisting=false < %s | FileCheck %s -; RUN: opt %loadPolly -S -polly-codegen \ +; RUN: opt %loadPolly -S -passes=polly-codegen \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; Check that we generate valid code even if the load of cont_STACKPOINTER is diff --git a/polly/test/CodeGen/hoisting_1.ll b/polly/test/CodeGen/hoisting_1.ll index 86b56637bc2c..e04ee68cc4c9 100644 --- a/polly/test/CodeGen/hoisting_1.ll +++ b/polly/test/CodeGen/hoisting_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -tbaa -polly-codegen -polly-allow-differing-element-types -disable-output %s +; RUN: opt %loadPolly -aa-pipeline=tbaa -passes=polly-codegen -polly-allow-differing-element-types -disable-output %s ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/hoisting_2.ll b/polly/test/CodeGen/hoisting_2.ll index 1f1be11c2d98..d5c27f58b95b 100644 --- a/polly/test/CodeGen/hoisting_2.ll +++ b/polly/test/CodeGen/hoisting_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -tbaa -polly-codegen -polly-allow-differing-element-types -disable-output %s +; RUN: opt %loadPolly -aa-pipeline=tbaa -passes=polly-codegen -polly-allow-differing-element-types -disable-output %s ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/inner_scev_sdiv_1.ll b/polly/test/CodeGen/inner_scev_sdiv_1.ll index 1a463fc178d1..25f2abd9b63e 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_1.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s ; ; Excerpt from the test-suite's oggenc reduced using bugpoint. ; diff --git a/polly/test/CodeGen/inner_scev_sdiv_2.ll b/polly/test/CodeGen/inner_scev_sdiv_2.ll index 76138034603e..4d80c2a170d6 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_2.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; The SCEV expression in this test case refers to a sequence of sdiv ; instructions, which are part of different bbs in the SCoP. When code diff --git a/polly/test/CodeGen/inner_scev_sdiv_3.ll b/polly/test/CodeGen/inner_scev_sdiv_3.ll index 874ead14ded2..8d13c8e168bf 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_3.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; This test case has a inner SCEV sdiv that will escape the SCoP. Just check we ; do not crash and generate valid code. diff --git a/polly/test/CodeGen/inner_scev_sdiv_in_lb.ll b/polly/test/CodeGen/inner_scev_sdiv_in_lb.ll index 6514e18687e4..b53ee034f960 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_in_lb.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_in_lb.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN ; ; CHECK: [N] -> { Stmt_bb11[i0, i1] : i0 < N and i1 >= 0 and 3i1 <= -3 + i0 }; ; CODEGEN: polly diff --git a/polly/test/CodeGen/inner_scev_sdiv_in_lb_invariant.ll b/polly/test/CodeGen/inner_scev_sdiv_in_lb_invariant.ll index 032942923379..3c392a2c4c4c 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_in_lb_invariant.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_in_lb_invariant.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen \ +; RUN: opt %loadPolly -S -passes=polly-codegen \ ; RUN: < %s | FileCheck %s ; ; Check that this will not crash our code generation. diff --git a/polly/test/CodeGen/inner_scev_sdiv_in_rtc.ll b/polly/test/CodeGen/inner_scev_sdiv_in_rtc.ll index f7292ca3073a..0748a274bb7d 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_in_rtc.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_in_rtc.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen \ +; RUN: opt %loadPolly -passes=polly-codegen \ ; RUN: -S < %s | FileCheck %s ; ; This will just check that we generate valid code here. diff --git a/polly/test/CodeGen/intrinsics_lifetime.ll b/polly/test/CodeGen/intrinsics_lifetime.ll index 6141b3abdd8a..5782b4724649 100644 --- a/polly/test/CodeGen/intrinsics_lifetime.ll +++ b/polly/test/CodeGen/intrinsics_lifetime.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -S < %s | FileCheck %s ; ; Verify that we remove the lifetime markers from everywhere. ; diff --git a/polly/test/CodeGen/intrinsics_misc.ll b/polly/test/CodeGen/intrinsics_misc.ll index c0a52fe97329..9b208b4e600b 100644 --- a/polly/test/CodeGen/intrinsics_misc.ll +++ b/polly/test/CodeGen/intrinsics_misc.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -S < %s | FileCheck %s ; ; Verify that we remove the misc intrinsics from the optimized SCoP. ; diff --git a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-2.ll b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-2.ll index 6727247a7f04..fd66cf0a47c9 100644 --- a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-2.ll +++ b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S \ +; RUN: opt %loadPolly -passes=polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; This crashed our codegen at some point, verify it runs through diff --git a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-3.ll b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-3.ll index a573049c8f67..408f0086a260 100644 --- a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-3.ll +++ b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S \ +; RUN: opt %loadPolly -passes=polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; This crashed our codegen at some point, verify it runs through diff --git a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order.ll b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order.ll index e05ca9951434..45bb5d041a49 100644 --- a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order.ll +++ b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S \ +; RUN: opt %loadPolly -passes=polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; This crashed our codegen at some point, verify it runs through diff --git a/polly/test/CodeGen/invariant-load-dimension.ll b/polly/test/CodeGen/invariant-load-dimension.ll index 7793c3b3bee3..07bd6923b54b 100644 --- a/polly/test/CodeGen/invariant-load-dimension.ll +++ b/polly/test/CodeGen/invariant-load-dimension.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -polly-invariant-load-hoisting -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=SCOPS -; RUN: opt %loadPolly -S < %s -polly-codegen -polly-process-unprofitable -polly-invariant-load-hoisting | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-process-unprofitable -polly-invariant-load-hoisting '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=SCOPS +; RUN: opt %loadPolly -S < %s -passes=polly-codegen -polly-process-unprofitable -polly-invariant-load-hoisting | FileCheck %s -check-prefix=CODEGEN target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n8:16:32-S64" diff --git a/polly/test/CodeGen/invariant-load-preload-base-pointer-origin-first.ll b/polly/test/CodeGen/invariant-load-preload-base-pointer-origin-first.ll index 474100995fd8..c4166dd4d2a9 100644 --- a/polly/test/CodeGen/invariant-load-preload-base-pointer-origin-first.ll +++ b/polly/test/CodeGen/invariant-load-preload-base-pointer-origin-first.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen -polly-invariant-load-hoisting=true < %s +; RUN: opt %loadPolly -S -passes=polly-codegen -polly-invariant-load-hoisting=true < %s ; ; Check that we generate valid code as we did non preload the base pointer ; origin of %tmp4 at some point. diff --git a/polly/test/CodeGen/invariant_cannot_handle_void.ll b/polly/test/CodeGen/invariant_cannot_handle_void.ll index de5d13d6a69a..633955b6053a 100644 --- a/polly/test/CodeGen/invariant_cannot_handle_void.ll +++ b/polly/test/CodeGen/invariant_cannot_handle_void.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=SCOP -; RUN: opt %loadPolly -S -polly-codegen -polly-invariant-load-hoisting=true %s | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -S -passes=polly-codegen -polly-invariant-load-hoisting=true %s | FileCheck %s ; ; The offset of the %tmp1 load wrt. to %buff (62 bytes) is not divisible ; by the type size (i32 = 4 bytes), thus we will have to represent %buff diff --git a/polly/test/CodeGen/invariant_load.ll b/polly/test/CodeGen/invariant_load.ll index be3f7a32f35b..bef3862e9c79 100644 --- a/polly/test/CodeGen/invariant_load.ll +++ b/polly/test/CodeGen/invariant_load.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK-NEXT: %polly.access.B = getelementptr i32, ptr %B, i64 0 diff --git a/polly/test/CodeGen/invariant_load_address_space.ll b/polly/test/CodeGen/invariant_load_address_space.ll index 7c611ad3dd87..9ffef5757cb8 100644 --- a/polly/test/CodeGen/invariant_load_address_space.ll +++ b/polly/test/CodeGen/invariant_load_address_space.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK-NEXT: %polly.access.B = getelementptr i32, ptr addrspace(1) %B, i64 0 diff --git a/polly/test/CodeGen/invariant_load_alias_metadata.ll b/polly/test/CodeGen/invariant_load_alias_metadata.ll index 5a82d82d43f8..a992a926880b 100644 --- a/polly/test/CodeGen/invariant_load_alias_metadata.ll +++ b/polly/test/CodeGen/invariant_load_alias_metadata.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true \ ; RUN: -S < %s | FileCheck %s ; ; This test case checks whether Polly generates alias metadata in case of diff --git a/polly/test/CodeGen/invariant_load_base_pointer.ll b/polly/test/CodeGen/invariant_load_base_pointer.ll index eb07f8317b79..c7d9e8df5b59 100644 --- a/polly/test/CodeGen/invariant_load_base_pointer.ll +++ b/polly/test/CodeGen/invariant_load_base_pointer.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK-NEXT: %polly.access.BPLoc = getelementptr ptr, ptr %BPLoc, i64 0 diff --git a/polly/test/CodeGen/invariant_load_base_pointer_conditional.ll b/polly/test/CodeGen/invariant_load_base_pointer_conditional.ll index 538077bb09e8..f24d8b7d7525 100644 --- a/polly/test/CodeGen/invariant_load_base_pointer_conditional.ll +++ b/polly/test/CodeGen/invariant_load_base_pointer_conditional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK-NEXT: %0 = sext i32 %N to i64 diff --git a/polly/test/CodeGen/invariant_load_base_pointer_conditional_2.ll b/polly/test/CodeGen/invariant_load_base_pointer_conditional_2.ll index 7c2fb3ef97ed..210060c90681 100644 --- a/polly/test/CodeGen/invariant_load_base_pointer_conditional_2.ll +++ b/polly/test/CodeGen/invariant_load_base_pointer_conditional_2.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -S -polly-codegen -polly-invariant-load-hoisting=true < %s | FileCheck %s --check-prefix=IR -; RUN: opt %loadPolly -S -polly-codegen -polly-invariant-load-hoisting=true --polly-overflow-tracking=always < %s | FileCheck %s --check-prefix=IRA +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen -polly-invariant-load-hoisting=true < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -S -passes=polly-codegen -polly-invariant-load-hoisting=true --polly-overflow-tracking=always < %s | FileCheck %s --check-prefix=IRA ; ; As (p + q) can overflow we have to check that we load from ; I[p + q] only if it does not. diff --git a/polly/test/CodeGen/invariant_load_canonicalize_array_baseptrs.ll b/polly/test/CodeGen/invariant_load_canonicalize_array_baseptrs.ll index dc5a4c890381..f6d4fef13d7a 100644 --- a/polly/test/CodeGen/invariant_load_canonicalize_array_baseptrs.ll +++ b/polly/test/CodeGen/invariant_load_canonicalize_array_baseptrs.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s \ +; RUN: opt %loadPolly -passes=polly-codegen -S < %s \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/CodeGen/invariant_load_condition.ll b/polly/test/CodeGen/invariant_load_condition.ll index edf0814d8983..1aab3b8497fc 100644 --- a/polly/test/CodeGen/invariant_load_condition.ll +++ b/polly/test/CodeGen/invariant_load_condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK-NEXT: %polly.access.C = getelementptr i32, ptr %C, i64 0 diff --git a/polly/test/CodeGen/invariant_load_different_sized_types.ll b/polly/test/CodeGen/invariant_load_different_sized_types.ll index 5b91a1901061..952786d71cc9 100644 --- a/polly/test/CodeGen/invariant_load_different_sized_types.ll +++ b/polly/test/CodeGen/invariant_load_different_sized_types.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S \ ; RUN: -polly-allow-differing-element-types < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/invariant_load_escaping.ll b/polly/test/CodeGen/invariant_load_escaping.ll index efccdf468a18..31d2066745ef 100644 --- a/polly/test/CodeGen/invariant_load_escaping.ll +++ b/polly/test/CodeGen/invariant_load_escaping.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; int f(int *A, int *B) { ; // Possible aliasing between A and B but if not then *B would be diff --git a/polly/test/CodeGen/invariant_load_escaping_second_scop.ll b/polly/test/CodeGen/invariant_load_escaping_second_scop.ll index c0ea888acdde..5dbf261d84e5 100644 --- a/polly/test/CodeGen/invariant_load_escaping_second_scop.ll +++ b/polly/test/CodeGen/invariant_load_escaping_second_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-process-unprofitable -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-process-unprofitable -S < %s | FileCheck %s ; ; void fence(void); ; diff --git a/polly/test/CodeGen/invariant_load_in_non_affine_subregion.ll b/polly/test/CodeGen/invariant_load_in_non_affine_subregion.ll index 241252b5d549..57b4a655cc24 100644 --- a/polly/test/CodeGen/invariant_load_in_non_affine_subregion.ll +++ b/polly/test/CodeGen/invariant_load_in_non_affine_subregion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; This crashed at some point as the invariant load is in a non-affine ; subregion. Just check it does not anymore. diff --git a/polly/test/CodeGen/invariant_load_loop_ub.ll b/polly/test/CodeGen/invariant_load_loop_ub.ll index ab9aa0dc69a7..a4b96fad0559 100644 --- a/polly/test/CodeGen/invariant_load_loop_ub.ll +++ b/polly/test/CodeGen/invariant_load_loop_ub.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-process-unprofitable -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-process-unprofitable -S < %s | FileCheck %s ; ; CHECK: polly.start ; diff --git a/polly/test/CodeGen/invariant_load_not_executed_but_in_parameters.ll b/polly/test/CodeGen/invariant_load_not_executed_but_in_parameters.ll index 08ff0871b610..2970dbb5bed9 100644 --- a/polly/test/CodeGen/invariant_load_not_executed_but_in_parameters.ll +++ b/polly/test/CodeGen/invariant_load_not_executed_but_in_parameters.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s ; ; Check that this does not crash as the invariant load is not executed (thus ; not preloaded) but still referenced by one of the parameters. diff --git a/polly/test/CodeGen/invariant_load_outermost.ll b/polly/test/CodeGen/invariant_load_outermost.ll index f42135c09014..eda42f76ed5d 100644 --- a/polly/test/CodeGen/invariant_load_outermost.ll +++ b/polly/test/CodeGen/invariant_load_outermost.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; CHECK: polly.start diff --git a/polly/test/CodeGen/invariant_load_parameters_cyclic_dependence.ll b/polly/test/CodeGen/invariant_load_parameters_cyclic_dependence.ll index d365c99eff66..73fb038baed2 100644 --- a/polly/test/CodeGen/invariant_load_parameters_cyclic_dependence.ll +++ b/polly/test/CodeGen/invariant_load_parameters_cyclic_dependence.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s --check-prefix=SCOP -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; SCOP: Assumed Context: ; SCOP-NEXT: [p_0, tmp4] -> { : } diff --git a/polly/test/CodeGen/invariant_load_ptr_ptr_noalias.ll b/polly/test/CodeGen/invariant_load_ptr_ptr_noalias.ll index b4d4c55f0d9b..82e957b9ef1d 100644 --- a/polly/test/CodeGen/invariant_load_ptr_ptr_noalias.ll +++ b/polly/test/CodeGen/invariant_load_ptr_ptr_noalias.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK: %polly.access.A = getelementptr ptr, ptr %A, i64 42 diff --git a/polly/test/CodeGen/invariant_load_scalar_dep.ll b/polly/test/CodeGen/invariant_load_scalar_dep.ll index 05a40a4c47cc..3906d5ab890f 100644 --- a/polly/test/CodeGen/invariant_load_scalar_dep.ll +++ b/polly/test/CodeGen/invariant_load_scalar_dep.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK: %polly.access.B = getelementptr i32, ptr %B, i64 0 diff --git a/polly/test/CodeGen/invariant_load_scalar_escape_alloca_sharing.ll b/polly/test/CodeGen/invariant_load_scalar_escape_alloca_sharing.ll index 44c035855b76..82e38e86bf77 100644 --- a/polly/test/CodeGen/invariant_load_scalar_escape_alloca_sharing.ll +++ b/polly/test/CodeGen/invariant_load_scalar_escape_alloca_sharing.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; Verify the preloaded %tmp0 is stored and communicated in the same alloca. ; In this case, we do not reload %ncol.load from the scalar stack slot, but diff --git a/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_1.ll b/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_1.ll index 0b6929a5fd3f..ef382eb20d0f 100644 --- a/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_1.ll +++ b/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true < %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true < %s ; ; Check we do not crash even though we pre-load values with different types ; from the same base pointer. diff --git a/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_2.ll b/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_2.ll index 2eb913fed447..07e7b97ed9de 100644 --- a/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_2.ll +++ b/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true < %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true < %s ; ; Check we do not crash even though we pre-load values with different types ; from the same base pointer. diff --git a/polly/test/CodeGen/invariant_loads_ignore_parameter_bounds.ll b/polly/test/CodeGen/invariant_loads_ignore_parameter_bounds.ll index a0c1f891bdf6..8be087467e99 100644 --- a/polly/test/CodeGen/invariant_loads_ignore_parameter_bounds.ll +++ b/polly/test/CodeGen/invariant_loads_ignore_parameter_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting \ ; RUN: -polly-ignore-parameter-bounds -S < %s | FileCheck %s ; CHECK: polly.preload.begin: diff --git a/polly/test/CodeGen/invariant_verify_function_failed.ll b/polly/test/CodeGen/invariant_verify_function_failed.ll index 6020caeee85d..86308a7fbbfc 100644 --- a/polly/test/CodeGen/invariant_verify_function_failed.ll +++ b/polly/test/CodeGen/invariant_verify_function_failed.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,scop(polly-codegen)' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; This crashed at some point as the pointer returned by the call ; to @__errno_location is invariant and defined in the SCoP but not diff --git a/polly/test/CodeGen/invariant_verify_function_failed_2.ll b/polly/test/CodeGen/invariant_verify_function_failed_2.ll index 81a4bd1dc153..97faa6155f18 100644 --- a/polly/test/CodeGen/invariant_verify_function_failed_2.ll +++ b/polly/test/CodeGen/invariant_verify_function_failed_2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -S -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -check-prefix=SCOPS -; RUN: opt %loadPolly -S -polly-codegen -polly-invariant-load-hoisting=true %s | FileCheck %s +; RUN: opt %loadPolly -S '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -check-prefix=SCOPS +; RUN: opt %loadPolly -S -passes=polly-codegen -polly-invariant-load-hoisting=true %s | FileCheck %s ; ; Check we generate valid code. diff --git a/polly/test/CodeGen/issue56692.ll b/polly/test/CodeGen/issue56692.ll index e935e43bfa44..b5ab63c3b72b 100644 --- a/polly/test/CodeGen/issue56692.ll +++ b/polly/test/CodeGen/issue56692.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-omp-backend=LLVM -polly-codegen-verify -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-omp-backend=LLVM -polly-codegen-verify -passes=polly-codegen -S < %s | FileCheck %s ; https://github.com/llvm/llvm-project/issues/56692 ; ; CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_call({{.*}}), !dbg ![[OPTLOC:[0-9]+]] diff --git a/polly/test/CodeGen/large-numbers-in-boundary-context.ll b/polly/test/CodeGen/large-numbers-in-boundary-context.ll index a0328dfec651..519511f1ddd5 100644 --- a/polly/test/CodeGen/large-numbers-in-boundary-context.ll +++ b/polly/test/CodeGen/large-numbers-in-boundary-context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; XFAIL: * ; ; The boundary context contains a constant that does not fit in 64 bits. Hence, diff --git a/polly/test/CodeGen/load_subset_with_context.ll b/polly/test/CodeGen/load_subset_with_context.ll index ef0e051d5635..980a06f23c73 100644 --- a/polly/test/CodeGen/load_subset_with_context.ll +++ b/polly/test/CodeGen/load_subset_with_context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s ; ; A load must provide a value for every statement instance. ; Statement instances not in the SCoP's context are irrelevant. diff --git a/polly/test/CodeGen/loop-invariant-load-type-mismatch.ll b/polly/test/CodeGen/loop-invariant-load-type-mismatch.ll index 90c61c591623..ca3463d72af3 100644 --- a/polly/test/CodeGen/loop-invariant-load-type-mismatch.ll +++ b/polly/test/CodeGen/loop-invariant-load-type-mismatch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/polly/test/CodeGen/loop_with_condition.ll b/polly/test/CodeGen/loop_with_condition.ll index 618a542c179a..436d37d1261a 100644 --- a/polly/test/CodeGen/loop_with_condition.ll +++ b/polly/test/CodeGen/loop_with_condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s ;#include ;#define N 1024 diff --git a/polly/test/CodeGen/loop_with_condition_2.ll b/polly/test/CodeGen/loop_with_condition_2.ll index b1a116785069..47ec693efbd5 100644 --- a/polly/test/CodeGen/loop_with_condition_2.ll +++ b/polly/test/CodeGen/loop_with_condition_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; Verify that we actually detect this loop as the innermost loop even though ; there is a conditional inside. diff --git a/polly/test/CodeGen/loop_with_condition_ineq.ll b/polly/test/CodeGen/loop_with_condition_ineq.ll index c35208c72dfe..98866000b0cb 100644 --- a/polly/test/CodeGen/loop_with_condition_ineq.ll +++ b/polly/test/CodeGen/loop_with_condition_ineq.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s ;#include ;#define N 1024 diff --git a/polly/test/CodeGen/loop_with_condition_nested.ll b/polly/test/CodeGen/loop_with_condition_nested.ll index 24a49b47d9e6..d9a9dafd4b7e 100644 --- a/polly/test/CodeGen/loop_with_condition_nested.ll +++ b/polly/test/CodeGen/loop_with_condition_nested.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -basic-aa -polly-codegen < %s | opt -passes='print' -disable-output 2>&1 | FileCheck %s -check-prefix=LOOPS +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen < %s | opt -passes='print' -disable-output 2>&1 | FileCheck %s -check-prefix=LOOPS ;#include diff --git a/polly/test/CodeGen/loop_with_conditional_entry_edge_split_hard_case.ll b/polly/test/CodeGen/loop_with_conditional_entry_edge_split_hard_case.ll index 4444cf1dc4dd..3687868b0baf 100644 --- a/polly/test/CodeGen/loop_with_conditional_entry_edge_split_hard_case.ll +++ b/polly/test/CodeGen/loop_with_conditional_entry_edge_split_hard_case.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; Test case to trigger the hard way of creating a unique entering ; edge for the SCoP. It is triggered because the entering edge diff --git a/polly/test/CodeGen/memcpy_annotations.ll b/polly/test/CodeGen/memcpy_annotations.ll index a0a09b75c82e..42fe5ca92b94 100644 --- a/polly/test/CodeGen/memcpy_annotations.ll +++ b/polly/test/CodeGen/memcpy_annotations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; Verify that @llvm.memcpy does not get a !alias.scope annotation. ; @llvm.memcpy takes two pointers, it is ambiguous to which the diff --git a/polly/test/CodeGen/multidim-non-matching-typesize-2.ll b/polly/test/CodeGen/multidim-non-matching-typesize-2.ll index 63afad6e2f41..cfd52a0b7793 100644 --- a/polly/test/CodeGen/multidim-non-matching-typesize-2.ll +++ b/polly/test/CodeGen/multidim-non-matching-typesize-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -disable-basic-aa -polly-codegen \ +; RUN: opt %loadPolly -disable-basic-aa -passes=polly-codegen \ ; RUN: -S < %s | FileCheck %s ; CHECK: polly target datalayout = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" diff --git a/polly/test/CodeGen/multidim-non-matching-typesize.ll b/polly/test/CodeGen/multidim-non-matching-typesize.ll index d117cefe3376..b3f70226f743 100644 --- a/polly/test/CodeGen/multidim-non-matching-typesize.ll +++ b/polly/test/CodeGen/multidim-non-matching-typesize.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -disable-basic-aa -polly-codegen \ +; RUN: opt %loadPolly -disable-basic-aa -passes=polly-codegen \ ; RUN: -S < %s | FileCheck %s target datalayout = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" diff --git a/polly/test/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll b/polly/test/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll index 464ddb3740f7..11976874ed84 100644 --- a/polly/test/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll +++ b/polly/test/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/CodeGen/multidim_alias_check.ll b/polly/test/CodeGen/multidim_alias_check.ll index 585577da0e6d..15390433a1b1 100644 --- a/polly/test/CodeGen/multidim_alias_check.ll +++ b/polly/test/CodeGen/multidim_alias_check.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly -passes=polly-codegen < %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; CHECK: %polly.access.sext.A = sext i32 %n to i64 diff --git a/polly/test/CodeGen/multiple-codegens.ll b/polly/test/CodeGen/multiple-codegens.ll index f950fa4a3e1d..683ccdfa092b 100644 --- a/polly/test/CodeGen/multiple-codegens.ll +++ b/polly/test/CodeGen/multiple-codegens.ll @@ -1,6 +1,5 @@ -; RUN: opt %loadPolly -polly-scops -polly-opt-isl -polly-codegen -polly-scops -polly-codegen -S < %s | FileCheck %s -; RUN: opt %loadNPMPolly "-passes=scop(polly-opt-isl,polly-codegen,polly-codegen)" -S < %s | FileCheck %s -; RUN: opt %loadNPMPolly "-passes=scop(polly-opt-isl,polly-codegen),scop(polly-codegen)" -S < %s | FileCheck %s +; RUN: opt %loadPolly "-passes=scop(polly-opt-isl,polly-codegen,polly-codegen)" -S < %s | FileCheck %s +; RUN: opt %loadPolly "-passes=scop(polly-opt-isl,polly-codegen),scop(polly-codegen)" -S < %s | FileCheck %s ; ; llvm.org/PR34441 ; Properly handle multiple -polly-scops/-polly-codegen in the same diff --git a/polly/test/CodeGen/multiple-scops-in-a-row.ll b/polly/test/CodeGen/multiple-scops-in-a-row.ll index a24a2e71ad4e..0ac158c79129 100644 --- a/polly/test/CodeGen/multiple-scops-in-a-row.ll +++ b/polly/test/CodeGen/multiple-scops-in-a-row.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; This test case has two scops in a row. When code generating the first scop, ; the second scop is invalidated. This test case verifies that we do not crash diff --git a/polly/test/CodeGen/multiple-types-invariant-load-2.ll b/polly/test/CodeGen/multiple-types-invariant-load-2.ll index 0fd1df75e2ec..7916d32bd7de 100644 --- a/polly/test/CodeGen/multiple-types-invariant-load-2.ll +++ b/polly/test/CodeGen/multiple-types-invariant-load-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S \ +; RUN: opt %loadPolly -passes=polly-codegen -S \ ; RUN: -polly-allow-differing-element-types < %s | FileCheck %s ; CHECK: polly diff --git a/polly/test/CodeGen/multiple-types-invariant-load.ll b/polly/test/CodeGen/multiple-types-invariant-load.ll index b1434679e3d1..5ce698d4fb4d 100644 --- a/polly/test/CodeGen/multiple-types-invariant-load.ll +++ b/polly/test/CodeGen/multiple-types-invariant-load.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-differing-element-types -polly-codegen -S \ +; RUN: opt %loadPolly -polly-allow-differing-element-types -passes=polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; CHECK: %polly.access.global.load = getelementptr i32, ptr %global.load, i64 0 diff --git a/polly/test/CodeGen/multiple_sai_fro_same_base_address.ll b/polly/test/CodeGen/multiple_sai_fro_same_base_address.ll index 0163f248229e..94c208e6692f 100644 --- a/polly/test/CodeGen/multiple_sai_fro_same_base_address.ll +++ b/polly/test/CodeGen/multiple_sai_fro_same_base_address.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-position=before-vectorizer -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=SCOP -; RUN: opt %loadPolly -polly-position=before-vectorizer -polly-codegen -S < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -polly-position=before-vectorizer '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -polly-position=before-vectorizer -passes=polly-codegen -S < %s | FileCheck %s --check-prefix=IR ; The IR has two ScopArrayInfo for the value %next.0. This used to produce two ; phi nodes in polly.merge_new_and_old, one illegaly using the result of the diff --git a/polly/test/CodeGen/no-overflow-tracking.ll b/polly/test/CodeGen/no-overflow-tracking.ll index f11e8927ddee..ff4a8023dead 100644 --- a/polly/test/CodeGen/no-overflow-tracking.ll +++ b/polly/test/CodeGen/no-overflow-tracking.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-overflow-tracking=never -polly-codegen -S < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-overflow-tracking=never -passes=polly-codegen -S < %s | FileCheck %s --check-prefix=IR ; ; As (p + q) can overflow we have to check that we load from ; I[p + q] only if it does not. diff --git a/polly/test/CodeGen/no_guard_bb.ll b/polly/test/CodeGen/no_guard_bb.ll index 47c87ff7c868..6635048e0f9b 100644 --- a/polly/test/CodeGen/no_guard_bb.ll +++ b/polly/test/CodeGen/no_guard_bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S -verify-dom-info < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s ; ; CHECK-NOT: br i1 true, label %polly.{{.*}}, label %polly.{{.*}} ; diff --git a/polly/test/CodeGen/non-affine-dominance-generated-entering.ll b/polly/test/CodeGen/non-affine-dominance-generated-entering.ll index ebf36acc8d96..d1d2fc644010 100644 --- a/polly/test/CodeGen/non-affine-dominance-generated-entering.ll +++ b/polly/test/CodeGen/non-affine-dominance-generated-entering.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; llvm.org/PR25439 ; Scalar reloads in the generated entering block were not recognized as diff --git a/polly/test/CodeGen/non-affine-exit-node-dominance.ll b/polly/test/CodeGen/non-affine-exit-node-dominance.ll index af19d2420e3e..8039f3b08543 100644 --- a/polly/test/CodeGen/non-affine-exit-node-dominance.ll +++ b/polly/test/CodeGen/non-affine-exit-node-dominance.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; llvm.org/PR25439 ; The dominance of the generated non-affine subregion block was based on the diff --git a/polly/test/CodeGen/non-affine-phi-node-expansion-2.ll b/polly/test/CodeGen/non-affine-phi-node-expansion-2.ll index 2aca316d4c88..5b6c2ecc81c8 100644 --- a/polly/test/CodeGen/non-affine-phi-node-expansion-2.ll +++ b/polly/test/CodeGen/non-affine-phi-node-expansion-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen \ +; RUN: opt %loadPolly -passes=polly-codegen \ ; RUN: -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/non-affine-phi-node-expansion-3.ll b/polly/test/CodeGen/non-affine-phi-node-expansion-3.ll index 18a4b6e4ed4a..9a4e1fa26a9f 100644 --- a/polly/test/CodeGen/non-affine-phi-node-expansion-3.ll +++ b/polly/test/CodeGen/non-affine-phi-node-expansion-3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen \ +; RUN: opt %loadPolly -passes=polly-codegen \ ; RUN: -S < %s | FileCheck %s define void @foo(ptr %A, i1 %cond0, i1 %cond1) { diff --git a/polly/test/CodeGen/non-affine-phi-node-expansion-4.ll b/polly/test/CodeGen/non-affine-phi-node-expansion-4.ll index 8a07ee7c7424..b5380b5d225c 100644 --- a/polly/test/CodeGen/non-affine-phi-node-expansion-4.ll +++ b/polly/test/CodeGen/non-affine-phi-node-expansion-4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen \ +; RUN: opt %loadPolly -passes=polly-codegen \ ; RUN: -S < %s | FileCheck %s define void @foo(ptr %A, i1 %cond0, i1 %cond1) { diff --git a/polly/test/CodeGen/non-affine-phi-node-expansion.ll b/polly/test/CodeGen/non-affine-phi-node-expansion.ll index 091fc3e323dc..7c29868675f4 100644 --- a/polly/test/CodeGen/non-affine-phi-node-expansion.ll +++ b/polly/test/CodeGen/non-affine-phi-node-expansion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen \ +; RUN: opt %loadPolly -passes=polly-codegen \ ; RUN: -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize-2.ll b/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize-2.ll index 6a1d1f12ba9c..f5c446a22c02 100644 --- a/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize-2.ll +++ b/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; This caused the code generation to generate invalid code as the same operand ; of the PHI node in the non-affine region was synthesized at the wrong place. diff --git a/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize.ll b/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize.ll index 036bf34cb7f7..fc894775b755 100644 --- a/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize.ll +++ b/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; This caused the code generation to generate invalid code as the same BBMap was ; used for the whole non-affine region. When %add is synthesized for the diff --git a/polly/test/CodeGen/non-affine-region-implicit-store.ll b/polly/test/CodeGen/non-affine-region-implicit-store.ll index e89197e24852..6f2c7005d1bb 100644 --- a/polly/test/CodeGen/non-affine-region-implicit-store.ll +++ b/polly/test/CodeGen/non-affine-region-implicit-store.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; llvm.org/PR25438 ; After loop versioning, a dominance check of a non-affine subregion's exit node diff --git a/polly/test/CodeGen/non-affine-region-phi-references-in-scop-value.ll b/polly/test/CodeGen/non-affine-region-phi-references-in-scop-value.ll index f6e4eb57319d..6151562555ee 100644 --- a/polly/test/CodeGen/non-affine-region-phi-references-in-scop-value.ll +++ b/polly/test/CodeGen/non-affine-region-phi-references-in-scop-value.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-allow-nonaffine-loops \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-allow-nonaffine-loops \ ; RUN: -S < %s | FileCheck %s ; This test verifies that values defined in another scop statement and used by diff --git a/polly/test/CodeGen/non-affine-subregion-dominance-reuse.ll b/polly/test/CodeGen/non-affine-subregion-dominance-reuse.ll index 6c749a404336..c2af74c215f9 100644 --- a/polly/test/CodeGen/non-affine-subregion-dominance-reuse.ll +++ b/polly/test/CodeGen/non-affine-subregion-dominance-reuse.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S -verify-dom-info \ +; RUN: opt %loadPolly -passes=polly-codegen -S -verify-dom-info \ ; RUN: < %s | FileCheck %s ; ; Check that we do not reuse the B[i-1] GEP created in block S again in diff --git a/polly/test/CodeGen/non-affine-switch.ll b/polly/test/CodeGen/non-affine-switch.ll index 9c08b98700ae..c829b682fb24 100644 --- a/polly/test/CodeGen/non-affine-switch.ll +++ b/polly/test/CodeGen/non-affine-switch.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly \ -; RUN: -S -polly-codegen < %s | FileCheck %s +; RUN: -S -passes=polly-codegen < %s | FileCheck %s ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/CodeGen/non-affine-synthesized-in-branch.ll b/polly/test/CodeGen/non-affine-synthesized-in-branch.ll index cc0e60abcd09..a0febb348434 100644 --- a/polly/test/CodeGen/non-affine-synthesized-in-branch.ll +++ b/polly/test/CodeGen/non-affine-synthesized-in-branch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable -passes=polly-codegen -S < %s | FileCheck %s ; ; llvm.org/PR25412 ; %synthgep caused %gep to be synthesized in subregion_if which was reused for diff --git a/polly/test/CodeGen/non-affine-update.ll b/polly/test/CodeGen/non-affine-update.ll index d2b7fae75b23..aacbb9e766c4 100644 --- a/polly/test/CodeGen/non-affine-update.ll +++ b/polly/test/CodeGen/non-affine-update.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-import-jscop \ -; RUN: -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ +; RUN: -S < %s | FileCheck %s ; ; void non-affine-update(double A[], double C[], double B[]) { ; for (int i = 0; i < 10; i++) { diff --git a/polly/test/CodeGen/non-hoisted-load-needed-as-base-ptr.ll b/polly/test/CodeGen/non-hoisted-load-needed-as-base-ptr.ll index 5f6642b0630d..0c7c5f9a1700 100644 --- a/polly/test/CodeGen/non-hoisted-load-needed-as-base-ptr.ll +++ b/polly/test/CodeGen/non-hoisted-load-needed-as-base-ptr.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -tbaa -polly-codegen -disable-output %s +; RUN: opt %loadPolly -aa-pipeline=tbaa -passes=polly-codegen -disable-output %s ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/non_affine_float_compare.ll b/polly/test/CodeGen/non_affine_float_compare.ll index be310b5bf5ca..0b4813ac11ae 100644 --- a/polly/test/CodeGen/non_affine_float_compare.ll +++ b/polly/test/CodeGen/non_affine_float_compare.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen \ +; RUN: opt %loadPolly -passes=polly-codegen \ ; RUN: -polly-allow-nonaffine-branches -S -verify-dom-info \ ; RUN: < %s | FileCheck %s ; diff --git a/polly/test/CodeGen/only_non_affine_error_region.ll b/polly/test/CodeGen/only_non_affine_error_region.ll index b2ad1c1fe3fd..472aec927dcd 100644 --- a/polly/test/CodeGen/only_non_affine_error_region.ll +++ b/polly/test/CodeGen/only_non_affine_error_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; CHECK-NOT: polly.start ; diff --git a/polly/test/CodeGen/openmp_limit_threads.ll b/polly/test/CodeGen/openmp_limit_threads.ll index e8eb819f13d9..70f78ebac173 100644 --- a/polly/test/CodeGen/openmp_limit_threads.ll +++ b/polly/test/CodeGen/openmp_limit_threads.ll @@ -1,10 +1,10 @@ -; RUN: opt %loadPolly -polly-codegen -polly-parallel -S < %s | FileCheck %s --check-prefix=AUTO -; RUN: opt %loadPolly -polly-codegen -polly-parallel -polly-num-threads=1 -S < %s | FileCheck %s --check-prefix=ONE -; RUN: opt %loadPolly -polly-codegen -polly-parallel -polly-num-threads=4 -S < %s | FileCheck %s --check-prefix=FOUR +; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -S < %s | FileCheck %s --check-prefix=AUTO +; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -polly-num-threads=1 -S < %s | FileCheck %s --check-prefix=ONE +; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -polly-num-threads=4 -S < %s | FileCheck %s --check-prefix=FOUR -; RUN: opt %loadPolly -polly-codegen -polly-parallel -polly-omp-backend=LLVM -S < %s | FileCheck %s --check-prefix=LIBOMP-AUTO -; RUN: opt %loadPolly -polly-codegen -polly-parallel -polly-omp-backend=LLVM -polly-num-threads=1 -S < %s | FileCheck %s --check-prefix=LIBOMP-ONE -; RUN: opt %loadPolly -polly-codegen -polly-parallel -polly-omp-backend=LLVM -polly-num-threads=4 -S < %s | FileCheck %s --check-prefix=LIBOMP-FOUR +; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -polly-omp-backend=LLVM -S < %s | FileCheck %s --check-prefix=LIBOMP-AUTO +; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -polly-omp-backend=LLVM -polly-num-threads=1 -S < %s | FileCheck %s --check-prefix=LIBOMP-ONE +; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -polly-omp-backend=LLVM -polly-num-threads=4 -S < %s | FileCheck %s --check-prefix=LIBOMP-FOUR ; Ensure that the provided thread numbers are forwarded to the OpenMP calls. ; diff --git a/polly/test/CodeGen/out-of-scop-phi-node-use.ll b/polly/test/CodeGen/out-of-scop-phi-node-use.ll index 54e909ecf378..9ef0586d7077 100644 --- a/polly/test/CodeGen/out-of-scop-phi-node-use.ll +++ b/polly/test/CodeGen/out-of-scop-phi-node-use.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/polly/test/CodeGen/param_div_div_div_2.ll b/polly/test/CodeGen/param_div_div_div_2.ll index 764ca241f166..027c147b173e 100644 --- a/polly/test/CodeGen/param_div_div_div_2.ll +++ b/polly/test/CodeGen/param_div_div_div_2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s --check-prefix=IR ; ; Check that we guard the divisions because we moved them and thereby increased ; their domain. diff --git a/polly/test/CodeGen/partial_write_array.ll b/polly/test/CodeGen/partial_write_array.ll index 6dc5550d82af..82277d631e4c 100644 --- a/polly/test/CodeGen/partial_write_array.ll +++ b/polly/test/CodeGen/partial_write_array.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s ; ; Partial write of an array access. ; diff --git a/polly/test/CodeGen/partial_write_emptyset.ll b/polly/test/CodeGen/partial_write_emptyset.ll index a25195f11ed7..687599025e09 100644 --- a/polly/test/CodeGen/partial_write_emptyset.ll +++ b/polly/test/CodeGen/partial_write_emptyset.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s ; ; Partial write, where "partial" is the empty set. ; The store is never executed in this case and we do generate it in the diff --git a/polly/test/CodeGen/partial_write_full_write_that_appears_partial.ll b/polly/test/CodeGen/partial_write_full_write_that_appears_partial.ll index 18a809b30557..261d6fe7a0c5 100644 --- a/polly/test/CodeGen/partial_write_full_write_that_appears_partial.ll +++ b/polly/test/CodeGen/partial_write_full_write_that_appears_partial.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; CHECK: polly.stmt.if.then81: ; preds = %polly.stmt.if.end75 ; CHECK-NEXT: store float undef, ptr %fX64, align 4, !alias.scope !0, !noalias !3 diff --git a/polly/test/CodeGen/partial_write_impossible_restriction.ll b/polly/test/CodeGen/partial_write_impossible_restriction.ll index 178227fef8e5..d041edb9262e 100644 --- a/polly/test/CodeGen/partial_write_impossible_restriction.ll +++ b/polly/test/CodeGen/partial_write_impossible_restriction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s ; ; The isl scheduler isolates %cond.false into two instances. ; A partial write access in one of the instances was never executed, diff --git a/polly/test/CodeGen/partial_write_in_region.ll b/polly/test/CodeGen/partial_write_in_region.ll index d8f57b35d585..be5025778096 100644 --- a/polly/test/CodeGen/partial_write_in_region.ll +++ b/polly/test/CodeGen/partial_write_in_region.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-import-jscop \ -; RUN: -polly-import-jscop-postfix=transformed -polly-codegen \ +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ +; RUN: -polly-import-jscop-postfix=transformed \ ; RUN: -verify-dom-info \ ; RUN: -S < %s | FileCheck %s ; diff --git a/polly/test/CodeGen/partial_write_in_region_with_loop.ll b/polly/test/CodeGen/partial_write_in_region_with_loop.ll index 48a9dbef21d1..8379a5f279ed 100644 --- a/polly/test/CodeGen/partial_write_in_region_with_loop.ll +++ b/polly/test/CodeGen/partial_write_in_region_with_loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-import-jscop \ -; RUN: -polly-import-jscop-postfix=transformed -polly-codegen \ +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ +; RUN: -polly-import-jscop-postfix=transformed \ ; RUN: -verify-dom-info -polly-allow-nonaffine-loops \ ; RUN: -S < %s | FileCheck %s diff --git a/polly/test/CodeGen/partial_write_mapped_scalar.ll b/polly/test/CodeGen/partial_write_mapped_scalar.ll index 9137ef2123c8..b74705250be5 100644 --- a/polly/test/CodeGen/partial_write_mapped_scalar.ll +++ b/polly/test/CodeGen/partial_write_mapped_scalar.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s ; ; Partial write of a (mapped) scalar. ; diff --git a/polly/test/CodeGen/partial_write_mapped_scalar_subregion.ll b/polly/test/CodeGen/partial_write_mapped_scalar_subregion.ll index e054b65eadf3..80a97e1aa657 100644 --- a/polly/test/CodeGen/partial_write_mapped_scalar_subregion.ll +++ b/polly/test/CodeGen/partial_write_mapped_scalar_subregion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s ; ; Partial write of a (mapped) scalar in a non-affine subregion. ; diff --git a/polly/test/CodeGen/perf_monitoring.ll b/polly/test/CodeGen/perf_monitoring.ll index 2abbf24f5e78..dde7853b37fd 100644 --- a/polly/test/CodeGen/perf_monitoring.ll +++ b/polly/test/CodeGen/perf_monitoring.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-codegen-perf-monitoring \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-codegen-perf-monitoring \ ; RUN: -S < %s | FileCheck %s ; void f(long A[], long N) { diff --git a/polly/test/CodeGen/perf_monitoring_cycles_per_scop.ll b/polly/test/CodeGen/perf_monitoring_cycles_per_scop.ll index 11d63fc47658..d9efed5f8efa 100644 --- a/polly/test/CodeGen/perf_monitoring_cycles_per_scop.ll +++ b/polly/test/CodeGen/perf_monitoring_cycles_per_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-codegen-perf-monitoring \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-codegen-perf-monitoring \ ; RUN: -S < %s | FileCheck %s ; void f(long A[], long N) { diff --git a/polly/test/CodeGen/perf_monitoring_trip_counts_per_scop.ll b/polly/test/CodeGen/perf_monitoring_trip_counts_per_scop.ll index 9b7f324df8e4..560b44561bf5 100644 --- a/polly/test/CodeGen/perf_monitoring_trip_counts_per_scop.ll +++ b/polly/test/CodeGen/perf_monitoring_trip_counts_per_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-codegen-perf-monitoring \ +; RUN: opt %loadPolly -passes=polly-codegen -polly-codegen-perf-monitoring \ ; RUN: -S < %s | FileCheck %s ; void f(long A[], long N) { diff --git a/polly/test/CodeGen/phi-defined-before-scop.ll b/polly/test/CodeGen/phi-defined-before-scop.ll index a3b1ba264f04..1e6266673a8c 100644 --- a/polly/test/CodeGen/phi-defined-before-scop.ll +++ b/polly/test/CodeGen/phi-defined-before-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; CHECK-LABEL: polly.merge_new_and_old: ; CHECK-NEXT: %tmp7.ph.merge = phi ptr [ %tmp7.ph.final_reload, %polly.exiting ], [ %tmp7.ph, %bb6.region_exiting ] diff --git a/polly/test/CodeGen/phi_after_error_block_outside_of_scop.ll b/polly/test/CodeGen/phi_after_error_block_outside_of_scop.ll index c34ebfc3ca02..0121888f9fa9 100644 --- a/polly/test/CodeGen/phi_after_error_block_outside_of_scop.ll +++ b/polly/test/CodeGen/phi_after_error_block_outside_of_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; Make sure code generation does not break in case an 'error block' is detected ; outside of the scope. In this situation, we should not affect code generation. diff --git a/polly/test/CodeGen/phi_condition_modeling_1.ll b/polly/test/CodeGen/phi_condition_modeling_1.ll index b14d32921cf7..cf464fe234e3 100644 --- a/polly/test/CodeGen/phi_condition_modeling_1.ll +++ b/polly/test/CodeGen/phi_condition_modeling_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; void f(int *A, int c, int N) { ; int tmp; diff --git a/polly/test/CodeGen/phi_condition_modeling_2.ll b/polly/test/CodeGen/phi_condition_modeling_2.ll index dab2977bf065..25c67e625542 100644 --- a/polly/test/CodeGen/phi_condition_modeling_2.ll +++ b/polly/test/CodeGen/phi_condition_modeling_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; void f(int *A, int c, int N) { ; int tmp; diff --git a/polly/test/CodeGen/phi_conditional_simple_1.ll b/polly/test/CodeGen/phi_conditional_simple_1.ll index f1b93b540f70..3d0e35ccd353 100644 --- a/polly/test/CodeGen/phi_conditional_simple_1.ll +++ b/polly/test/CodeGen/phi_conditional_simple_1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; void jd(int *A, int c) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_1.ll b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_1.ll index 13688480e315..70af1d96f4e7 100644 --- a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_1.ll +++ b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; This caused an lnt crash at some point, just verify it will run through. ; diff --git a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_2.ll b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_2.ll index 01dd450590d9..f17d4a6b9160 100644 --- a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_2.ll +++ b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; This caused an lnt crash at some point, just verify it will run through and ; produce the PHI node in the exit we are looking for. diff --git a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_3.ll b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_3.ll index 66b95b0e0317..cf9b4050a39c 100644 --- a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_3.ll +++ b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; This caused an lnt crash at some point, just verify it will run through and ; produce the PHI node in the exit we are looking for. diff --git a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_5.ll b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_5.ll index 9a046367e768..dfc3e6757af8 100644 --- a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_5.ll +++ b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; This caused an lnt crash at some point, just verify it will run through and ; produce the PHI node in the exit we are looking for. diff --git a/polly/test/CodeGen/phi_loop_carried_float.ll b/polly/test/CodeGen/phi_loop_carried_float.ll index ca1870fb3a09..df51c3599b29 100644 --- a/polly/test/CodeGen/phi_loop_carried_float.ll +++ b/polly/test/CodeGen/phi_loop_carried_float.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; float f(float *A, int N) { ; float tmp = 0; diff --git a/polly/test/CodeGen/phi_loop_carried_float_escape.ll b/polly/test/CodeGen/phi_loop_carried_float_escape.ll index 3b2ed01863b1..10bc751150e2 100644 --- a/polly/test/CodeGen/phi_loop_carried_float_escape.ll +++ b/polly/test/CodeGen/phi_loop_carried_float_escape.ll @@ -1,8 +1,8 @@ ; RUN: opt %loadPolly -S \ -; RUN: -polly-analyze-read-only-scalars=false -polly-codegen < %s | FileCheck %s +; RUN: -polly-analyze-read-only-scalars=false -passes=polly-codegen < %s | FileCheck %s ; RUN: opt %loadPolly -S \ -; RUN: -polly-analyze-read-only-scalars=true -polly-codegen < %s | FileCheck %s +; RUN: -polly-analyze-read-only-scalars=true -passes=polly-codegen < %s | FileCheck %s ; ; float f(float *A, int N) { ; float tmp = 0; diff --git a/polly/test/CodeGen/phi_scalar_simple_1.ll b/polly/test/CodeGen/phi_scalar_simple_1.ll index d62975b6a7b3..07b8021fb743 100644 --- a/polly/test/CodeGen/phi_scalar_simple_1.ll +++ b/polly/test/CodeGen/phi_scalar_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; int jd(int *restrict A, int x, int N) { ; for (int i = 1; i < N; i++) diff --git a/polly/test/CodeGen/phi_scalar_simple_2.ll b/polly/test/CodeGen/phi_scalar_simple_2.ll index e58945d39960..ab89b74c35a7 100644 --- a/polly/test/CodeGen/phi_scalar_simple_2.ll +++ b/polly/test/CodeGen/phi_scalar_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; int jd(int *restrict A, int x, int N, int c) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/CodeGen/phi_with_multi_exiting_edges_2.ll b/polly/test/CodeGen/phi_with_multi_exiting_edges_2.ll index 17e4b7d6b4de..313ae27a4165 100644 --- a/polly/test/CodeGen/phi_with_multi_exiting_edges_2.ll +++ b/polly/test/CodeGen/phi_with_multi_exiting_edges_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; CHECK: polly.merge_new_and_old: ; CHECK: %result.ph.merge = phi float [ %result.ph.final_reload, %polly.exiting ], [ %result.ph, %next.region_exiting ] diff --git a/polly/test/CodeGen/phi_with_one_exit_edge.ll b/polly/test/CodeGen/phi_with_one_exit_edge.ll index 81fd73b51c79..fa692a9cdd38 100644 --- a/polly/test/CodeGen/phi_with_one_exit_edge.ll +++ b/polly/test/CodeGen/phi_with_one_exit_edge.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; ; CHECK: polly.merge_new_and_old: diff --git a/polly/test/CodeGen/pointer-type-expressions-2.ll b/polly/test/CodeGen/pointer-type-expressions-2.ll index b261cfe53321..013a9634844b 100644 --- a/polly/test/CodeGen/pointer-type-expressions-2.ll +++ b/polly/test/CodeGen/pointer-type-expressions-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" define void @foo(ptr %start, ptr %end) { diff --git a/polly/test/CodeGen/pointer-type-expressions.ll b/polly/test/CodeGen/pointer-type-expressions.ll index 6bb3fa242362..ad0c0639a9d9 100644 --- a/polly/test/CodeGen/pointer-type-expressions.ll +++ b/polly/test/CodeGen/pointer-type-expressions.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN ; void f(int a[], int N, float *P) { ; int i; diff --git a/polly/test/CodeGen/pointer-type-pointer-type-comparison.ll b/polly/test/CodeGen/pointer-type-pointer-type-comparison.ll index eaef64017aa7..5627a85c01b8 100644 --- a/polly/test/CodeGen/pointer-type-pointer-type-comparison.ll +++ b/polly/test/CodeGen/pointer-type-pointer-type-comparison.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN ; ; void f(int a[], int N, float *P, float *Q) { diff --git a/polly/test/CodeGen/pointer_rem.ll b/polly/test/CodeGen/pointer_rem.ll index 5c92ee52da2c..a82c5cefa26d 100644 --- a/polly/test/CodeGen/pointer_rem.ll +++ b/polly/test/CodeGen/pointer_rem.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -polly-scops -polly-print-ast -disable-output -S < %s | FileCheck %s --check-prefix=AST -; RUN: opt %loadPolly -polly-process-unprofitable -polly-scops -polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print,scop(print)' -disable-output -S < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print,scop(polly-codegen)' -S < %s | FileCheck %s --check-prefix=CODEGEN target datalayout = "e-m:e-i64:64-i128:128-n8:16:32:64-S128" target triple = "aarch64--linux-gnu" diff --git a/polly/test/CodeGen/pr25241.ll b/polly/test/CodeGen/pr25241.ll index 9fa67e083a6c..2f982c5ffbfc 100644 --- a/polly/test/CodeGen/pr25241.ll +++ b/polly/test/CodeGen/pr25241.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; PR25241 (https://llvm.org/bugs/show_bug.cgi?id=25241) ; Ensure that synthesized values of a PHI node argument are generated in the diff --git a/polly/test/CodeGen/ptrtoint_as_parameter.ll b/polly/test/CodeGen/ptrtoint_as_parameter.ll index 4f6c8079729d..ea7cd57bdcc0 100644 --- a/polly/test/CodeGen/ptrtoint_as_parameter.ll +++ b/polly/test/CodeGen/ptrtoint_as_parameter.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; CHECK: if.then260: ; CHECK-NEXT: %p.4 = getelementptr inbounds i8, ptr null, i64 1 diff --git a/polly/test/CodeGen/read-only-scalars.ll b/polly/test/CodeGen/read-only-scalars.ll index a5e1d2719d7d..318362d6a27a 100644 --- a/polly/test/CodeGen/read-only-scalars.ll +++ b/polly/test/CodeGen/read-only-scalars.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-analyze-read-only-scalars=false -polly-codegen \ +; RUN: opt %loadPolly -polly-analyze-read-only-scalars=false -passes=polly-codegen \ ; RUN: \ ; RUN: -S < %s | FileCheck %s -; RUN: opt %loadPolly -polly-analyze-read-only-scalars=true -polly-codegen \ +; RUN: opt %loadPolly -polly-analyze-read-only-scalars=true -passes=polly-codegen \ ; RUN: \ ; RUN: -S < %s | FileCheck %s -check-prefix=SCALAR diff --git a/polly/test/CodeGen/reduction.ll b/polly/test/CodeGen/reduction.ll index 6e5a230ad231..1af5a0d80124 100644 --- a/polly/test/CodeGen/reduction.ll +++ b/polly/test/CodeGen/reduction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s 2>&1 | not FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s 2>&1 | not FileCheck %s ;#include ;#include diff --git a/polly/test/CodeGen/reduction_2.ll b/polly/test/CodeGen/reduction_2.ll index 7a50cea31400..b4ed4d95d543 100644 --- a/polly/test/CodeGen/reduction_2.ll +++ b/polly/test/CodeGen/reduction_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-invariant-load-hoisting=true -polly-print-ast -disable-output < %s | FileCheck %s --allow-empty +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s | FileCheck %s --allow-empty ;#include ;#include diff --git a/polly/test/CodeGen/reduction_simple_binary.ll b/polly/test/CodeGen/reduction_simple_binary.ll index c7c5501bb7ed..25903d6554c5 100644 --- a/polly/test/CodeGen/reduction_simple_binary.ll +++ b/polly/test/CodeGen/reduction_simple_binary.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: pragma simd reduction ; diff --git a/polly/test/CodeGen/region-with-instructions.ll b/polly/test/CodeGen/region-with-instructions.ll index 28cabefbf68b..125b791cbcf2 100644 --- a/polly/test/CodeGen/region-with-instructions.ll +++ b/polly/test/CodeGen/region-with-instructions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; CHECK-LABEL: polly.stmt.bb48: ; CHECK-NEXT: %[[offset:.*]] = shl i64 %polly.indvar, 3 diff --git a/polly/test/CodeGen/region_exiting-domtree.ll b/polly/test/CodeGen/region_exiting-domtree.ll index 05983da0a3e3..354f631e1002 100644 --- a/polly/test/CodeGen/region_exiting-domtree.ll +++ b/polly/test/CodeGen/region_exiting-domtree.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -verify-dom-info -disable-output < %s +; RUN: opt %loadPolly -passes=polly-codegen -verify-dom-info -disable-output < %s ; Verify that the DominatorTree is preserved correctly for the inserted ; %polly.stmt.exit.exit block, which serves as new exit block for the generated diff --git a/polly/test/CodeGen/region_multiexit_partialwrite.ll b/polly/test/CodeGen/region_multiexit_partialwrite.ll index b98d7f58732a..49547c6615d5 100644 --- a/polly/test/CodeGen/region_multiexit_partialwrite.ll +++ b/polly/test/CodeGen/region_multiexit_partialwrite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s ; ; This text case has a partial write of PHI in a region-statement. It ; requires that the new PHINode from the region's exiting block is diff --git a/polly/test/CodeGen/run-time-condition-with-scev-parameters.ll b/polly/test/CodeGen/run-time-condition-with-scev-parameters.ll index 0f62a8c743df..df6377ace33a 100644 --- a/polly/test/CodeGen/run-time-condition-with-scev-parameters.ll +++ b/polly/test/CodeGen/run-time-condition-with-scev-parameters.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; TODO: FIXME: Simplify the context. ; AST: if (n >= 1 && 0 == n <= -1) diff --git a/polly/test/CodeGen/run-time-condition.ll b/polly/test/CodeGen/run-time-condition.ll index 0faefad8aef4..2a8cc72f8e9e 100644 --- a/polly/test/CodeGen/run-time-condition.ll +++ b/polly/test/CodeGen/run-time-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -S < %s | 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-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/scalar-references-used-in-scop-compute.ll b/polly/test/CodeGen/scalar-references-used-in-scop-compute.ll index 3f88942c2300..3519ffaef99b 100644 --- a/polly/test/CodeGen/scalar-references-used-in-scop-compute.ll +++ b/polly/test/CodeGen/scalar-references-used-in-scop-compute.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; Test the code generation in the presence of a scalar out-of-scop value being ; used from within the SCoP. diff --git a/polly/test/CodeGen/scalar-store-from-same-bb.ll b/polly/test/CodeGen/scalar-store-from-same-bb.ll index ac8fab4b7a0d..016784a9deea 100644 --- a/polly/test/CodeGen/scalar-store-from-same-bb.ll +++ b/polly/test/CodeGen/scalar-store-from-same-bb.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly \ -; RUN: -polly-codegen -S < %s | FileCheck %s +; RUN: -passes=polly-codegen -S < %s | FileCheck %s ; This test ensures that the expression N + 1 that is stored in the phi-node ; alloca, is directly computed and not incorrectly transfered through memory. diff --git a/polly/test/CodeGen/scalar_codegen_crash.ll b/polly/test/CodeGen/scalar_codegen_crash.ll index c41a00f59e81..e89c3558a187 100644 --- a/polly/test/CodeGen/scalar_codegen_crash.ll +++ b/polly/test/CodeGen/scalar_codegen_crash.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly \ -; RUN: -polly-codegen -S < %s | FileCheck %s +; RUN: -passes=polly-codegen -S < %s | FileCheck %s ; This test cases used to crash the scalar code generation. Check that we ; can generate code for it. diff --git a/polly/test/CodeGen/scev-backedgetaken.ll b/polly/test/CodeGen/scev-backedgetaken.ll index 15e12ee8b451..00fcf0b03482 100644 --- a/polly/test/CodeGen/scev-backedgetaken.ll +++ b/polly/test/CodeGen/scev-backedgetaken.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; llvm.org/PR48422 ; Use of ScalarEvolution in Codegen not possible because DominatorTree is not updated. diff --git a/polly/test/CodeGen/scev-division-invariant-load.ll b/polly/test/CodeGen/scev-division-invariant-load.ll index 3156bdc9f5ce..242fb75c3883 100644 --- a/polly/test/CodeGen/scev-division-invariant-load.ll +++ b/polly/test/CodeGen/scev-division-invariant-load.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s ; ; Check that we generate valid code as we did not use the preloaded ; value of %tmp1 for the access function of the preloaded %tmp4. diff --git a/polly/test/CodeGen/scev.ll b/polly/test/CodeGen/scev.ll index 07d726d97caf..74faf062bdc7 100644 --- a/polly/test/CodeGen/scev.ll +++ b/polly/test/CodeGen/scev.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-detect < %s +; RUN: opt %loadPolly '-passes=print' < %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-n8:16:32:64" define fastcc void @f () inlinehint align 2 { diff --git a/polly/test/CodeGen/scev_expansion_in_nonaffine.ll b/polly/test/CodeGen/scev_expansion_in_nonaffine.ll index f61f21d4adb8..0575795cde48 100644 --- a/polly/test/CodeGen/scev_expansion_in_nonaffine.ll +++ b/polly/test/CodeGen/scev_expansion_in_nonaffine.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S \ +; RUN: opt %loadPolly -passes=polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; bugpoint-reduced testcase of MiBench/consumer-lame/quantize-pvt.c from the diff --git a/polly/test/CodeGen/scev_looking_through_bitcasts.ll b/polly/test/CodeGen/scev_looking_through_bitcasts.ll index c87d932479b7..776bb3332085 100644 --- a/polly/test/CodeGen/scev_looking_through_bitcasts.ll +++ b/polly/test/CodeGen/scev_looking_through_bitcasts.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; Scalar write of bitcasted value. Instead of writing %b of type ; %structty, the SCEV expression looks through the bitcast such that diff --git a/polly/test/CodeGen/scop_expander_insert_point.ll b/polly/test/CodeGen/scop_expander_insert_point.ll index 8492873b22ed..8434e7ec1aa8 100644 --- a/polly/test/CodeGen/scop_expander_insert_point.ll +++ b/polly/test/CodeGen/scop_expander_insert_point.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S \ +; RUN: opt %loadPolly -passes=polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; CHECK: entry: diff --git a/polly/test/CodeGen/scop_expander_segfault.ll b/polly/test/CodeGen/scop_expander_segfault.ll index 293c1e527959..73145c4bfa23 100644 --- a/polly/test/CodeGen/scop_expander_segfault.ll +++ b/polly/test/CodeGen/scop_expander_segfault.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S %s | FileCheck %s ; ; This test was extracted from gcc in SPEC2006 and it crashed our code ; generation, or to be more precise, the ScopExpander due to a endless diff --git a/polly/test/CodeGen/scop_never_executed_runtime_check_location.ll b/polly/test/CodeGen/scop_never_executed_runtime_check_location.ll index 91a58159b5f9..cc76ad1771c9 100644 --- a/polly/test/CodeGen/scop_never_executed_runtime_check_location.ll +++ b/polly/test/CodeGen/scop_never_executed_runtime_check_location.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; Verify that we generate the runtime check code after the conditional branch ; in the SCoP region entering block (here %entry). diff --git a/polly/test/CodeGen/select-base-pointer.ll b/polly/test/CodeGen/select-base-pointer.ll index 29bc40074e1f..9748736147ab 100644 --- a/polly/test/CodeGen/select-base-pointer.ll +++ b/polly/test/CodeGen/select-base-pointer.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -tbaa -polly-codegen -disable-output %s +; RUN: opt %loadPolly -aa-pipeline=tbaa -passes=polly-codegen -disable-output %s ; ; Check that we do not crash here. ; diff --git a/polly/test/CodeGen/sequential_loops.ll b/polly/test/CodeGen/sequential_loops.ll index 97d280de3cd2..a0cecfbd817b 100644 --- a/polly/test/CodeGen/sequential_loops.ll +++ b/polly/test/CodeGen/sequential_loops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ;#include ;#define N 1024 diff --git a/polly/test/CodeGen/simple_loop_non_single_exit.ll b/polly/test/CodeGen/simple_loop_non_single_exit.ll index dc1b09b765a1..a6f115ba1112 100644 --- a/polly/test/CodeGen/simple_loop_non_single_exit.ll +++ b/polly/test/CodeGen/simple_loop_non_single_exit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE ; void f(long A[], long N) { ; long i; diff --git a/polly/test/CodeGen/simple_loop_non_single_exit_2.ll b/polly/test/CodeGen/simple_loop_non_single_exit_2.ll index 178601cac9b8..d58a6ed7b746 100644 --- a/polly/test/CodeGen/simple_loop_non_single_exit_2.ll +++ b/polly/test/CodeGen/simple_loop_non_single_exit_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE ; void f(long A[], long N) { ; long i; diff --git a/polly/test/CodeGen/simple_non_single_entry.ll b/polly/test/CodeGen/simple_non_single_entry.ll index 3b4bf59bdc65..2b472496d364 100644 --- a/polly/test/CodeGen/simple_non_single_entry.ll +++ b/polly/test/CodeGen/simple_non_single_entry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE ; void f(long A[], long N) { ; long i; diff --git a/polly/test/CodeGen/simple_nonaffine_loop.ll b/polly/test/CodeGen/simple_nonaffine_loop.ll index d4e9c6082e6c..4074237d1bfb 100644 --- a/polly/test/CodeGen/simple_nonaffine_loop.ll +++ b/polly/test/CodeGen/simple_nonaffine_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-allow-nonaffine -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-allow-nonaffine -disable-output < %s | FileCheck %s ;#include ;#include diff --git a/polly/test/CodeGen/single_do_loop_int_max_iterations.ll b/polly/test/CodeGen/single_do_loop_int_max_iterations.ll index 9648fbe1cf12..0b1d3e14f68a 100644 --- a/polly/test/CodeGen/single_do_loop_int_max_iterations.ll +++ b/polly/test/CodeGen/single_do_loop_int_max_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ;#define N 20 ;#include "limits.h" diff --git a/polly/test/CodeGen/single_do_loop_int_param_iterations.ll b/polly/test/CodeGen/single_do_loop_int_param_iterations.ll index f28d828a5da0..459ba18edac4 100644 --- a/polly/test/CodeGen/single_do_loop_int_param_iterations.ll +++ b/polly/test/CodeGen/single_do_loop_int_param_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; XFAIL: * ;define N 20 diff --git a/polly/test/CodeGen/single_do_loop_ll_max_iterations.ll b/polly/test/CodeGen/single_do_loop_ll_max_iterations.ll index 68aaab96083a..5fdb5b14df4d 100644 --- a/polly/test/CodeGen/single_do_loop_ll_max_iterations.ll +++ b/polly/test/CodeGen/single_do_loop_ll_max_iterations.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen < %s ;#define N 20 ;#include "limits.h" diff --git a/polly/test/CodeGen/single_do_loop_one_iteration.ll b/polly/test/CodeGen/single_do_loop_one_iteration.ll index 9d97cb854734..18bab682adeb 100644 --- a/polly/test/CodeGen/single_do_loop_one_iteration.ll +++ b/polly/test/CodeGen/single_do_loop_one_iteration.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; XFAIL: * ;#define N 20 diff --git a/polly/test/CodeGen/single_do_loop_scev_replace.ll b/polly/test/CodeGen/single_do_loop_scev_replace.ll index 7963d9d29fe8..9bdc3d7cd9b5 100644 --- a/polly/test/CodeGen/single_do_loop_scev_replace.ll +++ b/polly/test/CodeGen/single_do_loop_scev_replace.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ;#define N 20 ;#include "limits.h" diff --git a/polly/test/CodeGen/single_loop.ll b/polly/test/CodeGen/single_loop.ll index 68cc498b43e0..fe68c81567f8 100644 --- a/polly/test/CodeGen/single_loop.ll +++ b/polly/test/CodeGen/single_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ;#include ;#define N 1024 diff --git a/polly/test/CodeGen/single_loop_int_max_iterations.ll b/polly/test/CodeGen/single_loop_int_max_iterations.ll index bfb5e4ab2698..017f1a3114cc 100644 --- a/polly/test/CodeGen/single_loop_int_max_iterations.ll +++ b/polly/test/CodeGen/single_loop_int_max_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ;#define N 20 ;#include "limits.h" diff --git a/polly/test/CodeGen/single_loop_ll_max_iterations.ll b/polly/test/CodeGen/single_loop_ll_max_iterations.ll index bdfd7fce4204..89fb9be7f9e1 100644 --- a/polly/test/CodeGen/single_loop_ll_max_iterations.ll +++ b/polly/test/CodeGen/single_loop_ll_max_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ;#include "limits.h" ;#define N 20 diff --git a/polly/test/CodeGen/single_loop_one_iteration.ll b/polly/test/CodeGen/single_loop_one_iteration.ll index 7d4dd590fab9..fcbe34da2a92 100644 --- a/polly/test/CodeGen/single_loop_one_iteration.ll +++ b/polly/test/CodeGen/single_loop_one_iteration.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ;#define N 20 ; diff --git a/polly/test/CodeGen/single_loop_param.ll b/polly/test/CodeGen/single_loop_param.ll index 5d72da354fdc..19f3fb42a475 100644 --- a/polly/test/CodeGen/single_loop_param.ll +++ b/polly/test/CodeGen/single_loop_param.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | 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-n8:16:32:64" @A = common global [1024 x i32] zeroinitializer, align 16 ; [#uses=3] diff --git a/polly/test/CodeGen/single_loop_param_less_equal.ll b/polly/test/CodeGen/single_loop_param_less_equal.ll index e63ee299a37c..07d0ef24f4c0 100644 --- a/polly/test/CodeGen/single_loop_param_less_equal.ll +++ b/polly/test/CodeGen/single_loop_param_less_equal.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN -; RUN: opt %loadPolly -polly-codegen < %s | opt -passes='print' -disable-output 2>&1 | FileCheck %s -check-prefix=LOOPS +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly -passes=polly-codegen < %s | opt -passes='print' -disable-output 2>&1 | FileCheck %s -check-prefix=LOOPS 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-n8:16:32:64" @A = common global [1024 x i32] zeroinitializer diff --git a/polly/test/CodeGen/single_loop_param_less_than.ll b/polly/test/CodeGen/single_loop_param_less_than.ll index 95130f926450..26dddea44b20 100644 --- a/polly/test/CodeGen/single_loop_param_less_than.ll +++ b/polly/test/CodeGen/single_loop_param_less_than.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN 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-n8:16:32:64" @A = common global [1024 x i32] zeroinitializer diff --git a/polly/test/CodeGen/single_loop_zero_iterations.ll b/polly/test/CodeGen/single_loop_zero_iterations.ll index 4f189687d330..e4a5b7670d77 100644 --- a/polly/test/CodeGen/single_loop_zero_iterations.ll +++ b/polly/test/CodeGen/single_loop_zero_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=SCALAR --allow-empty +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=SCALAR --allow-empty ;#define N 20 ; diff --git a/polly/test/CodeGen/split_edge_of_exit.ll b/polly/test/CodeGen/split_edge_of_exit.ll index 56ce215a62b2..3f2a1389f886 100644 --- a/polly/test/CodeGen/split_edge_of_exit.ll +++ b/polly/test/CodeGen/split_edge_of_exit.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -verify-region-info -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -verify-region-info -disable-output < %s ; ; This is a scop directly precedented by a region, i.e. the scop's entry is the ; region's exit block. This test is to ensure that the RegionInfo is correctly diff --git a/polly/test/CodeGen/split_edges.ll b/polly/test/CodeGen/split_edges.ll index e01d901e298c..0fc705becb91 100644 --- a/polly/test/CodeGen/split_edges.ll +++ b/polly/test/CodeGen/split_edges.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -verify-region-info -verify-dom-info -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -verify-region-info -verify-dom-info -S < %s | 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-n8:16:32:64" @A = common global [1536 x float] zeroinitializer diff --git a/polly/test/CodeGen/split_edges_2.ll b/polly/test/CodeGen/split_edges_2.ll index 4135d6feeb3e..84449327bf4c 100644 --- a/polly/test/CodeGen/split_edges_2.ll +++ b/polly/test/CodeGen/split_edges_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -verify-region-info -verify-dom-info -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -verify-region-info -verify-dom-info -S < %s | 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-n8:16:32:64" diff --git a/polly/test/CodeGen/srem-in-other-bb.ll b/polly/test/CodeGen/srem-in-other-bb.ll index 8bde1a3bbc1d..eaad663159f0 100644 --- a/polly/test/CodeGen/srem-in-other-bb.ll +++ b/polly/test/CodeGen/srem-in-other-bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S \ +; RUN: opt %loadPolly -passes=polly-codegen -S \ ; RUN: < %s | FileCheck %s ; ; void pos(float *A, long n) { diff --git a/polly/test/CodeGen/stack-overflow-in-load-hoisting.ll b/polly/test/CodeGen/stack-overflow-in-load-hoisting.ll index 02dfe96e3e91..41241de132a3 100644 --- a/polly/test/CodeGen/stack-overflow-in-load-hoisting.ll +++ b/polly/test/CodeGen/stack-overflow-in-load-hoisting.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -verify-dom-info -polly-codegen -S < %s \ +; RUN: opt %loadPolly -verify-dom-info -passes=polly-codegen -S < %s \ ; RUN: -polly-invariant-load-hoisting=true | FileCheck %s ; ; This caused an infinite recursion during invariant load hoisting at some diff --git a/polly/test/CodeGen/stmt_split_no_dependence.ll b/polly/test/CodeGen/stmt_split_no_dependence.ll index a395aa14b4c8..94407e8e7c38 100644 --- a/polly/test/CodeGen/stmt_split_no_dependence.ll +++ b/polly/test/CodeGen/stmt_split_no_dependence.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; CHECK: store i32 %9, ptr %scevgep, align 4, !alias.scope !1, !noalias !4 ; CHECK: store i32 %11, ptr %scevgep4, align 4, !alias.scope !4, !noalias !1 diff --git a/polly/test/CodeGen/switch-in-non-affine-region.ll b/polly/test/CodeGen/switch-in-non-affine-region.ll index 930755ef5648..2524699157b7 100644 --- a/polly/test/CodeGen/switch-in-non-affine-region.ll +++ b/polly/test/CodeGen/switch-in-non-affine-region.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly \ -; RUN: -S -polly-codegen < %s | FileCheck %s +; RUN: -S -passes=polly-codegen < %s | FileCheck %s ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/CodeGen/synthesizable_phi_write_after_loop.ll b/polly/test/CodeGen/synthesizable_phi_write_after_loop.ll index 6a8d3b94d1cc..86745d71953e 100644 --- a/polly/test/CodeGen/synthesizable_phi_write_after_loop.ll +++ b/polly/test/CodeGen/synthesizable_phi_write_after_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; Check for the correct written value of a scalar phi write whose value is ; defined within the loop, but its effective value is its last definition when diff --git a/polly/test/CodeGen/test-invalid-operands-for-select-2.ll b/polly/test/CodeGen/test-invalid-operands-for-select-2.ll index 5fa4773398fd..9b3608c81f50 100644 --- a/polly/test/CodeGen/test-invalid-operands-for-select-2.ll +++ b/polly/test/CodeGen/test-invalid-operands-for-select-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen -verify-loop-info < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen -verify-loop-info < %s | FileCheck %s ; ; Check that we do not crash as described here: http://llvm.org/bugs/show_bug.cgi?id=21167 ; diff --git a/polly/test/CodeGen/test-invalid-operands-for-select.ll b/polly/test/CodeGen/test-invalid-operands-for-select.ll index 40695af3e847..a10603126cf6 100644 --- a/polly/test/CodeGen/test-invalid-operands-for-select.ll +++ b/polly/test/CodeGen/test-invalid-operands-for-select.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; Check that we do not crash as described here: http://llvm.org/PR21167 ; diff --git a/polly/test/CodeGen/test.ll b/polly/test/CodeGen/test.ll index ac99688ed9e8..1038e57c358f 100644 --- a/polly/test/CodeGen/test.ll +++ b/polly/test/CodeGen/test.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; XFAIL: * ;int bar1(); diff --git a/polly/test/CodeGen/two-loops-right-after-each-other-2.ll b/polly/test/CodeGen/two-loops-right-after-each-other-2.ll index a7cae0a921ca..71bec88e7dde 100644 --- a/polly/test/CodeGen/two-loops-right-after-each-other-2.ll +++ b/polly/test/CodeGen/two-loops-right-after-each-other-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; CHECK: polly.merge_new_and_old: ; CHECK-NEXT: merge = phi diff --git a/polly/test/CodeGen/two-scops-in-row-invalidate-scevs.ll b/polly/test/CodeGen/two-scops-in-row-invalidate-scevs.ll index 4470f970fc1e..327430da11bb 100644 --- a/polly/test/CodeGen/two-scops-in-row-invalidate-scevs.ll +++ b/polly/test/CodeGen/two-scops-in-row-invalidate-scevs.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; CHECK-LABEL: for.cond: ; CHECK: %num.0 = phi i32 [ %add, %for.body15 ], [ 0, %for.cond.pre_entry_bb ] diff --git a/polly/test/CodeGen/two-scops-in-row.ll b/polly/test/CodeGen/two-scops-in-row.ll index 3e922cba1916..06e7ea096d79 100644 --- a/polly/test/CodeGen/two-scops-in-row.ll +++ b/polly/test/CodeGen/two-scops-in-row.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-ignore-aliasing -disable-output < %s | FileCheck %s -check-prefix=SCALAR -; RUN: opt %loadPolly -polly-codegen -polly-ignore-aliasing -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -polly-ignore-aliasing -disable-output < %s | FileCheck %s -check-prefix=SCALAR +; RUN: opt %loadPolly -passes=polly-codegen -polly-ignore-aliasing -disable-output < %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; SCALAR: if ( diff --git a/polly/test/CodeGen/udiv_expansion_position.ll b/polly/test/CodeGen/udiv_expansion_position.ll index bb37fed4a41e..39df17dc2030 100644 --- a/polly/test/CodeGen/udiv_expansion_position.ll +++ b/polly/test/CodeGen/udiv_expansion_position.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s ; ; Verify we do not crash when we synthezise code for the udiv in the SCoP. ; diff --git a/polly/test/CodeGen/uninitialized_scalar_memory.ll b/polly/test/CodeGen/uninitialized_scalar_memory.ll index 935ccc3d6289..89eb32c4cf0f 100644 --- a/polly/test/CodeGen/uninitialized_scalar_memory.ll +++ b/polly/test/CodeGen/uninitialized_scalar_memory.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s ; ; Verify we initialize the scalar locations reserved for the incoming phi ; values. diff --git a/polly/test/CodeGen/unpredictable-loop-unsynthesizable.ll b/polly/test/CodeGen/unpredictable-loop-unsynthesizable.ll index 9164bb4532e6..e3d0f2df7351 100644 --- a/polly/test/CodeGen/unpredictable-loop-unsynthesizable.ll +++ b/polly/test/CodeGen/unpredictable-loop-unsynthesizable.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops \ -; RUN: -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-codegen \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' \ +; RUN: -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -passes=polly-codegen \ ; RUN: -polly-invariant-load-hoisting=true -disable-output < %s ; The loop for.body is a scop with invariant load hoisting, but does not diff --git a/polly/test/CodeGen/variant_load_empty_domain.ll b/polly/test/CodeGen/variant_load_empty_domain.ll index f5ad0b195818..0ea3b0d1ed1f 100644 --- a/polly/test/CodeGen/variant_load_empty_domain.ll +++ b/polly/test/CodeGen/variant_load_empty_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -disable-output < %s +; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s ; ; ; void f(int *A) { diff --git a/polly/test/CodeGen/whole-scop-non-affine-subregion.ll b/polly/test/CodeGen/whole-scop-non-affine-subregion.ll index 931e644f6b8f..9c911715904d 100644 --- a/polly/test/CodeGen/whole-scop-non-affine-subregion.ll +++ b/polly/test/CodeGen/whole-scop-non-affine-subregion.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly \ -; RUN: -polly-codegen -S < %s | FileCheck %s +; RUN: -passes=polly-codegen -S < %s | FileCheck %s ; CHECK: polly.start ; int /* pure */ g() diff --git a/polly/test/DeLICM/confused_order.ll b/polly/test/DeLICM/confused_order.ll index 2015ebcf58f1..62f59cdef315 100644 --- a/polly/test/DeLICM/confused_order.ll +++ b/polly/test/DeLICM/confused_order.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-delicm -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-delicm -disable-output -pass-remarks-missed=polly-delicm < %s 2>&1 | FileCheck %s -check-prefix=REMARKS +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-delicm' -polly-import-jscop-postfix=transformed -disable-output -pass-remarks-missed=polly-delicm < %s 2>&1 | FileCheck %s -check-prefix=REMARKS ; ; ForwardOptree changes the SCoP and may already map some accesses. ; DeLICM must be prepared to encounter implicit reads diff --git a/polly/test/DeLICM/contradicting_assumed_context_and_domain.ll b/polly/test/DeLICM/contradicting_assumed_context_and_domain.ll index 4e039b22b415..768cb23631e7 100644 --- a/polly/test/DeLICM/contradicting_assumed_context_and_domain.ll +++ b/polly/test/DeLICM/contradicting_assumed_context_and_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; The domain of bb14 contradicts the SCoP's assumptions. This leads to ; 'anything goes' inside the statement since it is never executed, diff --git a/polly/test/DeLICM/load-in-cond-inf-loop.ll b/polly/test/DeLICM/load-in-cond-inf-loop.ll index f0aecfd87a15..40e30a52c545 100644 --- a/polly/test/DeLICM/load-in-cond-inf-loop.ll +++ b/polly/test/DeLICM/load-in-cond-inf-loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; When %b is 0, %for.body13 is an infite loop. In this case the loaded ; value %1 is not used anywhere. diff --git a/polly/test/DeLICM/map_memset_zero.ll b/polly/test/DeLICM/map_memset_zero.ll index 1a08eee63fe9..6789577cb046 100644 --- a/polly/test/DeLICM/map_memset_zero.ll +++ b/polly/test/DeLICM/map_memset_zero.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck -match-full-lines %s -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck -match-full-lines %s ; ; Check that PHI mapping works even in presence of a memset whose' ; zero value is used. diff --git a/polly/test/DeLICM/nomap_alreadymapped.ll b/polly/test/DeLICM/nomap_alreadymapped.ll index 7adf4ba88385..bf26a809324b 100644 --- a/polly/test/DeLICM/nomap_alreadymapped.ll +++ b/polly/test/DeLICM/nomap_alreadymapped.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/nomap_escaping.ll b/polly/test/DeLICM/nomap_escaping.ll index 034c0a96ccf2..17451a2941ea 100644 --- a/polly/test/DeLICM/nomap_escaping.ll +++ b/polly/test/DeLICM/nomap_escaping.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/nomap_occupied.ll b/polly/test/DeLICM/nomap_occupied.ll index db33532b1e65..e6ca903dae03 100644 --- a/polly/test/DeLICM/nomap_occupied.ll +++ b/polly/test/DeLICM/nomap_occupied.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/nomap_readonly.ll b/polly/test/DeLICM/nomap_readonly.ll index 1f3b5746fe9b..2c19bb9bc495 100644 --- a/polly/test/DeLICM/nomap_readonly.ll +++ b/polly/test/DeLICM/nomap_readonly.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; fsomeval = 21.0 + 21.0; diff --git a/polly/test/DeLICM/nomap_spuriouswrite.ll b/polly/test/DeLICM/nomap_spuriouswrite.ll index ef470f715bbe..f561a4b189ee 100644 --- a/polly/test/DeLICM/nomap_spuriouswrite.ll +++ b/polly/test/DeLICM/nomap_spuriouswrite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/nomap_storagesize.ll b/polly/test/DeLICM/nomap_storagesize.ll index fab8d54c2bdf..2c116cc85609 100644 --- a/polly/test/DeLICM/nomap_storagesize.ll +++ b/polly/test/DeLICM/nomap_storagesize.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; void func(float *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/nomap_writewrite.ll b/polly/test/DeLICM/nomap_writewrite.ll index 06192d9ae19e..6e3b06a4c57f 100644 --- a/polly/test/DeLICM/nomap_writewrite.ll +++ b/polly/test/DeLICM/nomap_writewrite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/outofquota-reverseDomain.ll b/polly/test/DeLICM/outofquota-reverseDomain.ll index d40ee03cf3bc..d917d294dcdf 100644 --- a/polly/test/DeLICM/outofquota-reverseDomain.ll +++ b/polly/test/DeLICM/outofquota-reverseDomain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-delicm-max-ops=1000000 -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-delicm-max-ops=1000000 '-passes=print' -disable-output < %s | FileCheck %s ; ; This causes an assertion to fail on out-of-quota after 1000000 operations. ; (The error was specific to -polly-delicm-max-ops=1000000 and changes diff --git a/polly/test/DeLICM/pass_existence.ll b/polly/test/DeLICM/pass_existence.ll index 7ed2da9c1da1..57adf45b207c 100644 --- a/polly/test/DeLICM/pass_existence.ll +++ b/polly/test/DeLICM/pass_existence.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-delicm -disable-output < %s -; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-delicm -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=scop(print)' -disable-output < %s | FileCheck %s ; ; Simple test for the existence of the DeLICM pass. ; diff --git a/polly/test/DeLICM/pr41656.ll b/polly/test/DeLICM/pr41656.ll index 965ad9f62ac3..ba65b5bf0416 100644 --- a/polly/test/DeLICM/pr41656.ll +++ b/polly/test/DeLICM/pr41656.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,scop(print)' -disable-output < %s 2>&1 | FileCheck %s ; ; llvm.org/PR41656 ; diff --git a/polly/test/DeLICM/pr48783.ll b/polly/test/DeLICM/pr48783.ll index 3cbd54b93baf..2bba7f731f56 100644 --- a/polly/test/DeLICM/pr48783.ll +++ b/polly/test/DeLICM/pr48783.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,scop(print)' -disable-output < %s 2>&1 | FileCheck %s ; ; llvm.org/PR48783 ; diff --git a/polly/test/DeLICM/reduction.ll b/polly/test/DeLICM/reduction.ll index 78c1a4ce5288..a6f1e032f6e4 100644 --- a/polly/test/DeLICM/reduction.ll +++ b/polly/test/DeLICM/reduction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-delicm-partial-writes=true -polly-print-delicm -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-delicm-partial-writes=true '-passes=print' -disable-output < %s | FileCheck -match-full-lines %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/reduction_looprotate_gvnpre_cond1.ll b/polly/test/DeLICM/reduction_looprotate_gvnpre_cond1.ll index b5bc0d589c65..e30fe12c8a74 100644 --- a/polly/test/DeLICM/reduction_looprotate_gvnpre_cond1.ll +++ b/polly/test/DeLICM/reduction_looprotate_gvnpre_cond1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Load (but not store) of A[j] hoisted, reduction only over some iterations. ; diff --git a/polly/test/DeLICM/reduction_looprotate_gvnpre_cond2.ll b/polly/test/DeLICM/reduction_looprotate_gvnpre_cond2.ll index e995be1143a6..a830782e9c44 100644 --- a/polly/test/DeLICM/reduction_looprotate_gvnpre_cond2.ll +++ b/polly/test/DeLICM/reduction_looprotate_gvnpre_cond2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Load (but not store) of A[j] hoisted, reduction not written in all iterations. ; FIXME: %join is not mapped because the MemoryKind::Value mapping does not diff --git a/polly/test/DeLICM/reduction_looprotate_gvnpre_nopreheader.ll b/polly/test/DeLICM/reduction_looprotate_gvnpre_nopreheader.ll index ca3a1211ca49..903bc80b9d47 100644 --- a/polly/test/DeLICM/reduction_looprotate_gvnpre_nopreheader.ll +++ b/polly/test/DeLICM/reduction_looprotate_gvnpre_nopreheader.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Hosted reduction load (but not the store) without preheader. ; diff --git a/polly/test/DeLICM/reduction_looprotate_licm_nopreheader.ll b/polly/test/DeLICM/reduction_looprotate_licm_nopreheader.ll index 41538239fbd8..23497f19402b 100644 --- a/polly/test/DeLICM/reduction_looprotate_licm_nopreheader.ll +++ b/polly/test/DeLICM/reduction_looprotate_licm_nopreheader.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s ; ; Register-promoted reduction but without preheader. ; diff --git a/polly/test/DeLICM/reduction_looprotate_loopguard_gvnpre.ll b/polly/test/DeLICM/reduction_looprotate_loopguard_gvnpre.ll index 35c723e864d2..c932a311a7aa 100644 --- a/polly/test/DeLICM/reduction_looprotate_loopguard_gvnpre.ll +++ b/polly/test/DeLICM/reduction_looprotate_loopguard_gvnpre.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Reduction over parametric number of elements and a loopguard if the ; reduction loop is not executed at all. Load hoisted before loop. diff --git a/polly/test/DeLICM/reduction_looprotate_loopguard_licm1.ll b/polly/test/DeLICM/reduction_looprotate_loopguard_licm1.ll index 2b5f4d8151a8..52073eb35014 100644 --- a/polly/test/DeLICM/reduction_looprotate_loopguard_licm1.ll +++ b/polly/test/DeLICM/reduction_looprotate_loopguard_licm1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Reduction over parametric number of elements and a loopguard if the ; reduction loop is not executed at all. diff --git a/polly/test/DeLICM/reduction_looprotate_loopguard_licm2.ll b/polly/test/DeLICM/reduction_looprotate_loopguard_licm2.ll index 2e92813d5551..88ae8b3b0f20 100644 --- a/polly/test/DeLICM/reduction_looprotate_loopguard_licm2.ll +++ b/polly/test/DeLICM/reduction_looprotate_loopguard_licm2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Reduction over parametric number of elements and a loopguard if the ; reduction loop is not executed at all, such that A[j] is also not written to. diff --git a/polly/test/DeLICM/reduction_looprotate_loopguard_licm3.ll b/polly/test/DeLICM/reduction_looprotate_loopguard_licm3.ll index 784c8ef2d321..3a356926afa0 100644 --- a/polly/test/DeLICM/reduction_looprotate_loopguard_licm3.ll +++ b/polly/test/DeLICM/reduction_looprotate_loopguard_licm3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Reduction over parametric number of elements and a loopguard if the ; reduction loop is not executed at all, such that A[j] is also not accessed. diff --git a/polly/test/DeLICM/reduction_unrelatedunusual.ll b/polly/test/DeLICM/reduction_unrelatedunusual.ll index 04c437770700..00097dfc92e8 100644 --- a/polly/test/DeLICM/reduction_unrelatedunusual.ll +++ b/polly/test/DeLICM/reduction_unrelatedunusual.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-delicm-partial-writes=true -polly-print-delicm -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-delicm-partial-writes=true '-passes=print' -disable-output < %s | FileCheck -match-full-lines %s ; ; Map %add and %phi to A[j]. ; The non-analyzable store to C[0] is unrelated and can be ignored. diff --git a/polly/test/DeLICM/reject_loadafterstore.ll b/polly/test/DeLICM/reject_loadafterstore.ll index 8af6e5e4818c..2a153b5cd710 100644 --- a/polly/test/DeLICM/reject_loadafterstore.ll +++ b/polly/test/DeLICM/reject_loadafterstore.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output -pass-remarks-missed=polly-delicm < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output -pass-remarks-missed=polly-delicm < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/reject_outofquota.ll b/polly/test/DeLICM/reject_outofquota.ll index 551431f0823c..35001ec1ab2d 100644 --- a/polly/test/DeLICM/reject_outofquota.ll +++ b/polly/test/DeLICM/reject_outofquota.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-delicm -pass-remarks-analysis=polly-delicm -polly-delicm-max-ops=1 -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-delicm -polly-print-dependences -polly-delicm-max-ops=1 -polly-dependences-computeout=0 -disable-output < %s | FileCheck %s -check-prefix=DEP +; RUN: opt %loadPolly '-passes=print' -pass-remarks-analysis=polly-delicm -polly-delicm-max-ops=1 -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-delicm,print' -polly-delicm-max-ops=1 -polly-dependences-computeout=0 -disable-output < %s | FileCheck %s -check-prefix=DEP ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/reject_storeafterstore.ll b/polly/test/DeLICM/reject_storeafterstore.ll index 1ec5ef67344c..715375fcdea2 100644 --- a/polly/test/DeLICM/reject_storeafterstore.ll +++ b/polly/test/DeLICM/reject_storeafterstore.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/reject_storeinsubregion.ll b/polly/test/DeLICM/reject_storeinsubregion.ll index 1d38e8066568..6490dc25d4a5 100644 --- a/polly/test/DeLICM/reject_storeinsubregion.ll +++ b/polly/test/DeLICM/reject_storeinsubregion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/reject_unusualstore.ll b/polly/test/DeLICM/reject_unusualstore.ll index a18a0c3ce9c4..22c7d8ca0ea6 100644 --- a/polly/test/DeLICM/reject_unusualstore.ll +++ b/polly/test/DeLICM/reject_unusualstore.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-delicm -disable-output -stats < %s 2>&1 | FileCheck %s --check-prefix=STATS +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -passes=polly-delicm -disable-output -stats < %s 2>&1 | FileCheck %s --check-prefix=STATS ; REQUIRES: asserts ; ; void func(double *A) { diff --git a/polly/test/DeLICM/skip_maywrite.ll b/polly/test/DeLICM/skip_maywrite.ll index 1e5f6b169fe4..4da0ddb9dfd2 100644 --- a/polly/test/DeLICM/skip_maywrite.ll +++ b/polly/test/DeLICM/skip_maywrite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/skip_multiaccess.ll b/polly/test/DeLICM/skip_multiaccess.ll index 6a8c8e5325e1..0eea60d0f488 100644 --- a/polly/test/DeLICM/skip_multiaccess.ll +++ b/polly/test/DeLICM/skip_multiaccess.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; llvm.org/PR34485 ; llvm.org/PR34989 diff --git a/polly/test/DeLICM/skip_notinloop.ll b/polly/test/DeLICM/skip_notinloop.ll index 0730a3a9a4f5..caa70179d666 100644 --- a/polly/test/DeLICM/skip_notinloop.ll +++ b/polly/test/DeLICM/skip_notinloop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; double phi = 0.0; diff --git a/polly/test/DeLICM/skip_scalaraccess.ll b/polly/test/DeLICM/skip_scalaraccess.ll index fa95d382409a..8c9728dc6c42 100644 --- a/polly/test/DeLICM/skip_scalaraccess.ll +++ b/polly/test/DeLICM/skip_scalaraccess.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeadCodeElimination/chained_iterations.ll b/polly/test/DeadCodeElimination/chained_iterations.ll index b79fdd659aae..10be83559f29 100644 --- a/polly/test/DeadCodeElimination/chained_iterations.ll +++ b/polly/test/DeadCodeElimination/chained_iterations.ll @@ -1,5 +1,5 @@ -; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-dependences-analysis-type=value-based '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-dependences-analysis-type=value-based '-passes=polly-dce,print' -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE 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-n8:16:32:64" ; ; for(i = 0; i < 200; i++ ) diff --git a/polly/test/DeadCodeElimination/chained_iterations_2.ll b/polly/test/DeadCodeElimination/chained_iterations_2.ll index 1d1af92db5da..42242c40eac9 100644 --- a/polly/test/DeadCodeElimination/chained_iterations_2.ll +++ b/polly/test/DeadCodeElimination/chained_iterations_2.ll @@ -1,5 +1,5 @@ -; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-dependences-analysis-type=value-based '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-dependences-analysis-type=value-based '-passes=polly-dce,print' -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE 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-n8:16:32:64" ; ; for(i = 0; i < 200; i++ ) diff --git a/polly/test/DeadCodeElimination/computeout.ll b/polly/test/DeadCodeElimination/computeout.ll index 51850d7da349..2ac6b8cbbedf 100644 --- a/polly/test/DeadCodeElimination/computeout.ll +++ b/polly/test/DeadCodeElimination/computeout.ll @@ -1,6 +1,5 @@ -; RUN: opt -S %loadPolly -basic-aa -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt -S %loadNPMPolly "-passes=scop(polly-dce,print)" < %s | FileCheck %s -; RUN: opt -S %loadPolly -basic-aa -polly-dce -polly-print-ast -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT +; RUN: opt -S %loadPolly "-passes=scop(polly-dce,print)" < %s | FileCheck %s +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa "-passes=scop(polly-dce,print)" -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT 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-n8:16:32:64" ; for(i = 0; i < 100; i++ ) diff --git a/polly/test/DeadCodeElimination/dead_iteration_elimination.ll b/polly/test/DeadCodeElimination/dead_iteration_elimination.ll index f496f7828e3d..4247ccbcd123 100644 --- a/polly/test/DeadCodeElimination/dead_iteration_elimination.ll +++ b/polly/test/DeadCodeElimination/dead_iteration_elimination.ll @@ -1,5 +1,4 @@ -; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-dce -polly-dce-precise-steps=2 -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt -S %loadNPMPolly "-passes=scop(polly-dce,print)" -polly-dependences-analysis-type=value-based -polly-dce-precise-steps=2 < %s | FileCheck %s +; RUN: opt -S %loadPolly "-passes=scop(polly-dce,print)" -polly-dependences-analysis-type=value-based -polly-dce-precise-steps=2 < %s | 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-n8:16:32:64" ; ; for(i = 0; i < 200; i++ ) diff --git a/polly/test/DeadCodeElimination/non-affine-affine-mix.ll b/polly/test/DeadCodeElimination/non-affine-affine-mix.ll index e6a5dd204ca1..e290d9997d96 100644 --- a/polly/test/DeadCodeElimination/non-affine-affine-mix.ll +++ b/polly/test/DeadCodeElimination/non-affine-affine-mix.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=polly-dce,print' -disable-output < %s | FileCheck %s ; ; void f(int *A) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/DeadCodeElimination/non-affine.ll b/polly/test/DeadCodeElimination/non-affine.ll index 38a7fcbcf9c9..8f437ef3e32a 100644 --- a/polly/test/DeadCodeElimination/non-affine.ll +++ b/polly/test/DeadCodeElimination/non-affine.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=polly-dce,print' -disable-output < %s | FileCheck %s ; ; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1) ; diff --git a/polly/test/DeadCodeElimination/null_schedule.ll b/polly/test/DeadCodeElimination/null_schedule.ll index 633a84b5d92b..13c8a127b173 100644 --- a/polly/test/DeadCodeElimination/null_schedule.ll +++ b/polly/test/DeadCodeElimination/null_schedule.ll @@ -1,4 +1,4 @@ -; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-dependences-analysis-type=value-based '-passes=polly-dce,print' -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE 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-n8:16:32:64" ; A[0] = 1; ; diff --git a/polly/test/DependenceInfo/computeout.ll b/polly/test/DependenceInfo/computeout.ll index 048de29864d3..0e64cd1a3725 100644 --- a/polly/test/DependenceInfo/computeout.ll +++ b/polly/test/DependenceInfo/computeout.ll @@ -1,7 +1,5 @@ -; RUN: opt -S %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s -check-prefix=VALUE -; RUN: opt -S %loadPolly -polly-print-function-dependences -disable-output < %s | FileCheck %s -check-prefix=FUNC-VALUE -; RUN: opt -S %loadPolly -polly-print-dependences -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT -; RUN: opt -S %loadPolly -polly-print-function-dependences -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT +; RUN: opt -S %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=VALUE +; RUN: opt -S %loadPolly '-passes=print' -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT 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-n8:16:32:64" ; for(i = 0; i < 100; i++ ) diff --git a/polly/test/DependenceInfo/different_schedule_dimensions.ll b/polly/test/DependenceInfo/different_schedule_dimensions.ll index 3f966168d3b7..edb8371d6e68 100644 --- a/polly/test/DependenceInfo/different_schedule_dimensions.ll +++ b/polly/test/DependenceInfo/different_schedule_dimensions.ll @@ -1,7 +1,5 @@ -; RUN: opt -S %loadPolly -polly-print-dependences \ +; RUN: opt -S %loadPolly '-passes=print' \ ; RUN: -disable-output < %s | FileCheck %s -; RUN: opt -S %loadPolly -polly-print-function-dependences \ -; RUN: -disable-output < %s | FileCheck %s -check-prefix=FUNC ; CHECK: RAW dependences: ; CHECK: { Stmt_bb9[0] -> Stmt_bb10[0] } diff --git a/polly/test/DependenceInfo/do_pluto_matmult.ll b/polly/test/DependenceInfo/do_pluto_matmult.ll index d71608e80e70..9532f9c7fb12 100644 --- a/polly/test/DependenceInfo/do_pluto_matmult.ll +++ b/polly/test/DependenceInfo/do_pluto_matmult.ll @@ -1,7 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-dependences -polly-dependences-analysis-type=value-based -disable-output < %s | FileCheck %s -check-prefix=VALUE -; RUN: opt %loadPolly -basic-aa -polly-print-dependences -polly-dependences-analysis-type=memory-based -disable-output < %s | FileCheck %s -check-prefix=MEMORY -; RUN: opt %loadPolly -basic-aa -polly-print-function-dependences -polly-dependences-analysis-type=value-based -disable-output < %s | FileCheck %s -check-prefix=FUNC-VALUE -; RUN: opt %loadPolly -basic-aa -polly-print-function-dependences -polly-dependences-analysis-type=memory-based -disable-output < %s | FileCheck %s -check-prefix=FUNC-MEMORY +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-dependences-analysis-type=value-based -disable-output < %s | FileCheck %s -check-prefix=VALUE +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-dependences-analysis-type=memory-based -disable-output < %s | FileCheck %s -check-prefix=MEMORY 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-n8:16:32:64" diff --git a/polly/test/DependenceInfo/fine_grain_dep_0.ll b/polly/test/DependenceInfo/fine_grain_dep_0.ll index 9c79e360690a..e7fc66882465 100644 --- a/polly/test/DependenceInfo/fine_grain_dep_0.ll +++ b/polly/test/DependenceInfo/fine_grain_dep_0.ll @@ -1,7 +1,6 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-dependences -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s --check-prefix=REF -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-dependences -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s --check-prefix=ACC -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-function-dependences -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s --check-prefix=ACC -; +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s --check-prefix=REF +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s --check-prefix=ACC + ; REF: RAW dependences: ; REF-NEXT: [N] -> { [Stmt_for_body[i0] -> MemRef_b[]] -> [Stmt_for_body[6 + i0] -> MemRef_b[]] : 0 <= i0 <= -13 + N; Stmt_for_body[i0] -> Stmt_for_body[6 + i0] : 0 <= i0 <= -13 + N; Stmt_for_body[i0] -> Stmt_for_body[4 + i0] : 0 <= i0 <= -11 + N; [Stmt_for_body[i0] -> MemRef_a[]] -> [Stmt_for_body[4 + i0] -> MemRef_a[]] : 0 <= i0 <= -11 + N } ; REF-NEXT: WAR dependences: diff --git a/polly/test/DependenceInfo/generate_may_write_dependence_info.ll b/polly/test/DependenceInfo/generate_may_write_dependence_info.ll index 0b7f2d48da9f..7f6f5f3e3b94 100644 --- a/polly/test/DependenceInfo/generate_may_write_dependence_info.ll +++ b/polly/test/DependenceInfo/generate_may_write_dependence_info.ll @@ -1,4 +1,4 @@ -; RUN: opt -S %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s -check-prefix=VALUE +; RUN: opt -S %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=VALUE target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ; for (int i = 0; i < N; i++) { diff --git a/polly/test/DependenceInfo/infeasible_context.ll b/polly/test/DependenceInfo/infeasible_context.ll index d701b821e15c..aab6072e4a45 100644 --- a/polly/test/DependenceInfo/infeasible_context.ll +++ b/polly/test/DependenceInfo/infeasible_context.ll @@ -1,10 +1,9 @@ -; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s -check-prefix=FUNC-SCOP -; RUN: opt %loadPolly -polly-print-function-dependences -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print,scop(print)' -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s -check-prefix=FUNC-DEPS ; ; FUNC-SCOP-NOT: Statement -; FUNC-DEPS-LABEL: Printing analysis 'Polly - Calculate dependences for all the SCoPs of a function' for function 'readgeo' ; FUNC-DEPS-NOT: RAW dependences ; ; Due to an infeasible run-time check, scop object is empty and we do not compute dependences. diff --git a/polly/test/DependenceInfo/may_writes_do_not_block_must_writes_for_war.ll b/polly/test/DependenceInfo/may_writes_do_not_block_must_writes_for_war.ll index 09c516274708..662cb3232e7e 100644 --- a/polly/test/DependenceInfo/may_writes_do_not_block_must_writes_for_war.ll +++ b/polly/test/DependenceInfo/may_writes_do_not_block_must_writes_for_war.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; Verify that the presence of a may-write (S1) between a read (S0) and a ; must-write (S2) does not block the generation of RAW dependences. This makes diff --git a/polly/test/DependenceInfo/nonaffine-condition-buildMemoryAccess.ll b/polly/test/DependenceInfo/nonaffine-condition-buildMemoryAccess.ll index 25c7e3d6e442..d8361a2b74a6 100644 --- a/polly/test/DependenceInfo/nonaffine-condition-buildMemoryAccess.ll +++ b/polly/test/DependenceInfo/nonaffine-condition-buildMemoryAccess.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -polly-allow-nonaffine-loops -polly-allow-nonaffine -debug-only=polly-dependence < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-allow-nonaffine-loops -polly-allow-nonaffine -debug-only=polly-dependence < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/DependenceInfo/reduction_complex_location.ll b/polly/test/DependenceInfo/reduction_complex_location.ll index 7ca839996326..2c14f116c904 100644 --- a/polly/test/DependenceInfo/reduction_complex_location.ll +++ b/polly/test/DependenceInfo/reduction_complex_location.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-dependences -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-dependences -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { } diff --git a/polly/test/DependenceInfo/reduction_dependences_equal_non_reduction_dependences.ll b/polly/test/DependenceInfo/reduction_dependences_equal_non_reduction_dependences.ll index 3632bd202da2..e32217910fc7 100644 --- a/polly/test/DependenceInfo/reduction_dependences_equal_non_reduction_dependences.ll +++ b/polly/test/DependenceInfo/reduction_dependences_equal_non_reduction_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s ; ; This loopnest contains a reduction which imposes the same dependences as the ; accesses to the array A. We need to ensure we keep the dependences of A. diff --git a/polly/test/DependenceInfo/reduction_dependences_not_null.ll b/polly/test/DependenceInfo/reduction_dependences_not_null.ll index 69fd74478ecc..852f03cb6f70 100644 --- a/polly/test/DependenceInfo/reduction_dependences_not_null.ll +++ b/polly/test/DependenceInfo/reduction_dependences_not_null.ll @@ -1,7 +1,7 @@ ; Test that the reduction dependences are always initialised, even in a case ; where we have no reduction. If this object is NULL, then isl operations on ; it will fail. -; RUN: opt -S %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s -check-prefix=VALUE +; RUN: opt -S %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=VALUE 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-n8:16:32:64" ; for(i = 0; i < 100; i++ ) diff --git a/polly/test/DependenceInfo/reduction_mixed_reduction_and_non_reduction_dependences.ll b/polly/test/DependenceInfo/reduction_mixed_reduction_and_non_reduction_dependences.ll index 71903d9e7111..4c78d80b8ceb 100644 --- a/polly/test/DependenceInfo/reduction_mixed_reduction_and_non_reduction_dependences.ll +++ b/polly/test/DependenceInfo/reduction_mixed_reduction_and_non_reduction_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_for_body3[i0, i1] -> Stmt_for_body3[i0 + i1, o1] : i0 >= 0 and 0 <= i1 <= 1023 - i0 and i1 <= 1 and 0 < o1 <= 511 } diff --git a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum.ll b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum.ll index 234de5c367a0..7e05265f6e6d 100644 --- a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum.ll +++ b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum.ll @@ -1,6 +1,6 @@ -; RUN: opt -basic-aa %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s -; RUN: opt -basic-aa %loadPolly -polly-print-dependences -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s -; RUN: opt -basic-aa %loadPolly -polly-print-dependences -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa %loadPolly '-passes=print' -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa %loadPolly '-passes=print' -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s ; ; Verify that only the inner reduction like accesses cause reduction dependences ; diff --git a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_2.ll b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_2.ll index acd674dc0117..7e8a66a50bfd 100644 --- a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_2.ll +++ b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -basic-aa -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { } diff --git a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_3.ll b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_3.ll index bdfcfc99c8cb..adb04f305993 100644 --- a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_3.ll +++ b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -basic-aa -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s ; ; CHECK: Reduction dependences: ; CHECK-NEXT: { Stmt_for_inc[i0, i1] -> Stmt_for_inc[i0, 1 + i1] : 0 <= i0 <= 99 and 0 <= i1 <= 98 } diff --git a/polly/test/DependenceInfo/reduction_multiple_reductions.ll b/polly/test/DependenceInfo/reduction_multiple_reductions.ll index cf705080e03d..2d810915bada 100644 --- a/polly/test/DependenceInfo/reduction_multiple_reductions.ll +++ b/polly/test/DependenceInfo/reduction_multiple_reductions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s ; ; Verify we do not have dependences between the if and the else clause ; diff --git a/polly/test/DependenceInfo/reduction_multiple_reductions_2.ll b/polly/test/DependenceInfo/reduction_multiple_reductions_2.ll index 8d8557a129ab..326dcaee5f07 100644 --- a/polly/test/DependenceInfo/reduction_multiple_reductions_2.ll +++ b/polly/test/DependenceInfo/reduction_multiple_reductions_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s ; ; ; These are the important RAW dependences, as they need to originate/end in only one iteration: diff --git a/polly/test/DependenceInfo/reduction_only_reduction_like_access.ll b/polly/test/DependenceInfo/reduction_only_reduction_like_access.ll index 7b4a68a2a897..1e6455b264d3 100644 --- a/polly/test/DependenceInfo/reduction_only_reduction_like_access.ll +++ b/polly/test/DependenceInfo/reduction_only_reduction_like_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; FIXME: Change the comment once we allow different pointers ; The statement is "almost" reduction like but should not yield any reduction dependences diff --git a/polly/test/DependenceInfo/reduction_partially_escaping_intermediate_in_other_stmt.ll b/polly/test/DependenceInfo/reduction_partially_escaping_intermediate_in_other_stmt.ll index 0d09e5a861a0..158e6a29d8a7 100644 --- a/polly/test/DependenceInfo/reduction_partially_escaping_intermediate_in_other_stmt.ll +++ b/polly/test/DependenceInfo/reduction_partially_escaping_intermediate_in_other_stmt.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -basic-aa -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s ; ; CHECK: Reduction dependences: ; CHECK-NEXT: [N] -> { Stmt_for_body3[i0, i1] -> Stmt_for_body3[i0, 1 + i1] : 0 <= i0 <= 1023 and i1 >= 0 and 1024 - N + i0 <= i1 <= 1022 } diff --git a/polly/test/DependenceInfo/reduction_privatization_deps.ll b/polly/test/DependenceInfo/reduction_privatization_deps.ll index ce90e21a898d..5d62b8f0a10a 100644 --- a/polly/test/DependenceInfo/reduction_privatization_deps.ll +++ b/polly/test/DependenceInfo/reduction_privatization_deps.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_S1[i0, i1] -> Stmt_S2[-1 + i0 + i1] : 0 <= i0 <= 1023 and i1 >= 0 and -i0 < i1 <= 1024 - i0 and i1 <= 1023; Stmt_S0[i0] -> Stmt_S1[o0, i0 - o0] : i0 <= 1023 and 0 <= o0 <= i0 } diff --git a/polly/test/DependenceInfo/reduction_privatization_deps_2.ll b/polly/test/DependenceInfo/reduction_privatization_deps_2.ll index 4904004d4781..ed936bfb3b7f 100644 --- a/polly/test/DependenceInfo/reduction_privatization_deps_2.ll +++ b/polly/test/DependenceInfo/reduction_privatization_deps_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; We have privatization dependences from a textually later statement to a ; textually earlier one, but the dependences still go forward in time. diff --git a/polly/test/DependenceInfo/reduction_privatization_deps_3.ll b/polly/test/DependenceInfo/reduction_privatization_deps_3.ll index a3935ebd6cc4..58ef9a4774b9 100644 --- a/polly/test/DependenceInfo/reduction_privatization_deps_3.ll +++ b/polly/test/DependenceInfo/reduction_privatization_deps_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_S1[i0] -> Stmt_S3[2 + i0] : 0 <= i0 <= 96; Stmt_S2[i0, i1] -> Stmt_S3[o0] : i1 <= 1 - i0 and -i1 < o0 <= 1 and o0 <= 1 + i0 - i1; Stmt_S3[i0] -> Stmt_S2[o0, 1 - i0] : 0 <= i0 <= 1 and i0 < o0 <= 98 } diff --git a/polly/test/DependenceInfo/reduction_privatization_deps_4.ll b/polly/test/DependenceInfo/reduction_privatization_deps_4.ll index 10d726af5145..3dad7b217486 100644 --- a/polly/test/DependenceInfo/reduction_privatization_deps_4.ll +++ b/polly/test/DependenceInfo/reduction_privatization_deps_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0, i0] : 0 <= i0 <= 98; Stmt_S2[i0, i0] -> Stmt_S3[i0] : 0 <= i0 <= 98; Stmt_S3[i0] -> Stmt_S2[o0, i0] : i0 >= 0 and i0 < o0 <= 98; Stmt_S2[i0, i1] -> Stmt_S1[i1] : i0 >= 0 and i0 < i1 <= 98 } diff --git a/polly/test/DependenceInfo/reduction_privatization_deps_5.ll b/polly/test/DependenceInfo/reduction_privatization_deps_5.ll index e8d51181725e..0c445d23a92d 100644 --- a/polly/test/DependenceInfo/reduction_privatization_deps_5.ll +++ b/polly/test/DependenceInfo/reduction_privatization_deps_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_S1[i0, 0] -> Stmt_S2[i0, 0] : 0 <= i0 <= 98; Stmt_S2[i0, 0] -> Stmt_S1[1 + i0, 0] : 0 <= i0 <= 97 } diff --git a/polly/test/DependenceInfo/reduction_sequence.ll b/polly/test/DependenceInfo/reduction_sequence.ll index 4a4688953938..7e1ebd4ab67c 100644 --- a/polly/test/DependenceInfo/reduction_sequence.ll +++ b/polly/test/DependenceInfo/reduction_sequence.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; void manyreductions(long *A) { ; for (long i = 0; i < 1024; i++) diff --git a/polly/test/DependenceInfo/reduction_simple_iv.ll b/polly/test/DependenceInfo/reduction_simple_iv.ll index e3307afae08b..64f6de22b078 100644 --- a/polly/test/DependenceInfo/reduction_simple_iv.ll +++ b/polly/test/DependenceInfo/reduction_simple_iv.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { } diff --git a/polly/test/DependenceInfo/reduction_simple_iv_debug_wrapped_dependences.ll b/polly/test/DependenceInfo/reduction_simple_iv_debug_wrapped_dependences.ll index c7651c39a563..61ee3dbc5b02 100644 --- a/polly/test/DependenceInfo/reduction_simple_iv_debug_wrapped_dependences.ll +++ b/polly/test/DependenceInfo/reduction_simple_iv_debug_wrapped_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -debug-only=polly-dependence -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -debug-only=polly-dependence -disable-output < %s 2>&1 | FileCheck %s ; ; REQUIRES: asserts ; diff --git a/polly/test/DependenceInfo/reduction_simple_privatization_deps_2.ll b/polly/test/DependenceInfo/reduction_simple_privatization_deps_2.ll index b61fd8453a8c..a181d2acb651 100644 --- a/polly/test/DependenceInfo/reduction_simple_privatization_deps_2.ll +++ b/polly/test/DependenceInfo/reduction_simple_privatization_deps_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_S1[i0, i1] -> Stmt_S2[i0] : 0 <= i0 <= 99 and 0 <= i1 <= 99; Stmt_S0[i0] -> Stmt_S1[i0, o1] : 0 <= i0 <= 99 and 0 <= o1 <= 99; Stmt_S2[i0] -> Stmt_S0[1 + i0] : 0 <= i0 <= 98 } diff --git a/polly/test/DependenceInfo/reduction_simple_privatization_deps_w_parameter.ll b/polly/test/DependenceInfo/reduction_simple_privatization_deps_w_parameter.ll index a3a87c70d905..ffa26b5eb76c 100644 --- a/polly/test/DependenceInfo/reduction_simple_privatization_deps_w_parameter.ll +++ b/polly/test/DependenceInfo/reduction_simple_privatization_deps_w_parameter.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: [N] -> { Stmt_S1[i0] -> Stmt_S2[] : N >= 11 and 0 <= i0 <= 1023; Stmt_S0[] -> Stmt_S1[o0] : N >= 11 and 0 <= o0 <= 1023 } diff --git a/polly/test/DependenceInfo/reduction_two_reductions_different_rloops.ll b/polly/test/DependenceInfo/reduction_two_reductions_different_rloops.ll index c90462962ce0..25d117d4cbf9 100644 --- a/polly/test/DependenceInfo/reduction_two_reductions_different_rloops.ll +++ b/polly/test/DependenceInfo/reduction_two_reductions_different_rloops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { } diff --git a/polly/test/DependenceInfo/sequential_loops.ll b/polly/test/DependenceInfo/sequential_loops.ll index 8dfa13cb9db8..14c9a6429c67 100644 --- a/polly/test/DependenceInfo/sequential_loops.ll +++ b/polly/test/DependenceInfo/sequential_loops.ll @@ -1,34 +1,43 @@ -; RUN: opt -S %loadPolly -basic-aa -polly-print-dependences -polly-dependences-analysis-type=value-based -disable-output < %s | FileCheck %s -check-prefix=VALUE -; RUN: opt -S %loadPolly -basic-aa -polly-print-dependences -polly-dependences-analysis-type=memory-based -disable-output < %s | FileCheck %s -check-prefix=MEMORY -; RUN: opt -S %loadPolly -basic-aa -polly-print-dependences -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s -check-prefix=VALUE_ACCESS +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-dependences-analysis-type=value-based -disable-output < %s | FileCheck %s -check-prefix=VALUE +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-dependences-analysis-type=memory-based -disable-output < %s | FileCheck %s -check-prefix=MEMORY +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s -check-prefix=VALUE_ACCESS -; VALUE-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'sequential_writes': -; VALUE-NEXT: RAW dependences: +; VALUE: RAW dependences: ; VALUE-NEXT: { } ; VALUE-NEXT: WAR dependences: ; VALUE-NEXT: { } ; VALUE-NEXT: WAW dependences: ; VALUE-NEXT: { Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99; Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9 } ; -;VALUE_ACCESS-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'sequential_writes': -;VALUE_ACCESS-NEXT: RAW dependences: -;VALUE_ACCESS-NEXT: { } -;VALUE_ACCESS-NEXT: WAR dependences: -;VALUE_ACCESS-NEXT: { } -;VALUE_ACCESS-NEXT: WAW dependences: -;VALUE_ACCESS-NEXT: { Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99; Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; [Stmt_S2[i0] -> Stmt_S2_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Write0[]] : 0 <= i0 <= 9; Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S2[i0] -> Stmt_S2_Write0[]] : 0 <= i0 <= 9; [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Write0[]] : 10 <= i0 <= 99 } - -; -; VALUE-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'read_after_writes': -; VALUE-NEXT: RAW dependences: +; VALUE: RAW dependences: ; VALUE-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99 } ; VALUE-NEXT: WAR dependences: ; VALUE-NEXT: { } ; VALUE-NEXT: WAW dependences: ; VALUE-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9 } ; -;VALUE_ACCESS-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'read_after_writes': -;VALUE_ACCESS-NEXT: RAW dependences: +; VALUE: RAW dependences: +; VALUE-NEXT: { } +; VALUE-NEXT: WAR dependences: +; VALUE-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99 } +; VALUE-NEXT: WAW dependences: +; VALUE-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9 } +; +; VALUE: RAW dependences: +; VALUE-NEXT: [p] -> { Stmt_S1[i0] -> Stmt_S2[-p + i0] : i0 >= p and 0 <= i0 <= 99 and i0 <= 9 + p } +; VALUE-NEXT: WAR dependences: +; VALUE-NEXT: [p] -> { } +; VALUE-NEXT: WAW dependences: +; VALUE-NEXT: [p] -> { } +; +;VALUE_ACCESS: RAW dependences: +;VALUE_ACCESS-NEXT: { } +;VALUE_ACCESS-NEXT: WAR dependences: +;VALUE_ACCESS-NEXT: { } +;VALUE_ACCESS-NEXT: WAW dependences: +;VALUE_ACCESS-NEXT: { Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99; Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; [Stmt_S2[i0] -> Stmt_S2_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Write0[]] : 0 <= i0 <= 9; Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S2[i0] -> Stmt_S2_Write0[]] : 0 <= i0 <= 9; [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Write0[]] : 10 <= i0 <= 99 } +; +;VALUE_ACCESS: RAW dependences: ;VALUE_ACCESS-NEXT: { Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99; Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; [Stmt_S2[i0] -> Stmt_S2_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Read0[]] : 0 <= i0 <= 9; [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Read0[]] : 10 <= i0 <= 99 } ;VALUE_ACCESS-NEXT: WAR dependences: @@ -36,64 +45,42 @@ ;VALUE_ACCESS-NEXT: WAW dependences: ;VALUE_ACCESS-NEXT: { [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S2[i0] -> Stmt_S2_Write0[]] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9 } ; -; VALUE-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'write_after_read': -; VALUE-NEXT: RAW dependences: -; VALUE-NEXT: { } -; VALUE-NEXT: WAR dependences: -; VALUE-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99 } -; VALUE-NEXT: WAW dependences: -; VALUE-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9 } -; -;VALUE_ACCESS-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'write_after_read': -;VALUE_ACCESS-NEXT: RAW dependences: +;VALUE_ACCESS: RAW dependences: ;VALUE_ACCESS-NEXT: { } ;VALUE_ACCESS-NEXT: WAR dependences: ;VALUE_ACCESS-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99; [Stmt_S1[i0] -> Stmt_S1_Read0[]] -> [Stmt_S2[i0] -> Stmt_S2_Write0[]] : 0 <= i0 <= 9; [Stmt_S1[i0] -> Stmt_S1_Read0[]] -> [Stmt_S3[i0] -> Stmt_S3_Write0[]] : 10 <= i0 <= 99 } ;VALUE_ACCESS-NEXT: WAW dependences: ;VALUE_ACCESS-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; [Stmt_S2[i0] -> Stmt_S2_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Write0[]] : 0 <= i0 <= 9 } ; -; VALUE-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.2' in function 'parametric_offset': -; VALUE-NEXT: RAW dependences: -; VALUE-NEXT: [p] -> { Stmt_S1[i0] -> Stmt_S2[-p + i0] : i0 >= p and 0 <= i0 <= 99 and i0 <= 9 + p } -; VALUE-NEXT: WAR dependences: -; VALUE-NEXT: [p] -> { } -; VALUE-NEXT: WAW dependences: -; VALUE-NEXT: [p] -> { } -; -;VALUE_ACCESS-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.2' in function 'parametric_offset': -;VALUE_ACCESS-NEXT: RAW dependences: +;VALUE_ACCESS: RAW dependences: ;VALUE_ACCESS-NEXT: [p] -> { Stmt_S1[i0] -> Stmt_S2[-p + i0] : i0 >= p and 0 <= i0 <= 99 and i0 <= 9 + p; [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S2[-p + i0] -> Stmt_S2_Read0[]] : i0 >= p and 0 <= i0 <= 99 and i0 <= 9 + p } ;VALUE_ACCESS-NEXT: WAR dependences: ;VALUE_ACCESS-NEXT: [p] -> { } ;VALUE_ACCESS-NEXT: WAW dependences: ;VALUE_ACCESS-NEXT: [p] -> { } -; MEMORY-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'sequential_writes': -; MEMORY-NEXT: RAW dependences: +; MEMORY: RAW dependences: ; MEMORY-NEXT: { } ; MEMORY-NEXT: WAR dependences: ; MEMORY-NEXT: { } ; MEMORY-NEXT: WAW dependences: ; MEMORY-NEXT: { Stmt_S1[i0] -> Stmt_S3[i0] : 0 <= i0 <= 99; Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9 } ; -; MEMORY-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'read_after_writes': -; MEMORY-NEXT: RAW dependences: +; MEMORY: RAW dependences: ; MEMORY-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 0 <= i0 <= 99 } ; MEMORY-NEXT: WAR dependences: ; MEMORY-NEXT: { } ; MEMORY-NEXT: WAW dependences: ; MEMORY-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9 } ; -; MEMORY-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'write_after_read': -; MEMORY-NEXT: RAW dependences: +; MEMORY: RAW dependences: ; MEMORY-NEXT: { } ; MEMORY-NEXT: WAR dependences: ; MEMORY-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 0 <= i0 <= 99 } ; MEMORY-NEXT: WAW dependences: ; MEMORY-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9 } ; -; MEMORY-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.2' in function 'parametric_offset': -; MEMORY-NEXT: RAW dependences: +; MEMORY: RAW dependences: ; MEMORY-NEXT: [p] -> { Stmt_S1[i0] -> Stmt_S2[-p + i0] : i0 >= p and 0 <= i0 <= 99 and i0 <= 9 + p } ; MEMORY-NEXT: WAR dependences: ; MEMORY-NEXT: [p] -> { } diff --git a/polly/test/ForwardOpTree/atax.ll b/polly/test/ForwardOpTree/atax.ll index 0690c1b000fa..7cc40fe7e1cb 100644 --- a/polly/test/ForwardOpTree/atax.ll +++ b/polly/test/ForwardOpTree/atax.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-optree-normalize-phi=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-optree-normalize-phi=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ForwardOpTree/changed-kind.ll b/polly/test/ForwardOpTree/changed-kind.ll index a1d59825b3b2..3c3d7f738779 100644 --- a/polly/test/ForwardOpTree/changed-kind.ll +++ b/polly/test/ForwardOpTree/changed-kind.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; In the code below, %0 is known to be equal to the content of @c (constant 0). ; Thus, in order to save a scalar dependency, forward-optree replaces diff --git a/polly/test/ForwardOpTree/forward_from_region.ll b/polly/test/ForwardOpTree/forward_from_region.ll index 53d22800081e..90448d800286 100644 --- a/polly/test/ForwardOpTree/forward_from_region.ll +++ b/polly/test/ForwardOpTree/forward_from_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Move instructions from region statements. ; diff --git a/polly/test/ForwardOpTree/forward_hoisted.ll b/polly/test/ForwardOpTree/forward_hoisted.ll index 32fca00141dd..163d43f56e8a 100644 --- a/polly/test/ForwardOpTree/forward_hoisted.ll +++ b/polly/test/ForwardOpTree/forward_hoisted.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Move %val to %bodyB, so %bodyA can be removed (by -polly-simplify). ; This involves making the load-hoisted %val1 to be made available in %bodyB. diff --git a/polly/test/ForwardOpTree/forward_instruction.ll b/polly/test/ForwardOpTree/forward_instruction.ll index 1dcd64357324..6269e359a59a 100644 --- a/polly/test/ForwardOpTree/forward_instruction.ll +++ b/polly/test/ForwardOpTree/forward_instruction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Move %val to %bodyB, so %bodyA can be removed (by -polly-simplify) ; diff --git a/polly/test/ForwardOpTree/forward_into_region.ll b/polly/test/ForwardOpTree/forward_into_region.ll index dd18cfe5e61a..be102a9574dc 100644 --- a/polly/test/ForwardOpTree/forward_into_region.ll +++ b/polly/test/ForwardOpTree/forward_into_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Move instructions to region statements. ; diff --git a/polly/test/ForwardOpTree/forward_into_region_redundant_use.ll b/polly/test/ForwardOpTree/forward_into_region_redundant_use.ll index e5458c027880..883a784230d9 100644 --- a/polly/test/ForwardOpTree/forward_into_region_redundant_use.ll +++ b/polly/test/ForwardOpTree/forward_into_region_redundant_use.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; define void @foo(ptr %A, i32 %p, ptr %B) { diff --git a/polly/test/ForwardOpTree/forward_load.ll b/polly/test/ForwardOpTree/forward_load.ll index 86e3cb0203fa..dec6812aade5 100644 --- a/polly/test/ForwardOpTree/forward_load.ll +++ b/polly/test/ForwardOpTree/forward_load.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load. ; diff --git a/polly/test/ForwardOpTree/forward_load_differentarray.ll b/polly/test/ForwardOpTree/forward_load_differentarray.ll index 786277bdeb87..a3ca0bad54ab 100644 --- a/polly/test/ForwardOpTree/forward_load_differentarray.ll +++ b/polly/test/ForwardOpTree/forward_load_differentarray.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; To forward %val, B[j] cannot be reused in bodyC because it is overwritten ; between. Verify that instead the alternative C[j] is used. diff --git a/polly/test/ForwardOpTree/forward_load_double_write.ll b/polly/test/ForwardOpTree/forward_load_double_write.ll index 1618722381fc..b0fbb69dc7ae 100644 --- a/polly/test/ForwardOpTree/forward_load_double_write.ll +++ b/polly/test/ForwardOpTree/forward_load_double_write.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load even in case two writes of identical values are in ; one scop statement. diff --git a/polly/test/ForwardOpTree/forward_load_fromloop.ll b/polly/test/ForwardOpTree/forward_load_fromloop.ll index 8f08a1356c38..62351883a189 100644 --- a/polly/test/ForwardOpTree/forward_load_fromloop.ll +++ b/polly/test/ForwardOpTree/forward_load_fromloop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Forward a the LoadInst %val into %bodyB. %val is executed multiple times, ; we must get the last loaded values. diff --git a/polly/test/ForwardOpTree/forward_load_indirect.ll b/polly/test/ForwardOpTree/forward_load_indirect.ll index f83af61e6741..c8144861abc4 100644 --- a/polly/test/ForwardOpTree/forward_load_indirect.ll +++ b/polly/test/ForwardOpTree/forward_load_indirect.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Forward an operand tree consisting of a speculatable instruction (%add) ; and a load (%val). diff --git a/polly/test/ForwardOpTree/forward_load_memset_after.ll b/polly/test/ForwardOpTree/forward_load_memset_after.ll index 13797a44c862..22a2ddf94888 100644 --- a/polly/test/ForwardOpTree/forward_load_memset_after.ll +++ b/polly/test/ForwardOpTree/forward_load_memset_after.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load in the presence of a non-store WRITE access. ; diff --git a/polly/test/ForwardOpTree/forward_load_memset_before.ll b/polly/test/ForwardOpTree/forward_load_memset_before.ll index 60b1e076b980..3d3c90e941d6 100644 --- a/polly/test/ForwardOpTree/forward_load_memset_before.ll +++ b/polly/test/ForwardOpTree/forward_load_memset_before.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load in the presence of a non-store WRITE access. ; diff --git a/polly/test/ForwardOpTree/forward_load_tripleuse.ll b/polly/test/ForwardOpTree/forward_load_tripleuse.ll index 1d0df2a22e87..03a47360c362 100644 --- a/polly/test/ForwardOpTree/forward_load_tripleuse.ll +++ b/polly/test/ForwardOpTree/forward_load_tripleuse.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-optree -polly-codegen -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print,polly-codegen' -disable-output < %s | FileCheck %s -match-full-lines ; ; %val1 is used three times: Twice by its own operand tree of %val2 and once ; more by the store in %bodyB. diff --git a/polly/test/ForwardOpTree/forward_load_unrelatedunusual.ll b/polly/test/ForwardOpTree/forward_load_unrelatedunusual.ll index b7bae5628986..dbeebbc27eba 100644 --- a/polly/test/ForwardOpTree/forward_load_unrelatedunusual.ll +++ b/polly/test/ForwardOpTree/forward_load_unrelatedunusual.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load. ; The non-analyzable store to C[0] is unrelated and can be ignored. diff --git a/polly/test/ForwardOpTree/forward_phi_load.ll b/polly/test/ForwardOpTree/forward_phi_load.ll index 0b0bb209a3ef..029261f269c3 100644 --- a/polly/test/ForwardOpTree/forward_phi_load.ll +++ b/polly/test/ForwardOpTree/forward_phi_load.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-optree-normalize-phi=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-optree-normalize-phi=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load. ; diff --git a/polly/test/ForwardOpTree/forward_readonly.ll b/polly/test/ForwardOpTree/forward_readonly.ll index a29c5bff5d70..7ded946a6ff8 100644 --- a/polly/test/ForwardOpTree/forward_readonly.ll +++ b/polly/test/ForwardOpTree/forward_readonly.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-analyze-read-only-scalars=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines -check-prefixes=STATS,MODEL -; RUN: opt %loadPolly -polly-analyze-read-only-scalars=false -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines -check-prefixes=STATS,NOMODEL +; RUN: opt %loadPolly -polly-analyze-read-only-scalars=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines -check-prefixes=STATS,MODEL +; RUN: opt %loadPolly -polly-analyze-read-only-scalars=false '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines -check-prefixes=STATS,NOMODEL ; ; Move %val to %bodyB, so %bodyA can be removed (by -polly-simplify) ; diff --git a/polly/test/ForwardOpTree/forward_reusue.ll b/polly/test/ForwardOpTree/forward_reusue.ll index ead8c7379803..1151aa94e1f9 100644 --- a/polly/test/ForwardOpTree/forward_reusue.ll +++ b/polly/test/ForwardOpTree/forward_reusue.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Move operand tree without duplicating values used multiple times. ; diff --git a/polly/test/ForwardOpTree/forward_store.ll b/polly/test/ForwardOpTree/forward_store.ll index a6369eb303c1..e02c6891f436 100644 --- a/polly/test/ForwardOpTree/forward_store.ll +++ b/polly/test/ForwardOpTree/forward_store.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load. ; diff --git a/polly/test/ForwardOpTree/forward_synthesizable_definloop.ll b/polly/test/ForwardOpTree/forward_synthesizable_definloop.ll index f0da9320c43f..90e489ad6f54 100644 --- a/polly/test/ForwardOpTree/forward_synthesizable_definloop.ll +++ b/polly/test/ForwardOpTree/forward_synthesizable_definloop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Copy %val to bodyB, assuming the exit value of %i. ; diff --git a/polly/test/ForwardOpTree/forward_synthesizable_indvar.ll b/polly/test/ForwardOpTree/forward_synthesizable_indvar.ll index a38ab543e255..395e68482657 100644 --- a/polly/test/ForwardOpTree/forward_synthesizable_indvar.ll +++ b/polly/test/ForwardOpTree/forward_synthesizable_indvar.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Test support for (synthesizable) inducation variables. ; diff --git a/polly/test/ForwardOpTree/forward_synthesizable_useinloop.ll b/polly/test/ForwardOpTree/forward_synthesizable_useinloop.ll index bb1760ae0ffb..a45d420e5c20 100644 --- a/polly/test/ForwardOpTree/forward_synthesizable_useinloop.ll +++ b/polly/test/ForwardOpTree/forward_synthesizable_useinloop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Synthesizable values defined outside of a loop can be used ; inside the loop. diff --git a/polly/test/ForwardOpTree/forward_transitive.ll b/polly/test/ForwardOpTree/forward_transitive.ll index 243889437149..69cfb555f315 100644 --- a/polly/test/ForwardOpTree/forward_transitive.ll +++ b/polly/test/ForwardOpTree/forward_transitive.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Move %v and %val to %bodyB, so %bodyA can be removed (by -polly-simplify) ; diff --git a/polly/test/ForwardOpTree/jacobi-1d.ll b/polly/test/ForwardOpTree/jacobi-1d.ll index 05ccd998c1a2..dbc051dde425 100644 --- a/polly/test/ForwardOpTree/jacobi-1d.ll +++ b/polly/test/ForwardOpTree/jacobi-1d.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-optree-normalize-phi=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-optree-normalize-phi=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ForwardOpTree/noforward_from_region.ll b/polly/test/ForwardOpTree/noforward_from_region.ll index 30150912f32e..11d4312ad3bc 100644 --- a/polly/test/ForwardOpTree/noforward_from_region.ll +++ b/polly/test/ForwardOpTree/noforward_from_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Ensure we do not move instructions from region statements in case the ; instruction to move loads from an array which is also written to from diff --git a/polly/test/ForwardOpTree/noforward_load_conditional.ll b/polly/test/ForwardOpTree/noforward_load_conditional.ll index eaa0fc52186b..053134196001 100644 --- a/polly/test/ForwardOpTree/noforward_load_conditional.ll +++ b/polly/test/ForwardOpTree/noforward_load_conditional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; B[j] is overwritten by at least one statement between the ; definition of %val and its use. Hence, it cannot be forwarded. diff --git a/polly/test/ForwardOpTree/noforward_load_writebetween.ll b/polly/test/ForwardOpTree/noforward_load_writebetween.ll index e2272c1c1f13..4a281b66c618 100644 --- a/polly/test/ForwardOpTree/noforward_load_writebetween.ll +++ b/polly/test/ForwardOpTree/noforward_load_writebetween.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Cannot rematerialize %val from B[0] at bodyC because B[0] has been ; overwritten in bodyB. diff --git a/polly/test/ForwardOpTree/noforward_outofquota.ll b/polly/test/ForwardOpTree/noforward_outofquota.ll index 2ec965d71184..9c17349fb9e2 100644 --- a/polly/test/ForwardOpTree/noforward_outofquota.ll +++ b/polly/test/ForwardOpTree/noforward_outofquota.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-optree-max-ops=1 -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadPolly -polly-optree-max-ops=1 -polly-optree -disable-output -stats < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=STATS +; RUN: opt %loadPolly -polly-optree-max-ops=1 '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-optree-max-ops=1 -passes=polly-optree -disable-output -stats < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=STATS ; REQUIRES: asserts ; ; for (int j = 0; j < n; j += 1) { diff --git a/polly/test/ForwardOpTree/noforward_partial.ll b/polly/test/ForwardOpTree/noforward_partial.ll index 127ac9ff5f14..67bda40337e0 100644 --- a/polly/test/ForwardOpTree/noforward_partial.ll +++ b/polly/test/ForwardOpTree/noforward_partial.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Not the entire operand tree can be forwarded, ; some scalar dependencies would remain. diff --git a/polly/test/ForwardOpTree/noforward_phi.ll b/polly/test/ForwardOpTree/noforward_phi.ll index 58d41a410d3b..455edfd1a831 100644 --- a/polly/test/ForwardOpTree/noforward_phi.ll +++ b/polly/test/ForwardOpTree/noforward_phi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Do not move PHI nodes. ; diff --git a/polly/test/ForwardOpTree/noforward_selfrefphi.ll b/polly/test/ForwardOpTree/noforward_selfrefphi.ll index b2d4dc51c978..e7ab21b6ba28 100644 --- a/polly/test/ForwardOpTree/noforward_selfrefphi.ll +++ b/polly/test/ForwardOpTree/noforward_selfrefphi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-optree-normalize-phi=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-optree-normalize-phi=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Contains a self-referencing PHINode that would require a ; transitive closure to handle. diff --git a/polly/test/ForwardOpTree/noforward_sideffects.ll b/polly/test/ForwardOpTree/noforward_sideffects.ll index a5633769f670..0298da90e4ac 100644 --- a/polly/test/ForwardOpTree/noforward_sideffects.ll +++ b/polly/test/ForwardOpTree/noforward_sideffects.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Do not forward instructions with side-effects (here: function call). ; diff --git a/polly/test/ForwardOpTree/noforward_synthesizable_unknownit.ll b/polly/test/ForwardOpTree/noforward_synthesizable_unknownit.ll index f589fde6e415..159972345bdc 100644 --- a/polly/test/ForwardOpTree/noforward_synthesizable_unknownit.ll +++ b/polly/test/ForwardOpTree/noforward_synthesizable_unknownit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Do not try to forward %i.trunc, it is not synthesizable in %body. ; diff --git a/polly/test/ForwardOpTree/out-of-quota1.ll b/polly/test/ForwardOpTree/out-of-quota1.ll index 7afdb8e60244..5a69f6c3ad60 100644 --- a/polly/test/ForwardOpTree/out-of-quota1.ll +++ b/polly/test/ForwardOpTree/out-of-quota1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-optree -disable-output %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output %s | FileCheck %s ; This used to loop infinitely because of UINT_MAX returned by ISL on out-of-quota. diff --git a/polly/test/IstAstInfo/alias_checks_with_empty_context.ll b/polly/test/IstAstInfo/alias_checks_with_empty_context.ll index 9b95cd5b4bbd..d64f7529135e 100644 --- a/polly/test/IstAstInfo/alias_checks_with_empty_context.ll +++ b/polly/test/IstAstInfo/alias_checks_with_empty_context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s \ ; RUN: | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/IstAstInfo/alias_simple_1.ll b/polly/test/IstAstInfo/alias_simple_1.ll index 83d470c2d19b..659c17879ed5 100644 --- a/polly/test/IstAstInfo/alias_simple_1.ll +++ b/polly/test/IstAstInfo/alias_simple_1.ll @@ -1,8 +1,8 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -disable-output < %s | FileCheck %s --check-prefix=NOAA -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=BASI -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB +; RUN: opt %loadPolly '-passes=print' -aa-pipeline= -disable-output < %s | FileCheck %s --check-prefix=NOAA +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s --check-prefix=BASI +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB ; ; int A[1024]; ; diff --git a/polly/test/IstAstInfo/alias_simple_2.ll b/polly/test/IstAstInfo/alias_simple_2.ll index bbf528f93b47..569fe45e1e02 100644 --- a/polly/test/IstAstInfo/alias_simple_2.ll +++ b/polly/test/IstAstInfo/alias_simple_2.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -disable-output < %s | FileCheck %s --check-prefix=NOAA -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=BASI -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -globals-aa -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE +; RUN: opt %loadPolly '-passes=print' -aa-pipeline= -disable-output < %s | FileCheck %s --check-prefix=NOAA +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s --check-prefix=BASI +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=globals-aa -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE ; ; int A[1024], B[1024]; ; diff --git a/polly/test/IstAstInfo/alias_simple_3.ll b/polly/test/IstAstInfo/alias_simple_3.ll index 9067521323ab..8bad170eda79 100644 --- a/polly/test/IstAstInfo/alias_simple_3.ll +++ b/polly/test/IstAstInfo/alias_simple_3.ll @@ -1,8 +1,8 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -disable-output < %s | FileCheck %s --check-prefix=NOAA -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=BASI -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV -; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB +; RUN: opt %loadPolly '-passes=print' -aa-pipeline= -disable-output < %s | FileCheck %s --check-prefix=NOAA +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s --check-prefix=BASI +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB ; ; int A[1024]; ; float B[1024]; diff --git a/polly/test/IstAstInfo/aliasing_arrays_with_identical_base.ll b/polly/test/IstAstInfo/aliasing_arrays_with_identical_base.ll index 0cabd20168ba..2bf71fb8fd2c 100644 --- a/polly/test/IstAstInfo/aliasing_arrays_with_identical_base.ll +++ b/polly/test/IstAstInfo/aliasing_arrays_with_identical_base.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/IstAstInfo/aliasing_multiple_alias_groups.ll b/polly/test/IstAstInfo/aliasing_multiple_alias_groups.ll index b824c211fd31..6cdc5b0fdcec 100644 --- a/polly/test/IstAstInfo/aliasing_multiple_alias_groups.ll +++ b/polly/test/IstAstInfo/aliasing_multiple_alias_groups.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=NOAA -; RUN: opt %loadPolly -polly-print-ast -tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA +; RUN: opt %loadPolly '-passes=print' -aa-pipeline= -disable-output < %s | FileCheck %s --check-prefix=NOAA +; RUN: opt %loadPolly '-passes=print' -aa-pipeline=tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA ; ; void jd(int *Int0, int *Int1, float *Float0, float *Float1) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/IstAstInfo/aliasing_parametric_simple_1.ll b/polly/test/IstAstInfo/aliasing_parametric_simple_1.ll index e0c3255dd766..a63854d94b68 100644 --- a/polly/test/IstAstInfo/aliasing_parametric_simple_1.ll +++ b/polly/test/IstAstInfo/aliasing_parametric_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output %s | FileCheck %s ; ; void jd(int *A, int *B, int c) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/IstAstInfo/aliasing_parametric_simple_2.ll b/polly/test/IstAstInfo/aliasing_parametric_simple_2.ll index 74bad6c75784..7b2d163d54a2 100644 --- a/polly/test/IstAstInfo/aliasing_parametric_simple_2.ll +++ b/polly/test/IstAstInfo/aliasing_parametric_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; ; void jd(int *A, int *B, int c) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/IstAstInfo/dependence_distance_minimal.ll b/polly/test/IstAstInfo/dependence_distance_minimal.ll index c6b1d156e55d..4a77123e5031 100644 --- a/polly/test/IstAstInfo/dependence_distance_minimal.ll +++ b/polly/test/IstAstInfo/dependence_distance_minimal.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; The minimal dependence distance of the innermost loop should be 1 instead of 250. ; CHECK: #pragma minimal dependence distance: 1 diff --git a/polly/test/IstAstInfo/domain_bounded_only_with_context.ll b/polly/test/IstAstInfo/domain_bounded_only_with_context.ll index 32cebd7a3a8b..bcf6fd394209 100644 --- a/polly/test/IstAstInfo/domain_bounded_only_with_context.ll +++ b/polly/test/IstAstInfo/domain_bounded_only_with_context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; CHECK: { ; CHECK-NEXT: if (p <= -1 || p >= 1) diff --git a/polly/test/IstAstInfo/non_affine_access.ll b/polly/test/IstAstInfo/non_affine_access.ll index d8757b2e21cf..b3f669ee4670 100644 --- a/polly/test/IstAstInfo/non_affine_access.ll +++ b/polly/test/IstAstInfo/non_affine_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-ast-print-accesses -polly-allow-nonaffine -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-ast-print-accesses -polly-allow-nonaffine -disable-output < %s | FileCheck %s ; ; void non_affine_access(float A[]) { ; for (long i = 0; i < 1024; i++) diff --git a/polly/test/IstAstInfo/reduction_clauses_onedimensional_access.ll b/polly/test/IstAstInfo/reduction_clauses_onedimensional_access.ll index 8d52e345a76d..ea47e63bb7a6 100644 --- a/polly/test/IstAstInfo/reduction_clauses_onedimensional_access.ll +++ b/polly/test/IstAstInfo/reduction_clauses_onedimensional_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: #pragma known-parallel reduction (^ : MemRef_sum) ; void f(int N, int M, int *sum) { diff --git a/polly/test/IstAstInfo/reduction_dependences_equal_non_reduction_dependences.ll b/polly/test/IstAstInfo/reduction_dependences_equal_non_reduction_dependences.ll index 9c6eea6aaa1e..6650fc034f87 100644 --- a/polly/test/IstAstInfo/reduction_dependences_equal_non_reduction_dependences.ll +++ b/polly/test/IstAstInfo/reduction_dependences_equal_non_reduction_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; This loopnest contains a reduction which imposes the same dependences as the ; accesses to the array A. We need to ensure we do __not__ parallelize anything diff --git a/polly/test/IstAstInfo/reduction_different_reduction_clauses.ll b/polly/test/IstAstInfo/reduction_different_reduction_clauses.ll index 5104f716d810..d89953cdd2fb 100644 --- a/polly/test/IstAstInfo/reduction_different_reduction_clauses.ll +++ b/polly/test/IstAstInfo/reduction_different_reduction_clauses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: #pragma simd reduction (+ : MemRef_sum{{[1,2]}}, MemRef_sum{{[1,2]}}) reduction (* : MemRef_prod) reduction (| : MemRef_or) reduction (& : MemRef_and) ; CHECK: #pragma known-parallel reduction (+ : MemRef_sum{{[1,2]}}, MemRef_sum{{[1,2]}}) reduction (* : MemRef_prod) reduction (| : MemRef_or) reduction (& : MemRef_and) diff --git a/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule.ll b/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule.ll index 8a42cf8bd165..a8ce13b4c56d 100644 --- a/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule.ll +++ b/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: #pragma known-parallel reduction (+ : MemRef_A) ; CHECK-NEXT: for (int c0 = 0; c0 <= 2; c0 += 1) { diff --git a/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule_2.ll b/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule_2.ll index 8f5efd165546..535ec397969d 100644 --- a/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule_2.ll +++ b/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: #pragma known-parallel reduction ; CHECK: for (int c0 = 0; c0 <= 2; c0 += 1) { diff --git a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions.ll b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions.ll index a711a36a367f..0ea3916fb274 100644 --- a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions.ll +++ b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: #pragma known-parallel ; CHECK: for (int c0 = 0; c0 <= 1; c0 += 1) diff --git a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_2.ll b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_2.ll index 485d6965b6d3..703b0f3e04ea 100644 --- a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_2.ll +++ b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; Verify that the outer dimension doesnt't carry reduction dependences ; diff --git a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_3.ll b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_3.ll index 375fabbf6a8b..3a847e939b5b 100644 --- a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_3.ll +++ b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; Verify that the outer dimension doesnt't carry reduction dependences ; diff --git a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_4.ll b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_4.ll index 584c076dcff4..f2691bc6a503 100644 --- a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_4.ll +++ b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; Verify that the outer dimension doesnt't carry reduction dependences ; diff --git a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_5.ll b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_5.ll index eaa3444a04d7..480af5505a33 100644 --- a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_5.ll +++ b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; Verify that only the outer dimension needs privatization ; diff --git a/polly/test/IstAstInfo/reduction_multiple_dimensions.ll b/polly/test/IstAstInfo/reduction_multiple_dimensions.ll index 9618ec872c38..96ecb0c078fe 100644 --- a/polly/test/IstAstInfo/reduction_multiple_dimensions.ll +++ b/polly/test/IstAstInfo/reduction_multiple_dimensions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK-NOT:#pragma known-parallel reduction ; CHECK: #pragma known-parallel diff --git a/polly/test/IstAstInfo/reduction_multiple_dimensions_2.ll b/polly/test/IstAstInfo/reduction_multiple_dimensions_2.ll index af317570eb37..d2232ca88143 100644 --- a/polly/test/IstAstInfo/reduction_multiple_dimensions_2.ll +++ b/polly/test/IstAstInfo/reduction_multiple_dimensions_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK-NOT:#pragma known-parallel reduction ; CHECK: #pragma known-parallel diff --git a/polly/test/IstAstInfo/reduction_multiple_dimensions_3.ll b/polly/test/IstAstInfo/reduction_multiple_dimensions_3.ll index 1f7191433bf8..dfc1682bd95b 100644 --- a/polly/test/IstAstInfo/reduction_multiple_dimensions_3.ll +++ b/polly/test/IstAstInfo/reduction_multiple_dimensions_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK-NOT:#pragma known-parallel reduction ; CHECK: #pragma known-parallel diff --git a/polly/test/IstAstInfo/reduction_multiple_dimensions_4.ll b/polly/test/IstAstInfo/reduction_multiple_dimensions_4.ll index 40bae5e9ac6c..d0bad81efb2f 100644 --- a/polly/test/IstAstInfo/reduction_multiple_dimensions_4.ll +++ b/polly/test/IstAstInfo/reduction_multiple_dimensions_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK-NOT:#pragma known-parallel reduction ; CHECK: #pragma known-parallel diff --git a/polly/test/IstAstInfo/run-time-condition.ll b/polly/test/IstAstInfo/run-time-condition.ll index ccc9c7cfd321..c3ea8c460b6d 100644 --- a/polly/test/IstAstInfo/run-time-condition.ll +++ b/polly/test/IstAstInfo/run-time-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s ; for (i = 0; i < 1024; i++) ; A[i] = B[i]; diff --git a/polly/test/IstAstInfo/runtime_context_with_error_blocks.ll b/polly/test/IstAstInfo/runtime_context_with_error_blocks.ll index 2853e0acf9b8..26a242b00ee7 100644 --- a/polly/test/IstAstInfo/runtime_context_with_error_blocks.ll +++ b/polly/test/IstAstInfo/runtime_context_with_error_blocks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; Verify we do not simplify the runtime check to "true" due to the domain ; constraints as the test contains an error block that influenced the domains diff --git a/polly/test/IstAstInfo/simple-run-time-condition.ll b/polly/test/IstAstInfo/simple-run-time-condition.ll index 5fb99f0676b7..c6a6f027652f 100644 --- a/polly/test/IstAstInfo/simple-run-time-condition.ll +++ b/polly/test/IstAstInfo/simple-run-time-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-precise-inbounds -polly-precise-fold-accesses -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-precise-inbounds -polly-precise-fold-accesses -disable-output < %s | 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-n8:16:32:64-S128" diff --git a/polly/test/IstAstInfo/single_loop_strip_mine.ll b/polly/test/IstAstInfo/single_loop_strip_mine.ll index 1c627f817b0b..4405ee1dc138 100644 --- a/polly/test/IstAstInfo/single_loop_strip_mine.ll +++ b/polly/test/IstAstInfo/single_loop_strip_mine.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -basic-aa -polly-import-jscop -polly-ast-print-accesses -polly-ast-detect-parallel -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=CHECK-VECTOR +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-ast-print-accesses -polly-ast-detect-parallel '-passes=polly-import-jscop,print' -disable-output < %s | FileCheck %s -check-prefix=CHECK-VECTOR ; for (i = 0; i < 1024; i++) ; A[i] = B[i]; diff --git a/polly/test/IstAstInfo/single_loop_uint_max_iterations.ll b/polly/test/IstAstInfo/single_loop_uint_max_iterations.ll index f1cd5dae11ce..3f673584a268 100644 --- a/polly/test/IstAstInfo/single_loop_uint_max_iterations.ll +++ b/polly/test/IstAstInfo/single_loop_uint_max_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; XFAIL: * ;#include "limits.h" diff --git a/polly/test/IstAstInfo/single_loop_ull_max_iterations.ll b/polly/test/IstAstInfo/single_loop_ull_max_iterations.ll index d421e221240a..ff56cfb11780 100644 --- a/polly/test/IstAstInfo/single_loop_ull_max_iterations.ll +++ b/polly/test/IstAstInfo/single_loop_ull_max_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s ; XFAIL: * ;#include "limits.h" diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Bad-relation.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Bad-relation.ll index d4a1a6222518..545a88909bf6 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Bad-relation.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Bad-relation.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: expecting other token ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-No-accesses-key.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-No-accesses-key.ll index 43f9d3eda049..f9f13b4cff58 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-No-accesses-key.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-No-accesses-key.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: Statement from JScop file has no key name 'accesses' for index 1. ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-MemAcc.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-MemAcc.ll index 24ad03741216..6031465cd03f 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-MemAcc.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-MemAcc.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: The number of memory accesses in the JSop file and the number of memory accesses differ for index 0. ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-statements.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-statements.ll index 1060926e7fac..fc67ec51f218 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-statements.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-statements.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: The number of indices and the number of statements differ. ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Relation-mispelled.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Relation-mispelled.ll index 07975976c38b..64b7b14c1939 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Relation-mispelled.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Relation-mispelled.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: Memory access number 0 has no key name 'relation' for statement number 1. ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Statements-mispelled.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Statements-mispelled.ll index 9f7259633811..bd58cb3be5c3 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Statements-mispelled.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Statements-mispelled.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: JScop file has no key name 'statements'. ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Undeclared-ScopArrayInfo.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Undeclared-ScopArrayInfo.ll index df7eb42da85f..565117584861 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Undeclared-ScopArrayInfo.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Undeclared-ScopArrayInfo.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: JScop file contains access function with undeclared ScopArrayInfo ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Wrong-number-dimensions.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Wrong-number-dimensions.ll index 61c1173db2e7..4a7d51019133 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Wrong-number-dimensions.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Wrong-number-dimensions.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: JScop file changes the number of parameter dimensions. ; diff --git a/polly/test/JSONExporter/ImportArrays/ImportArrays-Mispelled-type.ll b/polly/test/JSONExporter/ImportArrays/ImportArrays-Mispelled-type.ll index a14ae5c4d1bc..1dd71ba5816a 100644 --- a/polly/test/JSONExporter/ImportArrays/ImportArrays-Mispelled-type.ll +++ b/polly/test/JSONExporter/ImportArrays/ImportArrays-Mispelled-type.ll @@ -1,4 +1,4 @@ - ; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s + ; RUN: not --crash opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Array has not a valid type. ; diff --git a/polly/test/JSONExporter/ImportArrays/ImportArrays-Negative-size.ll b/polly/test/JSONExporter/ImportArrays/ImportArrays-Negative-size.ll index 2a03197f1c1b..5270cc8c680f 100644 --- a/polly/test/JSONExporter/ImportArrays/ImportArrays-Negative-size.ll +++ b/polly/test/JSONExporter/ImportArrays/ImportArrays-Negative-size.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-stmt-granularity=bb -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s ; ; #define Ni 1056 ; #define Nj 1056 diff --git a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-name.ll b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-name.ll index 45bb3495de08..21c4a736a25e 100644 --- a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-name.ll +++ b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-name.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s +; RUN: not --crash opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Array has no key 'name'. ; diff --git a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-sizes-key.ll b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-sizes-key.ll index 5bbb974346ba..930bfce45df0 100644 --- a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-sizes-key.ll +++ b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-sizes-key.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s +; RUN: not --crash opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Array has no key 'sizes'. ; diff --git a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-type-key.ll b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-type-key.ll index af013992fca0..eb13390dd2b9 100644 --- a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-type-key.ll +++ b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-type-key.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s +; RUN: not --crash opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Array has no key 'type'. ; diff --git a/polly/test/JSONExporter/ImportContext/ImportContext-Context-mispelled.ll b/polly/test/JSONExporter/ImportContext/ImportContext-Context-mispelled.ll index 2490e44ec347..79e175378af6 100644 --- a/polly/test/JSONExporter/ImportContext/ImportContext-Context-mispelled.ll +++ b/polly/test/JSONExporter/ImportContext/ImportContext-Context-mispelled.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: JScop file has no key named 'context'. ; diff --git a/polly/test/JSONExporter/ImportContext/ImportContext-Not-parameter-set.ll b/polly/test/JSONExporter/ImportContext/ImportContext-Not-parameter-set.ll index 66ce6a6ed922..96539188cdff 100644 --- a/polly/test/JSONExporter/ImportContext/ImportContext-Not-parameter-set.ll +++ b/polly/test/JSONExporter/ImportContext/ImportContext-Not-parameter-set.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: The isl_set is not a parameter set. ; diff --git a/polly/test/JSONExporter/ImportContext/ImportContext-Unvalid-Context.ll b/polly/test/JSONExporter/ImportContext/ImportContext-Unvalid-Context.ll index 7bcc54dde52e..0e80d3623c10 100644 --- a/polly/test/JSONExporter/ImportContext/ImportContext-Unvalid-Context.ll +++ b/polly/test/JSONExporter/ImportContext/ImportContext-Unvalid-Context.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: unexpected isl_token ; diff --git a/polly/test/JSONExporter/ImportContext/ImportContext-Wrong-dimension.ll b/polly/test/JSONExporter/ImportContext/ImportContext-Wrong-dimension.ll index 65cdcbdcdef6..9a04d89b18d1 100644 --- a/polly/test/JSONExporter/ImportContext/ImportContext-Wrong-dimension.ll +++ b/polly/test/JSONExporter/ImportContext/ImportContext-Wrong-dimension.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: Imported context has the wrong number of parameters : Found 2 Expected 1 ; diff --git a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-No-schedule-key.ll b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-No-schedule-key.ll index b52db0876cc5..6347d17da4cc 100644 --- a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-No-schedule-key.ll +++ b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-No-schedule-key.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: Statement 0 has no 'schedule' key. ; diff --git a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Schedule-not-valid.ll b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Schedule-not-valid.ll index 5ce3ad267bb0..b6f4d188fad0 100644 --- a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Schedule-not-valid.ll +++ b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Schedule-not-valid.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: expecting other token ; diff --git a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Statements-mispelled.ll b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Statements-mispelled.ll index 4329653899b2..9c325f9bfb77 100644 --- a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Statements-mispelled.ll +++ b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Statements-mispelled.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: JScop file has no key name 'statements'. ; diff --git a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Wrong-number-statements.ll b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Wrong-number-statements.ll index f66fc6c1e5d7..a6a3c7d35668 100644 --- a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Wrong-number-statements.ll +++ b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Wrong-number-statements.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: The number of indices and the number of statements differ. ; diff --git a/polly/test/MaximalStaticExpansion/load_after_store_same_statement.ll b/polly/test/MaximalStaticExpansion/load_after_store_same_statement.ll index 791210f7710d..a3611f0b89f3 100644 --- a/polly/test/MaximalStaticExpansion/load_after_store_same_statement.ll +++ b/polly/test/MaximalStaticExpansion/load_after_store_same_statement.ll @@ -1,7 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1| FileCheck %s --check-prefix=MSE -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that the expansion of an array with load after store in a same statement is not done. ; diff --git a/polly/test/MaximalStaticExpansion/read_from_original.ll b/polly/test/MaximalStaticExpansion/read_from_original.ll index 59f9379516c7..fe9c5850bc5f 100644 --- a/polly/test/MaximalStaticExpansion/read_from_original.ll +++ b/polly/test/MaximalStaticExpansion/read_from_original.ll @@ -1,7 +1,5 @@ -; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1| FileCheck %s --check-prefix=MSE -; RUN: opt %loadNPMPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that Polly detects problems and does not expand the array ; diff --git a/polly/test/MaximalStaticExpansion/too_many_writes.ll b/polly/test/MaximalStaticExpansion/too_many_writes.ll index 50a66cd11d0a..01cdd2b46682 100644 --- a/polly/test/MaximalStaticExpansion/too_many_writes.ll +++ b/polly/test/MaximalStaticExpansion/too_many_writes.ll @@ -1,7 +1,5 @@ -; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE -; RUN: opt %loadNPMPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that Polly detects problems and does not expand the array ; diff --git a/polly/test/MaximalStaticExpansion/working_deps_between_inners.ll b/polly/test/MaximalStaticExpansion/working_deps_between_inners.ll index 8e2707cfee64..3b9f951be2b4 100644 --- a/polly/test/MaximalStaticExpansion/working_deps_between_inners.ll +++ b/polly/test/MaximalStaticExpansion/working_deps_between_inners.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s ; ; Verify that the accesses are correctly expanded for MemoryKind::Array ; diff --git a/polly/test/MaximalStaticExpansion/working_deps_between_inners_phi.ll b/polly/test/MaximalStaticExpansion/working_deps_between_inners_phi.ll index 2bf49b89db05..32ed2b99bde2 100644 --- a/polly/test/MaximalStaticExpansion/working_deps_between_inners_phi.ll +++ b/polly/test/MaximalStaticExpansion/working_deps_between_inners_phi.ll @@ -1,7 +1,5 @@ -; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that the accesses are correctly expanded for MemoryKind::Array and MemoryKind::PHI. ; tmp_06_phi is not expanded because it need copy in. diff --git a/polly/test/MaximalStaticExpansion/working_expansion.ll b/polly/test/MaximalStaticExpansion/working_expansion.ll index bb5b2360143f..29ac90174f88 100644 --- a/polly/test/MaximalStaticExpansion/working_expansion.ll +++ b/polly/test/MaximalStaticExpansion/working_expansion.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s ; ; Verify that the accesses are correctly expanded for MemoryKind::Array ; diff --git a/polly/test/MaximalStaticExpansion/working_expansion_multiple_dependences_per_statement.ll b/polly/test/MaximalStaticExpansion/working_expansion_multiple_dependences_per_statement.ll index 89ff7890fc7e..6ef2f298adb9 100644 --- a/polly/test/MaximalStaticExpansion/working_expansion_multiple_dependences_per_statement.ll +++ b/polly/test/MaximalStaticExpansion/working_expansion_multiple_dependences_per_statement.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s ; ; Verify that the accesses are correctly expanded ; diff --git a/polly/test/MaximalStaticExpansion/working_expansion_multiple_instruction_per_statement.ll b/polly/test/MaximalStaticExpansion/working_expansion_multiple_instruction_per_statement.ll index 7ffd39f0f534..6c7ea23d2f53 100644 --- a/polly/test/MaximalStaticExpansion/working_expansion_multiple_instruction_per_statement.ll +++ b/polly/test/MaximalStaticExpansion/working_expansion_multiple_instruction_per_statement.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s ; ; Verify that the accesses are correctly expanded ; diff --git a/polly/test/MaximalStaticExpansion/working_phi_expansion.ll b/polly/test/MaximalStaticExpansion/working_phi_expansion.ll index 43919c61b045..0d4f18f21ade 100644 --- a/polly/test/MaximalStaticExpansion/working_phi_expansion.ll +++ b/polly/test/MaximalStaticExpansion/working_phi_expansion.ll @@ -1,7 +1,5 @@ -; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE -; RUN: opt %loadNPMPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that the accesses are correctly expanded for MemoryKind::PHI ; tmp_04 is not expanded because it need copy-in. diff --git a/polly/test/MaximalStaticExpansion/working_phi_two_scalars.ll b/polly/test/MaximalStaticExpansion/working_phi_two_scalars.ll index a581a389e742..93e984b95c95 100644 --- a/polly/test/MaximalStaticExpansion/working_phi_two_scalars.ll +++ b/polly/test/MaximalStaticExpansion/working_phi_two_scalars.ll @@ -1,7 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that the accesses are correctly expanded for MemoryKind::PHI ; tmp_05 and tmp2_06 are not expanded because they need copy-in. diff --git a/polly/test/MaximalStaticExpansion/working_value_expansion.ll b/polly/test/MaximalStaticExpansion/working_value_expansion.ll index d54eff9e03ec..27c4304d2fe5 100644 --- a/polly/test/MaximalStaticExpansion/working_value_expansion.ll +++ b/polly/test/MaximalStaticExpansion/working_value_expansion.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s ; ; Verify that the accesses are correctly expanded for MemoryKind::Value ; diff --git a/polly/test/PruneUnprofitable/prune_only_scalardeps.ll b/polly/test/PruneUnprofitable/prune_only_scalardeps.ll index 31db5560c051..c64512fc3d7a 100644 --- a/polly/test/PruneUnprofitable/prune_only_scalardeps.ll +++ b/polly/test/PruneUnprofitable/prune_only_scalardeps.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=false -polly-prune-unprofitable -disable-output -stats < %s 2>&1 | FileCheck -match-full-lines %s -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=false "-passes=scop(polly-prune-unprofitable)" -disable-output -stats < %s 2>&1 | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=false "-passes=scop(polly-prune-unprofitable)" -disable-output -stats < %s 2>&1 | FileCheck -match-full-lines %s ; REQUIRES: asserts ; ; Skip this SCoP for having scalar dependencies between all statements, diff --git a/polly/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll b/polly/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll index 5acc35343ac3..b9baa35b0cf8 100644 --- a/polly/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll +++ b/polly/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -S < %s +; RUN: opt %loadPolly -passes=polly-opt-isl -S < %s target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-a0:0-n32" define void @sdbout_label() nounwind { diff --git a/polly/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll b/polly/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll index 3f4237b330b2..e3e1d61f74c1 100644 --- a/polly/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll +++ b/polly/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -S < %s +; RUN: opt %loadPolly -passes=polly-opt-isl -S < %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-n8:16:32:64-S128" ; Check that we handle statements with an empty iteration domain correctly. diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-double.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-double.ll index a61af2d092f3..b1acd130acb6 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-double.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-double.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-first.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-first.ll index 185d5c5b8c25..4590b01f6112 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-first.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-first.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,OPT +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,OPT define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B, i32 %k) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-third.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-third.ll index f1eca0ede061..a9afceac3880 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-third.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-third.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B, i32 %k) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-carried.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-carried.ll index 35903ced7741..16dc6d8bc673 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-carried.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-carried.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,OPT +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,OPT define void @func(i32 %n, ptr noalias nonnull %A) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-third.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-third.ll index 1fb8c001069f..54611c7a1cb8 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-third.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-third.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B, i32 %k) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner.ll index 2db6833fa897..905a7804215f 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s define void @func(i32 %n, ptr noalias nonnull %A) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-simple.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-simple.ll index 49d008ba2cfa..32be9181c66b 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-simple.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-simple.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s define void @func(i32 %n, ptr noalias nonnull %A) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-simple.ll b/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-simple.ll index 175b85997ec0..d15d69e69fac 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-simple.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-simple.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s ; This could theoretically be fused by adjusting the offset of the second loop by %k (instead of relying on schedule dimensions). diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-with-middle.ll b/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-with-middle.ll index 48ba20347d55..5dc5330db107 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-with-middle.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-with-middle.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B, i32 %k) { entry: diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/disable_nonforced.ll b/polly/test/ScheduleOptimizer/ManualOptimization/disable_nonforced.ll index 537721f8718a..8676b2dd7e18 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/disable_nonforced.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/disable_nonforced.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-opt-isl -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Check that the disable_nonforced metadata is honored; optimization ; heuristics/rescheduling must not be applied. diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_heuristic.ll b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_heuristic.ll index aaf4d27f4c5e..90dc071ae8f6 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_heuristic.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_heuristic.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-pragma-based-opts=1 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines --check-prefix=ON -; RUN: opt %loadPolly -polly-reschedule=0 -polly-pragma-based-opts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines --check-prefix=OFF +; RUN: opt %loadPolly -polly-reschedule=0 -polly-pragma-based-opts=1 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines --check-prefix=ON +; RUN: opt %loadPolly -polly-reschedule=0 -polly-pragma-based-opts=0 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines --check-prefix=OFF ; define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B) { entry: diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_looploc.ll b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_looploc.ll index b1e94227c9a5..f513835c60eb 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_looploc.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_looploc.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-reschedule=0 -polly-pragma-based-opts=1 -disable-output < %s 2>&1 | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-reschedule=0 -polly-pragma-based-opts=1 -disable-output < %s 2>&1 | FileCheck %s --match-full-lines ; ; CHECK: warning: distribute_illegal.c:2:3: not applying loop fission/distribution: cannot ensure semantic equivalence due to possible dependency violations ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_pragmaloc.ll b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_pragmaloc.ll index fc0df85b1346..c18b9bb72ad7 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_pragmaloc.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_pragmaloc.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-reschedule=0 -polly-pragma-based-opts=1 -disable-output < %s 2>&1 | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-reschedule=0 -polly-pragma-based-opts=1 -disable-output < %s 2>&1 | FileCheck %s --match-full-lines ; ; CHECK: warning: distribute_illegal.c:1:42: not applying loop fission/distribution: cannot ensure semantic equivalence due to possible dependency violations ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_disable.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_disable.ll index 9537f3a9b0a8..20f5a4538b16 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_disable.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_disable.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-pragma-based-opts=1 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-pragma-based-opts=1 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines ; ; Override unroll metadata with llvm.loop.unroll.disable. ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_double.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_double.ll index b0310970f8d6..afc39a72da1d 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_double.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_double.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines ; ; Apply two loop transformations. First partial, then full unrolling. ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_full.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_full.ll index b9a4c845477c..a166421ca21a 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_full.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_full.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines ; ; Full unroll of a loop with 5 iterations. ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_heuristic.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_heuristic.ll index 0387aecd683b..68ee147895cf 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_heuristic.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_heuristic.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-pragma-based-opts=1 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines -; RUN: opt %loadPolly -polly-pragma-based-opts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-pragma-based-opts=1 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-pragma-based-opts=0 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines ; ; Unrolling with heuristic factor. ; Currently not supported and expected to be handled by LLVM's unroll pass. diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial.ll index 81e40f0a98bb..042e1b4e088a 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-pragma-based-opts=1 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines -; RUN: opt %loadPolly -polly-pragma-based-opts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefix=OFF --match-full-lines +; RUN: opt %loadPolly -polly-pragma-based-opts=1 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-pragma-based-opts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=OFF --match-full-lines ; ; Partial unroll by a factor of 4. ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial_followup.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial_followup.ll index 8665f68b99c1..893d40a41777 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial_followup.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial_followup.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefix=OPT --match-full-lines -; RUN: opt %loadPolly -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST --match-full-lines -; RUN: opt %loadPolly -polly-opt-isl -polly-codegen -simplifycfg -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=OPT --match-full-lines +; RUN: opt %loadPolly '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s --check-prefix=AST --match-full-lines +; RUN: opt %loadPolly '-passes=scop(polly-opt-isl,polly-codegen),simplifycfg' -S < %s | FileCheck %s --check-prefix=CODEGEN ; ; Partial unroll by a factor of 4. ; @@ -49,7 +49,7 @@ return: ; OPT-NEXT: - filter: "[n] -> { Stmt_body[i0] : (1 + i0) mod 4 = 0 }" -; AST-LABEL: Printing analysis 'Polly - Generate an AST of the SCoP (isl)'for => return' in function 'func': +; AST-LABEL: :: isl ast :: func :: %for---%return ; AST: // Loop with Metadata ; AST-NEXT: for (int c0 = 0; c0 < n; c0 += 4) { diff --git a/polly/test/ScheduleOptimizer/SIMDInParallelFor.ll b/polly/test/ScheduleOptimizer/SIMDInParallelFor.ll index 8585634e10ff..b0385d50c6c6 100644 --- a/polly/test/ScheduleOptimizer/SIMDInParallelFor.ll +++ b/polly/test/ScheduleOptimizer/SIMDInParallelFor.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-parallel -polly-vectorizer=stripmine -polly-codegen-verify -polly-opt-isl -polly-print-ast -polly-codegen -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-parallel -polly-vectorizer=stripmine -passes=polly-codegen-verify '-passes=polly-opt-isl,print,polly-codegen' -disable-output < %s | FileCheck %s ; ; Check that there are no nested #pragma omp parallel for inside a ; #pragma omp parallel for loop. diff --git a/polly/test/ScheduleOptimizer/computeout.ll b/polly/test/ScheduleOptimizer/computeout.ll index 35e3416f91d1..1cf6513e7a5c 100644 --- a/polly/test/ScheduleOptimizer/computeout.ll +++ b/polly/test/ScheduleOptimizer/computeout.ll @@ -1,7 +1,5 @@ -; RUN: opt -S %loadPolly -basic-aa -polly-opt-isl -polly-isl-arg=--no-schedule-serialize-sccs -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt -S %loadNPMPolly "-passes=scop(polly-opt-isl,print)" -polly-isl-arg=--no-schedule-serialize-sccs -disable-output < %s | FileCheck %s -; RUN: opt -S %loadPolly -basic-aa -polly-opt-isl -polly-isl-arg=--schedule-serialize-sccs -polly-dependences-computeout=1 -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT -; RUN: opt -S %loadNPMPolly "-passes=scop(polly-opt-isl,print)" -polly-isl-arg=--no-schedule-serialize-sccs -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT +; RUN: opt -S %loadPolly "-passes=scop(polly-opt-isl,print)" -polly-isl-arg=--no-schedule-serialize-sccs -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly "-passes=scop(polly-opt-isl,print)" -polly-isl-arg=--no-schedule-serialize-sccs -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT 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-n8:16:32:64" ; for(i = 0; i < 100; i++ ) diff --git a/polly/test/ScheduleOptimizer/ensure-correct-tile-sizes.ll b/polly/test/ScheduleOptimizer/ensure-correct-tile-sizes.ll index 43caca5372ad..87f6c6c4eee6 100644 --- a/polly/test/ScheduleOptimizer/ensure-correct-tile-sizes.ll +++ b/polly/test/ScheduleOptimizer/ensure-correct-tile-sizes.ll @@ -1,9 +1,9 @@ ; RUN: opt %loadPolly -polly-process-unprofitable -polly-remarks-minimal \ -; RUN: -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: '-passes=polly-opt-isl,print' -polly-pattern-matching-based-opts=true \ ; RUN: -polly-target-throughput-vector-fma=1 \ ; RUN: -polly-target-latency-vector-fma=1 \ ; RUN: -polly-target-vector-register-bitwidth=4096 \ -; RUN: -polly-target-1st-cache-level-associativity=3 -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: -polly-target-1st-cache-level-associativity=3 -disable-output < %s | FileCheck %s ; ; /* Test that Polly does not crash due to configurations that can lead to ; incorrect tile size computations. diff --git a/polly/test/ScheduleOptimizer/focaltech_test_detail_threshold-7bc17e.ll b/polly/test/ScheduleOptimizer/focaltech_test_detail_threshold-7bc17e.ll index daa1afdd0aa8..483737ee5928 100644 --- a/polly/test/ScheduleOptimizer/focaltech_test_detail_threshold-7bc17e.ll +++ b/polly/test/ScheduleOptimizer/focaltech_test_detail_threshold-7bc17e.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-vectorizer=stripmine -polly-invariant-load-hoisting -polly-optimized-scops -polly-print-opt-isl -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly "-passes=scop(print)" -polly-vectorizer=stripmine -polly-invariant-load-hoisting -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly "-passes=scop(print)" -polly-vectorizer=stripmine -polly-invariant-load-hoisting -disable-output < %s | FileCheck %s ; ; llvm.org/PR46578 ; diff --git a/polly/test/ScheduleOptimizer/full_partial_tile_separation.ll b/polly/test/ScheduleOptimizer/full_partial_tile_separation.ll index 06e86d7da1c6..9c4627717ee8 100644 --- a/polly/test/ScheduleOptimizer/full_partial_tile_separation.ll +++ b/polly/test/ScheduleOptimizer/full_partial_tile_separation.ll @@ -1,4 +1,4 @@ -; RUN: opt -S %loadPolly -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s ; CHECK: // 1st level tiling - Tiles ; CHECK-NEXT: #pragma known-parallel ; CHECK-NEXT: for (int c0 = 0; c0 <= floord(ni - 1, 32); c0 += 1) diff --git a/polly/test/ScheduleOptimizer/line-tiling-2.ll b/polly/test/ScheduleOptimizer/line-tiling-2.ll index eb374cb07cf3..d3d11a7990a6 100644 --- a/polly/test/ScheduleOptimizer/line-tiling-2.ll +++ b/polly/test/ScheduleOptimizer/line-tiling-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-tile-sizes=1,64 -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-tile-sizes=1,64 '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s ; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1) ; CHECK: for (int c1 = 0; c1 <= 7; c1 += 1) diff --git a/polly/test/ScheduleOptimizer/line-tiling.ll b/polly/test/ScheduleOptimizer/line-tiling.ll index 2f14ac1d02a5..273a27ba5931 100644 --- a/polly/test/ScheduleOptimizer/line-tiling.ll +++ b/polly/test/ScheduleOptimizer/line-tiling.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-tile-sizes=64,1 -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-tile-sizes=64,1 '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s ; CHECK: for (int c0 = 0; c0 <= 15; c0 += 1) ; CHECK: for (int c1 = 0; c1 <= 511; c1 += 1) diff --git a/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout.ll b/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout.ll index faf51e097a70..69dfd383060e 100644 --- a/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout.ll +++ b/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-target-throughput-vector-fma=1 \ ; RUN: -polly-target-latency-vector-fma=8 \ ; RUN: -polly-target-1st-cache-level-associativity=8 \ diff --git a/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout_2.ll b/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout_2.ll index 30b693a2e241..fe1bc0518e2c 100644 --- a/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout_2.ll +++ b/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout_2.ll @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ -; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s ; ; /* C := alpha*A*B + beta*C */ ; /* _PB_NK % Kc != 0 */ @@ -18,7 +18,7 @@ ; C[i][j] += alpha * A[i][k] * B[k][j]; ; } ; -; CHECK-LABEL: Printing analysis 'Polly - Generate an AST from the SCoP (isl)' for region: 'bb8 => bb32' in function 'kernel_gemm': +; CHECK-LABEL: :: isl ast :: kernel_gemm :: %bb8---%bb32 ; CHECK: { ; CHECK-NEXT: // 1st level tiling - Tiles ; CHECK-NEXT: for (int c0 = 0; c0 <= 32; c0 += 1) diff --git a/polly/test/ScheduleOptimizer/one-dimensional-band.ll b/polly/test/ScheduleOptimizer/one-dimensional-band.ll index 4592907a44ad..594386662ef3 100644 --- a/polly/test/ScheduleOptimizer/one-dimensional-band.ll +++ b/polly/test/ScheduleOptimizer/one-dimensional-band.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s ; ; void jacobi1d(long T, long N, float *A, float *B) { ; long t, i, j; diff --git a/polly/test/ScheduleOptimizer/outer_coincidence.ll b/polly/test/ScheduleOptimizer/outer_coincidence.ll index 2ab33edda86b..4a92f416fecc 100644 --- a/polly/test/ScheduleOptimizer/outer_coincidence.ll +++ b/polly/test/ScheduleOptimizer/outer_coincidence.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-tiling=0 -polly-parallel -polly-opt-outer-coincidence=no -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-tiling=0 -polly-parallel -polly-opt-outer-coincidence=yes -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=OUTER +; RUN: opt %loadPolly -polly-tiling=0 -polly-parallel -polly-opt-outer-coincidence=no '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-tiling=0 -polly-parallel -polly-opt-outer-coincidence=yes '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s --check-prefix=OUTER ; By skewing, the diagonal can be made parallel. ISL does this when the Check ; the 'outer_coincidence' option is enabled. diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm.ll index 66011168fcc1..979df17632b2 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm.ll @@ -1,7 +1,7 @@ ; RUN: opt %loadPolly \ ; RUN: -polly-pattern-matching-based-opts=true \ -; RUN: -polly-optree -polly-delicm -polly-simplify \ -; RUN: -polly-opt-isl -polly-tc-opt=true -debug -disable-output < %s 2>&1 \ +; RUN: '-passes=polly-optree,polly-delicm,polly-simplify,polly-opt-isl' \ +; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm_2.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm_2.ll index 95da89f90755..80cae8554fdb 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm_2.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-delicm -polly-simplify -polly-opt-isl \ +; RUN: opt %loadPolly '-passes=polly-delicm,polly-simplify,polly-opt-isl' \ ; RUN: -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts.ll index 7604257f98e0..5e0bb81c5908 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts.ll @@ -1,8 +1,8 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=false \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=false \ ; RUN: -debug -polly-tc-opt -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true -debug -polly-tc-opt -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PATTERN-MATCHING-OPTS -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true -polly-ast-detect-parallel -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=PARALLEL-AST -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true -stats -disable-output < %s 2>&1 | FileCheck %s --check-prefix=STATS -match-full-lines +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true -debug -polly-tc-opt -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PATTERN-MATCHING-OPTS +; RUN: opt %loadPolly '-passes=polly-opt-isl,print' -polly-pattern-matching-based-opts=true -polly-ast-detect-parallel -disable-output < %s | FileCheck %s --check-prefix=PARALLEL-AST +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true -stats -disable-output < %s 2>&1 | FileCheck %s --check-prefix=STATS -match-full-lines ; REQUIRES: asserts ; ; /* C := alpha*A*B + beta*C */ diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_11.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_11.ll index ccdb39b60d75..5c4391693b13 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_11.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_11.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop \ +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-opt-isl' \ ; RUN: -polly-import-jscop-postfix=transformed \ ; RUN: -polly-pattern-matching-based-opts=true \ ; RUN: -polly-target-throughput-vector-fma=1 \ @@ -8,7 +8,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-opt-isl -debug \ +; RUN: -debug \ ; RUN: -polly-tc-opt=true -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_12.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_12.ll index dd39fec5e21f..b21a26b4772d 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_12.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_12.ll @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-opt-isl -disable-output < %s +; RUN: -passes=polly-opt-isl -disable-output < %s ; ; Test whether isolation works as expected. ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_13.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_13.ll index e086dd36c4d9..a16ecf6af6ce 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_13.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_13.ll @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=128 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s ; ; Test whether isolation works as expected. ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_14.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_14.ll index a4c71c2dace5..2c23ebbac43c 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_14.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_14.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-opt-isl \ +; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-opt-isl,polly-codegen' \ ; RUN: -polly-target-throughput-vector-fma=1 \ ; RUN: -polly-target-latency-vector-fma=8 \ ; RUN: -polly-target-1st-cache-level-associativity=8 \ @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-import-jscop-postfix=transformed -polly-codegen -S < %s \ +; RUN: -polly-import-jscop-postfix=transformed -S < %s \ ; RUN: | FileCheck %s ; ; Check that we disable the Loop Vectorizer. diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_15.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_15.ll index a8da21955b63..c8d8d295e8c8 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_15.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_15.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -debug-only=polly-opt-isl -disable-output \ ; RUN: -polly-tc-opt=true < %s 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_16.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_16.ll index c1ad3017a0d4..970b4a0cf932 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_16.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_16.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_17.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_17.ll index 002816a4ae80..e44e3bfa04c2 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_17.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_17.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_18.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_18.ll index d5679c7ae2f7..2612321b3d09 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_18.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_18.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_19.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_19.ll index 4e1620abd252..bd5f0ed40953 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_19.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_19.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_2.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_2.ll index 01e336ebc60f..573c35256992 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_2.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_20.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_20.ll index 0be08d8d493c..78cc48d830c8 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_20.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_20.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_21.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_21.ll index 9b2df49698a1..adfba0584a88 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_21.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_21.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_22.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_22.ll index 3d3641df5098..54e03b301e69 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_22.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_22.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_24.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_24.ll index 895961488014..fee5027848a8 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_24.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_24.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-opt-isl \ +; RUN: opt %loadPolly -polly-reschedule=0 -passes=polly-opt-isl \ ; RUN: -polly-pattern-matching-based-opts=true -polly-tc-opt=true \ ; RUN: -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_25.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_25.ll index 8a3957909d9d..029dcc491f02 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_25.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_25.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; @@ -53,4 +53,4 @@ for.body8: ; preds = %for.body8, %for.con br i1 %exitcond.not, label %for.cond.cleanup7, label %for.body8 } -declare double @llvm.fmuladd.f64(double, double, double) \ No newline at end of file +declare double @llvm.fmuladd.f64(double, double, double) diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_3.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_3.ll index fab3ac5e58dc..46c8c7e35f2a 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_3.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_3.ll @@ -3,7 +3,7 @@ ; RUN: -polly-target-latency-vector-fma=8 \ ; RUN: -polly-target-1st-cache-level-size=0 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ -; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s 2>&1 | FileCheck %s +; RUN: '-passes=polly-opt-isl,print' -disable-output < %s 2>&1 | FileCheck %s ; RUN: opt %loadPolly -polly-pattern-matching-based-opts=true \ ; RUN: -polly-target-throughput-vector-fma=1 \ @@ -13,7 +13,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s 2>&1 | FileCheck %s --check-prefix=EXTRACTION-OF-MACRO-KERNEL +; RUN: '-passes=polly-opt-isl,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=EXTRACTION-OF-MACRO-KERNEL ; ; /* C := alpha*A*B + beta*C */ ; for (i = 0; i < _PB_NI; i++) @@ -24,7 +24,7 @@ ; C[i][j] += alpha * A[i][k] * B[k][j]; ; } ; -; CHECK-LABEL: Printing analysis 'Polly - Generate an AST from the SCoP (isl)' for region: 'bb8 => bb32' in function 'kernel_gemm': +; CHECK-LABEL: :: isl ast :: kernel_gemm :: %bb8---%bb32 ; CHECK: { ; CHECK-NEXT: // 1st level tiling - Tiles ; CHECK-NEXT: for (int c0 = 0; c0 <= 32; c0 += 1) @@ -76,7 +76,7 @@ ; CHECK-NEXT: } ; CHECK-NEXT: } ; -; EXTRACTION-OF-MACRO-KERNEL-LABEL: Printing analysis 'Polly - Generate an AST from the SCoP (isl)' for region: 'bb8 => bb32' in function 'kernel_gemm': +; EXTRACTION-OF-MACRO-KERNEL-LABEL: :: isl ast :: kernel_gemm :: %bb8---%bb32 ; EXTRACTION-OF-MACRO-KERNEL: { ; EXTRACTION-OF-MACRO-KERNEL-NEXT: // 1st level tiling - Tiles ; EXTRACTION-OF-MACRO-KERNEL-NEXT: for (int c0 = 0; c0 <= 32; c0 += 1) diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_4.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_4.ll index dc0edc6c5a3b..ec1926ebb75f 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_4.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_4.ll @@ -1,12 +1,12 @@ -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -debug -polly-tc-opt=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly '-passes=polly-opt-isl,print' -polly-pattern-matching-based-opts=true \ ; RUN: -polly-target-throughput-vector-fma=1 \ ; RUN: -polly-target-latency-vector-fma=8 \ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ -; RUN: -polly-target-2nd-cache-level-size=262144 -polly-print-ast \ -; RUN: -polly-tc-opt=true -disable-output -polly-opt-isl < %s | \ +; RUN: -polly-target-2nd-cache-level-size=262144 \ +; RUN: -polly-tc-opt=true -disable-output < %s | \ ; RUN: FileCheck %s --check-prefix=PATTERN-MATCHING-OPTS ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_5.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_5.ll index 6581566bf13f..bfb378259210 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_5.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_5.ll @@ -6,12 +6,12 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s ; -; opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; -polly-target-throughput-vector-fma=1 \ ; -polly-target-latency-vector-fma=8 \ -; -polly-codegen -polly-target-1st-cache-level-associativity=8 \ +; -passes=polly-codegen -polly-target-1st-cache-level-associativity=8 \ ; -polly-target-2nd-cache-level-associativity=8 \ ; -polly-target-1st-cache-level-size=32768 \ ; -polly-target-vector-register-bitwidth=256 \ diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_6.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_6.ll index bcf1fc9fe813..684cd9be1728 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_6.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_6.ll @@ -6,12 +6,12 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s ; -; opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ +; opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ ; -polly-target-throughput-vector-fma=1 \ ; -polly-target-latency-vector-fma=8 \ -; -polly-codegen -polly-target-1st-cache-level-associativity=8 \ +; -passes=polly-codegen -polly-target-1st-cache-level-associativity=8 \ ; -polly-target-2nd-cache-level-associativity=8 \ ; -polly-target-1st-cache-level-size=32768 \ ; -polly-target-vector-register-bitwidth=256 \ diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_7.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_7.ll index 77a3e02a0063..b34b4f020ccb 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_7.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_7.ll @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s ; ; /* C := A * B + C */ ; /* Elements of the matrices A, B, C have the float type. */ diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_8.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_8.ll index d02bc359e79d..a65d92940665 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_8.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_8.ll @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s ; ; /* C := A * B + C */ ; /* Elements of the matrices B, C have the double type. */ diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_9.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_9.ll index 144abfd7622f..5a35e2c049f0 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_9.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_9.ll @@ -6,9 +6,9 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-opt-isl -disable-output < %s +; RUN: -passes=polly-opt-isl -disable-output < %s ; -; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s --check-prefix=DEPENDENCES +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=DEPENDENCES ; ; /* C := A * B + C */ ; /* Elements of the matrices A, B, C have the char type. */ diff --git a/polly/test/ScheduleOptimizer/pattern_matching_based_opts_splitmap.ll b/polly/test/ScheduleOptimizer/pattern_matching_based_opts_splitmap.ll index 5b9783d20bfc..05362c712a4d 100644 --- a/polly/test/ScheduleOptimizer/pattern_matching_based_opts_splitmap.ll +++ b/polly/test/ScheduleOptimizer/pattern_matching_based_opts_splitmap.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-opt-isl -debug-only=polly-opt-isl -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -passes=polly-opt-isl -debug-only=polly-opt-isl -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; ; void pattern_matching_based_opts_splitmap(double C[static const restrict 2][2], double A[static const restrict 2][784], double B[static const restrict 784][2]) { diff --git a/polly/test/ScheduleOptimizer/prevectorization-without-tiling.ll b/polly/test/ScheduleOptimizer/prevectorization-without-tiling.ll index fea2155b1e4e..5c44f73c287c 100644 --- a/polly/test/ScheduleOptimizer/prevectorization-without-tiling.ll +++ b/polly/test/ScheduleOptimizer/prevectorization-without-tiling.ll @@ -1,4 +1,4 @@ -; RUN: opt -S %loadPolly -basic-aa -polly-tiling=false -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-tiling=false -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" @C = common global [1536 x [1536 x float]] zeroinitializer, align 16 diff --git a/polly/test/ScheduleOptimizer/prevectorization.ll b/polly/test/ScheduleOptimizer/prevectorization.ll index 385ebf14712a..6a8ec549c784 100644 --- a/polly/test/ScheduleOptimizer/prevectorization.ll +++ b/polly/test/ScheduleOptimizer/prevectorization.ll @@ -1,5 +1,5 @@ -; RUN: opt -S %loadPolly -basic-aa -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt -S %loadPolly -basic-aa -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine -polly-prevect-width=16 -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=VEC16 +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine -polly-prevect-width=16 '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s -check-prefix=VEC16 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScheduleOptimizer/rectangular-tiling.ll b/polly/test/ScheduleOptimizer/rectangular-tiling.ll index b527255ab5f7..9d34c7c17a79 100644 --- a/polly/test/ScheduleOptimizer/rectangular-tiling.ll +++ b/polly/test/ScheduleOptimizer/rectangular-tiling.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-tiling=false -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=NOTILING -; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-2nd-level-tiling -polly-2nd-level-tile-sizes=16,8 -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=TWOLEVEL -; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-2nd-level-tiling -polly-2nd-level-tile-sizes=16,8 -polly-register-tiling -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=TWO-PLUS-REGISTER +; RUN: opt %loadPolly -polly-tile-sizes=256,16 '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-tiling=false '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s --check-prefix=NOTILING +; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-2nd-level-tiling -polly-2nd-level-tile-sizes=16,8 '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s --check-prefix=TWOLEVEL +; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-2nd-level-tiling -polly-2nd-level-tile-sizes=16,8 -polly-register-tiling '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s --check-prefix=TWO-PLUS-REGISTER ; CHECK: // 1st level tiling - Tiles ; CHECK: for (int c0 = 0; c0 <= 3; c0 += 1) diff --git a/polly/test/ScheduleOptimizer/schedule_computeout.ll b/polly/test/ScheduleOptimizer/schedule_computeout.ll index acc8601a31a8..6e60fe1cd6f3 100644 --- a/polly/test/ScheduleOptimizer/schedule_computeout.ll +++ b/polly/test/ScheduleOptimizer/schedule_computeout.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -polly-optree -polly-delicm -polly-opt-isl -polly-schedule-computeout=10000 -debug-only="polly-opt-isl" < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-optree -passes=polly-delicm -passes=polly-opt-isl -polly-schedule-computeout=10000 -debug-only="polly-opt-isl" < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; Bailout if the computations of schedule compute exceeds the max scheduling quota. diff --git a/polly/test/ScheduleOptimizer/statistics.ll b/polly/test/ScheduleOptimizer/statistics.ll index 472febea173f..56bf06894dd4 100644 --- a/polly/test/ScheduleOptimizer/statistics.ll +++ b/polly/test/ScheduleOptimizer/statistics.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-opt-isl -stats -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -passes=polly-opt-isl -stats -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/tile_after_fusion.ll b/polly/test/ScheduleOptimizer/tile_after_fusion.ll index 8e5849234af6..b834b354af4d 100644 --- a/polly/test/ScheduleOptimizer/tile_after_fusion.ll +++ b/polly/test/ScheduleOptimizer/tile_after_fusion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-isl-arg=--no-schedule-serialize-sccs -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-isl-arg=--no-schedule-serialize-sccs '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s ; ; ; void tf(int C[256][256][256], int A0[256][256][256], int A1[256][256][256]) { @@ -17,7 +17,7 @@ ; checks whether they are tiled after being fused when polly-opt-fusion equals ; "max". ; -; CHECK-LABEL: Printing analysis 'Polly - Generate an AST from the SCoP (isl)' for region: 'for.cond => for.end56' in function 'tf': +; CHECK-LABEL: :: isl ast :: tf :: %for.cond---%for.end56 ; CHECK: 1st level tiling - Tiles ; CHECK-NEXT: for (int c0 = 0; c0 <= 7; c0 += 1) ; CHECK-NEXT: for (int c1 = 0; c1 <= 7; c1 += 1) diff --git a/polly/test/ScheduleOptimizer/vivid-vbi-gen-vivid_vbi_gen_sliced-before-llvmreduced.ll b/polly/test/ScheduleOptimizer/vivid-vbi-gen-vivid_vbi_gen_sliced-before-llvmreduced.ll index d08595db8fce..bfa1f017b61a 100644 --- a/polly/test/ScheduleOptimizer/vivid-vbi-gen-vivid_vbi_gen_sliced-before-llvmreduced.ll +++ b/polly/test/ScheduleOptimizer/vivid-vbi-gen-vivid_vbi_gen_sliced-before-llvmreduced.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-vectorizer=stripmine -polly-isl-arg=--no-schedule-serialize-sccs -polly-tiling=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-vectorizer=stripmine -polly-isl-arg=--no-schedule-serialize-sccs -polly-tiling=0 '-passes=print' -disable-output < %s | FileCheck %s ; isl_schedule_node_band_sink may sink into multiple children. ; https://llvm.org/PR52637 diff --git a/polly/test/ScopDetect/aliasing_parametric_simple_1.ll b/polly/test/ScopDetect/aliasing_parametric_simple_1.ll index 2eddbd4cb262..8a2317446d64 100644 --- a/polly/test/ScopDetect/aliasing_parametric_simple_1.ll +++ b/polly/test/ScopDetect/aliasing_parametric_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Valid Region for Scop: ; diff --git a/polly/test/ScopDetect/aliasing_parametric_simple_2.ll b/polly/test/ScopDetect/aliasing_parametric_simple_2.ll index c111f686c462..df1d1f8d56bc 100644 --- a/polly/test/ScopDetect/aliasing_parametric_simple_2.ll +++ b/polly/test/ScopDetect/aliasing_parametric_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Valid Region for Scop: ; diff --git a/polly/test/ScopDetect/aliasing_simple_1.ll b/polly/test/ScopDetect/aliasing_simple_1.ll index 524ca19ae398..af5b7cf1dfb7 100644 --- a/polly/test/ScopDetect/aliasing_simple_1.ll +++ b/polly/test/ScopDetect/aliasing_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Valid Region for Scop: ; diff --git a/polly/test/ScopDetect/aliasing_simple_2.ll b/polly/test/ScopDetect/aliasing_simple_2.ll index 457df996c7b8..cd3155ec613a 100644 --- a/polly/test/ScopDetect/aliasing_simple_2.ll +++ b/polly/test/ScopDetect/aliasing_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Valid Region for Scop: ; diff --git a/polly/test/ScopDetect/base_pointer_load_setNewAccessRelation.ll b/polly/test/ScopDetect/base_pointer_load_setNewAccessRelation.ll index 0411aed6ae04..ab56f344f093 100644 --- a/polly/test/ScopDetect/base_pointer_load_setNewAccessRelation.ll +++ b/polly/test/ScopDetect/base_pointer_load_setNewAccessRelation.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true -polly-scops -polly-print-import-jscop -polly-codegen -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true '-passes=print,scop(polly-import-jscop,polly-codegen)' -disable-output < %s 2>&1 | FileCheck %s ; ; This violated an assertion in setNewAccessRelation that assumed base pointers ; to be load-hoisted. Without this assertion, it codegen would generate invalid diff --git a/polly/test/ScopDetect/base_pointer_setNewAccessRelation.ll b/polly/test/ScopDetect/base_pointer_setNewAccessRelation.ll index ff9be6ea16e8..df7f3d706fd3 100644 --- a/polly/test/ScopDetect/base_pointer_setNewAccessRelation.ll +++ b/polly/test/ScopDetect/base_pointer_setNewAccessRelation.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -disable-basic-aa -polly-detect -polly-print-import-jscop -polly-codegen -disable-output < %s | FileCheck %s --allow-empty +; RUN: opt %loadPolly '-passes=print,scop(polly-import-jscop,polly-codegen)' -disable-output < %s 2>&1 | FileCheck %s --allow-empty ; ; Polly codegen used to generate invalid code (referring to %ptr from the ; original region) when regeneration of the access function is necessary. diff --git a/polly/test/ScopDetect/callbr.ll b/polly/test/ScopDetect/callbr.ll index d65ab934bf2e..5183b9c1a085 100644 --- a/polly/test/ScopDetect/callbr.ll +++ b/polly/test/ScopDetect/callbr.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-detect -polly-detect-track-failures -disable-output -pass-remarks-missed=polly-detect < %s 2>&1 | FileCheck %s --check-prefix=REMARK -; RUN: opt %loadPolly -polly-detect -polly-detect-track-failures -disable-output -stats < %s 2>&1 | FileCheck %s --check-prefix=STAT +; RUN: opt %loadPolly '-passes=print' -polly-detect-track-failures -disable-output -pass-remarks-missed=polly-detect < %s 2>&1 | FileCheck %s --check-prefix=REMARK +; RUN: opt %loadPolly '-passes=print' -polly-detect-track-failures -disable-output -stats < %s 2>&1 | FileCheck %s --check-prefix=STAT ; REQUIRES: asserts ; REMARK: Branch from indirect terminator. diff --git a/polly/test/ScopDetect/collective_invariant_loads.ll b/polly/test/ScopDetect/collective_invariant_loads.ll index f1d2eea520c6..96f154f07d2e 100644 --- a/polly/test/ScopDetect/collective_invariant_loads.ll +++ b/polly/test/ScopDetect/collective_invariant_loads.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting -disable-output< %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting -disable-output< %s 2>&1 | FileCheck %s ;CHECK: Function: test_init_chpl ;CHECK-NEXT: Region: %bb1---%bb16 diff --git a/polly/test/ScopDetect/cross_loop_non_single_exit.ll b/polly/test/ScopDetect/cross_loop_non_single_exit.ll index ae23930b92a6..e54d30fc2164 100644 --- a/polly/test/ScopDetect/cross_loop_non_single_exit.ll +++ b/polly/test/ScopDetect/cross_loop_non_single_exit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/cross_loop_non_single_exit_2.ll b/polly/test/ScopDetect/cross_loop_non_single_exit_2.ll index 5c25da66d7ef..f3bd0d097b71 100644 --- a/polly/test/ScopDetect/cross_loop_non_single_exit_2.ll +++ b/polly/test/ScopDetect/cross_loop_non_single_exit_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll b/polly/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll index 12983d2321cc..6d262a9a464b 100644 --- a/polly/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll +++ b/polly/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-detect -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %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" define void @f(ptr %A, i64 %N, i64 %M) nounwind { diff --git a/polly/test/ScopDetect/dot-scops-npm.ll b/polly/test/ScopDetect/dot-scops-npm.ll index 7c8be032fd4f..9de6a5e2e1a5 100644 --- a/polly/test/ScopDetect/dot-scops-npm.ll +++ b/polly/test/ScopDetect/dot-scops-npm.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadNPMPolly "-passes=polly-scop-printer" -disable-output < %s +; RUN: opt %loadPolly '-passes=polly-scop-printer' -disable-output < %s ; RUN: FileCheck %s -input-file=scops.func_npm.dot ; ; Check that the ScopPrinter does not crash. diff --git a/polly/test/ScopDetect/dot-scops.ll b/polly/test/ScopDetect/dot-scops.ll index c31562e4c62d..2297fd3253ca 100644 --- a/polly/test/ScopDetect/dot-scops.ll +++ b/polly/test/ScopDetect/dot-scops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-scops -dot-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print,polly-scop-printer' -disable-output < %s ; ; Check that the ScopPrinter does not crash. ; ScopPrinter needs the ScopDetection pass, which should depend on diff --git a/polly/test/ScopDetect/error-block-always-executed.ll b/polly/test/ScopDetect/error-block-always-executed.ll index 894be2119941..312c48cfee96 100644 --- a/polly/test/ScopDetect/error-block-always-executed.ll +++ b/polly/test/ScopDetect/error-block-always-executed.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK-NOT: Valid Region for Scop: diff --git a/polly/test/ScopDetect/error-block-referenced-from-scop.ll b/polly/test/ScopDetect/error-block-referenced-from-scop.ll index 085351482139..d3e56472e497 100644 --- a/polly/test/ScopDetect/error-block-referenced-from-scop.ll +++ b/polly/test/ScopDetect/error-block-referenced-from-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK-NOT: Valid Region for Scop: diff --git a/polly/test/ScopDetect/error-block-unreachable.ll b/polly/test/ScopDetect/error-block-unreachable.ll index 48f6fe8e0547..72d43004e322 100644 --- a/polly/test/ScopDetect/error-block-unreachable.ll +++ b/polly/test/ScopDetect/error-block-unreachable.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-detect -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ; Verify that the scop detection does not crash on inputs with unreachable ; blocks. Earlier we crashed when detecting error blocks. diff --git a/polly/test/ScopDetect/expand-region-correctly-2.ll b/polly/test/ScopDetect/expand-region-correctly-2.ll index fadb503cff35..b6632c643fdf 100644 --- a/polly/test/ScopDetect/expand-region-correctly-2.ll +++ b/polly/test/ScopDetect/expand-region-correctly-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Valid Region for Scop: if.end.1631 => for.cond.1647.outer ; diff --git a/polly/test/ScopDetect/expand-region-correctly.ll b/polly/test/ScopDetect/expand-region-correctly.ll index 72082a32fa79..022dfb68ecd9 100644 --- a/polly/test/ScopDetect/expand-region-correctly.ll +++ b/polly/test/ScopDetect/expand-region-correctly.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Valid Region for Scop: if.end.1631 => for.cond.1647.outer diff --git a/polly/test/ScopDetect/ignore_func_flag_regex.ll b/polly/test/ScopDetect/ignore_func_flag_regex.ll index 224126ec010e..15b92b418bcb 100644 --- a/polly/test/ScopDetect/ignore_func_flag_regex.ll +++ b/polly/test/ScopDetect/ignore_func_flag_regex.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-ignore-func=f.*,g.* -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-ignore-func=f.*,g.* '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that the flag `-polly-ignore-func` works with regexes. ; diff --git a/polly/test/ScopDetect/index_from_unpredictable_loop.ll b/polly/test/ScopDetect/index_from_unpredictable_loop.ll index 27ed64da17e6..e0be6243ebf8 100644 --- a/polly/test/ScopDetect/index_from_unpredictable_loop.ll +++ b/polly/test/ScopDetect/index_from_unpredictable_loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=AFFINE -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=AFFINE +; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopDetect/index_from_unpredictable_loop2.ll b/polly/test/ScopDetect/index_from_unpredictable_loop2.ll index 9b5a3a4389d4..4d4b6f988b69 100644 --- a/polly/test/ScopDetect/index_from_unpredictable_loop2.ll +++ b/polly/test/ScopDetect/index_from_unpredictable_loop2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=AFFINE -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE +; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=AFFINE +; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopDetect/indvars.ll b/polly/test/ScopDetect/indvars.ll index 2ba4d1f5aabf..023f68435988 100644 --- a/polly/test/ScopDetect/indvars.ll +++ b/polly/test/ScopDetect/indvars.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -polly-codegen -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,scop(polly-codegen)' -disable-output < %s 2>&1 | 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-n8:16:32:64" diff --git a/polly/test/ScopDetect/intrinsics_1.ll b/polly/test/ScopDetect/intrinsics_1.ll index 65d3968e247c..61e1c1fc3d86 100644 --- a/polly/test/ScopDetect/intrinsics_1.ll +++ b/polly/test/ScopDetect/intrinsics_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Valid Region for Scop: for.cond => for.end ; diff --git a/polly/test/ScopDetect/intrinsics_2.ll b/polly/test/ScopDetect/intrinsics_2.ll index f0575511b2ef..0c2aa49c2d21 100644 --- a/polly/test/ScopDetect/intrinsics_2.ll +++ b/polly/test/ScopDetect/intrinsics_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify that we allow the lifetime markers for the tmp array. ; diff --git a/polly/test/ScopDetect/intrinsics_3.ll b/polly/test/ScopDetect/intrinsics_3.ll index bce90d136a41..16d41d0550af 100644 --- a/polly/test/ScopDetect/intrinsics_3.ll +++ b/polly/test/ScopDetect/intrinsics_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify that we allow the misc intrinsics. ; diff --git a/polly/test/ScopDetect/invalid-latch-conditions.ll b/polly/test/ScopDetect/invalid-latch-conditions.ll index eb8097470ecf..1264ba0483c0 100644 --- a/polly/test/ScopDetect/invalid-latch-conditions.ll +++ b/polly/test/ScopDetect/invalid-latch-conditions.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=NALOOPS -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NALOOPS +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT ; The latch conditions of the outer loop are not affine, thus the loop cannot ; handled by the domain generation and needs to be overapproximated. diff --git a/polly/test/ScopDetect/invalidate_scalar_evolution.ll b/polly/test/ScopDetect/invalidate_scalar_evolution.ll index 01d34c49e289..c691c7a633d2 100644 --- a/polly/test/ScopDetect/invalidate_scalar_evolution.ll +++ b/polly/test/ScopDetect/invalidate_scalar_evolution.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=PHI +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=PHI ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/invariant-load-before-scop.ll b/polly/test/ScopDetect/invariant-load-before-scop.ll index f72085ff88a1..ee2eba5e8ec6 100644 --- a/polly/test/ScopDetect/invariant-load-before-scop.ll +++ b/polly/test/ScopDetect/invariant-load-before-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; ; The LoadInst %.b761 is defined outside the SCoP, hence is always constant ; within it. It is no "required invariant load". diff --git a/polly/test/ScopDetect/keep_going_expansion.ll b/polly/test/ScopDetect/keep_going_expansion.ll index 9bcfb3924f6a..7da7cd41c1f9 100644 --- a/polly/test/ScopDetect/keep_going_expansion.ll +++ b/polly/test/ScopDetect/keep_going_expansion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-detect-track-failures -polly-detect-keep-going -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-detect-track-failures -polly-detect-keep-going '-passes=print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopDetect/mod_ref_read_pointer.ll b/polly/test/ScopDetect/mod_ref_read_pointer.ll index 95a4649f4705..7b185a87c821 100644 --- a/polly/test/ScopDetect/mod_ref_read_pointer.ll +++ b/polly/test/ScopDetect/mod_ref_read_pointer.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-allow-modref-calls -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=MODREF -; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-modref-calls '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=MODREF +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK-NOT: Valid Region for Scop: for.body => for.end ; MODREF: Valid Region for Scop: for.body => for.end diff --git a/polly/test/ScopDetect/more-than-one-loop.ll b/polly/test/ScopDetect/more-than-one-loop.ll index bfd226c1bcfc..5972fbf50889 100644 --- a/polly/test/ScopDetect/more-than-one-loop.ll +++ b/polly/test/ScopDetect/more-than-one-loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-process-unprofitable=true -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Valid Region for Scop: diff --git a/polly/test/ScopDetect/multidim-with-undef-size.ll b/polly/test/ScopDetect/multidim-with-undef-size.ll index 9973c6c72169..2adf7bb00b42 100644 --- a/polly/test/ScopDetect/multidim-with-undef-size.ll +++ b/polly/test/ScopDetect/multidim-with-undef-size.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; CHECK: Valid Region for Scop: bb14 => bb17 diff --git a/polly/test/ScopDetect/multidim.ll b/polly/test/ScopDetect/multidim.ll index f43698819f32..a1a6167a121e 100644 --- a/polly/test/ScopDetect/multidim.ll +++ b/polly/test/ScopDetect/multidim.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; CHECK: Valid Region for Scop: bb19 => bb20 diff --git a/polly/test/ScopDetect/multidim_indirect_access.ll b/polly/test/ScopDetect/multidim_indirect_access.ll index 3e06251f5fd1..4a3012d1c93c 100644 --- a/polly/test/ScopDetect/multidim_indirect_access.ll +++ b/polly/test/ScopDetect/multidim_indirect_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that we will recognize this SCoP. ; diff --git a/polly/test/ScopDetect/multidim_two_accesses_different_delinearization.ll b/polly/test/ScopDetect/multidim_two_accesses_different_delinearization.ll index ed554a24a6d6..23d520ed58be 100644 --- a/polly/test/ScopDetect/multidim_two_accesses_different_delinearization.ll +++ b/polly/test/ScopDetect/multidim_two_accesses_different_delinearization.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/ScopDetect/nested_loop_single_exit.ll b/polly/test/ScopDetect/nested_loop_single_exit.ll index 377e8088eedb..a794e2c48ff9 100644 --- a/polly/test/ScopDetect/nested_loop_single_exit.ll +++ b/polly/test/ScopDetect/nested_loop_single_exit.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s ; void f(long A[], long N) { ; long i, j; diff --git a/polly/test/ScopDetect/non-affine-conditional.ll b/polly/test/ScopDetect/non-affine-conditional.ll index fc2d0c02d2da..f69b6f8cd1ed 100644 --- a/polly/test/ScopDetect/non-affine-conditional.ll +++ b/polly/test/ScopDetect/non-affine-conditional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-branches '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/ScopDetect/non-affine-float-compare.ll b/polly/test/ScopDetect/non-affine-float-compare.ll index 984f14aaff8f..1e4c580fa00d 100644 --- a/polly/test/ScopDetect/non-affine-float-compare.ll +++ b/polly/test/ScopDetect/non-affine-float-compare.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-branches '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(float *A) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access.ll b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access.ll index 068367fa1e3c..443a0e13c6ca 100644 --- a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access.ll +++ b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT ; ; Here we have a non-affine loop but also a non-affine access which should ; be rejected as long as -polly-allow-nonaffine isn't given. diff --git a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_2.ll b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_2.ll index cd2140518b46..77733a8d9b96 100644 --- a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_2.ll +++ b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_2.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES ; ; Here we have a non-affine loop (in the context of the loop nest) ; and also a non-affine access (A[k]). While we can always detect the diff --git a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_3.ll b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_3.ll index fb936216e45c..034ab61fa03e 100644 --- a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_3.ll +++ b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_3.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES ; ; Here we have a non-affine loop (in the context of the loop nest) ; and also a non-affine access (A[k]). While we can always detect the diff --git a/polly/test/ScopDetect/non-affine-loop.ll b/polly/test/ScopDetect/non-affine-loop.ll index d5f7ea128a79..d17fd39da701 100644 --- a/polly/test/ScopDetect/non-affine-loop.ll +++ b/polly/test/ScopDetect/non-affine-loop.ll @@ -1,8 +1,8 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-allow-nonaffine -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINEREGIONSANDACCESSES -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINEREGIONSANDACCESSES +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT ; ; This function/region does contain a loop, however it is non-affine, hence the access ; A[i] is also. Furthermore, it is the only loop, thus when we over approximate diff --git a/polly/test/ScopDetect/non-beneficial-loops-small-trip-count.ll b/polly/test/ScopDetect/non-beneficial-loops-small-trip-count.ll index 43af1684dccb..d5901b63dd37 100644 --- a/polly/test/ScopDetect/non-beneficial-loops-small-trip-count.ll +++ b/polly/test/ScopDetect/non-beneficial-loops-small-trip-count.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK-NOT: Valid ; diff --git a/polly/test/ScopDetect/non-constant-add-rec-start-expr.ll b/polly/test/ScopDetect/non-constant-add-rec-start-expr.ll index 4cddcc916a76..f39e774021a9 100644 --- a/polly/test/ScopDetect/non-constant-add-rec-start-expr.ll +++ b/polly/test/ScopDetect/non-constant-add-rec-start-expr.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Valid Region for Scop: bb11 => bb25 diff --git a/polly/test/ScopDetect/non-simple-memory-accesses.ll b/polly/test/ScopDetect/non-simple-memory-accesses.ll index a82228982885..d1c2ce63059e 100644 --- a/polly/test/ScopDetect/non-simple-memory-accesses.ll +++ b/polly/test/ScopDetect/non-simple-memory-accesses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify that we do not model atomic memory accesses. We did not reason about ; how to handle them correctly and the Alias Set Tracker models some of them diff --git a/polly/test/ScopDetect/non_affine_loop_condition.ll b/polly/test/ScopDetect/non_affine_loop_condition.ll index f268442cd8ee..1d67df58d9bb 100644 --- a/polly/test/ScopDetect/non_affine_loop_condition.ll +++ b/polly/test/ScopDetect/non_affine_loop_condition.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-print-detect -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT ; ; void f(int *A) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/ScopDetect/only-one-affine-loop.ll b/polly/test/ScopDetect/only-one-affine-loop.ll index d6d50bb611d9..3f4305ab83e7 100644 --- a/polly/test/ScopDetect/only-one-affine-loop.ll +++ b/polly/test/ScopDetect/only-one-affine-loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable=false -polly-allow-nonaffine-loops -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable=false -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Even if we allow non-affine loops we can only model the outermost loop, all ; other loops are boxed in non-affine regions. However, the inner loops can be diff --git a/polly/test/ScopDetect/only_func_flag.ll b/polly/test/ScopDetect/only_func_flag.ll index d465cd0f50f7..35a38e875e12 100644 --- a/polly/test/ScopDetect/only_func_flag.ll +++ b/polly/test/ScopDetect/only_func_flag.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-only-func=f,g -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-only-func=f,g '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that the flag `-polly-only-func` limits analysis to `f` and `g`. ; diff --git a/polly/test/ScopDetect/only_func_flag_regex.ll b/polly/test/ScopDetect/only_func_flag_regex.ll index e6675798eeb9..3b577b100db3 100644 --- a/polly/test/ScopDetect/only_func_flag_regex.ll +++ b/polly/test/ScopDetect/only_func_flag_regex.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-only-func=f.*,g.* -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-only-func=f.*,g.* '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that the flag `-polly-only-func` works with regexes. ; diff --git a/polly/test/ScopDetect/parametric-multiply-in-scev-2.ll b/polly/test/ScopDetect/parametric-multiply-in-scev-2.ll index fc957a7f912c..6cb8a9ee5125 100644 --- a/polly/test/ScopDetect/parametric-multiply-in-scev-2.ll +++ b/polly/test/ScopDetect/parametric-multiply-in-scev-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK-NOT: Valid Region diff --git a/polly/test/ScopDetect/parametric-multiply-in-scev.ll b/polly/test/ScopDetect/parametric-multiply-in-scev.ll index 9c6e5ccc8f52..bb6dd6c73593 100644 --- a/polly/test/ScopDetect/parametric-multiply-in-scev.ll +++ b/polly/test/ScopDetect/parametric-multiply-in-scev.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; foo(float *A, long n, long k) { ; if (true) diff --git a/polly/test/ScopDetect/phi_with_multi_exiting_edges.ll b/polly/test/ScopDetect/phi_with_multi_exiting_edges.ll index 054de168d76b..c88dcfd860f4 100644 --- a/polly/test/ScopDetect/phi_with_multi_exiting_edges.ll +++ b/polly/test/ScopDetect/phi_with_multi_exiting_edges.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Region with an exit node that has a PHI node multiple incoming edges from ; inside the region. Motivation for supporting such cases in Polly. diff --git a/polly/test/ScopDetect/profitability-large-basic-blocks.ll b/polly/test/ScopDetect/profitability-large-basic-blocks.ll index e1650febf11c..7296812ad85c 100644 --- a/polly/test/ScopDetect/profitability-large-basic-blocks.ll +++ b/polly/test/ScopDetect/profitability-large-basic-blocks.ll @@ -1,12 +1,12 @@ ; RUN: opt %loadPolly -polly-process-unprofitable=false \ ; RUN: -polly-detect-profitability-min-per-loop-insts=40 \ -; RUN: -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=PROFITABLE +; RUN: '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=PROFITABLE ; RUN: opt %loadPolly -polly-process-unprofitable=true \ -; RUN: -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=PROFITABLE +; RUN: '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=PROFITABLE ; RUN: opt %loadPolly -polly-process-unprofitable=false \ -; RUN: -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=UNPROFITABLE +; RUN: '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=UNPROFITABLE ; UNPROFITABLE-NOT: Valid Region for Scop: ; PROFITABLE: Valid Region for Scop: diff --git a/polly/test/ScopDetect/profitability-two-nested-loops.ll b/polly/test/ScopDetect/profitability-two-nested-loops.ll index 525f91cbc2f4..9311fc87d378 100644 --- a/polly/test/ScopDetect/profitability-two-nested-loops.ll +++ b/polly/test/ScopDetect/profitability-two-nested-loops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Valid Region for Scop: next => bb3 ; diff --git a/polly/test/ScopDetect/remove_all_children.ll b/polly/test/ScopDetect/remove_all_children.ll index 6d5097b80607..a6b211ccfe0b 100644 --- a/polly/test/ScopDetect/remove_all_children.ll +++ b/polly/test/ScopDetect/remove_all_children.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" diff --git a/polly/test/ScopDetect/report-scop-location.ll b/polly/test/ScopDetect/report-scop-location.ll index 750699cbe763..03043faedc34 100644 --- a/polly/test/ScopDetect/report-scop-location.ll +++ b/polly/test/ScopDetect/report-scop-location.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-detect -polly-report -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-report -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-i64:64-f80:128-s:64-n8:16:32:64-S128" ; Function Attrs: nounwind uwtable diff --git a/polly/test/ScopDetect/restrict-undef-size-scopdetect.ll b/polly/test/ScopDetect/restrict-undef-size-scopdetect.ll index e94f1e7728c5..04d6b151ebba 100644 --- a/polly/test/ScopDetect/restrict-undef-size-scopdetect.ll +++ b/polly/test/ScopDetect/restrict-undef-size-scopdetect.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK-NOT: Valid Region for Scop: target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopDetect/run_time_alias_check.ll b/polly/test/ScopDetect/run_time_alias_check.ll index 672f3dfa6365..aa6ba8698fe9 100644 --- a/polly/test/ScopDetect/run_time_alias_check.ll +++ b/polly/test/ScopDetect/run_time_alias_check.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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" diff --git a/polly/test/ScopDetect/scev_remove_max.ll b/polly/test/ScopDetect/scev_remove_max.ll index 5353e06bdf2f..5aa121977cfe 100644 --- a/polly/test/ScopDetect/scev_remove_max.ll +++ b/polly/test/ScopDetect/scev_remove_max.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-detect < %s +; RUN: opt %loadPolly '-passes=print' < %s ; This test case helps to determine wether SCEVRemoveMax::remove produces ; an infinite loop and a segmentation fault, if it processes, for example, diff --git a/polly/test/ScopDetect/sequential_loops.ll b/polly/test/ScopDetect/sequential_loops.ll index e6ac38aa1604..df10da3aac36 100644 --- a/polly/test/ScopDetect/sequential_loops.ll +++ b/polly/test/ScopDetect/sequential_loops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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" @@ -13,7 +13,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 ; } define void @f1(ptr %A, i64 %N) nounwind { -; CHECK-LABEL: 'Polly - Detect static control parts (SCoPs)' for function 'f1' +; CHECK-LABEL: Detected Scops in Function f1 entry: fence seq_cst br label %for.i.1 @@ -60,7 +60,7 @@ return: ; } define void @f2(ptr %A, i64 %N) nounwind { -; CHECK-LABEL: 'Polly - Detect static control parts (SCoPs)' for function 'f2' +; CHECK-LABEL: Detected Scops in Function f2 entry: fence seq_cst br label %for.i.1 diff --git a/polly/test/ScopDetect/simple_loop.ll b/polly/test/ScopDetect/simple_loop.ll index c8ed89a97d00..376a7dfa9f9b 100644 --- a/polly/test/ScopDetect/simple_loop.ll +++ b/polly/test/ScopDetect/simple_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/simple_loop_non_single_entry.ll b/polly/test/ScopDetect/simple_loop_non_single_entry.ll index 22adec5d2039..64e2a084188d 100644 --- a/polly/test/ScopDetect/simple_loop_non_single_entry.ll +++ b/polly/test/ScopDetect/simple_loop_non_single_entry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/simple_loop_non_single_exit.ll b/polly/test/ScopDetect/simple_loop_non_single_exit.ll index 71ac830cae7d..4c3a1aea1ad8 100644 --- a/polly/test/ScopDetect/simple_loop_non_single_exit.ll +++ b/polly/test/ScopDetect/simple_loop_non_single_exit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/simple_loop_non_single_exit_2.ll b/polly/test/ScopDetect/simple_loop_non_single_exit_2.ll index d9915dc130d5..ae4ffa7b4972 100644 --- a/polly/test/ScopDetect/simple_loop_non_single_exit_2.ll +++ b/polly/test/ScopDetect/simple_loop_non_single_exit_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/simple_loop_two_phi_nodes.ll b/polly/test/ScopDetect/simple_loop_two_phi_nodes.ll index 867bd50513f0..a6bca0ec9d73 100644 --- a/polly/test/ScopDetect/simple_loop_two_phi_nodes.ll +++ b/polly/test/ScopDetect/simple_loop_two_phi_nodes.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/simple_loop_with_param.ll b/polly/test/ScopDetect/simple_loop_with_param.ll index 1ae5c6608739..ab48709d290d 100644 --- a/polly/test/ScopDetect/simple_loop_with_param.ll +++ b/polly/test/ScopDetect/simple_loop_with_param.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=PHI +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=PHI ; void f(long A[], long N, long *init_ptr) { ; long i, j; diff --git a/polly/test/ScopDetect/simple_loop_with_param_2.ll b/polly/test/ScopDetect/simple_loop_with_param_2.ll index 1a4750621c19..baa647489543 100644 --- a/polly/test/ScopDetect/simple_loop_with_param_2.ll +++ b/polly/test/ScopDetect/simple_loop_with_param_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long A[], int N, int *init_ptr) { ; long i, j; diff --git a/polly/test/ScopDetect/simple_non_single_entry.ll b/polly/test/ScopDetect/simple_non_single_entry.ll index a1995a427903..1f1cc95147a5 100644 --- a/polly/test/ScopDetect/simple_non_single_entry.ll +++ b/polly/test/ScopDetect/simple_non_single_entry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/skip_function_attribute.ll b/polly/test/ScopDetect/skip_function_attribute.ll index e85dbd4c2b83..d30c042fb74e 100644 --- a/polly/test/ScopDetect/skip_function_attribute.ll +++ b/polly/test/ScopDetect/skip_function_attribute.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify polly skips this function ; diff --git a/polly/test/ScopDetect/srem_with_parametric_divisor.ll b/polly/test/ScopDetect/srem_with_parametric_divisor.ll index 4b5c3b04c2ce..9a6352b9afe6 100644 --- a/polly/test/ScopDetect/srem_with_parametric_divisor.ll +++ b/polly/test/ScopDetect/srem_with_parametric_divisor.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK-NOT: Valid Region for Scop: ; diff --git a/polly/test/ScopDetect/statistics.ll b/polly/test/ScopDetect/statistics.ll index 64df3d081605..5789677325d8 100644 --- a/polly/test/ScopDetect/statistics.ll +++ b/polly/test/ScopDetect/statistics.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-detect -stats -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -stats -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScopDetect/switch-in-loop-patch.ll b/polly/test/ScopDetect/switch-in-loop-patch.ll index ab4729fc09a4..508f59ee398e 100644 --- a/polly/test/ScopDetect/switch-in-loop-patch.ll +++ b/polly/test/ScopDetect/switch-in-loop-patch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK-NOT: Valid diff --git a/polly/test/ScopDetectionDiagnostics/ReportAlias-01.ll b/polly/test/ScopDetectionDiagnostics/ReportAlias-01.ll index 97ba7f9634e9..8f575df22f84 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportAlias-01.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportAlias-01.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-use-runtime-alias-checks=false -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -polly-use-runtime-alias-checks=false -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1| FileCheck %s ;void f(int A[], int B[]) { ; for (int i=0; i<42; i++) diff --git a/polly/test/ScopDetectionDiagnostics/ReportEntry.ll b/polly/test/ScopDetectionDiagnostics/ReportEntry.ll index fc21e192f32c..f80b48fc3b22 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportEntry.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportEntry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-detect -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s ; CHECK: remark: :0:0: Scop contains function entry (not yet supported). diff --git a/polly/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll b/polly/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll index abace4ba520d..2d9175607ba4 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; #define N 1024 ; double invalidCall(double A[N]); diff --git a/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegion.ll b/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegion.ll index 8368a68b42f0..8f5f08fb27c1 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegion.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ;void foo(int a, int b) { diff --git a/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegionWithoutDebugLoc.ll b/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegionWithoutDebugLoc.ll index 82c6c33e287c..f5ca683f0fd5 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegionWithoutDebugLoc.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegionWithoutDebugLoc.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-detect -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s ; CHECK: remark: :0:0: Irreducible region encountered in control flow. diff --git a/polly/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll b/polly/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll index 35986b5e0b35..27d26e665193 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll @@ -1,15 +1,15 @@ ; RUN: opt %loadPolly \ ; RUN: -pass-remarks-missed="polly-detect" -polly-detect-track-failures \ -; RUN: -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output \ +; RUN: -polly-allow-nonaffine-loops=false '-passes=print' -disable-output \ ; RUN: < %s 2>&1| FileCheck %s --check-prefix=REJECTNONAFFINELOOPS ; RUN: opt %loadPolly \ ; RUN: -pass-remarks-missed="polly-detect" -polly-detect-track-failures \ -; RUN: -polly-allow-nonaffine-loops=true -polly-print-detect -disable-output \ +; RUN: -polly-allow-nonaffine-loops=true '-passes=print' -disable-output \ ; RUN: < %s 2>&1| FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS ; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" \ ; RUN: -polly-process-unprofitable=false \ ; RUN: -polly-detect-track-failures -polly-allow-nonaffine-loops=true \ -; RUN: -polly-allow-nonaffine -polly-print-detect -disable-output < %s 2>&1 \ +; RUN: -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=ALLOWNONAFFINEALL ; void f(int A[], int n) { diff --git a/polly/test/ScopDetectionDiagnostics/ReportLoopHasNoExit.ll b/polly/test/ScopDetectionDiagnostics/ReportLoopHasNoExit.ll index 5dbeaded45c9..a40b423f04fc 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportLoopHasNoExit.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportLoopHasNoExit.ll @@ -4,8 +4,8 @@ ; the PostDominatorTree. Infinite loops are postdominated ony by the virtual ; root, which causes them not to appear in regions in ScopDetection anymore. -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-allow-nonaffine-loops -polly-print-detect -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void func (int param0, int N, int *A) ; { diff --git a/polly/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll b/polly/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll index 634b63e6d44d..b5eaaea1327e 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1| FileCheck %s -; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -polly-delinearize=false -polly-detect-keep-going -disable-output < %s 2>&1| FileCheck %s -check-prefix=ALL -; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1| FileCheck %s -check-prefix=DELIN -; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -polly-detect-keep-going -disable-output < %s 2>&1| FileCheck %s -check-prefix=DELIN-ALL -; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -polly-allow-nonaffine -disable-output < %s 2>&1| FileCheck %s -check-prefix=NONAFFINE -; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -polly-allow-nonaffine -disable-output < %s 2>&1| FileCheck %s -check-prefix=NONAFFINE +; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -polly-delinearize=false -polly-detect-keep-going -disable-output < %s 2>&1| FileCheck %s -check-prefix=ALL +; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1| FileCheck %s -check-prefix=DELIN +; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -polly-detect-keep-going -disable-output < %s 2>&1| FileCheck %s -check-prefix=DELIN-ALL +; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1| FileCheck %s -check-prefix=NONAFFINE +; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1| FileCheck %s -check-prefix=NONAFFINE ; 1 void manyaccesses(float A[restrict], long n, float B[restrict][n]) ; 2 { diff --git a/polly/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll b/polly/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll index 23d8c9c061c9..369a464a0f77 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1| FileCheck %s ; void f(int A[]) { ; for(int i=0; i<42; ++i) diff --git a/polly/test/ScopDetectionDiagnostics/ReportUnprofitable.ll b/polly/test/ScopDetectionDiagnostics/ReportUnprofitable.ll index d35b7a28ba89..c606fc2b6921 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportUnprofitable.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportUnprofitable.ll @@ -1,9 +1,9 @@ ; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" \ -; RUN: -polly-detect-track-failures -polly-print-detect -disable-output \ +; RUN: -polly-detect-track-failures '-passes=print' -disable-output \ ; RUN: -polly-process-unprofitable=false < %s 2>&1| FileCheck %s ; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" \ -; RUN: -polly-detect-track-failures -polly-print-detect -disable-output \ +; RUN: -polly-detect-track-failures '-passes=print' -disable-output \ ; RUN: -polly-process-unprofitable=false < %s 2>&1 -pass-remarks-output=%t.yaml ; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopDetectionDiagnostics/ReportUnreachableInExit.ll b/polly/test/ScopDetectionDiagnostics/ReportUnreachableInExit.ll index 6c868db78ce7..5b20d6bea3dc 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportUnreachableInExit.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportUnreachableInExit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s \ ; RUN: -pass-remarks-missed="polly-detect" 2>&1 | FileCheck %s ; void f(long A[], long N) { diff --git a/polly/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll b/polly/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll index a82f56b7a5fa..ca10b0ac0256 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1| FileCheck %s ; struct b { ; double **b; diff --git a/polly/test/ScopDetectionDiagnostics/loop_has_multiple_exits.ll b/polly/test/ScopDetectionDiagnostics/loop_has_multiple_exits.ll index a0f2704b1372..5d0a2bf8f1d5 100644 --- a/polly/test/ScopDetectionDiagnostics/loop_has_multiple_exits.ll +++ b/polly/test/ScopDetectionDiagnostics/loop_has_multiple_exits.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -disable-output 2>&1 < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output 2>&1 < %s | FileCheck %s -match-full-lines ; ; Derived from test-suite/MultiSource/Benchmarks/BitBench/uuencode/uuencode.c ; diff --git a/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop-2.ll b/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop-2.ll index 667ed7d18ab5..4370380cb71e 100644 --- a/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop-2.ll +++ b/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s ; CHECK: remark: :0:0: Loop cannot be handled because not all latches are part of loop region. diff --git a/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop.ll b/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop.ll index 9dce56a3a3c4..05bd165d38cf 100644 --- a/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop.ll +++ b/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s ; CHECK: remark: :0:0: Loop cannot be handled because not all latches are part of loop region. ; CHECK: remark: :0:0: Loop cannot be handled because not all latches are part of loop region. diff --git a/polly/test/ScopInfo/20110312-Fail-without-basicaa.ll b/polly/test/ScopInfo/20110312-Fail-without-basicaa.ll index 94dd5824777c..6f08e433c4ee 100644 --- a/polly/test/ScopInfo/20110312-Fail-without-basicaa.ll +++ b/polly/test/ScopInfo/20110312-Fail-without-basicaa.ll @@ -1,5 +1,5 @@ ; This should be run without alias analysis enabled. -;RUN: opt %loadPolly -polly-scops -disable-output < %s +;RUN: opt %loadPolly '-passes=print' -disable-output < %s 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:32:32-n8:16:32" define i32 @main() nounwind { diff --git a/polly/test/ScopInfo/20111108-Parameter-not-detected.ll b/polly/test/ScopInfo/20111108-Parameter-not-detected.ll index f80177cb90e7..531e4149cffa 100644 --- a/polly/test/ScopInfo/20111108-Parameter-not-detected.ll +++ b/polly/test/ScopInfo/20111108-Parameter-not-detected.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" declare void @foo() diff --git a/polly/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll b/polly/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll index b55d635947e5..d92b35de2de7 100644 --- a/polly/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll +++ b/polly/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-a0:0-n32" diff --git a/polly/test/ScopInfo/2015-10-04-Crash-in-domain-generation.ll b/polly/test/ScopInfo/2015-10-04-Crash-in-domain-generation.ll index d4d931fd2e0c..05165ed02a90 100644 --- a/polly/test/ScopInfo/2015-10-04-Crash-in-domain-generation.ll +++ b/polly/test/ScopInfo/2015-10-04-Crash-in-domain-generation.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-scops -disable-output < %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/Alias-0.ll b/polly/test/ScopInfo/Alias-0.ll index 0fc4ad91b7db..4e7e8fa11a08 100644 --- a/polly/test/ScopInfo/Alias-0.ll +++ b/polly/test/ScopInfo/Alias-0.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA -; RUN: opt %loadPolly -polly-print-scops -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA +; RUN: opt %loadPolly '-passes=print' -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA +; RUN: opt %loadPolly '-passes=print' -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA ; REQUIRES: asserts 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/Alias-1.ll b/polly/test/ScopInfo/Alias-1.ll index eab8c062f4ba..7a734f810976 100644 --- a/polly/test/ScopInfo/Alias-1.ll +++ b/polly/test/ScopInfo/Alias-1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA -; RUN: opt %loadPolly -polly-print-scops -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA +; RUN: opt %loadPolly '-passes=print' -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA +; RUN: opt %loadPolly '-passes=print' -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA ; REQUIRES: asserts 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/Alias-2.ll b/polly/test/ScopInfo/Alias-2.ll index 64f1e0bc919d..9d3d44826237 100644 --- a/polly/test/ScopInfo/Alias-2.ll +++ b/polly/test/ScopInfo/Alias-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA -; RUN: opt %loadPolly -polly-print-scops -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA +; RUN: opt %loadPolly '-passes=print' -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA +; RUN: opt %loadPolly '-passes=print' -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA ; REQUIRES: asserts 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/Alias-3.ll b/polly/test/ScopInfo/Alias-3.ll index 5e9b94e692bc..83d68ddf371b 100644 --- a/polly/test/ScopInfo/Alias-3.ll +++ b/polly/test/ScopInfo/Alias-3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA -; RUN: opt %loadPolly -polly-print-scops -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA +; RUN: opt %loadPolly '-passes=print' -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA +; RUN: opt %loadPolly '-passes=print' -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA ; REQUIRES: asserts 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/Alias-4.ll b/polly/test/ScopInfo/Alias-4.ll index 4d5a91abb96f..bdcf729f4061 100644 --- a/polly/test/ScopInfo/Alias-4.ll +++ b/polly/test/ScopInfo/Alias-4.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -disable-basic-aa -polly-print-scops -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA -; RUN: opt %loadPolly -disable-basic-aa -polly-print-scops -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA +; RUN: opt %loadPolly -aa-pipeline= '-passes=print,print' -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA +; RUN: opt %loadPolly -aa-pipeline= '-passes=print,print' -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA ; REQUIRES: asserts 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/BoundChecks/single-loop.ll b/polly/test/ScopInfo/BoundChecks/single-loop.ll index bc96c907afc9..0ada318baabf 100644 --- a/polly/test/ScopInfo/BoundChecks/single-loop.ll +++ b/polly/test/ScopInfo/BoundChecks/single-loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST ; ; This only works after the post-dominator tree has been fixed. ; diff --git a/polly/test/ScopInfo/BoundChecks/two-loops.ll b/polly/test/ScopInfo/BoundChecks/two-loops.ll index 14e07f42a3ae..38ea23b80b9d 100644 --- a/polly/test/ScopInfo/BoundChecks/two-loops.ll +++ b/polly/test/ScopInfo/BoundChecks/two-loops.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output< %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly '-passes=print' -disable-output< %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST ; ; This only works after the post-dominator tree has fixed. ; XFAIL: * diff --git a/polly/test/ScopInfo/NonAffine/div_backedge.ll b/polly/test/ScopInfo/NonAffine/div_backedge.ll index a6aca032ef62..69af32d92325 100644 --- a/polly/test/ScopInfo/NonAffine/div_backedge.ll +++ b/polly/test/ScopInfo/NonAffine/div_backedge.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void foo(float *A) { ; for (long i = 1;; i++) { diff --git a/polly/test/ScopInfo/NonAffine/div_domain.ll b/polly/test/ScopInfo/NonAffine/div_domain.ll index f61c4eb459ed..27cc284f53c4 100644 --- a/polly/test/ScopInfo/NonAffine/div_domain.ll +++ b/polly/test/ScopInfo/NonAffine/div_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void foo(float *A) { ; for (long i = 0; i < 16; i++) { diff --git a/polly/test/ScopInfo/NonAffine/invariant_loads_dependent_in_non_affine_region.ll b/polly/test/ScopInfo/NonAffine/invariant_loads_dependent_in_non_affine_region.ll index f5d63dfb9d2c..4cf60324f99b 100644 --- a/polly/test/ScopInfo/NonAffine/invariant_loads_dependent_in_non_affine_region.ll +++ b/polly/test/ScopInfo/NonAffine/invariant_loads_dependent_in_non_affine_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, int *B, int *C) { ; for (int i = 0; i < 1000; i++) diff --git a/polly/test/ScopInfo/NonAffine/modulo_backedge.ll b/polly/test/ScopInfo/NonAffine/modulo_backedge.ll index dec63ca6813d..322720ae0633 100644 --- a/polly/test/ScopInfo/NonAffine/modulo_backedge.ll +++ b/polly/test/ScopInfo/NonAffine/modulo_backedge.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Domain := ; CHECK: { Stmt_for_body[i0] : 0 <= i0 <= 6 }; diff --git a/polly/test/ScopInfo/NonAffine/modulo_domain.ll b/polly/test/ScopInfo/NonAffine/modulo_domain.ll index f5ebec2b0346..cbd9d8901ce3 100644 --- a/polly/test/ScopInfo/NonAffine/modulo_domain.ll +++ b/polly/test/ScopInfo/NonAffine/modulo_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; TODO: The new domain generation cannot handle modulo domain constraints, ; hence modulo handling has been disabled completely. Once this is diff --git a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_1.ll b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_1.ll index 837d9b21b16e..e38de4ab6aba 100644 --- a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_1.ll +++ b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=SCALAR -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-process-unprofitable=false -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=PROFIT +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=SCALAR +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-process-unprofitable=false '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=PROFIT ; ; SCALAR: Function: f ; SCALAR-NEXT: Region: %bb1---%bb13 diff --git a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_2.ll b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_2.ll index e39569abc52d..4e792e5e4e50 100644 --- a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_2.ll +++ b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_2.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=ALL +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALL ; ; Here we have a non-affine loop (in the context of the loop nest) ; and also a non-affine access (A[k]). While we can always model the diff --git a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_3.ll b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_3.ll index 75dd7ac26bb3..1845505a5a2d 100644 --- a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_3.ll +++ b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_3.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=ALL +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALL ; ; Here we have a non-affine loop (in the context of the loop nest) ; and also a non-affine access (A[k]). While we can always model the diff --git a/polly/test/ScopInfo/NonAffine/non_affine_access_with_range_2.ll b/polly/test/ScopInfo/NonAffine/non_affine_access_with_range_2.ll index 34b04933af86..2ba4065770bd 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_access_with_range_2.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_access_with_range_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A) { ; for (int i = 0; i < 128; i++) diff --git a/polly/test/ScopInfo/NonAffine/non_affine_but_sdiv.ll b/polly/test/ScopInfo/NonAffine/non_affine_but_sdiv.ll index 9955c88b2cfd..8ba1f013fda4 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_but_sdiv.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_but_sdiv.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_for_body diff --git a/polly/test/ScopInfo/NonAffine/non_affine_but_srem.ll b/polly/test/ScopInfo/NonAffine/non_affine_but_srem.ll index b194ee762e9f..059129168bad 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_but_srem.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_but_srem.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void pos(float *A, long n) { ; for (long i = 0; i < 100; i++) diff --git a/polly/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll b/polly/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll index 1f55530b137d..a25b27297b0f 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-branches '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_affine_loop.ll b/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_affine_loop.ll index 3511362304b4..1f66b8a096c9 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_affine_loop.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_affine_loop.ll @@ -1,11 +1,11 @@ ; RUN: opt %loadPolly -polly-allow-nonaffine-branches \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -polly-allow-nonaffine-loops=true \ -; RUN: -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST +; RUN: '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST ; RUN: opt %loadPolly -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true \ -; RUN: -polly-print-scops -disable-output < %s | FileCheck %s \ +; RUN: '-passes=print' -disable-output < %s 2>&1 | FileCheck %s \ ; RUN: --check-prefix=ALL ; ; Negative test for INNERMOST. diff --git a/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_non_affine_loop.ll b/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_non_affine_loop.ll index c2e1e46f6f18..5127481dde29 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_non_affine_loop.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_non_affine_loop.ll @@ -1,16 +1,16 @@ ; RUN: opt %loadPolly -polly-allow-nonaffine-branches \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -polly-allow-nonaffine-loops=true \ -; RUN: -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST +; RUN: '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST ; RUN: opt %loadPolly -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true \ -; RUN: -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=ALL +; RUN: '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALL ; RUN: opt %loadPolly -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -polly-process-unprofitable=false \ ; RUN: -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true \ -; RUN: -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=PROFIT +; RUN: '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT ; ; Negative test for INNERMOST. ; At the moment we will optimistically assume A[i] in the conditional before the inner diff --git a/polly/test/ScopInfo/NonAffine/non_affine_float_compare.ll b/polly/test/ScopInfo/NonAffine/non_affine_float_compare.ll index c62447b6c15c..ced23ab8f8df 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_float_compare.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_float_compare.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-branches '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(float *A) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/ScopInfo/NonAffine/non_affine_loop_condition.ll b/polly/test/ScopInfo/NonAffine/non_affine_loop_condition.ll index 873b44b9c8cf..ce00233fd7af 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_loop_condition.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_loop_condition.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-process-unprofitable=false -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=PROFIT -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-detect-reductions=false -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=NO-REDUCTION +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-process-unprofitable=false '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-detect-reductions=false '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=NO-REDUCTION ; ; void f(int *A, int *C) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/ScopInfo/NonAffine/non_affine_loop_used_later.ll b/polly/test/ScopInfo/NonAffine/non_affine_loop_used_later.ll index 127bf80b9451..daf06a3b5f89 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_loop_used_later.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_loop_used_later.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-unprofitable-scalar-accs=true -polly-process-unprofitable=false -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-unprofitable-scalar-accs=true -polly-process-unprofitable=false '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT ; ; Verify that we over approximate the read acces of A[j] in the last statement as j is ; computed in a non-affine loop we do not model. diff --git a/polly/test/ScopInfo/NonAffine/non_affine_parametric_loop.ll b/polly/test/ScopInfo/NonAffine/non_affine_parametric_loop.ll index de011e29aeea..be94e0e3307e 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_parametric_loop.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_parametric_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; void foo(long n, double A[], int INDEX[]) { diff --git a/polly/test/ScopInfo/NonAffine/non_affine_region_guaranteed_non-entry.ll b/polly/test/ScopInfo/NonAffine/non_affine_region_guaranteed_non-entry.ll index 7303b4ea47fd..a4daca4d9f36 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_region_guaranteed_non-entry.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_region_guaranteed_non-entry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-detect -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-detect '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/NonAffine/whole-scop-non-affine-subregion-in-loop.ll b/polly/test/ScopInfo/NonAffine/whole-scop-non-affine-subregion-in-loop.ll index 4f54d03d43fb..ba9146a8eca7 100644 --- a/polly/test/ScopInfo/NonAffine/whole-scop-non-affine-subregion-in-loop.ll +++ b/polly/test/ScopInfo/NonAffine/whole-scop-non-affine-subregion-in-loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ; ; Regression test that triggered a memory leak at some point (24947). ; diff --git a/polly/test/ScopInfo/aliasing_conditional_alias_groups_1.ll b/polly/test/ScopInfo/aliasing_conditional_alias_groups_1.ll index dc59fbfc66a8..a2836c199514 100644 --- a/polly/test/ScopInfo/aliasing_conditional_alias_groups_1.ll +++ b/polly/test/ScopInfo/aliasing_conditional_alias_groups_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that there is no alias group because we either access A or B never both. ; diff --git a/polly/test/ScopInfo/aliasing_conditional_alias_groups_2.ll b/polly/test/ScopInfo/aliasing_conditional_alias_groups_2.ll index a19d60dd9147..15cea1c4f8cb 100644 --- a/polly/test/ScopInfo/aliasing_conditional_alias_groups_2.ll +++ b/polly/test/ScopInfo/aliasing_conditional_alias_groups_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that we create two alias groups since the minimal/maximal accesses ; depend on %b. diff --git a/polly/test/ScopInfo/aliasing_dead_access.ll b/polly/test/ScopInfo/aliasing_dead_access.ll index 2a725cf3c855..400fea0573a1 100644 --- a/polly/test/ScopInfo/aliasing_dead_access.ll +++ b/polly/test/ScopInfo/aliasing_dead_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that we do not create a SCoP if there is no statement executed. ; diff --git a/polly/test/ScopInfo/aliasing_many_arrays_to_compare.ll b/polly/test/ScopInfo/aliasing_many_arrays_to_compare.ll index 937d4ada3ec9..a1b954cb63ee 100644 --- a/polly/test/ScopInfo/aliasing_many_arrays_to_compare.ll +++ b/polly/test/ScopInfo/aliasing_many_arrays_to_compare.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output \ -; RUN: < %s | FileCheck %s --check-prefix=FOUND -; RUN: opt %loadPolly -polly-print-scops -disable-output \ -; RUN: -polly-rtc-max-arrays-per-group=3 < %s | FileCheck %s \ +; RUN: opt %loadPolly '-passes=print,print' -disable-output \ +; RUN: < %s 2>&1 | FileCheck %s --check-prefix=FOUND +; RUN: opt %loadPolly '-passes=print,print' -disable-output \ +; RUN: -polly-rtc-max-arrays-per-group=3 < %s 2>&1 | FileCheck %s \ ; RUN: --check-prefix=IGNORED ; ; FOUND: Function: foo diff --git a/polly/test/ScopInfo/aliasing_many_read_only_acesses.ll b/polly/test/ScopInfo/aliasing_many_read_only_acesses.ll index c22cfe55e118..9447744a12a8 100644 --- a/polly/test/ScopInfo/aliasing_many_read_only_acesses.ll +++ b/polly/test/ScopInfo/aliasing_many_read_only_acesses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: { : } diff --git a/polly/test/ScopInfo/aliasing_multiple_alias_groups.ll b/polly/test/ScopInfo/aliasing_multiple_alias_groups.ll index 16cb3dc0f5ac..5c4a864ec777 100644 --- a/polly/test/ScopInfo/aliasing_multiple_alias_groups.ll +++ b/polly/test/ScopInfo/aliasing_multiple_alias_groups.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=NOAA -; RUN: opt %loadPolly -polly-print-scops -disable-output -tbaa < %s | FileCheck %s --check-prefix=TBAA +; RUN: opt %loadPolly '-passes=print' -disable-output -aa-pipeline= < %s 2>&1 | FileCheck %s --check-prefix=NOAA +; RUN: opt %loadPolly '-passes=print' -disable-output -aa-pipeline=tbaa < %s 2>&1 | FileCheck %s --check-prefix=TBAA ; ; void jd(int *Int0, int *Int1, float *Float0, float *Float1) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/ScopInfo/aliasing_with_non_affine_access.ll b/polly/test/ScopInfo/aliasing_with_non_affine_access.ll index 056b644cd5ed..76bc18e8ac53 100644 --- a/polly/test/ScopInfo/aliasing_with_non_affine_access.ll +++ b/polly/test/ScopInfo/aliasing_with_non_affine_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-ast -polly-process-unprofitable -polly-allow-nonaffine -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-process-unprofitable -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s ; ; @test1 ; Make sure we generate the correct aliasing check for a fixed-size memset operation. diff --git a/polly/test/ScopInfo/allow-all-parameters-dereferencable.ll b/polly/test/ScopInfo/allow-all-parameters-dereferencable.ll index d170a50e26fc..b37b560599ad 100644 --- a/polly/test/ScopInfo/allow-all-parameters-dereferencable.ll +++ b/polly/test/ScopInfo/allow-all-parameters-dereferencable.ll @@ -1,14 +1,14 @@ ; RUN: opt %loadPolly -disable-output -polly-invariant-load-hoisting \ ; RUN: -polly-allow-dereference-of-all-function-parameters \ -; RUN: -polly-print-scops < %s | FileCheck %s --check-prefix=SCOP +; RUN: '-passes=print' < %s 2>&1 | FileCheck %s --check-prefix=SCOP ; RUN: opt %loadPolly -S -polly-invariant-load-hoisting \ -; RUN: -polly-codegen < %s | FileCheck %s --check-prefix=CODE-RTC +; RUN: -passes=polly-codegen < %s 2>&1 | FileCheck %s --check-prefix=CODE-RTC ; RUN: opt %loadPolly -S -polly-invariant-load-hoisting \ ; RUN: -polly-allow-dereference-of-all-function-parameters \ -; RUN: -polly-codegen < %s | FileCheck %s --check-prefix=CODE +; RUN: -passes=polly-codegen < %s 2>&1 | FileCheck %s --check-prefix=CODE ; SCOP: Function: hoge ; SCOP-NEXT: Region: %bb15---%bb37 diff --git a/polly/test/ScopInfo/assume_gep_bounds.ll b/polly/test/ScopInfo/assume_gep_bounds.ll index d0ce47148071..7b7fd15e3346 100644 --- a/polly/test/ScopInfo/assume_gep_bounds.ll +++ b/polly/test/ScopInfo/assume_gep_bounds.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void foo(float A[][20][30], long n, long m, long p) { ; for (long i = 0; i < n; i++) diff --git a/polly/test/ScopInfo/assume_gep_bounds_2.ll b/polly/test/ScopInfo/assume_gep_bounds_2.ll index e327195da94c..3ada0f817300 100644 --- a/polly/test/ScopInfo/assume_gep_bounds_2.ll +++ b/polly/test/ScopInfo/assume_gep_bounds_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output < %s \ +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 \ ; RUN: -polly-precise-inbounds | FileCheck %s ; ; void foo(float A[restrict][20], float B[restrict][20], long n, long m, diff --git a/polly/test/ScopInfo/assume_gep_bounds_many.ll b/polly/test/ScopInfo/assume_gep_bounds_many.ll index 261491564fc2..2106b96ecd56 100644 --- a/polly/test/ScopInfo/assume_gep_bounds_many.ll +++ b/polly/test/ScopInfo/assume_gep_bounds_many.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -disable-output -polly-print-scops -polly-ignore-aliasing \ -; RUN: < %s | FileCheck %s +; RUN: opt %loadPolly -disable-output '-passes=print' -polly-ignore-aliasing \ +; RUN: < %s 2>&1 | FileCheck %s ; CHECK: Assumed Context: ; CHECK-NEXT: [n1_a, n1_b, n1_c, n1_d, n2_a, n2_b, n2_c, n2_d, n3_a, n3_b, n3_c, n3_d, n4_a, n4_b, n4_c, n4_d, n5_a, n5_b, n5_c, n5_d, n6_a, n6_b, n6_c, n6_d, n7_a, n7_b, n7_c, n7_d, n8_a, n8_b, n8_c, n8_d, n9_a, n9_b, n9_c, n9_d, p1_b, p1_c, p1_d, p2_b, p2_c, p2_d, p3_b, p3_c, p3_d, p4_b, p4_c, p4_d, p5_b, p5_c, p5_d, p6_b, p6_c, p6_d, p7_b, p7_c, p7_d, p8_b, p8_c, p8_d, p9_b, p9_c, p9_d] -> { : p1_b >= n1_b and p1_c >= n1_c and p1_d >= n1_d and p2_b >= n2_b and p2_c >= n2_c and p2_d >= n2_d and p3_b >= n3_b and p3_c >= n3_c and p3_d >= n3_d and p4_b >= n4_b and p4_c >= n4_c and p4_d >= n4_d and p5_b >= n5_b and p5_c >= n5_c and p5_d >= n5_d and p6_b >= n6_b and p6_c >= n6_c and p6_d >= n6_d and p7_b >= n7_b and p7_c >= n7_c and p7_d >= n7_d and p8_b >= n8_b and p8_c >= n8_c and p8_d >= n8_d and p9_b >= n9_b and p9_c >= n9_c and p9_d >= n9_d } diff --git a/polly/test/ScopInfo/avoid_new_parameters_from_geps.ll b/polly/test/ScopInfo/avoid_new_parameters_from_geps.ll index 0e17eb1d3668..e81b791f9312 100644 --- a/polly/test/ScopInfo/avoid_new_parameters_from_geps.ll +++ b/polly/test/ScopInfo/avoid_new_parameters_from_geps.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that we do no introduce a parameter here that is actually not needed. ; diff --git a/polly/test/ScopInfo/bool-addrec.ll b/polly/test/ScopInfo/bool-addrec.ll index 1924a4b5266b..51687cd9caa5 100644 --- a/polly/test/ScopInfo/bool-addrec.ll +++ b/polly/test/ScopInfo/bool-addrec.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -disable-output -polly-print-ast -polly-process-unprofitable < %s | FileCheck %s +; RUN: opt %loadPolly -disable-output '-passes=print' -polly-process-unprofitable < %s 2>&1 | FileCheck %s ; CHECK: for (int c0 = 0; c0 <= 19999; c0 += 1) { ; CHECK-NEXT: if (c0 % 2 == 0) diff --git a/polly/test/ScopInfo/bounded_loop_assumptions.ll b/polly/test/ScopInfo/bounded_loop_assumptions.ll index d472c7586c53..6b8acfc97c60 100644 --- a/polly/test/ScopInfo/bounded_loop_assumptions.ll +++ b/polly/test/ScopInfo/bounded_loop_assumptions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; The assumed context is tricky here as the equality test for the inner loop ; allows an "unbounded" loop trip count. We assume that does not happen, thus diff --git a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-2.ll b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-2.ll index 5c5f264aab60..bbf151f0206a 100644 --- a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-2.ll +++ b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-2.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | \ ; RUN: FileCheck %s -check-prefix=DETECT -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | \ ; RUN: FileCheck %s -check-prefix=SCOP ; DETECT: Valid Region for Scop: loop => barrier diff --git a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-3.ll b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-3.ll index d69d3a16c0d7..9b72a74e8628 100644 --- a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-3.ll +++ b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-3.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | \ ; RUN: FileCheck %s -check-prefix=NONAFFINE -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output \ -; RUN: -polly-allow-nonaffine-branches=false < %s | \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output \ +; RUN: -polly-allow-nonaffine-branches=false < %s 2>&1 | \ ; RUN: FileCheck %s -check-prefix=NO-NONEAFFINE ; NONAFFINE: Statements { diff --git a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations.ll b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations.ll index 57918fa5c92d..c6b1cddeaf85 100644 --- a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations.ll +++ b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | \ +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | \ ; RUN: FileCheck %s -check-prefix=NONAFFINE -; RUN: opt %loadPolly -polly-print-scops -disable-output \ -; RUN: -polly-allow-nonaffine-branches=false < %s | \ +; RUN: opt %loadPolly '-passes=print,print' -disable-output \ +; RUN: -polly-allow-nonaffine-branches=false < %s 2>&1 | \ ; RUN: FileCheck %s -check-prefix=NO-NONEAFFINE ; NONAFFINE-NOT: Statements diff --git a/polly/test/ScopInfo/bug_2010_10_22.ll b/polly/test/ScopInfo/bug_2010_10_22.ll index 7ba996b6d0f1..2e492e7633a0 100644 --- a/polly/test/ScopInfo/bug_2010_10_22.ll +++ b/polly/test/ScopInfo/bug_2010_10_22.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %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-n8:16:32:64" diff --git a/polly/test/ScopInfo/bug_2011_1_5.ll b/polly/test/ScopInfo/bug_2011_1_5.ll index 95c25f9d9cdb..ce815e57e627 100644 --- a/polly/test/ScopInfo/bug_2011_1_5.ll +++ b/polly/test/ScopInfo/bug_2011_1_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ; Bug description: Alias Analysis thinks IntToPtrInst aliases with alloca instructions created by IndependentBlocks Pass. ; This will trigger the assertion when we are verifying the SCoP after IndependentBlocks. diff --git a/polly/test/ScopInfo/bug_scev_not_fully_eval.ll b/polly/test/ScopInfo/bug_scev_not_fully_eval.ll index 89d5f318829e..8711f8e58a21 100644 --- a/polly/test/ScopInfo/bug_scev_not_fully_eval.ll +++ b/polly/test/ScopInfo/bug_scev_not_fully_eval.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | not FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | not 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-n8:16:32:64" @edge.8265 = external global [72 x i32], align 32 ; [#uses=1] diff --git a/polly/test/ScopInfo/cfg_consequences.ll b/polly/test/ScopInfo/cfg_consequences.ll index 84f94b135735..bd23ec7fc3bf 100644 --- a/polly/test/ScopInfo/cfg_consequences.ll +++ b/polly/test/ScopInfo/cfg_consequences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void consequences(int *A, int bool_cond, int lhs, int rhs) { ; diff --git a/polly/test/ScopInfo/complex-branch-structure.ll b/polly/test/ScopInfo/complex-branch-structure.ll index 24ebdcf213f8..69eb716e6877 100644 --- a/polly/test/ScopInfo/complex-branch-structure.ll +++ b/polly/test/ScopInfo/complex-branch-structure.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; We build a scop of the following form to check that the domain construction diff --git a/polly/test/ScopInfo/complex-condition.ll b/polly/test/ScopInfo/complex-condition.ll index 31d34b033725..348446a40007 100644 --- a/polly/test/ScopInfo/complex-condition.ll +++ b/polly/test/ScopInfo/complex-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/complex-expression.ll b/polly/test/ScopInfo/complex-expression.ll index 1822c9de852a..1340b0e0c981 100644 --- a/polly/test/ScopInfo/complex-expression.ll +++ b/polly/test/ScopInfo/complex-expression.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/complex-loop-nesting.ll b/polly/test/ScopInfo/complex-loop-nesting.ll index 97a9bfd939d5..a0e4a1e92050 100644 --- a/polly/test/ScopInfo/complex-loop-nesting.ll +++ b/polly/test/ScopInfo/complex-loop-nesting.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/complex-successor-structure-2.ll b/polly/test/ScopInfo/complex-successor-structure-2.ll index 6bb7bb14a8cc..eceadc818b48 100644 --- a/polly/test/ScopInfo/complex-successor-structure-2.ll +++ b/polly/test/ScopInfo/complex-successor-structure-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s diff --git a/polly/test/ScopInfo/complex-successor-structure-3.ll b/polly/test/ScopInfo/complex-successor-structure-3.ll index 14c3fc1babeb..b5ba6958c57b 100644 --- a/polly/test/ScopInfo/complex-successor-structure-3.ll +++ b/polly/test/ScopInfo/complex-successor-structure-3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -disable-output -polly-print-scops \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s +; RUN: opt %loadPolly -disable-output '-passes=print' \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s ; ; Check that propagation of domains from A(X) to A(X+1) will keep the ; domains small and concise. diff --git a/polly/test/ScopInfo/complex-successor-structure.ll b/polly/test/ScopInfo/complex-successor-structure.ll index 364344045a6a..f39ab9bfa29b 100644 --- a/polly/test/ScopInfo/complex-successor-structure.ll +++ b/polly/test/ScopInfo/complex-successor-structure.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s diff --git a/polly/test/ScopInfo/complex_domain_binary_condition.ll b/polly/test/ScopInfo/complex_domain_binary_condition.ll index cec26855debb..4dd39733eae2 100644 --- a/polly/test/ScopInfo/complex_domain_binary_condition.ll +++ b/polly/test/ScopInfo/complex_domain_binary_condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Low complexity assumption: { : false } diff --git a/polly/test/ScopInfo/complex_execution_context.ll b/polly/test/ScopInfo/complex_execution_context.ll index 164254308fa9..c58d6fe9a50a 100644 --- a/polly/test/ScopInfo/complex_execution_context.ll +++ b/polly/test/ScopInfo/complex_execution_context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/cond_constant_in_loop.ll b/polly/test/ScopInfo/cond_constant_in_loop.ll index ef7d857e1084..45cae34e1af2 100644 --- a/polly/test/ScopInfo/cond_constant_in_loop.ll +++ b/polly/test/ScopInfo/cond_constant_in_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ;void f(long a[], long N, long M) { ; long i, j, k; diff --git a/polly/test/ScopInfo/cond_in_loop.ll b/polly/test/ScopInfo/cond_in_loop.ll index 2d435f6a6a93..2101b25e4799 100644 --- a/polly/test/ScopInfo/cond_in_loop.ll +++ b/polly/test/ScopInfo/cond_in_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ;void f(long a[], long N, long M) { ; long i, j, k; diff --git a/polly/test/ScopInfo/condition-after-error-block-2.ll b/polly/test/ScopInfo/condition-after-error-block-2.ll index 695d864e483c..e3025d0ca259 100644 --- a/polly/test/ScopInfo/condition-after-error-block-2.ll +++ b/polly/test/ScopInfo/condition-after-error-block-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; Verify that we do not allow PHI nodes such as %phi, if they reference an error ; block and are used by anything else than a terminator instruction. diff --git a/polly/test/ScopInfo/condition-after-error-block-before-scop.ll b/polly/test/ScopInfo/condition-after-error-block-before-scop.ll index 184be3642f0c..7a4d1467de46 100644 --- a/polly/test/ScopInfo/condition-after-error-block-before-scop.ll +++ b/polly/test/ScopInfo/condition-after-error-block-before-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/polly/test/ScopInfo/condtion-after-error-block.ll b/polly/test/ScopInfo/condtion-after-error-block.ll index 92e743e2d879..1a8681f829e4 100644 --- a/polly/test/ScopInfo/condtion-after-error-block.ll +++ b/polly/test/ScopInfo/condtion-after-error-block.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; Verify that we allow scops containing uniform branch conditions, where all ; but one incoming block comes from an error condition. diff --git a/polly/test/ScopInfo/const_srem_sdiv.ll b/polly/test/ScopInfo/const_srem_sdiv.ll index 3acca980da70..cf243fc74a9a 100644 --- a/polly/test/ScopInfo/const_srem_sdiv.ll +++ b/polly/test/ScopInfo/const_srem_sdiv.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s ; ; See http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf ; diff --git a/polly/test/ScopInfo/constant-non-integer-branch-condition.ll b/polly/test/ScopInfo/constant-non-integer-branch-condition.ll index fc95a4cc7891..8c8beac8f304 100644 --- a/polly/test/ScopInfo/constant-non-integer-branch-condition.ll +++ b/polly/test/ScopInfo/constant-non-integer-branch-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; At some point this caused a problem in the domain generation as we ; assumed any constant branch condition to be valid. However, only constant diff --git a/polly/test/ScopInfo/constant_factor_in_parameter.ll b/polly/test/ScopInfo/constant_factor_in_parameter.ll index 1f0173c0edf9..ca7d094be300 100644 --- a/polly/test/ScopInfo/constant_factor_in_parameter.ll +++ b/polly/test/ScopInfo/constant_factor_in_parameter.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -disable-output -polly-print-scops < %s | FileCheck %s -; RUN: opt %loadPolly -disable-output -polly-print-function-scops < %s | FileCheck %s +; RUN: opt %loadPolly -disable-output '-passes=print' < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -disable-output '-passes=print' < %s 2>&1 | FileCheck %s ; ; Check that the constant part of the N * M * 4 expression is not part of the ; parameter but explicit in the access function. This can avoid existentially diff --git a/polly/test/ScopInfo/constant_functions_outside_scop_as_unknown.ll b/polly/test/ScopInfo/constant_functions_outside_scop_as_unknown.ll index 38b2b8958e2f..afb8ec3eabed 100644 --- a/polly/test/ScopInfo/constant_functions_outside_scop_as_unknown.ll +++ b/polly/test/ScopInfo/constant_functions_outside_scop_as_unknown.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" diff --git a/polly/test/ScopInfo/constant_start_integer.ll b/polly/test/ScopInfo/constant_start_integer.ll index aa6640c98f73..94e43b324f98 100644 --- a/polly/test/ScopInfo/constant_start_integer.ll +++ b/polly/test/ScopInfo/constant_start_integer.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; void foo(float *input) { diff --git a/polly/test/ScopInfo/debug_call.ll b/polly/test/ScopInfo/debug_call.ll index 93b5bc520a00..ba74e68c9f36 100644 --- a/polly/test/ScopInfo/debug_call.ll +++ b/polly/test/ScopInfo/debug_call.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-debug-func=dbg_printf -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-debug-func=dbg_printf '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; ; Check that the call to dbg_printf is accepted as a debug-function. ; diff --git a/polly/test/ScopInfo/delinearize-together-all-data-refs.ll b/polly/test/ScopInfo/delinearize-together-all-data-refs.ll index 108392b27f07..ac17ba005bd0 100644 --- a/polly/test/ScopInfo/delinearize-together-all-data-refs.ll +++ b/polly/test/ScopInfo/delinearize-together-all-data-refs.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void foo(long n, long m, long o, double A[n][m][o]) { ; for (long i = 0; i < n-3; i++) diff --git a/polly/test/ScopInfo/div_by_zero.ll b/polly/test/ScopInfo/div_by_zero.ll index 2205b85a9ebc..74380f7a4c71 100644 --- a/polly/test/ScopInfo/div_by_zero.ll +++ b/polly/test/ScopInfo/div_by_zero.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/do-not-model-error-block-accesses.ll b/polly/test/ScopInfo/do-not-model-error-block-accesses.ll index 997e0d4b37cf..563e5d11474b 100644 --- a/polly/test/ScopInfo/do-not-model-error-block-accesses.ll +++ b/polly/test/ScopInfo/do-not-model-error-block-accesses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ; Check that we do not crash on this input. Earlier this indeed crashed as ; we tried to model the access functions in an error block. diff --git a/polly/test/ScopInfo/eager-binary-and-or-conditions.ll b/polly/test/ScopInfo/eager-binary-and-or-conditions.ll index e9ad63c51b85..ee846d3ca98c 100644 --- a/polly/test/ScopInfo/eager-binary-and-or-conditions.ll +++ b/polly/test/ScopInfo/eager-binary-and-or-conditions.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output< %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output< %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s ; ; void or(float *A, long n, long m) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/early_exit_for_complex_domains.ll b/polly/test/ScopInfo/early_exit_for_complex_domains.ll index a72ea031c236..2a8e6d15fea4 100644 --- a/polly/test/ScopInfo/early_exit_for_complex_domains.ll +++ b/polly/test/ScopInfo/early_exit_for_complex_domains.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ; ; Check we do not crash. ; diff --git a/polly/test/ScopInfo/error-blocks-1.ll b/polly/test/ScopInfo/error-blocks-1.ll index 03353edf297a..e0b59e01d13d 100644 --- a/polly/test/ScopInfo/error-blocks-1.ll +++ b/polly/test/ScopInfo/error-blocks-1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Context: ; CHECK-NEXT: [N] -> { : -2147483648 <= N <= 2147483647 } diff --git a/polly/test/ScopInfo/error-blocks-2.ll b/polly/test/ScopInfo/error-blocks-2.ll index 29095dacacfb..59096e3315f5 100644 --- a/polly/test/ScopInfo/error-blocks-2.ll +++ b/polly/test/ScopInfo/error-blocks-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/escaping_empty_scop.ll b/polly/test/ScopInfo/escaping_empty_scop.ll index 8837e19eefe4..e27130af952a 100644 --- a/polly/test/ScopInfo/escaping_empty_scop.ll +++ b/polly/test/ScopInfo/escaping_empty_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void g(); ; int f(int *A) { diff --git a/polly/test/ScopInfo/exit-phi-1.ll b/polly/test/ScopInfo/exit-phi-1.ll index 8e6c5fb9e211..41b56dde043a 100644 --- a/polly/test/ScopInfo/exit-phi-1.ll +++ b/polly/test/ScopInfo/exit-phi-1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -passes=polly-codegen -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN ; ; Check for correct code generation of exit PHIs, even if the same PHI value ; is used again inside the the SCoP. diff --git a/polly/test/ScopInfo/exit-phi-2.ll b/polly/test/ScopInfo/exit-phi-2.ll index d218d5fa039b..c2b463f657ea 100644 --- a/polly/test/ScopInfo/exit-phi-2.ll +++ b/polly/test/ScopInfo/exit-phi-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that there is no MK_ExitPHI READ access. ; diff --git a/polly/test/ScopInfo/exit_phi_accesses-2.ll b/polly/test/ScopInfo/exit_phi_accesses-2.ll index e376f0df9d54..cfc385dc6aba 100644 --- a/polly/test/ScopInfo/exit_phi_accesses-2.ll +++ b/polly/test/ScopInfo/exit_phi_accesses-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK-LABEL: Function: foo ; diff --git a/polly/test/ScopInfo/exit_phi_accesses.ll b/polly/test/ScopInfo/exit_phi_accesses.ll index f4fbe31f6b24..c598e411739c 100644 --- a/polly/test/ScopInfo/exit_phi_accesses.ll +++ b/polly/test/ScopInfo/exit_phi_accesses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; Check that PHI nodes only create PHI access and nothing else (e.g. unnecessary ; SCALAR accesses). In this case, for a PHI in the exit node, hence there is no diff --git a/polly/test/ScopInfo/expensive-boundary-context.ll b/polly/test/ScopInfo/expensive-boundary-context.ll index 7001b96acd21..dd660c543f2c 100644 --- a/polly/test/ScopInfo/expensive-boundary-context.ll +++ b/polly/test/ScopInfo/expensive-boundary-context.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output \ -; RUN: < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output \ +; RUN: < %s 2>&1 | FileCheck %s ; CHECK-NOT: Assumed Context: target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/extract_constant_factor_introduces_new_parameter.ll b/polly/test/ScopInfo/extract_constant_factor_introduces_new_parameter.ll index 89ca344fdf54..9475a870e4b5 100644 --- a/polly/test/ScopInfo/extract_constant_factor_introduces_new_parameter.ll +++ b/polly/test/ScopInfo/extract_constant_factor_introduces_new_parameter.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ; CHECK: Valid Region for Scop: bb10 => bb16 diff --git a/polly/test/ScopInfo/full-function.ll b/polly/test/ScopInfo/full-function.ll index 670472576fe7..bb2d12fb0e3f 100644 --- a/polly/test/ScopInfo/full-function.ll +++ b/polly/test/ScopInfo/full-function.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output -polly-detect-full-functions < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output -polly-detect-full-functions < %s 2>&1 \ ; RUN: | FileCheck %s -check-prefix=FULL -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s -check-prefix=WITHOUT-FULL ; FULL: Region: %bb---FunctionExit diff --git a/polly/test/ScopInfo/granularity_same_name.ll b/polly/test/ScopInfo/granularity_same_name.ll index 1ebf5c6f71a2..4e8dd1840890 100644 --- a/polly/test/ScopInfo/granularity_same_name.ll +++ b/polly/test/ScopInfo/granularity_same_name.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-use-llvm-names=0 -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines -check-prefix=IDX -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-use-llvm-names=1 -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines -check-prefix=BB -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-use-llvm-names=0 -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines -check-prefix=IDX -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-use-llvm-names=1 -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines -check-prefix=BB +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-use-llvm-names=0 '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=IDX +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-use-llvm-names=1 '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=BB +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-use-llvm-names=0 '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=IDX +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-use-llvm-names=1 '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=BB ; ; Check that the statement has the same name, regardless of how the ; basic block is split into multiple statements. diff --git a/polly/test/ScopInfo/granularity_scalar-indep.ll b/polly/test/ScopInfo/granularity_scalar-indep.ll index fe509b468272..b28060d87180 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; ; Split a block into two independent statements that share no scalar. ; This case has the instructions of the two statements interleaved, such that diff --git a/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi1.ll b/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi1.ll index 56bc11aed28d..fb2bfa663ef2 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi1.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; ; Two PHIs, cross-referencing each other. The PHI READs must be carried-out ; before the PHI WRITEs to ensure that the value when entering the block is diff --git a/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi2.ll b/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi2.ll index f46cf4e6a0a2..aa066b5cd46c 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi2.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; ; Two PHIs, cross-referencing each other. The PHI READs must be carried-out ; before the PHI WRITEs to ensure that the value when entering the block is diff --git a/polly/test/ScopInfo/granularity_scalar-indep_epilogue.ll b/polly/test/ScopInfo/granularity_scalar-indep_epilogue.ll index e202e38f0844..da326191762a 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_epilogue.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_epilogue.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; ; Split a block into two independent statements that share no scalar. ; This case has an independent statement just for PHI writes. diff --git a/polly/test/ScopInfo/granularity_scalar-indep_epilogue_last.ll b/polly/test/ScopInfo/granularity_scalar-indep_epilogue_last.ll index 40af34bfb067..19484319ee35 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_epilogue_last.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_epilogue_last.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; ; Check that the PHI Write of value that is defined in the same basic ; block is in the statement where it is defined. diff --git a/polly/test/ScopInfo/granularity_scalar-indep_noepilogue.ll b/polly/test/ScopInfo/granularity_scalar-indep_noepilogue.ll index 9a0d207c0c2a..484156abdbcd 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_noepilogue.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_noepilogue.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; ; This case has no explicit epilogue for PHI writes because it would ; have a scalar dependency to the previous statement. diff --git a/polly/test/ScopInfo/granularity_scalar-indep_ordered-2.ll b/polly/test/ScopInfo/granularity_scalar-indep_ordered-2.ll index d093806bc9cc..ec69b8000bf5 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_ordered-2.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_ordered-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; ; This case should be split into two statements because {X[0], Y[0]} ; and {A[0], B[0]} do not intersect. diff --git a/polly/test/ScopInfo/granularity_scalar-indep_ordered.ll b/polly/test/ScopInfo/granularity_scalar-indep_ordered.ll index b1d2936882aa..a7f8e2697cac 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_ordered.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_ordered.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; ; This case cannot be split into two statements because the order of ; loads and store would be violated. diff --git a/polly/test/ScopInfo/i1_params.ll b/polly/test/ScopInfo/i1_params.ll index 1cb1329b08f9..28eb838b56b0 100644 --- a/polly/test/ScopInfo/i1_params.ll +++ b/polly/test/ScopInfo/i1_params.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that both a signed as well as an unsigned extended i1 parameter ; is represented correctly. diff --git a/polly/test/ScopInfo/infeasible-rtc.ll b/polly/test/ScopInfo/infeasible-rtc.ll index ef96627e640e..5540b2365ce3 100644 --- a/polly/test/ScopInfo/infeasible-rtc.ll +++ b/polly/test/ScopInfo/infeasible-rtc.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s -check-prefix=DETECT -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s -check-prefix=SCOPS 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-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/infeasible_invalid_context.ll b/polly/test/ScopInfo/infeasible_invalid_context.ll index 2c299f06c12e..86ecb4053d5a 100644 --- a/polly/test/ScopInfo/infeasible_invalid_context.ll +++ b/polly/test/ScopInfo/infeasible_invalid_context.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s -check-prefix=DETECT -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s -check-prefix=SCOPS ; DETECT: Valid Region for Scop: if.end116 => for.inc216 diff --git a/polly/test/ScopInfo/int2ptr_ptr2int.ll b/polly/test/ScopInfo/int2ptr_ptr2int.ll index 9fadc5a8eb28..f375e79e807d 100644 --- a/polly/test/ScopInfo/int2ptr_ptr2int.ll +++ b/polly/test/ScopInfo/int2ptr_ptr2int.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen < %s 2>&1 | FileCheck %s --check-prefix=IR ; ; void f(long *A, long *ptr, long val) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/int2ptr_ptr2int_2.ll b/polly/test/ScopInfo/int2ptr_ptr2int_2.ll index 97878f7091b1..1c8251361b51 100644 --- a/polly/test/ScopInfo/int2ptr_ptr2int_2.ll +++ b/polly/test/ScopInfo/int2ptr_ptr2int_2.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-print-scops \ -; RUN: -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -S -polly-codegen \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly '-passes=print' \ +; RUN: -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -S -passes=polly-codegen \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s --check-prefix=IR ; ; void f(long *A, long *B, long *ptr, long val) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/integers.ll b/polly/test/ScopInfo/integers.ll index b608bf84cffa..87bc31e214ff 100644 --- a/polly/test/ScopInfo/integers.ll +++ b/polly/test/ScopInfo/integers.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; Check that we correctly convert integers to isl values. diff --git a/polly/test/ScopInfo/inter-error-bb-dependence.ll b/polly/test/ScopInfo/inter-error-bb-dependence.ll index 4e23de7e6a99..00f482267a0b 100644 --- a/polly/test/ScopInfo/inter-error-bb-dependence.ll +++ b/polly/test/ScopInfo/inter-error-bb-dependence.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops -disable-output < %s 2>&1 > /dev/null | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 > /dev/null | FileCheck %s ; ; Error statements (%bb33) do not require their uses to be verified. ; In this case it uses %tmp32 from %bb31 which is not available because diff --git a/polly/test/ScopInfo/inter_bb_scalar_dep.ll b/polly/test/ScopInfo/inter_bb_scalar_dep.ll index 456f7a773f04..0af814516038 100644 --- a/polly/test/ScopInfo/inter_bb_scalar_dep.ll +++ b/polly/test/ScopInfo/inter_bb_scalar_dep.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-scops \ -; RUN: -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' \ +; RUN: -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; void f(long A[], int N, int *init_ptr) { ; long i, j; diff --git a/polly/test/ScopInfo/intra-non-affine-stmt-phi-node.ll b/polly/test/ScopInfo/intra-non-affine-stmt-phi-node.ll index 859972b27402..0fc635abae45 100644 --- a/polly/test/ScopInfo/intra-non-affine-stmt-phi-node.ll +++ b/polly/test/ScopInfo/intra-non-affine-stmt-phi-node.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output \ -; RUN: < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output \ +; RUN: < %s 2>&1 | FileCheck %s ; CHECK: Statements { ; CHECK-NEXT: Stmt_loop__TO__backedge diff --git a/polly/test/ScopInfo/intra_and_inter_bb_scalar_dep.ll b/polly/test/ScopInfo/intra_and_inter_bb_scalar_dep.ll index 37f4e0513ed3..209c475b5bbb 100644 --- a/polly/test/ScopInfo/intra_and_inter_bb_scalar_dep.ll +++ b/polly/test/ScopInfo/intra_and_inter_bb_scalar_dep.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s ; void f(long A[], int N, int *init_ptr) { ; long i, j; diff --git a/polly/test/ScopInfo/intra_bb_scalar_dep.ll b/polly/test/ScopInfo/intra_bb_scalar_dep.ll index 0252273d3107..8ad5ac175802 100644 --- a/polly/test/ScopInfo/intra_bb_scalar_dep.ll +++ b/polly/test/ScopInfo/intra_bb_scalar_dep.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s ; void f(long A[], int N, int *init_ptr) { ; long i, j; diff --git a/polly/test/ScopInfo/intrinsics.ll b/polly/test/ScopInfo/intrinsics.ll index 853429341381..8b484cc21b52 100644 --- a/polly/test/ScopInfo/intrinsics.ll +++ b/polly/test/ScopInfo/intrinsics.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-print-instructions -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-print-instructions -disable-output < %s 2>&1 | FileCheck %s ; ; Verify that we remove the ignored intrinsics from the instruction list. ; diff --git a/polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll b/polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll index 8d0de03e9866..d9f64d5eba9c 100644 --- a/polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll +++ b/polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ; ; This crashed at some point as we place %1 and %4 in the same equivalence class ; for invariant loads and when we remap SCEVs to use %4 instead of %1 AddRec SCEVs diff --git a/polly/test/ScopInfo/invalidate_iterator_during_MA_removal.ll b/polly/test/ScopInfo/invalidate_iterator_during_MA_removal.ll index dcb0ad301ba3..0f48052a40e1 100644 --- a/polly/test/ScopInfo/invalidate_iterator_during_MA_removal.ll +++ b/polly/test/ScopInfo/invalidate_iterator_during_MA_removal.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ; ; Check that no invalidated iterator is accessed while elements from ; the list of MemoryAccesses are removed. diff --git a/polly/test/ScopInfo/invariant-load-instlist.ll b/polly/test/ScopInfo/invariant-load-instlist.ll index 7f4cf050f064..b65d843f0ab6 100644 --- a/polly/test/ScopInfo/invariant-load-instlist.ll +++ b/polly/test/ScopInfo/invariant-load-instlist.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ; The load is a required invariant load and at the same time used in a store. ; Polly used to add two MemoryAccesses for it which caused an assertion to fail. diff --git a/polly/test/ScopInfo/invariant-loads-leave-read-only-statements.ll b/polly/test/ScopInfo/invariant-loads-leave-read-only-statements.ll index b97fe22e076e..12a72bd47fdf 100644 --- a/polly/test/ScopInfo/invariant-loads-leave-read-only-statements.ll +++ b/polly/test/ScopInfo/invariant-loads-leave-read-only-statements.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s ; CHECK: Statements { ; CHECK-NEXT: Stmt_L_4 diff --git a/polly/test/ScopInfo/invariant_load.ll b/polly/test/ScopInfo/invariant_load.ll index fcea77e19b85..47501022247e 100644 --- a/polly/test/ScopInfo/invariant_load.ll +++ b/polly/test/ScopInfo/invariant_load.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type.ll b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type.ll index 100a8db2a9d1..c402f90cbdd1 100644 --- a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type.ll +++ b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN ; ; struct { ; int a; diff --git a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_escaping.ll b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_escaping.ll index e31deb6fd472..435c9a575d73 100644 --- a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_escaping.ll +++ b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_escaping.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN ; ; struct { ; int a; diff --git a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer.ll b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer.ll index bbf6d69a5fbb..a2f43f2348b8 100644 --- a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer.ll +++ b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN ; ; int U; ; void f(int *A) { diff --git a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer_escaping.ll b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer_escaping.ll index 011c2fe3d549..412e62f26511 100644 --- a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer_escaping.ll +++ b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer_escaping.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN ; ; int U; ; int f(int *A) { diff --git a/polly/test/ScopInfo/invariant_load_addrec_sum.ll b/polly/test/ScopInfo/invariant_load_addrec_sum.ll index 09b158d342ed..8026d351fdf7 100644 --- a/polly/test/ScopInfo/invariant_load_addrec_sum.ll +++ b/polly/test/ScopInfo/invariant_load_addrec_sum.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Region: %entry.split---%if.end ; CHECK: Invariant Accesses: { diff --git a/polly/test/ScopInfo/invariant_load_base_pointer.ll b/polly/test/ScopInfo/invariant_load_base_pointer.ll index ddf11d892adb..7bf9c5a44788 100644 --- a/polly/test/ScopInfo/invariant_load_base_pointer.ll +++ b/polly/test/ScopInfo/invariant_load_base_pointer.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_base_pointer_conditional.ll b/polly/test/ScopInfo/invariant_load_base_pointer_conditional.ll index 07f2c3768b0a..42dfc7b3885a 100644 --- a/polly/test/ScopInfo/invariant_load_base_pointer_conditional.ll +++ b/polly/test/ScopInfo/invariant_load_base_pointer_conditional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_base_pointer_in_conditional.ll b/polly/test/ScopInfo/invariant_load_base_pointer_in_conditional.ll index d66d718d492a..68c60edce09c 100644 --- a/polly/test/ScopInfo/invariant_load_base_pointer_in_conditional.ll +++ b/polly/test/ScopInfo/invariant_load_base_pointer_in_conditional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -polly-ignore-aliasing -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-ignore-aliasing -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_branch_condition.ll b/polly/test/ScopInfo/invariant_load_branch_condition.ll index 4f49d2969d86..e8c18adee1f3 100644 --- a/polly/test/ScopInfo/invariant_load_branch_condition.ll +++ b/polly/test/ScopInfo/invariant_load_branch_condition.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output \ -; RUN: -polly-invariant-load-hoisting < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output \ +; RUN: -polly-invariant-load-hoisting < %s 2>&1 | FileCheck %s ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs.ll index c6a7faf2e355..d19018db7967 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_2.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_2.ll index 921dd4fbde5c..556b50284f34 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_2.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_3.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_3.ll index c15d11ca865d..58c553023191 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_3.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4.ll index 0495a330792c..881003b15839 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4b.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4b.ll index 9144fcf186c3..6f4d40ec98f7 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4b.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4b.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4c.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4c.ll index aefacff6b46f..d1859cb54241 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4c.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4c.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_5.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_5.ll index ecc0c0a23014..74d6f1021124 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_5.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_complex_condition.ll b/polly/test/ScopInfo/invariant_load_complex_condition.ll index e721c222db5f..34f5c45ac2b4 100644 --- a/polly/test/ScopInfo/invariant_load_complex_condition.ll +++ b/polly/test/ScopInfo/invariant_load_complex_condition.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -S -polly-print-scops -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -S '-passes=print' -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/invariant_load_condition.ll b/polly/test/ScopInfo/invariant_load_condition.ll index 84546984709e..7d14a398d874 100644 --- a/polly/test/ScopInfo/invariant_load_condition.ll +++ b/polly/test/ScopInfo/invariant_load_condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_dereferenceable.ll b/polly/test/ScopInfo/invariant_load_dereferenceable.ll index adba32d8d463..c590e4043f64 100644 --- a/polly/test/ScopInfo/invariant_load_dereferenceable.ll +++ b/polly/test/ScopInfo/invariant_load_dereferenceable.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-print-detect -polly-print-scops \ +; RUN: opt %loadPolly '-passes=print' '-passes=print' \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -disable-output < %s | FileCheck %s +; RUN: -disable-output < %s 2>&1 | FileCheck %s ; CHECK-NOT: Function: foo_undereferanceable diff --git a/polly/test/ScopInfo/invariant_load_distinct_parameter_valuations.ll b/polly/test/ScopInfo/invariant_load_distinct_parameter_valuations.ll index 60b4a1daa824..b9b55cc4ecb1 100644 --- a/polly/test/ScopInfo/invariant_load_distinct_parameter_valuations.ll +++ b/polly/test/ScopInfo/invariant_load_distinct_parameter_valuations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; Check that we do not consolidate the invariant loads to smp[order - 1] and ; smp[order - 2] in the blocks %0 and %16. While they have the same pointer diff --git a/polly/test/ScopInfo/invariant_load_in_non_affine.ll b/polly/test/ScopInfo/invariant_load_in_non_affine.ll index d00bc2d642e0..08c8bd28caa7 100644 --- a/polly/test/ScopInfo/invariant_load_in_non_affine.ll +++ b/polly/test/ScopInfo/invariant_load_in_non_affine.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s ; ; CHECK-NOT: Valid Region for Scop ; diff --git a/polly/test/ScopInfo/invariant_load_loop_ub.ll b/polly/test/ScopInfo/invariant_load_loop_ub.ll index 856b6e4dd508..009f036bcb62 100644 --- a/polly/test/ScopInfo/invariant_load_loop_ub.ll +++ b/polly/test/ScopInfo/invariant_load_loop_ub.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -polly-process-unprofitable -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -polly-invariant-load-hoisting=true -polly-process-unprofitable -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-process-unprofitable -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-process-unprofitable -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_ptr_ptr_noalias.ll b/polly/test/ScopInfo/invariant_load_ptr_ptr_noalias.ll index 69463d420aca..ba381dea72e9 100644 --- a/polly/test/ScopInfo/invariant_load_ptr_ptr_noalias.ll +++ b/polly/test/ScopInfo/invariant_load_ptr_ptr_noalias.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -tbaa -polly-print-scops -polly-invariant-load-hoisting=true -polly-ignore-aliasing \ -; RUN: -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=tbaa '-passes=print' -polly-invariant-load-hoisting=true -polly-ignore-aliasing \ +; RUN: -disable-output < %s 2>&1 | FileCheck %s ; ; Note: The order of the invariant accesses is important because A is the ; base pointer of tmp3 and we will generate code in the same order as diff --git a/polly/test/ScopInfo/invariant_load_scalar_dep.ll b/polly/test/ScopInfo/invariant_load_scalar_dep.ll index 79a10426862a..ea0227d4a6e9 100644 --- a/polly/test/ScopInfo/invariant_load_scalar_dep.ll +++ b/polly/test/ScopInfo/invariant_load_scalar_dep.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_stmt_domain.ll b/polly/test/ScopInfo/invariant_load_stmt_domain.ll index 6cd71c85ea2f..31da46f40f8c 100644 --- a/polly/test/ScopInfo/invariant_load_stmt_domain.ll +++ b/polly/test/ScopInfo/invariant_load_stmt_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; This test case verifies that the statement domain of the invariant access ; is the universe. In earlier versions of Polly, we accidentally computed an diff --git a/polly/test/ScopInfo/invariant_load_zext_parameter-2.ll b/polly/test/ScopInfo/invariant_load_zext_parameter-2.ll index e77515280241..2bf6d1d4d8b1 100644 --- a/polly/test/ScopInfo/invariant_load_zext_parameter-2.ll +++ b/polly/test/ScopInfo/invariant_load_zext_parameter-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -scalar-evolution-max-value-compare-depth=3 -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -scalar-evolution-max-value-compare-depth=3 -polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s +; RUN: opt %loadPolly -scalar-evolution-max-value-compare-depth=3 '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -scalar-evolution-max-value-compare-depth=3 -passes=polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s ; ; Stress test for the code generation of invariant accesses. ; diff --git a/polly/test/ScopInfo/invariant_load_zext_parameter.ll b/polly/test/ScopInfo/invariant_load_zext_parameter.ll index 1bde70282d44..41559ff14efa 100644 --- a/polly/test/ScopInfo/invariant_load_zext_parameter.ll +++ b/polly/test/ScopInfo/invariant_load_zext_parameter.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN ; ; void f(int *I0, int *I1, int *V) { ; for (int i = 0; i < 1000; i++) { diff --git a/polly/test/ScopInfo/invariant_load_zextended_in_own_execution_context.ll b/polly/test/ScopInfo/invariant_load_zextended_in_own_execution_context.ll index 775369e55c92..2ae99acd47ec 100644 --- a/polly/test/ScopInfo/invariant_load_zextended_in_own_execution_context.ll +++ b/polly/test/ScopInfo/invariant_load_zextended_in_own_execution_context.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s ; ; CHECK: Execution Context: [p_0_loaded_from_currpc] -> { : } ; diff --git a/polly/test/ScopInfo/invariant_loads_complicated_dependences.ll b/polly/test/ScopInfo/invariant_loads_complicated_dependences.ll index 1d54ccc69023..9cee220d1f3c 100644 --- a/polly/test/ScopInfo/invariant_loads_complicated_dependences.ll +++ b/polly/test/ScopInfo/invariant_loads_complicated_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_loads_cyclic_dependences.ll b/polly/test/ScopInfo/invariant_loads_cyclic_dependences.ll index e97de0c936bc..0434bbd34e4c 100644 --- a/polly/test/ScopInfo/invariant_loads_cyclic_dependences.ll +++ b/polly/test/ScopInfo/invariant_loads_cyclic_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; Negative test. If we assume UB[*V] to be invariant we get a cyclic ; dependence in the invariant loads that needs to be resolved by diff --git a/polly/test/ScopInfo/invariant_loop_bounds.ll b/polly/test/ScopInfo/invariant_loop_bounds.ll index 4e1fd88fac30..279199b805f1 100644 --- a/polly/test/ScopInfo/invariant_loop_bounds.ll +++ b/polly/test/ScopInfo/invariant_loop_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-1.ll b/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-1.ll index 3d5737bbe168..d8e293f7e6f3 100644 --- a/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-1.ll +++ b/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; Verify that we only have one parameter and one invariant load for all ; three loads that occure in the region but actually access the same diff --git a/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-2.ll b/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-2.ll index e2de503eb83f..e68f3be7fb30 100644 --- a/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-2.ll +++ b/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; Verify that we only have one parameter and one invariant load for all ; three loads that occure in the region but actually access the same diff --git a/polly/test/ScopInfo/isl_aff_out_of_bounds.ll b/polly/test/ScopInfo/isl_aff_out_of_bounds.ll index ca1b235be358..4f7a604272bb 100644 --- a/polly/test/ScopInfo/isl_aff_out_of_bounds.ll +++ b/polly/test/ScopInfo/isl_aff_out_of_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-detect < %s +; RUN: opt %loadPolly '-passes=print' < %s 2>&1 ; Used to fail with: ; ../../isl/isl_aff.c:591: position out of bounds diff --git a/polly/test/ScopInfo/isl_trip_count_01.ll b/polly/test/ScopInfo/isl_trip_count_01.ll index fc6b79c5a68a..6ad4929888e3 100644 --- a/polly/test/ScopInfo/isl_trip_count_01.ll +++ b/polly/test/ScopInfo/isl_trip_count_01.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: [M, N] -> { Stmt_while_body[i0] : i0 > 0 and 4i0 <= -M + N; Stmt_while_body[0] }; ; diff --git a/polly/test/ScopInfo/isl_trip_count_02.ll b/polly/test/ScopInfo/isl_trip_count_02.ll index 9376cb415cec..b356fa9fdf22 100644 --- a/polly/test/ScopInfo/isl_trip_count_02.ll +++ b/polly/test/ScopInfo/isl_trip_count_02.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s ; ; TODO: We do not allow unbounded loops at the moment. ; diff --git a/polly/test/ScopInfo/isl_trip_count_03.ll b/polly/test/ScopInfo/isl_trip_count_03.ll index f5b0048a0e0e..886143114df6 100644 --- a/polly/test/ScopInfo/isl_trip_count_03.ll +++ b/polly/test/ScopInfo/isl_trip_count_03.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Test comes from a bug (15771) or better a feature request. It was not allowed ; in Polly in the old domain generation as ScalarEvolution cannot figure out the diff --git a/polly/test/ScopInfo/isl_trip_count_multiple_exiting_blocks.ll b/polly/test/ScopInfo/isl_trip_count_multiple_exiting_blocks.ll index 91bc19e2de44..8ddb26a6ac88 100644 --- a/polly/test/ScopInfo/isl_trip_count_multiple_exiting_blocks.ll +++ b/polly/test/ScopInfo/isl_trip_count_multiple_exiting_blocks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/licm_load.ll b/polly/test/ScopInfo/licm_load.ll index ade640976d00..c4695ecddaf7 100644 --- a/polly/test/ScopInfo/licm_load.ll +++ b/polly/test/ScopInfo/licm_load.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadNPMPolly -passes='loop(loop-rotate,indvars),polly-prepare,print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -passes='loop(loop-rotate,indvars),polly-prepare,print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s -; RUN: opt %loadNPMPolly -passes='loop-mssa(loop-rotate,indvars,licm),polly-prepare,print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -passes='loop-mssa(loop-rotate,indvars,licm),polly-prepare,print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s ; ; void foo(int n, float A[static const restrict n], diff --git a/polly/test/ScopInfo/licm_potential_store.ll b/polly/test/ScopInfo/licm_potential_store.ll index 8a36ee84313a..fd19df793306 100644 --- a/polly/test/ScopInfo/licm_potential_store.ll +++ b/polly/test/ScopInfo/licm_potential_store.ll @@ -1,8 +1,8 @@ -; RUN: opt %loadNPMPolly -passes='sroa,instcombine,simplifycfg,reassociate,loop(loop-rotate),instcombine,indvars,polly-prepare,print' \ +; RUN: opt %loadPolly -passes='sroa,instcombine,simplifycfg,reassociate,loop(loop-rotate),instcombine,indvars,polly-prepare,print' \ ; RUN: -tailcallopt -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=NOLICM -; RUN: opt %loadNPMPolly -passes='sroa,instcombine,simplifycfg,reassociate,loop(loop-rotate),instcombine,indvars,loop-mssa(licm),polly-prepare,print' \ +; RUN: opt %loadPolly -passes='sroa,instcombine,simplifycfg,reassociate,loop(loop-rotate),instcombine,indvars,loop-mssa(licm),polly-prepare,print' \ ; RUN: -tailcallopt -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=LICM diff --git a/polly/test/ScopInfo/licm_reduction_nested.ll b/polly/test/ScopInfo/licm_reduction_nested.ll index a3ba478cd9ff..98d6dfcfa074 100644 --- a/polly/test/ScopInfo/licm_reduction_nested.ll +++ b/polly/test/ScopInfo/licm_reduction_nested.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -loop-rotate -indvars -polly-prepare -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -basic-aa -loop-rotate -indvars -licm -polly-prepare -polly-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -loop-rotate -indvars -passes=polly-prepare '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -loop-rotate -indvars -licm -passes=polly-prepare '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; XFAIL: * ; diff --git a/polly/test/ScopInfo/long-compile-time-alias-analysis.ll b/polly/test/ScopInfo/long-compile-time-alias-analysis.ll index 1cbecf086968..5fa9a74d0fe3 100644 --- a/polly/test/ScopInfo/long-compile-time-alias-analysis.ll +++ b/polly/test/ScopInfo/long-compile-time-alias-analysis.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ; Verify that the compilation of this test case does not take infinite time. ; At some point Polly tried to model this test case and got stuck in diff --git a/polly/test/ScopInfo/long-sequence-of-error-blocks-2.ll b/polly/test/ScopInfo/long-sequence-of-error-blocks-2.ll index c88ea1327389..283a0bea7c49 100644 --- a/polly/test/ScopInfo/long-sequence-of-error-blocks-2.ll +++ b/polly/test/ScopInfo/long-sequence-of-error-blocks-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/polly/test/ScopInfo/long-sequence-of-error-blocks.ll b/polly/test/ScopInfo/long-sequence-of-error-blocks.ll index 5b6ea9cc212d..812de273a7df 100644 --- a/polly/test/ScopInfo/long-sequence-of-error-blocks.ll +++ b/polly/test/ScopInfo/long-sequence-of-error-blocks.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/polly/test/ScopInfo/loop-multiexit-succ-cond.ll b/polly/test/ScopInfo/loop-multiexit-succ-cond.ll index 350db05c6dc0..f8f47a332a13 100644 --- a/polly/test/ScopInfo/loop-multiexit-succ-cond.ll +++ b/polly/test/ScopInfo/loop-multiexit-succ-cond.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s 2>&1 | FileCheck %s --check-prefix=IR ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/loop_affine_bound_0.ll b/polly/test/ScopInfo/loop_affine_bound_0.ll index 33f49df7780f..77b0ebe8e494 100644 --- a/polly/test/ScopInfo/loop_affine_bound_0.ll +++ b/polly/test/ScopInfo/loop_affine_bound_0.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long a[][128], long N, long M) { ; long i, j; diff --git a/polly/test/ScopInfo/loop_affine_bound_1.ll b/polly/test/ScopInfo/loop_affine_bound_1.ll index 38e47b74465b..7c1eaa5dff8c 100644 --- a/polly/test/ScopInfo/loop_affine_bound_1.ll +++ b/polly/test/ScopInfo/loop_affine_bound_1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output< %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output< %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ;void f(long a[][128], long N, long M) { ; long i, j; diff --git a/polly/test/ScopInfo/loop_affine_bound_2.ll b/polly/test/ScopInfo/loop_affine_bound_2.ll index e34662f4e6ab..12d81c78b794 100644 --- a/polly/test/ScopInfo/loop_affine_bound_2.ll +++ b/polly/test/ScopInfo/loop_affine_bound_2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long a[][128], long N, long M) { ; long i, j; diff --git a/polly/test/ScopInfo/loop_carry.ll b/polly/test/ScopInfo/loop_carry.ll index f7c1dca0919c..856efb730056 100644 --- a/polly/test/ScopInfo/loop_carry.ll +++ b/polly/test/ScopInfo/loop_carry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/many-scalar-dependences.ll b/polly/test/ScopInfo/many-scalar-dependences.ll index aaa02f581a1c..56e02d56254d 100644 --- a/polly/test/ScopInfo/many-scalar-dependences.ll +++ b/polly/test/ScopInfo/many-scalar-dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(float a[100][100]) { ; float x; diff --git a/polly/test/ScopInfo/max-loop-depth.ll b/polly/test/ScopInfo/max-loop-depth.ll index 3c7db4458604..4da0f35121d0 100644 --- a/polly/test/ScopInfo/max-loop-depth.ll +++ b/polly/test/ScopInfo/max-loop-depth.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void bar(); ; void foo(int *A, int *B, long int N, long int M) { diff --git a/polly/test/ScopInfo/memcpy-raw-source.ll b/polly/test/ScopInfo/memcpy-raw-source.ll index 137ab8229220..c3ecce23cf5c 100644 --- a/polly/test/ScopInfo/memcpy-raw-source.ll +++ b/polly/test/ScopInfo/memcpy-raw-source.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -scoped-noalias-aa -tbaa -polly-print-scops -disable-output < %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa,scoped-noalias-aa,tbaa '-passes=print' -disable-output < %s ; ; Ensure that ScopInfo's alias analysis llvm.memcpy for, ; like the AliasSetTracker, preserves bitcasts. diff --git a/polly/test/ScopInfo/memcpy.ll b/polly/test/ScopInfo/memcpy.ll index 705dea769e42..2e34b0d87a5f 100644 --- a/polly/test/ScopInfo/memcpy.ll +++ b/polly/test/ScopInfo/memcpy.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-allow-differing-element-types -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -S -basic-aa -polly-allow-differing-element-types -polly-codegen < %s | FileCheck --check-prefix=IR %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-differing-element-types '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -S -aa-pipeline=basic-aa -polly-allow-differing-element-types -passes=polly-codegen < %s 2>&1 | FileCheck --check-prefix=IR %s ; ; CHECK: Arrays { ; CHECK-NEXT: i8 MemRef_A[*]; // Element size 1 diff --git a/polly/test/ScopInfo/memmove.ll b/polly/test/ScopInfo/memmove.ll index 15123422f419..28a4ebeee7e2 100644 --- a/polly/test/ScopInfo/memmove.ll +++ b/polly/test/ScopInfo/memmove.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-allow-differing-element-types -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -S -basic-aa -polly-allow-differing-element-types -polly-codegen < %s | FileCheck --check-prefix=IR %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-differing-element-types '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -S -aa-pipeline=basic-aa -polly-allow-differing-element-types -passes=polly-codegen < %s 2>&1 | FileCheck --check-prefix=IR %s ; ; CHECK: Arrays { ; CHECK-NEXT: i8 MemRef_A[*]; // Element size 1 diff --git a/polly/test/ScopInfo/memset.ll b/polly/test/ScopInfo/memset.ll index ef86b4c275e5..163b58dc54dc 100644 --- a/polly/test/ScopInfo/memset.ll +++ b/polly/test/ScopInfo/memset.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-differing-element-types -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -S -polly-allow-differing-element-types -polly-codegen < %s | FileCheck --check-prefix=IR %s +; RUN: opt %loadPolly -polly-allow-differing-element-types '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -S -polly-allow-differing-element-types -passes=polly-codegen < %s 2>&1 | FileCheck --check-prefix=IR %s ; ; CHECK: Arrays { ; CHECK-NEXT: i8 MemRef_A[*]; // Element size 1 diff --git a/polly/test/ScopInfo/memset_null.ll b/polly/test/ScopInfo/memset_null.ll index 1608ff6ebef4..3d38fa1e6851 100644 --- a/polly/test/ScopInfo/memset_null.ll +++ b/polly/test/ScopInfo/memset_null.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-modref-calls -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-allow-modref-calls -S -polly-codegen < %s +; RUN: opt %loadPolly -polly-allow-modref-calls '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-modref-calls -S -passes=polly-codegen < %s ; ; Verify we can handle a memset to "null" and that we do not model it. ; TODO: FIXME: We could use the undefined memset to optimize the code further, diff --git a/polly/test/ScopInfo/mismatching-array-dimensions.ll b/polly/test/ScopInfo/mismatching-array-dimensions.ll index a1c6d4e82127..a2deef16eafd 100644 --- a/polly/test/ScopInfo/mismatching-array-dimensions.ll +++ b/polly/test/ScopInfo/mismatching-array-dimensions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK-NOT: AssumedContext diff --git a/polly/test/ScopInfo/mod_ref_access_pointee_arguments.ll b/polly/test/ScopInfo/mod_ref_access_pointee_arguments.ll index 72889324e37e..202295abf57c 100644 --- a/polly/test/ScopInfo/mod_ref_access_pointee_arguments.ll +++ b/polly/test/ScopInfo/mod_ref_access_pointee_arguments.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-scops -polly-allow-modref-calls \ -; RUN: -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-codegen -polly-allow-modref-calls \ +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -polly-allow-modref-calls \ +; RUN: -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb -passes=polly-codegen -polly-allow-modref-calls \ ; RUN: -disable-output < %s ; ; Verify that we model the may-write access of the prefetch intrinsic diff --git a/polly/test/ScopInfo/mod_ref_read_pointee_arguments.ll b/polly/test/ScopInfo/mod_ref_read_pointee_arguments.ll index 2f6c6792fd9d..f1124f0a977b 100644 --- a/polly/test/ScopInfo/mod_ref_read_pointee_arguments.ll +++ b/polly/test/ScopInfo/mod_ref_read_pointee_arguments.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-scops -polly-allow-modref-calls \ -; RUN: -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -basic-aa -polly-codegen -disable-output \ +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -polly-allow-modref-calls \ +; RUN: -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -disable-output \ ; RUN: -polly-allow-modref-calls < %s ; ; Verify that we model the read access of the gcread intrinsic diff --git a/polly/test/ScopInfo/mod_ref_read_pointer.ll b/polly/test/ScopInfo/mod_ref_read_pointer.ll index 657e37c68a7b..24f276621532 100644 --- a/polly/test/ScopInfo/mod_ref_read_pointer.ll +++ b/polly/test/ScopInfo/mod_ref_read_pointer.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-allow-modref-calls -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -basic-aa -polly-allow-modref-calls -polly-codegen -disable-output < %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-modref-calls '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-modref-calls -passes=polly-codegen -disable-output < %s ; ; Check that we assume the call to func has a read on the whole A array. ; diff --git a/polly/test/ScopInfo/mod_ref_read_pointers.ll b/polly/test/ScopInfo/mod_ref_read_pointers.ll index 7ed3423a2aeb..260f759c1449 100644 --- a/polly/test/ScopInfo/mod_ref_read_pointers.ll +++ b/polly/test/ScopInfo/mod_ref_read_pointers.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-scops -polly-allow-modref-calls \ -; RUN: -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -basic-aa -polly-codegen -disable-output \ +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-allow-modref-calls \ +; RUN: -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -disable-output \ ; RUN: -polly-allow-modref-calls < %s ; ; Check that the call to func will "read" not only the A array but also the diff --git a/polly/test/ScopInfo/modulo_zext_1.ll b/polly/test/ScopInfo/modulo_zext_1.ll index d611ec4807b5..60083098eb08 100644 --- a/polly/test/ScopInfo/modulo_zext_1.ll +++ b/polly/test/ScopInfo/modulo_zext_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/modulo_zext_2.ll b/polly/test/ScopInfo/modulo_zext_2.ll index 8d2321849174..7ed70d085546 100644 --- a/polly/test/ScopInfo/modulo_zext_2.ll +++ b/polly/test/ScopInfo/modulo_zext_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/modulo_zext_3.ll b/polly/test/ScopInfo/modulo_zext_3.ll index acb26dc1c77f..67b26d813918 100644 --- a/polly/test/ScopInfo/modulo_zext_3.ll +++ b/polly/test/ScopInfo/modulo_zext_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/multi-scop.ll b/polly/test/ScopInfo/multi-scop.ll index e26c8c7bae10..747f76bbf275 100644 --- a/polly/test/ScopInfo/multi-scop.ll +++ b/polly/test/ScopInfo/multi-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-detect -polly-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; This test case contains two scops. diff --git a/polly/test/ScopInfo/multidim_2d-diagonal-matrix.ll b/polly/test/ScopInfo/multidim_2d-diagonal-matrix.ll index 278c06a2fdba..8d023a671d86 100644 --- a/polly/test/ScopInfo/multidim_2d-diagonal-matrix.ll +++ b/polly/test/ScopInfo/multidim_2d-diagonal-matrix.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/ScopInfo/multidim_2d_outer_parametric_offset.ll b/polly/test/ScopInfo/multidim_2d_outer_parametric_offset.ll index 06a76466c25e..6cd612d155cb 100644 --- a/polly/test/ScopInfo/multidim_2d_outer_parametric_offset.ll +++ b/polly/test/ScopInfo/multidim_2d_outer_parametric_offset.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll b/polly/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll index bfbe5682d44a..aed318b51b15 100644 --- a/polly/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll +++ b/polly/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/ScopInfo/multidim_2d_with_modref_call.ll b/polly/test/ScopInfo/multidim_2d_with_modref_call.ll index ba934adb675a..872544d872cd 100644 --- a/polly/test/ScopInfo/multidim_2d_with_modref_call.ll +++ b/polly/test/ScopInfo/multidim_2d_with_modref_call.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-modref-calls \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-modref-calls \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-nonaffine \ +; RUN: -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -polly-allow-modref-calls -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE +; RUN: -polly-allow-modref-calls -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NONAFFINE ; TODO: We should delinearize the accesses despite the use in a call to a ; readonly function. For now we verify we do not delinearize them though. diff --git a/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll b/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll index 3da123fd1f60..add130e2087f 100644 --- a/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll +++ b/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-modref-calls \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-modref-calls \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-nonaffine \ +; RUN: -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -polly-allow-modref-calls -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE +; RUN: -polly-allow-modref-calls -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NONAFFINE ; TODO: We should delinearize the accesses despite the use in a call to a ; readonly function. For now we verify we do not delinearize them though. diff --git a/polly/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll b/polly/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll index 988475575fec..5e0f58cb276b 100644 --- a/polly/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll +++ b/polly/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o]) { diff --git a/polly/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll b/polly/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll index ddc35a46a633..765077142df6 100644 --- a/polly/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll +++ b/polly/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; #define N 400 ; diff --git a/polly/test/ScopInfo/multidim_fixedsize_multi_offset.ll b/polly/test/ScopInfo/multidim_fixedsize_multi_offset.ll index 9c749f0c48c8..8e26a2ad6a21 100644 --- a/polly/test/ScopInfo/multidim_fixedsize_multi_offset.ll +++ b/polly/test/ScopInfo/multidim_fixedsize_multi_offset.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Context: ; CHECK-NEXT: { : } diff --git a/polly/test/ScopInfo/multidim_fold_constant_dim.ll b/polly/test/ScopInfo/multidim_fold_constant_dim.ll index e95d400a860c..b142a2ab442f 100644 --- a/polly/test/ScopInfo/multidim_fold_constant_dim.ll +++ b/polly/test/ScopInfo/multidim_fold_constant_dim.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; struct com { ; double Real; diff --git a/polly/test/ScopInfo/multidim_fold_constant_dim_zero.ll b/polly/test/ScopInfo/multidim_fold_constant_dim_zero.ll index 57275e4024ab..dac9dac1e7ad 100644 --- a/polly/test/ScopInfo/multidim_fold_constant_dim_zero.ll +++ b/polly/test/ScopInfo/multidim_fold_constant_dim_zero.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -debug -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScopInfo/multidim_fortran_2d.ll b/polly/test/ScopInfo/multidim_fortran_2d.ll index 29279a4e886b..ee13da875d4e 100644 --- a/polly/test/ScopInfo/multidim_fortran_2d.ll +++ b/polly/test/ScopInfo/multidim_fortran_2d.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops \ -; RUN: -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' \ +; RUN: -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; subroutine init_array(ni, nj, pi, pj, a) ; implicit none diff --git a/polly/test/ScopInfo/multidim_fortran_2d_params.ll b/polly/test/ScopInfo/multidim_fortran_2d_params.ll index 93145b399ca5..f4978ecb35f7 100644 --- a/polly/test/ScopInfo/multidim_fortran_2d_params.ll +++ b/polly/test/ScopInfo/multidim_fortran_2d_params.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output \ +; RUN: opt %loadPolly '-passes=print' -disable-output \ ; RUN: -polly-precise-fold-accesses \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s ; subroutine init_array(ni, nj, pi, pj, a) ; implicit none diff --git a/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll b/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll index dff6a8be85cf..f3a5e0ba9305 100644 --- a/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll +++ b/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-modref-calls \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-modref-calls \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-nonaffine \ +; RUN: -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -polly-allow-modref-calls -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE +; RUN: -polly-allow-modref-calls -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NONAFFINE ; TODO: We should delinearize the accesses despite the use in a call to a ; readonly function. For now we verify we do not delinearize them though. diff --git a/polly/test/ScopInfo/multidim_fortran_srem.ll b/polly/test/ScopInfo/multidim_fortran_srem.ll index 8c24c5b8ee71..fc65ff2954cf 100644 --- a/polly/test/ScopInfo/multidim_fortran_srem.ll +++ b/polly/test/ScopInfo/multidim_fortran_srem.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" ; CHECK: Statements { diff --git a/polly/test/ScopInfo/multidim_gep_pointercast.ll b/polly/test/ScopInfo/multidim_gep_pointercast.ll index 20d59fa91eaf..6b69dd7bb571 100644 --- a/polly/test/ScopInfo/multidim_gep_pointercast.ll +++ b/polly/test/ScopInfo/multidim_gep_pointercast.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; The load access to A has a pointer-bitcast to another elements size before the ; GetElementPtr. Verify that we do not the GEP delinearization because it diff --git a/polly/test/ScopInfo/multidim_gep_pointercast2.ll b/polly/test/ScopInfo/multidim_gep_pointercast2.ll index deed9c7c3f57..0c8139f7f8e1 100644 --- a/polly/test/ScopInfo/multidim_gep_pointercast2.ll +++ b/polly/test/ScopInfo/multidim_gep_pointercast2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verfy that we do not use the GetElementPtr information to delinearize A ; because of the cast in-between. Use the single-dimensional modeling instead. diff --git a/polly/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll b/polly/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll index 9f7e6bc4a2a2..4610f46ea082 100644 --- a/polly/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll +++ b/polly/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o]) { diff --git a/polly/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll b/polly/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll index 131bb7b3ebed..b64e0a99c73b 100644 --- a/polly/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll +++ b/polly/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-precise-fold-accesses -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-precise-fold-accesses '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o], long p, long q, long r) { diff --git a/polly/test/ScopInfo/multidim_many_references.ll b/polly/test/ScopInfo/multidim_many_references.ll index b0483b267260..0736fd947a31 100644 --- a/polly/test/ScopInfo/multidim_many_references.ll +++ b/polly/test/ScopInfo/multidim_many_references.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-ignore-aliasing -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -polly-ignore-aliasing -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-ignore-aliasing -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-ignore-aliasing -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/multidim_nested_start_integer.ll b/polly/test/ScopInfo/multidim_nested_start_integer.ll index 741a0ef45c27..db99ab176a3a 100644 --- a/polly/test/ScopInfo/multidim_nested_start_integer.ll +++ b/polly/test/ScopInfo/multidim_nested_start_integer.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o]) { diff --git a/polly/test/ScopInfo/multidim_nested_start_share_parameter.ll b/polly/test/ScopInfo/multidim_nested_start_share_parameter.ll index 692746bad3d7..0ecac3cdaaab 100644 --- a/polly/test/ScopInfo/multidim_nested_start_share_parameter.ll +++ b/polly/test/ScopInfo/multidim_nested_start_share_parameter.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o]) { diff --git a/polly/test/ScopInfo/multidim_only_ivs_2d.ll b/polly/test/ScopInfo/multidim_only_ivs_2d.ll index 71245642e751..ccfa7a7de8e2 100644 --- a/polly/test/ScopInfo/multidim_only_ivs_2d.ll +++ b/polly/test/ScopInfo/multidim_only_ivs_2d.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/ScopInfo/multidim_only_ivs_3d.ll b/polly/test/ScopInfo/multidim_only_ivs_3d.ll index a019d58b241d..7a18aec573e8 100644 --- a/polly/test/ScopInfo/multidim_only_ivs_3d.ll +++ b/polly/test/ScopInfo/multidim_only_ivs_3d.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o]) { diff --git a/polly/test/ScopInfo/multidim_only_ivs_3d_cast.ll b/polly/test/ScopInfo/multidim_only_ivs_3d_cast.ll index 41577ef1a0be..dd9c4d374f28 100644 --- a/polly/test/ScopInfo/multidim_only_ivs_3d_cast.ll +++ b/polly/test/ScopInfo/multidim_only_ivs_3d_cast.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void foo(int n, int m, int o, double A[n][m][o]) { ; diff --git a/polly/test/ScopInfo/multidim_only_ivs_3d_reverse.ll b/polly/test/ScopInfo/multidim_only_ivs_3d_reverse.ll index 25907f2ee79c..be1b1eb8fc8d 100644 --- a/polly/test/ScopInfo/multidim_only_ivs_3d_reverse.ll +++ b/polly/test/ScopInfo/multidim_only_ivs_3d_reverse.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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-n8:16:32:64-S128" ; This test case checks for array access functions where the order in which the diff --git a/polly/test/ScopInfo/multidim_param_in_subscript-2.ll b/polly/test/ScopInfo/multidim_param_in_subscript-2.ll index 0790664f7129..f0cd1589b987 100644 --- a/polly/test/ScopInfo/multidim_param_in_subscript-2.ll +++ b/polly/test/ScopInfo/multidim_param_in_subscript-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-precise-fold-accesses -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-precise-fold-accesses '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void foo(long n, long m, float A[][n][m]) { ; for (long i = 0; i < 100; i++) diff --git a/polly/test/ScopInfo/multidim_param_in_subscript.ll b/polly/test/ScopInfo/multidim_param_in_subscript.ll index b8ec80b321fe..ca423919e488 100644 --- a/polly/test/ScopInfo/multidim_param_in_subscript.ll +++ b/polly/test/ScopInfo/multidim_param_in_subscript.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; ; void foo(long n, float A[][n]) { diff --git a/polly/test/ScopInfo/multidim_parameter_addrec_product.ll b/polly/test/ScopInfo/multidim_parameter_addrec_product.ll index 7db3e9dc3b5f..ec311d42386a 100644 --- a/polly/test/ScopInfo/multidim_parameter_addrec_product.ll +++ b/polly/test/ScopInfo/multidim_parameter_addrec_product.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void foo(float *A, long *p) { ; for (long i = 0; i < 100; i++) diff --git a/polly/test/ScopInfo/multidim_single_and_multidim_array.ll b/polly/test/ScopInfo/multidim_single_and_multidim_array.ll index 1e302dec4861..0d51aa115559 100644 --- a/polly/test/ScopInfo/multidim_single_and_multidim_array.ll +++ b/polly/test/ScopInfo/multidim_single_and_multidim_array.ll @@ -1,11 +1,11 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-delinearize=false -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-scops -polly-delinearize=false -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=DELIN -; RUN: opt %loadPolly -polly-print-scops -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=DELIN -; RUN: opt %loadPolly -polly-print-function-scops -polly-delinearize=false -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -polly-delinearize=false -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE -; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s --check-prefix=DELIN -; RUN: opt %loadPolly -polly-print-function-scops -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=DELIN +; RUN: opt %loadPolly '-passes=print' -polly-delinearize=false -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-delinearize=false -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NONAFFINE +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=DELIN +; RUN: opt %loadPolly '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s --check-prefix=DELIN +; RUN: opt %loadPolly '-passes=print' -polly-delinearize=false -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-delinearize=false -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NONAFFINE +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=DELIN +; RUN: opt %loadPolly '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s --check-prefix=DELIN target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/multidim_srem.ll b/polly/test/ScopInfo/multidim_srem.ll index f89843f0a5bc..b4eee668207c 100644 --- a/polly/test/ScopInfo/multidim_srem.ll +++ b/polly/test/ScopInfo/multidim_srem.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void foo(long n, float A[][n][n]) { ; for (long i = 0; i < 200; i++) diff --git a/polly/test/ScopInfo/multidim_with_bitcast.ll b/polly/test/ScopInfo/multidim_with_bitcast.ll index b77ff689b953..8af2e18265b0 100644 --- a/polly/test/ScopInfo/multidim_with_bitcast.ll +++ b/polly/test/ScopInfo/multidim_with_bitcast.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/multiple-binary-or-conditions.ll b/polly/test/ScopInfo/multiple-binary-or-conditions.ll index b905a11f577c..481f799ed0fe 100644 --- a/polly/test/ScopInfo/multiple-binary-or-conditions.ll +++ b/polly/test/ScopInfo/multiple-binary-or-conditions.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s ; ; void or(float *A, long n, long m) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/multiple-types-access-offset-not-dividable-by-element-size.ll b/polly/test/ScopInfo/multiple-types-access-offset-not-dividable-by-element-size.ll index 2d03ad941c05..69b00402ba6b 100644 --- a/polly/test/ScopInfo/multiple-types-access-offset-not-dividable-by-element-size.ll +++ b/polly/test/ScopInfo/multiple-types-access-offset-not-dividable-by-element-size.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -pass-remarks-analysis="polly-scops" \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -pass-remarks-analysis="polly-scops" \ ; RUN: -polly-allow-differing-element-types \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/multiple-types-non-affine-2.ll b/polly/test/ScopInfo/multiple-types-non-affine-2.ll index 5b0aa5de1e71..a7e9a31744b4 100644 --- a/polly/test/ScopInfo/multiple-types-non-affine-2.ll +++ b/polly/test/ScopInfo/multiple-types-non-affine-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -polly-print-scops -polly-allow-nonaffine -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -polly-codegen -polly-allow-nonaffine -disable-output +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -passes=polly-codegen -polly-allow-nonaffine -disable-output ; ; // Check that accessing one array with different types works, ; // even though some accesses are non-affine. diff --git a/polly/test/ScopInfo/multiple-types-non-affine.ll b/polly/test/ScopInfo/multiple-types-non-affine.ll index 8e4be4c86d5a..e49612aa2791 100644 --- a/polly/test/ScopInfo/multiple-types-non-affine.ll +++ b/polly/test/ScopInfo/multiple-types-non-affine.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -polly-print-scops -polly-allow-nonaffine -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -polly-codegen -polly-allow-nonaffine -disable-output +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -passes=polly-codegen -polly-allow-nonaffine -disable-output ; ; // Check that accessing one array with different types works, ; // even though some accesses are non-affine. diff --git a/polly/test/ScopInfo/multiple-types-non-power-of-two-2.ll b/polly/test/ScopInfo/multiple-types-non-power-of-two-2.ll index 01f5923457b4..8347de936eff 100644 --- a/polly/test/ScopInfo/multiple-types-non-power-of-two-2.ll +++ b/polly/test/ScopInfo/multiple-types-non-power-of-two-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-allow-differing-element-types -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-allow-differing-element-types -disable-output < %s 2>&1 | FileCheck %s ; ; void multiple_types(i8 *A) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/multiple-types-non-power-of-two.ll b/polly/test/ScopInfo/multiple-types-non-power-of-two.ll index 142a5ac395b3..077ff1a741ad 100644 --- a/polly/test/ScopInfo/multiple-types-non-power-of-two.ll +++ b/polly/test/ScopInfo/multiple-types-non-power-of-two.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-allow-differing-element-types -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-allow-differing-element-types -disable-output < %s 2>&1 | FileCheck %s ; ; void multiple_types(i8 *A) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/multiple-types-two-dimensional-2.ll b/polly/test/ScopInfo/multiple-types-two-dimensional-2.ll index 1e2e53e85c25..431a0c1e966f 100644 --- a/polly/test/ScopInfo/multiple-types-two-dimensional-2.ll +++ b/polly/test/ScopInfo/multiple-types-two-dimensional-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -pass-remarks-analysis="polly-scops" \ +; RUN: opt %loadPolly '-passes=print' -pass-remarks-analysis="polly-scops" \ ; RUN: -polly-allow-differing-element-types \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/multiple-types-two-dimensional.ll b/polly/test/ScopInfo/multiple-types-two-dimensional.ll index 21dc96e6f95d..2cc2454ca6e4 100644 --- a/polly/test/ScopInfo/multiple-types-two-dimensional.ll +++ b/polly/test/ScopInfo/multiple-types-two-dimensional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -pass-remarks-analysis="polly-scops" \ +; RUN: opt %loadPolly '-passes=print' -pass-remarks-analysis="polly-scops" \ ; RUN: -polly-allow-differing-element-types \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/multiple-types.ll b/polly/test/ScopInfo/multiple-types.ll index 16db191c522f..b7006c104426 100644 --- a/polly/test/ScopInfo/multiple-types.ll +++ b/polly/test/ScopInfo/multiple-types.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops \ -; RUN: -polly-allow-differing-element-types -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' \ +; RUN: -polly-allow-differing-element-types -disable-output < %s 2>&1 | FileCheck %s ; ; // Check that accessing one array with different types works. ; void multiple_types(char *Short, char *Float, char *Double) { diff --git a/polly/test/ScopInfo/multiple_exiting_blocks.ll b/polly/test/ScopInfo/multiple_exiting_blocks.ll index f8e5d4106a16..a21a7252c2ff 100644 --- a/polly/test/ScopInfo/multiple_exiting_blocks.ll +++ b/polly/test/ScopInfo/multiple_exiting_blocks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/multiple_exiting_blocks_two_loop.ll b/polly/test/ScopInfo/multiple_exiting_blocks_two_loop.ll index c695f3c913db..e56c8b7094ea 100644 --- a/polly/test/ScopInfo/multiple_exiting_blocks_two_loop.ll +++ b/polly/test/ScopInfo/multiple_exiting_blocks_two_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/multiple_latch_blocks.ll b/polly/test/ScopInfo/multiple_latch_blocks.ll index d3949e7e2c3c..c1a64ee1c3cb 100644 --- a/polly/test/ScopInfo/multiple_latch_blocks.ll +++ b/polly/test/ScopInfo/multiple_latch_blocks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Domain := ; CHECK: [N, P] -> { Stmt_if_end[i0] : 0 <= i0 < N and (i0 > P or i0 < P) }; diff --git a/polly/test/ScopInfo/nested-loops.ll b/polly/test/ScopInfo/nested-loops.ll index ed814f826829..2819ae461fce 100644 --- a/polly/test/ScopInfo/nested-loops.ll +++ b/polly/test/ScopInfo/nested-loops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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" diff --git a/polly/test/ScopInfo/no-scalar-deps-in-non-affine-subregion.ll b/polly/test/ScopInfo/no-scalar-deps-in-non-affine-subregion.ll index 7c55e242641c..6fc364076750 100644 --- a/polly/test/ScopInfo/no-scalar-deps-in-non-affine-subregion.ll +++ b/polly/test/ScopInfo/no-scalar-deps-in-non-affine-subregion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that we do not generate any scalar dependences regarding x. It is ; defined and used on the non-affine subregion only, thus we do not need diff --git a/polly/test/ScopInfo/non-affine-region-phi.ll b/polly/test/ScopInfo/non-affine-region-phi.ll index f99782b9a0ff..4de76c4adfb1 100644 --- a/polly/test/ScopInfo/non-affine-region-phi.ll +++ b/polly/test/ScopInfo/non-affine-region-phi.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -S < %s | FileCheck %s --check-prefix=CODE -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -S < %s 2>&1 | FileCheck %s --check-prefix=CODE +; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify there is a phi in the non-affine region but it is not represented in ; the SCoP as all operands as well as the uses are inside the region too. diff --git a/polly/test/ScopInfo/non-affine-region-with-loop-2.ll b/polly/test/ScopInfo/non-affine-region-with-loop-2.ll index b673fda5ec3c..9870b813d287 100644 --- a/polly/test/ScopInfo/non-affine-region-with-loop-2.ll +++ b/polly/test/ScopInfo/non-affine-region-with-loop-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-nonaffine-loops -polly-print-scops -polly-codegen -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-nonaffine-loops '-passes=print,print,scop(polly-codegen)' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Stmt_loop3 ; CHECK: Domain := diff --git a/polly/test/ScopInfo/non-affine-region-with-loop.ll b/polly/test/ScopInfo/non-affine-region-with-loop.ll index 32dde8b4a682..e1342e1b5257 100644 --- a/polly/test/ScopInfo/non-affine-region-with-loop.ll +++ b/polly/test/ScopInfo/non-affine-region-with-loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-codegen -disable-output +; RUN: opt %loadPolly -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -passes=polly-codegen -disable-output ; ; CHECK: Domain := ; CHECK-NEXT: { Stmt_loop2__TO__loop[] }; diff --git a/polly/test/ScopInfo/non-precise-inv-load-1.ll b/polly/test/ScopInfo/non-precise-inv-load-1.ll index 5394206dd547..f35235d2de8f 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-1.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; Verify we do hoist the invariant access to I with a execution context ; as the address computation might wrap in the original but not in our diff --git a/polly/test/ScopInfo/non-precise-inv-load-2.ll b/polly/test/ScopInfo/non-precise-inv-load-2.ll index 5c0c56513a08..c538c0e7bda0 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-2.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; ; CHECK: Invariant Accesses: { diff --git a/polly/test/ScopInfo/non-precise-inv-load-3.ll b/polly/test/ScopInfo/non-precise-inv-load-3.ll index 09d09319656b..c16879a18562 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-3.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/non-precise-inv-load-4.ll b/polly/test/ScopInfo/non-precise-inv-load-4.ll index da5f656576d1..24f9d45d28e7 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-4.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; Verify we hoist I[0] without execution context even though it ; is executed in a statement with an invalid domain. diff --git a/polly/test/ScopInfo/non-precise-inv-load-5.ll b/polly/test/ScopInfo/non-precise-inv-load-5.ll index bff5f59a3302..17046685562d 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-5.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; Verify we do not hoist I[c] without execution context because it ; is executed in a statement with an invalid domain and it depends diff --git a/polly/test/ScopInfo/non-precise-inv-load-6.ll b/polly/test/ScopInfo/non-precise-inv-load-6.ll index 03540a8ead96..eeada91299f6 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-6.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-6.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; Check that we model the execution context correctly. ; diff --git a/polly/test/ScopInfo/non-pure-function-call.ll b/polly/test/ScopInfo/non-pure-function-call.ll index 4ffb8d28865d..974c9ba0527d 100644 --- a/polly/test/ScopInfo/non-pure-function-call.ll +++ b/polly/test/ScopInfo/non-pure-function-call.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll b/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll index 27998b50b74f..983c45bc7536 100644 --- a/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll +++ b/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Error blocks are skipped during SCoP detection. We skip them during ; SCoP formation too as they might contain instructions we can not handle. diff --git a/polly/test/ScopInfo/non-pure-function-calls.ll b/polly/test/ScopInfo/non-pure-function-calls.ll index 3ecf75853773..fd6a6dc3f8f1 100644 --- a/polly/test/ScopInfo/non-pure-function-calls.ll +++ b/polly/test/ScopInfo/non-pure-function-calls.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Allow the user to define function names that are treated as ; error functions and assumed not to be executed. diff --git a/polly/test/ScopInfo/non_affine_access.ll b/polly/test/ScopInfo/non_affine_access.ll index a83c9484ad52..e20be38598db 100644 --- a/polly/test/ScopInfo/non_affine_access.ll +++ b/polly/test/ScopInfo/non_affine_access.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-scops -polly-allow-nonaffine -disable-output < %s | FileCheck %s -check-prefix=NONAFFINE +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s -check-prefix=NONAFFINE 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-n8:16:32:64-S128" ; void foo(long *A) { diff --git a/polly/test/ScopInfo/non_affine_region_1.ll b/polly/test/ScopInfo/non_affine_region_1.ll index 7c4312599cf0..623d322c508c 100644 --- a/polly/test/ScopInfo/non_affine_region_1.ll +++ b/polly/test/ScopInfo/non_affine_region_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify only the incoming scalar x is modeled as a read in the non-affine ; region. diff --git a/polly/test/ScopInfo/non_affine_region_2.ll b/polly/test/ScopInfo/non_affine_region_2.ll index 0bc467c92bcb..ba20d9e6cf6e 100644 --- a/polly/test/ScopInfo/non_affine_region_2.ll +++ b/polly/test/ScopInfo/non_affine_region_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify the scalar x defined in a non-affine subregion is written as it ; escapes the region. In this test the two conditionals inside the region diff --git a/polly/test/ScopInfo/non_affine_region_3.ll b/polly/test/ScopInfo/non_affine_region_3.ll index 6d5f94df6110..ff619b579355 100644 --- a/polly/test/ScopInfo/non_affine_region_3.ll +++ b/polly/test/ScopInfo/non_affine_region_3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify the scalar x defined in a non-affine subregion is written as it ; escapes the region. In this test the two conditionals inside the region diff --git a/polly/test/ScopInfo/non_affine_region_4.ll b/polly/test/ScopInfo/non_affine_region_4.ll index f37e0ecb89d1..70f40727849a 100644 --- a/polly/test/ScopInfo/non_affine_region_4.ll +++ b/polly/test/ScopInfo/non_affine_region_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify that both scalars (x and y) are properly written in the non-affine ; region and read afterwards. diff --git a/polly/test/ScopInfo/nonaffine-buildMemoryAccess.ll b/polly/test/ScopInfo/nonaffine-buildMemoryAccess.ll index 445dd164898b..246610ee5194 100644 --- a/polly/test/ScopInfo/nonaffine-buildMemoryAccess.ll +++ b/polly/test/ScopInfo/nonaffine-buildMemoryAccess.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Domain := ; CHECK-NEXT: { Stmt_while_cond_i__TO__while_end_i[] }; diff --git a/polly/test/ScopInfo/not-a-reduction.ll b/polly/test/ScopInfo/not-a-reduction.ll index 87909290fd71..7fe41332c67d 100644 --- a/polly/test/ScopInfo/not-a-reduction.ll +++ b/polly/test/ScopInfo/not-a-reduction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s 2>&1 | not FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | not FileCheck %s ;#define TYPE float ;#define NUM 4 diff --git a/polly/test/ScopInfo/opaque-struct.ll b/polly/test/ScopInfo/opaque-struct.ll index 19fdd9bf9179..1a0859f71f36 100644 --- a/polly/test/ScopInfo/opaque-struct.ll +++ b/polly/test/ScopInfo/opaque-struct.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-scops -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s ; ; Check that we do not crash with unsized (opaque) types. ; diff --git a/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node-nonaffine-subregion.ll b/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node-nonaffine-subregion.ll index 394173bdc986..58c2116ab9dc 100644 --- a/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node-nonaffine-subregion.ll +++ b/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node-nonaffine-subregion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S < %s 2>&1 | FileCheck %s ; ; Check whether %newval is identified as escaping value, even though it is used ; in a phi that is in the region. Non-affine subregion case. diff --git a/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node.ll b/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node.ll index e17164e89372..7986399a6c7e 100644 --- a/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node.ll +++ b/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] ; CHECK-NEXT: [p_0] -> { Stmt_bb3[] -> MemRef_tmp5[] }; diff --git a/polly/test/ScopInfo/parameter-constant-division.ll b/polly/test/ScopInfo/parameter-constant-division.ll index cd6b9e3526aa..f1e006e29454 100644 --- a/polly/test/ScopInfo/parameter-constant-division.ll +++ b/polly/test/ScopInfo/parameter-constant-division.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -disable-output < %s | FileCheck %s +; RUN: -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/parameter_in_dead_statement.ll b/polly/test/ScopInfo/parameter_in_dead_statement.ll index 4b4a87f098d7..13602515d46f 100644 --- a/polly/test/ScopInfo/parameter_in_dead_statement.ll +++ b/polly/test/ScopInfo/parameter_in_dead_statement.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -S \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly '-passes=print' -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -S \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s --check-prefix=IR ; ; Verify we do not create assumptions based on the parameter p_1 which is the ; load %0 and due to error-assumptions not "part of the SCoP". diff --git a/polly/test/ScopInfo/parameter_product.ll b/polly/test/ScopInfo/parameter_product.ll index 1ba7280f97c9..9783268f2a10 100644 --- a/polly/test/ScopInfo/parameter_product.ll +++ b/polly/test/ScopInfo/parameter_product.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; int n, m; ; void foo(char* __restrict a) diff --git a/polly/test/ScopInfo/parameter_with_constant_factor_in_add.ll b/polly/test/ScopInfo/parameter_with_constant_factor_in_add.ll index 72d580801573..f750cf7f3320 100644 --- a/polly/test/ScopInfo/parameter_with_constant_factor_in_add.ll +++ b/polly/test/ScopInfo/parameter_with_constant_factor_in_add.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that the access function of the store is simple and concise ; diff --git a/polly/test/ScopInfo/partially_invariant_load_1.ll b/polly/test/ScopInfo/partially_invariant_load_1.ll index 274a7873c782..5757e4d7095c 100644 --- a/polly/test/ScopInfo/partially_invariant_load_1.ll +++ b/polly/test/ScopInfo/partially_invariant_load_1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=IR ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/partially_invariant_load_2.ll b/polly/test/ScopInfo/partially_invariant_load_2.ll index ee1092883f72..e07d6d39132b 100644 --- a/polly/test/ScopInfo/partially_invariant_load_2.ll +++ b/polly/test/ScopInfo/partially_invariant_load_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; Check that we do not try to preload *I and assume p != 42. ; diff --git a/polly/test/ScopInfo/phi-in-non-affine-region.ll b/polly/test/ScopInfo/phi-in-non-affine-region.ll index 6ef24e3f1456..c8e81fd1ba98 100644 --- a/polly/test/ScopInfo/phi-in-non-affine-region.ll +++ b/polly/test/ScopInfo/phi-in-non-affine-region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; Verify that 'tmp' is stored in bb1 and read by bb3, as it is needed as ; incoming value for the tmp11 PHI node. diff --git a/polly/test/ScopInfo/phi_after_error_block.ll b/polly/test/ScopInfo/phi_after_error_block.ll index 039fb86bec5b..21d532b06d60 100644 --- a/polly/test/ScopInfo/phi_after_error_block.ll +++ b/polly/test/ScopInfo/phi_after_error_block.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s declare void @bar() diff --git a/polly/test/ScopInfo/phi_condition_modeling_1.ll b/polly/test/ScopInfo/phi_condition_modeling_1.ll index a879c2005ad8..ca87055630c6 100644 --- a/polly/test/ScopInfo/phi_condition_modeling_1.ll +++ b/polly/test/ScopInfo/phi_condition_modeling_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, int c, int N) { ; int tmp; diff --git a/polly/test/ScopInfo/phi_condition_modeling_2.ll b/polly/test/ScopInfo/phi_condition_modeling_2.ll index cedc140f8438..10511ef0009f 100644 --- a/polly/test/ScopInfo/phi_condition_modeling_2.ll +++ b/polly/test/ScopInfo/phi_condition_modeling_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, int c, int N) { ; int tmp; diff --git a/polly/test/ScopInfo/phi_conditional_simple_1.ll b/polly/test/ScopInfo/phi_conditional_simple_1.ll index 90213a953767..2a009dc26d24 100644 --- a/polly/test/ScopInfo/phi_conditional_simple_1.ll +++ b/polly/test/ScopInfo/phi_conditional_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void jd(int *A, int c) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/ScopInfo/phi_loop_carried_float.ll b/polly/test/ScopInfo/phi_loop_carried_float.ll index d8d2608329bc..5bb740154877 100644 --- a/polly/test/ScopInfo/phi_loop_carried_float.ll +++ b/polly/test/ScopInfo/phi_loop_carried_float.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; float f(float *A, int N) { ; float tmp = 0; diff --git a/polly/test/ScopInfo/phi_not_grouped_at_top.ll b/polly/test/ScopInfo/phi_not_grouped_at_top.ll index be082165b635..1ed22b3fec42 100644 --- a/polly/test/ScopInfo/phi_not_grouped_at_top.ll +++ b/polly/test/ScopInfo/phi_not_grouped_at_top.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-prepare -disable-output < %s +; RUN: opt %loadPolly -passes=polly-prepare -disable-output < %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-n8:16:32:64" declare i32 @funa() align 2 diff --git a/polly/test/ScopInfo/phi_scalar_simple_1.ll b/polly/test/ScopInfo/phi_scalar_simple_1.ll index d042613c023f..eab261b0d153 100644 --- a/polly/test/ScopInfo/phi_scalar_simple_1.ll +++ b/polly/test/ScopInfo/phi_scalar_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; The assumed context should be empty since the flags on the IV ; increments already guarantee that there is no wrap in the loop trip diff --git a/polly/test/ScopInfo/phi_scalar_simple_2.ll b/polly/test/ScopInfo/phi_scalar_simple_2.ll index fb4292e05ca6..73bef9601f33 100644 --- a/polly/test/ScopInfo/phi_scalar_simple_2.ll +++ b/polly/test/ScopInfo/phi_scalar_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; int jd(int *restrict A, int x, int N, int c) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/phi_with_invoke_edge.ll b/polly/test/ScopInfo/phi_with_invoke_edge.ll index dbcf04c0561a..3d7b7d3d38d5 100644 --- a/polly/test/ScopInfo/phi_with_invoke_edge.ll +++ b/polly/test/ScopInfo/phi_with_invoke_edge.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-detect -disable-output < %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %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-n8:16:32:64" declare i32 @generic_personality_v0(i32, i64, ptr, ptr) diff --git a/polly/test/ScopInfo/pointer-comparison-no-nsw.ll b/polly/test/ScopInfo/pointer-comparison-no-nsw.ll index 094c5ccab54d..40d2138f81d5 100644 --- a/polly/test/ScopInfo/pointer-comparison-no-nsw.ll +++ b/polly/test/ScopInfo/pointer-comparison-no-nsw.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, int *B) { ; while (A != B) { diff --git a/polly/test/ScopInfo/pointer-comparison.ll b/polly/test/ScopInfo/pointer-comparison.ll index 15ce0491209a..960b9c5f3132 100644 --- a/polly/test/ScopInfo/pointer-comparison.ll +++ b/polly/test/ScopInfo/pointer-comparison.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; TODO: FIXME: Investigate why we need a InvalidContext here. ; diff --git a/polly/test/ScopInfo/pointer-type-expressions.ll b/polly/test/ScopInfo/pointer-type-expressions.ll index ebbb644340f6..919a9fd4000b 100644 --- a/polly/test/ScopInfo/pointer-type-expressions.ll +++ b/polly/test/ScopInfo/pointer-type-expressions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(int a[], int N, float *P) { ; int i; diff --git a/polly/test/ScopInfo/pointer-used-as-base-pointer-and-scalar-read.ll b/polly/test/ScopInfo/pointer-used-as-base-pointer-and-scalar-read.ll index 3ac86a3443af..1eb053c83132 100644 --- a/polly/test/ScopInfo/pointer-used-as-base-pointer-and-scalar-read.ll +++ b/polly/test/ScopInfo/pointer-used-as-base-pointer-and-scalar-read.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; In this test case we pass a pointer %A into a PHI node and also use this ; pointer as base pointer of an array store. As a result, we get both scalar diff --git a/polly/test/ScopInfo/polly-timeout-parameter-bounds.ll b/polly/test/ScopInfo/polly-timeout-parameter-bounds.ll index 8152010c2c99..7723c185e41c 100644 --- a/polly/test/ScopInfo/polly-timeout-parameter-bounds.ll +++ b/polly/test/ScopInfo/polly-timeout-parameter-bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Statements { ; CHECK-NEXT: Stmt_bb9 diff --git a/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll b/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll index 4a68acd3d509..3cc3e51ef013 100644 --- a/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll +++ b/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/process_added_dimensions.ll b/polly/test/ScopInfo/process_added_dimensions.ll index 6cb270a071f4..66c9ded40f7c 100644 --- a/polly/test/ScopInfo/process_added_dimensions.ll +++ b/polly/test/ScopInfo/process_added_dimensions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Context: ; CHECK-NEXT: { : } diff --git a/polly/test/ScopInfo/pwaff-complexity-bailout.ll b/polly/test/ScopInfo/pwaff-complexity-bailout.ll index 19dd156d27db..5119334745bc 100644 --- a/polly/test/ScopInfo/pwaff-complexity-bailout.ll +++ b/polly/test/ScopInfo/pwaff-complexity-bailout.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-scops -pass-remarks-analysis=.* -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -pass-remarks-analysis=.* -disable-output < %s 2>&1 | FileCheck %s ; Make sure we hit the complexity bailout, and don't crash. ; CHECK: Low complexity assumption: { : false } diff --git a/polly/test/ScopInfo/ranged_parameter.ll b/polly/test/ScopInfo/ranged_parameter.ll index 4b04960ee845..b5cb77593352 100644 --- a/polly/test/ScopInfo/ranged_parameter.ll +++ b/polly/test/ScopInfo/ranged_parameter.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that the constraints on the parameter derived from the ; range metadata (see bottom of the file) are present: diff --git a/polly/test/ScopInfo/ranged_parameter_2.ll b/polly/test/ScopInfo/ranged_parameter_2.ll index cd7d2bfb84d0..52933398f796 100644 --- a/polly/test/ScopInfo/ranged_parameter_2.ll +++ b/polly/test/ScopInfo/ranged_parameter_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output -polly-allow-nonaffine -polly-invariant-load-hoisting=true < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output -polly-allow-nonaffine -polly-invariant-load-hoisting=true < %s \ ; RUN: -debug 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScopInfo/ranged_parameter_wrap.ll b/polly/test/ScopInfo/ranged_parameter_wrap.ll index 173746352cf0..724427fabfd1 100644 --- a/polly/test/ScopInfo/ranged_parameter_wrap.ll +++ b/polly/test/ScopInfo/ranged_parameter_wrap.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that the constraints on the parameter derived from the ; __wrapping__ range metadata (see bottom of the file) are present: diff --git a/polly/test/ScopInfo/ranged_parameter_wrap_2.ll b/polly/test/ScopInfo/ranged_parameter_wrap_2.ll index 33f57f37a1e8..234c3edde14e 100644 --- a/polly/test/ScopInfo/ranged_parameter_wrap_2.ll +++ b/polly/test/ScopInfo/ranged_parameter_wrap_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that the context is built fast and does not explode due to us ; combining a large number of non-convex ranges. Instead, after a certain diff --git a/polly/test/ScopInfo/read-only-scalar-used-in-phi-2.ll b/polly/test/ScopInfo/read-only-scalar-used-in-phi-2.ll index 23c7aa261ac0..1ab8fe897308 100644 --- a/polly/test/ScopInfo/read-only-scalar-used-in-phi-2.ll +++ b/polly/test/ScopInfo/read-only-scalar-used-in-phi-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; float foo(float sum, float A[]) { ; diff --git a/polly/test/ScopInfo/read-only-scalar-used-in-phi.ll b/polly/test/ScopInfo/read-only-scalar-used-in-phi.ll index 20f44c94251c..358b51904c72 100644 --- a/polly/test/ScopInfo/read-only-scalar-used-in-phi.ll +++ b/polly/test/ScopInfo/read-only-scalar-used-in-phi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; float foo(float sum, float A[]) { ; diff --git a/polly/test/ScopInfo/read-only-scalars.ll b/polly/test/ScopInfo/read-only-scalars.ll index 71c2d21e357a..43a456ea9977 100644 --- a/polly/test/ScopInfo/read-only-scalars.ll +++ b/polly/test/ScopInfo/read-only-scalars.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-analyze-read-only-scalars=false -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-analyze-read-only-scalars=true -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=SCALARS +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-analyze-read-only-scalars=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-analyze-read-only-scalars=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=SCALARS ; CHECK-NOT: Memref_scalar diff --git a/polly/test/ScopInfo/read-only-statements.ll b/polly/test/ScopInfo/read-only-statements.ll index a93063ea3ad6..3fa72789f4e1 100644 --- a/polly/test/ScopInfo/read-only-statements.ll +++ b/polly/test/ScopInfo/read-only-statements.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check we remove read only statements. ; diff --git a/polly/test/ScopInfo/reduction_alternating_base.ll b/polly/test/ScopInfo/reduction_alternating_base.ll index 854e28023a3e..f44367f295ff 100644 --- a/polly/test/ScopInfo/reduction_alternating_base.ll +++ b/polly/test/ScopInfo/reduction_alternating_base.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; ; void f(int *A) { diff --git a/polly/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll b/polly/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll index fb0274972082..5636ee7ed828 100644 --- a/polly/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll +++ b/polly/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Reduction Type: NONE ; diff --git a/polly/test/ScopInfo/reduction_different_index.ll b/polly/test/ScopInfo/reduction_different_index.ll index 575e5a16d7b2..7ed9e662a15c 100644 --- a/polly/test/ScopInfo/reduction_different_index.ll +++ b/polly/test/ScopInfo/reduction_different_index.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; Verify if the following case is not detected as reduction. ; ; void f(int *A,int *sum) { diff --git a/polly/test/ScopInfo/reduction_different_index1.ll b/polly/test/ScopInfo/reduction_different_index1.ll index 39bd3c4b9abe..f868bd657f3b 100644 --- a/polly/test/ScopInfo/reduction_different_index1.ll +++ b/polly/test/ScopInfo/reduction_different_index1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; Verify if the following case is not detected as reduction. ; ; void f(int *A, int *sum, int i1, int i2) { diff --git a/polly/test/ScopInfo/reduction_disabled_multiplicative.ll b/polly/test/ScopInfo/reduction_disabled_multiplicative.ll index 7120740fbf34..b031fd352323 100644 --- a/polly/test/ScopInfo/reduction_disabled_multiplicative.ll +++ b/polly/test/ScopInfo/reduction_disabled_multiplicative.ll @@ -1,4 +1,4 @@ -; RUN: opt -basic-aa %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-disable-multiplicative-reductions -disable-output < %s | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-disable-multiplicative-reductions -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: ReadAccess := [Reduction Type: + ; CHECK: { Stmt_for_body[i0] -> MemRef_sum[0] }; diff --git a/polly/test/ScopInfo/reduction_escaping_intermediate.ll b/polly/test/ScopInfo/reduction_escaping_intermediate.ll index dde09108ecc4..dbfa1f1b1d59 100644 --- a/polly/test/ScopInfo/reduction_escaping_intermediate.ll +++ b/polly/test/ScopInfo/reduction_escaping_intermediate.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int N, int * restrict sums, int * restrict escape) { ; int i, j; diff --git a/polly/test/ScopInfo/reduction_escaping_intermediate_2.ll b/polly/test/ScopInfo/reduction_escaping_intermediate_2.ll index 702fc56025d9..1fa8bbcc53e0 100644 --- a/polly/test/ScopInfo/reduction_escaping_intermediate_2.ll +++ b/polly/test/ScopInfo/reduction_escaping_intermediate_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int N, int * restrict sums, int * restrict escape) { ; int i, j; diff --git a/polly/test/ScopInfo/reduction_invalid_different_operators.ll b/polly/test/ScopInfo/reduction_invalid_different_operators.ll index f47919dcad99..d1bfb71fbbd4 100644 --- a/polly/test/ScopInfo/reduction_invalid_different_operators.ll +++ b/polly/test/ScopInfo/reduction_invalid_different_operators.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; int f() { ; int i, sum = 0, sth = 0; diff --git a/polly/test/ScopInfo/reduction_invalid_overlapping_accesses.ll b/polly/test/ScopInfo/reduction_invalid_overlapping_accesses.ll index be1d7b5bbbd9..654475253799 100644 --- a/polly/test/ScopInfo/reduction_invalid_overlapping_accesses.ll +++ b/polly/test/ScopInfo/reduction_invalid_overlapping_accesses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *sums) { ; int i, j; diff --git a/polly/test/ScopInfo/reduction_multiple_loops_array_sum.ll b/polly/test/ScopInfo/reduction_multiple_loops_array_sum.ll index 8d20fa13ffe5..a8167f1c38de 100644 --- a/polly/test/ScopInfo/reduction_multiple_loops_array_sum.ll +++ b/polly/test/ScopInfo/reduction_multiple_loops_array_sum.ll @@ -1,4 +1,4 @@ -; RUN: opt -basic-aa %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Stmt_for_body ; CHECK: Reduction Type: * diff --git a/polly/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll b/polly/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll index 782332b56aad..a0c54572b599 100644 --- a/polly/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll +++ b/polly/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll @@ -1,4 +1,4 @@ -; RUN: opt -basic-aa %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Stmt_for_body ; CHECK: Reduction Type: NONE diff --git a/polly/test/ScopInfo/reduction_multiple_simple_binary.ll b/polly/test/ScopInfo/reduction_multiple_simple_binary.ll index 0f1a3ad90dac..3ed664050a0b 100644 --- a/polly/test/ScopInfo/reduction_multiple_simple_binary.ll +++ b/polly/test/ScopInfo/reduction_multiple_simple_binary.ll @@ -1,4 +1,4 @@ -; RUN: opt -basic-aa %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: ReadAccess := [Reduction Type: NONE ; CHECK: { Stmt_for_body[i0] -> MemRef_A[1 + i0] }; diff --git a/polly/test/ScopInfo/reduction_non_overlapping_chains.ll b/polly/test/ScopInfo/reduction_non_overlapping_chains.ll index 4e3f841cd8e1..7c8c8616a1cd 100644 --- a/polly/test/ScopInfo/reduction_non_overlapping_chains.ll +++ b/polly/test/ScopInfo/reduction_non_overlapping_chains.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Reduction Type: + ; CHECK: Reduction Type: + diff --git a/polly/test/ScopInfo/reduction_only_reduction_like_access.ll b/polly/test/ScopInfo/reduction_only_reduction_like_access.ll index 0c61d63a2d45..95cda973a9b0 100644 --- a/polly/test/ScopInfo/reduction_only_reduction_like_access.ll +++ b/polly/test/ScopInfo/reduction_only_reduction_like_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Reduction Type: + ; diff --git a/polly/test/ScopInfo/reduction_simple_fp.ll b/polly/test/ScopInfo/reduction_simple_fp.ll index ba0a034a17e3..37693353376b 100644 --- a/polly/test/ScopInfo/reduction_simple_fp.ll +++ b/polly/test/ScopInfo/reduction_simple_fp.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Function: f_no_fast_math ; CHECK: Reduction Type: NONE diff --git a/polly/test/ScopInfo/reduction_simple_w_constant.ll b/polly/test/ScopInfo/reduction_simple_w_constant.ll index dc1f8550602d..550882300116 100644 --- a/polly/test/ScopInfo/reduction_simple_w_constant.ll +++ b/polly/test/ScopInfo/reduction_simple_w_constant.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Reduction Type: + ; diff --git a/polly/test/ScopInfo/reduction_simple_w_iv.ll b/polly/test/ScopInfo/reduction_simple_w_iv.ll index b6c3229d08d5..480c2ebf8d47 100644 --- a/polly/test/ScopInfo/reduction_simple_w_iv.ll +++ b/polly/test/ScopInfo/reduction_simple_w_iv.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Reduction Type: + ; diff --git a/polly/test/ScopInfo/reduction_two_identical_reads.ll b/polly/test/ScopInfo/reduction_two_identical_reads.ll index 19d45a5f4ea9..7fce22d15c77 100644 --- a/polly/test/ScopInfo/reduction_two_identical_reads.ll +++ b/polly/test/ScopInfo/reduction_two_identical_reads.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Reduction Type: NONE ; diff --git a/polly/test/ScopInfo/redundant_parameter_constraint.ll b/polly/test/ScopInfo/redundant_parameter_constraint.ll index c9d912191eed..231cab0fda1f 100644 --- a/polly/test/ScopInfo/redundant_parameter_constraint.ll +++ b/polly/test/ScopInfo/redundant_parameter_constraint.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; The constraint that r2 has to be bigger than r1 is implicitly contained in ; the domain, hence we do not want to see it explicitly. diff --git a/polly/test/ScopInfo/region-with-instructions.ll b/polly/test/ScopInfo/region-with-instructions.ll index 39d4a72a7814..a3040636836f 100644 --- a/polly/test/ScopInfo/region-with-instructions.ll +++ b/polly/test/ScopInfo/region-with-instructions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -polly-print-instructions -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -polly-print-instructions -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Statements { ; CHECK: Stmt_bb46 diff --git a/polly/test/ScopInfo/remarks.ll b/polly/test/ScopInfo/remarks.ll index dcdeb58c7694..0a6ef2f1e5f7 100644 --- a/polly/test/ScopInfo/remarks.ll +++ b/polly/test/ScopInfo/remarks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ ; RUN: -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: remark: test/ScopInfo/remarks.c:4:7: SCoP begins here. diff --git a/polly/test/ScopInfo/required-invariant-loop-bounds.ll b/polly/test/ScopInfo/required-invariant-loop-bounds.ll index 248acbea6e68..19ed625a85db 100644 --- a/polly/test/ScopInfo/required-invariant-loop-bounds.ll +++ b/polly/test/ScopInfo/required-invariant-loop-bounds.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/restriction_in_dead_block.ll b/polly/test/ScopInfo/restriction_in_dead_block.ll index 81d9b96be419..27df53f03b03 100644 --- a/polly/test/ScopInfo/restriction_in_dead_block.ll +++ b/polly/test/ScopInfo/restriction_in_dead_block.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify we do not generate an empty invalid context only because the wrap ; in the second conditional will always happen if the block is executed. diff --git a/polly/test/ScopInfo/run-time-check-many-array-disjuncts.ll b/polly/test/ScopInfo/run-time-check-many-array-disjuncts.ll index d36da2b2becf..e84a1b3e5bc6 100644 --- a/polly/test/ScopInfo/run-time-check-many-array-disjuncts.ll +++ b/polly/test/ScopInfo/run-time-check-many-array-disjuncts.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s -check-prefix=DETECT -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s ; ; DETECT: Valid Region for Scop: bb124 => bb176 ; diff --git a/polly/test/ScopInfo/run-time-check-many-parameters.ll b/polly/test/ScopInfo/run-time-check-many-parameters.ll index 30f8d5fff34c..540ea57fad0c 100644 --- a/polly/test/ScopInfo/run-time-check-many-parameters.ll +++ b/polly/test/ScopInfo/run-time-check-many-parameters.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s ; ; A valid Scop would print the list of it's statements, we check that we do not ; see that list. diff --git a/polly/test/ScopInfo/run-time-check-many-piecewise-aliasing.ll b/polly/test/ScopInfo/run-time-check-many-piecewise-aliasing.ll index 487c803bba98..cefda1eed0c6 100644 --- a/polly/test/ScopInfo/run-time-check-many-piecewise-aliasing.ll +++ b/polly/test/ScopInfo/run-time-check-many-piecewise-aliasing.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-print-detect -disable-output < %s \ +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s -check-prefix=DETECT -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s ; ; DETECT: Valid Region for Scop: for => return ; diff --git a/polly/test/ScopInfo/run-time-check-read-only-arrays.ll b/polly/test/ScopInfo/run-time-check-read-only-arrays.ll index d590aaf00ddb..395622b12616 100644 --- a/polly/test/ScopInfo/run-time-check-read-only-arrays.ll +++ b/polly/test/ScopInfo/run-time-check-read-only-arrays.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void foo(float *A, float *B, float *C, long N) { ; for (long i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/same-base-address-scalar-and-array.ll b/polly/test/ScopInfo/same-base-address-scalar-and-array.ll index a5f353e7ad2a..22cf77636d10 100644 --- a/polly/test/ScopInfo/same-base-address-scalar-and-array.ll +++ b/polly/test/ScopInfo/same-base-address-scalar-and-array.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify we introduce two ScopArrayInfo objects (or virtual arrays) for the %out variable ; as it is used as a memory base pointer (%0) but also as a scalar (%out.addr.0.lcssa). diff --git a/polly/test/ScopInfo/scalar.ll b/polly/test/ScopInfo/scalar.ll index c38eaa853b9b..80493723bbfc 100644 --- a/polly/test/ScopInfo/scalar.ll +++ b/polly/test/ScopInfo/scalar.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | 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" diff --git a/polly/test/ScopInfo/scalar_dependence_cond_br.ll b/polly/test/ScopInfo/scalar_dependence_cond_br.ll index 3303bfb7c6c5..940dabbc4cfc 100644 --- a/polly/test/ScopInfo/scalar_dependence_cond_br.ll +++ b/polly/test/ScopInfo/scalar_dependence_cond_br.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output< %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output< %s 2>&1 | FileCheck %s ; ; void f(int *A, int c, int d) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/ScopInfo/scalar_to_array.ll b/polly/test/ScopInfo/scalar_to_array.ll index 5c275108602a..692a0dbd67c8 100644 --- a/polly/test/ScopInfo/scalar_to_array.ll +++ b/polly/test/ScopInfo/scalar_to_array.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -basic-aa -polly-print-function-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ModuleID = 'scalar_to_array.ll' 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/scev-div-with-evaluatable-divisor.ll b/polly/test/ScopInfo/scev-div-with-evaluatable-divisor.ll index fc7a1bfc3d5e..f969176cee16 100644 --- a/polly/test/ScopInfo/scev-div-with-evaluatable-divisor.ll +++ b/polly/test/ScopInfo/scev-div-with-evaluatable-divisor.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; Derived from test-suite/SingleSource/UnitTests/Vector/SSE/sse.stepfft.c diff --git a/polly/test/ScopInfo/scev-invalidated.ll b/polly/test/ScopInfo/scev-invalidated.ll index 97fc5ec3d4ca..921cb06a0cd5 100644 --- a/polly/test/ScopInfo/scev-invalidated.ll +++ b/polly/test/ScopInfo/scev-invalidated.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Region: %if.then6---%return ; diff --git a/polly/test/ScopInfo/schedule-const-post-dominator-walk-2.ll b/polly/test/ScopInfo/schedule-const-post-dominator-walk-2.ll index 2fdf7d66c3ad..e956b0ed7cb9 100644 --- a/polly/test/ScopInfo/schedule-const-post-dominator-walk-2.ll +++ b/polly/test/ScopInfo/schedule-const-post-dominator-walk-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/schedule-const-post-dominator-walk.ll b/polly/test/ScopInfo/schedule-const-post-dominator-walk.ll index 92685858610c..325d19dd210d 100644 --- a/polly/test/ScopInfo/schedule-const-post-dominator-walk.ll +++ b/polly/test/ScopInfo/schedule-const-post-dominator-walk.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/schedule-constuction-endless-loop1.ll b/polly/test/ScopInfo/schedule-constuction-endless-loop1.ll index 413d1d8ec556..0225c53faa9a 100644 --- a/polly/test/ScopInfo/schedule-constuction-endless-loop1.ll +++ b/polly/test/ScopInfo/schedule-constuction-endless-loop1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that we do not build a SCoP and do not crash. ; diff --git a/polly/test/ScopInfo/schedule-constuction-endless-loop2.ll b/polly/test/ScopInfo/schedule-constuction-endless-loop2.ll index be254477286f..bc34070dcf46 100644 --- a/polly/test/ScopInfo/schedule-constuction-endless-loop2.ll +++ b/polly/test/ScopInfo/schedule-constuction-endless-loop2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s ; ; Check that we do not build a SCoP and do not crash. ; diff --git a/polly/test/ScopInfo/schedule-incorrectly-contructed-in-case-of-infinite-loop.ll b/polly/test/ScopInfo/schedule-incorrectly-contructed-in-case-of-infinite-loop.ll index ff339e03fb5a..f8b3dfea844f 100644 --- a/polly/test/ScopInfo/schedule-incorrectly-contructed-in-case-of-infinite-loop.ll +++ b/polly/test/ScopInfo/schedule-incorrectly-contructed-in-case-of-infinite-loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -polly-scops -disable-output < %s +; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print' -disable-output < %s ; ; This test contains a infinite loop (bb13) and crashed the domain generation ; at some point. Just verify it does not anymore. diff --git a/polly/test/ScopInfo/scop-affine-parameter-ordering.ll b/polly/test/ScopInfo/scop-affine-parameter-ordering.ll index 24c028a6764a..5a8019eabe9d 100644 --- a/polly/test/ScopInfo/scop-affine-parameter-ordering.ll +++ b/polly/test/ScopInfo/scop-affine-parameter-ordering.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-i128:128-n8:16:32:64-S128" target triple = "aarch64--linux-android" diff --git a/polly/test/ScopInfo/sign_wrapped_set.ll b/polly/test/ScopInfo/sign_wrapped_set.ll index 23c9c8a3b84d..7b24f29563ea 100644 --- a/polly/test/ScopInfo/sign_wrapped_set.ll +++ b/polly/test/ScopInfo/sign_wrapped_set.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-process-unprofitable -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-process-unprofitable '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Domain := ; CHECK-NEXT: [srcHeight] -> { Stmt_for_cond6_preheader_us[i0] : 0 <= i0 <= -3 + srcHeight }; diff --git a/polly/test/ScopInfo/simple_loop_1.ll b/polly/test/ScopInfo/simple_loop_1.ll index 2c3481facc02..4872b8e59ba9 100644 --- a/polly/test/ScopInfo/simple_loop_1.ll +++ b/polly/test/ScopInfo/simple_loop_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(int a[], int N) { ; int i; diff --git a/polly/test/ScopInfo/simple_loop_2.ll b/polly/test/ScopInfo/simple_loop_2.ll index 2f580094a147..120b5e790077 100644 --- a/polly/test/ScopInfo/simple_loop_2.ll +++ b/polly/test/ScopInfo/simple_loop_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(int a[], int N) { ; int i; diff --git a/polly/test/ScopInfo/simple_loop_unsigned.ll b/polly/test/ScopInfo/simple_loop_unsigned.ll index 12903d9c1580..6c0e8798a6cd 100644 --- a/polly/test/ScopInfo/simple_loop_unsigned.ll +++ b/polly/test/ScopInfo/simple_loop_unsigned.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(int a[], unsigned N) { ; unsigned i; diff --git a/polly/test/ScopInfo/simple_loop_unsigned_2.ll b/polly/test/ScopInfo/simple_loop_unsigned_2.ll index 1379180a6dd9..4b19a8c52c6b 100644 --- a/polly/test/ScopInfo/simple_loop_unsigned_2.ll +++ b/polly/test/ScopInfo/simple_loop_unsigned_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/simple_loop_unsigned_3.ll b/polly/test/ScopInfo/simple_loop_unsigned_3.ll index 7783c4681e1f..fd974f219bec 100644 --- a/polly/test/ScopInfo/simple_loop_unsigned_3.ll +++ b/polly/test/ScopInfo/simple_loop_unsigned_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/simple_nonaffine_loop_not.ll b/polly/test/ScopInfo/simple_nonaffine_loop_not.ll index 42eff85d8c9b..d2aa22f8cca7 100644 --- a/polly/test/ScopInfo/simple_nonaffine_loop_not.ll +++ b/polly/test/ScopInfo/simple_nonaffine_loop_not.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | not FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | not 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-n8:16:32:64-S128" @.str = private unnamed_addr constant [17 x i8] c"Random Value: %d\00", align 1 diff --git a/polly/test/ScopInfo/smax.ll b/polly/test/ScopInfo/smax.ll index b938e4e412da..502d52baaaef 100644 --- a/polly/test/ScopInfo/smax.ll +++ b/polly/test/ScopInfo/smax.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:32-n32-S64" define void @foo(ptr noalias %data, ptr noalias %ptr, i32 %x_pos, i32 %w) { diff --git a/polly/test/ScopInfo/statistics.ll b/polly/test/ScopInfo/statistics.ll index 3797b7d71df9..c69852e21875 100644 --- a/polly/test/ScopInfo/statistics.ll +++ b/polly/test/ScopInfo/statistics.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-scops -stats -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -stats -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; CHECK-DAG: 4 polly-scops - Maximal number of loops in scops diff --git a/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll b/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll index d86d2418cf9b..1d4d3f19b571 100644 --- a/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll +++ b/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Region__TO__Stmt diff --git a/polly/test/ScopInfo/stmt_split_no_after_split.ll b/polly/test/ScopInfo/stmt_split_no_after_split.ll index f8339bd8ae94..e3e440584f25 100644 --- a/polly/test/ScopInfo/stmt_split_no_after_split.ll +++ b/polly/test/ScopInfo/stmt_split_no_after_split.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_split_no_dependence.ll b/polly/test/ScopInfo/stmt_split_no_dependence.ll index 7ad48f499792..0bf98c9b70be 100644 --- a/polly/test/ScopInfo/stmt_split_no_dependence.ll +++ b/polly/test/ScopInfo/stmt_split_no_dependence.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void func(int *A, int *B){ ; for (int i = 0; i < 1024; i+=1) { diff --git a/polly/test/ScopInfo/stmt_split_on_store.ll b/polly/test/ScopInfo/stmt_split_on_store.ll index 6af3dc8633dd..82b1f5bbc3cd 100644 --- a/polly/test/ScopInfo/stmt_split_on_store.ll +++ b/polly/test/ScopInfo/stmt_split_on_store.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=store -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=store -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void func(int *A, int *B){ ; for (int i = 0; i < 1024; i+=1) { diff --git a/polly/test/ScopInfo/stmt_split_on_synthesizable.ll b/polly/test/ScopInfo/stmt_split_on_synthesizable.ll index 92855cfd0124..323c83bc570e 100644 --- a/polly/test/ScopInfo/stmt_split_on_synthesizable.ll +++ b/polly/test/ScopInfo/stmt_split_on_synthesizable.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll b/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll index ee6afa4638d2..7f72e672a1a6 100644 --- a/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll +++ b/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll b/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll index 0a5f41d637e7..9306cdc7615a 100644 --- a/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll +++ b/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_split_scalar_dependence.ll b/polly/test/ScopInfo/stmt_split_scalar_dependence.ll index 5b02d1b5d08a..efd5cf14def0 100644 --- a/polly/test/ScopInfo/stmt_split_scalar_dependence.ll +++ b/polly/test/ScopInfo/stmt_split_scalar_dependence.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_split_within_loop.ll b/polly/test/ScopInfo/stmt_split_within_loop.ll index 3ed9bbbeaccb..f24904df307c 100644 --- a/polly/test/ScopInfo/stmt_split_within_loop.ll +++ b/polly/test/ScopInfo/stmt_split_within_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_with_read_but_without_sideffect.ll b/polly/test/ScopInfo/stmt_with_read_but_without_sideffect.ll index 73fc543a66e8..41f58844569f 100644 --- a/polly/test/ScopInfo/stmt_with_read_but_without_sideffect.ll +++ b/polly/test/ScopInfo/stmt_with_read_but_without_sideffect.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; The statement Stmt_for_if_else_1 should be removed because it has no ; sideeffects. But it has a use of MemRef_tmp21 that must also be diff --git a/polly/test/ScopInfo/switch-1.ll b/polly/test/ScopInfo/switch-1.ll index 0ea40a7ed251..6bc630834e93 100644 --- a/polly/test/ScopInfo/switch-1.ll +++ b/polly/test/ScopInfo/switch-1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/switch-2.ll b/polly/test/ScopInfo/switch-2.ll index 7956058c9de6..a64d133baae7 100644 --- a/polly/test/ScopInfo/switch-2.ll +++ b/polly/test/ScopInfo/switch-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/switch-3.ll b/polly/test/ScopInfo/switch-3.ll index aa7ada4edbb8..3aa2d7811c77 100644 --- a/polly/test/ScopInfo/switch-3.ll +++ b/polly/test/ScopInfo/switch-3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/switch-4.ll b/polly/test/ScopInfo/switch-4.ll index 6aeb7197e382..567c3de030ea 100644 --- a/polly/test/ScopInfo/switch-4.ll +++ b/polly/test/ScopInfo/switch-4.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/switch-5.ll b/polly/test/ScopInfo/switch-5.ll index 24cc92a0933d..b6a42d9da749 100644 --- a/polly/test/ScopInfo/switch-5.ll +++ b/polly/test/ScopInfo/switch-5.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/switch-6.ll b/polly/test/ScopInfo/switch-6.ll index efb3df504d23..24538328c581 100644 --- a/polly/test/ScopInfo/switch-6.ll +++ b/polly/test/ScopInfo/switch-6.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) { diff --git a/polly/test/ScopInfo/switch-7.ll b/polly/test/ScopInfo/switch-7.ll index 2f0d034e84fe..99c1bed81874 100644 --- a/polly/test/ScopInfo/switch-7.ll +++ b/polly/test/ScopInfo/switch-7.ll @@ -1,6 +1,5 @@ - -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST ; ; void f(int *A, int c, int N) { ; switch (c) { diff --git a/polly/test/ScopInfo/tempscop-printing.ll b/polly/test/ScopInfo/tempscop-printing.ll index 80c675d4c3d3..e99a6f2582ee 100644 --- a/polly/test/ScopInfo/tempscop-printing.ll +++ b/polly/test/ScopInfo/tempscop-printing.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -basic-aa -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(long A[], int N, int *init_ptr) { ; long i, j; diff --git a/polly/test/ScopInfo/test-wrapping-in-condition.ll b/polly/test/ScopInfo/test-wrapping-in-condition.ll index 3ff978f7265e..7c1301748c39 100644 --- a/polly/test/ScopInfo/test-wrapping-in-condition.ll +++ b/polly/test/ScopInfo/test-wrapping-in-condition.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invalid Context: ; CHECK: [N] -> { : N >= 129 } diff --git a/polly/test/ScopInfo/truncate-1.ll b/polly/test/ScopInfo/truncate-1.ll index 5c5fac150b4b..b21755c67ac4 100644 --- a/polly/test/ScopInfo/truncate-1.ll +++ b/polly/test/ScopInfo/truncate-1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(char *A, short N) { ; for (char i = 0; i < (char)N; i++) diff --git a/polly/test/ScopInfo/truncate-2.ll b/polly/test/ScopInfo/truncate-2.ll index e6c5f2cb32d0..0d4abb343993 100644 --- a/polly/test/ScopInfo/truncate-2.ll +++ b/polly/test/ScopInfo/truncate-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(char *A, short N) { ; for (short i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/truncate-3.ll b/polly/test/ScopInfo/truncate-3.ll index dd0fe489e990..f9cdd0274f22 100644 --- a/polly/test/ScopInfo/truncate-3.ll +++ b/polly/test/ScopInfo/truncate-3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-scops -pass-remarks-analysis="polly-scops" \ +; RUN: opt %loadPolly '-passes=print' -pass-remarks-analysis="polly-scops" \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Signed-unsigned restriction: [p] -> { : p <= -129 or p >= 128 } diff --git a/polly/test/ScopInfo/two-loops-one-infinite.ll b/polly/test/ScopInfo/two-loops-one-infinite.ll index 71f72383b048..02ad18e3d567 100644 --- a/polly/test/ScopInfo/two-loops-one-infinite.ll +++ b/polly/test/ScopInfo/two-loops-one-infinite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s ; ; Verify we do not create a SCoP in the presence of infinite loops. ; diff --git a/polly/test/ScopInfo/two-loops-right-after-each-other.ll b/polly/test/ScopInfo/two-loops-right-after-each-other.ll index dd457c31afdd..36ab13a68c1e 100644 --- a/polly/test/ScopInfo/two-loops-right-after-each-other.ll +++ b/polly/test/ScopInfo/two-loops-right-after-each-other.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Statements { ; CHECK-NEXT: Stmt_loop_1 diff --git a/polly/test/ScopInfo/undef_in_cond.ll b/polly/test/ScopInfo/undef_in_cond.ll index 5282a853c17a..4bdcc1697068 100644 --- a/polly/test/ScopInfo/undef_in_cond.ll +++ b/polly/test/ScopInfo/undef_in_cond.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | 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-n8:16:32:64" define fastcc void @fix_operands() nounwind { diff --git a/polly/test/ScopInfo/unnamed_nonaffine.ll b/polly/test/ScopInfo/unnamed_nonaffine.ll index bf32cc7806f4..d9415eabab94 100644 --- a/polly/test/ScopInfo/unnamed_nonaffine.ll +++ b/polly/test/ScopInfo/unnamed_nonaffine.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-use-llvm-names=true -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-use-llvm-names=false -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=UNNAMED +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-use-llvm-names=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-use-llvm-names=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=UNNAMED ; ; void f(int *A, int b) { ; int x; diff --git a/polly/test/ScopInfo/unnamed_stmts.ll b/polly/test/ScopInfo/unnamed_stmts.ll index 686c0f87d9cf..0bd53d8c8425 100644 --- a/polly/test/ScopInfo/unnamed_stmts.ll +++ b/polly/test/ScopInfo/unnamed_stmts.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; This test case verifies that we generate numbered statement names in case ; no LLVM-IR names are used in the test case. We also verify, that we diff --git a/polly/test/ScopInfo/unpredictable_nonscop_loop.ll b/polly/test/ScopInfo/unpredictable_nonscop_loop.ll index 0656b77e3409..c0e768216eb0 100644 --- a/polly/test/ScopInfo/unpredictable_nonscop_loop.ll +++ b/polly/test/ScopInfo/unpredictable_nonscop_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; Derived from test-suite/MultiSource/Applications/sgefa/blas.c ; ; The exit value of %i.0320 in land.rhs is not computable. diff --git a/polly/test/ScopInfo/unprofitable_scalar-accs.ll b/polly/test/ScopInfo/unprofitable_scalar-accs.ll index 9703587091a7..e7c8a57093b8 100644 --- a/polly/test/ScopInfo/unprofitable_scalar-accs.ll +++ b/polly/test/ScopInfo/unprofitable_scalar-accs.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=false -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=true -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=HEURISTIC +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=false '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=true '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=HEURISTIC ; Check the effect of -polly-unprofitable-scalar-accs diff --git a/polly/test/ScopInfo/unsigned-condition.ll b/polly/test/ScopInfo/unsigned-condition.ll index 35673d1b6a36..1dca9bab41ec 100644 --- a/polly/test/ScopInfo/unsigned-condition.ll +++ b/polly/test/ScopInfo/unsigned-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(int a[], int N, unsigned P) { ; int i; diff --git a/polly/test/ScopInfo/unsigned-division-1.ll b/polly/test/ScopInfo/unsigned-division-1.ll index 8c65062bd941..da080b3a306b 100644 --- a/polly/test/ScopInfo/unsigned-division-1.ll +++ b/polly/test/ScopInfo/unsigned-division-1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, unsigned N) { ; for (unsigned i = 0; i < N / 2; i++) diff --git a/polly/test/ScopInfo/unsigned-division-2.ll b/polly/test/ScopInfo/unsigned-division-2.ll index bf4ebce9099a..2fe4207d1bd1 100644 --- a/polly/test/ScopInfo/unsigned-division-2.ll +++ b/polly/test/ScopInfo/unsigned-division-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, unsigned N) { ; for (unsigned i = 0; i < N / 2 + 3; i++) diff --git a/polly/test/ScopInfo/unsigned-division-3.ll b/polly/test/ScopInfo/unsigned-division-3.ll index 47ba1f2ef09d..aefb590b28df 100644 --- a/polly/test/ScopInfo/unsigned-division-3.ll +++ b/polly/test/ScopInfo/unsigned-division-3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, unsigned char N) { ; for (unsigned i = 0; i <= N / -128; i++) diff --git a/polly/test/ScopInfo/unsigned-division-4.ll b/polly/test/ScopInfo/unsigned-division-4.ll index edcd8a18a854..9fe10d7440ef 100644 --- a/polly/test/ScopInfo/unsigned-division-4.ll +++ b/polly/test/ScopInfo/unsigned-division-4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, unsigned char N) { ; for (unsigned i = 0; i < (N / -128) + 3; i++) diff --git a/polly/test/ScopInfo/unsigned-division-5.ll b/polly/test/ScopInfo/unsigned-division-5.ll index f9a3d39288a9..fb90345f477e 100644 --- a/polly/test/ScopInfo/unsigned-division-5.ll +++ b/polly/test/ScopInfo/unsigned-division-5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, unsigned N) { ; for (unsigned i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/unsigned_wrap_uge.ll b/polly/test/ScopInfo/unsigned_wrap_uge.ll index 89c50ee3764b..3d54cad70285 100644 --- a/polly/test/ScopInfo/unsigned_wrap_uge.ll +++ b/polly/test/ScopInfo/unsigned_wrap_uge.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Unsigned wrap-around check. ; diff --git a/polly/test/ScopInfo/unsigned_wrap_ugt.ll b/polly/test/ScopInfo/unsigned_wrap_ugt.ll index 3249123c9918..8c98f13cfb72 100644 --- a/polly/test/ScopInfo/unsigned_wrap_ugt.ll +++ b/polly/test/ScopInfo/unsigned_wrap_ugt.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Unsigned wrap-around check. ; diff --git a/polly/test/ScopInfo/unsigned_wrap_ule.ll b/polly/test/ScopInfo/unsigned_wrap_ule.ll index 3c6ea18b439c..e0b0339475fc 100644 --- a/polly/test/ScopInfo/unsigned_wrap_ule.ll +++ b/polly/test/ScopInfo/unsigned_wrap_ule.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Unsigned wrap-around check. ; diff --git a/polly/test/ScopInfo/unsigned_wrap_ult.ll b/polly/test/ScopInfo/unsigned_wrap_ult.ll index 5d859f85d52b..cb15bc04669e 100644 --- a/polly/test/ScopInfo/unsigned_wrap_ult.ll +++ b/polly/test/ScopInfo/unsigned_wrap_ult.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; Unsigned wrap-around check. ; diff --git a/polly/test/ScopInfo/user_context.ll b/polly/test/ScopInfo/user_context.ll index 46232cd59c03..d67244e1ad95 100644 --- a/polly/test/ScopInfo/user_context.ll +++ b/polly/test/ScopInfo/user_context.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-context='[N] -> {: N = 1024}' -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=CTX -; RUN: opt %loadPolly -polly-context='[N,M] -> {: 1 = 0}' -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-context='[] -> {: 1 = 0}' -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-context='[N] -> {: N = 1024}' '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=CTX +; RUN: opt %loadPolly -polly-context='[N,M] -> {: 1 = 0}' '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-context='[] -> {: 1 = 0}' '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; void f(int a[], int N) { ; int i; diff --git a/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed-conditional.ll b/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed-conditional.ll index 4bd02c96a3d2..829d1ef10664 100644 --- a/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed-conditional.ll +++ b/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed-conditional.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REMARK -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REMARK +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; REMARK: remark: :0:0: Use user assumption: [n, b] -> { : n <= 100 or (b = 0 and n >= 101) } ; diff --git a/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed.ll b/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed.ll index 262bd1349a69..8518a0ece23c 100644 --- a/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed.ll +++ b/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Context: ; CHECK-NEXT: [n] -> { : -9223372036854775808 <= n <= 100 } diff --git a/polly/test/ScopInfo/user_provided_assumptions-in-bb-unsigned.ll b/polly/test/ScopInfo/user_provided_assumptions-in-bb-unsigned.ll index 4a10fcff929a..678be1c06d0a 100644 --- a/polly/test/ScopInfo/user_provided_assumptions-in-bb-unsigned.ll +++ b/polly/test/ScopInfo/user_provided_assumptions-in-bb-unsigned.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REMARK -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REMARK +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; REMARK: remark: :0:0: SCoP begins here. ; REMARK-NEXT: remark: :0:0: Use user assumption: [n] -> { : n <= 100 } diff --git a/polly/test/ScopInfo/user_provided_assumptions.ll b/polly/test/ScopInfo/user_provided_assumptions.ll index 6640e4a65e36..e4556eb3a386 100644 --- a/polly/test/ScopInfo/user_provided_assumptions.ll +++ b/polly/test/ScopInfo/user_provided_assumptions.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP ; ; CHECK: remark: :0:0: SCoP begins here. ; CHECK-NEXT: remark: :0:0: Use user assumption: [M, N] -> { : N <= 2147483647 - M } diff --git a/polly/test/ScopInfo/user_provided_assumptions_2.ll b/polly/test/ScopInfo/user_provided_assumptions_2.ll index 994cd6f15103..98057740eab3 100644 --- a/polly/test/ScopInfo/user_provided_assumptions_2.ll +++ b/polly/test/ScopInfo/user_provided_assumptions_2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP ; ; CHECK: remark: :0:0: SCoP begins here. ; CHECK-NEXT: remark: :0:0: Use user assumption: { : } diff --git a/polly/test/ScopInfo/user_provided_assumptions_3.ll b/polly/test/ScopInfo/user_provided_assumptions_3.ll index 2fcde8bd1826..de3fbba46e0a 100644 --- a/polly/test/ScopInfo/user_provided_assumptions_3.ll +++ b/polly/test/ScopInfo/user_provided_assumptions_3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP ; ; CHECK: remark: :0:0: SCoP begins here. ; CHECK-NEXT: remark: :0:0: Use user assumption: [N] -> { : N >= 2 } diff --git a/polly/test/ScopInfo/user_provided_non_dominating_assumptions.ll b/polly/test/ScopInfo/user_provided_non_dominating_assumptions.ll index 1eb3c15810e4..4f3be408c9ef 100644 --- a/polly/test/ScopInfo/user_provided_non_dominating_assumptions.ll +++ b/polly/test/ScopInfo/user_provided_non_dominating_assumptions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ ; RUN: -polly-precise-inbounds -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: remark: :0:0: SCoP begins here. @@ -18,7 +18,7 @@ ; -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ ; RUN: -polly-precise-inbounds -disable-output < %s 2>&1 -pass-remarks-output=%t.yaml ; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s ; YAML: --- !Analysis diff --git a/polly/test/ScopInfo/variant_base_pointer.ll b/polly/test/ScopInfo/variant_base_pointer.ll index 321657c87e79..3a6ea88d3473 100644 --- a/polly/test/ScopInfo/variant_base_pointer.ll +++ b/polly/test/ScopInfo/variant_base_pointer.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true -polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true -passes=polly-codegen -disable-output < %s ; ; %tmp is added to the list of required hoists by -polly-scops and just ; assumed to be hoisted. Only -polly-scops recognizes it to be unhoistable diff --git a/polly/test/ScopInfo/variant_load_empty_domain.ll b/polly/test/ScopInfo/variant_load_empty_domain.ll index 0e685c3c7e73..4b91778a225b 100644 --- a/polly/test/ScopInfo/variant_load_empty_domain.ll +++ b/polly/test/ScopInfo/variant_load_empty_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: } diff --git a/polly/test/ScopInfo/wraping_signed_expr_0.ll b/polly/test/ScopInfo/wraping_signed_expr_0.ll index 7ad0f64028b6..bbb49bffe925 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_0.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_0.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, char N, char p) { ; for (char i = 0; i < N; i++) { diff --git a/polly/test/ScopInfo/wraping_signed_expr_1.ll b/polly/test/ScopInfo/wraping_signed_expr_1.ll index 0a62b9cf542c..e43a691312a0 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_1.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(long *A, long N, long p) { ; for (long i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/wraping_signed_expr_2.ll b/polly/test/ScopInfo/wraping_signed_expr_2.ll index f3b4665f7f37..eef357acc582 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_2.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, int N, int p) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/wraping_signed_expr_3.ll b/polly/test/ScopInfo/wraping_signed_expr_3.ll index 7a5cbba9436b..a0500eb48941 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_3.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(int *A, int N, int p) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/wraping_signed_expr_4.ll b/polly/test/ScopInfo/wraping_signed_expr_4.ll index ec65f70a092f..d21f321e4ac9 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_4.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(char *A, char N, char p) { ; for (char i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/wraping_signed_expr_5.ll b/polly/test/ScopInfo/wraping_signed_expr_5.ll index 5f3b09ba33c1..395342d2f55a 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_5.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; We should not generate runtime check for ((int)r1 + (int)r2) as it is known not ; to overflow. However (p + q) can, thus checks are needed. diff --git a/polly/test/ScopInfo/wraping_signed_expr_6.ll b/polly/test/ScopInfo/wraping_signed_expr_6.ll index 23258bb513bf..4147f7fa20cf 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_6.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_6.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invalid Context: ; CHECK: [N] -> { : N >= 129 } diff --git a/polly/test/ScopInfo/wraping_signed_expr_7.ll b/polly/test/ScopInfo/wraping_signed_expr_7.ll index 0663d4e0bc10..f41e89c07db0 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_7.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_7.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Invalid Context: ; CHECK: [N] -> { : N >= 129 } diff --git a/polly/test/ScopInfo/wraping_signed_expr_slow_1.ll b/polly/test/ScopInfo/wraping_signed_expr_slow_1.ll index ec36d2c5fcde..ddaeed06874a 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_slow_1.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_slow_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; This checks that the no-wraps checks will be computed fast as some example ; already showed huge slowdowns even though the inbounds and nsw flags were diff --git a/polly/test/ScopInfo/wraping_signed_expr_slow_2.ll b/polly/test/ScopInfo/wraping_signed_expr_slow_2.ll index 6db33ab166d5..798a5d0855b3 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_slow_2.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_slow_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; This checks that the no-wraps checks will be computed fast as some example ; already showed huge slowdowns even though the inbounds and nsw flags were diff --git a/polly/test/ScopInfo/zero_ext_of_truncate.ll b/polly/test/ScopInfo/zero_ext_of_truncate.ll index fc55df5e053c..bf5b6354a6d6 100644 --- a/polly/test/ScopInfo/zero_ext_of_truncate.ll +++ b/polly/test/ScopInfo/zero_ext_of_truncate.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(unsigned *restrict I, unsigned *restrict A, unsigned N, unsigned M) { ; for (unsigned i = 0; i < N; i++) { diff --git a/polly/test/ScopInfo/zero_ext_of_truncate_2.ll b/polly/test/ScopInfo/zero_ext_of_truncate_2.ll index 13e9c03ecd2d..595b21c71869 100644 --- a/polly/test/ScopInfo/zero_ext_of_truncate_2.ll +++ b/polly/test/ScopInfo/zero_ext_of_truncate_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; void f(unsigned long *restrict I, unsigned *restrict A, unsigned N) { ; for (unsigned i = 0; i < N; i++) { diff --git a/polly/test/ScopInfo/zero_ext_space_mismatch.ll b/polly/test/ScopInfo/zero_ext_space_mismatch.ll index 835a8664b75e..0a329fdef8c2 100644 --- a/polly/test/ScopInfo/zero_ext_space_mismatch.ll +++ b/polly/test/ScopInfo/zero_ext_space_mismatch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: [dim] -> { : dim > 0 } diff --git a/polly/test/ScopInliner/invariant-load-func.ll b/polly/test/ScopInliner/invariant-load-func.ll index 38e4a15aab94..8da50f90beba 100644 --- a/polly/test/ScopInliner/invariant-load-func.ll +++ b/polly/test/ScopInliner/invariant-load-func.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly -polly-detect-full-functions -polly-scop-inliner \ -; RUN: -polly-invariant-load-hoisting -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: -polly-invariant-load-hoisting '-passes=print' -disable-output < %s | FileCheck %s ; Check that we inline a function that requires invariant load hoisting ; correctly. diff --git a/polly/test/Simplify/coalesce_3partials.ll b/polly/test/Simplify/coalesce_3partials.ll index 0c1556ff263a..937f655c344c 100644 --- a/polly/test/Simplify/coalesce_3partials.ll +++ b/polly/test/Simplify/coalesce_3partials.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s ; ; Combine 3 partial accesses into one. ; diff --git a/polly/test/Simplify/coalesce_disjointelements.ll b/polly/test/Simplify/coalesce_disjointelements.ll index 2f4cf4e3f920..6080ee4dde81 100644 --- a/polly/test/Simplify/coalesce_disjointelements.ll +++ b/polly/test/Simplify/coalesce_disjointelements.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s ; ; Combine four partial stores into two. ; The stores write to the same array, but never the same element. diff --git a/polly/test/Simplify/coalesce_overlapping.ll b/polly/test/Simplify/coalesce_overlapping.ll index 78ed21e9855b..3c52d44e8003 100644 --- a/polly/test/Simplify/coalesce_overlapping.ll +++ b/polly/test/Simplify/coalesce_overlapping.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s ; ; Combine two partial stores (with overlapping domains) into one. ; diff --git a/polly/test/Simplify/coalesce_partial.ll b/polly/test/Simplify/coalesce_partial.ll index c42aaa113035..cec58a9121b2 100644 --- a/polly/test/Simplify/coalesce_partial.ll +++ b/polly/test/Simplify/coalesce_partial.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s ; ; Combine two partial stores (with disjoint domains) into one. ; diff --git a/polly/test/Simplify/dead_access_load.ll b/polly/test/Simplify/dead_access_load.ll index 1804613c0a79..5e0a9b574516 100644 --- a/polly/test/Simplify/dead_access_load.ll +++ b/polly/test/Simplify/dead_access_load.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Remove a dead load-instruction ; (an load whose result is not used anywhere) diff --git a/polly/test/Simplify/dead_access_phi.ll b/polly/test/Simplify/dead_access_phi.ll index d263b89aff58..6044f7f50be7 100644 --- a/polly/test/Simplify/dead_access_phi.ll +++ b/polly/test/Simplify/dead_access_phi.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Remove a dead PHI write/read pair ; (accesses that are effectively not used) diff --git a/polly/test/Simplify/dead_access_value.ll b/polly/test/Simplify/dead_access_value.ll index 6e3c211577f6..a3b9d5ebe76a 100644 --- a/polly/test/Simplify/dead_access_value.ll +++ b/polly/test/Simplify/dead_access_value.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Remove a dead value write/read pair ; (accesses that are effectively not used) diff --git a/polly/test/Simplify/dead_instruction.ll b/polly/test/Simplify/dead_instruction.ll index 4e693b0ccb44..2bf7f8571a46 100644 --- a/polly/test/Simplify/dead_instruction.ll +++ b/polly/test/Simplify/dead_instruction.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Remove a dead instruction ; (an instruction whose result is not used anywhere) diff --git a/polly/test/Simplify/emptyaccessdomain.ll b/polly/test/Simplify/emptyaccessdomain.ll index 54ac14ab398c..bf6d4d9dc8bd 100644 --- a/polly/test/Simplify/emptyaccessdomain.ll +++ b/polly/test/Simplify/emptyaccessdomain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines ; ; for (int j = 0; j < n; j += 1) { ; A[0] = 42.0; diff --git a/polly/test/Simplify/exit_phi_accesses-2.ll b/polly/test/Simplify/exit_phi_accesses-2.ll index 01748aa59bd3..2116d8008aec 100644 --- a/polly/test/Simplify/exit_phi_accesses-2.ll +++ b/polly/test/Simplify/exit_phi_accesses-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-scops -polly-print-simplify -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print,scop(print)' -disable-output < %s | FileCheck %s ; ; The use of %sum.next by %phi counts as an escaping use. ; Don't remove the scalar write of %sum.next. diff --git a/polly/test/Simplify/func-b320a7.ll b/polly/test/Simplify/func-b320a7.ll index c8a823a468d7..c5afc37eb7de 100644 --- a/polly/test/Simplify/func-b320a7.ll +++ b/polly/test/Simplify/func-b320a7.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-simplify -polly-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=print,polly-optree' -disable-output < %s | FileCheck %s -match-full-lines ; llvm.org/PR47098 ; Use-after-free by reference to Stmt remaining in InstStmtMap after removing it has been removed by Scop::simplifyScop. diff --git a/polly/test/Simplify/gemm.ll b/polly/test/Simplify/gemm.ll index 23f8de5573cd..4074078742fc 100644 --- a/polly/test/Simplify/gemm.ll +++ b/polly/test/Simplify/gemm.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s ; ; void gemm(float A[][1024], float B[][1024], float C[][1024]) { ; for (long i = 0; i < 1024; i++) diff --git a/polly/test/Simplify/nocoalesce_differentvalues.ll b/polly/test/Simplify/nocoalesce_differentvalues.ll index 68991d2eecf5..d08c80ee0c06 100644 --- a/polly/test/Simplify/nocoalesce_differentvalues.ll +++ b/polly/test/Simplify/nocoalesce_differentvalues.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s ; ; Do not combine stores that write different values. ; diff --git a/polly/test/Simplify/nocoalesce_elementmismatch.ll b/polly/test/Simplify/nocoalesce_elementmismatch.ll index 2bab360e6858..af12e611fdbc 100644 --- a/polly/test/Simplify/nocoalesce_elementmismatch.ll +++ b/polly/test/Simplify/nocoalesce_elementmismatch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s ; ; Do not combine stores that do not write to different elements in the ; same instance. diff --git a/polly/test/Simplify/nocoalesce_readbetween.ll b/polly/test/Simplify/nocoalesce_readbetween.ll index ada79dc18b87..1a71d2da4c1f 100644 --- a/polly/test/Simplify/nocoalesce_readbetween.ll +++ b/polly/test/Simplify/nocoalesce_readbetween.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s ; ; Do not combine stores if there is a read between them. ; Note: The read between is unused, so will be removed by markAndSweep. diff --git a/polly/test/Simplify/nocoalesce_writebetween.ll b/polly/test/Simplify/nocoalesce_writebetween.ll index 48e785ec2c26..bc2c47a4c9ec 100644 --- a/polly/test/Simplify/nocoalesce_writebetween.ll +++ b/polly/test/Simplify/nocoalesce_writebetween.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s ; ; Do not combine stores if there is a write between them. ; diff --git a/polly/test/Simplify/notdead_region_exitphi.ll b/polly/test/Simplify/notdead_region_exitphi.ll index bd29fd578b97..a796f2a419ad 100644 --- a/polly/test/Simplify/notdead_region_exitphi.ll +++ b/polly/test/Simplify/notdead_region_exitphi.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Do not remove dependencies of a phi node in a region's exit block. ; diff --git a/polly/test/Simplify/notdead_region_innerphi.ll b/polly/test/Simplify/notdead_region_innerphi.ll index a176a28af233..c76485cb5019 100644 --- a/polly/test/Simplify/notdead_region_innerphi.ll +++ b/polly/test/Simplify/notdead_region_innerphi.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Do not remove dependencies of a phi node within a region statement (%phi). ; diff --git a/polly/test/Simplify/notredundant_region_loop.ll b/polly/test/Simplify/notredundant_region_loop.ll index 0ea9be7e9d2d..0bf0dd531524 100644 --- a/polly/test/Simplify/notredundant_region_loop.ll +++ b/polly/test/Simplify/notredundant_region_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-allow-nonaffine-loops -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -polly-allow-nonaffine-loops -disable-output < %s | FileCheck %s -match-full-lines ; ; Do not remove the store in region_entry. It can be executed multiple times ; due to being part of a non-affine loop. diff --git a/polly/test/Simplify/notredundant_region_middle.ll b/polly/test/Simplify/notredundant_region_middle.ll index 84598746e0bb..392dd48ae985 100644 --- a/polly/test/Simplify/notredundant_region_middle.ll +++ b/polly/test/Simplify/notredundant_region_middle.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Do not remove redundant stores in the middle of region statements. ; The store in region_true could be removed, but in practice we do try to diff --git a/polly/test/Simplify/notredundant_synthesizable_unknownit.ll b/polly/test/Simplify/notredundant_synthesizable_unknownit.ll index 2affdbb2f1de..d522d5dd68ae 100644 --- a/polly/test/Simplify/notredundant_synthesizable_unknownit.ll +++ b/polly/test/Simplify/notredundant_synthesizable_unknownit.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Do not remove the scalar value write of %i.trunc in inner.for. ; It is used by body. diff --git a/polly/test/Simplify/out-of-scop-use-in-region-entry-phi-node.ll b/polly/test/Simplify/out-of-scop-use-in-region-entry-phi-node.ll index 511f35a9388e..fe57a0ef6c9d 100644 --- a/polly/test/Simplify/out-of-scop-use-in-region-entry-phi-node.ll +++ b/polly/test/Simplify/out-of-scop-use-in-region-entry-phi-node.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-print-simplify -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print,scop(print)' -disable-output < %s 2>&1 | FileCheck %s ; ; %tmp5 must keep the Value WRITE MemoryAccess, because as an incoming value of ; %tmp4, it is an "external use". diff --git a/polly/test/Simplify/overwritten.ll b/polly/test/Simplify/overwritten.ll index a32d6a8daeb0..b693e9c0db27 100644 --- a/polly/test/Simplify/overwritten.ll +++ b/polly/test/Simplify/overwritten.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s ; ; Remove a store that is overwritten by another store in the same statement. ; diff --git a/polly/test/Simplify/overwritten_3phi.ll b/polly/test/Simplify/overwritten_3phi.ll index 24758b9b7cf9..84cf67fa7cdc 100644 --- a/polly/test/Simplify/overwritten_3phi.ll +++ b/polly/test/Simplify/overwritten_3phi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s ; ; Remove identical writes ; (two stores in the same statement that write the same value to the same diff --git a/polly/test/Simplify/overwritten_3store.ll b/polly/test/Simplify/overwritten_3store.ll index 63eb5b54f931..72e9917b36a9 100644 --- a/polly/test/Simplify/overwritten_3store.ll +++ b/polly/test/Simplify/overwritten_3store.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s -; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s ; ; Remove a store that is overwritten by another store in the same statement. ; Check that even multiple stores are removed. diff --git a/polly/test/Simplify/overwritten_implicit_and_explicit.ll b/polly/test/Simplify/overwritten_implicit_and_explicit.ll index 56c63b48f761..ba7c6d0f20b1 100644 --- a/polly/test/Simplify/overwritten_implicit_and_explicit.ll +++ b/polly/test/Simplify/overwritten_implicit_and_explicit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s ; ; Remove a store that is overwritten by another store in the same statement. ; Check that this works even if one of the writes is a scalar MemoryKind. diff --git a/polly/test/Simplify/overwritten_loadbetween.ll b/polly/test/Simplify/overwritten_loadbetween.ll index b31f45d5db62..f271b4559dc8 100644 --- a/polly/test/Simplify/overwritten_loadbetween.ll +++ b/polly/test/Simplify/overwritten_loadbetween.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s ; ; Do not remove overwrites when the value is read before. ; diff --git a/polly/test/Simplify/overwritten_scalar.ll b/polly/test/Simplify/overwritten_scalar.ll index d55ea7712c36..41c5c6fa2470 100644 --- a/polly/test/Simplify/overwritten_scalar.ll +++ b/polly/test/Simplify/overwritten_scalar.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s ; ; Remove identical writes ; (two stores in the same statement that write the same value to the same diff --git a/polly/test/Simplify/pass_existence.ll b/polly/test/Simplify/pass_existence.ll index fc5287ed2ee2..a8fc184b1616 100644 --- a/polly/test/Simplify/pass_existence.ll +++ b/polly/test/Simplify/pass_existence.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -; RUN: opt %loadNPMPolly -disable-output "-passes=scop(print)" < %s -aa-pipeline=basic-aa < %s | FileCheck %s +; RUN: opt %loadPolly -disable-output "-passes=scop(print)" < %s -aa-pipeline=basic-aa < %s | FileCheck %s ; ; Simple test for the existence of the Simplify pass. ; diff --git a/polly/test/Simplify/phi_in_regionstmt.ll b/polly/test/Simplify/phi_in_regionstmt.ll index 32bb75427589..4c6a8744e200 100644 --- a/polly/test/Simplify/phi_in_regionstmt.ll +++ b/polly/test/Simplify/phi_in_regionstmt.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; The PHINode %cond91.sink.sink.us.sink.6 is in the middle of a region ; statement. diff --git a/polly/test/Simplify/pr33323.ll b/polly/test/Simplify/pr33323.ll index 751f0bff5961..de2e00e8e2e9 100644 --- a/polly/test/Simplify/pr33323.ll +++ b/polly/test/Simplify/pr33323.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s ; ; llvm.org/PR33323 ; diff --git a/polly/test/Simplify/redundant.ll b/polly/test/Simplify/redundant.ll index e85352bc889f..720f2e3d0ef2 100644 --- a/polly/test/Simplify/redundant.ll +++ b/polly/test/Simplify/redundant.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Remove redundant store (a store that writes the same value already ; at the destination) diff --git a/polly/test/Simplify/redundant_differentindex.ll b/polly/test/Simplify/redundant_differentindex.ll index 23531c24344f..c79364608e58 100644 --- a/polly/test/Simplify/redundant_differentindex.ll +++ b/polly/test/Simplify/redundant_differentindex.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; A store that has a different index than the load it is storing is ; not redundant. diff --git a/polly/test/Simplify/redundant_region.ll b/polly/test/Simplify/redundant_region.ll index dbcb420ac2f3..d5c9586283de 100644 --- a/polly/test/Simplify/redundant_region.ll +++ b/polly/test/Simplify/redundant_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines ; ; Remove redundant store (a store that writes the same value already ; at the destination) in a region. diff --git a/polly/test/Simplify/redundant_region_scalar.ll b/polly/test/Simplify/redundant_region_scalar.ll index 95a581ad6f57..ab07126fe268 100644 --- a/polly/test/Simplify/redundant_region_scalar.ll +++ b/polly/test/Simplify/redundant_region_scalar.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines ; ; Remove redundant store (a store that writes the same value already ; at the destination) in a region. diff --git a/polly/test/Simplify/redundant_scalarwrite.ll b/polly/test/Simplify/redundant_scalarwrite.ll index e2f7bbedc023..c09be5f61837 100644 --- a/polly/test/Simplify/redundant_scalarwrite.ll +++ b/polly/test/Simplify/redundant_scalarwrite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines ; ; Remove redundant scalar stores. ; diff --git a/polly/test/Simplify/redundant_storebetween.ll b/polly/test/Simplify/redundant_storebetween.ll index f624b6e5b995..f87c1126cd26 100644 --- a/polly/test/Simplify/redundant_storebetween.ll +++ b/polly/test/Simplify/redundant_storebetween.ll @@ -1,5 +1,4 @@ -; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Don't remove store where there is another store to the same target ; in-between them. diff --git a/polly/test/Simplify/scalability1.ll b/polly/test/Simplify/scalability1.ll index 0ef99ce1ad8e..a91574e2b274 100644 --- a/polly/test/Simplify/scalability1.ll +++ b/polly/test/Simplify/scalability1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-ignore-inbounds -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-ignore-inbounds '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Test scalability. ; diff --git a/polly/test/Simplify/scalability2.ll b/polly/test/Simplify/scalability2.ll index bac0810b0afa..4e4874df219e 100644 --- a/polly/test/Simplify/scalability2.ll +++ b/polly/test/Simplify/scalability2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-ignore-inbounds -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-ignore-inbounds '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines ; ; Test scalability. ; diff --git a/polly/test/Simplify/sweep_mapped_phi.ll b/polly/test/Simplify/sweep_mapped_phi.ll index add1681cdf36..3b9e61c72b4d 100644 --- a/polly/test/Simplify/sweep_mapped_phi.ll +++ b/polly/test/Simplify/sweep_mapped_phi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines ; ; Map %phi to A[j], so the scalar write in Stmt_for_bodyA can be removed. ; diff --git a/polly/test/Simplify/sweep_mapped_value.ll b/polly/test/Simplify/sweep_mapped_value.ll index 2e2f9c37febe..5992e2401ca5 100644 --- a/polly/test/Simplify/sweep_mapped_value.ll +++ b/polly/test/Simplify/sweep_mapped_value.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines ; ; Map %val to A[j], so the scalar write on Stmt_for_bodyB can be removed. ; diff --git a/polly/test/Simplify/ununsed_read_in_region_entry.ll b/polly/test/Simplify/ununsed_read_in_region_entry.ll index 9b2d4521e2d6..111c19f706b9 100644 --- a/polly/test/Simplify/ununsed_read_in_region_entry.ll +++ b/polly/test/Simplify/ununsed_read_in_region_entry.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-print-simplify -disable-output< %s | FileCheck %s -match-full-lines -; RUN: opt %loadPolly -polly-simplify -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly '-passes=print' -disable-output< %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly '-passes=polly-simplify,polly-codegen' -S < %s | FileCheck %s -check-prefix=CODEGEN ; ; for (int i = 0; i < n; i+=1) { ; (void)A[0]; diff --git a/polly/test/Support/Plugins.ll b/polly/test/Support/Plugins.ll index cee878f1c6ac..c4579470192b 100644 --- a/polly/test/Support/Plugins.ll +++ b/polly/test/Support/Plugins.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadNPMPolly -passes='polly-prepare,scop(print)' -S < %s \ +; RUN: opt %loadPolly '-passes=polly-prepare,scop(print)' -S < %s \ ; RUN: | FileCheck %s ; This testcase tests plugin registration. Check-lines below serve to verify diff --git a/polly/test/Support/defaultpipelines.ll b/polly/test/Support/defaultpipelines.ll index ab0329a70327..6681042727c6 100644 --- a/polly/test/Support/defaultpipelines.ll +++ b/polly/test/Support/defaultpipelines.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadNPMPolly -polly -O0 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF -; RUN: opt %loadNPMPolly -polly -O1 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON -; RUN: opt %loadNPMPolly -polly -O2 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON -; RUN: opt %loadNPMPolly -polly -O3 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON -; RUN: opt %loadNPMPolly -polly -Os -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF -; RUN: opt %loadNPMPolly -polly -Oz -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF +; RUN: opt %loadPolly -polly -O0 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF +; RUN: opt %loadPolly -polly -O1 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON +; RUN: opt %loadPolly -polly -O2 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON +; RUN: opt %loadPolly -polly -O3 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON +; RUN: opt %loadPolly -polly -Os -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF +; RUN: opt %loadPolly -polly -Oz -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF ; ; Check that Polly's default pipeline works from detection to code generation ; with either pass manager. diff --git a/polly/test/Support/dumpfunction.ll b/polly/test/Support/dumpfunction.ll index 863212b2ef7d..e99261508f1a 100644 --- a/polly/test/Support/dumpfunction.ll +++ b/polly/test/Support/dumpfunction.ll @@ -1,9 +1,9 @@ ; New pass manager -; RUN: opt %loadNPMPolly -O3 -polly -polly-position=before-vectorizer -polly-dump-before --disable-output %s +; RUN: opt %loadPolly -O3 -polly -polly-position=before-vectorizer -polly-dump-before --disable-output %s ; RUN: FileCheck --input-file=dumpfunction-callee-before.ll --check-prefix=CHECK --check-prefix=CALLEE %s ; RUN: FileCheck --input-file=dumpfunction-caller-before.ll --check-prefix=CHECK --check-prefix=CALLER %s ; -; RUN: opt %loadNPMPolly -O3 -polly -polly-position=before-vectorizer -polly-dump-after --disable-output %s +; RUN: opt %loadPolly -O3 -polly -polly-position=before-vectorizer -polly-dump-after --disable-output %s ; RUN: FileCheck --input-file=dumpfunction-callee-after.ll --check-prefix=CHECK --check-prefix=CALLEE %s ; RUN: FileCheck --input-file=dumpfunction-caller-after.ll --check-prefix=CHECK --check-prefix=CALLER %s diff --git a/polly/test/Support/dumpmodule.ll b/polly/test/Support/dumpmodule.ll index 693fe4bc6cde..d7aa88439f64 100644 --- a/polly/test/Support/dumpmodule.ll +++ b/polly/test/Support/dumpmodule.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadNPMPolly -O3 -polly -polly-position=early -polly-dump-before-file=%t-npm-before-early.ll --disable-output < %s && FileCheck --input-file=%t-npm-before-early.ll --check-prefix=EARLY %s -; RUN: opt %loadNPMPolly -O3 -polly -polly-position=early -polly-dump-after-file=%t-npm-after-early.ll --disable-output < %s && FileCheck --input-file=%t-npm-after-early.ll --check-prefix=EARLY --check-prefix=AFTEREARLY %s +; RUN: opt %loadPolly -O3 -polly -polly-position=early -polly-dump-before-file=%t-npm-before-early.ll --disable-output < %s && FileCheck --input-file=%t-npm-before-early.ll --check-prefix=EARLY %s +; RUN: opt %loadPolly -O3 -polly -polly-position=early -polly-dump-after-file=%t-npm-after-early.ll --disable-output < %s && FileCheck --input-file=%t-npm-after-early.ll --check-prefix=EARLY --check-prefix=AFTEREARLY %s ; ; Check the module dumping before Polly at specific positions in the ; pass pipeline. diff --git a/polly/test/Support/exportjson.ll b/polly/test/Support/exportjson.ll index 22cfea23534c..22ba845bafc2 100644 --- a/polly/test/Support/exportjson.ll +++ b/polly/test/Support/exportjson.ll @@ -1,6 +1,6 @@ ; RUN: rm -rf %t ; RUN: mkdir -p %t -; RUN: opt %loadNPMPolly -polly-import-jscop-dir=%t -polly -O2 -polly-export -S < %s +; RUN: opt %loadPolly -polly-import-jscop-dir=%t -polly -O2 -polly-export -S < %s ; RUN: FileCheck %s -input-file %t/exportjson___%entry.split---%return.jscop ; ; for (int j = 0; j < n; j += 1) { diff --git a/polly/test/Support/isl-args.ll b/polly/test/Support/isl-args.ll index efa94194bc3f..442742d55f81 100644 --- a/polly/test/Support/isl-args.ll +++ b/polly/test/Support/isl-args.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-scops -disable-output -polly-isl-arg=-V < %s | FileCheck %s -match-full-lines --check-prefix=VERSION -; RUN: opt %loadPolly -polly-scops -disable-output -polly-isl-arg=-h < %s | FileCheck %s -match-full-lines --check-prefix=HELP -; RUN: not opt %loadPolly -polly-scops -disable-output -polly-isl-arg=-asdf < %s 2>&1| FileCheck %s -match-full-lines --check-prefix=UNKNOWN -; RUN: opt %loadPolly -polly-scops -disable-output -polly-isl-arg=--schedule-algorithm=feautrier < %s +; RUN: opt %loadPolly '-passes=print' -disable-output -polly-isl-arg=-V < %s | FileCheck %s -match-full-lines --check-prefix=VERSION +; RUN: opt %loadPolly '-passes=print' -disable-output -polly-isl-arg=-h < %s | FileCheck %s -match-full-lines --check-prefix=HELP +; RUN: not opt %loadPolly '-passes=print' -disable-output -polly-isl-arg=-asdf < %s 2>&1| FileCheck %s -match-full-lines --check-prefix=UNKNOWN +; RUN: opt %loadPolly '-passes=print' -disable-output -polly-isl-arg=--schedule-algorithm=feautrier < %s ; VERSION: isl-{{.*}}-IMath-32 ; HELP: Usage: -polly-isl-arg [OPTION...] diff --git a/polly/test/Support/pipelineposition.ll b/polly/test/Support/pipelineposition.ll index a4506ba1d64e..757af91011fb 100644 --- a/polly/test/Support/pipelineposition.ll +++ b/polly/test/Support/pipelineposition.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadNPMPolly -O3 -polly -polly-position=early -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=NOINLINE -; RUN: opt %loadNPMPolly -O3 -polly -polly-position=early -polly-run-inliner -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=INLINED1 -; RUN: opt %loadNPMPolly -O3 -polly -polly-position=before-vectorizer -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=INLINED3 +; RUN: opt %loadPolly -O3 -polly -polly-position=early -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=NOINLINE +; RUN: opt %loadPolly -O3 -polly -polly-position=early -polly-run-inliner -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=INLINED1 +; RUN: opt %loadPolly -O3 -polly -polly-position=before-vectorizer -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=INLINED3 ; ; REQUIRES: asserts ; diff --git a/polly/test/Support/pollyDebug.ll b/polly/test/Support/pollyDebug.ll index ada079023b6c..e5e327c3976e 100644 --- a/polly/test/Support/pollyDebug.ll +++ b/polly/test/Support/pollyDebug.ll @@ -1,5 +1,5 @@ ; Test if "polly-debug" flag enables debug prints from different parts of polly -; RUN: opt %loadNPMPolly -O3 -polly -polly-debug --disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -O3 -polly -polly-debug --disable-output < %s 2>&1 | FileCheck %s ; ; REQUIRES: asserts diff --git a/polly/test/lit.site.cfg.in b/polly/test/lit.site.cfg.in index b44061260834..703752896239 100644 --- a/polly/test/lit.site.cfg.in +++ b/polly/test/lit.site.cfg.in @@ -38,16 +38,11 @@ if config.llvm_polly_link_into_tools == '' or \ config.llvm_polly_link_into_tools.lower() == 'false' or \ config.llvm_polly_link_into_tools.lower() == 'notfound' or \ config.llvm_polly_link_into_tools.lower() == 'llvm_polly_link_into_tools-notfound': - config.substitutions.append(('%loadPolly', '-load ' - + config.polly_lib_dir + '/LLVMPolly@LLVM_SHLIBEXT@' - + commonOpts )) - config.substitutions.append(('%loadNPMPolly', '-load-pass-plugin ' + config.substitutions.append(('%loadPolly', '-load-pass-plugin ' + config.polly_lib_dir + '/LLVMPolly@LLVM_SHLIBEXT@' + commonOpts )) else: config.substitutions.append(('%loadPolly', commonOpts )) - config.substitutions.append(('%loadNPMPolly', commonOpts )) - import lit.llvm lit.llvm.initialize(lit_config, config) diff --git a/polly/test/polly.ll b/polly/test/polly.ll index f78cceacfb12..6654468470a6 100644 --- a/polly/test/polly.ll +++ b/polly/test/polly.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-scops -S < %s | FileCheck %s +; RUN: opt %loadPolly '-passes=print' -S < %s 2>&1 | 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-n8:16:32:64" define void @foo() nounwind { start: -- GitLab From 847c83f7cceeaec6676f33291081912d6b8fda5e Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 15 May 2024 07:02:31 +0200 Subject: [PATCH 305/578] InstCombine: Process addrspacecast uses in PointerReplacer (#91953) This was looking through an addrspacecast, and not finding a later unfoldable cast to another address space. Fixes improperly deleting a required alloca + memcpy and introducing an illegal addrspacecast. This also required fixing some worklist management issues with addrspacecast, and assuming that only memcpy sources could need replacement. Regresses one test function, but this looks like it optimized before by accident. It never saw the pointer use by the call to readonly_callee, which should require insertion of a new cast. Fixes #68120 --- .../InstCombineLoadStoreAlloca.cpp | 33 ++++---- .../InstCombine/AMDGPU/issue68120.ll | 81 +++++++++++++++++++ .../InstCombine/ptr-replace-alloca.ll | 6 +- 3 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 llvm/test/Transforms/InstCombine/AMDGPU/issue68120.ll diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 537890d9025f..4351a55ea1d3 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -342,9 +342,13 @@ bool PointerReplacer::collectUsersRecursive(Instruction &I) { Worklist.insert(Inst); } else if (isEqualOrValidAddrSpaceCast(Inst, FromAS)) { Worklist.insert(Inst); + if (!collectUsersRecursive(*Inst)) + return false; } else if (Inst->isLifetimeStartOrEnd()) { continue; } else { + // TODO: For arbitrary uses with address space mismatches, should we check + // if we can introduce a valid addrspacecast? LLVM_DEBUG(dbgs() << "Cannot handle pointer user: " << *U << '\n'); return false; } @@ -406,20 +410,18 @@ void PointerReplacer::replace(Instruction *I) { NewSI->takeName(SI); WorkMap[SI] = NewSI; } else if (auto *MemCpy = dyn_cast(I)) { - auto *SrcV = getReplacement(MemCpy->getRawSource()); - // The pointer may appear in the destination of a copy, but we don't want to - // replace it. - if (!SrcV) { - assert(getReplacement(MemCpy->getRawDest()) && - "destination not in replace list"); - return; - } + auto *DestV = MemCpy->getRawDest(); + auto *SrcV = MemCpy->getRawSource(); + + if (auto *DestReplace = getReplacement(DestV)) + DestV = DestReplace; + if (auto *SrcReplace = getReplacement(SrcV)) + SrcV = SrcReplace; IC.Builder.SetInsertPoint(MemCpy); auto *NewI = IC.Builder.CreateMemTransferInst( - MemCpy->getIntrinsicID(), MemCpy->getRawDest(), MemCpy->getDestAlign(), - SrcV, MemCpy->getSourceAlign(), MemCpy->getLength(), - MemCpy->isVolatile()); + MemCpy->getIntrinsicID(), DestV, MemCpy->getDestAlign(), SrcV, + MemCpy->getSourceAlign(), MemCpy->getLength(), MemCpy->isVolatile()); AAMDNodes AAMD = MemCpy->getAAMetadata(); if (AAMD) NewI->setAAMetadata(AAMD); @@ -432,16 +434,17 @@ void PointerReplacer::replace(Instruction *I) { assert(isEqualOrValidAddrSpaceCast( ASC, V->getType()->getPointerAddressSpace()) && "Invalid address space cast!"); - auto *NewV = V; + if (V->getType()->getPointerAddressSpace() != ASC->getType()->getPointerAddressSpace()) { auto *NewI = new AddrSpaceCastInst(V, ASC->getType(), ""); NewI->takeName(ASC); IC.InsertNewInstWith(NewI, ASC->getIterator()); - NewV = NewI; + WorkMap[ASC] = NewI; + } else { + WorkMap[ASC] = V; } - IC.replaceInstUsesWith(*ASC, NewV); - IC.eraseInstFromFunction(*ASC); + } else { llvm_unreachable("should never reach here"); } diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/issue68120.ll b/llvm/test/Transforms/InstCombine/AMDGPU/issue68120.ll new file mode 100644 index 000000000000..346c64f096ba --- /dev/null +++ b/llvm/test/Transforms/InstCombine/AMDGPU/issue68120.ll @@ -0,0 +1,81 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=instcombine %s | FileCheck %s + +; It is illegal to pass ptr addrspace(4) in %arg by addrspacecasting +; to ptr addrspace(5) to pass off to the stack argument. A temporary +; alloca and memcpy is necessary. +define void @issue68120_invalid_addrspacecast_introduced_0(ptr addrspace(4) byref([56 x i8]) %arg) { +; CHECK-LABEL: define void @issue68120_invalid_addrspacecast_introduced_0( +; CHECK-SAME: ptr addrspace(4) byref([56 x i8]) [[ARG:%.*]]) { +; CHECK-NEXT: [[ADDRSPACECAST_0_TO_5:%.*]] = alloca [56 x i8], align 1, addrspace(5) +; CHECK-NEXT: call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) noundef align 1 dereferenceable(56) [[ADDRSPACECAST_0_TO_5]], ptr addrspace(4) noundef align 1 dereferenceable(56) [[ARG]], i64 56, i1 false) +; CHECK-NEXT: call void @byval_func(ptr addrspace(5) [[ADDRSPACECAST_0_TO_5]]) +; CHECK-NEXT: ret void +; + %alloca = alloca [56 x i8], addrspace(5) + %alloca1 = alloca [56 x i8], addrspace(5) + call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) %alloca, ptr addrspace(4) %arg, i64 56, i1 false) + call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) %alloca1, ptr addrspace(5) %alloca, i64 56, i1 false) + %addrspacecast.alloca1 = addrspacecast ptr addrspace(5) %alloca1 to ptr + %addrspacecast.0.to.5 = addrspacecast ptr %addrspacecast.alloca1 to ptr addrspace(5) + call void @byval_func(ptr addrspace(5) %addrspacecast.0.to.5) + ret void +} + +; Further reduced variant that already eliminated one of the copies +define void @issue68120_invalid_addrspacecast_introduced_1(ptr addrspace(4) byref([56 x i8]) %arg) { +; CHECK-LABEL: define void @issue68120_invalid_addrspacecast_introduced_1( +; CHECK-SAME: ptr addrspace(4) byref([56 x i8]) [[ARG:%.*]]) { +; CHECK-NEXT: [[ADDRSPACECAST_0_TO_5:%.*]] = alloca [56 x i8], align 1, addrspace(5) +; CHECK-NEXT: call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) noundef align 1 dereferenceable(56) [[ADDRSPACECAST_0_TO_5]], ptr addrspace(4) noundef align 1 dereferenceable(56) [[ARG]], i64 56, i1 false) +; CHECK-NEXT: call void @byval_func(ptr addrspace(5) [[ADDRSPACECAST_0_TO_5]]) +; CHECK-NEXT: ret void +; + %alloca = alloca [56 x i8], addrspace(5) + call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) %alloca, ptr addrspace(4) %arg, i64 56, i1 false) + %addrspacecast.alloca = addrspacecast ptr addrspace(5) %alloca to ptr + %addrspacecast.0.to.5 = addrspacecast ptr %addrspacecast.alloca to ptr addrspace(5) + call void @byval_func(ptr addrspace(5) %addrspacecast.0.to.5) + ret void +} + +define void @issue68120_use_cast_to_as0(ptr addrspace(4) byref([56 x i8]) %arg) { +; CHECK-LABEL: define void @issue68120_use_cast_to_as0( +; CHECK-SAME: ptr addrspace(4) byref([56 x i8]) [[ARG:%.*]]) { +; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [56 x i8], align 1, addrspace(5) +; CHECK-NEXT: call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) noundef align 1 dereferenceable(56) [[ALLOCA]], ptr addrspace(4) noundef align 1 dereferenceable(56) [[ARG]], i64 56, i1 false) +; CHECK-NEXT: [[ADDRSPACECAST_ALLOCA:%.*]] = addrspacecast ptr addrspace(5) [[ALLOCA]] to ptr +; CHECK-NEXT: call void @other_func(ptr [[ADDRSPACECAST_ALLOCA]]) +; CHECK-NEXT: ret void +; + %alloca = alloca [56 x i8], addrspace(5) + call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) %alloca, ptr addrspace(4) %arg, i64 56, i1 false) + %addrspacecast.alloca = addrspacecast ptr addrspace(5) %alloca to ptr + %addrspacecast.0.to.5 = addrspacecast ptr %addrspacecast.alloca to ptr addrspace(5) + call void @other_func(ptr %addrspacecast.alloca) + ret void +} + +define void @issue68120_uses_invalid_addrspacecast(ptr addrspace(4) byref([56 x i8]) %arg) { +; CHECK-LABEL: define void @issue68120_uses_invalid_addrspacecast( +; CHECK-SAME: ptr addrspace(4) byref([56 x i8]) [[ARG:%.*]]) { +; CHECK-NEXT: [[ADDRSPACECAST_0_TO_5:%.*]] = alloca [56 x i8], align 1, addrspace(5) +; CHECK-NEXT: call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) noundef align 1 dereferenceable(56) [[ADDRSPACECAST_0_TO_5]], ptr addrspace(4) noundef align 1 dereferenceable(56) [[ARG]], i64 56, i1 false) +; CHECK-NEXT: call void @byval_func(ptr addrspace(5) [[ADDRSPACECAST_0_TO_5]]) +; CHECK-NEXT: ret void +; + %alloca = alloca [56 x i8], addrspace(5) + %alloca1 = alloca [56 x i8], addrspace(5) + %illegal.cast = addrspacecast ptr addrspace(4) %arg to ptr addrspace(5) + call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) %alloca, ptr addrspace(5) %illegal.cast, i64 56, i1 false) + call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) %alloca1, ptr addrspace(5) %alloca, i64 56, i1 false) + %addrspacecast.alloca1 = addrspacecast ptr addrspace(5) %alloca1 to ptr + %addrspacecast.0.to.5 = addrspacecast ptr %addrspacecast.alloca1 to ptr addrspace(5) + call void @byval_func(ptr addrspace(5) %addrspacecast.0.to.5) + ret void +} + + +declare void @byval_func(ptr addrspace(5) byval([56 x i8])) +declare void @other_func(ptr) + diff --git a/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll b/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll index a7aa3a8ef1be..c783b101251d 100644 --- a/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll +++ b/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll @@ -429,9 +429,13 @@ entry: declare i8 @readonly_callee(ptr readonly nocapture) +; FIXME: This should be able to fold to call i8 @readonly_callee(ptr nonnull @g1) define i8 @call_readonly_remove_alloca() { ; CHECK-LABEL: @call_readonly_remove_alloca( -; CHECK-NEXT: [[V:%.*]] = call i8 @readonly_callee(ptr nonnull @g1) +; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 1, addrspace(1) +; CHECK-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 1 dereferenceable(32) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false) +; CHECK-NEXT: [[P:%.*]] = addrspacecast ptr addrspace(1) [[ALLOCA]] to ptr +; CHECK-NEXT: [[V:%.*]] = call i8 @readonly_callee(ptr [[P]]) ; CHECK-NEXT: ret i8 [[V]] ; %alloca = alloca [32 x i8], addrspace(1) -- GitLab From 15397583e3d85eb1f1a051de26eb409aaedd3b54 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Tue, 14 May 2024 22:04:50 -0700 Subject: [PATCH 306/578] Revert "[polly] Port polly tests to use NPM" (#92215) Reverts llvm/llvm-project#90632. Causing failures on buildbots that dynamically load polly. Reverting while we sort it out. --- polly/test/CodeGen/20100617.ll | 2 +- polly/test/CodeGen/20100622.ll | 4 +- polly/test/CodeGen/20100707.ll | 2 +- polly/test/CodeGen/20100707_2.ll | 2 +- polly/test/CodeGen/20100708.ll | 2 +- polly/test/CodeGen/20100708_2.ll | 2 +- polly/test/CodeGen/20100713.ll | 2 +- polly/test/CodeGen/20100713_2.ll | 2 +- polly/test/CodeGen/20100717.ll | 2 +- polly/test/CodeGen/20100718-DomInfo-2.ll | 2 +- polly/test/CodeGen/20100718-DomInfo.ll | 2 +- .../CodeGen/20100720-MultipleConditions.ll | 2 +- .../test/CodeGen/20100809-IndependentBlock.ll | 2 +- ...0100811-ScalarDependencyBetweenBrAndCnd.ll | 2 +- polly/test/CodeGen/20101030-Overflow.ll | 2 +- polly/test/CodeGen/20101103-Overflow3.ll | 2 +- polly/test/CodeGen/20101103-signmissmatch.ll | 2 +- .../test/CodeGen/20110226-Ignore-Dead-Code.ll | 2 +- .../test/CodeGen/20110226-PHI-Node-removed.ll | 2 +- polly/test/CodeGen/20120316-InvalidCast.ll | 2 +- .../CodeGen/20120403-RHS-type-mismatch.ll | 2 +- polly/test/CodeGen/20130221.ll | 2 +- .../20150328-SCEVExpanderIntroducesNewIV.ll | 2 +- polly/test/CodeGen/Intrinsics/llvm-expect.ll | 2 +- .../do_not_mutate_debug_info.ll | 2 +- .../loop_nest_param_parallel.ll | 2 +- .../single_loop_param_parallel.ll | 4 +- polly/test/CodeGen/MemAccess/bad_alignment.ll | 2 +- .../MemAccess/codegen_address_space.ll | 2 +- .../MemAccess/codegen_constant_offset.ll | 2 +- .../test/CodeGen/MemAccess/codegen_simple.ll | 2 +- .../CodeGen/MemAccess/codegen_simple_float.ll | 2 +- .../CodeGen/MemAccess/codegen_simple_md.ll | 4 +- .../MemAccess/codegen_simple_md_float.ll | 4 +- .../test/CodeGen/MemAccess/different_types.ll | 4 +- polly/test/CodeGen/MemAccess/generate-all.ll | 4 +- .../CodeGen/MemAccess/invariant_base_ptr.ll | 4 +- .../test/CodeGen/MemAccess/multiple_types.ll | 4 +- polly/test/CodeGen/MemAccess/simple.ll | 2 +- .../MemAccess/update_access_functions.ll | 4 +- polly/test/CodeGen/OpenMP/alias-metadata.ll | 2 +- .../floord-as-argument-to-subfunction.ll | 2 +- polly/test/CodeGen/OpenMP/inlineasm.ll | 2 +- .../invariant_base_pointer_preloaded.ll | 2 +- ...ant_base_pointer_preloaded_different_bb.ll | 2 +- ...base_pointer_preloaded_pass_only_needed.ll | 2 +- .../invariant_base_pointers_preloaded.ll | 2 +- .../OpenMP/loop-body-references-outer-iv.ll | 4 +- .../loop-body-references-outer-values-2.ll | 4 +- .../loop-body-references-outer-values-3.ll | 4 +- .../loop-body-references-outer-values.ll | 4 +- .../OpenMP/loop-bounds-reference-outer-ids.ll | 4 +- .../test/CodeGen/OpenMP/mapped-phi-access.ll | 2 +- polly/test/CodeGen/OpenMP/matmul-parallel.ll | 4 +- polly/test/CodeGen/OpenMP/recomputed-srem.ll | 2 +- ...ference-argument-from-non-affine-region.ll | 6 +- .../test/CodeGen/OpenMP/reference-other-bb.ll | 2 +- .../OpenMP/reference-preceeding-loop.ll | 4 +- polly/test/CodeGen/OpenMP/reference_latest.ll | 2 +- polly/test/CodeGen/OpenMP/scev-rewriting.ll | 2 +- polly/test/CodeGen/OpenMP/single_loop.ll | 18 ++--- ...single_loop_with_loop_invariant_baseptr.ll | 4 +- .../CodeGen/OpenMP/single_loop_with_param.ll | 6 +- ...o-parallel-loops-reference-outer-indvar.ll | 4 +- polly/test/CodeGen/PHIInExit.ll | 2 +- .../combine_different_values.ll | 2 +- .../RuntimeDebugBuilder/stmt_tracing.ll | 2 +- polly/test/CodeGen/alias-check-multi-dim.ll | 2 +- .../CodeGen/alias_metadata_too_many_arrays.ll | 2 +- ...aliasing_different_base_and_access_type.ll | 2 +- .../aliasing_different_pointer_types.ll | 2 +- .../aliasing_multidimensional_access.ll | 2 +- .../CodeGen/aliasing_parametric_simple_1.ll | 2 +- .../CodeGen/aliasing_parametric_simple_2.ll | 2 +- polly/test/CodeGen/aliasing_struct_element.ll | 2 +- polly/test/CodeGen/alignment.ll | 2 +- polly/test/CodeGen/annotated_alias_scopes.ll | 2 +- polly/test/CodeGen/blas_sscal_simplified.ll | 2 +- ...code-hosting-and-escape-map-computation.ll | 2 +- polly/test/CodeGen/constant_condition.ll | 2 +- polly/test/CodeGen/create-conditional-scop.ll | 2 +- ...d_instruction_referenced_by_parameter_1.ll | 2 +- ...d_instruction_referenced_by_parameter_2.ll | 2 +- polly/test/CodeGen/debug-intrinsics.ll | 4 +- ...nce_problem_after_early_codegen_bailout.ll | 2 +- polly/test/CodeGen/empty_domain_in_context.ll | 2 +- polly/test/CodeGen/entry_with_trivial_phi.ll | 2 +- .../entry_with_trivial_phi_other_bb.ll | 2 +- .../error-stmt-in-non-affine-region.ll | 2 +- ...or_block_contains_invalid_memory_access.ll | 2 +- polly/test/CodeGen/exprModDiv.ll | 8 +- .../hoisted_load_escapes_through_phi.ll | 4 +- polly/test/CodeGen/hoisting_1.ll | 2 +- polly/test/CodeGen/hoisting_2.ll | 2 +- polly/test/CodeGen/inner_scev_sdiv_1.ll | 2 +- polly/test/CodeGen/inner_scev_sdiv_2.ll | 2 +- polly/test/CodeGen/inner_scev_sdiv_3.ll | 2 +- polly/test/CodeGen/inner_scev_sdiv_in_lb.ll | 4 +- .../inner_scev_sdiv_in_lb_invariant.ll | 2 +- polly/test/CodeGen/inner_scev_sdiv_in_rtc.ll | 2 +- polly/test/CodeGen/intrinsics_lifetime.ll | 2 +- polly/test/CodeGen/intrinsics_misc.ll | 2 +- .../inv-load-lnt-crash-wrong-order-2.ll | 2 +- .../inv-load-lnt-crash-wrong-order-3.ll | 2 +- .../CodeGen/inv-load-lnt-crash-wrong-order.ll | 2 +- .../test/CodeGen/invariant-load-dimension.ll | 4 +- ...-load-preload-base-pointer-origin-first.ll | 2 +- .../CodeGen/invariant_cannot_handle_void.ll | 4 +- polly/test/CodeGen/invariant_load.ll | 2 +- .../CodeGen/invariant_load_address_space.ll | 2 +- .../CodeGen/invariant_load_alias_metadata.ll | 2 +- .../CodeGen/invariant_load_base_pointer.ll | 2 +- ...invariant_load_base_pointer_conditional.ll | 2 +- ...variant_load_base_pointer_conditional_2.ll | 6 +- ...ariant_load_canonicalize_array_baseptrs.ll | 2 +- .../test/CodeGen/invariant_load_condition.ll | 2 +- .../invariant_load_different_sized_types.ll | 2 +- polly/test/CodeGen/invariant_load_escaping.ll | 2 +- .../invariant_load_escaping_second_scop.ll | 2 +- .../invariant_load_in_non_affine_subregion.ll | 2 +- polly/test/CodeGen/invariant_load_loop_ub.ll | 2 +- ...ant_load_not_executed_but_in_parameters.ll | 2 +- .../test/CodeGen/invariant_load_outermost.ll | 2 +- ...riant_load_parameters_cyclic_dependence.ll | 4 +- .../CodeGen/invariant_load_ptr_ptr_noalias.ll | 2 +- .../test/CodeGen/invariant_load_scalar_dep.ll | 2 +- ...riant_load_scalar_escape_alloca_sharing.ll | 2 +- ...oads_from_struct_with_different_types_1.ll | 2 +- ...oads_from_struct_with_different_types_2.ll | 2 +- ...invariant_loads_ignore_parameter_bounds.ll | 2 +- .../invariant_verify_function_failed.ll | 2 +- .../invariant_verify_function_failed_2.ll | 4 +- polly/test/CodeGen/issue56692.ll | 2 +- .../large-numbers-in-boundary-context.ll | 2 +- .../test/CodeGen/load_subset_with_context.ll | 2 +- .../loop-invariant-load-type-mismatch.ll | 2 +- polly/test/CodeGen/loop_with_condition.ll | 2 +- polly/test/CodeGen/loop_with_condition_2.ll | 2 +- .../test/CodeGen/loop_with_condition_ineq.ll | 2 +- .../CodeGen/loop_with_condition_nested.ll | 4 +- ..._conditional_entry_edge_split_hard_case.ll | 2 +- polly/test/CodeGen/memcpy_annotations.ll | 2 +- .../multidim-non-matching-typesize-2.ll | 2 +- .../CodeGen/multidim-non-matching-typesize.ll | 2 +- ..._2d_parametric_array_static_loop_bounds.ll | 2 +- polly/test/CodeGen/multidim_alias_check.ll | 2 +- polly/test/CodeGen/multiple-codegens.ll | 5 +- polly/test/CodeGen/multiple-scops-in-a-row.ll | 2 +- .../multiple-types-invariant-load-2.ll | 2 +- .../CodeGen/multiple-types-invariant-load.ll | 2 +- .../multiple_sai_fro_same_base_address.ll | 4 +- polly/test/CodeGen/no-overflow-tracking.ll | 4 +- polly/test/CodeGen/no_guard_bb.ll | 2 +- ...non-affine-dominance-generated-entering.ll | 2 +- .../CodeGen/non-affine-exit-node-dominance.ll | 2 +- .../non-affine-phi-node-expansion-2.ll | 2 +- .../non-affine-phi-node-expansion-3.ll | 2 +- .../non-affine-phi-node-expansion-4.ll | 2 +- .../CodeGen/non-affine-phi-node-expansion.ll | 2 +- ...e-region-exit-phi-incoming-synthesize-2.ll | 2 +- ...ine-region-exit-phi-incoming-synthesize.ll | 2 +- .../non-affine-region-implicit-store.ll | 2 +- ...ine-region-phi-references-in-scop-value.ll | 2 +- .../non-affine-subregion-dominance-reuse.ll | 2 +- polly/test/CodeGen/non-affine-switch.ll | 2 +- .../non-affine-synthesized-in-branch.ll | 2 +- polly/test/CodeGen/non-affine-update.ll | 4 +- .../non-hoisted-load-needed-as-base-ptr.ll | 2 +- .../test/CodeGen/non_affine_float_compare.ll | 2 +- .../CodeGen/only_non_affine_error_region.ll | 2 +- polly/test/CodeGen/openmp_limit_threads.ll | 12 +-- .../test/CodeGen/out-of-scop-phi-node-use.ll | 2 +- polly/test/CodeGen/param_div_div_div_2.ll | 4 +- polly/test/CodeGen/partial_write_array.ll | 2 +- polly/test/CodeGen/partial_write_emptyset.ll | 2 +- ...l_write_full_write_that_appears_partial.ll | 2 +- .../partial_write_impossible_restriction.ll | 2 +- polly/test/CodeGen/partial_write_in_region.ll | 4 +- .../partial_write_in_region_with_loop.ll | 4 +- .../CodeGen/partial_write_mapped_scalar.ll | 2 +- .../partial_write_mapped_scalar_subregion.ll | 2 +- polly/test/CodeGen/perf_monitoring.ll | 2 +- .../perf_monitoring_cycles_per_scop.ll | 2 +- .../perf_monitoring_trip_counts_per_scop.ll | 2 +- polly/test/CodeGen/phi-defined-before-scop.ll | 2 +- .../phi_after_error_block_outside_of_scop.ll | 2 +- .../test/CodeGen/phi_condition_modeling_1.ll | 2 +- .../test/CodeGen/phi_condition_modeling_2.ll | 2 +- .../test/CodeGen/phi_conditional_simple_1.ll | 4 +- .../phi_in_exit_early_lnt_failure_1.ll | 2 +- .../phi_in_exit_early_lnt_failure_2.ll | 2 +- .../phi_in_exit_early_lnt_failure_3.ll | 2 +- .../phi_in_exit_early_lnt_failure_5.ll | 2 +- polly/test/CodeGen/phi_loop_carried_float.ll | 2 +- .../CodeGen/phi_loop_carried_float_escape.ll | 4 +- polly/test/CodeGen/phi_scalar_simple_1.ll | 2 +- polly/test/CodeGen/phi_scalar_simple_2.ll | 2 +- .../CodeGen/phi_with_multi_exiting_edges_2.ll | 2 +- polly/test/CodeGen/phi_with_one_exit_edge.ll | 2 +- .../CodeGen/pointer-type-expressions-2.ll | 4 +- .../test/CodeGen/pointer-type-expressions.ll | 4 +- .../pointer-type-pointer-type-comparison.ll | 4 +- polly/test/CodeGen/pointer_rem.ll | 4 +- polly/test/CodeGen/pr25241.ll | 2 +- polly/test/CodeGen/ptrtoint_as_parameter.ll | 2 +- polly/test/CodeGen/read-only-scalars.ll | 4 +- polly/test/CodeGen/reduction.ll | 2 +- polly/test/CodeGen/reduction_2.ll | 2 +- polly/test/CodeGen/reduction_simple_binary.ll | 2 +- .../test/CodeGen/region-with-instructions.ll | 2 +- polly/test/CodeGen/region_exiting-domtree.ll | 2 +- .../CodeGen/region_multiexit_partialwrite.ll | 2 +- ...run-time-condition-with-scev-parameters.ll | 4 +- polly/test/CodeGen/run-time-condition.ll | 2 +- .../scalar-references-used-in-scop-compute.ll | 2 +- .../test/CodeGen/scalar-store-from-same-bb.ll | 2 +- polly/test/CodeGen/scalar_codegen_crash.ll | 2 +- polly/test/CodeGen/scev-backedgetaken.ll | 2 +- .../CodeGen/scev-division-invariant-load.ll | 2 +- polly/test/CodeGen/scev.ll | 2 +- .../CodeGen/scev_expansion_in_nonaffine.ll | 2 +- .../CodeGen/scev_looking_through_bitcasts.ll | 2 +- .../CodeGen/scop_expander_insert_point.ll | 2 +- polly/test/CodeGen/scop_expander_segfault.ll | 2 +- ...p_never_executed_runtime_check_location.ll | 2 +- polly/test/CodeGen/select-base-pointer.ll | 2 +- polly/test/CodeGen/sequential_loops.ll | 2 +- .../CodeGen/simple_loop_non_single_exit.ll | 2 +- .../CodeGen/simple_loop_non_single_exit_2.ll | 2 +- polly/test/CodeGen/simple_non_single_entry.ll | 2 +- polly/test/CodeGen/simple_nonaffine_loop.ll | 2 +- .../single_do_loop_int_max_iterations.ll | 2 +- .../single_do_loop_int_param_iterations.ll | 2 +- .../single_do_loop_ll_max_iterations.ll | 4 +- .../CodeGen/single_do_loop_one_iteration.ll | 2 +- .../CodeGen/single_do_loop_scev_replace.ll | 2 +- polly/test/CodeGen/single_loop.ll | 2 +- .../CodeGen/single_loop_int_max_iterations.ll | 2 +- .../CodeGen/single_loop_ll_max_iterations.ll | 2 +- .../test/CodeGen/single_loop_one_iteration.ll | 2 +- polly/test/CodeGen/single_loop_param.ll | 2 +- .../CodeGen/single_loop_param_less_equal.ll | 6 +- .../CodeGen/single_loop_param_less_than.ll | 4 +- .../CodeGen/single_loop_zero_iterations.ll | 2 +- polly/test/CodeGen/split_edge_of_exit.ll | 4 +- polly/test/CodeGen/split_edges.ll | 2 +- polly/test/CodeGen/split_edges_2.ll | 2 +- polly/test/CodeGen/srem-in-other-bb.ll | 2 +- .../stack-overflow-in-load-hoisting.ll | 2 +- .../test/CodeGen/stmt_split_no_dependence.ll | 2 +- .../CodeGen/switch-in-non-affine-region.ll | 2 +- .../synthesizable_phi_write_after_loop.ll | 2 +- .../test-invalid-operands-for-select-2.ll | 2 +- .../test-invalid-operands-for-select.ll | 2 +- polly/test/CodeGen/test.ll | 2 +- .../two-loops-right-after-each-other-2.ll | 2 +- .../two-scops-in-row-invalidate-scevs.ll | 2 +- polly/test/CodeGen/two-scops-in-row.ll | 4 +- polly/test/CodeGen/udiv_expansion_position.ll | 2 +- .../CodeGen/uninitialized_scalar_memory.ll | 2 +- .../unpredictable-loop-unsynthesizable.ll | 6 +- .../test/CodeGen/variant_load_empty_domain.ll | 2 +- .../whole-scop-non-affine-subregion.ll | 2 +- polly/test/DeLICM/confused_order.ll | 4 +- ...ontradicting_assumed_context_and_domain.ll | 2 +- polly/test/DeLICM/load-in-cond-inf-loop.ll | 2 +- polly/test/DeLICM/map_memset_zero.ll | 4 +- polly/test/DeLICM/nomap_alreadymapped.ll | 2 +- polly/test/DeLICM/nomap_escaping.ll | 2 +- polly/test/DeLICM/nomap_occupied.ll | 2 +- polly/test/DeLICM/nomap_readonly.ll | 2 +- polly/test/DeLICM/nomap_spuriouswrite.ll | 2 +- polly/test/DeLICM/nomap_storagesize.ll | 2 +- polly/test/DeLICM/nomap_writewrite.ll | 2 +- polly/test/DeLICM/outofquota-reverseDomain.ll | 2 +- polly/test/DeLICM/pass_existence.ll | 6 +- polly/test/DeLICM/pr41656.ll | 2 +- polly/test/DeLICM/pr48783.ll | 2 +- polly/test/DeLICM/reduction.ll | 2 +- .../reduction_looprotate_gvnpre_cond1.ll | 2 +- .../reduction_looprotate_gvnpre_cond2.ll | 2 +- ...reduction_looprotate_gvnpre_nopreheader.ll | 2 +- .../reduction_looprotate_licm_nopreheader.ll | 2 +- .../reduction_looprotate_loopguard_gvnpre.ll | 2 +- .../reduction_looprotate_loopguard_licm1.ll | 2 +- .../reduction_looprotate_loopguard_licm2.ll | 2 +- .../reduction_looprotate_loopguard_licm3.ll | 2 +- .../test/DeLICM/reduction_unrelatedunusual.ll | 2 +- polly/test/DeLICM/reject_loadafterstore.ll | 2 +- polly/test/DeLICM/reject_outofquota.ll | 4 +- polly/test/DeLICM/reject_storeafterstore.ll | 2 +- polly/test/DeLICM/reject_storeinsubregion.ll | 2 +- polly/test/DeLICM/reject_unusualstore.ll | 4 +- polly/test/DeLICM/skip_maywrite.ll | 2 +- polly/test/DeLICM/skip_multiaccess.ll | 2 +- polly/test/DeLICM/skip_notinloop.ll | 2 +- polly/test/DeLICM/skip_scalaraccess.ll | 2 +- .../DeadCodeElimination/chained_iterations.ll | 4 +- .../chained_iterations_2.ll | 4 +- polly/test/DeadCodeElimination/computeout.ll | 5 +- .../dead_iteration_elimination.ll | 3 +- .../non-affine-affine-mix.ll | 2 +- polly/test/DeadCodeElimination/non-affine.ll | 2 +- .../test/DeadCodeElimination/null_schedule.ll | 2 +- polly/test/DependenceInfo/computeout.ll | 6 +- .../different_schedule_dimensions.ll | 4 +- polly/test/DependenceInfo/do_pluto_matmult.ll | 6 +- polly/test/DependenceInfo/fine_grain_dep_0.ll | 7 +- .../generate_may_write_dependence_info.ll | 2 +- .../test/DependenceInfo/infeasible_context.ll | 5 +- ...writes_do_not_block_must_writes_for_war.ll | 2 +- .../nonaffine-condition-buildMemoryAccess.ll | 2 +- .../reduction_complex_location.ll | 6 +- ...ndences_equal_non_reduction_dependences.ll | 2 +- .../reduction_dependences_not_null.ll | 2 +- ...reduction_and_non_reduction_dependences.ll | 2 +- .../reduction_multiple_loops_array_sum.ll | 6 +- .../reduction_multiple_loops_array_sum_2.ll | 2 +- .../reduction_multiple_loops_array_sum_3.ll | 2 +- .../reduction_multiple_reductions.ll | 2 +- .../reduction_multiple_reductions_2.ll | 2 +- .../reduction_only_reduction_like_access.ll | 2 +- ...lly_escaping_intermediate_in_other_stmt.ll | 2 +- .../reduction_privatization_deps.ll | 2 +- .../reduction_privatization_deps_2.ll | 2 +- .../reduction_privatization_deps_3.ll | 2 +- .../reduction_privatization_deps_4.ll | 2 +- .../reduction_privatization_deps_5.ll | 2 +- .../test/DependenceInfo/reduction_sequence.ll | 2 +- .../DependenceInfo/reduction_simple_iv.ll | 2 +- ...ion_simple_iv_debug_wrapped_dependences.ll | 2 +- .../reduction_simple_privatization_deps_2.ll | 2 +- ...n_simple_privatization_deps_w_parameter.ll | 2 +- ...duction_two_reductions_different_rloops.ll | 2 +- polly/test/DependenceInfo/sequential_loops.ll | 79 +++++++++++-------- polly/test/ForwardOpTree/atax.ll | 2 +- polly/test/ForwardOpTree/changed-kind.ll | 2 +- .../test/ForwardOpTree/forward_from_region.ll | 2 +- polly/test/ForwardOpTree/forward_hoisted.ll | 2 +- .../test/ForwardOpTree/forward_instruction.ll | 2 +- .../test/ForwardOpTree/forward_into_region.ll | 2 +- .../forward_into_region_redundant_use.ll | 2 +- polly/test/ForwardOpTree/forward_load.ll | 3 +- .../forward_load_differentarray.ll | 2 +- .../forward_load_double_write.ll | 2 +- .../ForwardOpTree/forward_load_fromloop.ll | 2 +- .../ForwardOpTree/forward_load_indirect.ll | 2 +- .../forward_load_memset_after.ll | 2 +- .../forward_load_memset_before.ll | 2 +- .../ForwardOpTree/forward_load_tripleuse.ll | 2 +- .../forward_load_unrelatedunusual.ll | 2 +- polly/test/ForwardOpTree/forward_phi_load.ll | 2 +- polly/test/ForwardOpTree/forward_readonly.ll | 4 +- polly/test/ForwardOpTree/forward_reusue.ll | 2 +- polly/test/ForwardOpTree/forward_store.ll | 2 +- .../forward_synthesizable_definloop.ll | 2 +- .../forward_synthesizable_indvar.ll | 2 +- .../forward_synthesizable_useinloop.ll | 2 +- .../test/ForwardOpTree/forward_transitive.ll | 2 +- polly/test/ForwardOpTree/jacobi-1d.ll | 2 +- .../ForwardOpTree/noforward_from_region.ll | 2 +- .../noforward_load_conditional.ll | 2 +- .../noforward_load_writebetween.ll | 2 +- .../ForwardOpTree/noforward_outofquota.ll | 4 +- polly/test/ForwardOpTree/noforward_partial.ll | 2 +- polly/test/ForwardOpTree/noforward_phi.ll | 2 +- .../ForwardOpTree/noforward_selfrefphi.ll | 2 +- .../ForwardOpTree/noforward_sideffects.ll | 2 +- .../noforward_synthesizable_unknownit.ll | 2 +- polly/test/ForwardOpTree/out-of-quota1.ll | 2 +- .../alias_checks_with_empty_context.ll | 2 +- polly/test/IstAstInfo/alias_simple_1.ll | 10 +-- polly/test/IstAstInfo/alias_simple_2.ll | 12 +-- polly/test/IstAstInfo/alias_simple_3.ll | 10 +-- .../aliasing_arrays_with_identical_base.ll | 2 +- .../aliasing_multiple_alias_groups.ll | 4 +- .../aliasing_parametric_simple_1.ll | 2 +- .../aliasing_parametric_simple_2.ll | 2 +- .../IstAstInfo/dependence_distance_minimal.ll | 2 +- .../domain_bounded_only_with_context.ll | 2 +- polly/test/IstAstInfo/non_affine_access.ll | 2 +- ...reduction_clauses_onedimensional_access.ll | 2 +- ...ndences_equal_non_reduction_dependences.ll | 2 +- .../reduction_different_reduction_clauses.ll | 2 +- ...ction_modulo_and_loop_reversal_schedule.ll | 2 +- ...ion_modulo_and_loop_reversal_schedule_2.ll | 2 +- ...ion_modulo_schedule_multiple_dimensions.ll | 2 +- ...n_modulo_schedule_multiple_dimensions_2.ll | 2 +- ...n_modulo_schedule_multiple_dimensions_3.ll | 2 +- ...n_modulo_schedule_multiple_dimensions_4.ll | 2 +- ...n_modulo_schedule_multiple_dimensions_5.ll | 2 +- .../reduction_multiple_dimensions.ll | 2 +- .../reduction_multiple_dimensions_2.ll | 2 +- .../reduction_multiple_dimensions_3.ll | 2 +- .../reduction_multiple_dimensions_4.ll | 2 +- polly/test/IstAstInfo/run-time-condition.ll | 2 +- .../runtime_context_with_error_blocks.ll | 2 +- .../IstAstInfo/simple-run-time-condition.ll | 2 +- .../test/IstAstInfo/single_loop_strip_mine.ll | 4 +- .../single_loop_uint_max_iterations.ll | 2 +- .../single_loop_ull_max_iterations.ll | 2 +- .../ImportAccesses-Bad-relation.ll | 2 +- .../ImportAccesses-No-accesses-key.ll | 2 +- .../ImportAccesses-Not-enough-MemAcc.ll | 2 +- .../ImportAccesses-Not-enough-statements.ll | 2 +- .../ImportAccesses-Relation-mispelled.ll | 2 +- .../ImportAccesses-Statements-mispelled.ll | 2 +- ...ImportAccesses-Undeclared-ScopArrayInfo.ll | 2 +- .../ImportAccesses-Wrong-number-dimensions.ll | 2 +- .../ImportArrays-Mispelled-type.ll | 2 +- .../ImportArrays-Negative-size.ll | 2 +- .../ImportArrays/ImportArrays-No-name.ll | 2 +- .../ImportArrays/ImportArrays-No-sizes-key.ll | 2 +- .../ImportArrays/ImportArrays-No-type-key.ll | 2 +- .../ImportContext-Context-mispelled.ll | 2 +- .../ImportContext-Not-parameter-set.ll | 2 +- .../ImportContext-Unvalid-Context.ll | 2 +- .../ImportContext-Wrong-dimension.ll | 2 +- .../ImportSchedule-No-schedule-key.ll | 2 +- .../ImportSchedule-Schedule-not-valid.ll | 2 +- .../ImportSchedule-Statements-mispelled.ll | 2 +- .../ImportSchedule-Wrong-number-statements.ll | 2 +- .../load_after_store_same_statement.ll | 6 +- .../read_from_original.ll | 6 +- .../MaximalStaticExpansion/too_many_writes.ll | 6 +- .../working_deps_between_inners.ll | 3 +- .../working_deps_between_inners_phi.ll | 6 +- .../working_expansion.ll | 3 +- ...sion_multiple_dependences_per_statement.ll | 3 +- ...sion_multiple_instruction_per_statement.ll | 3 +- .../working_phi_expansion.ll | 6 +- .../working_phi_two_scalars.ll | 6 +- .../working_value_expansion.ll | 3 +- .../prune_only_scalardeps.ll | 3 +- .../2012-03-16-Empty-Domain.ll | 2 +- .../2013-04-11-Empty-Domain-two.ll | 2 +- .../GreedyFuse/fuse-double.ll | 4 +- .../GreedyFuse/fuse-except-first.ll | 4 +- .../GreedyFuse/fuse-except-third.ll | 4 +- .../GreedyFuse/fuse-inner-carried.ll | 4 +- .../GreedyFuse/fuse-inner-third.ll | 4 +- .../GreedyFuse/fuse-inner.ll | 4 +- .../GreedyFuse/fuse-simple.ll | 4 +- .../GreedyFuse/nofuse-simple.ll | 4 +- .../GreedyFuse/nofuse-with-middle.ll | 4 +- .../ManualOptimization/disable_nonforced.ll | 2 +- .../distribute_heuristic.ll | 4 +- .../distribute_illegal_looploc.ll | 2 +- .../distribute_illegal_pragmaloc.ll | 2 +- .../ManualOptimization/unroll_disable.ll | 2 +- .../ManualOptimization/unroll_double.ll | 2 +- .../ManualOptimization/unroll_full.ll | 2 +- .../ManualOptimization/unroll_heuristic.ll | 4 +- .../ManualOptimization/unroll_partial.ll | 4 +- .../unroll_partial_followup.ll | 8 +- .../ScheduleOptimizer/SIMDInParallelFor.ll | 2 +- polly/test/ScheduleOptimizer/computeout.ll | 6 +- .../ensure-correct-tile-sizes.ll | 4 +- .../focaltech_test_detail_threshold-7bc17e.ll | 3 +- .../full_partial_tile_separation.ll | 2 +- polly/test/ScheduleOptimizer/line-tiling-2.ll | 2 +- polly/test/ScheduleOptimizer/line-tiling.ll | 2 +- .../mat_mul_pattern_data_layout.ll | 2 +- .../mat_mul_pattern_data_layout_2.ll | 4 +- .../ScheduleOptimizer/one-dimensional-band.ll | 2 +- .../ScheduleOptimizer/outer_coincidence.ll | 4 +- ...attern-matching-based-opts-after-delicm.ll | 4 +- ...tern-matching-based-opts-after-delicm_2.ll | 2 +- .../pattern-matching-based-opts.ll | 8 +- .../pattern-matching-based-opts_11.ll | 4 +- .../pattern-matching-based-opts_12.ll | 2 +- .../pattern-matching-based-opts_13.ll | 2 +- .../pattern-matching-based-opts_14.ll | 4 +- .../pattern-matching-based-opts_15.ll | 2 +- .../pattern-matching-based-opts_16.ll | 2 +- .../pattern-matching-based-opts_17.ll | 2 +- .../pattern-matching-based-opts_18.ll | 2 +- .../pattern-matching-based-opts_19.ll | 2 +- .../pattern-matching-based-opts_2.ll | 2 +- .../pattern-matching-based-opts_20.ll | 2 +- .../pattern-matching-based-opts_21.ll | 2 +- .../pattern-matching-based-opts_22.ll | 2 +- .../pattern-matching-based-opts_24.ll | 2 +- .../pattern-matching-based-opts_25.ll | 4 +- .../pattern-matching-based-opts_3.ll | 8 +- .../pattern-matching-based-opts_4.ll | 8 +- .../pattern-matching-based-opts_5.ll | 6 +- .../pattern-matching-based-opts_6.ll | 6 +- .../pattern-matching-based-opts_7.ll | 2 +- .../pattern-matching-based-opts_8.ll | 2 +- .../pattern-matching-based-opts_9.ll | 4 +- .../pattern_matching_based_opts_splitmap.ll | 2 +- .../prevectorization-without-tiling.ll | 2 +- .../ScheduleOptimizer/prevectorization.ll | 4 +- .../ScheduleOptimizer/rectangular-tiling.ll | 8 +- .../ScheduleOptimizer/schedule_computeout.ll | 2 +- polly/test/ScheduleOptimizer/statistics.ll | 2 +- .../ScheduleOptimizer/tile_after_fusion.ll | 4 +- ...vivid_vbi_gen_sliced-before-llvmreduced.ll | 2 +- .../aliasing_parametric_simple_1.ll | 2 +- .../aliasing_parametric_simple_2.ll | 2 +- polly/test/ScopDetect/aliasing_simple_1.ll | 2 +- polly/test/ScopDetect/aliasing_simple_2.ll | 2 +- .../base_pointer_load_setNewAccessRelation.ll | 2 +- .../base_pointer_setNewAccessRelation.ll | 2 +- polly/test/ScopDetect/callbr.ll | 4 +- .../ScopDetect/collective_invariant_loads.ll | 2 +- .../ScopDetect/cross_loop_non_single_exit.ll | 2 +- .../cross_loop_non_single_exit_2.ll | 2 +- ...ependency_to_phi_node_outside_of_region.ll | 2 +- polly/test/ScopDetect/dot-scops-npm.ll | 2 +- polly/test/ScopDetect/dot-scops.ll | 2 +- .../ScopDetect/error-block-always-executed.ll | 2 +- .../error-block-referenced-from-scop.ll | 2 +- .../ScopDetect/error-block-unreachable.ll | 2 +- .../ScopDetect/expand-region-correctly-2.ll | 2 +- .../ScopDetect/expand-region-correctly.ll | 2 +- .../test/ScopDetect/ignore_func_flag_regex.ll | 2 +- .../index_from_unpredictable_loop.ll | 4 +- .../index_from_unpredictable_loop2.ll | 4 +- polly/test/ScopDetect/indvars.ll | 2 +- polly/test/ScopDetect/intrinsics_1.ll | 2 +- polly/test/ScopDetect/intrinsics_2.ll | 2 +- polly/test/ScopDetect/intrinsics_3.ll | 2 +- .../ScopDetect/invalid-latch-conditions.ll | 6 +- .../ScopDetect/invalidate_scalar_evolution.ll | 2 +- .../ScopDetect/invariant-load-before-scop.ll | 2 +- polly/test/ScopDetect/keep_going_expansion.ll | 2 +- polly/test/ScopDetect/mod_ref_read_pointer.ll | 4 +- polly/test/ScopDetect/more-than-one-loop.ll | 4 +- .../ScopDetect/multidim-with-undef-size.ll | 2 +- polly/test/ScopDetect/multidim.ll | 2 +- .../ScopDetect/multidim_indirect_access.ll | 2 +- ..._two_accesses_different_delinearization.ll | 2 +- .../ScopDetect/nested_loop_single_exit.ll | 4 +- .../test/ScopDetect/non-affine-conditional.ll | 2 +- .../ScopDetect/non-affine-float-compare.ll | 2 +- ...-affine-loop-condition-dependent-access.ll | 8 +- ...ffine-loop-condition-dependent-access_2.ll | 6 +- ...ffine-loop-condition-dependent-access_3.ll | 6 +- polly/test/ScopDetect/non-affine-loop.ll | 10 +-- .../non-beneficial-loops-small-trip-count.ll | 2 +- .../non-constant-add-rec-start-expr.ll | 2 +- .../ScopDetect/non-simple-memory-accesses.ll | 2 +- .../ScopDetect/non_affine_loop_condition.ll | 4 +- polly/test/ScopDetect/only-one-affine-loop.ll | 2 +- polly/test/ScopDetect/only_func_flag.ll | 2 +- polly/test/ScopDetect/only_func_flag_regex.ll | 2 +- .../parametric-multiply-in-scev-2.ll | 2 +- .../ScopDetect/parametric-multiply-in-scev.ll | 2 +- .../phi_with_multi_exiting_edges.ll | 2 +- .../profitability-large-basic-blocks.ll | 6 +- .../profitability-two-nested-loops.ll | 2 +- polly/test/ScopDetect/remove_all_children.ll | 2 +- polly/test/ScopDetect/report-scop-location.ll | 2 +- .../restrict-undef-size-scopdetect.ll | 2 +- polly/test/ScopDetect/run_time_alias_check.ll | 2 +- polly/test/ScopDetect/scev_remove_max.ll | 2 +- polly/test/ScopDetect/sequential_loops.ll | 6 +- polly/test/ScopDetect/simple_loop.ll | 2 +- .../simple_loop_non_single_entry.ll | 2 +- .../ScopDetect/simple_loop_non_single_exit.ll | 2 +- .../simple_loop_non_single_exit_2.ll | 2 +- .../ScopDetect/simple_loop_two_phi_nodes.ll | 2 +- .../test/ScopDetect/simple_loop_with_param.ll | 2 +- .../ScopDetect/simple_loop_with_param_2.ll | 2 +- .../ScopDetect/simple_non_single_entry.ll | 2 +- .../ScopDetect/skip_function_attribute.ll | 2 +- .../srem_with_parametric_divisor.ll | 2 +- polly/test/ScopDetect/statistics.ll | 2 +- polly/test/ScopDetect/switch-in-loop-patch.ll | 2 +- .../ReportAlias-01.ll | 2 +- .../ScopDetectionDiagnostics/ReportEntry.ll | 2 +- .../ReportFuncCall-01.ll | 2 +- .../ReportIrreducibleRegion.ll | 2 +- .../ReportIrreducibleRegionWithoutDebugLoc.ll | 2 +- .../ReportLoopBound-01.ll | 6 +- .../ReportLoopHasNoExit.ll | 4 +- .../ReportMultipleNonAffineAccesses.ll | 12 +-- .../ReportNonAffineAccess-01.ll | 2 +- .../ReportUnprofitable.ll | 4 +- .../ReportUnreachableInExit.ll | 2 +- .../ReportVariantBasePtr-01.ll | 2 +- .../loop_has_multiple_exits.ll | 2 +- .../loop_partially_in_scop-2.ll | 2 +- .../loop_partially_in_scop.ll | 2 +- .../ScopInfo/20110312-Fail-without-basicaa.ll | 2 +- .../20111108-Parameter-not-detected.ll | 2 +- ...03-16-Crash-because-of-unsigned-in-scev.ll | 2 +- .../2015-10-04-Crash-in-domain-generation.ll | 2 +- polly/test/ScopInfo/Alias-0.ll | 4 +- polly/test/ScopInfo/Alias-1.ll | 4 +- polly/test/ScopInfo/Alias-2.ll | 4 +- polly/test/ScopInfo/Alias-3.ll | 4 +- polly/test/ScopInfo/Alias-4.ll | 4 +- .../test/ScopInfo/BoundChecks/single-loop.ll | 4 +- polly/test/ScopInfo/BoundChecks/two-loops.ll | 4 +- polly/test/ScopInfo/NonAffine/div_backedge.ll | 2 +- polly/test/ScopInfo/NonAffine/div_domain.ll | 2 +- ...nt_loads_dependent_in_non_affine_region.ll | 2 +- .../ScopInfo/NonAffine/modulo_backedge.ll | 2 +- .../test/ScopInfo/NonAffine/modulo_domain.ll | 2 +- ...ffine-loop-condition-dependent-access_1.ll | 4 +- ...ffine-loop-condition-dependent-access_2.ll | 6 +- ...ffine-loop-condition-dependent-access_3.ll | 6 +- .../non_affine_access_with_range_2.ll | 2 +- .../ScopInfo/NonAffine/non_affine_but_sdiv.ll | 2 +- .../ScopInfo/NonAffine/non_affine_but_srem.ll | 2 +- .../non_affine_conditional_nested.ll | 2 +- ...ine_conditional_surrounding_affine_loop.ll | 4 +- ...conditional_surrounding_non_affine_loop.ll | 6 +- .../NonAffine/non_affine_float_compare.ll | 2 +- .../NonAffine/non_affine_loop_condition.ll | 6 +- .../NonAffine/non_affine_loop_used_later.ll | 4 +- .../NonAffine/non_affine_parametric_loop.ll | 2 +- .../non_affine_region_guaranteed_non-entry.ll | 2 +- ...whole-scop-non-affine-subregion-in-loop.ll | 2 +- .../aliasing_conditional_alias_groups_1.ll | 2 +- .../aliasing_conditional_alias_groups_2.ll | 2 +- polly/test/ScopInfo/aliasing_dead_access.ll | 2 +- .../aliasing_many_arrays_to_compare.ll | 8 +- .../aliasing_many_read_only_acesses.ll | 2 +- .../aliasing_multiple_alias_groups.ll | 4 +- .../aliasing_with_non_affine_access.ll | 2 +- .../allow-all-parameters-dereferencable.ll | 6 +- polly/test/ScopInfo/assume_gep_bounds.ll | 4 +- polly/test/ScopInfo/assume_gep_bounds_2.ll | 2 +- polly/test/ScopInfo/assume_gep_bounds_many.ll | 4 +- .../avoid_new_parameters_from_geps.ll | 2 +- polly/test/ScopInfo/bool-addrec.ll | 2 +- .../test/ScopInfo/bounded_loop_assumptions.ll | 2 +- ...ces-loop-scev-with-unknown-iterations-2.ll | 4 +- ...ces-loop-scev-with-unknown-iterations-3.ll | 6 +- ...ences-loop-scev-with-unknown-iterations.ll | 6 +- polly/test/ScopInfo/bug_2010_10_22.ll | 2 +- polly/test/ScopInfo/bug_2011_1_5.ll | 2 +- .../test/ScopInfo/bug_scev_not_fully_eval.ll | 2 +- polly/test/ScopInfo/cfg_consequences.ll | 2 +- .../test/ScopInfo/complex-branch-structure.ll | 2 +- polly/test/ScopInfo/complex-condition.ll | 2 +- polly/test/ScopInfo/complex-expression.ll | 2 +- polly/test/ScopInfo/complex-loop-nesting.ll | 2 +- .../ScopInfo/complex-successor-structure-2.ll | 2 +- .../ScopInfo/complex-successor-structure-3.ll | 4 +- .../ScopInfo/complex-successor-structure.ll | 2 +- .../complex_domain_binary_condition.ll | 2 +- .../ScopInfo/complex_execution_context.ll | 2 +- polly/test/ScopInfo/cond_constant_in_loop.ll | 2 +- polly/test/ScopInfo/cond_in_loop.ll | 2 +- .../ScopInfo/condition-after-error-block-2.ll | 2 +- ...condition-after-error-block-before-scop.ll | 2 +- .../ScopInfo/condtion-after-error-block.ll | 2 +- polly/test/ScopInfo/const_srem_sdiv.ll | 4 +- .../constant-non-integer-branch-condition.ll | 2 +- .../ScopInfo/constant_factor_in_parameter.ll | 4 +- ...stant_functions_outside_scop_as_unknown.ll | 2 +- polly/test/ScopInfo/constant_start_integer.ll | 2 +- polly/test/ScopInfo/debug_call.ll | 2 +- .../delinearize-together-all-data-refs.ll | 2 +- polly/test/ScopInfo/div_by_zero.ll | 2 +- .../do-not-model-error-block-accesses.ll | 2 +- .../eager-binary-and-or-conditions.ll | 4 +- .../early_exit_for_complex_domains.ll | 2 +- polly/test/ScopInfo/error-blocks-1.ll | 2 +- polly/test/ScopInfo/error-blocks-2.ll | 4 +- polly/test/ScopInfo/escaping_empty_scop.ll | 2 +- polly/test/ScopInfo/exit-phi-1.ll | 4 +- polly/test/ScopInfo/exit-phi-2.ll | 2 +- polly/test/ScopInfo/exit_phi_accesses-2.ll | 2 +- polly/test/ScopInfo/exit_phi_accesses.ll | 2 +- .../ScopInfo/expensive-boundary-context.ll | 4 +- ...onstant_factor_introduces_new_parameter.ll | 4 +- polly/test/ScopInfo/full-function.ll | 4 +- polly/test/ScopInfo/granularity_same_name.ll | 8 +- .../test/ScopInfo/granularity_scalar-indep.ll | 2 +- ...ity_scalar-indep_cross-referencing-phi1.ll | 2 +- ...ity_scalar-indep_cross-referencing-phi2.ll | 2 +- .../granularity_scalar-indep_epilogue.ll | 2 +- .../granularity_scalar-indep_epilogue_last.ll | 2 +- .../granularity_scalar-indep_noepilogue.ll | 2 +- .../granularity_scalar-indep_ordered-2.ll | 2 +- .../granularity_scalar-indep_ordered.ll | 2 +- polly/test/ScopInfo/i1_params.ll | 2 +- polly/test/ScopInfo/infeasible-rtc.ll | 4 +- .../ScopInfo/infeasible_invalid_context.ll | 4 +- polly/test/ScopInfo/int2ptr_ptr2int.ll | 4 +- polly/test/ScopInfo/int2ptr_ptr2int_2.ll | 8 +- polly/test/ScopInfo/integers.ll | 2 +- .../ScopInfo/inter-error-bb-dependence.ll | 2 +- polly/test/ScopInfo/inter_bb_scalar_dep.ll | 4 +- .../intra-non-affine-stmt-phi-node.ll | 4 +- .../ScopInfo/intra_and_inter_bb_scalar_dep.ll | 4 +- polly/test/ScopInfo/intra_bb_scalar_dep.ll | 4 +- polly/test/ScopInfo/intrinsics.ll | 2 +- ..._add_rec_after_invariant_load_remapping.ll | 2 +- .../invalidate_iterator_during_MA_removal.ll | 2 +- .../test/ScopInfo/invariant-load-instlist.ll | 2 +- ...ariant-loads-leave-read-only-statements.ll | 4 +- polly/test/ScopInfo/invariant_load.ll | 2 +- ...load_access_classes_different_base_type.ll | 4 +- ...ss_classes_different_base_type_escaping.ll | 4 +- ...lasses_different_base_type_same_pointer.ll | 4 +- ...fferent_base_type_same_pointer_escaping.ll | 4 +- .../ScopInfo/invariant_load_addrec_sum.ll | 2 +- .../ScopInfo/invariant_load_base_pointer.ll | 2 +- ...invariant_load_base_pointer_conditional.ll | 2 +- ...ariant_load_base_pointer_in_conditional.ll | 2 +- .../invariant_load_branch_condition.ll | 4 +- ...ariant_load_canonicalize_array_baseptrs.ll | 2 +- ...iant_load_canonicalize_array_baseptrs_2.ll | 2 +- ...iant_load_canonicalize_array_baseptrs_3.ll | 2 +- ...iant_load_canonicalize_array_baseptrs_4.ll | 2 +- ...ant_load_canonicalize_array_baseptrs_4b.ll | 2 +- ...ant_load_canonicalize_array_baseptrs_4c.ll | 2 +- ...iant_load_canonicalize_array_baseptrs_5.ll | 2 +- .../invariant_load_complex_condition.ll | 4 +- .../test/ScopInfo/invariant_load_condition.ll | 2 +- .../invariant_load_dereferenceable.ll | 4 +- ...iant_load_distinct_parameter_valuations.ll | 2 +- .../ScopInfo/invariant_load_in_non_affine.ll | 4 +- polly/test/ScopInfo/invariant_load_loop_ub.ll | 4 +- .../invariant_load_ptr_ptr_noalias.ll | 4 +- .../ScopInfo/invariant_load_scalar_dep.ll | 2 +- .../ScopInfo/invariant_load_stmt_domain.ll | 2 +- .../invariant_load_zext_parameter-2.ll | 4 +- .../ScopInfo/invariant_load_zext_parameter.ll | 4 +- ...load_zextended_in_own_execution_context.ll | 4 +- ...invariant_loads_complicated_dependences.ll | 2 +- .../invariant_loads_cyclic_dependences.ll | 2 +- polly/test/ScopInfo/invariant_loop_bounds.ll | 2 +- ...ariant_same_loop_bound_multiple_times-1.ll | 2 +- ...ariant_same_loop_bound_multiple_times-2.ll | 2 +- polly/test/ScopInfo/isl_aff_out_of_bounds.ll | 2 +- polly/test/ScopInfo/isl_trip_count_01.ll | 2 +- polly/test/ScopInfo/isl_trip_count_02.ll | 2 +- polly/test/ScopInfo/isl_trip_count_03.ll | 2 +- .../isl_trip_count_multiple_exiting_blocks.ll | 2 +- polly/test/ScopInfo/licm_load.ll | 4 +- polly/test/ScopInfo/licm_potential_store.ll | 4 +- polly/test/ScopInfo/licm_reduction_nested.ll | 4 +- .../long-compile-time-alias-analysis.ll | 2 +- .../long-sequence-of-error-blocks-2.ll | 2 +- .../ScopInfo/long-sequence-of-error-blocks.ll | 4 +- .../test/ScopInfo/loop-multiexit-succ-cond.ll | 4 +- polly/test/ScopInfo/loop_affine_bound_0.ll | 4 +- polly/test/ScopInfo/loop_affine_bound_1.ll | 4 +- polly/test/ScopInfo/loop_affine_bound_2.ll | 4 +- polly/test/ScopInfo/loop_carry.ll | 2 +- .../test/ScopInfo/many-scalar-dependences.ll | 2 +- polly/test/ScopInfo/max-loop-depth.ll | 2 +- polly/test/ScopInfo/memcpy-raw-source.ll | 2 +- polly/test/ScopInfo/memcpy.ll | 4 +- polly/test/ScopInfo/memmove.ll | 4 +- polly/test/ScopInfo/memset.ll | 4 +- polly/test/ScopInfo/memset_null.ll | 4 +- .../ScopInfo/mismatching-array-dimensions.ll | 2 +- .../mod_ref_access_pointee_arguments.ll | 6 +- .../mod_ref_read_pointee_arguments.ll | 6 +- polly/test/ScopInfo/mod_ref_read_pointer.ll | 4 +- polly/test/ScopInfo/mod_ref_read_pointers.ll | 6 +- polly/test/ScopInfo/modulo_zext_1.ll | 2 +- polly/test/ScopInfo/modulo_zext_2.ll | 2 +- polly/test/ScopInfo/modulo_zext_3.ll | 2 +- polly/test/ScopInfo/multi-scop.ll | 2 +- .../ScopInfo/multidim_2d-diagonal-matrix.ll | 4 +- .../multidim_2d_outer_parametric_offset.ll | 2 +- ..._2d_parametric_array_static_loop_bounds.ll | 2 +- .../ScopInfo/multidim_2d_with_modref_call.ll | 8 +- .../multidim_2d_with_modref_call_2.ll | 8 +- ..._3d_parametric_array_static_loop_bounds.ll | 2 +- ...idim_fixedsize_different_dimensionality.ll | 2 +- .../multidim_fixedsize_multi_offset.ll | 2 +- .../ScopInfo/multidim_fold_constant_dim.ll | 2 +- .../multidim_fold_constant_dim_zero.ll | 2 +- polly/test/ScopInfo/multidim_fortran_2d.ll | 4 +- .../ScopInfo/multidim_fortran_2d_params.ll | 4 +- .../multidim_fortran_2d_with_modref_call.ll | 8 +- polly/test/ScopInfo/multidim_fortran_srem.ll | 2 +- .../test/ScopInfo/multidim_gep_pointercast.ll | 2 +- .../ScopInfo/multidim_gep_pointercast2.ll | 2 +- .../multidim_ivs_and_integer_offsets_3d.ll | 2 +- ...multidim_ivs_and_parameteric_offsets_3d.ll | 2 +- .../test/ScopInfo/multidim_many_references.ll | 4 +- .../ScopInfo/multidim_nested_start_integer.ll | 4 +- .../multidim_nested_start_share_parameter.ll | 2 +- polly/test/ScopInfo/multidim_only_ivs_2d.ll | 2 +- polly/test/ScopInfo/multidim_only_ivs_3d.ll | 2 +- .../ScopInfo/multidim_only_ivs_3d_cast.ll | 2 +- .../ScopInfo/multidim_only_ivs_3d_reverse.ll | 2 +- .../ScopInfo/multidim_param_in_subscript-2.ll | 2 +- .../ScopInfo/multidim_param_in_subscript.ll | 2 +- .../multidim_parameter_addrec_product.ll | 2 +- .../multidim_single_and_multidim_array.ll | 16 ++-- polly/test/ScopInfo/multidim_srem.ll | 2 +- polly/test/ScopInfo/multidim_with_bitcast.ll | 2 +- .../ScopInfo/multiple-binary-or-conditions.ll | 4 +- ...ss-offset-not-dividable-by-element-size.ll | 2 +- .../ScopInfo/multiple-types-non-affine-2.ll | 4 +- .../ScopInfo/multiple-types-non-affine.ll | 4 +- .../multiple-types-non-power-of-two-2.ll | 2 +- .../multiple-types-non-power-of-two.ll | 2 +- .../multiple-types-two-dimensional-2.ll | 2 +- .../multiple-types-two-dimensional.ll | 2 +- polly/test/ScopInfo/multiple-types.ll | 4 +- .../test/ScopInfo/multiple_exiting_blocks.ll | 2 +- .../multiple_exiting_blocks_two_loop.ll | 2 +- polly/test/ScopInfo/multiple_latch_blocks.ll | 2 +- polly/test/ScopInfo/nested-loops.ll | 2 +- .../no-scalar-deps-in-non-affine-subregion.ll | 2 +- polly/test/ScopInfo/non-affine-region-phi.ll | 4 +- .../ScopInfo/non-affine-region-with-loop-2.ll | 2 +- .../ScopInfo/non-affine-region-with-loop.ll | 4 +- polly/test/ScopInfo/non-precise-inv-load-1.ll | 2 +- polly/test/ScopInfo/non-precise-inv-load-2.ll | 2 +- polly/test/ScopInfo/non-precise-inv-load-3.ll | 2 +- polly/test/ScopInfo/non-precise-inv-load-4.ll | 2 +- polly/test/ScopInfo/non-precise-inv-load-5.ll | 2 +- polly/test/ScopInfo/non-precise-inv-load-6.ll | 2 +- polly/test/ScopInfo/non-pure-function-call.ll | 2 +- ...-pure-function-calls-causes-dead-blocks.ll | 2 +- .../test/ScopInfo/non-pure-function-calls.ll | 2 +- polly/test/ScopInfo/non_affine_access.ll | 4 +- polly/test/ScopInfo/non_affine_region_1.ll | 2 +- polly/test/ScopInfo/non_affine_region_2.ll | 2 +- polly/test/ScopInfo/non_affine_region_3.ll | 4 +- polly/test/ScopInfo/non_affine_region_4.ll | 2 +- .../ScopInfo/nonaffine-buildMemoryAccess.ll | 2 +- polly/test/ScopInfo/not-a-reduction.ll | 2 +- polly/test/ScopInfo/opaque-struct.ll | 2 +- ...gion-entry-phi-node-nonaffine-subregion.ll | 2 +- ...ut-of-scop-use-in-region-entry-phi-node.ll | 2 +- .../ScopInfo/parameter-constant-division.ll | 4 +- .../ScopInfo/parameter_in_dead_statement.ll | 8 +- polly/test/ScopInfo/parameter_product.ll | 2 +- .../parameter_with_constant_factor_in_add.ll | 2 +- .../ScopInfo/partially_invariant_load_1.ll | 4 +- .../ScopInfo/partially_invariant_load_2.ll | 2 +- .../test/ScopInfo/phi-in-non-affine-region.ll | 2 +- polly/test/ScopInfo/phi_after_error_block.ll | 2 +- .../test/ScopInfo/phi_condition_modeling_1.ll | 2 +- .../test/ScopInfo/phi_condition_modeling_2.ll | 2 +- .../test/ScopInfo/phi_conditional_simple_1.ll | 2 +- polly/test/ScopInfo/phi_loop_carried_float.ll | 2 +- polly/test/ScopInfo/phi_not_grouped_at_top.ll | 2 +- polly/test/ScopInfo/phi_scalar_simple_1.ll | 2 +- polly/test/ScopInfo/phi_scalar_simple_2.ll | 2 +- polly/test/ScopInfo/phi_with_invoke_edge.ll | 2 +- .../ScopInfo/pointer-comparison-no-nsw.ll | 2 +- polly/test/ScopInfo/pointer-comparison.ll | 2 +- .../test/ScopInfo/pointer-type-expressions.ll | 2 +- ...er-used-as-base-pointer-and-scalar-read.ll | 2 +- .../polly-timeout-parameter-bounds.ll | 2 +- ...eserve-equiv-class-order-in-basic_block.ll | 2 +- .../test/ScopInfo/process_added_dimensions.ll | 2 +- .../test/ScopInfo/pwaff-complexity-bailout.ll | 2 +- polly/test/ScopInfo/ranged_parameter.ll | 2 +- polly/test/ScopInfo/ranged_parameter_2.ll | 2 +- polly/test/ScopInfo/ranged_parameter_wrap.ll | 2 +- .../test/ScopInfo/ranged_parameter_wrap_2.ll | 2 +- .../read-only-scalar-used-in-phi-2.ll | 2 +- .../ScopInfo/read-only-scalar-used-in-phi.ll | 2 +- polly/test/ScopInfo/read-only-scalars.ll | 4 +- polly/test/ScopInfo/read-only-statements.ll | 2 +- .../ScopInfo/reduction_alternating_base.ll | 2 +- ...uction_chain_partially_outside_the_scop.ll | 2 +- .../ScopInfo/reduction_different_index.ll | 2 +- .../ScopInfo/reduction_different_index1.ll | 2 +- .../reduction_disabled_multiplicative.ll | 2 +- .../reduction_escaping_intermediate.ll | 2 +- .../reduction_escaping_intermediate_2.ll | 2 +- .../reduction_invalid_different_operators.ll | 2 +- .../reduction_invalid_overlapping_accesses.ll | 2 +- .../reduction_multiple_loops_array_sum.ll | 2 +- .../reduction_multiple_loops_array_sum_1.ll | 2 +- .../reduction_multiple_simple_binary.ll | 2 +- .../reduction_non_overlapping_chains.ll | 2 +- .../reduction_only_reduction_like_access.ll | 2 +- polly/test/ScopInfo/reduction_simple_fp.ll | 2 +- .../ScopInfo/reduction_simple_w_constant.ll | 2 +- polly/test/ScopInfo/reduction_simple_w_iv.ll | 2 +- .../ScopInfo/reduction_two_identical_reads.ll | 4 +- .../redundant_parameter_constraint.ll | 2 +- .../test/ScopInfo/region-with-instructions.ll | 2 +- polly/test/ScopInfo/remarks.ll | 2 +- .../required-invariant-loop-bounds.ll | 4 +- .../ScopInfo/restriction_in_dead_block.ll | 2 +- .../run-time-check-many-array-disjuncts.ll | 4 +- .../run-time-check-many-parameters.ll | 2 +- .../run-time-check-many-piecewise-aliasing.ll | 4 +- .../run-time-check-read-only-arrays.ll | 2 +- .../same-base-address-scalar-and-array.ll | 2 +- polly/test/ScopInfo/scalar.ll | 2 +- .../ScopInfo/scalar_dependence_cond_br.ll | 2 +- polly/test/ScopInfo/scalar_to_array.ll | 4 +- .../scev-div-with-evaluatable-divisor.ll | 2 +- polly/test/ScopInfo/scev-invalidated.ll | 2 +- .../schedule-const-post-dominator-walk-2.ll | 2 +- .../schedule-const-post-dominator-walk.ll | 2 +- .../schedule-constuction-endless-loop1.ll | 2 +- .../schedule-constuction-endless-loop2.ll | 2 +- ...tly-contructed-in-case-of-infinite-loop.ll | 2 +- .../scop-affine-parameter-ordering.ll | 2 +- polly/test/ScopInfo/sign_wrapped_set.ll | 2 +- polly/test/ScopInfo/simple_loop_1.ll | 2 +- polly/test/ScopInfo/simple_loop_2.ll | 2 +- polly/test/ScopInfo/simple_loop_unsigned.ll | 2 +- polly/test/ScopInfo/simple_loop_unsigned_2.ll | 2 +- polly/test/ScopInfo/simple_loop_unsigned_3.ll | 2 +- .../ScopInfo/simple_nonaffine_loop_not.ll | 2 +- polly/test/ScopInfo/smax.ll | 2 +- polly/test/ScopInfo/statistics.ll | 2 +- .../stmt_split_exit_of_region_stmt.ll | 2 +- .../ScopInfo/stmt_split_no_after_split.ll | 2 +- .../test/ScopInfo/stmt_split_no_dependence.ll | 2 +- polly/test/ScopInfo/stmt_split_on_store.ll | 2 +- .../ScopInfo/stmt_split_on_synthesizable.ll | 2 +- .../stmt_split_phi_in_beginning_bb.ll | 2 +- polly/test/ScopInfo/stmt_split_phi_in_stmt.ll | 2 +- .../ScopInfo/stmt_split_scalar_dependence.ll | 2 +- polly/test/ScopInfo/stmt_split_within_loop.ll | 2 +- .../stmt_with_read_but_without_sideffect.ll | 2 +- polly/test/ScopInfo/switch-1.ll | 4 +- polly/test/ScopInfo/switch-2.ll | 4 +- polly/test/ScopInfo/switch-3.ll | 4 +- polly/test/ScopInfo/switch-4.ll | 4 +- polly/test/ScopInfo/switch-5.ll | 4 +- polly/test/ScopInfo/switch-6.ll | 4 +- polly/test/ScopInfo/switch-7.ll | 5 +- polly/test/ScopInfo/tempscop-printing.ll | 2 +- .../ScopInfo/test-wrapping-in-condition.ll | 4 +- polly/test/ScopInfo/truncate-1.ll | 2 +- polly/test/ScopInfo/truncate-2.ll | 2 +- polly/test/ScopInfo/truncate-3.ll | 2 +- polly/test/ScopInfo/two-loops-one-infinite.ll | 2 +- .../two-loops-right-after-each-other.ll | 2 +- polly/test/ScopInfo/undef_in_cond.ll | 2 +- polly/test/ScopInfo/unnamed_nonaffine.ll | 4 +- polly/test/ScopInfo/unnamed_stmts.ll | 2 +- .../ScopInfo/unpredictable_nonscop_loop.ll | 2 +- .../test/ScopInfo/unprofitable_scalar-accs.ll | 4 +- polly/test/ScopInfo/unsigned-condition.ll | 2 +- polly/test/ScopInfo/unsigned-division-1.ll | 2 +- polly/test/ScopInfo/unsigned-division-2.ll | 2 +- polly/test/ScopInfo/unsigned-division-3.ll | 2 +- polly/test/ScopInfo/unsigned-division-4.ll | 2 +- polly/test/ScopInfo/unsigned-division-5.ll | 2 +- polly/test/ScopInfo/unsigned_wrap_uge.ll | 2 +- polly/test/ScopInfo/unsigned_wrap_ugt.ll | 2 +- polly/test/ScopInfo/unsigned_wrap_ule.ll | 2 +- polly/test/ScopInfo/unsigned_wrap_ult.ll | 2 +- polly/test/ScopInfo/user_context.ll | 8 +- ...ed_assumptions-in-bb-signed-conditional.ll | 4 +- .../user_provided_assumptions-in-bb-signed.ll | 2 +- ...ser_provided_assumptions-in-bb-unsigned.ll | 4 +- .../ScopInfo/user_provided_assumptions.ll | 4 +- .../ScopInfo/user_provided_assumptions_2.ll | 4 +- .../ScopInfo/user_provided_assumptions_3.ll | 4 +- ...ser_provided_non_dominating_assumptions.ll | 4 +- polly/test/ScopInfo/variant_base_pointer.ll | 4 +- .../ScopInfo/variant_load_empty_domain.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_0.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_1.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_2.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_3.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_4.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_5.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_6.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_7.ll | 2 +- .../ScopInfo/wraping_signed_expr_slow_1.ll | 2 +- .../ScopInfo/wraping_signed_expr_slow_2.ll | 2 +- polly/test/ScopInfo/zero_ext_of_truncate.ll | 2 +- polly/test/ScopInfo/zero_ext_of_truncate_2.ll | 2 +- .../test/ScopInfo/zero_ext_space_mismatch.ll | 2 +- polly/test/ScopInliner/invariant-load-func.ll | 2 +- polly/test/Simplify/coalesce_3partials.ll | 2 +- .../Simplify/coalesce_disjointelements.ll | 2 +- polly/test/Simplify/coalesce_overlapping.ll | 2 +- polly/test/Simplify/coalesce_partial.ll | 2 +- polly/test/Simplify/dead_access_load.ll | 3 +- polly/test/Simplify/dead_access_phi.ll | 3 +- polly/test/Simplify/dead_access_value.ll | 3 +- polly/test/Simplify/dead_instruction.ll | 3 +- polly/test/Simplify/emptyaccessdomain.ll | 2 +- polly/test/Simplify/exit_phi_accesses-2.ll | 2 +- polly/test/Simplify/func-b320a7.ll | 2 +- polly/test/Simplify/gemm.ll | 2 +- .../Simplify/nocoalesce_differentvalues.ll | 2 +- .../Simplify/nocoalesce_elementmismatch.ll | 2 +- polly/test/Simplify/nocoalesce_readbetween.ll | 2 +- .../test/Simplify/nocoalesce_writebetween.ll | 2 +- polly/test/Simplify/notdead_region_exitphi.ll | 3 +- .../test/Simplify/notdead_region_innerphi.ll | 3 +- .../test/Simplify/notredundant_region_loop.ll | 2 +- .../Simplify/notredundant_region_middle.ll | 3 +- .../notredundant_synthesizable_unknownit.ll | 3 +- ...ut-of-scop-use-in-region-entry-phi-node.ll | 2 +- polly/test/Simplify/overwritten.ll | 3 +- polly/test/Simplify/overwritten_3phi.ll | 2 +- polly/test/Simplify/overwritten_3store.ll | 3 +- .../overwritten_implicit_and_explicit.ll | 2 +- .../test/Simplify/overwritten_loadbetween.ll | 3 +- polly/test/Simplify/overwritten_scalar.ll | 2 +- polly/test/Simplify/pass_existence.ll | 3 +- polly/test/Simplify/phi_in_regionstmt.ll | 3 +- polly/test/Simplify/pr33323.ll | 2 +- polly/test/Simplify/redundant.ll | 3 +- .../test/Simplify/redundant_differentindex.ll | 3 +- polly/test/Simplify/redundant_region.ll | 2 +- .../test/Simplify/redundant_region_scalar.ll | 2 +- polly/test/Simplify/redundant_scalarwrite.ll | 2 +- polly/test/Simplify/redundant_storebetween.ll | 3 +- polly/test/Simplify/scalability1.ll | 2 +- polly/test/Simplify/scalability2.ll | 2 +- polly/test/Simplify/sweep_mapped_phi.ll | 2 +- polly/test/Simplify/sweep_mapped_value.ll | 2 +- .../Simplify/ununsed_read_in_region_entry.ll | 4 +- polly/test/Support/Plugins.ll | 2 +- polly/test/Support/defaultpipelines.ll | 12 +-- polly/test/Support/dumpfunction.ll | 4 +- polly/test/Support/dumpmodule.ll | 4 +- polly/test/Support/exportjson.ll | 2 +- polly/test/Support/isl-args.ll | 8 +- polly/test/Support/pipelineposition.ll | 6 +- polly/test/Support/pollyDebug.ll | 2 +- polly/test/lit.site.cfg.in | 7 +- polly/test/polly.ll | 2 +- 1026 files changed, 1472 insertions(+), 1404 deletions(-) diff --git a/polly/test/CodeGen/20100617.ll b/polly/test/CodeGen/20100617.ll index 320c48192a8a..71a889f067b8 100644 --- a/polly/test/CodeGen/20100617.ll +++ b/polly/test/CodeGen/20100617.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" define void @init_array() nounwind { diff --git a/polly/test/CodeGen/20100622.ll b/polly/test/CodeGen/20100622.ll index 584107df8971..872d6a0d75cf 100644 --- a/polly/test/CodeGen/20100622.ll +++ b/polly/test/CodeGen/20100622.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | not FileCheck %s +; RUN: opt %loadPolly -polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | not FileCheck %s 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:32:32" diff --git a/polly/test/CodeGen/20100707.ll b/polly/test/CodeGen/20100707.ll index 1a4d3556bae8..338198084fc7 100644 --- a/polly/test/CodeGen/20100707.ll +++ b/polly/test/CodeGen/20100707.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" define void @clause_SetSplitField(i32 %Length) nounwind inlinehint { diff --git a/polly/test/CodeGen/20100707_2.ll b/polly/test/CodeGen/20100707_2.ll index 96f329ccbfa9..df784c6d7957 100644 --- a/polly/test/CodeGen/20100707_2.ll +++ b/polly/test/CodeGen/20100707_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" @win193 = external global [4 x [36 x double]], align 32 ; [#uses=3] diff --git a/polly/test/CodeGen/20100708.ll b/polly/test/CodeGen/20100708.ll index 00fb6fa694c1..50b8e385df53 100644 --- a/polly/test/CodeGen/20100708.ll +++ b/polly/test/CodeGen/20100708.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' < %s +; RUN: opt %loadPolly -polly-detect < %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-n8:16:32:64" define fastcc void @execute() nounwind { diff --git a/polly/test/CodeGen/20100708_2.ll b/polly/test/CodeGen/20100708_2.ll index 67f3913d69d4..2f4807d9e4d7 100644 --- a/polly/test/CodeGen/20100708_2.ll +++ b/polly/test/CodeGen/20100708_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" define void @init_array() nounwind { diff --git a/polly/test/CodeGen/20100713.ll b/polly/test/CodeGen/20100713.ll index 73ba0272e5c9..edd352a4c4cc 100644 --- a/polly/test/CodeGen/20100713.ll +++ b/polly/test/CodeGen/20100713.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" define void @fft_float(i32 %NumSamples) nounwind { diff --git a/polly/test/CodeGen/20100713_2.ll b/polly/test/CodeGen/20100713_2.ll index c146e00d4231..92f8959d91d6 100644 --- a/polly/test/CodeGen/20100713_2.ll +++ b/polly/test/CodeGen/20100713_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" define hidden void @luaD_callhook() nounwind { diff --git a/polly/test/CodeGen/20100717.ll b/polly/test/CodeGen/20100717.ll index 24114f2c70c6..a400eeaa3370 100644 --- a/polly/test/CodeGen/20100717.ll +++ b/polly/test/CodeGen/20100717.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-codegen -disable-output < %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-n8:16:32:64" define void @matrixTranspose(ptr %A) nounwind { diff --git a/polly/test/CodeGen/20100718-DomInfo-2.ll b/polly/test/CodeGen/20100718-DomInfo-2.ll index 396a1009a415..512b4c5c99af 100644 --- a/polly/test/CodeGen/20100718-DomInfo-2.ll +++ b/polly/test/CodeGen/20100718-DomInfo-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -verify-dom-info -disable-output < %s +; RUN: opt %loadPolly -polly-codegen -verify-dom-info -disable-output < %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-n8:16:32:64" define void @getNonAffNeighbour() nounwind { diff --git a/polly/test/CodeGen/20100718-DomInfo.ll b/polly/test/CodeGen/20100718-DomInfo.ll index 7a7f4300e107..e12334359c33 100644 --- a/polly/test/CodeGen/20100718-DomInfo.ll +++ b/polly/test/CodeGen/20100718-DomInfo.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -verify-dom-info -disable-output < %s +; RUN: opt %loadPolly -polly-codegen -verify-dom-info -disable-output < %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-n8:16:32:64" define void @intrapred_luma_16x16(i32 %predmode) nounwind { diff --git a/polly/test/CodeGen/20100720-MultipleConditions.ll b/polly/test/CodeGen/20100720-MultipleConditions.ll index ca3758d95681..9f2268713853 100644 --- a/polly/test/CodeGen/20100720-MultipleConditions.ll +++ b/polly/test/CodeGen/20100720-MultipleConditions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-ast -disable-output < %s ;int bar1(); ;int bar2(); diff --git a/polly/test/CodeGen/20100809-IndependentBlock.ll b/polly/test/CodeGen/20100809-IndependentBlock.ll index 849594afa871..8d596689d8ae 100644 --- a/polly/test/CodeGen/20100809-IndependentBlock.ll +++ b/polly/test/CodeGen/20100809-IndependentBlock.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-codegen -disable-output < %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-n8:16:32:64" define void @cfft2(ptr %x) nounwind { entry: diff --git a/polly/test/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll b/polly/test/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll index 313dad6fe3f7..261a205560b5 100644 --- a/polly/test/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll +++ b/polly/test/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-codegen -disable-output < %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-n8:16:32:64" diff --git a/polly/test/CodeGen/20101030-Overflow.ll b/polly/test/CodeGen/20101030-Overflow.ll index bf91272399d2..caaa4851f93e 100644 --- a/polly/test/CodeGen/20101030-Overflow.ll +++ b/polly/test/CodeGen/20101030-Overflow.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" define void @compdecomp() nounwind { diff --git a/polly/test/CodeGen/20101103-Overflow3.ll b/polly/test/CodeGen/20101103-Overflow3.ll index bab00231758f..b2faf14fba0b 100644 --- a/polly/test/CodeGen/20101103-Overflow3.ll +++ b/polly/test/CodeGen/20101103-Overflow3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" define void @Reflection_coefficients(ptr %r) nounwind { bb20: diff --git a/polly/test/CodeGen/20101103-signmissmatch.ll b/polly/test/CodeGen/20101103-signmissmatch.ll index d12ed4be4cdf..e157d292dc8a 100644 --- a/polly/test/CodeGen/20101103-signmissmatch.ll +++ b/polly/test/CodeGen/20101103-signmissmatch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" define void @CleanNet() nounwind { diff --git a/polly/test/CodeGen/20110226-Ignore-Dead-Code.ll b/polly/test/CodeGen/20110226-Ignore-Dead-Code.ll index 1c82d2aba887..c792d8c3d0bf 100644 --- a/polly/test/CodeGen/20110226-Ignore-Dead-Code.ll +++ b/polly/test/CodeGen/20110226-Ignore-Dead-Code.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" define void @main() nounwind { diff --git a/polly/test/CodeGen/20110226-PHI-Node-removed.ll b/polly/test/CodeGen/20110226-PHI-Node-removed.ll index d7003882a776..3458d75c47a0 100644 --- a/polly/test/CodeGen/20110226-PHI-Node-removed.ll +++ b/polly/test/CodeGen/20110226-PHI-Node-removed.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" diff --git a/polly/test/CodeGen/20120316-InvalidCast.ll b/polly/test/CodeGen/20120316-InvalidCast.ll index 14717dd29b23..8355cc51c468 100644 --- a/polly/test/CodeGen/20120316-InvalidCast.ll +++ b/polly/test/CodeGen/20120316-InvalidCast.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; CHECK: polly.start diff --git a/polly/test/CodeGen/20120403-RHS-type-mismatch.ll b/polly/test/CodeGen/20120403-RHS-type-mismatch.ll index 2d3e3b02dd38..1d629e388452 100644 --- a/polly/test/CodeGen/20120403-RHS-type-mismatch.ll +++ b/polly/test/CodeGen/20120403-RHS-type-mismatch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %s ; We just check that this compilation does not crash. diff --git a/polly/test/CodeGen/20130221.ll b/polly/test/CodeGen/20130221.ll index e5f63adabc25..45414671081a 100644 --- a/polly/test/CodeGen/20130221.ll +++ b/polly/test/CodeGen/20130221.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s +; RUN: opt %loadPolly -polly-codegen -S < %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-n8:16:32:64-S128" define void @list_sequence(ptr %A) { diff --git a/polly/test/CodeGen/20150328-SCEVExpanderIntroducesNewIV.ll b/polly/test/CodeGen/20150328-SCEVExpanderIntroducesNewIV.ll index 786adc7286e6..d54be5c3f35f 100644 --- a/polly/test/CodeGen/20150328-SCEVExpanderIntroducesNewIV.ll +++ b/polly/test/CodeGen/20150328-SCEVExpanderIntroducesNewIV.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/Intrinsics/llvm-expect.ll b/polly/test/CodeGen/Intrinsics/llvm-expect.ll index ac65f6f439ae..84057e276521 100644 --- a/polly/test/CodeGen/Intrinsics/llvm-expect.ll +++ b/polly/test/CodeGen/Intrinsics/llvm-expect.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; Check that we generate code without crashing. ; diff --git a/polly/test/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll b/polly/test/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll index fb02d7f55e23..b04319550938 100644 --- a/polly/test/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll +++ b/polly/test/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll @@ -1,6 +1,6 @@ ; This test checks that we do not accidently mutate the debug info when ; inserting loop parallel metadata. -; RUN: opt %loadPolly < %s -S -polly -passes=polly-codegen -polly-ast-detect-parallel | FileCheck %s +; RUN: opt %loadPolly < %s -S -polly -polly-codegen -polly-ast-detect-parallel | FileCheck %s ; CHECK-NOT: !7 = !{!7} target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll b/polly/test/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll index c6c27b4a75a8..7b131c5ebcbd 100644 --- a/polly/test/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll +++ b/polly/test/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-ast-detect-parallel -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-ast-detect-parallel -S < %s | FileCheck %s ; ; Check that we mark multiple parallel loops correctly including the memory instructions. ; diff --git a/polly/test/CodeGen/LoopParallelMD/single_loop_param_parallel.ll b/polly/test/CodeGen/LoopParallelMD/single_loop_param_parallel.ll index f91bd64a895a..ec927acb1ec7 100644 --- a/polly/test/CodeGen/LoopParallelMD/single_loop_param_parallel.ll +++ b/polly/test/CodeGen/LoopParallelMD/single_loop_param_parallel.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=SEQUENTIAL -; RUN: opt %loadPolly -passes=polly-codegen -polly-ast-detect-parallel -S < %s | FileCheck %s -check-prefix=PARALLEL +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=SEQUENTIAL +; RUN: opt %loadPolly -polly-codegen -polly-ast-detect-parallel -S < %s | FileCheck %s -check-prefix=PARALLEL 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-n8:16:32:64" ; This is a trivially parallel loop. We just use it to ensure that we actually diff --git a/polly/test/CodeGen/MemAccess/bad_alignment.ll b/polly/test/CodeGen/MemAccess/bad_alignment.ll index 2f297384ccdb..32f3cfe963b7 100644 --- a/polly/test/CodeGen/MemAccess/bad_alignment.ll +++ b/polly/test/CodeGen/MemAccess/bad_alignment.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -passes=polly-import-jscop -disable-output 2>&1 < %s | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -disable-output 2>&1 < %s | FileCheck %s ; ; Check that we do not allow to access elements not accessed before because the ; alignment information would become invalid. diff --git a/polly/test/CodeGen/MemAccess/codegen_address_space.ll b/polly/test/CodeGen/MemAccess/codegen_address_space.ll index 986775ed5717..7c9b12d64f9c 100644 --- a/polly/test/CodeGen/MemAccess/codegen_address_space.ll +++ b/polly/test/CodeGen/MemAccess/codegen_address_space.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed < %s -S | FileCheck %s +;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen < %s -S | FileCheck %s ;int A[100]; ; diff --git a/polly/test/CodeGen/MemAccess/codegen_constant_offset.ll b/polly/test/CodeGen/MemAccess/codegen_constant_offset.ll index b4168b89267b..e008a789fe7d 100644 --- a/polly/test/CodeGen/MemAccess/codegen_constant_offset.ll +++ b/polly/test/CodeGen/MemAccess/codegen_constant_offset.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed < %s -S | FileCheck %s +;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen < %s -S | FileCheck %s ;int A[100]; ; diff --git a/polly/test/CodeGen/MemAccess/codegen_simple.ll b/polly/test/CodeGen/MemAccess/codegen_simple.ll index cf2a57ad8a1f..5ba6f3269fb9 100644 --- a/polly/test/CodeGen/MemAccess/codegen_simple.ll +++ b/polly/test/CodeGen/MemAccess/codegen_simple.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed < %s -S | FileCheck %s +;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen < %s -S | FileCheck %s ;int A[100]; ; diff --git a/polly/test/CodeGen/MemAccess/codegen_simple_float.ll b/polly/test/CodeGen/MemAccess/codegen_simple_float.ll index bdd0e56b0a29..cf8913fc5197 100644 --- a/polly/test/CodeGen/MemAccess/codegen_simple_float.ll +++ b/polly/test/CodeGen/MemAccess/codegen_simple_float.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed < %s -S | FileCheck %s +;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen < %s -S | FileCheck %s ; ;float A[100]; ; diff --git a/polly/test/CodeGen/MemAccess/codegen_simple_md.ll b/polly/test/CodeGen/MemAccess/codegen_simple_md.ll index 8f676725146d..e4afcc8d2243 100644 --- a/polly/test/CodeGen/MemAccess/codegen_simple_md.ll +++ b/polly/test/CodeGen/MemAccess/codegen_simple_md.ll @@ -1,5 +1,5 @@ -;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed+withconst < %s -S | FileCheck -check-prefix=WITHCONST %s -;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed+withoutconst < %s -S | FileCheck -check-prefix=WITHOUTCONST %s +;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed+withconst -polly-codegen < %s -S | FileCheck -check-prefix=WITHCONST %s +;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed+withoutconst -polly-codegen < %s -S | FileCheck -check-prefix=WITHOUTCONST %s ;int A[1040]; ; diff --git a/polly/test/CodeGen/MemAccess/codegen_simple_md_float.ll b/polly/test/CodeGen/MemAccess/codegen_simple_md_float.ll index 1ac1efa2f727..c9913f3ed873 100644 --- a/polly/test/CodeGen/MemAccess/codegen_simple_md_float.ll +++ b/polly/test/CodeGen/MemAccess/codegen_simple_md_float.ll @@ -1,5 +1,5 @@ -;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed+withconst < %s -S | FileCheck -check-prefix=WITHCONST %s -;RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed+withoutconst < %s -S | FileCheck -check-prefix=WITHOUTCONST %s +;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed+withconst -polly-codegen < %s -S | FileCheck -check-prefix=WITHCONST %s +;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed+withoutconst -polly-codegen < %s -S | FileCheck -check-prefix=WITHOUTCONST %s ; ;float A[1040]; ; diff --git a/polly/test/CodeGen/MemAccess/different_types.ll b/polly/test/CodeGen/MemAccess/different_types.ll index 52fca9d87759..624de62911ff 100644 --- a/polly/test/CodeGen/MemAccess/different_types.ll +++ b/polly/test/CodeGen/MemAccess/different_types.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ +; RUN: opt %loadPolly -polly-import-jscop \ ; RUN: \ -; RUN: -S < %s | FileCheck %s +; RUN: -polly-codegen -S < %s | FileCheck %s ; ; void foo(float A[], float B[]) { ; for (long i = 0; i < 100; i++) diff --git a/polly/test/CodeGen/MemAccess/generate-all.ll b/polly/test/CodeGen/MemAccess/generate-all.ll index a64c6db0978c..6f92ba13587e 100644 --- a/polly/test/CodeGen/MemAccess/generate-all.ll +++ b/polly/test/CodeGen/MemAccess/generate-all.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-codegen-generate-expressions=false \ +; RUN: opt %loadPolly -polly-codegen -polly-codegen-generate-expressions=false \ ; RUN: -S < %s | FileCheck %s -check-prefix=SCEV -; RUN: opt %loadPolly -passes=polly-codegen -polly-codegen-generate-expressions=true \ +; RUN: opt %loadPolly -polly-codegen -polly-codegen-generate-expressions=true \ ; RUN: -S < %s | FileCheck %s -check-prefix=ASTEXPR ; ; void foo(float A[]) { diff --git a/polly/test/CodeGen/MemAccess/invariant_base_ptr.ll b/polly/test/CodeGen/MemAccess/invariant_base_ptr.ll index 12c38b7a66c4..a6d1de0aac63 100644 --- a/polly/test/CodeGen/MemAccess/invariant_base_ptr.ll +++ b/polly/test/CodeGen/MemAccess/invariant_base_ptr.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ -; RUN: -polly-invariant-load-hoisting -S \ +; RUN: opt %loadPolly -polly-import-jscop \ +; RUN: -polly-codegen -polly-invariant-load-hoisting -S \ ; RUN: 2>&1 < %s | FileCheck %s ; Setting new access functions where the base pointer of the array that is newly diff --git a/polly/test/CodeGen/MemAccess/multiple_types.ll b/polly/test/CodeGen/MemAccess/multiple_types.ll index 7c0ddffbd6d1..1793bd30fc5b 100644 --- a/polly/test/CodeGen/MemAccess/multiple_types.ll +++ b/polly/test/CodeGen/MemAccess/multiple_types.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,polly-codegen' \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop \ ; RUN: -polly-allow-differing-element-types \ -; RUN: -S < %s | FileCheck %s +; RUN: -polly-codegen -S < %s | FileCheck %s ; ; // Check that accessing one array with different types works. ; void multiple_types(char *Short, char *Float, char *Double) { diff --git a/polly/test/CodeGen/MemAccess/simple.ll b/polly/test/CodeGen/MemAccess/simple.ll index 8964e189b8a7..39e8a2c91b79 100644 --- a/polly/test/CodeGen/MemAccess/simple.ll +++ b/polly/test/CodeGen/MemAccess/simple.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -stats < %s 2>&1 | FileCheck %s +;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -stats < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ;int A[100]; diff --git a/polly/test/CodeGen/MemAccess/update_access_functions.ll b/polly/test/CodeGen/MemAccess/update_access_functions.ll index 00644c52ecd7..05d208708a36 100644 --- a/polly/test/CodeGen/MemAccess/update_access_functions.ll +++ b/polly/test/CodeGen/MemAccess/update_access_functions.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ -; RUN: -polly-import-jscop-postfix=transformed \ +; RUN: opt %loadPolly -polly-import-jscop \ +; RUN: -polly-import-jscop-postfix=transformed -polly-codegen \ ; RUN: < %s -S | FileCheck %s ; CHECK-LABEL: polly.stmt.loop1: diff --git a/polly/test/CodeGen/OpenMP/alias-metadata.ll b/polly/test/CodeGen/OpenMP/alias-metadata.ll index e7ca6abac283..07d79631b2cb 100644 --- a/polly/test/CodeGen/OpenMP/alias-metadata.ll +++ b/polly/test/CodeGen/OpenMP/alias-metadata.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-parallel -S < %s | FileCheck %s ; ; void foo(float *A, float *B) { ; for (long i = 0; i < 1000; i++) diff --git a/polly/test/CodeGen/OpenMP/floord-as-argument-to-subfunction.ll b/polly/test/CodeGen/OpenMP/floord-as-argument-to-subfunction.ll index 40ea62088940..eb9dfcd9e920 100644 --- a/polly/test/CodeGen/OpenMP/floord-as-argument-to-subfunction.ll +++ b/polly/test/CodeGen/OpenMP/floord-as-argument-to-subfunction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-opt-max-coefficient=-1 -polly-parallel -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-opt-isl -polly-opt-max-coefficient=-1 -polly-parallel -polly-codegen -S < %s | FileCheck %s ; ; Check that we do not crash but generate parallel code ; diff --git a/polly/test/CodeGen/OpenMP/inlineasm.ll b/polly/test/CodeGen/OpenMP/inlineasm.ll index a2ca2f79d649..69b1b0aa53f3 100644 --- a/polly/test/CodeGen/OpenMP/inlineasm.ll +++ b/polly/test/CodeGen/OpenMP/inlineasm.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-opt-isl,polly-codegen' -polly-parallel -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-opt-isl -polly-parallel -polly-codegen -S < %s | FileCheck %s ; llvm.org/PR51960 ; CHECK-LABEL: define internal void @foo_polly_subfn diff --git a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded.ll b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded.ll index 9394755254a7..30beef5b0709 100644 --- a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded.ll +++ b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ ; RUN: -polly-parallel-force -S < %s | FileCheck %s ; ; Test to verify that we hand down the preloaded A[0] to the OpenMP subfunction. diff --git a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_different_bb.ll b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_different_bb.ll index 48f075c37d82..fe5d2ab8c96d 100644 --- a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_different_bb.ll +++ b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_different_bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ ; RUN: -polly-parallel-force -S < %s | FileCheck %s ; ; Test to verify that we hand down the preloaded A[0] to the OpenMP subfunction. diff --git a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_pass_only_needed.ll b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_pass_only_needed.ll index e4273384dd72..49b9321c40b8 100644 --- a/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_pass_only_needed.ll +++ b/polly/test/CodeGen/OpenMP/invariant_base_pointer_preloaded_pass_only_needed.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ ; RUN: -polly-parallel-force -S < %s | FileCheck %s ; ; Test to verify that we hand down the preloaded A[0] to the OpenMP subfunction but diff --git a/polly/test/CodeGen/OpenMP/invariant_base_pointers_preloaded.ll b/polly/test/CodeGen/OpenMP/invariant_base_pointers_preloaded.ll index 8400a5594d10..06c4cdab45f1 100644 --- a/polly/test/CodeGen/OpenMP/invariant_base_pointers_preloaded.ll +++ b/polly/test/CodeGen/OpenMP/invariant_base_pointers_preloaded.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-parallel \ ; RUN: -polly-parallel-force -S < %s | FileCheck %s ; ; Test to verify that we hand down the preloaded A[0] to the OpenMP subfunction. diff --git a/polly/test/CodeGen/OpenMP/loop-body-references-outer-iv.ll b/polly/test/CodeGen/OpenMP/loop-body-references-outer-iv.ll index b3297b5b32af..db58c3ab7593 100644 --- a/polly/test/CodeGen/OpenMP/loop-body-references-outer-iv.ll +++ b/polly/test/CodeGen/OpenMP/loop-body-references-outer-iv.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; This code has failed the scev based code generation as the scev in the scop ; contains an AddRecExpr of an outer loop. When generating code, we did not diff --git a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-2.ll b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-2.ll index c478e91eb9db..c2ddc1e26496 100644 --- a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-2.ll +++ b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; AST: #pragma simd ; AST: #pragma omp parallel for diff --git a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-3.ll b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-3.ll index 26c2fe6da6ca..0f025bb94112 100644 --- a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-3.ll +++ b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values-3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-parallel -polly-parallel-force -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-parallel -polly-parallel-force -polly-invariant-load-hoisting=true -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -basic-aa -polly-parallel -polly-parallel-force -polly-invariant-load-hoisting=true -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -basic-aa -polly-parallel -polly-parallel-force -polly-invariant-load-hoisting=true -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; The interesting part of this test case is the instruction: ; %tmp = bitcast i8* %call to i64** diff --git a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values.ll b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values.ll index debd89ab151d..f9612d77533d 100644 --- a/polly/test/CodeGen/OpenMP/loop-body-references-outer-values.ll +++ b/polly/test/CodeGen/OpenMP/loop-body-references-outer-values.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S < %s | FileCheck %s -check-prefix=IR ; Make sure we correctly forward the reference to 'A' to the OpenMP subfunction. ; diff --git a/polly/test/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll b/polly/test/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll index db2299e5e73d..da9da18c89b2 100644 --- a/polly/test/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll +++ b/polly/test/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-codegen -S < %s | FileCheck %s -check-prefix=IR ; ; float A[100]; ; diff --git a/polly/test/CodeGen/OpenMP/mapped-phi-access.ll b/polly/test/CodeGen/OpenMP/mapped-phi-access.ll index 4b71760ea224..1b8433693abf 100644 --- a/polly/test/CodeGen/OpenMP/mapped-phi-access.ll +++ b/polly/test/CodeGen/OpenMP/mapped-phi-access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-parallel '-passes=polly-delicm,polly-codegen' -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-parallel -polly-delicm -polly-codegen -S < %s | FileCheck %s ; ; Verify that -polly-parallel can handle mapped scalar MemoryAccesses. ; diff --git a/polly/test/CodeGen/OpenMP/matmul-parallel.ll b/polly/test/CodeGen/OpenMP/matmul-parallel.ll index 1f3ad5ca8426..5ee9a7c7a824 100644 --- a/polly/test/CodeGen/OpenMP/matmul-parallel.ll +++ b/polly/test/CodeGen/OpenMP/matmul-parallel.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel '-passes=polly-opt-isl,print' -disable-output -debug-only=polly-ast < %s 2>&1 | FileCheck --check-prefix=AST %s -; RUN: opt %loadPolly -polly-parallel '-passes=polly-opt-isl,polly-codegen' -S < %s | FileCheck --check-prefix=CODEGEN %s +; RUN: opt %loadPolly -polly-parallel -polly-opt-isl -polly-ast -disable-output -debug-only=polly-ast < %s 2>&1 | FileCheck --check-prefix=AST %s +; RUN: opt %loadPolly -polly-parallel -polly-opt-isl -polly-codegen -S < %s | FileCheck --check-prefix=CODEGEN %s ; REQUIRES: asserts ; Parallelization of detected matrix-multiplication. diff --git a/polly/test/CodeGen/OpenMP/recomputed-srem.ll b/polly/test/CodeGen/OpenMP/recomputed-srem.ll index 3411308a4b11..cfae8e943cf1 100644 --- a/polly/test/CodeGen/OpenMP/recomputed-srem.ll +++ b/polly/test/CodeGen/OpenMP/recomputed-srem.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -passes=polly-codegen -polly-parallel \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-codegen -polly-parallel \ ; RUN: -polly-parallel-force -S < %s | FileCheck %s ; ; Test to verify that we pass %rem96 to the parallel subfunction. diff --git a/polly/test/CodeGen/OpenMP/reference-argument-from-non-affine-region.ll b/polly/test/CodeGen/OpenMP/reference-argument-from-non-affine-region.ll index 247e89be0027..f243c3a04949 100644 --- a/polly/test/CodeGen/OpenMP/reference-argument-from-non-affine-region.ll +++ b/polly/test/CodeGen/OpenMP/reference-argument-from-non-affine-region.ll @@ -1,15 +1,15 @@ ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -passes=polly-codegen \ +; RUN: -polly-parallel-force -polly-codegen \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=IR ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -passes=polly-codegen -polly-scheduling=runtime \ +; RUN: -polly-parallel-force -polly-codegen -polly-scheduling=runtime \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=IR ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM \ +; RUN: -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=LIBOMP-IR diff --git a/polly/test/CodeGen/OpenMP/reference-other-bb.ll b/polly/test/CodeGen/OpenMP/reference-other-bb.ll index 2c399f12af24..b7abdc23d258 100644 --- a/polly/test/CodeGen/OpenMP/reference-other-bb.ll +++ b/polly/test/CodeGen/OpenMP/reference-other-bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; IR: @foo_polly_subfn target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/OpenMP/reference-preceeding-loop.ll b/polly/test/CodeGen/OpenMP/reference-preceeding-loop.ll index 90a95dccbcb1..b88589f39a6f 100644 --- a/polly/test/CodeGen/OpenMP/reference-preceeding-loop.ll +++ b/polly/test/CodeGen/OpenMP/reference-preceeding-loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; - Test the case where scalar evolution references a loop that is outside diff --git a/polly/test/CodeGen/OpenMP/reference_latest.ll b/polly/test/CodeGen/OpenMP/reference_latest.ll index 696c3c74ad0e..54875c2630f0 100644 --- a/polly/test/CodeGen/OpenMP/reference_latest.ll +++ b/polly/test/CodeGen/OpenMP/reference_latest.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-delicm,polly-simplify,polly-codegen' -polly-parallel -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-delicm -polly-simplify -polly-parallel -polly-codegen -S < %s | FileCheck %s ; ; Test that parallel codegen handles scalars mapped to other arrays. ; After mapping "store double %add10" references the array "MemRef2". diff --git a/polly/test/CodeGen/OpenMP/scev-rewriting.ll b/polly/test/CodeGen/OpenMP/scev-rewriting.ll index 551946fc698b..1b229fc19d25 100644 --- a/polly/test/CodeGen/OpenMP/scev-rewriting.ll +++ b/polly/test/CodeGen/OpenMP/scev-rewriting.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly < %s -polly-vectorizer=stripmine -polly-parallel -polly-parallel-force -polly-process-unprofitable -passes=polly-codegen -S | FileCheck %s +; RUN: opt %loadPolly < %s -polly-vectorizer=stripmine -polly-parallel -polly-parallel-force -polly-process-unprofitable -polly-codegen -S | FileCheck %s ; CHECK: define internal void @DoStringSort_polly_subfn target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" target triple = "aarch64-unknown-linux-gnueabi" diff --git a/polly/test/CodeGen/OpenMP/single_loop.ll b/polly/test/CodeGen/OpenMP/single_loop.ll index 7e45ab08080e..f79653a08d21 100644 --- a/polly/test/CodeGen/OpenMP/single_loop.ll +++ b/polly/test/CodeGen/OpenMP/single_loop.ll @@ -1,14 +1,14 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=polly-import-jscop,print' -disable-output < %s | FileCheck %s -check-prefix=AST-STRIDE4 -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=polly-import-jscop,polly-codegen' -S < %s | FileCheck %s -check-prefix=IR-STRIDE4 +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-import-jscop -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST-STRIDE4 +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-import-jscop -polly-codegen -S < %s | FileCheck %s -check-prefix=IR-STRIDE4 -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM -polly-scheduling=static -polly-scheduling-chunksize=43 -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-STATIC-CHUNKED -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM -polly-scheduling=static -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-STATIC -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM -polly-scheduling=dynamic -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-DYNAMIC -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM -polly-scheduling=dynamic -polly-scheduling-chunksize=4 -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-DYNAMIC-FOUR -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=polly-import-jscop,polly-codegen' -polly-omp-backend=LLVM -S < %s | FileCheck %s -check-prefix=LIBOMP-IR-STRIDE4 +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM -polly-scheduling=static -polly-scheduling-chunksize=43 -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-STATIC-CHUNKED +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM -polly-scheduling=static -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-STATIC +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM -polly-scheduling=dynamic -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-DYNAMIC +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM -polly-scheduling=dynamic -polly-scheduling-chunksize=4 -S -verify-dom-info < %s | FileCheck %s -check-prefix=LIBOMP-IR-DYNAMIC-FOUR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-import-jscop -polly-codegen -polly-omp-backend=LLVM -S < %s | FileCheck %s -check-prefix=LIBOMP-IR-STRIDE4 ; This extensive test case tests the creation of the full set of OpenMP calls ; as well as the subfunction creation using a trivial loop as example. diff --git a/polly/test/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll b/polly/test/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll index 519cbbc496b1..50da5dd2b7c0 100644 --- a/polly/test/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll +++ b/polly/test/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=tbaa -polly-parallel -polly-parallel-force -polly-parallel-force -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -aa-pipeline=tbaa -polly-parallel -polly-parallel-force -polly-parallel-force -polly-invariant-load-hoisting=true -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -tbaa -polly-parallel -polly-parallel-force -polly-parallel-force -polly-invariant-load-hoisting=true -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -tbaa -polly-parallel -polly-parallel-force -polly-parallel-force -polly-invariant-load-hoisting=true -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; #define N 1024 ; float A[N]; diff --git a/polly/test/CodeGen/OpenMP/single_loop_with_param.ll b/polly/test/CodeGen/OpenMP/single_loop_with_param.ll index 0288d4c8f5e4..d01b7a2fdcad 100644 --- a/polly/test/CodeGen/OpenMP/single_loop_with_param.ll +++ b/polly/test/CodeGen/OpenMP/single_loop_with_param.ll @@ -1,15 +1,15 @@ ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -passes=polly-codegen \ +; RUN: -polly-parallel-force -polly-codegen \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=IR ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM \ +; RUN: -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=LIBOMP-IR ; RUN: opt %loadPolly -polly-parallel \ -; RUN: -polly-parallel-force -passes=polly-codegen -polly-omp-backend=LLVM \ +; RUN: -polly-parallel-force -polly-codegen -polly-omp-backend=LLVM \ ; RUN: -polly-scheduling=static \ ; RUN: -S -verify-dom-info < %s \ ; RUN: | FileCheck %s -check-prefix=LIBOMP-STATIC-IR diff --git a/polly/test/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll b/polly/test/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll index 133a00c3be71..05c6ed177e9c 100644 --- a/polly/test/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll +++ b/polly/test/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=AST -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=AST +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR ; This test case verifies that we create correct code even if two OpenMP loops ; share common outer variables. diff --git a/polly/test/CodeGen/PHIInExit.ll b/polly/test/CodeGen/PHIInExit.ll index 5617d873e529..eadd6054386b 100644 --- a/polly/test/CodeGen/PHIInExit.ll +++ b/polly/test/CodeGen/PHIInExit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %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-n8:16:32:64" %struct..0__pthread_mutex_s = type { i32, i32, i32, i32, i32, i32, %struct.__pthread_list_t } diff --git a/polly/test/CodeGen/RuntimeDebugBuilder/combine_different_values.ll b/polly/test/CodeGen/RuntimeDebugBuilder/combine_different_values.ll index c7f9186c3777..84827dd26049 100644 --- a/polly/test/CodeGen/RuntimeDebugBuilder/combine_different_values.ll +++ b/polly/test/CodeGen/RuntimeDebugBuilder/combine_different_values.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S \ +; RUN: opt %loadPolly -polly-codegen -S \ ; RUN: -polly-codegen-add-debug-printing \ ; RUN: -polly-ignore-aliasing < %s | FileCheck %s diff --git a/polly/test/CodeGen/RuntimeDebugBuilder/stmt_tracing.ll b/polly/test/CodeGen/RuntimeDebugBuilder/stmt_tracing.ll index 80fa3ee8d0f2..822eccc306ef 100644 --- a/polly/test/CodeGen/RuntimeDebugBuilder/stmt_tracing.ll +++ b/polly/test/CodeGen/RuntimeDebugBuilder/stmt_tracing.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-codegen-trace-stmts -polly-codegen-trace-scalars -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen-trace-stmts -polly-codegen-trace-scalars -polly-codegen -S < %s | FileCheck %s ; define void @func(i32 %n, ptr %A) { diff --git a/polly/test/CodeGen/alias-check-multi-dim.ll b/polly/test/CodeGen/alias-check-multi-dim.ll index 821e19290612..d923a4cc14fd 100644 --- a/polly/test/CodeGen/alias-check-multi-dim.ll +++ b/polly/test/CodeGen/alias-check-multi-dim.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen \ +; RUN: opt %loadPolly -polly-codegen \ ; RUN: -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/alias_metadata_too_many_arrays.ll b/polly/test/CodeGen/alias_metadata_too_many_arrays.ll index 9207f3015e3a..7c5ca012a378 100644 --- a/polly/test/CodeGen/alias_metadata_too_many_arrays.ll +++ b/polly/test/CodeGen/alias_metadata_too_many_arrays.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-ignore-aliasing -S < %s \ +; RUN: opt %loadPolly -polly-codegen -polly-ignore-aliasing -S < %s \ ; RUN: | FileCheck %s ; ; void manyarrays(float A1[], float A2[], float A3[], float A4[], float A5[], diff --git a/polly/test/CodeGen/aliasing_different_base_and_access_type.ll b/polly/test/CodeGen/aliasing_different_base_and_access_type.ll index d74f51702f36..a087414b8403 100644 --- a/polly/test/CodeGen/aliasing_different_base_and_access_type.ll +++ b/polly/test/CodeGen/aliasing_different_base_and_access_type.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; We have to cast %B to "short *" before we create RTCs. ; diff --git a/polly/test/CodeGen/aliasing_different_pointer_types.ll b/polly/test/CodeGen/aliasing_different_pointer_types.ll index 5ba1d1b587bf..91f5eab6b2a6 100644 --- a/polly/test/CodeGen/aliasing_different_pointer_types.ll +++ b/polly/test/CodeGen/aliasing_different_pointer_types.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; Check that we cast the different pointer types correctly before we compare ; them in the RTC's. We use i8* as max pointer type. diff --git a/polly/test/CodeGen/aliasing_multidimensional_access.ll b/polly/test/CodeGen/aliasing_multidimensional_access.ll index 338ab05e4ad3..48768399e850 100644 --- a/polly/test/CodeGen/aliasing_multidimensional_access.ll +++ b/polly/test/CodeGen/aliasing_multidimensional_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; Check that we calculate the maximal access into array A correctly and track the overflow state. ; diff --git a/polly/test/CodeGen/aliasing_parametric_simple_1.ll b/polly/test/CodeGen/aliasing_parametric_simple_1.ll index 281ecf488fd4..5422da4426e9 100644 --- a/polly/test/CodeGen/aliasing_parametric_simple_1.ll +++ b/polly/test/CodeGen/aliasing_parametric_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; void jd(int *A, int *B, int c) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/CodeGen/aliasing_parametric_simple_2.ll b/polly/test/CodeGen/aliasing_parametric_simple_2.ll index 9ac59f93febb..de945d403f92 100644 --- a/polly/test/CodeGen/aliasing_parametric_simple_2.ll +++ b/polly/test/CodeGen/aliasing_parametric_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; void jd(int *A, int *B, int c) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/CodeGen/aliasing_struct_element.ll b/polly/test/CodeGen/aliasing_struct_element.ll index 32b7c1ac905c..2219ca9d28bb 100644 --- a/polly/test/CodeGen/aliasing_struct_element.ll +++ b/polly/test/CodeGen/aliasing_struct_element.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; We should only access (or compute the address of) "the first element" of %S ; as it is a single struct not a struct array. The maximal access to S, thus diff --git a/polly/test/CodeGen/alignment.ll b/polly/test/CodeGen/alignment.ll index f3c786780f0a..a94b1f7e2883 100644 --- a/polly/test/CodeGen/alignment.ll +++ b/polly/test/CodeGen/alignment.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; Check that the special alignment information is kept ; diff --git a/polly/test/CodeGen/annotated_alias_scopes.ll b/polly/test/CodeGen/annotated_alias_scopes.ll index 1dd409edc9a5..f8d14cd34b62 100644 --- a/polly/test/CodeGen/annotated_alias_scopes.ll +++ b/polly/test/CodeGen/annotated_alias_scopes.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s --check-prefix=SCOPES +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=SCOPES ; ; Check that we create alias scopes that indicate the accesses to A, B and C cannot alias in any way. ; diff --git a/polly/test/CodeGen/blas_sscal_simplified.ll b/polly/test/CodeGen/blas_sscal_simplified.ll index b2072d3822a2..a370fcff46f8 100644 --- a/polly/test/CodeGen/blas_sscal_simplified.ll +++ b/polly/test/CodeGen/blas_sscal_simplified.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %s ; ; Regression test for a bug in the runtime check generation. diff --git a/polly/test/CodeGen/conflict-between-loop-invariant-code-hosting-and-escape-map-computation.ll b/polly/test/CodeGen/conflict-between-loop-invariant-code-hosting-and-escape-map-computation.ll index e977627ed7be..e0f8c435879a 100644 --- a/polly/test/CodeGen/conflict-between-loop-invariant-code-hosting-and-escape-map-computation.ll +++ b/polly/test/CodeGen/conflict-between-loop-invariant-code-hosting-and-escape-map-computation.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-process-unprofitable -polly-codegen -disable-output < %s ; ; CHECK: store i32 %tmp14_p_scalar_, ptr %tmp14.s2a ; CHECK: %tmp14.final_reload = load i32, ptr %tmp14.s2a diff --git a/polly/test/CodeGen/constant_condition.ll b/polly/test/CodeGen/constant_condition.ll index e259b5799763..dad1f6cffd17 100644 --- a/polly/test/CodeGen/constant_condition.ll +++ b/polly/test/CodeGen/constant_condition.ll @@ -1,4 +1,4 @@ -;RUN: opt %loadPolly '-passes=polly-prepare,scop(print)' -disable-output < %s 2>&1 | FileCheck %s +;RUN: opt %loadPolly -polly-prepare -polly-print-ast -disable-output < %s | FileCheck %s ;#include ;int A[1]; diff --git a/polly/test/CodeGen/create-conditional-scop.ll b/polly/test/CodeGen/create-conditional-scop.ll index 235726fdaf15..f51a2dcc9b3c 100644 --- a/polly/test/CodeGen/create-conditional-scop.ll +++ b/polly/test/CodeGen/create-conditional-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -verify-loop-info < %s -S | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-codegen -verify-loop-info < %s -S | FileCheck %s target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-a0:0-n32" diff --git a/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_1.ll b/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_1.ll index 220bdc179158..991e3c83eef1 100644 --- a/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_1.ll +++ b/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %s ; ; Check we do not crash even though the dead %tmp8 is referenced by a parameter ; and we do not pre-load it (as it is dead). diff --git a/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_2.ll b/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_2.ll index 4830de888237..153f6912cea5 100644 --- a/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_2.ll +++ b/polly/test/CodeGen/dead_invariant_load_instruction_referenced_by_parameter_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %s ; ; Check we do not crash even though there is a dead load that is referenced by ; a parameter and we do not pre-load it (as it is dead). diff --git a/polly/test/CodeGen/debug-intrinsics.ll b/polly/test/CodeGen/debug-intrinsics.ll index c98fae8e2e10..2feeb7c838b0 100644 --- a/polly/test/CodeGen/debug-intrinsics.ll +++ b/polly/test/CodeGen/debug-intrinsics.ll @@ -1,9 +1,9 @@ ; RUN: opt %loadPolly \ -; RUN: -polly-analyze-read-only-scalars=false -passes=polly-codegen -S < %s | \ +; RUN: -polly-analyze-read-only-scalars=false -polly-codegen -S < %s | \ ; RUN: FileCheck %s ; RUN: opt %loadPolly \ -; RUN: -polly-analyze-read-only-scalars=true -passes=polly-codegen -S < %s | \ +; RUN: -polly-analyze-read-only-scalars=true -polly-codegen -S < %s | \ ; RUN: FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/dominance_problem_after_early_codegen_bailout.ll b/polly/test/CodeGen/dominance_problem_after_early_codegen_bailout.ll index 2a3f3bd8a065..c9e006a01204 100644 --- a/polly/test/CodeGen/dominance_problem_after_early_codegen_bailout.ll +++ b/polly/test/CodeGen/dominance_problem_after_early_codegen_bailout.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-codegen -disable-output < %s ; ; This caused dominance problems at some point as we do bail out during ; code generation. Just verify it runs through. diff --git a/polly/test/CodeGen/empty_domain_in_context.ll b/polly/test/CodeGen/empty_domain_in_context.ll index b7a6b95171cb..c67ace9502e1 100644 --- a/polly/test/CodeGen/empty_domain_in_context.ll +++ b/polly/test/CodeGen/empty_domain_in_context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-optree,polly-opt-isl,polly-codegen' -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-optree -polly-opt-isl -polly-codegen -S < %s | FileCheck %s ; ; llvm.org/PR35362 ; isl codegen does not allow to generate isl_ast_expr from pw_aff which have an diff --git a/polly/test/CodeGen/entry_with_trivial_phi.ll b/polly/test/CodeGen/entry_with_trivial_phi.ll index 99d0776f3aa9..b057690ab29b 100644 --- a/polly/test/CodeGen/entry_with_trivial_phi.ll +++ b/polly/test/CodeGen/entry_with_trivial_phi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s +; RUN: opt %loadPolly -polly-codegen -S < %s ; ; The entry of this scop's simple region (entry.split => for.end) has an trivial ; PHI node. LCSSA may create such PHI nodes. This is a breakdown of this case in diff --git a/polly/test/CodeGen/entry_with_trivial_phi_other_bb.ll b/polly/test/CodeGen/entry_with_trivial_phi_other_bb.ll index ec3967b51049..5673cc746b5f 100644 --- a/polly/test/CodeGen/entry_with_trivial_phi_other_bb.ll +++ b/polly/test/CodeGen/entry_with_trivial_phi_other_bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; The entry of this scop's simple region (entry.split => for.end) has an trivial ; PHI node that is used in a different of the scop region. LCSSA may create such diff --git a/polly/test/CodeGen/error-stmt-in-non-affine-region.ll b/polly/test/CodeGen/error-stmt-in-non-affine-region.ll index ab85fbabd3f8..9832afe7a5fd 100644 --- a/polly/test/CodeGen/error-stmt-in-non-affine-region.ll +++ b/polly/test/CodeGen/error-stmt-in-non-affine-region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; XFAIL: * ; ; CHECK-LABEL: polly.stmt.if.then: diff --git a/polly/test/CodeGen/error_block_contains_invalid_memory_access.ll b/polly/test/CodeGen/error_block_contains_invalid_memory_access.ll index 6d1c3f74cc03..048847f3e322 100644 --- a/polly/test/CodeGen/error_block_contains_invalid_memory_access.ll +++ b/polly/test/CodeGen/error_block_contains_invalid_memory_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %s ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/exprModDiv.ll b/polly/test/CodeGen/exprModDiv.ll index 625e0e6464d7..936b018bc1ad 100644 --- a/polly/test/CodeGen/exprModDiv.ll +++ b/polly/test/CodeGen/exprModDiv.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ -; RUN: -S < %s | FileCheck %s -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ -; RUN: -polly-import-jscop-postfix=pow2 \ +; RUN: opt %loadPolly -polly-import-jscop \ +; RUN: -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop \ +; RUN: -polly-codegen -polly-import-jscop-postfix=pow2 \ ; RUN: -S < %s | FileCheck %s -check-prefix=POW2 ; ; void exprModDiv(float *A, float *B, float *C, long N, long p) { diff --git a/polly/test/CodeGen/hoisted_load_escapes_through_phi.ll b/polly/test/CodeGen/hoisted_load_escapes_through_phi.ll index ad7d84648a09..d7588b3b8e00 100644 --- a/polly/test/CodeGen/hoisted_load_escapes_through_phi.ll +++ b/polly/test/CodeGen/hoisted_load_escapes_through_phi.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen \ +; RUN: opt %loadPolly -S -polly-codegen \ ; RUN: -polly-invariant-load-hoisting=false < %s | FileCheck %s -; RUN: opt %loadPolly -S -passes=polly-codegen \ +; RUN: opt %loadPolly -S -polly-codegen \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; Check that we generate valid code even if the load of cont_STACKPOINTER is diff --git a/polly/test/CodeGen/hoisting_1.ll b/polly/test/CodeGen/hoisting_1.ll index e04ee68cc4c9..86b56637bc2c 100644 --- a/polly/test/CodeGen/hoisting_1.ll +++ b/polly/test/CodeGen/hoisting_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=tbaa -passes=polly-codegen -polly-allow-differing-element-types -disable-output %s +; RUN: opt %loadPolly -tbaa -polly-codegen -polly-allow-differing-element-types -disable-output %s ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/hoisting_2.ll b/polly/test/CodeGen/hoisting_2.ll index d5c27f58b95b..1f1be11c2d98 100644 --- a/polly/test/CodeGen/hoisting_2.ll +++ b/polly/test/CodeGen/hoisting_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=tbaa -passes=polly-codegen -polly-allow-differing-element-types -disable-output %s +; RUN: opt %loadPolly -tbaa -polly-codegen -polly-allow-differing-element-types -disable-output %s ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/inner_scev_sdiv_1.ll b/polly/test/CodeGen/inner_scev_sdiv_1.ll index 25f2abd9b63e..1a463fc178d1 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_1.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s +; RUN: opt %loadPolly -S -polly-codegen < %s ; ; Excerpt from the test-suite's oggenc reduced using bugpoint. ; diff --git a/polly/test/CodeGen/inner_scev_sdiv_2.ll b/polly/test/CodeGen/inner_scev_sdiv_2.ll index 4d80c2a170d6..76138034603e 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_2.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; The SCEV expression in this test case refers to a sequence of sdiv ; instructions, which are part of different bbs in the SCoP. When code diff --git a/polly/test/CodeGen/inner_scev_sdiv_3.ll b/polly/test/CodeGen/inner_scev_sdiv_3.ll index 8d13c8e168bf..874ead14ded2 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_3.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; This test case has a inner SCEV sdiv that will escape the SCoP. Just check we ; do not crash and generate valid code. diff --git a/polly/test/CodeGen/inner_scev_sdiv_in_lb.ll b/polly/test/CodeGen/inner_scev_sdiv_in_lb.ll index b53ee034f960..6514e18687e4 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_in_lb.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_in_lb.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN ; ; CHECK: [N] -> { Stmt_bb11[i0, i1] : i0 < N and i1 >= 0 and 3i1 <= -3 + i0 }; ; CODEGEN: polly diff --git a/polly/test/CodeGen/inner_scev_sdiv_in_lb_invariant.ll b/polly/test/CodeGen/inner_scev_sdiv_in_lb_invariant.ll index 3c392a2c4c4c..032942923379 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_in_lb_invariant.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_in_lb_invariant.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen \ +; RUN: opt %loadPolly -S -polly-codegen \ ; RUN: < %s | FileCheck %s ; ; Check that this will not crash our code generation. diff --git a/polly/test/CodeGen/inner_scev_sdiv_in_rtc.ll b/polly/test/CodeGen/inner_scev_sdiv_in_rtc.ll index 0748a274bb7d..f7292ca3073a 100644 --- a/polly/test/CodeGen/inner_scev_sdiv_in_rtc.ll +++ b/polly/test/CodeGen/inner_scev_sdiv_in_rtc.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen \ +; RUN: opt %loadPolly -polly-codegen \ ; RUN: -S < %s | FileCheck %s ; ; This will just check that we generate valid code here. diff --git a/polly/test/CodeGen/intrinsics_lifetime.ll b/polly/test/CodeGen/intrinsics_lifetime.ll index 5782b4724649..6141b3abdd8a 100644 --- a/polly/test/CodeGen/intrinsics_lifetime.ll +++ b/polly/test/CodeGen/intrinsics_lifetime.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-codegen -S < %s | FileCheck %s ; ; Verify that we remove the lifetime markers from everywhere. ; diff --git a/polly/test/CodeGen/intrinsics_misc.ll b/polly/test/CodeGen/intrinsics_misc.ll index 9b208b4e600b..c0a52fe97329 100644 --- a/polly/test/CodeGen/intrinsics_misc.ll +++ b/polly/test/CodeGen/intrinsics_misc.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-codegen -S < %s | FileCheck %s ; ; Verify that we remove the misc intrinsics from the optimized SCoP. ; diff --git a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-2.ll b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-2.ll index fd66cf0a47c9..6727247a7f04 100644 --- a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-2.ll +++ b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S \ +; RUN: opt %loadPolly -polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; This crashed our codegen at some point, verify it runs through diff --git a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-3.ll b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-3.ll index 408f0086a260..a573049c8f67 100644 --- a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-3.ll +++ b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order-3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S \ +; RUN: opt %loadPolly -polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; This crashed our codegen at some point, verify it runs through diff --git a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order.ll b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order.ll index 45bb5d041a49..e05ca9951434 100644 --- a/polly/test/CodeGen/inv-load-lnt-crash-wrong-order.ll +++ b/polly/test/CodeGen/inv-load-lnt-crash-wrong-order.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S \ +; RUN: opt %loadPolly -polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; This crashed our codegen at some point, verify it runs through diff --git a/polly/test/CodeGen/invariant-load-dimension.ll b/polly/test/CodeGen/invariant-load-dimension.ll index 07bd6923b54b..7793c3b3bee3 100644 --- a/polly/test/CodeGen/invariant-load-dimension.ll +++ b/polly/test/CodeGen/invariant-load-dimension.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -polly-invariant-load-hoisting '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=SCOPS -; RUN: opt %loadPolly -S < %s -passes=polly-codegen -polly-process-unprofitable -polly-invariant-load-hoisting | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-process-unprofitable -polly-invariant-load-hoisting -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=SCOPS +; RUN: opt %loadPolly -S < %s -polly-codegen -polly-process-unprofitable -polly-invariant-load-hoisting | FileCheck %s -check-prefix=CODEGEN target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n8:16:32-S64" diff --git a/polly/test/CodeGen/invariant-load-preload-base-pointer-origin-first.ll b/polly/test/CodeGen/invariant-load-preload-base-pointer-origin-first.ll index c4166dd4d2a9..474100995fd8 100644 --- a/polly/test/CodeGen/invariant-load-preload-base-pointer-origin-first.ll +++ b/polly/test/CodeGen/invariant-load-preload-base-pointer-origin-first.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen -polly-invariant-load-hoisting=true < %s +; RUN: opt %loadPolly -S -polly-codegen -polly-invariant-load-hoisting=true < %s ; ; Check that we generate valid code as we did non preload the base pointer ; origin of %tmp4 at some point. diff --git a/polly/test/CodeGen/invariant_cannot_handle_void.ll b/polly/test/CodeGen/invariant_cannot_handle_void.ll index 633955b6053a..de5d13d6a69a 100644 --- a/polly/test/CodeGen/invariant_cannot_handle_void.ll +++ b/polly/test/CodeGen/invariant_cannot_handle_void.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP -; RUN: opt %loadPolly -S -passes=polly-codegen -polly-invariant-load-hoisting=true %s | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -S -polly-codegen -polly-invariant-load-hoisting=true %s | FileCheck %s ; ; The offset of the %tmp1 load wrt. to %buff (62 bytes) is not divisible ; by the type size (i32 = 4 bytes), thus we will have to represent %buff diff --git a/polly/test/CodeGen/invariant_load.ll b/polly/test/CodeGen/invariant_load.ll index bef3862e9c79..be3f7a32f35b 100644 --- a/polly/test/CodeGen/invariant_load.ll +++ b/polly/test/CodeGen/invariant_load.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK-NEXT: %polly.access.B = getelementptr i32, ptr %B, i64 0 diff --git a/polly/test/CodeGen/invariant_load_address_space.ll b/polly/test/CodeGen/invariant_load_address_space.ll index 9ffef5757cb8..7c611ad3dd87 100644 --- a/polly/test/CodeGen/invariant_load_address_space.ll +++ b/polly/test/CodeGen/invariant_load_address_space.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK-NEXT: %polly.access.B = getelementptr i32, ptr addrspace(1) %B, i64 0 diff --git a/polly/test/CodeGen/invariant_load_alias_metadata.ll b/polly/test/CodeGen/invariant_load_alias_metadata.ll index a992a926880b..5a82d82d43f8 100644 --- a/polly/test/CodeGen/invariant_load_alias_metadata.ll +++ b/polly/test/CodeGen/invariant_load_alias_metadata.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true \ +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true \ ; RUN: -S < %s | FileCheck %s ; ; This test case checks whether Polly generates alias metadata in case of diff --git a/polly/test/CodeGen/invariant_load_base_pointer.ll b/polly/test/CodeGen/invariant_load_base_pointer.ll index c7d9e8df5b59..eb07f8317b79 100644 --- a/polly/test/CodeGen/invariant_load_base_pointer.ll +++ b/polly/test/CodeGen/invariant_load_base_pointer.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK-NEXT: %polly.access.BPLoc = getelementptr ptr, ptr %BPLoc, i64 0 diff --git a/polly/test/CodeGen/invariant_load_base_pointer_conditional.ll b/polly/test/CodeGen/invariant_load_base_pointer_conditional.ll index f24d8b7d7525..538077bb09e8 100644 --- a/polly/test/CodeGen/invariant_load_base_pointer_conditional.ll +++ b/polly/test/CodeGen/invariant_load_base_pointer_conditional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK-NEXT: %0 = sext i32 %N to i64 diff --git a/polly/test/CodeGen/invariant_load_base_pointer_conditional_2.ll b/polly/test/CodeGen/invariant_load_base_pointer_conditional_2.ll index 210060c90681..7c2fb3ef97ed 100644 --- a/polly/test/CodeGen/invariant_load_base_pointer_conditional_2.ll +++ b/polly/test/CodeGen/invariant_load_base_pointer_conditional_2.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -S -passes=polly-codegen -polly-invariant-load-hoisting=true < %s | FileCheck %s --check-prefix=IR -; RUN: opt %loadPolly -S -passes=polly-codegen -polly-invariant-load-hoisting=true --polly-overflow-tracking=always < %s | FileCheck %s --check-prefix=IRA +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen -polly-invariant-load-hoisting=true < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -S -polly-codegen -polly-invariant-load-hoisting=true --polly-overflow-tracking=always < %s | FileCheck %s --check-prefix=IRA ; ; As (p + q) can overflow we have to check that we load from ; I[p + q] only if it does not. diff --git a/polly/test/CodeGen/invariant_load_canonicalize_array_baseptrs.ll b/polly/test/CodeGen/invariant_load_canonicalize_array_baseptrs.ll index f6d4fef13d7a..dc5a4c890381 100644 --- a/polly/test/CodeGen/invariant_load_canonicalize_array_baseptrs.ll +++ b/polly/test/CodeGen/invariant_load_canonicalize_array_baseptrs.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s \ +; RUN: opt %loadPolly -polly-codegen -S < %s \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/CodeGen/invariant_load_condition.ll b/polly/test/CodeGen/invariant_load_condition.ll index 1aab3b8497fc..edf0814d8983 100644 --- a/polly/test/CodeGen/invariant_load_condition.ll +++ b/polly/test/CodeGen/invariant_load_condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK-NEXT: %polly.access.C = getelementptr i32, ptr %C, i64 0 diff --git a/polly/test/CodeGen/invariant_load_different_sized_types.ll b/polly/test/CodeGen/invariant_load_different_sized_types.ll index 952786d71cc9..5b91a1901061 100644 --- a/polly/test/CodeGen/invariant_load_different_sized_types.ll +++ b/polly/test/CodeGen/invariant_load_different_sized_types.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S \ +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S \ ; RUN: -polly-allow-differing-element-types < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/invariant_load_escaping.ll b/polly/test/CodeGen/invariant_load_escaping.ll index 31d2066745ef..efccdf468a18 100644 --- a/polly/test/CodeGen/invariant_load_escaping.ll +++ b/polly/test/CodeGen/invariant_load_escaping.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; int f(int *A, int *B) { ; // Possible aliasing between A and B but if not then *B would be diff --git a/polly/test/CodeGen/invariant_load_escaping_second_scop.ll b/polly/test/CodeGen/invariant_load_escaping_second_scop.ll index 5dbf261d84e5..c0ea888acdde 100644 --- a/polly/test/CodeGen/invariant_load_escaping_second_scop.ll +++ b/polly/test/CodeGen/invariant_load_escaping_second_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-process-unprofitable -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-process-unprofitable -S < %s | FileCheck %s ; ; void fence(void); ; diff --git a/polly/test/CodeGen/invariant_load_in_non_affine_subregion.ll b/polly/test/CodeGen/invariant_load_in_non_affine_subregion.ll index 57b4a655cc24..241252b5d549 100644 --- a/polly/test/CodeGen/invariant_load_in_non_affine_subregion.ll +++ b/polly/test/CodeGen/invariant_load_in_non_affine_subregion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; This crashed at some point as the invariant load is in a non-affine ; subregion. Just check it does not anymore. diff --git a/polly/test/CodeGen/invariant_load_loop_ub.ll b/polly/test/CodeGen/invariant_load_loop_ub.ll index a4b96fad0559..ab9aa0dc69a7 100644 --- a/polly/test/CodeGen/invariant_load_loop_ub.ll +++ b/polly/test/CodeGen/invariant_load_loop_ub.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-process-unprofitable -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-process-unprofitable -S < %s | FileCheck %s ; ; CHECK: polly.start ; diff --git a/polly/test/CodeGen/invariant_load_not_executed_but_in_parameters.ll b/polly/test/CodeGen/invariant_load_not_executed_but_in_parameters.ll index 2970dbb5bed9..08ff0871b610 100644 --- a/polly/test/CodeGen/invariant_load_not_executed_but_in_parameters.ll +++ b/polly/test/CodeGen/invariant_load_not_executed_but_in_parameters.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s ; ; Check that this does not crash as the invariant load is not executed (thus ; not preloaded) but still referenced by one of the parameters. diff --git a/polly/test/CodeGen/invariant_load_outermost.ll b/polly/test/CodeGen/invariant_load_outermost.ll index eda42f76ed5d..f42135c09014 100644 --- a/polly/test/CodeGen/invariant_load_outermost.ll +++ b/polly/test/CodeGen/invariant_load_outermost.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; CHECK: polly.start diff --git a/polly/test/CodeGen/invariant_load_parameters_cyclic_dependence.ll b/polly/test/CodeGen/invariant_load_parameters_cyclic_dependence.ll index 73fb038baed2..d365c99eff66 100644 --- a/polly/test/CodeGen/invariant_load_parameters_cyclic_dependence.ll +++ b/polly/test/CodeGen/invariant_load_parameters_cyclic_dependence.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; SCOP: Assumed Context: ; SCOP-NEXT: [p_0, tmp4] -> { : } diff --git a/polly/test/CodeGen/invariant_load_ptr_ptr_noalias.ll b/polly/test/CodeGen/invariant_load_ptr_ptr_noalias.ll index 82e957b9ef1d..b4d4c55f0d9b 100644 --- a/polly/test/CodeGen/invariant_load_ptr_ptr_noalias.ll +++ b/polly/test/CodeGen/invariant_load_ptr_ptr_noalias.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable -polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK: %polly.access.A = getelementptr ptr, ptr %A, i64 42 diff --git a/polly/test/CodeGen/invariant_load_scalar_dep.ll b/polly/test/CodeGen/invariant_load_scalar_dep.ll index 3906d5ab890f..05a40a4c47cc 100644 --- a/polly/test/CodeGen/invariant_load_scalar_dep.ll +++ b/polly/test/CodeGen/invariant_load_scalar_dep.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -S < %s | FileCheck %s ; ; CHECK-LABEL: polly.preload.begin: ; CHECK: %polly.access.B = getelementptr i32, ptr %B, i64 0 diff --git a/polly/test/CodeGen/invariant_load_scalar_escape_alloca_sharing.ll b/polly/test/CodeGen/invariant_load_scalar_escape_alloca_sharing.ll index 82e38e86bf77..44c035855b76 100644 --- a/polly/test/CodeGen/invariant_load_scalar_escape_alloca_sharing.ll +++ b/polly/test/CodeGen/invariant_load_scalar_escape_alloca_sharing.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s ; ; Verify the preloaded %tmp0 is stored and communicated in the same alloca. ; In this case, we do not reload %ncol.load from the scalar stack slot, but diff --git a/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_1.ll b/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_1.ll index ef382eb20d0f..0b6929a5fd3f 100644 --- a/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_1.ll +++ b/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true < %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true < %s ; ; Check we do not crash even though we pre-load values with different types ; from the same base pointer. diff --git a/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_2.ll b/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_2.ll index 07e7b97ed9de..2eb913fed447 100644 --- a/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_2.ll +++ b/polly/test/CodeGen/invariant_loads_from_struct_with_different_types_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true < %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true < %s ; ; Check we do not crash even though we pre-load values with different types ; from the same base pointer. diff --git a/polly/test/CodeGen/invariant_loads_ignore_parameter_bounds.ll b/polly/test/CodeGen/invariant_loads_ignore_parameter_bounds.ll index 8be087467e99..a0c1f891bdf6 100644 --- a/polly/test/CodeGen/invariant_loads_ignore_parameter_bounds.ll +++ b/polly/test/CodeGen/invariant_loads_ignore_parameter_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting \ +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting \ ; RUN: -polly-ignore-parameter-bounds -S < %s | FileCheck %s ; CHECK: polly.preload.begin: diff --git a/polly/test/CodeGen/invariant_verify_function_failed.ll b/polly/test/CodeGen/invariant_verify_function_failed.ll index 86308a7fbbfc..6020caeee85d 100644 --- a/polly/test/CodeGen/invariant_verify_function_failed.ll +++ b/polly/test/CodeGen/invariant_verify_function_failed.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,scop(polly-codegen)' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; This crashed at some point as the pointer returned by the call ; to @__errno_location is invariant and defined in the SCoP but not diff --git a/polly/test/CodeGen/invariant_verify_function_failed_2.ll b/polly/test/CodeGen/invariant_verify_function_failed_2.ll index 97faa6155f18..81a4bd1dc153 100644 --- a/polly/test/CodeGen/invariant_verify_function_failed_2.ll +++ b/polly/test/CodeGen/invariant_verify_function_failed_2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -S '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -check-prefix=SCOPS -; RUN: opt %loadPolly -S -passes=polly-codegen -polly-invariant-load-hoisting=true %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s -check-prefix=SCOPS +; RUN: opt %loadPolly -S -polly-codegen -polly-invariant-load-hoisting=true %s | FileCheck %s ; ; Check we generate valid code. diff --git a/polly/test/CodeGen/issue56692.ll b/polly/test/CodeGen/issue56692.ll index b5ab63c3b72b..e935e43bfa44 100644 --- a/polly/test/CodeGen/issue56692.ll +++ b/polly/test/CodeGen/issue56692.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-omp-backend=LLVM -polly-codegen-verify -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-omp-backend=LLVM -polly-codegen-verify -polly-codegen -S < %s | FileCheck %s ; https://github.com/llvm/llvm-project/issues/56692 ; ; CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_call({{.*}}), !dbg ![[OPTLOC:[0-9]+]] diff --git a/polly/test/CodeGen/large-numbers-in-boundary-context.ll b/polly/test/CodeGen/large-numbers-in-boundary-context.ll index 519511f1ddd5..a0328dfec651 100644 --- a/polly/test/CodeGen/large-numbers-in-boundary-context.ll +++ b/polly/test/CodeGen/large-numbers-in-boundary-context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; XFAIL: * ; ; The boundary context contains a constant that does not fit in 64 bits. Hence, diff --git a/polly/test/CodeGen/load_subset_with_context.ll b/polly/test/CodeGen/load_subset_with_context.ll index 980a06f23c73..ef0e051d5635 100644 --- a/polly/test/CodeGen/load_subset_with_context.ll +++ b/polly/test/CodeGen/load_subset_with_context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s ; ; A load must provide a value for every statement instance. ; Statement instances not in the SCoP's context are irrelevant. diff --git a/polly/test/CodeGen/loop-invariant-load-type-mismatch.ll b/polly/test/CodeGen/loop-invariant-load-type-mismatch.ll index ca3463d72af3..90c61c591623 100644 --- a/polly/test/CodeGen/loop-invariant-load-type-mismatch.ll +++ b/polly/test/CodeGen/loop-invariant-load-type-mismatch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/polly/test/CodeGen/loop_with_condition.ll b/polly/test/CodeGen/loop_with_condition.ll index 436d37d1261a..618a542c179a 100644 --- a/polly/test/CodeGen/loop_with_condition.ll +++ b/polly/test/CodeGen/loop_with_condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-ast -disable-output < %s | FileCheck %s ;#include ;#define N 1024 diff --git a/polly/test/CodeGen/loop_with_condition_2.ll b/polly/test/CodeGen/loop_with_condition_2.ll index 47ec693efbd5..b1a116785069 100644 --- a/polly/test/CodeGen/loop_with_condition_2.ll +++ b/polly/test/CodeGen/loop_with_condition_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; Verify that we actually detect this loop as the innermost loop even though ; there is a conditional inside. diff --git a/polly/test/CodeGen/loop_with_condition_ineq.ll b/polly/test/CodeGen/loop_with_condition_ineq.ll index 98866000b0cb..c35208c72dfe 100644 --- a/polly/test/CodeGen/loop_with_condition_ineq.ll +++ b/polly/test/CodeGen/loop_with_condition_ineq.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-ast -disable-output < %s | FileCheck %s ;#include ;#define N 1024 diff --git a/polly/test/CodeGen/loop_with_condition_nested.ll b/polly/test/CodeGen/loop_with_condition_nested.ll index d9a9dafd4b7e..24a49b47d9e6 100644 --- a/polly/test/CodeGen/loop_with_condition_nested.ll +++ b/polly/test/CodeGen/loop_with_condition_nested.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen < %s | opt -passes='print' -disable-output 2>&1 | FileCheck %s -check-prefix=LOOPS +; RUN: opt %loadPolly -basic-aa -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-codegen < %s | opt -passes='print' -disable-output 2>&1 | FileCheck %s -check-prefix=LOOPS ;#include diff --git a/polly/test/CodeGen/loop_with_conditional_entry_edge_split_hard_case.ll b/polly/test/CodeGen/loop_with_conditional_entry_edge_split_hard_case.ll index 3687868b0baf..4444cf1dc4dd 100644 --- a/polly/test/CodeGen/loop_with_conditional_entry_edge_split_hard_case.ll +++ b/polly/test/CodeGen/loop_with_conditional_entry_edge_split_hard_case.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; Test case to trigger the hard way of creating a unique entering ; edge for the SCoP. It is triggered because the entering edge diff --git a/polly/test/CodeGen/memcpy_annotations.ll b/polly/test/CodeGen/memcpy_annotations.ll index 42fe5ca92b94..a0a09b75c82e 100644 --- a/polly/test/CodeGen/memcpy_annotations.ll +++ b/polly/test/CodeGen/memcpy_annotations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; Verify that @llvm.memcpy does not get a !alias.scope annotation. ; @llvm.memcpy takes two pointers, it is ambiguous to which the diff --git a/polly/test/CodeGen/multidim-non-matching-typesize-2.ll b/polly/test/CodeGen/multidim-non-matching-typesize-2.ll index cfd52a0b7793..63afad6e2f41 100644 --- a/polly/test/CodeGen/multidim-non-matching-typesize-2.ll +++ b/polly/test/CodeGen/multidim-non-matching-typesize-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -disable-basic-aa -passes=polly-codegen \ +; RUN: opt %loadPolly -disable-basic-aa -polly-codegen \ ; RUN: -S < %s | FileCheck %s ; CHECK: polly target datalayout = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" diff --git a/polly/test/CodeGen/multidim-non-matching-typesize.ll b/polly/test/CodeGen/multidim-non-matching-typesize.ll index b3f70226f743..d117cefe3376 100644 --- a/polly/test/CodeGen/multidim-non-matching-typesize.ll +++ b/polly/test/CodeGen/multidim-non-matching-typesize.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -disable-basic-aa -passes=polly-codegen \ +; RUN: opt %loadPolly -disable-basic-aa -polly-codegen \ ; RUN: -S < %s | FileCheck %s target datalayout = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" diff --git a/polly/test/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll b/polly/test/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll index 11976874ed84..464ddb3740f7 100644 --- a/polly/test/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll +++ b/polly/test/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/CodeGen/multidim_alias_check.ll b/polly/test/CodeGen/multidim_alias_check.ll index 15390433a1b1..585577da0e6d 100644 --- a/polly/test/CodeGen/multidim_alias_check.ll +++ b/polly/test/CodeGen/multidim_alias_check.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-codegen < %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; CHECK: %polly.access.sext.A = sext i32 %n to i64 diff --git a/polly/test/CodeGen/multiple-codegens.ll b/polly/test/CodeGen/multiple-codegens.ll index 683ccdfa092b..f950fa4a3e1d 100644 --- a/polly/test/CodeGen/multiple-codegens.ll +++ b/polly/test/CodeGen/multiple-codegens.ll @@ -1,5 +1,6 @@ -; RUN: opt %loadPolly "-passes=scop(polly-opt-isl,polly-codegen,polly-codegen)" -S < %s | FileCheck %s -; RUN: opt %loadPolly "-passes=scop(polly-opt-isl,polly-codegen),scop(polly-codegen)" -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-scops -polly-opt-isl -polly-codegen -polly-scops -polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadNPMPolly "-passes=scop(polly-opt-isl,polly-codegen,polly-codegen)" -S < %s | FileCheck %s +; RUN: opt %loadNPMPolly "-passes=scop(polly-opt-isl,polly-codegen),scop(polly-codegen)" -S < %s | FileCheck %s ; ; llvm.org/PR34441 ; Properly handle multiple -polly-scops/-polly-codegen in the same diff --git a/polly/test/CodeGen/multiple-scops-in-a-row.ll b/polly/test/CodeGen/multiple-scops-in-a-row.ll index 0ac158c79129..a24a2e71ad4e 100644 --- a/polly/test/CodeGen/multiple-scops-in-a-row.ll +++ b/polly/test/CodeGen/multiple-scops-in-a-row.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; This test case has two scops in a row. When code generating the first scop, ; the second scop is invalidated. This test case verifies that we do not crash diff --git a/polly/test/CodeGen/multiple-types-invariant-load-2.ll b/polly/test/CodeGen/multiple-types-invariant-load-2.ll index 7916d32bd7de..0fd1df75e2ec 100644 --- a/polly/test/CodeGen/multiple-types-invariant-load-2.ll +++ b/polly/test/CodeGen/multiple-types-invariant-load-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S \ +; RUN: opt %loadPolly -polly-codegen -S \ ; RUN: -polly-allow-differing-element-types < %s | FileCheck %s ; CHECK: polly diff --git a/polly/test/CodeGen/multiple-types-invariant-load.ll b/polly/test/CodeGen/multiple-types-invariant-load.ll index 5ce698d4fb4d..b1434679e3d1 100644 --- a/polly/test/CodeGen/multiple-types-invariant-load.ll +++ b/polly/test/CodeGen/multiple-types-invariant-load.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-differing-element-types -passes=polly-codegen -S \ +; RUN: opt %loadPolly -polly-allow-differing-element-types -polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; CHECK: %polly.access.global.load = getelementptr i32, ptr %global.load, i64 0 diff --git a/polly/test/CodeGen/multiple_sai_fro_same_base_address.ll b/polly/test/CodeGen/multiple_sai_fro_same_base_address.ll index 94c208e6692f..0163f248229e 100644 --- a/polly/test/CodeGen/multiple_sai_fro_same_base_address.ll +++ b/polly/test/CodeGen/multiple_sai_fro_same_base_address.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-position=before-vectorizer '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP -; RUN: opt %loadPolly -polly-position=before-vectorizer -passes=polly-codegen -S < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -polly-position=before-vectorizer -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -polly-position=before-vectorizer -polly-codegen -S < %s | FileCheck %s --check-prefix=IR ; The IR has two ScopArrayInfo for the value %next.0. This used to produce two ; phi nodes in polly.merge_new_and_old, one illegaly using the result of the diff --git a/polly/test/CodeGen/no-overflow-tracking.ll b/polly/test/CodeGen/no-overflow-tracking.ll index ff4a8023dead..f11e8927ddee 100644 --- a/polly/test/CodeGen/no-overflow-tracking.ll +++ b/polly/test/CodeGen/no-overflow-tracking.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-overflow-tracking=never -passes=polly-codegen -S < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-overflow-tracking=never -polly-codegen -S < %s | FileCheck %s --check-prefix=IR ; ; As (p + q) can overflow we have to check that we load from ; I[p + q] only if it does not. diff --git a/polly/test/CodeGen/no_guard_bb.ll b/polly/test/CodeGen/no_guard_bb.ll index 6635048e0f9b..47c87ff7c868 100644 --- a/polly/test/CodeGen/no_guard_bb.ll +++ b/polly/test/CodeGen/no_guard_bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S -verify-dom-info < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S -verify-dom-info < %s | FileCheck %s ; ; CHECK-NOT: br i1 true, label %polly.{{.*}}, label %polly.{{.*}} ; diff --git a/polly/test/CodeGen/non-affine-dominance-generated-entering.ll b/polly/test/CodeGen/non-affine-dominance-generated-entering.ll index d1d2fc644010..ebf36acc8d96 100644 --- a/polly/test/CodeGen/non-affine-dominance-generated-entering.ll +++ b/polly/test/CodeGen/non-affine-dominance-generated-entering.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; llvm.org/PR25439 ; Scalar reloads in the generated entering block were not recognized as diff --git a/polly/test/CodeGen/non-affine-exit-node-dominance.ll b/polly/test/CodeGen/non-affine-exit-node-dominance.ll index 8039f3b08543..af19d2420e3e 100644 --- a/polly/test/CodeGen/non-affine-exit-node-dominance.ll +++ b/polly/test/CodeGen/non-affine-exit-node-dominance.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; llvm.org/PR25439 ; The dominance of the generated non-affine subregion block was based on the diff --git a/polly/test/CodeGen/non-affine-phi-node-expansion-2.ll b/polly/test/CodeGen/non-affine-phi-node-expansion-2.ll index 5b6c2ecc81c8..2aca316d4c88 100644 --- a/polly/test/CodeGen/non-affine-phi-node-expansion-2.ll +++ b/polly/test/CodeGen/non-affine-phi-node-expansion-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen \ +; RUN: opt %loadPolly -polly-codegen \ ; RUN: -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/non-affine-phi-node-expansion-3.ll b/polly/test/CodeGen/non-affine-phi-node-expansion-3.ll index 9a4e1fa26a9f..18a4b6e4ed4a 100644 --- a/polly/test/CodeGen/non-affine-phi-node-expansion-3.ll +++ b/polly/test/CodeGen/non-affine-phi-node-expansion-3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen \ +; RUN: opt %loadPolly -polly-codegen \ ; RUN: -S < %s | FileCheck %s define void @foo(ptr %A, i1 %cond0, i1 %cond1) { diff --git a/polly/test/CodeGen/non-affine-phi-node-expansion-4.ll b/polly/test/CodeGen/non-affine-phi-node-expansion-4.ll index b5380b5d225c..8a07ee7c7424 100644 --- a/polly/test/CodeGen/non-affine-phi-node-expansion-4.ll +++ b/polly/test/CodeGen/non-affine-phi-node-expansion-4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen \ +; RUN: opt %loadPolly -polly-codegen \ ; RUN: -S < %s | FileCheck %s define void @foo(ptr %A, i1 %cond0, i1 %cond1) { diff --git a/polly/test/CodeGen/non-affine-phi-node-expansion.ll b/polly/test/CodeGen/non-affine-phi-node-expansion.ll index 7c29868675f4..091fc3e323dc 100644 --- a/polly/test/CodeGen/non-affine-phi-node-expansion.ll +++ b/polly/test/CodeGen/non-affine-phi-node-expansion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen \ +; RUN: opt %loadPolly -polly-codegen \ ; RUN: -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize-2.ll b/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize-2.ll index f5c446a22c02..6a1d1f12ba9c 100644 --- a/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize-2.ll +++ b/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; This caused the code generation to generate invalid code as the same operand ; of the PHI node in the non-affine region was synthesized at the wrong place. diff --git a/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize.ll b/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize.ll index fc894775b755..036bf34cb7f7 100644 --- a/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize.ll +++ b/polly/test/CodeGen/non-affine-region-exit-phi-incoming-synthesize.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; This caused the code generation to generate invalid code as the same BBMap was ; used for the whole non-affine region. When %add is synthesized for the diff --git a/polly/test/CodeGen/non-affine-region-implicit-store.ll b/polly/test/CodeGen/non-affine-region-implicit-store.ll index 6f2c7005d1bb..e89197e24852 100644 --- a/polly/test/CodeGen/non-affine-region-implicit-store.ll +++ b/polly/test/CodeGen/non-affine-region-implicit-store.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; llvm.org/PR25438 ; After loop versioning, a dominance check of a non-affine subregion's exit node diff --git a/polly/test/CodeGen/non-affine-region-phi-references-in-scop-value.ll b/polly/test/CodeGen/non-affine-region-phi-references-in-scop-value.ll index 6151562555ee..f6e4eb57319d 100644 --- a/polly/test/CodeGen/non-affine-region-phi-references-in-scop-value.ll +++ b/polly/test/CodeGen/non-affine-region-phi-references-in-scop-value.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-allow-nonaffine-loops \ +; RUN: opt %loadPolly -polly-codegen -polly-allow-nonaffine-loops \ ; RUN: -S < %s | FileCheck %s ; This test verifies that values defined in another scop statement and used by diff --git a/polly/test/CodeGen/non-affine-subregion-dominance-reuse.ll b/polly/test/CodeGen/non-affine-subregion-dominance-reuse.ll index c2af74c215f9..6c749a404336 100644 --- a/polly/test/CodeGen/non-affine-subregion-dominance-reuse.ll +++ b/polly/test/CodeGen/non-affine-subregion-dominance-reuse.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S -verify-dom-info \ +; RUN: opt %loadPolly -polly-codegen -S -verify-dom-info \ ; RUN: < %s | FileCheck %s ; ; Check that we do not reuse the B[i-1] GEP created in block S again in diff --git a/polly/test/CodeGen/non-affine-switch.ll b/polly/test/CodeGen/non-affine-switch.ll index c829b682fb24..9c08b98700ae 100644 --- a/polly/test/CodeGen/non-affine-switch.ll +++ b/polly/test/CodeGen/non-affine-switch.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly \ -; RUN: -S -passes=polly-codegen < %s | FileCheck %s +; RUN: -S -polly-codegen < %s | FileCheck %s ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/CodeGen/non-affine-synthesized-in-branch.ll b/polly/test/CodeGen/non-affine-synthesized-in-branch.ll index a0febb348434..cc0e60abcd09 100644 --- a/polly/test/CodeGen/non-affine-synthesized-in-branch.ll +++ b/polly/test/CodeGen/non-affine-synthesized-in-branch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable -polly-codegen -S < %s | FileCheck %s ; ; llvm.org/PR25412 ; %synthgep caused %gep to be synthesized in subregion_if which was reused for diff --git a/polly/test/CodeGen/non-affine-update.ll b/polly/test/CodeGen/non-affine-update.ll index aacbb9e766c4..d2b7fae75b23 100644 --- a/polly/test/CodeGen/non-affine-update.ll +++ b/polly/test/CodeGen/non-affine-update.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ -; RUN: -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop \ +; RUN: -polly-codegen -S < %s | FileCheck %s ; ; void non-affine-update(double A[], double C[], double B[]) { ; for (int i = 0; i < 10; i++) { diff --git a/polly/test/CodeGen/non-hoisted-load-needed-as-base-ptr.ll b/polly/test/CodeGen/non-hoisted-load-needed-as-base-ptr.ll index 0c7c5f9a1700..5f6642b0630d 100644 --- a/polly/test/CodeGen/non-hoisted-load-needed-as-base-ptr.ll +++ b/polly/test/CodeGen/non-hoisted-load-needed-as-base-ptr.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=tbaa -passes=polly-codegen -disable-output %s +; RUN: opt %loadPolly -tbaa -polly-codegen -disable-output %s ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/non_affine_float_compare.ll b/polly/test/CodeGen/non_affine_float_compare.ll index 0b4813ac11ae..be310b5bf5ca 100644 --- a/polly/test/CodeGen/non_affine_float_compare.ll +++ b/polly/test/CodeGen/non_affine_float_compare.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen \ +; RUN: opt %loadPolly -polly-codegen \ ; RUN: -polly-allow-nonaffine-branches -S -verify-dom-info \ ; RUN: < %s | FileCheck %s ; diff --git a/polly/test/CodeGen/only_non_affine_error_region.ll b/polly/test/CodeGen/only_non_affine_error_region.ll index 472aec927dcd..b2ad1c1fe3fd 100644 --- a/polly/test/CodeGen/only_non_affine_error_region.ll +++ b/polly/test/CodeGen/only_non_affine_error_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; CHECK-NOT: polly.start ; diff --git a/polly/test/CodeGen/openmp_limit_threads.ll b/polly/test/CodeGen/openmp_limit_threads.ll index 70f78ebac173..e8eb819f13d9 100644 --- a/polly/test/CodeGen/openmp_limit_threads.ll +++ b/polly/test/CodeGen/openmp_limit_threads.ll @@ -1,10 +1,10 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -S < %s | FileCheck %s --check-prefix=AUTO -; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -polly-num-threads=1 -S < %s | FileCheck %s --check-prefix=ONE -; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -polly-num-threads=4 -S < %s | FileCheck %s --check-prefix=FOUR +; RUN: opt %loadPolly -polly-codegen -polly-parallel -S < %s | FileCheck %s --check-prefix=AUTO +; RUN: opt %loadPolly -polly-codegen -polly-parallel -polly-num-threads=1 -S < %s | FileCheck %s --check-prefix=ONE +; RUN: opt %loadPolly -polly-codegen -polly-parallel -polly-num-threads=4 -S < %s | FileCheck %s --check-prefix=FOUR -; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -polly-omp-backend=LLVM -S < %s | FileCheck %s --check-prefix=LIBOMP-AUTO -; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -polly-omp-backend=LLVM -polly-num-threads=1 -S < %s | FileCheck %s --check-prefix=LIBOMP-ONE -; RUN: opt %loadPolly -passes=polly-codegen -polly-parallel -polly-omp-backend=LLVM -polly-num-threads=4 -S < %s | FileCheck %s --check-prefix=LIBOMP-FOUR +; RUN: opt %loadPolly -polly-codegen -polly-parallel -polly-omp-backend=LLVM -S < %s | FileCheck %s --check-prefix=LIBOMP-AUTO +; RUN: opt %loadPolly -polly-codegen -polly-parallel -polly-omp-backend=LLVM -polly-num-threads=1 -S < %s | FileCheck %s --check-prefix=LIBOMP-ONE +; RUN: opt %loadPolly -polly-codegen -polly-parallel -polly-omp-backend=LLVM -polly-num-threads=4 -S < %s | FileCheck %s --check-prefix=LIBOMP-FOUR ; Ensure that the provided thread numbers are forwarded to the OpenMP calls. ; diff --git a/polly/test/CodeGen/out-of-scop-phi-node-use.ll b/polly/test/CodeGen/out-of-scop-phi-node-use.ll index 9ef0586d7077..54e909ecf378 100644 --- a/polly/test/CodeGen/out-of-scop-phi-node-use.ll +++ b/polly/test/CodeGen/out-of-scop-phi-node-use.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/polly/test/CodeGen/param_div_div_div_2.ll b/polly/test/CodeGen/param_div_div_div_2.ll index 027c147b173e..764ca241f166 100644 --- a/polly/test/CodeGen/param_div_div_div_2.ll +++ b/polly/test/CodeGen/param_div_div_div_2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=IR ; ; Check that we guard the divisions because we moved them and thereby increased ; their domain. diff --git a/polly/test/CodeGen/partial_write_array.ll b/polly/test/CodeGen/partial_write_array.ll index 82277d631e4c..6dc5550d82af 100644 --- a/polly/test/CodeGen/partial_write_array.ll +++ b/polly/test/CodeGen/partial_write_array.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s ; ; Partial write of an array access. ; diff --git a/polly/test/CodeGen/partial_write_emptyset.ll b/polly/test/CodeGen/partial_write_emptyset.ll index 687599025e09..a25195f11ed7 100644 --- a/polly/test/CodeGen/partial_write_emptyset.ll +++ b/polly/test/CodeGen/partial_write_emptyset.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s ; ; Partial write, where "partial" is the empty set. ; The store is never executed in this case and we do generate it in the diff --git a/polly/test/CodeGen/partial_write_full_write_that_appears_partial.ll b/polly/test/CodeGen/partial_write_full_write_that_appears_partial.ll index 261d6fe7a0c5..18a809b30557 100644 --- a/polly/test/CodeGen/partial_write_full_write_that_appears_partial.ll +++ b/polly/test/CodeGen/partial_write_full_write_that_appears_partial.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; CHECK: polly.stmt.if.then81: ; preds = %polly.stmt.if.end75 ; CHECK-NEXT: store float undef, ptr %fX64, align 4, !alias.scope !0, !noalias !3 diff --git a/polly/test/CodeGen/partial_write_impossible_restriction.ll b/polly/test/CodeGen/partial_write_impossible_restriction.ll index d041edb9262e..178227fef8e5 100644 --- a/polly/test/CodeGen/partial_write_impossible_restriction.ll +++ b/polly/test/CodeGen/partial_write_impossible_restriction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s ; ; The isl scheduler isolates %cond.false into two instances. ; A partial write access in one of the instances was never executed, diff --git a/polly/test/CodeGen/partial_write_in_region.ll b/polly/test/CodeGen/partial_write_in_region.ll index be5025778096..d8f57b35d585 100644 --- a/polly/test/CodeGen/partial_write_in_region.ll +++ b/polly/test/CodeGen/partial_write_in_region.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ -; RUN: -polly-import-jscop-postfix=transformed \ +; RUN: opt %loadPolly -polly-import-jscop \ +; RUN: -polly-import-jscop-postfix=transformed -polly-codegen \ ; RUN: -verify-dom-info \ ; RUN: -S < %s | FileCheck %s ; diff --git a/polly/test/CodeGen/partial_write_in_region_with_loop.ll b/polly/test/CodeGen/partial_write_in_region_with_loop.ll index 8379a5f279ed..48a9dbef21d1 100644 --- a/polly/test/CodeGen/partial_write_in_region_with_loop.ll +++ b/polly/test/CodeGen/partial_write_in_region_with_loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' \ -; RUN: -polly-import-jscop-postfix=transformed \ +; RUN: opt %loadPolly -polly-import-jscop \ +; RUN: -polly-import-jscop-postfix=transformed -polly-codegen \ ; RUN: -verify-dom-info -polly-allow-nonaffine-loops \ ; RUN: -S < %s | FileCheck %s diff --git a/polly/test/CodeGen/partial_write_mapped_scalar.ll b/polly/test/CodeGen/partial_write_mapped_scalar.ll index b74705250be5..9137ef2123c8 100644 --- a/polly/test/CodeGen/partial_write_mapped_scalar.ll +++ b/polly/test/CodeGen/partial_write_mapped_scalar.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s ; ; Partial write of a (mapped) scalar. ; diff --git a/polly/test/CodeGen/partial_write_mapped_scalar_subregion.ll b/polly/test/CodeGen/partial_write_mapped_scalar_subregion.ll index 80a97e1aa657..e054b65eadf3 100644 --- a/polly/test/CodeGen/partial_write_mapped_scalar_subregion.ll +++ b/polly/test/CodeGen/partial_write_mapped_scalar_subregion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s ; ; Partial write of a (mapped) scalar in a non-affine subregion. ; diff --git a/polly/test/CodeGen/perf_monitoring.ll b/polly/test/CodeGen/perf_monitoring.ll index dde7853b37fd..2abbf24f5e78 100644 --- a/polly/test/CodeGen/perf_monitoring.ll +++ b/polly/test/CodeGen/perf_monitoring.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-codegen-perf-monitoring \ +; RUN: opt %loadPolly -polly-codegen -polly-codegen-perf-monitoring \ ; RUN: -S < %s | FileCheck %s ; void f(long A[], long N) { diff --git a/polly/test/CodeGen/perf_monitoring_cycles_per_scop.ll b/polly/test/CodeGen/perf_monitoring_cycles_per_scop.ll index d9efed5f8efa..11d63fc47658 100644 --- a/polly/test/CodeGen/perf_monitoring_cycles_per_scop.ll +++ b/polly/test/CodeGen/perf_monitoring_cycles_per_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-codegen-perf-monitoring \ +; RUN: opt %loadPolly -polly-codegen -polly-codegen-perf-monitoring \ ; RUN: -S < %s | FileCheck %s ; void f(long A[], long N) { diff --git a/polly/test/CodeGen/perf_monitoring_trip_counts_per_scop.ll b/polly/test/CodeGen/perf_monitoring_trip_counts_per_scop.ll index 560b44561bf5..9b7f324df8e4 100644 --- a/polly/test/CodeGen/perf_monitoring_trip_counts_per_scop.ll +++ b/polly/test/CodeGen/perf_monitoring_trip_counts_per_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-codegen-perf-monitoring \ +; RUN: opt %loadPolly -polly-codegen -polly-codegen-perf-monitoring \ ; RUN: -S < %s | FileCheck %s ; void f(long A[], long N) { diff --git a/polly/test/CodeGen/phi-defined-before-scop.ll b/polly/test/CodeGen/phi-defined-before-scop.ll index 1e6266673a8c..a3b1ba264f04 100644 --- a/polly/test/CodeGen/phi-defined-before-scop.ll +++ b/polly/test/CodeGen/phi-defined-before-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; CHECK-LABEL: polly.merge_new_and_old: ; CHECK-NEXT: %tmp7.ph.merge = phi ptr [ %tmp7.ph.final_reload, %polly.exiting ], [ %tmp7.ph, %bb6.region_exiting ] diff --git a/polly/test/CodeGen/phi_after_error_block_outside_of_scop.ll b/polly/test/CodeGen/phi_after_error_block_outside_of_scop.ll index 0121888f9fa9..c34ebfc3ca02 100644 --- a/polly/test/CodeGen/phi_after_error_block_outside_of_scop.ll +++ b/polly/test/CodeGen/phi_after_error_block_outside_of_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; Make sure code generation does not break in case an 'error block' is detected ; outside of the scope. In this situation, we should not affect code generation. diff --git a/polly/test/CodeGen/phi_condition_modeling_1.ll b/polly/test/CodeGen/phi_condition_modeling_1.ll index cf464fe234e3..b14d32921cf7 100644 --- a/polly/test/CodeGen/phi_condition_modeling_1.ll +++ b/polly/test/CodeGen/phi_condition_modeling_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; void f(int *A, int c, int N) { ; int tmp; diff --git a/polly/test/CodeGen/phi_condition_modeling_2.ll b/polly/test/CodeGen/phi_condition_modeling_2.ll index 25c67e625542..dab2977bf065 100644 --- a/polly/test/CodeGen/phi_condition_modeling_2.ll +++ b/polly/test/CodeGen/phi_condition_modeling_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; void f(int *A, int c, int N) { ; int tmp; diff --git a/polly/test/CodeGen/phi_conditional_simple_1.ll b/polly/test/CodeGen/phi_conditional_simple_1.ll index 3d0e35ccd353..f1b93b540f70 100644 --- a/polly/test/CodeGen/phi_conditional_simple_1.ll +++ b/polly/test/CodeGen/phi_conditional_simple_1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=AST -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; void jd(int *A, int c) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_1.ll b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_1.ll index 70af1d96f4e7..13688480e315 100644 --- a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_1.ll +++ b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; This caused an lnt crash at some point, just verify it will run through. ; diff --git a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_2.ll b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_2.ll index f17d4a6b9160..01dd450590d9 100644 --- a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_2.ll +++ b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; This caused an lnt crash at some point, just verify it will run through and ; produce the PHI node in the exit we are looking for. diff --git a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_3.ll b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_3.ll index cf9b4050a39c..66b95b0e0317 100644 --- a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_3.ll +++ b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; This caused an lnt crash at some point, just verify it will run through and ; produce the PHI node in the exit we are looking for. diff --git a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_5.ll b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_5.ll index dfc3e6757af8..9a046367e768 100644 --- a/polly/test/CodeGen/phi_in_exit_early_lnt_failure_5.ll +++ b/polly/test/CodeGen/phi_in_exit_early_lnt_failure_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; This caused an lnt crash at some point, just verify it will run through and ; produce the PHI node in the exit we are looking for. diff --git a/polly/test/CodeGen/phi_loop_carried_float.ll b/polly/test/CodeGen/phi_loop_carried_float.ll index df51c3599b29..ca1870fb3a09 100644 --- a/polly/test/CodeGen/phi_loop_carried_float.ll +++ b/polly/test/CodeGen/phi_loop_carried_float.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; float f(float *A, int N) { ; float tmp = 0; diff --git a/polly/test/CodeGen/phi_loop_carried_float_escape.ll b/polly/test/CodeGen/phi_loop_carried_float_escape.ll index 10bc751150e2..3b2ed01863b1 100644 --- a/polly/test/CodeGen/phi_loop_carried_float_escape.ll +++ b/polly/test/CodeGen/phi_loop_carried_float_escape.ll @@ -1,8 +1,8 @@ ; RUN: opt %loadPolly -S \ -; RUN: -polly-analyze-read-only-scalars=false -passes=polly-codegen < %s | FileCheck %s +; RUN: -polly-analyze-read-only-scalars=false -polly-codegen < %s | FileCheck %s ; RUN: opt %loadPolly -S \ -; RUN: -polly-analyze-read-only-scalars=true -passes=polly-codegen < %s | FileCheck %s +; RUN: -polly-analyze-read-only-scalars=true -polly-codegen < %s | FileCheck %s ; ; float f(float *A, int N) { ; float tmp = 0; diff --git a/polly/test/CodeGen/phi_scalar_simple_1.ll b/polly/test/CodeGen/phi_scalar_simple_1.ll index 07b8021fb743..d62975b6a7b3 100644 --- a/polly/test/CodeGen/phi_scalar_simple_1.ll +++ b/polly/test/CodeGen/phi_scalar_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; int jd(int *restrict A, int x, int N) { ; for (int i = 1; i < N; i++) diff --git a/polly/test/CodeGen/phi_scalar_simple_2.ll b/polly/test/CodeGen/phi_scalar_simple_2.ll index ab89b74c35a7..e58945d39960 100644 --- a/polly/test/CodeGen/phi_scalar_simple_2.ll +++ b/polly/test/CodeGen/phi_scalar_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; int jd(int *restrict A, int x, int N, int c) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/CodeGen/phi_with_multi_exiting_edges_2.ll b/polly/test/CodeGen/phi_with_multi_exiting_edges_2.ll index 313ae27a4165..17e4b7d6b4de 100644 --- a/polly/test/CodeGen/phi_with_multi_exiting_edges_2.ll +++ b/polly/test/CodeGen/phi_with_multi_exiting_edges_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; CHECK: polly.merge_new_and_old: ; CHECK: %result.ph.merge = phi float [ %result.ph.final_reload, %polly.exiting ], [ %result.ph, %next.region_exiting ] diff --git a/polly/test/CodeGen/phi_with_one_exit_edge.ll b/polly/test/CodeGen/phi_with_one_exit_edge.ll index fa692a9cdd38..81fd73b51c79 100644 --- a/polly/test/CodeGen/phi_with_one_exit_edge.ll +++ b/polly/test/CodeGen/phi_with_one_exit_edge.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; ; CHECK: polly.merge_new_and_old: diff --git a/polly/test/CodeGen/pointer-type-expressions-2.ll b/polly/test/CodeGen/pointer-type-expressions-2.ll index 013a9634844b..b261cfe53321 100644 --- a/polly/test/CodeGen/pointer-type-expressions-2.ll +++ b/polly/test/CodeGen/pointer-type-expressions-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" define void @foo(ptr %start, ptr %end) { diff --git a/polly/test/CodeGen/pointer-type-expressions.ll b/polly/test/CodeGen/pointer-type-expressions.ll index ad0c0639a9d9..6bb3fa242362 100644 --- a/polly/test/CodeGen/pointer-type-expressions.ll +++ b/polly/test/CodeGen/pointer-type-expressions.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN ; void f(int a[], int N, float *P) { ; int i; diff --git a/polly/test/CodeGen/pointer-type-pointer-type-comparison.ll b/polly/test/CodeGen/pointer-type-pointer-type-comparison.ll index 5627a85c01b8..eaef64017aa7 100644 --- a/polly/test/CodeGen/pointer-type-pointer-type-comparison.ll +++ b/polly/test/CodeGen/pointer-type-pointer-type-comparison.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN ; ; void f(int a[], int N, float *P, float *Q) { diff --git a/polly/test/CodeGen/pointer_rem.ll b/polly/test/CodeGen/pointer_rem.ll index a82c5cefa26d..5c92ee52da2c 100644 --- a/polly/test/CodeGen/pointer_rem.ll +++ b/polly/test/CodeGen/pointer_rem.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print,scop(print)' -disable-output -S < %s | FileCheck %s --check-prefix=AST -; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print,scop(polly-codegen)' -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-process-unprofitable -polly-scops -polly-print-ast -disable-output -S < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -polly-process-unprofitable -polly-scops -polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN target datalayout = "e-m:e-i64:64-i128:128-n8:16:32:64-S128" target triple = "aarch64--linux-gnu" diff --git a/polly/test/CodeGen/pr25241.ll b/polly/test/CodeGen/pr25241.ll index 2f982c5ffbfc..9fa67e083a6c 100644 --- a/polly/test/CodeGen/pr25241.ll +++ b/polly/test/CodeGen/pr25241.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; PR25241 (https://llvm.org/bugs/show_bug.cgi?id=25241) ; Ensure that synthesized values of a PHI node argument are generated in the diff --git a/polly/test/CodeGen/ptrtoint_as_parameter.ll b/polly/test/CodeGen/ptrtoint_as_parameter.ll index ea7cd57bdcc0..4f6c8079729d 100644 --- a/polly/test/CodeGen/ptrtoint_as_parameter.ll +++ b/polly/test/CodeGen/ptrtoint_as_parameter.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; CHECK: if.then260: ; CHECK-NEXT: %p.4 = getelementptr inbounds i8, ptr null, i64 1 diff --git a/polly/test/CodeGen/read-only-scalars.ll b/polly/test/CodeGen/read-only-scalars.ll index 318362d6a27a..a5e1d2719d7d 100644 --- a/polly/test/CodeGen/read-only-scalars.ll +++ b/polly/test/CodeGen/read-only-scalars.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-analyze-read-only-scalars=false -passes=polly-codegen \ +; RUN: opt %loadPolly -polly-analyze-read-only-scalars=false -polly-codegen \ ; RUN: \ ; RUN: -S < %s | FileCheck %s -; RUN: opt %loadPolly -polly-analyze-read-only-scalars=true -passes=polly-codegen \ +; RUN: opt %loadPolly -polly-analyze-read-only-scalars=true -polly-codegen \ ; RUN: \ ; RUN: -S < %s | FileCheck %s -check-prefix=SCALAR diff --git a/polly/test/CodeGen/reduction.ll b/polly/test/CodeGen/reduction.ll index 1af5a0d80124..6e5a230ad231 100644 --- a/polly/test/CodeGen/reduction.ll +++ b/polly/test/CodeGen/reduction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s 2>&1 | not FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s 2>&1 | not FileCheck %s ;#include ;#include diff --git a/polly/test/CodeGen/reduction_2.ll b/polly/test/CodeGen/reduction_2.ll index b4ed4d95d543..7a50cea31400 100644 --- a/polly/test/CodeGen/reduction_2.ll +++ b/polly/test/CodeGen/reduction_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s | FileCheck %s --allow-empty +; RUN: opt %loadPolly -basic-aa -polly-invariant-load-hoisting=true -polly-print-ast -disable-output < %s | FileCheck %s --allow-empty ;#include ;#include diff --git a/polly/test/CodeGen/reduction_simple_binary.ll b/polly/test/CodeGen/reduction_simple_binary.ll index 25903d6554c5..c7c5501bb7ed 100644 --- a/polly/test/CodeGen/reduction_simple_binary.ll +++ b/polly/test/CodeGen/reduction_simple_binary.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: pragma simd reduction ; diff --git a/polly/test/CodeGen/region-with-instructions.ll b/polly/test/CodeGen/region-with-instructions.ll index 125b791cbcf2..28cabefbf68b 100644 --- a/polly/test/CodeGen/region-with-instructions.ll +++ b/polly/test/CodeGen/region-with-instructions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; CHECK-LABEL: polly.stmt.bb48: ; CHECK-NEXT: %[[offset:.*]] = shl i64 %polly.indvar, 3 diff --git a/polly/test/CodeGen/region_exiting-domtree.ll b/polly/test/CodeGen/region_exiting-domtree.ll index 354f631e1002..05983da0a3e3 100644 --- a/polly/test/CodeGen/region_exiting-domtree.ll +++ b/polly/test/CodeGen/region_exiting-domtree.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -verify-dom-info -disable-output < %s +; RUN: opt %loadPolly -polly-codegen -verify-dom-info -disable-output < %s ; Verify that the DominatorTree is preserved correctly for the inserted ; %polly.stmt.exit.exit block, which serves as new exit block for the generated diff --git a/polly/test/CodeGen/region_multiexit_partialwrite.ll b/polly/test/CodeGen/region_multiexit_partialwrite.ll index 49547c6615d5..b98d7f58732a 100644 --- a/polly/test/CodeGen/region_multiexit_partialwrite.ll +++ b/polly/test/CodeGen/region_multiexit_partialwrite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-codegen' -polly-import-jscop-postfix=transformed -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s | FileCheck %s ; ; This text case has a partial write of PHI in a region-statement. It ; requires that the new PHINode from the region's exiting block is diff --git a/polly/test/CodeGen/run-time-condition-with-scev-parameters.ll b/polly/test/CodeGen/run-time-condition-with-scev-parameters.ll index df6377ace33a..0f62a8c743df 100644 --- a/polly/test/CodeGen/run-time-condition-with-scev-parameters.ll +++ b/polly/test/CodeGen/run-time-condition-with-scev-parameters.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=AST -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; TODO: FIXME: Simplify the context. ; AST: if (n >= 1 && 0 == n <= -1) diff --git a/polly/test/CodeGen/run-time-condition.ll b/polly/test/CodeGen/run-time-condition.ll index 2a8cc72f8e9e..0faefad8aef4 100644 --- a/polly/test/CodeGen/run-time-condition.ll +++ b/polly/test/CodeGen/run-time-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-codegen -S < %s | 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-n8:16:32:64-S128" diff --git a/polly/test/CodeGen/scalar-references-used-in-scop-compute.ll b/polly/test/CodeGen/scalar-references-used-in-scop-compute.ll index 3519ffaef99b..3f88942c2300 100644 --- a/polly/test/CodeGen/scalar-references-used-in-scop-compute.ll +++ b/polly/test/CodeGen/scalar-references-used-in-scop-compute.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; Test the code generation in the presence of a scalar out-of-scop value being ; used from within the SCoP. diff --git a/polly/test/CodeGen/scalar-store-from-same-bb.ll b/polly/test/CodeGen/scalar-store-from-same-bb.ll index 016784a9deea..ac8fab4b7a0d 100644 --- a/polly/test/CodeGen/scalar-store-from-same-bb.ll +++ b/polly/test/CodeGen/scalar-store-from-same-bb.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly \ -; RUN: -passes=polly-codegen -S < %s | FileCheck %s +; RUN: -polly-codegen -S < %s | FileCheck %s ; This test ensures that the expression N + 1 that is stored in the phi-node ; alloca, is directly computed and not incorrectly transfered through memory. diff --git a/polly/test/CodeGen/scalar_codegen_crash.ll b/polly/test/CodeGen/scalar_codegen_crash.ll index e89c3558a187..c41a00f59e81 100644 --- a/polly/test/CodeGen/scalar_codegen_crash.ll +++ b/polly/test/CodeGen/scalar_codegen_crash.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly \ -; RUN: -passes=polly-codegen -S < %s | FileCheck %s +; RUN: -polly-codegen -S < %s | FileCheck %s ; This test cases used to crash the scalar code generation. Check that we ; can generate code for it. diff --git a/polly/test/CodeGen/scev-backedgetaken.ll b/polly/test/CodeGen/scev-backedgetaken.ll index 00fcf0b03482..15e12ee8b451 100644 --- a/polly/test/CodeGen/scev-backedgetaken.ll +++ b/polly/test/CodeGen/scev-backedgetaken.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; llvm.org/PR48422 ; Use of ScalarEvolution in Codegen not possible because DominatorTree is not updated. diff --git a/polly/test/CodeGen/scev-division-invariant-load.ll b/polly/test/CodeGen/scev-division-invariant-load.ll index 242fb75c3883..3156bdc9f5ce 100644 --- a/polly/test/CodeGen/scev-division-invariant-load.ll +++ b/polly/test/CodeGen/scev-division-invariant-load.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s +; RUN: opt %loadPolly -S -polly-codegen < %s ; ; Check that we generate valid code as we did not use the preloaded ; value of %tmp1 for the access function of the preloaded %tmp4. diff --git a/polly/test/CodeGen/scev.ll b/polly/test/CodeGen/scev.ll index 74faf062bdc7..07d726d97caf 100644 --- a/polly/test/CodeGen/scev.ll +++ b/polly/test/CodeGen/scev.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' < %s +; RUN: opt %loadPolly -polly-detect < %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-n8:16:32:64" define fastcc void @f () inlinehint align 2 { diff --git a/polly/test/CodeGen/scev_expansion_in_nonaffine.ll b/polly/test/CodeGen/scev_expansion_in_nonaffine.ll index 0575795cde48..f61f21d4adb8 100644 --- a/polly/test/CodeGen/scev_expansion_in_nonaffine.ll +++ b/polly/test/CodeGen/scev_expansion_in_nonaffine.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S \ +; RUN: opt %loadPolly -polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; bugpoint-reduced testcase of MiBench/consumer-lame/quantize-pvt.c from the diff --git a/polly/test/CodeGen/scev_looking_through_bitcasts.ll b/polly/test/CodeGen/scev_looking_through_bitcasts.ll index 776bb3332085..c87d932479b7 100644 --- a/polly/test/CodeGen/scev_looking_through_bitcasts.ll +++ b/polly/test/CodeGen/scev_looking_through_bitcasts.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; Scalar write of bitcasted value. Instead of writing %b of type ; %structty, the SCEV expression looks through the bitcast such that diff --git a/polly/test/CodeGen/scop_expander_insert_point.ll b/polly/test/CodeGen/scop_expander_insert_point.ll index 8434e7ec1aa8..8492873b22ed 100644 --- a/polly/test/CodeGen/scop_expander_insert_point.ll +++ b/polly/test/CodeGen/scop_expander_insert_point.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S \ +; RUN: opt %loadPolly -polly-codegen -S \ ; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; CHECK: entry: diff --git a/polly/test/CodeGen/scop_expander_segfault.ll b/polly/test/CodeGen/scop_expander_segfault.ll index 73145c4bfa23..293c1e527959 100644 --- a/polly/test/CodeGen/scop_expander_segfault.ll +++ b/polly/test/CodeGen/scop_expander_segfault.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S %s | FileCheck %s ; ; This test was extracted from gcc in SPEC2006 and it crashed our code ; generation, or to be more precise, the ScopExpander due to a endless diff --git a/polly/test/CodeGen/scop_never_executed_runtime_check_location.ll b/polly/test/CodeGen/scop_never_executed_runtime_check_location.ll index cc76ad1771c9..91a58159b5f9 100644 --- a/polly/test/CodeGen/scop_never_executed_runtime_check_location.ll +++ b/polly/test/CodeGen/scop_never_executed_runtime_check_location.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; Verify that we generate the runtime check code after the conditional branch ; in the SCoP region entering block (here %entry). diff --git a/polly/test/CodeGen/select-base-pointer.ll b/polly/test/CodeGen/select-base-pointer.ll index 9748736147ab..29bc40074e1f 100644 --- a/polly/test/CodeGen/select-base-pointer.ll +++ b/polly/test/CodeGen/select-base-pointer.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=tbaa -passes=polly-codegen -disable-output %s +; RUN: opt %loadPolly -tbaa -polly-codegen -disable-output %s ; ; Check that we do not crash here. ; diff --git a/polly/test/CodeGen/sequential_loops.ll b/polly/test/CodeGen/sequential_loops.ll index a0cecfbd817b..97d280de3cd2 100644 --- a/polly/test/CodeGen/sequential_loops.ll +++ b/polly/test/CodeGen/sequential_loops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ;#include ;#define N 1024 diff --git a/polly/test/CodeGen/simple_loop_non_single_exit.ll b/polly/test/CodeGen/simple_loop_non_single_exit.ll index a6f115ba1112..dc1b09b765a1 100644 --- a/polly/test/CodeGen/simple_loop_non_single_exit.ll +++ b/polly/test/CodeGen/simple_loop_non_single_exit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE ; void f(long A[], long N) { ; long i; diff --git a/polly/test/CodeGen/simple_loop_non_single_exit_2.ll b/polly/test/CodeGen/simple_loop_non_single_exit_2.ll index d58a6ed7b746..178601cac9b8 100644 --- a/polly/test/CodeGen/simple_loop_non_single_exit_2.ll +++ b/polly/test/CodeGen/simple_loop_non_single_exit_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE ; void f(long A[], long N) { ; long i; diff --git a/polly/test/CodeGen/simple_non_single_entry.ll b/polly/test/CodeGen/simple_non_single_entry.ll index 2b472496d364..3b4bf59bdc65 100644 --- a/polly/test/CodeGen/simple_non_single_entry.ll +++ b/polly/test/CodeGen/simple_non_single_entry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CHECK-CODE ; void f(long A[], long N) { ; long i; diff --git a/polly/test/CodeGen/simple_nonaffine_loop.ll b/polly/test/CodeGen/simple_nonaffine_loop.ll index 4074237d1bfb..d4e9c6082e6c 100644 --- a/polly/test/CodeGen/simple_nonaffine_loop.ll +++ b/polly/test/CodeGen/simple_nonaffine_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-allow-nonaffine -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-allow-nonaffine -disable-output < %s | FileCheck %s ;#include ;#include diff --git a/polly/test/CodeGen/single_do_loop_int_max_iterations.ll b/polly/test/CodeGen/single_do_loop_int_max_iterations.ll index 0b1d3e14f68a..9648fbe1cf12 100644 --- a/polly/test/CodeGen/single_do_loop_int_max_iterations.ll +++ b/polly/test/CodeGen/single_do_loop_int_max_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ;#define N 20 ;#include "limits.h" diff --git a/polly/test/CodeGen/single_do_loop_int_param_iterations.ll b/polly/test/CodeGen/single_do_loop_int_param_iterations.ll index 459ba18edac4..f28d828a5da0 100644 --- a/polly/test/CodeGen/single_do_loop_int_param_iterations.ll +++ b/polly/test/CodeGen/single_do_loop_int_param_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ; XFAIL: * ;define N 20 diff --git a/polly/test/CodeGen/single_do_loop_ll_max_iterations.ll b/polly/test/CodeGen/single_do_loop_ll_max_iterations.ll index 5fdb5b14df4d..68aaab96083a 100644 --- a/polly/test/CodeGen/single_do_loop_ll_max_iterations.ll +++ b/polly/test/CodeGen/single_do_loop_ll_max_iterations.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen < %s ;#define N 20 ;#include "limits.h" diff --git a/polly/test/CodeGen/single_do_loop_one_iteration.ll b/polly/test/CodeGen/single_do_loop_one_iteration.ll index 18bab682adeb..9d97cb854734 100644 --- a/polly/test/CodeGen/single_do_loop_one_iteration.ll +++ b/polly/test/CodeGen/single_do_loop_one_iteration.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ; XFAIL: * ;#define N 20 diff --git a/polly/test/CodeGen/single_do_loop_scev_replace.ll b/polly/test/CodeGen/single_do_loop_scev_replace.ll index 9bdc3d7cd9b5..7963d9d29fe8 100644 --- a/polly/test/CodeGen/single_do_loop_scev_replace.ll +++ b/polly/test/CodeGen/single_do_loop_scev_replace.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ;#define N 20 ;#include "limits.h" diff --git a/polly/test/CodeGen/single_loop.ll b/polly/test/CodeGen/single_loop.ll index fe68c81567f8..68cc498b43e0 100644 --- a/polly/test/CodeGen/single_loop.ll +++ b/polly/test/CodeGen/single_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ;#include ;#define N 1024 diff --git a/polly/test/CodeGen/single_loop_int_max_iterations.ll b/polly/test/CodeGen/single_loop_int_max_iterations.ll index 017f1a3114cc..bfb5e4ab2698 100644 --- a/polly/test/CodeGen/single_loop_int_max_iterations.ll +++ b/polly/test/CodeGen/single_loop_int_max_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ;#define N 20 ;#include "limits.h" diff --git a/polly/test/CodeGen/single_loop_ll_max_iterations.ll b/polly/test/CodeGen/single_loop_ll_max_iterations.ll index 89fb9be7f9e1..bdfd7fce4204 100644 --- a/polly/test/CodeGen/single_loop_ll_max_iterations.ll +++ b/polly/test/CodeGen/single_loop_ll_max_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ;#include "limits.h" ;#define N 20 diff --git a/polly/test/CodeGen/single_loop_one_iteration.ll b/polly/test/CodeGen/single_loop_one_iteration.ll index fcbe34da2a92..7d4dd590fab9 100644 --- a/polly/test/CodeGen/single_loop_one_iteration.ll +++ b/polly/test/CodeGen/single_loop_one_iteration.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ;#define N 20 ; diff --git a/polly/test/CodeGen/single_loop_param.ll b/polly/test/CodeGen/single_loop_param.ll index 19f3fb42a475..5d72da354fdc 100644 --- a/polly/test/CodeGen/single_loop_param.ll +++ b/polly/test/CodeGen/single_loop_param.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | 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-n8:16:32:64" @A = common global [1024 x i32] zeroinitializer, align 16 ; [#uses=3] diff --git a/polly/test/CodeGen/single_loop_param_less_equal.ll b/polly/test/CodeGen/single_loop_param_less_equal.ll index 07d0ef24f4c0..e63ee299a37c 100644 --- a/polly/test/CodeGen/single_loop_param_less_equal.ll +++ b/polly/test/CodeGen/single_loop_param_less_equal.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN -; RUN: opt %loadPolly -passes=polly-codegen < %s | opt -passes='print' -disable-output 2>&1 | FileCheck %s -check-prefix=LOOPS +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-codegen < %s | opt -passes='print' -disable-output 2>&1 | FileCheck %s -check-prefix=LOOPS 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-n8:16:32:64" @A = common global [1024 x i32] zeroinitializer diff --git a/polly/test/CodeGen/single_loop_param_less_than.ll b/polly/test/CodeGen/single_loop_param_less_than.ll index 26dddea44b20..95130f926450 100644 --- a/polly/test/CodeGen/single_loop_param_less_than.ll +++ b/polly/test/CodeGen/single_loop_param_less_than.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN 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-n8:16:32:64" @A = common global [1024 x i32] zeroinitializer diff --git a/polly/test/CodeGen/single_loop_zero_iterations.ll b/polly/test/CodeGen/single_loop_zero_iterations.ll index e4a5b7670d77..4f189687d330 100644 --- a/polly/test/CodeGen/single_loop_zero_iterations.ll +++ b/polly/test/CodeGen/single_loop_zero_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=SCALAR --allow-empty +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=SCALAR --allow-empty ;#define N 20 ; diff --git a/polly/test/CodeGen/split_edge_of_exit.ll b/polly/test/CodeGen/split_edge_of_exit.ll index 3f2a1389f886..56ce215a62b2 100644 --- a/polly/test/CodeGen/split_edge_of_exit.ll +++ b/polly/test/CodeGen/split_edge_of_exit.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -verify-region-info -disable-output < %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -verify-region-info -disable-output < %s ; ; This is a scop directly precedented by a region, i.e. the scop's entry is the ; region's exit block. This test is to ensure that the RegionInfo is correctly diff --git a/polly/test/CodeGen/split_edges.ll b/polly/test/CodeGen/split_edges.ll index 0fc705becb91..e01d901e298c 100644 --- a/polly/test/CodeGen/split_edges.ll +++ b/polly/test/CodeGen/split_edges.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -verify-region-info -verify-dom-info -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -verify-region-info -verify-dom-info -S < %s | 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-n8:16:32:64" @A = common global [1536 x float] zeroinitializer diff --git a/polly/test/CodeGen/split_edges_2.ll b/polly/test/CodeGen/split_edges_2.ll index 84449327bf4c..4135d6feeb3e 100644 --- a/polly/test/CodeGen/split_edges_2.ll +++ b/polly/test/CodeGen/split_edges_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -verify-region-info -verify-dom-info -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -verify-region-info -verify-dom-info -S < %s | 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-n8:16:32:64" diff --git a/polly/test/CodeGen/srem-in-other-bb.ll b/polly/test/CodeGen/srem-in-other-bb.ll index eaad663159f0..8bde1a3bbc1d 100644 --- a/polly/test/CodeGen/srem-in-other-bb.ll +++ b/polly/test/CodeGen/srem-in-other-bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S \ +; RUN: opt %loadPolly -polly-codegen -S \ ; RUN: < %s | FileCheck %s ; ; void pos(float *A, long n) { diff --git a/polly/test/CodeGen/stack-overflow-in-load-hoisting.ll b/polly/test/CodeGen/stack-overflow-in-load-hoisting.ll index 41241de132a3..02dfe96e3e91 100644 --- a/polly/test/CodeGen/stack-overflow-in-load-hoisting.ll +++ b/polly/test/CodeGen/stack-overflow-in-load-hoisting.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -verify-dom-info -passes=polly-codegen -S < %s \ +; RUN: opt %loadPolly -verify-dom-info -polly-codegen -S < %s \ ; RUN: -polly-invariant-load-hoisting=true | FileCheck %s ; ; This caused an infinite recursion during invariant load hoisting at some diff --git a/polly/test/CodeGen/stmt_split_no_dependence.ll b/polly/test/CodeGen/stmt_split_no_dependence.ll index 94407e8e7c38..a395aa14b4c8 100644 --- a/polly/test/CodeGen/stmt_split_no_dependence.ll +++ b/polly/test/CodeGen/stmt_split_no_dependence.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; CHECK: store i32 %9, ptr %scevgep, align 4, !alias.scope !1, !noalias !4 ; CHECK: store i32 %11, ptr %scevgep4, align 4, !alias.scope !4, !noalias !1 diff --git a/polly/test/CodeGen/switch-in-non-affine-region.ll b/polly/test/CodeGen/switch-in-non-affine-region.ll index 2524699157b7..930755ef5648 100644 --- a/polly/test/CodeGen/switch-in-non-affine-region.ll +++ b/polly/test/CodeGen/switch-in-non-affine-region.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly \ -; RUN: -S -passes=polly-codegen < %s | FileCheck %s +; RUN: -S -polly-codegen < %s | FileCheck %s ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/CodeGen/synthesizable_phi_write_after_loop.ll b/polly/test/CodeGen/synthesizable_phi_write_after_loop.ll index 86745d71953e..6a8d3b94d1cc 100644 --- a/polly/test/CodeGen/synthesizable_phi_write_after_loop.ll +++ b/polly/test/CodeGen/synthesizable_phi_write_after_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; Check for the correct written value of a scalar phi write whose value is ; defined within the loop, but its effective value is its last definition when diff --git a/polly/test/CodeGen/test-invalid-operands-for-select-2.ll b/polly/test/CodeGen/test-invalid-operands-for-select-2.ll index 9b3608c81f50..5fa4773398fd 100644 --- a/polly/test/CodeGen/test-invalid-operands-for-select-2.ll +++ b/polly/test/CodeGen/test-invalid-operands-for-select-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen -verify-loop-info < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen -verify-loop-info < %s | FileCheck %s ; ; Check that we do not crash as described here: http://llvm.org/bugs/show_bug.cgi?id=21167 ; diff --git a/polly/test/CodeGen/test-invalid-operands-for-select.ll b/polly/test/CodeGen/test-invalid-operands-for-select.ll index a10603126cf6..40695af3e847 100644 --- a/polly/test/CodeGen/test-invalid-operands-for-select.ll +++ b/polly/test/CodeGen/test-invalid-operands-for-select.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; Check that we do not crash as described here: http://llvm.org/PR21167 ; diff --git a/polly/test/CodeGen/test.ll b/polly/test/CodeGen/test.ll index 1038e57c358f..ac99688ed9e8 100644 --- a/polly/test/CodeGen/test.ll +++ b/polly/test/CodeGen/test.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ; XFAIL: * ;int bar1(); diff --git a/polly/test/CodeGen/two-loops-right-after-each-other-2.ll b/polly/test/CodeGen/two-loops-right-after-each-other-2.ll index 71bec88e7dde..a7cae0a921ca 100644 --- a/polly/test/CodeGen/two-loops-right-after-each-other-2.ll +++ b/polly/test/CodeGen/two-loops-right-after-each-other-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; CHECK: polly.merge_new_and_old: ; CHECK-NEXT: merge = phi diff --git a/polly/test/CodeGen/two-scops-in-row-invalidate-scevs.ll b/polly/test/CodeGen/two-scops-in-row-invalidate-scevs.ll index 327430da11bb..4470f970fc1e 100644 --- a/polly/test/CodeGen/two-scops-in-row-invalidate-scevs.ll +++ b/polly/test/CodeGen/two-scops-in-row-invalidate-scevs.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; CHECK-LABEL: for.cond: ; CHECK: %num.0 = phi i32 [ %add, %for.body15 ], [ 0, %for.cond.pre_entry_bb ] diff --git a/polly/test/CodeGen/two-scops-in-row.ll b/polly/test/CodeGen/two-scops-in-row.ll index 06e7ea096d79..3e922cba1916 100644 --- a/polly/test/CodeGen/two-scops-in-row.ll +++ b/polly/test/CodeGen/two-scops-in-row.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly '-passes=print' -polly-ignore-aliasing -disable-output < %s | FileCheck %s -check-prefix=SCALAR -; RUN: opt %loadPolly -passes=polly-codegen -polly-ignore-aliasing -disable-output < %s +; RUN: opt %loadPolly -polly-print-ast -polly-ignore-aliasing -disable-output < %s | FileCheck %s -check-prefix=SCALAR +; RUN: opt %loadPolly -polly-codegen -polly-ignore-aliasing -disable-output < %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; SCALAR: if ( diff --git a/polly/test/CodeGen/udiv_expansion_position.ll b/polly/test/CodeGen/udiv_expansion_position.ll index 39df17dc2030..bb37fed4a41e 100644 --- a/polly/test/CodeGen/udiv_expansion_position.ll +++ b/polly/test/CodeGen/udiv_expansion_position.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; Verify we do not crash when we synthezise code for the udiv in the SCoP. ; diff --git a/polly/test/CodeGen/uninitialized_scalar_memory.ll b/polly/test/CodeGen/uninitialized_scalar_memory.ll index 89eb32c4cf0f..935ccc3d6289 100644 --- a/polly/test/CodeGen/uninitialized_scalar_memory.ll +++ b/polly/test/CodeGen/uninitialized_scalar_memory.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-codegen < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s ; ; Verify we initialize the scalar locations reserved for the incoming phi ; values. diff --git a/polly/test/CodeGen/unpredictable-loop-unsynthesizable.ll b/polly/test/CodeGen/unpredictable-loop-unsynthesizable.ll index e3d0f2df7351..9164bb4532e6 100644 --- a/polly/test/CodeGen/unpredictable-loop-unsynthesizable.ll +++ b/polly/test/CodeGen/unpredictable-loop-unsynthesizable.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' \ -; RUN: -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -passes=polly-codegen \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops \ +; RUN: -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-codegen \ ; RUN: -polly-invariant-load-hoisting=true -disable-output < %s ; The loop for.body is a scop with invariant load hoisting, but does not diff --git a/polly/test/CodeGen/variant_load_empty_domain.ll b/polly/test/CodeGen/variant_load_empty_domain.ll index 0ea3b0d1ed1f..f5ad0b195818 100644 --- a/polly/test/CodeGen/variant_load_empty_domain.ll +++ b/polly/test/CodeGen/variant_load_empty_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-codegen -disable-output < %s ; ; ; void f(int *A) { diff --git a/polly/test/CodeGen/whole-scop-non-affine-subregion.ll b/polly/test/CodeGen/whole-scop-non-affine-subregion.ll index 9c911715904d..931e644f6b8f 100644 --- a/polly/test/CodeGen/whole-scop-non-affine-subregion.ll +++ b/polly/test/CodeGen/whole-scop-non-affine-subregion.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly \ -; RUN: -passes=polly-codegen -S < %s | FileCheck %s +; RUN: -polly-codegen -S < %s | FileCheck %s ; CHECK: polly.start ; int /* pure */ g() diff --git a/polly/test/DeLICM/confused_order.ll b/polly/test/DeLICM/confused_order.ll index 62f59cdef315..2015ebcf58f1 100644 --- a/polly/test/DeLICM/confused_order.ll +++ b/polly/test/DeLICM/confused_order.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-delicm' -polly-import-jscop-postfix=transformed -disable-output -pass-remarks-missed=polly-delicm < %s 2>&1 | FileCheck %s -check-prefix=REMARKS +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-delicm -disable-output -pass-remarks-missed=polly-delicm < %s 2>&1 | FileCheck %s -check-prefix=REMARKS ; ; ForwardOptree changes the SCoP and may already map some accesses. ; DeLICM must be prepared to encounter implicit reads diff --git a/polly/test/DeLICM/contradicting_assumed_context_and_domain.ll b/polly/test/DeLICM/contradicting_assumed_context_and_domain.ll index 768cb23631e7..4e039b22b415 100644 --- a/polly/test/DeLICM/contradicting_assumed_context_and_domain.ll +++ b/polly/test/DeLICM/contradicting_assumed_context_and_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s ; ; The domain of bb14 contradicts the SCoP's assumptions. This leads to ; 'anything goes' inside the statement since it is never executed, diff --git a/polly/test/DeLICM/load-in-cond-inf-loop.ll b/polly/test/DeLICM/load-in-cond-inf-loop.ll index 40e30a52c545..f0aecfd87a15 100644 --- a/polly/test/DeLICM/load-in-cond-inf-loop.ll +++ b/polly/test/DeLICM/load-in-cond-inf-loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s ; When %b is 0, %for.body13 is an infite loop. In this case the loaded ; value %1 is not used anywhere. diff --git a/polly/test/DeLICM/map_memset_zero.ll b/polly/test/DeLICM/map_memset_zero.ll index 6789577cb046..1a08eee63fe9 100644 --- a/polly/test/DeLICM/map_memset_zero.ll +++ b/polly/test/DeLICM/map_memset_zero.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck -match-full-lines %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck -match-full-lines %s ; ; Check that PHI mapping works even in presence of a memset whose' ; zero value is used. diff --git a/polly/test/DeLICM/nomap_alreadymapped.ll b/polly/test/DeLICM/nomap_alreadymapped.ll index bf26a809324b..7adf4ba88385 100644 --- a/polly/test/DeLICM/nomap_alreadymapped.ll +++ b/polly/test/DeLICM/nomap_alreadymapped.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/nomap_escaping.ll b/polly/test/DeLICM/nomap_escaping.ll index 17451a2941ea..034c0a96ccf2 100644 --- a/polly/test/DeLICM/nomap_escaping.ll +++ b/polly/test/DeLICM/nomap_escaping.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/nomap_occupied.ll b/polly/test/DeLICM/nomap_occupied.ll index e6ca903dae03..db33532b1e65 100644 --- a/polly/test/DeLICM/nomap_occupied.ll +++ b/polly/test/DeLICM/nomap_occupied.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/nomap_readonly.ll b/polly/test/DeLICM/nomap_readonly.ll index 2c19bb9bc495..1f3b5746fe9b 100644 --- a/polly/test/DeLICM/nomap_readonly.ll +++ b/polly/test/DeLICM/nomap_readonly.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; fsomeval = 21.0 + 21.0; diff --git a/polly/test/DeLICM/nomap_spuriouswrite.ll b/polly/test/DeLICM/nomap_spuriouswrite.ll index f561a4b189ee..ef470f715bbe 100644 --- a/polly/test/DeLICM/nomap_spuriouswrite.ll +++ b/polly/test/DeLICM/nomap_spuriouswrite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/nomap_storagesize.ll b/polly/test/DeLICM/nomap_storagesize.ll index 2c116cc85609..fab8d54c2bdf 100644 --- a/polly/test/DeLICM/nomap_storagesize.ll +++ b/polly/test/DeLICM/nomap_storagesize.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s ; ; void func(float *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/nomap_writewrite.ll b/polly/test/DeLICM/nomap_writewrite.ll index 6e3b06a4c57f..06192d9ae19e 100644 --- a/polly/test/DeLICM/nomap_writewrite.ll +++ b/polly/test/DeLICM/nomap_writewrite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/outofquota-reverseDomain.ll b/polly/test/DeLICM/outofquota-reverseDomain.ll index d917d294dcdf..d40ee03cf3bc 100644 --- a/polly/test/DeLICM/outofquota-reverseDomain.ll +++ b/polly/test/DeLICM/outofquota-reverseDomain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-delicm-max-ops=1000000 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-delicm-max-ops=1000000 -polly-print-delicm -disable-output < %s | FileCheck %s ; ; This causes an assertion to fail on out-of-quota after 1000000 operations. ; (The error was specific to -polly-delicm-max-ops=1000000 and changes diff --git a/polly/test/DeLICM/pass_existence.ll b/polly/test/DeLICM/pass_existence.ll index 57adf45b207c..7ed2da9c1da1 100644 --- a/polly/test/DeLICM/pass_existence.ll +++ b/polly/test/DeLICM/pass_existence.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -passes=polly-delicm -disable-output < %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly '-passes=scop(print)' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-delicm -disable-output < %s +; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s ; ; Simple test for the existence of the DeLICM pass. ; diff --git a/polly/test/DeLICM/pr41656.ll b/polly/test/DeLICM/pr41656.ll index ba65b5bf0416..965ad9f62ac3 100644 --- a/polly/test/DeLICM/pr41656.ll +++ b/polly/test/DeLICM/pr41656.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,scop(print)' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-print-delicm -disable-output < %s | FileCheck %s ; ; llvm.org/PR41656 ; diff --git a/polly/test/DeLICM/pr48783.ll b/polly/test/DeLICM/pr48783.ll index 2bba7f731f56..3cbd54b93baf 100644 --- a/polly/test/DeLICM/pr48783.ll +++ b/polly/test/DeLICM/pr48783.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,scop(print)' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-print-delicm -disable-output < %s | FileCheck %s ; ; llvm.org/PR48783 ; diff --git a/polly/test/DeLICM/reduction.ll b/polly/test/DeLICM/reduction.ll index a6f1e032f6e4..78c1a4ce5288 100644 --- a/polly/test/DeLICM/reduction.ll +++ b/polly/test/DeLICM/reduction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-delicm-partial-writes=true '-passes=print' -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-delicm-partial-writes=true -polly-print-delicm -disable-output < %s | FileCheck -match-full-lines %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/reduction_looprotate_gvnpre_cond1.ll b/polly/test/DeLICM/reduction_looprotate_gvnpre_cond1.ll index e30fe12c8a74..b5bc0d589c65 100644 --- a/polly/test/DeLICM/reduction_looprotate_gvnpre_cond1.ll +++ b/polly/test/DeLICM/reduction_looprotate_gvnpre_cond1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines ; ; Load (but not store) of A[j] hoisted, reduction only over some iterations. ; diff --git a/polly/test/DeLICM/reduction_looprotate_gvnpre_cond2.ll b/polly/test/DeLICM/reduction_looprotate_gvnpre_cond2.ll index a830782e9c44..e995be1143a6 100644 --- a/polly/test/DeLICM/reduction_looprotate_gvnpre_cond2.ll +++ b/polly/test/DeLICM/reduction_looprotate_gvnpre_cond2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines ; ; Load (but not store) of A[j] hoisted, reduction not written in all iterations. ; FIXME: %join is not mapped because the MemoryKind::Value mapping does not diff --git a/polly/test/DeLICM/reduction_looprotate_gvnpre_nopreheader.ll b/polly/test/DeLICM/reduction_looprotate_gvnpre_nopreheader.ll index 903bc80b9d47..ca3a1211ca49 100644 --- a/polly/test/DeLICM/reduction_looprotate_gvnpre_nopreheader.ll +++ b/polly/test/DeLICM/reduction_looprotate_gvnpre_nopreheader.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines ; ; Hosted reduction load (but not the store) without preheader. ; diff --git a/polly/test/DeLICM/reduction_looprotate_licm_nopreheader.ll b/polly/test/DeLICM/reduction_looprotate_licm_nopreheader.ll index 23497f19402b..41538239fbd8 100644 --- a/polly/test/DeLICM/reduction_looprotate_licm_nopreheader.ll +++ b/polly/test/DeLICM/reduction_looprotate_licm_nopreheader.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s ; ; Register-promoted reduction but without preheader. ; diff --git a/polly/test/DeLICM/reduction_looprotate_loopguard_gvnpre.ll b/polly/test/DeLICM/reduction_looprotate_loopguard_gvnpre.ll index c932a311a7aa..35c723e864d2 100644 --- a/polly/test/DeLICM/reduction_looprotate_loopguard_gvnpre.ll +++ b/polly/test/DeLICM/reduction_looprotate_loopguard_gvnpre.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines ; ; Reduction over parametric number of elements and a loopguard if the ; reduction loop is not executed at all. Load hoisted before loop. diff --git a/polly/test/DeLICM/reduction_looprotate_loopguard_licm1.ll b/polly/test/DeLICM/reduction_looprotate_loopguard_licm1.ll index 52073eb35014..2b5f4d8151a8 100644 --- a/polly/test/DeLICM/reduction_looprotate_loopguard_licm1.ll +++ b/polly/test/DeLICM/reduction_looprotate_loopguard_licm1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines ; ; Reduction over parametric number of elements and a loopguard if the ; reduction loop is not executed at all. diff --git a/polly/test/DeLICM/reduction_looprotate_loopguard_licm2.ll b/polly/test/DeLICM/reduction_looprotate_loopguard_licm2.ll index 88ae8b3b0f20..2e92813d5551 100644 --- a/polly/test/DeLICM/reduction_looprotate_loopguard_licm2.ll +++ b/polly/test/DeLICM/reduction_looprotate_loopguard_licm2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines ; ; Reduction over parametric number of elements and a loopguard if the ; reduction loop is not executed at all, such that A[j] is also not written to. diff --git a/polly/test/DeLICM/reduction_looprotate_loopguard_licm3.ll b/polly/test/DeLICM/reduction_looprotate_loopguard_licm3.ll index 3a356926afa0..784c8ef2d321 100644 --- a/polly/test/DeLICM/reduction_looprotate_loopguard_licm3.ll +++ b/polly/test/DeLICM/reduction_looprotate_loopguard_licm3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s -match-full-lines ; ; Reduction over parametric number of elements and a loopguard if the ; reduction loop is not executed at all, such that A[j] is also not accessed. diff --git a/polly/test/DeLICM/reduction_unrelatedunusual.ll b/polly/test/DeLICM/reduction_unrelatedunusual.ll index 00097dfc92e8..04c437770700 100644 --- a/polly/test/DeLICM/reduction_unrelatedunusual.ll +++ b/polly/test/DeLICM/reduction_unrelatedunusual.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-delicm-partial-writes=true '-passes=print' -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-delicm-partial-writes=true -polly-print-delicm -disable-output < %s | FileCheck -match-full-lines %s ; ; Map %add and %phi to A[j]. ; The non-analyzable store to C[0] is unrelated and can be ignored. diff --git a/polly/test/DeLICM/reject_loadafterstore.ll b/polly/test/DeLICM/reject_loadafterstore.ll index 2a153b5cd710..8af6e5e4818c 100644 --- a/polly/test/DeLICM/reject_loadafterstore.ll +++ b/polly/test/DeLICM/reject_loadafterstore.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output -pass-remarks-missed=polly-delicm < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output -pass-remarks-missed=polly-delicm < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/reject_outofquota.ll b/polly/test/DeLICM/reject_outofquota.ll index 35001ec1ab2d..551431f0823c 100644 --- a/polly/test/DeLICM/reject_outofquota.ll +++ b/polly/test/DeLICM/reject_outofquota.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-analysis=polly-delicm -polly-delicm-max-ops=1 -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=polly-delicm,print' -polly-delicm-max-ops=1 -polly-dependences-computeout=0 -disable-output < %s | FileCheck %s -check-prefix=DEP +; RUN: opt %loadPolly -polly-print-delicm -pass-remarks-analysis=polly-delicm -polly-delicm-max-ops=1 -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-delicm -polly-print-dependences -polly-delicm-max-ops=1 -polly-dependences-computeout=0 -disable-output < %s | FileCheck %s -check-prefix=DEP ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/reject_storeafterstore.ll b/polly/test/DeLICM/reject_storeafterstore.ll index 715375fcdea2..1ec5ef67344c 100644 --- a/polly/test/DeLICM/reject_storeafterstore.ll +++ b/polly/test/DeLICM/reject_storeafterstore.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/reject_storeinsubregion.ll b/polly/test/DeLICM/reject_storeinsubregion.ll index 6490dc25d4a5..1d38e8066568 100644 --- a/polly/test/DeLICM/reject_storeinsubregion.ll +++ b/polly/test/DeLICM/reject_storeinsubregion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/reject_unusualstore.ll b/polly/test/DeLICM/reject_unusualstore.ll index 22c7d8ca0ea6..a18a0c3ce9c4 100644 --- a/polly/test/DeLICM/reject_unusualstore.ll +++ b/polly/test/DeLICM/reject_unusualstore.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -passes=polly-delicm -disable-output -stats < %s 2>&1 | FileCheck %s --check-prefix=STATS +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-delicm -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-delicm -disable-output -stats < %s 2>&1 | FileCheck %s --check-prefix=STATS ; REQUIRES: asserts ; ; void func(double *A) { diff --git a/polly/test/DeLICM/skip_maywrite.ll b/polly/test/DeLICM/skip_maywrite.ll index 4da0ddb9dfd2..1e5f6b169fe4 100644 --- a/polly/test/DeLICM/skip_maywrite.ll +++ b/polly/test/DeLICM/skip_maywrite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeLICM/skip_multiaccess.ll b/polly/test/DeLICM/skip_multiaccess.ll index 0eea60d0f488..6a8c8e5325e1 100644 --- a/polly/test/DeLICM/skip_multiaccess.ll +++ b/polly/test/DeLICM/skip_multiaccess.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; llvm.org/PR34485 ; llvm.org/PR34989 diff --git a/polly/test/DeLICM/skip_notinloop.ll b/polly/test/DeLICM/skip_notinloop.ll index caa70179d666..0730a3a9a4f5 100644 --- a/polly/test/DeLICM/skip_notinloop.ll +++ b/polly/test/DeLICM/skip_notinloop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; double phi = 0.0; diff --git a/polly/test/DeLICM/skip_scalaraccess.ll b/polly/test/DeLICM/skip_scalaraccess.ll index 8c9728dc6c42..fa95d382409a 100644 --- a/polly/test/DeLICM/skip_scalaraccess.ll +++ b/polly/test/DeLICM/skip_scalaraccess.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -pass-remarks-missed=polly-delicm -disable-output < %s 2>&1 | FileCheck %s ; ; void func(double *A) { ; for (int j = 0; j < 2; j += 1) { /* outer */ diff --git a/polly/test/DeadCodeElimination/chained_iterations.ll b/polly/test/DeadCodeElimination/chained_iterations.ll index 10be83559f29..b79fdd659aae 100644 --- a/polly/test/DeadCodeElimination/chained_iterations.ll +++ b/polly/test/DeadCodeElimination/chained_iterations.ll @@ -1,5 +1,5 @@ -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-dependences-analysis-type=value-based '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-dependences-analysis-type=value-based '-passes=polly-dce,print' -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE +; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE 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-n8:16:32:64" ; ; for(i = 0; i < 200; i++ ) diff --git a/polly/test/DeadCodeElimination/chained_iterations_2.ll b/polly/test/DeadCodeElimination/chained_iterations_2.ll index 42242c40eac9..1d1af92db5da 100644 --- a/polly/test/DeadCodeElimination/chained_iterations_2.ll +++ b/polly/test/DeadCodeElimination/chained_iterations_2.ll @@ -1,5 +1,5 @@ -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-dependences-analysis-type=value-based '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-dependences-analysis-type=value-based '-passes=polly-dce,print' -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE +; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE 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-n8:16:32:64" ; ; for(i = 0; i < 200; i++ ) diff --git a/polly/test/DeadCodeElimination/computeout.ll b/polly/test/DeadCodeElimination/computeout.ll index 2ac6b8cbbedf..51850d7da349 100644 --- a/polly/test/DeadCodeElimination/computeout.ll +++ b/polly/test/DeadCodeElimination/computeout.ll @@ -1,5 +1,6 @@ -; RUN: opt -S %loadPolly "-passes=scop(polly-dce,print)" < %s | FileCheck %s -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa "-passes=scop(polly-dce,print)" -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT +; RUN: opt -S %loadPolly -basic-aa -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt -S %loadNPMPolly "-passes=scop(polly-dce,print)" < %s | FileCheck %s +; RUN: opt -S %loadPolly -basic-aa -polly-dce -polly-print-ast -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT 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-n8:16:32:64" ; for(i = 0; i < 100; i++ ) diff --git a/polly/test/DeadCodeElimination/dead_iteration_elimination.ll b/polly/test/DeadCodeElimination/dead_iteration_elimination.ll index 4247ccbcd123..f496f7828e3d 100644 --- a/polly/test/DeadCodeElimination/dead_iteration_elimination.ll +++ b/polly/test/DeadCodeElimination/dead_iteration_elimination.ll @@ -1,4 +1,5 @@ -; RUN: opt -S %loadPolly "-passes=scop(polly-dce,print)" -polly-dependences-analysis-type=value-based -polly-dce-precise-steps=2 < %s | FileCheck %s +; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-dce -polly-dce-precise-steps=2 -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt -S %loadNPMPolly "-passes=scop(polly-dce,print)" -polly-dependences-analysis-type=value-based -polly-dce-precise-steps=2 < %s | 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-n8:16:32:64" ; ; for(i = 0; i < 200; i++ ) diff --git a/polly/test/DeadCodeElimination/non-affine-affine-mix.ll b/polly/test/DeadCodeElimination/non-affine-affine-mix.ll index e290d9997d96..e6a5dd204ca1 100644 --- a/polly/test/DeadCodeElimination/non-affine-affine-mix.ll +++ b/polly/test/DeadCodeElimination/non-affine-affine-mix.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=polly-dce,print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s ; ; void f(int *A) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/DeadCodeElimination/non-affine.ll b/polly/test/DeadCodeElimination/non-affine.ll index 8f437ef3e32a..38a7fcbcf9c9 100644 --- a/polly/test/DeadCodeElimination/non-affine.ll +++ b/polly/test/DeadCodeElimination/non-affine.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=polly-dce,print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s ; ; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1) ; diff --git a/polly/test/DeadCodeElimination/null_schedule.ll b/polly/test/DeadCodeElimination/null_schedule.ll index 13c8a127b173..633a84b5d92b 100644 --- a/polly/test/DeadCodeElimination/null_schedule.ll +++ b/polly/test/DeadCodeElimination/null_schedule.ll @@ -1,4 +1,4 @@ -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-dependences-analysis-type=value-based '-passes=polly-dce,print' -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE +; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-dce -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=CHECK-DCE 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-n8:16:32:64" ; A[0] = 1; ; diff --git a/polly/test/DependenceInfo/computeout.ll b/polly/test/DependenceInfo/computeout.ll index 0e64cd1a3725..048de29864d3 100644 --- a/polly/test/DependenceInfo/computeout.ll +++ b/polly/test/DependenceInfo/computeout.ll @@ -1,5 +1,7 @@ -; RUN: opt -S %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=VALUE -; RUN: opt -S %loadPolly '-passes=print' -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT +; RUN: opt -S %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s -check-prefix=VALUE +; RUN: opt -S %loadPolly -polly-print-function-dependences -disable-output < %s | FileCheck %s -check-prefix=FUNC-VALUE +; RUN: opt -S %loadPolly -polly-print-dependences -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT +; RUN: opt -S %loadPolly -polly-print-function-dependences -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT 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-n8:16:32:64" ; for(i = 0; i < 100; i++ ) diff --git a/polly/test/DependenceInfo/different_schedule_dimensions.ll b/polly/test/DependenceInfo/different_schedule_dimensions.ll index edb8371d6e68..3f966168d3b7 100644 --- a/polly/test/DependenceInfo/different_schedule_dimensions.ll +++ b/polly/test/DependenceInfo/different_schedule_dimensions.ll @@ -1,5 +1,7 @@ -; RUN: opt -S %loadPolly '-passes=print' \ +; RUN: opt -S %loadPolly -polly-print-dependences \ ; RUN: -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -polly-print-function-dependences \ +; RUN: -disable-output < %s | FileCheck %s -check-prefix=FUNC ; CHECK: RAW dependences: ; CHECK: { Stmt_bb9[0] -> Stmt_bb10[0] } diff --git a/polly/test/DependenceInfo/do_pluto_matmult.ll b/polly/test/DependenceInfo/do_pluto_matmult.ll index 9532f9c7fb12..d71608e80e70 100644 --- a/polly/test/DependenceInfo/do_pluto_matmult.ll +++ b/polly/test/DependenceInfo/do_pluto_matmult.ll @@ -1,5 +1,7 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-dependences-analysis-type=value-based -disable-output < %s | FileCheck %s -check-prefix=VALUE -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-dependences-analysis-type=memory-based -disable-output < %s | FileCheck %s -check-prefix=MEMORY +; RUN: opt %loadPolly -basic-aa -polly-print-dependences -polly-dependences-analysis-type=value-based -disable-output < %s | FileCheck %s -check-prefix=VALUE +; RUN: opt %loadPolly -basic-aa -polly-print-dependences -polly-dependences-analysis-type=memory-based -disable-output < %s | FileCheck %s -check-prefix=MEMORY +; RUN: opt %loadPolly -basic-aa -polly-print-function-dependences -polly-dependences-analysis-type=value-based -disable-output < %s | FileCheck %s -check-prefix=FUNC-VALUE +; RUN: opt %loadPolly -basic-aa -polly-print-function-dependences -polly-dependences-analysis-type=memory-based -disable-output < %s | FileCheck %s -check-prefix=FUNC-MEMORY 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-n8:16:32:64" diff --git a/polly/test/DependenceInfo/fine_grain_dep_0.ll b/polly/test/DependenceInfo/fine_grain_dep_0.ll index e7fc66882465..9c79e360690a 100644 --- a/polly/test/DependenceInfo/fine_grain_dep_0.ll +++ b/polly/test/DependenceInfo/fine_grain_dep_0.ll @@ -1,6 +1,7 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s --check-prefix=REF -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s --check-prefix=ACC - +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-dependences -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s --check-prefix=REF +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-dependences -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s --check-prefix=ACC +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-function-dependences -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s --check-prefix=ACC +; ; REF: RAW dependences: ; REF-NEXT: [N] -> { [Stmt_for_body[i0] -> MemRef_b[]] -> [Stmt_for_body[6 + i0] -> MemRef_b[]] : 0 <= i0 <= -13 + N; Stmt_for_body[i0] -> Stmt_for_body[6 + i0] : 0 <= i0 <= -13 + N; Stmt_for_body[i0] -> Stmt_for_body[4 + i0] : 0 <= i0 <= -11 + N; [Stmt_for_body[i0] -> MemRef_a[]] -> [Stmt_for_body[4 + i0] -> MemRef_a[]] : 0 <= i0 <= -11 + N } ; REF-NEXT: WAR dependences: diff --git a/polly/test/DependenceInfo/generate_may_write_dependence_info.ll b/polly/test/DependenceInfo/generate_may_write_dependence_info.ll index 7f6f5f3e3b94..0b7f2d48da9f 100644 --- a/polly/test/DependenceInfo/generate_may_write_dependence_info.ll +++ b/polly/test/DependenceInfo/generate_may_write_dependence_info.ll @@ -1,4 +1,4 @@ -; RUN: opt -S %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=VALUE +; RUN: opt -S %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s -check-prefix=VALUE target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ; for (int i = 0; i < N; i++) { diff --git a/polly/test/DependenceInfo/infeasible_context.ll b/polly/test/DependenceInfo/infeasible_context.ll index aab6072e4a45..d701b821e15c 100644 --- a/polly/test/DependenceInfo/infeasible_context.ll +++ b/polly/test/DependenceInfo/infeasible_context.ll @@ -1,9 +1,10 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s \ ; RUN: | FileCheck %s -check-prefix=FUNC-SCOP -; RUN: opt %loadPolly '-passes=print,scop(print)' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-function-dependences -disable-output < %s \ ; RUN: | FileCheck %s -check-prefix=FUNC-DEPS ; ; FUNC-SCOP-NOT: Statement +; FUNC-DEPS-LABEL: Printing analysis 'Polly - Calculate dependences for all the SCoPs of a function' for function 'readgeo' ; FUNC-DEPS-NOT: RAW dependences ; ; Due to an infeasible run-time check, scop object is empty and we do not compute dependences. diff --git a/polly/test/DependenceInfo/may_writes_do_not_block_must_writes_for_war.ll b/polly/test/DependenceInfo/may_writes_do_not_block_must_writes_for_war.ll index 662cb3232e7e..09c516274708 100644 --- a/polly/test/DependenceInfo/may_writes_do_not_block_must_writes_for_war.ll +++ b/polly/test/DependenceInfo/may_writes_do_not_block_must_writes_for_war.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; ; Verify that the presence of a may-write (S1) between a read (S0) and a ; must-write (S2) does not block the generation of RAW dependences. This makes diff --git a/polly/test/DependenceInfo/nonaffine-condition-buildMemoryAccess.ll b/polly/test/DependenceInfo/nonaffine-condition-buildMemoryAccess.ll index d8361a2b74a6..25c7e3d6e442 100644 --- a/polly/test/DependenceInfo/nonaffine-condition-buildMemoryAccess.ll +++ b/polly/test/DependenceInfo/nonaffine-condition-buildMemoryAccess.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -polly-allow-nonaffine-loops -polly-allow-nonaffine -debug-only=polly-dependence < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-allow-nonaffine-loops -polly-allow-nonaffine -debug-only=polly-dependence < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/DependenceInfo/reduction_complex_location.ll b/polly/test/DependenceInfo/reduction_complex_location.ll index 2c14f116c904..7ca839996326 100644 --- a/polly/test/DependenceInfo/reduction_complex_location.ll +++ b/polly/test/DependenceInfo/reduction_complex_location.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { } diff --git a/polly/test/DependenceInfo/reduction_dependences_equal_non_reduction_dependences.ll b/polly/test/DependenceInfo/reduction_dependences_equal_non_reduction_dependences.ll index e32217910fc7..3632bd202da2 100644 --- a/polly/test/DependenceInfo/reduction_dependences_equal_non_reduction_dependences.ll +++ b/polly/test/DependenceInfo/reduction_dependences_equal_non_reduction_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-dependences -disable-output < %s | FileCheck %s ; ; This loopnest contains a reduction which imposes the same dependences as the ; accesses to the array A. We need to ensure we keep the dependences of A. diff --git a/polly/test/DependenceInfo/reduction_dependences_not_null.ll b/polly/test/DependenceInfo/reduction_dependences_not_null.ll index 852f03cb6f70..69fd74478ecc 100644 --- a/polly/test/DependenceInfo/reduction_dependences_not_null.ll +++ b/polly/test/DependenceInfo/reduction_dependences_not_null.ll @@ -1,7 +1,7 @@ ; Test that the reduction dependences are always initialised, even in a case ; where we have no reduction. If this object is NULL, then isl operations on ; it will fail. -; RUN: opt -S %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -check-prefix=VALUE +; RUN: opt -S %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s -check-prefix=VALUE 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-n8:16:32:64" ; for(i = 0; i < 100; i++ ) diff --git a/polly/test/DependenceInfo/reduction_mixed_reduction_and_non_reduction_dependences.ll b/polly/test/DependenceInfo/reduction_mixed_reduction_and_non_reduction_dependences.ll index 4c78d80b8ceb..71903d9e7111 100644 --- a/polly/test/DependenceInfo/reduction_mixed_reduction_and_non_reduction_dependences.ll +++ b/polly/test/DependenceInfo/reduction_mixed_reduction_and_non_reduction_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_for_body3[i0, i1] -> Stmt_for_body3[i0 + i1, o1] : i0 >= 0 and 0 <= i1 <= 1023 - i0 and i1 <= 1 and 0 < o1 <= 511 } diff --git a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum.ll b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum.ll index 7e05265f6e6d..234de5c367a0 100644 --- a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum.ll +++ b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum.ll @@ -1,6 +1,6 @@ -; RUN: opt -aa-pipeline=basic-aa %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt -aa-pipeline=basic-aa %loadPolly '-passes=print' -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s -; RUN: opt -aa-pipeline=basic-aa %loadPolly '-passes=print' -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s +; RUN: opt -basic-aa %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s +; RUN: opt -basic-aa %loadPolly -polly-print-dependences -polly-dependences-analysis-level=reference-wise -disable-output < %s | FileCheck %s +; RUN: opt -basic-aa %loadPolly -polly-print-dependences -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s ; ; Verify that only the inner reduction like accesses cause reduction dependences ; diff --git a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_2.ll b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_2.ll index 7e8a66a50bfd..acd674dc0117 100644 --- a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_2.ll +++ b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -basic-aa -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { } diff --git a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_3.ll b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_3.ll index adb04f305993..bdfcfc99c8cb 100644 --- a/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_3.ll +++ b/polly/test/DependenceInfo/reduction_multiple_loops_array_sum_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -basic-aa -disable-output < %s | FileCheck %s ; ; CHECK: Reduction dependences: ; CHECK-NEXT: { Stmt_for_inc[i0, i1] -> Stmt_for_inc[i0, 1 + i1] : 0 <= i0 <= 99 and 0 <= i1 <= 98 } diff --git a/polly/test/DependenceInfo/reduction_multiple_reductions.ll b/polly/test/DependenceInfo/reduction_multiple_reductions.ll index 2d810915bada..cf705080e03d 100644 --- a/polly/test/DependenceInfo/reduction_multiple_reductions.ll +++ b/polly/test/DependenceInfo/reduction_multiple_reductions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-dependences -disable-output < %s | FileCheck %s ; ; Verify we do not have dependences between the if and the else clause ; diff --git a/polly/test/DependenceInfo/reduction_multiple_reductions_2.ll b/polly/test/DependenceInfo/reduction_multiple_reductions_2.ll index 326dcaee5f07..8d8557a129ab 100644 --- a/polly/test/DependenceInfo/reduction_multiple_reductions_2.ll +++ b/polly/test/DependenceInfo/reduction_multiple_reductions_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-dependences -disable-output < %s | FileCheck %s ; ; ; These are the important RAW dependences, as they need to originate/end in only one iteration: diff --git a/polly/test/DependenceInfo/reduction_only_reduction_like_access.ll b/polly/test/DependenceInfo/reduction_only_reduction_like_access.ll index 1e6455b264d3..7b4a68a2a897 100644 --- a/polly/test/DependenceInfo/reduction_only_reduction_like_access.ll +++ b/polly/test/DependenceInfo/reduction_only_reduction_like_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; ; FIXME: Change the comment once we allow different pointers ; The statement is "almost" reduction like but should not yield any reduction dependences diff --git a/polly/test/DependenceInfo/reduction_partially_escaping_intermediate_in_other_stmt.ll b/polly/test/DependenceInfo/reduction_partially_escaping_intermediate_in_other_stmt.ll index 158e6a29d8a7..0d09e5a861a0 100644 --- a/polly/test/DependenceInfo/reduction_partially_escaping_intermediate_in_other_stmt.ll +++ b/polly/test/DependenceInfo/reduction_partially_escaping_intermediate_in_other_stmt.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -basic-aa -disable-output < %s | FileCheck %s ; ; CHECK: Reduction dependences: ; CHECK-NEXT: [N] -> { Stmt_for_body3[i0, i1] -> Stmt_for_body3[i0, 1 + i1] : 0 <= i0 <= 1023 and i1 >= 0 and 1024 - N + i0 <= i1 <= 1022 } diff --git a/polly/test/DependenceInfo/reduction_privatization_deps.ll b/polly/test/DependenceInfo/reduction_privatization_deps.ll index 5d62b8f0a10a..ce90e21a898d 100644 --- a/polly/test/DependenceInfo/reduction_privatization_deps.ll +++ b/polly/test/DependenceInfo/reduction_privatization_deps.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_S1[i0, i1] -> Stmt_S2[-1 + i0 + i1] : 0 <= i0 <= 1023 and i1 >= 0 and -i0 < i1 <= 1024 - i0 and i1 <= 1023; Stmt_S0[i0] -> Stmt_S1[o0, i0 - o0] : i0 <= 1023 and 0 <= o0 <= i0 } diff --git a/polly/test/DependenceInfo/reduction_privatization_deps_2.ll b/polly/test/DependenceInfo/reduction_privatization_deps_2.ll index ed936bfb3b7f..4904004d4781 100644 --- a/polly/test/DependenceInfo/reduction_privatization_deps_2.ll +++ b/polly/test/DependenceInfo/reduction_privatization_deps_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; ; We have privatization dependences from a textually later statement to a ; textually earlier one, but the dependences still go forward in time. diff --git a/polly/test/DependenceInfo/reduction_privatization_deps_3.ll b/polly/test/DependenceInfo/reduction_privatization_deps_3.ll index 58ef9a4774b9..a3935ebd6cc4 100644 --- a/polly/test/DependenceInfo/reduction_privatization_deps_3.ll +++ b/polly/test/DependenceInfo/reduction_privatization_deps_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_S1[i0] -> Stmt_S3[2 + i0] : 0 <= i0 <= 96; Stmt_S2[i0, i1] -> Stmt_S3[o0] : i1 <= 1 - i0 and -i1 < o0 <= 1 and o0 <= 1 + i0 - i1; Stmt_S3[i0] -> Stmt_S2[o0, 1 - i0] : 0 <= i0 <= 1 and i0 < o0 <= 98 } diff --git a/polly/test/DependenceInfo/reduction_privatization_deps_4.ll b/polly/test/DependenceInfo/reduction_privatization_deps_4.ll index 3dad7b217486..10d726af5145 100644 --- a/polly/test/DependenceInfo/reduction_privatization_deps_4.ll +++ b/polly/test/DependenceInfo/reduction_privatization_deps_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0, i0] : 0 <= i0 <= 98; Stmt_S2[i0, i0] -> Stmt_S3[i0] : 0 <= i0 <= 98; Stmt_S3[i0] -> Stmt_S2[o0, i0] : i0 >= 0 and i0 < o0 <= 98; Stmt_S2[i0, i1] -> Stmt_S1[i1] : i0 >= 0 and i0 < i1 <= 98 } diff --git a/polly/test/DependenceInfo/reduction_privatization_deps_5.ll b/polly/test/DependenceInfo/reduction_privatization_deps_5.ll index 0c445d23a92d..e8d51181725e 100644 --- a/polly/test/DependenceInfo/reduction_privatization_deps_5.ll +++ b/polly/test/DependenceInfo/reduction_privatization_deps_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_S1[i0, 0] -> Stmt_S2[i0, 0] : 0 <= i0 <= 98; Stmt_S2[i0, 0] -> Stmt_S1[1 + i0, 0] : 0 <= i0 <= 97 } diff --git a/polly/test/DependenceInfo/reduction_sequence.ll b/polly/test/DependenceInfo/reduction_sequence.ll index 7e1ebd4ab67c..4a4688953938 100644 --- a/polly/test/DependenceInfo/reduction_sequence.ll +++ b/polly/test/DependenceInfo/reduction_sequence.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; void manyreductions(long *A) { ; for (long i = 0; i < 1024; i++) diff --git a/polly/test/DependenceInfo/reduction_simple_iv.ll b/polly/test/DependenceInfo/reduction_simple_iv.ll index 64f6de22b078..e3307afae08b 100644 --- a/polly/test/DependenceInfo/reduction_simple_iv.ll +++ b/polly/test/DependenceInfo/reduction_simple_iv.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { } diff --git a/polly/test/DependenceInfo/reduction_simple_iv_debug_wrapped_dependences.ll b/polly/test/DependenceInfo/reduction_simple_iv_debug_wrapped_dependences.ll index 61ee3dbc5b02..c7651c39a563 100644 --- a/polly/test/DependenceInfo/reduction_simple_iv_debug_wrapped_dependences.ll +++ b/polly/test/DependenceInfo/reduction_simple_iv_debug_wrapped_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -debug-only=polly-dependence -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -debug-only=polly-dependence -disable-output < %s 2>&1 | FileCheck %s ; ; REQUIRES: asserts ; diff --git a/polly/test/DependenceInfo/reduction_simple_privatization_deps_2.ll b/polly/test/DependenceInfo/reduction_simple_privatization_deps_2.ll index a181d2acb651..b61fd8453a8c 100644 --- a/polly/test/DependenceInfo/reduction_simple_privatization_deps_2.ll +++ b/polly/test/DependenceInfo/reduction_simple_privatization_deps_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { Stmt_S1[i0, i1] -> Stmt_S2[i0] : 0 <= i0 <= 99 and 0 <= i1 <= 99; Stmt_S0[i0] -> Stmt_S1[i0, o1] : 0 <= i0 <= 99 and 0 <= o1 <= 99; Stmt_S2[i0] -> Stmt_S0[1 + i0] : 0 <= i0 <= 98 } diff --git a/polly/test/DependenceInfo/reduction_simple_privatization_deps_w_parameter.ll b/polly/test/DependenceInfo/reduction_simple_privatization_deps_w_parameter.ll index ffa26b5eb76c..a3a87c70d905 100644 --- a/polly/test/DependenceInfo/reduction_simple_privatization_deps_w_parameter.ll +++ b/polly/test/DependenceInfo/reduction_simple_privatization_deps_w_parameter.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: [N] -> { Stmt_S1[i0] -> Stmt_S2[] : N >= 11 and 0 <= i0 <= 1023; Stmt_S0[] -> Stmt_S1[o0] : N >= 11 and 0 <= o0 <= 1023 } diff --git a/polly/test/DependenceInfo/reduction_two_reductions_different_rloops.ll b/polly/test/DependenceInfo/reduction_two_reductions_different_rloops.ll index 25d117d4cbf9..c90462962ce0 100644 --- a/polly/test/DependenceInfo/reduction_two_reductions_different_rloops.ll +++ b/polly/test/DependenceInfo/reduction_two_reductions_different_rloops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-dependences -disable-output < %s | FileCheck %s ; ; CHECK: RAW dependences: ; CHECK-NEXT: { } diff --git a/polly/test/DependenceInfo/sequential_loops.ll b/polly/test/DependenceInfo/sequential_loops.ll index 14c9a6429c67..8dfa13cb9db8 100644 --- a/polly/test/DependenceInfo/sequential_loops.ll +++ b/polly/test/DependenceInfo/sequential_loops.ll @@ -1,43 +1,34 @@ -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-dependences-analysis-type=value-based -disable-output < %s | FileCheck %s -check-prefix=VALUE -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-dependences-analysis-type=memory-based -disable-output < %s | FileCheck %s -check-prefix=MEMORY -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s -check-prefix=VALUE_ACCESS +; RUN: opt -S %loadPolly -basic-aa -polly-print-dependences -polly-dependences-analysis-type=value-based -disable-output < %s | FileCheck %s -check-prefix=VALUE +; RUN: opt -S %loadPolly -basic-aa -polly-print-dependences -polly-dependences-analysis-type=memory-based -disable-output < %s | FileCheck %s -check-prefix=MEMORY +; RUN: opt -S %loadPolly -basic-aa -polly-print-dependences -polly-dependences-analysis-type=value-based -polly-dependences-analysis-level=access-wise -disable-output < %s | FileCheck %s -check-prefix=VALUE_ACCESS -; VALUE: RAW dependences: +; VALUE-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'sequential_writes': +; VALUE-NEXT: RAW dependences: ; VALUE-NEXT: { } ; VALUE-NEXT: WAR dependences: ; VALUE-NEXT: { } ; VALUE-NEXT: WAW dependences: ; VALUE-NEXT: { Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99; Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9 } ; -; VALUE: RAW dependences: -; VALUE-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99 } -; VALUE-NEXT: WAR dependences: -; VALUE-NEXT: { } -; VALUE-NEXT: WAW dependences: -; VALUE-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9 } -; -; VALUE: RAW dependences: -; VALUE-NEXT: { } -; VALUE-NEXT: WAR dependences: -; VALUE-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99 } -; VALUE-NEXT: WAW dependences: -; VALUE-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9 } -; -; VALUE: RAW dependences: -; VALUE-NEXT: [p] -> { Stmt_S1[i0] -> Stmt_S2[-p + i0] : i0 >= p and 0 <= i0 <= 99 and i0 <= 9 + p } -; VALUE-NEXT: WAR dependences: -; VALUE-NEXT: [p] -> { } -; VALUE-NEXT: WAW dependences: -; VALUE-NEXT: [p] -> { } -; -;VALUE_ACCESS: RAW dependences: +;VALUE_ACCESS-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'sequential_writes': +;VALUE_ACCESS-NEXT: RAW dependences: ;VALUE_ACCESS-NEXT: { } ;VALUE_ACCESS-NEXT: WAR dependences: ;VALUE_ACCESS-NEXT: { } ;VALUE_ACCESS-NEXT: WAW dependences: ;VALUE_ACCESS-NEXT: { Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99; Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; [Stmt_S2[i0] -> Stmt_S2_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Write0[]] : 0 <= i0 <= 9; Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S2[i0] -> Stmt_S2_Write0[]] : 0 <= i0 <= 9; [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Write0[]] : 10 <= i0 <= 99 } + ; -;VALUE_ACCESS: RAW dependences: +; VALUE-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'read_after_writes': +; VALUE-NEXT: RAW dependences: +; VALUE-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99 } +; VALUE-NEXT: WAR dependences: +; VALUE-NEXT: { } +; VALUE-NEXT: WAW dependences: +; VALUE-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9 } +; +;VALUE_ACCESS-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'read_after_writes': +;VALUE_ACCESS-NEXT: RAW dependences: ;VALUE_ACCESS-NEXT: { Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99; Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; [Stmt_S2[i0] -> Stmt_S2_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Read0[]] : 0 <= i0 <= 9; [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Read0[]] : 10 <= i0 <= 99 } ;VALUE_ACCESS-NEXT: WAR dependences: @@ -45,42 +36,64 @@ ;VALUE_ACCESS-NEXT: WAW dependences: ;VALUE_ACCESS-NEXT: { [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S2[i0] -> Stmt_S2_Write0[]] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9 } ; -;VALUE_ACCESS: RAW dependences: +; VALUE-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'write_after_read': +; VALUE-NEXT: RAW dependences: +; VALUE-NEXT: { } +; VALUE-NEXT: WAR dependences: +; VALUE-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99 } +; VALUE-NEXT: WAW dependences: +; VALUE-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9 } +; +;VALUE_ACCESS-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'write_after_read': +;VALUE_ACCESS-NEXT: RAW dependences: ;VALUE_ACCESS-NEXT: { } ;VALUE_ACCESS-NEXT: WAR dependences: ;VALUE_ACCESS-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 10 <= i0 <= 99; [Stmt_S1[i0] -> Stmt_S1_Read0[]] -> [Stmt_S2[i0] -> Stmt_S2_Write0[]] : 0 <= i0 <= 9; [Stmt_S1[i0] -> Stmt_S1_Read0[]] -> [Stmt_S3[i0] -> Stmt_S3_Write0[]] : 10 <= i0 <= 99 } ;VALUE_ACCESS-NEXT: WAW dependences: ;VALUE_ACCESS-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; [Stmt_S2[i0] -> Stmt_S2_Write0[]] -> [Stmt_S3[i0] -> Stmt_S3_Write0[]] : 0 <= i0 <= 9 } ; -;VALUE_ACCESS: RAW dependences: +; VALUE-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.2' in function 'parametric_offset': +; VALUE-NEXT: RAW dependences: +; VALUE-NEXT: [p] -> { Stmt_S1[i0] -> Stmt_S2[-p + i0] : i0 >= p and 0 <= i0 <= 99 and i0 <= 9 + p } +; VALUE-NEXT: WAR dependences: +; VALUE-NEXT: [p] -> { } +; VALUE-NEXT: WAW dependences: +; VALUE-NEXT: [p] -> { } +; +;VALUE_ACCESS-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.2' in function 'parametric_offset': +;VALUE_ACCESS-NEXT: RAW dependences: ;VALUE_ACCESS-NEXT: [p] -> { Stmt_S1[i0] -> Stmt_S2[-p + i0] : i0 >= p and 0 <= i0 <= 99 and i0 <= 9 + p; [Stmt_S1[i0] -> Stmt_S1_Write0[]] -> [Stmt_S2[-p + i0] -> Stmt_S2_Read0[]] : i0 >= p and 0 <= i0 <= 99 and i0 <= 9 + p } ;VALUE_ACCESS-NEXT: WAR dependences: ;VALUE_ACCESS-NEXT: [p] -> { } ;VALUE_ACCESS-NEXT: WAW dependences: ;VALUE_ACCESS-NEXT: [p] -> { } -; MEMORY: RAW dependences: +; MEMORY-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'sequential_writes': +; MEMORY-NEXT: RAW dependences: ; MEMORY-NEXT: { } ; MEMORY-NEXT: WAR dependences: ; MEMORY-NEXT: { } ; MEMORY-NEXT: WAW dependences: ; MEMORY-NEXT: { Stmt_S1[i0] -> Stmt_S3[i0] : 0 <= i0 <= 99; Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9 } ; -; MEMORY: RAW dependences: +; MEMORY-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'read_after_writes': +; MEMORY-NEXT: RAW dependences: ; MEMORY-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 0 <= i0 <= 99 } ; MEMORY-NEXT: WAR dependences: ; MEMORY-NEXT: { } ; MEMORY-NEXT: WAW dependences: ; MEMORY-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9 } ; -; MEMORY: RAW dependences: +; MEMORY-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.3' in function 'write_after_read': +; MEMORY-NEXT: RAW dependences: ; MEMORY-NEXT: { } ; MEMORY-NEXT: WAR dependences: ; MEMORY-NEXT: { Stmt_S1[i0] -> Stmt_S2[i0] : 0 <= i0 <= 9; Stmt_S1[i0] -> Stmt_S3[i0] : 0 <= i0 <= 99 } ; MEMORY-NEXT: WAW dependences: ; MEMORY-NEXT: { Stmt_S2[i0] -> Stmt_S3[i0] : 0 <= i0 <= 9 } ; -; MEMORY: RAW dependences: +; MEMORY-LABEL: Printing analysis 'Polly - Calculate dependences' for region: 'S1 => exit.2' in function 'parametric_offset': +; MEMORY-NEXT: RAW dependences: ; MEMORY-NEXT: [p] -> { Stmt_S1[i0] -> Stmt_S2[-p + i0] : i0 >= p and 0 <= i0 <= 99 and i0 <= 9 + p } ; MEMORY-NEXT: WAR dependences: ; MEMORY-NEXT: [p] -> { } diff --git a/polly/test/ForwardOpTree/atax.ll b/polly/test/ForwardOpTree/atax.ll index 7cc40fe7e1cb..0690c1b000fa 100644 --- a/polly/test/ForwardOpTree/atax.ll +++ b/polly/test/ForwardOpTree/atax.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-optree-normalize-phi=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-optree-normalize-phi=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ForwardOpTree/changed-kind.ll b/polly/test/ForwardOpTree/changed-kind.ll index 3c3d7f738779..a1d59825b3b2 100644 --- a/polly/test/ForwardOpTree/changed-kind.ll +++ b/polly/test/ForwardOpTree/changed-kind.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; In the code below, %0 is known to be equal to the content of @c (constant 0). ; Thus, in order to save a scalar dependency, forward-optree replaces diff --git a/polly/test/ForwardOpTree/forward_from_region.ll b/polly/test/ForwardOpTree/forward_from_region.ll index 90448d800286..53d22800081e 100644 --- a/polly/test/ForwardOpTree/forward_from_region.ll +++ b/polly/test/ForwardOpTree/forward_from_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Move instructions from region statements. ; diff --git a/polly/test/ForwardOpTree/forward_hoisted.ll b/polly/test/ForwardOpTree/forward_hoisted.ll index 163d43f56e8a..32fca00141dd 100644 --- a/polly/test/ForwardOpTree/forward_hoisted.ll +++ b/polly/test/ForwardOpTree/forward_hoisted.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Move %val to %bodyB, so %bodyA can be removed (by -polly-simplify). ; This involves making the load-hoisted %val1 to be made available in %bodyB. diff --git a/polly/test/ForwardOpTree/forward_instruction.ll b/polly/test/ForwardOpTree/forward_instruction.ll index 6269e359a59a..1dcd64357324 100644 --- a/polly/test/ForwardOpTree/forward_instruction.ll +++ b/polly/test/ForwardOpTree/forward_instruction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Move %val to %bodyB, so %bodyA can be removed (by -polly-simplify) ; diff --git a/polly/test/ForwardOpTree/forward_into_region.ll b/polly/test/ForwardOpTree/forward_into_region.ll index be102a9574dc..dd18cfe5e61a 100644 --- a/polly/test/ForwardOpTree/forward_into_region.ll +++ b/polly/test/ForwardOpTree/forward_into_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Move instructions to region statements. ; diff --git a/polly/test/ForwardOpTree/forward_into_region_redundant_use.ll b/polly/test/ForwardOpTree/forward_into_region_redundant_use.ll index 883a784230d9..e5458c027880 100644 --- a/polly/test/ForwardOpTree/forward_into_region_redundant_use.ll +++ b/polly/test/ForwardOpTree/forward_into_region_redundant_use.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; define void @foo(ptr %A, i32 %p, ptr %B) { diff --git a/polly/test/ForwardOpTree/forward_load.ll b/polly/test/ForwardOpTree/forward_load.ll index dec6812aade5..86e3cb0203fa 100644 --- a/polly/test/ForwardOpTree/forward_load.ll +++ b/polly/test/ForwardOpTree/forward_load.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load. ; diff --git a/polly/test/ForwardOpTree/forward_load_differentarray.ll b/polly/test/ForwardOpTree/forward_load_differentarray.ll index a3ca0bad54ab..786277bdeb87 100644 --- a/polly/test/ForwardOpTree/forward_load_differentarray.ll +++ b/polly/test/ForwardOpTree/forward_load_differentarray.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; To forward %val, B[j] cannot be reused in bodyC because it is overwritten ; between. Verify that instead the alternative C[j] is used. diff --git a/polly/test/ForwardOpTree/forward_load_double_write.ll b/polly/test/ForwardOpTree/forward_load_double_write.ll index b0fbb69dc7ae..1618722381fc 100644 --- a/polly/test/ForwardOpTree/forward_load_double_write.ll +++ b/polly/test/ForwardOpTree/forward_load_double_write.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load even in case two writes of identical values are in ; one scop statement. diff --git a/polly/test/ForwardOpTree/forward_load_fromloop.ll b/polly/test/ForwardOpTree/forward_load_fromloop.ll index 62351883a189..8f08a1356c38 100644 --- a/polly/test/ForwardOpTree/forward_load_fromloop.ll +++ b/polly/test/ForwardOpTree/forward_load_fromloop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Forward a the LoadInst %val into %bodyB. %val is executed multiple times, ; we must get the last loaded values. diff --git a/polly/test/ForwardOpTree/forward_load_indirect.ll b/polly/test/ForwardOpTree/forward_load_indirect.ll index c8144861abc4..f83af61e6741 100644 --- a/polly/test/ForwardOpTree/forward_load_indirect.ll +++ b/polly/test/ForwardOpTree/forward_load_indirect.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Forward an operand tree consisting of a speculatable instruction (%add) ; and a load (%val). diff --git a/polly/test/ForwardOpTree/forward_load_memset_after.ll b/polly/test/ForwardOpTree/forward_load_memset_after.ll index 22a2ddf94888..13797a44c862 100644 --- a/polly/test/ForwardOpTree/forward_load_memset_after.ll +++ b/polly/test/ForwardOpTree/forward_load_memset_after.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load in the presence of a non-store WRITE access. ; diff --git a/polly/test/ForwardOpTree/forward_load_memset_before.ll b/polly/test/ForwardOpTree/forward_load_memset_before.ll index 3d3c90e941d6..60b1e076b980 100644 --- a/polly/test/ForwardOpTree/forward_load_memset_before.ll +++ b/polly/test/ForwardOpTree/forward_load_memset_before.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load in the presence of a non-store WRITE access. ; diff --git a/polly/test/ForwardOpTree/forward_load_tripleuse.ll b/polly/test/ForwardOpTree/forward_load_tripleuse.ll index 03a47360c362..1d0df2a22e87 100644 --- a/polly/test/ForwardOpTree/forward_load_tripleuse.ll +++ b/polly/test/ForwardOpTree/forward_load_tripleuse.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print,polly-codegen' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-optree -polly-codegen -disable-output < %s | FileCheck %s -match-full-lines ; ; %val1 is used three times: Twice by its own operand tree of %val2 and once ; more by the store in %bodyB. diff --git a/polly/test/ForwardOpTree/forward_load_unrelatedunusual.ll b/polly/test/ForwardOpTree/forward_load_unrelatedunusual.ll index dbeebbc27eba..b7bae5628986 100644 --- a/polly/test/ForwardOpTree/forward_load_unrelatedunusual.ll +++ b/polly/test/ForwardOpTree/forward_load_unrelatedunusual.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load. ; The non-analyzable store to C[0] is unrelated and can be ignored. diff --git a/polly/test/ForwardOpTree/forward_phi_load.ll b/polly/test/ForwardOpTree/forward_phi_load.ll index 029261f269c3..0b0bb209a3ef 100644 --- a/polly/test/ForwardOpTree/forward_phi_load.ll +++ b/polly/test/ForwardOpTree/forward_phi_load.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-optree-normalize-phi=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-optree-normalize-phi=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load. ; diff --git a/polly/test/ForwardOpTree/forward_readonly.ll b/polly/test/ForwardOpTree/forward_readonly.ll index 7ded946a6ff8..a29c5bff5d70 100644 --- a/polly/test/ForwardOpTree/forward_readonly.ll +++ b/polly/test/ForwardOpTree/forward_readonly.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-analyze-read-only-scalars=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines -check-prefixes=STATS,MODEL -; RUN: opt %loadPolly -polly-analyze-read-only-scalars=false '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines -check-prefixes=STATS,NOMODEL +; RUN: opt %loadPolly -polly-analyze-read-only-scalars=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines -check-prefixes=STATS,MODEL +; RUN: opt %loadPolly -polly-analyze-read-only-scalars=false -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines -check-prefixes=STATS,NOMODEL ; ; Move %val to %bodyB, so %bodyA can be removed (by -polly-simplify) ; diff --git a/polly/test/ForwardOpTree/forward_reusue.ll b/polly/test/ForwardOpTree/forward_reusue.ll index 1151aa94e1f9..ead8c7379803 100644 --- a/polly/test/ForwardOpTree/forward_reusue.ll +++ b/polly/test/ForwardOpTree/forward_reusue.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Move operand tree without duplicating values used multiple times. ; diff --git a/polly/test/ForwardOpTree/forward_store.ll b/polly/test/ForwardOpTree/forward_store.ll index e02c6891f436..a6369eb303c1 100644 --- a/polly/test/ForwardOpTree/forward_store.ll +++ b/polly/test/ForwardOpTree/forward_store.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Rematerialize a load. ; diff --git a/polly/test/ForwardOpTree/forward_synthesizable_definloop.ll b/polly/test/ForwardOpTree/forward_synthesizable_definloop.ll index 90e489ad6f54..f0da9320c43f 100644 --- a/polly/test/ForwardOpTree/forward_synthesizable_definloop.ll +++ b/polly/test/ForwardOpTree/forward_synthesizable_definloop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Copy %val to bodyB, assuming the exit value of %i. ; diff --git a/polly/test/ForwardOpTree/forward_synthesizable_indvar.ll b/polly/test/ForwardOpTree/forward_synthesizable_indvar.ll index 395e68482657..a38ab543e255 100644 --- a/polly/test/ForwardOpTree/forward_synthesizable_indvar.ll +++ b/polly/test/ForwardOpTree/forward_synthesizable_indvar.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Test support for (synthesizable) inducation variables. ; diff --git a/polly/test/ForwardOpTree/forward_synthesizable_useinloop.ll b/polly/test/ForwardOpTree/forward_synthesizable_useinloop.ll index a45d420e5c20..bb1760ae0ffb 100644 --- a/polly/test/ForwardOpTree/forward_synthesizable_useinloop.ll +++ b/polly/test/ForwardOpTree/forward_synthesizable_useinloop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Synthesizable values defined outside of a loop can be used ; inside the loop. diff --git a/polly/test/ForwardOpTree/forward_transitive.ll b/polly/test/ForwardOpTree/forward_transitive.ll index 69cfb555f315..243889437149 100644 --- a/polly/test/ForwardOpTree/forward_transitive.ll +++ b/polly/test/ForwardOpTree/forward_transitive.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Move %v and %val to %bodyB, so %bodyA can be removed (by -polly-simplify) ; diff --git a/polly/test/ForwardOpTree/jacobi-1d.ll b/polly/test/ForwardOpTree/jacobi-1d.ll index dbc051dde425..05ccd998c1a2 100644 --- a/polly/test/ForwardOpTree/jacobi-1d.ll +++ b/polly/test/ForwardOpTree/jacobi-1d.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-optree-normalize-phi=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-optree-normalize-phi=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ForwardOpTree/noforward_from_region.ll b/polly/test/ForwardOpTree/noforward_from_region.ll index 11d4312ad3bc..30150912f32e 100644 --- a/polly/test/ForwardOpTree/noforward_from_region.ll +++ b/polly/test/ForwardOpTree/noforward_from_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Ensure we do not move instructions from region statements in case the ; instruction to move loads from an array which is also written to from diff --git a/polly/test/ForwardOpTree/noforward_load_conditional.ll b/polly/test/ForwardOpTree/noforward_load_conditional.ll index 053134196001..eaa0fc52186b 100644 --- a/polly/test/ForwardOpTree/noforward_load_conditional.ll +++ b/polly/test/ForwardOpTree/noforward_load_conditional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; B[j] is overwritten by at least one statement between the ; definition of %val and its use. Hence, it cannot be forwarded. diff --git a/polly/test/ForwardOpTree/noforward_load_writebetween.ll b/polly/test/ForwardOpTree/noforward_load_writebetween.ll index 4a281b66c618..e2272c1c1f13 100644 --- a/polly/test/ForwardOpTree/noforward_load_writebetween.ll +++ b/polly/test/ForwardOpTree/noforward_load_writebetween.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Cannot rematerialize %val from B[0] at bodyC because B[0] has been ; overwritten in bodyB. diff --git a/polly/test/ForwardOpTree/noforward_outofquota.ll b/polly/test/ForwardOpTree/noforward_outofquota.ll index 9c17349fb9e2..2ec965d71184 100644 --- a/polly/test/ForwardOpTree/noforward_outofquota.ll +++ b/polly/test/ForwardOpTree/noforward_outofquota.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-optree-max-ops=1 '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines -; RUN: opt %loadPolly -polly-optree-max-ops=1 -passes=polly-optree -disable-output -stats < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=STATS +; RUN: opt %loadPolly -polly-optree-max-ops=1 -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-optree-max-ops=1 -polly-optree -disable-output -stats < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=STATS ; REQUIRES: asserts ; ; for (int j = 0; j < n; j += 1) { diff --git a/polly/test/ForwardOpTree/noforward_partial.ll b/polly/test/ForwardOpTree/noforward_partial.ll index 67bda40337e0..127ac9ff5f14 100644 --- a/polly/test/ForwardOpTree/noforward_partial.ll +++ b/polly/test/ForwardOpTree/noforward_partial.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Not the entire operand tree can be forwarded, ; some scalar dependencies would remain. diff --git a/polly/test/ForwardOpTree/noforward_phi.ll b/polly/test/ForwardOpTree/noforward_phi.ll index 455edfd1a831..58d41a410d3b 100644 --- a/polly/test/ForwardOpTree/noforward_phi.ll +++ b/polly/test/ForwardOpTree/noforward_phi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Do not move PHI nodes. ; diff --git a/polly/test/ForwardOpTree/noforward_selfrefphi.ll b/polly/test/ForwardOpTree/noforward_selfrefphi.ll index e7ab21b6ba28..b2d4dc51c978 100644 --- a/polly/test/ForwardOpTree/noforward_selfrefphi.ll +++ b/polly/test/ForwardOpTree/noforward_selfrefphi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-optree-normalize-phi=true '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-optree-normalize-phi=true -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Contains a self-referencing PHINode that would require a ; transitive closure to handle. diff --git a/polly/test/ForwardOpTree/noforward_sideffects.ll b/polly/test/ForwardOpTree/noforward_sideffects.ll index 0298da90e4ac..a5633769f670 100644 --- a/polly/test/ForwardOpTree/noforward_sideffects.ll +++ b/polly/test/ForwardOpTree/noforward_sideffects.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Do not forward instructions with side-effects (here: function call). ; diff --git a/polly/test/ForwardOpTree/noforward_synthesizable_unknownit.ll b/polly/test/ForwardOpTree/noforward_synthesizable_unknownit.ll index 159972345bdc..f589fde6e415 100644 --- a/polly/test/ForwardOpTree/noforward_synthesizable_unknownit.ll +++ b/polly/test/ForwardOpTree/noforward_synthesizable_unknownit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-optree -disable-output < %s | FileCheck %s -match-full-lines ; ; Do not try to forward %i.trunc, it is not synthesizable in %body. ; diff --git a/polly/test/ForwardOpTree/out-of-quota1.ll b/polly/test/ForwardOpTree/out-of-quota1.ll index 5a69f6c3ad60..7afdb8e60244 100644 --- a/polly/test/ForwardOpTree/out-of-quota1.ll +++ b/polly/test/ForwardOpTree/out-of-quota1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-optree -disable-output %s | FileCheck %s ; This used to loop infinitely because of UINT_MAX returned by ISL on out-of-quota. diff --git a/polly/test/IstAstInfo/alias_checks_with_empty_context.ll b/polly/test/IstAstInfo/alias_checks_with_empty_context.ll index d64f7529135e..9b95cd5b4bbd 100644 --- a/polly/test/IstAstInfo/alias_checks_with_empty_context.ll +++ b/polly/test/IstAstInfo/alias_checks_with_empty_context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s \ +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s \ ; RUN: | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/IstAstInfo/alias_simple_1.ll b/polly/test/IstAstInfo/alias_simple_1.ll index 659c17879ed5..83d470c2d19b 100644 --- a/polly/test/IstAstInfo/alias_simple_1.ll +++ b/polly/test/IstAstInfo/alias_simple_1.ll @@ -1,8 +1,8 @@ -; RUN: opt %loadPolly '-passes=print' -aa-pipeline= -disable-output < %s | FileCheck %s --check-prefix=NOAA -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s --check-prefix=BASI -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -disable-output < %s | FileCheck %s --check-prefix=NOAA +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=BASI +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB ; ; int A[1024]; ; diff --git a/polly/test/IstAstInfo/alias_simple_2.ll b/polly/test/IstAstInfo/alias_simple_2.ll index 569fe45e1e02..bbf528f93b47 100644 --- a/polly/test/IstAstInfo/alias_simple_2.ll +++ b/polly/test/IstAstInfo/alias_simple_2.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadPolly '-passes=print' -aa-pipeline= -disable-output < %s | FileCheck %s --check-prefix=NOAA -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s --check-prefix=BASI -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=globals-aa -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -disable-output < %s | FileCheck %s --check-prefix=NOAA +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=BASI +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -globals-aa -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE ; ; int A[1024], B[1024]; ; diff --git a/polly/test/IstAstInfo/alias_simple_3.ll b/polly/test/IstAstInfo/alias_simple_3.ll index 8bad170eda79..9067521323ab 100644 --- a/polly/test/IstAstInfo/alias_simple_3.ll +++ b/polly/test/IstAstInfo/alias_simple_3.ll @@ -1,8 +1,8 @@ -; RUN: opt %loadPolly '-passes=print' -aa-pipeline= -disable-output < %s | FileCheck %s --check-prefix=NOAA -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=basic-aa -disable-output < %s | FileCheck %s --check-prefix=BASI -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -disable-output < %s | FileCheck %s --check-prefix=NOAA +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=BASI +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -scev-aa -disable-output < %s | FileCheck %s --check-prefix=SCEV +; RUN: opt %loadPolly -polly-print-ast -disable-basic-aa -globals-aa -disable-output < %s | FileCheck %s --check-prefix=GLOB ; ; int A[1024]; ; float B[1024]; diff --git a/polly/test/IstAstInfo/aliasing_arrays_with_identical_base.ll b/polly/test/IstAstInfo/aliasing_arrays_with_identical_base.ll index 2bf71fb8fd2c..0cabd20168ba 100644 --- a/polly/test/IstAstInfo/aliasing_arrays_with_identical_base.ll +++ b/polly/test/IstAstInfo/aliasing_arrays_with_identical_base.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s \ +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/IstAstInfo/aliasing_multiple_alias_groups.ll b/polly/test/IstAstInfo/aliasing_multiple_alias_groups.ll index 6cdc5b0fdcec..b824c211fd31 100644 --- a/polly/test/IstAstInfo/aliasing_multiple_alias_groups.ll +++ b/polly/test/IstAstInfo/aliasing_multiple_alias_groups.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -aa-pipeline= -disable-output < %s | FileCheck %s --check-prefix=NOAA -; RUN: opt %loadPolly '-passes=print' -aa-pipeline=tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=NOAA +; RUN: opt %loadPolly -polly-print-ast -tbaa -disable-output < %s | FileCheck %s --check-prefix=TBAA ; ; void jd(int *Int0, int *Int1, float *Float0, float *Float1) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/IstAstInfo/aliasing_parametric_simple_1.ll b/polly/test/IstAstInfo/aliasing_parametric_simple_1.ll index a63854d94b68..e0c3255dd766 100644 --- a/polly/test/IstAstInfo/aliasing_parametric_simple_1.ll +++ b/polly/test/IstAstInfo/aliasing_parametric_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output %s | FileCheck %s ; ; void jd(int *A, int *B, int c) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/IstAstInfo/aliasing_parametric_simple_2.ll b/polly/test/IstAstInfo/aliasing_parametric_simple_2.ll index 7b2d163d54a2..74bad6c75784 100644 --- a/polly/test/IstAstInfo/aliasing_parametric_simple_2.ll +++ b/polly/test/IstAstInfo/aliasing_parametric_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ; ; void jd(int *A, int *B, int c) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/IstAstInfo/dependence_distance_minimal.ll b/polly/test/IstAstInfo/dependence_distance_minimal.ll index 4a77123e5031..c6b1d156e55d 100644 --- a/polly/test/IstAstInfo/dependence_distance_minimal.ll +++ b/polly/test/IstAstInfo/dependence_distance_minimal.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; The minimal dependence distance of the innermost loop should be 1 instead of 250. ; CHECK: #pragma minimal dependence distance: 1 diff --git a/polly/test/IstAstInfo/domain_bounded_only_with_context.ll b/polly/test/IstAstInfo/domain_bounded_only_with_context.ll index bcf6fd394209..32cebd7a3a8b 100644 --- a/polly/test/IstAstInfo/domain_bounded_only_with_context.ll +++ b/polly/test/IstAstInfo/domain_bounded_only_with_context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ; CHECK: { ; CHECK-NEXT: if (p <= -1 || p >= 1) diff --git a/polly/test/IstAstInfo/non_affine_access.ll b/polly/test/IstAstInfo/non_affine_access.ll index b3f669ee4670..d8757b2e21cf 100644 --- a/polly/test/IstAstInfo/non_affine_access.ll +++ b/polly/test/IstAstInfo/non_affine_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-ast-print-accesses -polly-allow-nonaffine -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-ast-print-accesses -polly-allow-nonaffine -disable-output < %s | FileCheck %s ; ; void non_affine_access(float A[]) { ; for (long i = 0; i < 1024; i++) diff --git a/polly/test/IstAstInfo/reduction_clauses_onedimensional_access.ll b/polly/test/IstAstInfo/reduction_clauses_onedimensional_access.ll index ea47e63bb7a6..8d52e345a76d 100644 --- a/polly/test/IstAstInfo/reduction_clauses_onedimensional_access.ll +++ b/polly/test/IstAstInfo/reduction_clauses_onedimensional_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: #pragma known-parallel reduction (^ : MemRef_sum) ; void f(int N, int M, int *sum) { diff --git a/polly/test/IstAstInfo/reduction_dependences_equal_non_reduction_dependences.ll b/polly/test/IstAstInfo/reduction_dependences_equal_non_reduction_dependences.ll index 6650fc034f87..9c6eea6aaa1e 100644 --- a/polly/test/IstAstInfo/reduction_dependences_equal_non_reduction_dependences.ll +++ b/polly/test/IstAstInfo/reduction_dependences_equal_non_reduction_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; This loopnest contains a reduction which imposes the same dependences as the ; accesses to the array A. We need to ensure we do __not__ parallelize anything diff --git a/polly/test/IstAstInfo/reduction_different_reduction_clauses.ll b/polly/test/IstAstInfo/reduction_different_reduction_clauses.ll index d89953cdd2fb..5104f716d810 100644 --- a/polly/test/IstAstInfo/reduction_different_reduction_clauses.ll +++ b/polly/test/IstAstInfo/reduction_different_reduction_clauses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: #pragma simd reduction (+ : MemRef_sum{{[1,2]}}, MemRef_sum{{[1,2]}}) reduction (* : MemRef_prod) reduction (| : MemRef_or) reduction (& : MemRef_and) ; CHECK: #pragma known-parallel reduction (+ : MemRef_sum{{[1,2]}}, MemRef_sum{{[1,2]}}) reduction (* : MemRef_prod) reduction (| : MemRef_or) reduction (& : MemRef_and) diff --git a/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule.ll b/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule.ll index a8ce13b4c56d..8a42cf8bd165 100644 --- a/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule.ll +++ b/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: #pragma known-parallel reduction (+ : MemRef_A) ; CHECK-NEXT: for (int c0 = 0; c0 <= 2; c0 += 1) { diff --git a/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule_2.ll b/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule_2.ll index 535ec397969d..8f5efd165546 100644 --- a/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule_2.ll +++ b/polly/test/IstAstInfo/reduction_modulo_and_loop_reversal_schedule_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: #pragma known-parallel reduction ; CHECK: for (int c0 = 0; c0 <= 2; c0 += 1) { diff --git a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions.ll b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions.ll index 0ea3916fb274..a711a36a367f 100644 --- a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions.ll +++ b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK: #pragma known-parallel ; CHECK: for (int c0 = 0; c0 <= 1; c0 += 1) diff --git a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_2.ll b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_2.ll index 703b0f3e04ea..485d6965b6d3 100644 --- a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_2.ll +++ b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; Verify that the outer dimension doesnt't carry reduction dependences ; diff --git a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_3.ll b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_3.ll index 3a847e939b5b..375fabbf6a8b 100644 --- a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_3.ll +++ b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; Verify that the outer dimension doesnt't carry reduction dependences ; diff --git a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_4.ll b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_4.ll index f2691bc6a503..584c076dcff4 100644 --- a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_4.ll +++ b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; Verify that the outer dimension doesnt't carry reduction dependences ; diff --git a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_5.ll b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_5.ll index 480af5505a33..eaa3444a04d7 100644 --- a/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_5.ll +++ b/polly/test/IstAstInfo/reduction_modulo_schedule_multiple_dimensions_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; Verify that only the outer dimension needs privatization ; diff --git a/polly/test/IstAstInfo/reduction_multiple_dimensions.ll b/polly/test/IstAstInfo/reduction_multiple_dimensions.ll index 96ecb0c078fe..9618ec872c38 100644 --- a/polly/test/IstAstInfo/reduction_multiple_dimensions.ll +++ b/polly/test/IstAstInfo/reduction_multiple_dimensions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK-NOT:#pragma known-parallel reduction ; CHECK: #pragma known-parallel diff --git a/polly/test/IstAstInfo/reduction_multiple_dimensions_2.ll b/polly/test/IstAstInfo/reduction_multiple_dimensions_2.ll index d2232ca88143..af317570eb37 100644 --- a/polly/test/IstAstInfo/reduction_multiple_dimensions_2.ll +++ b/polly/test/IstAstInfo/reduction_multiple_dimensions_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK-NOT:#pragma known-parallel reduction ; CHECK: #pragma known-parallel diff --git a/polly/test/IstAstInfo/reduction_multiple_dimensions_3.ll b/polly/test/IstAstInfo/reduction_multiple_dimensions_3.ll index dfc1682bd95b..1f7191433bf8 100644 --- a/polly/test/IstAstInfo/reduction_multiple_dimensions_3.ll +++ b/polly/test/IstAstInfo/reduction_multiple_dimensions_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK-NOT:#pragma known-parallel reduction ; CHECK: #pragma known-parallel diff --git a/polly/test/IstAstInfo/reduction_multiple_dimensions_4.ll b/polly/test/IstAstInfo/reduction_multiple_dimensions_4.ll index d0bad81efb2f..40bae5e9ac6c 100644 --- a/polly/test/IstAstInfo/reduction_multiple_dimensions_4.ll +++ b/polly/test/IstAstInfo/reduction_multiple_dimensions_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-ast-detect-parallel -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s ; ; CHECK-NOT:#pragma known-parallel reduction ; CHECK: #pragma known-parallel diff --git a/polly/test/IstAstInfo/run-time-condition.ll b/polly/test/IstAstInfo/run-time-condition.ll index c3ea8c460b6d..ccc9c7cfd321 100644 --- a/polly/test/IstAstInfo/run-time-condition.ll +++ b/polly/test/IstAstInfo/run-time-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-ast -disable-output < %s | FileCheck %s ; for (i = 0; i < 1024; i++) ; A[i] = B[i]; diff --git a/polly/test/IstAstInfo/runtime_context_with_error_blocks.ll b/polly/test/IstAstInfo/runtime_context_with_error_blocks.ll index 26a242b00ee7..2853e0acf9b8 100644 --- a/polly/test/IstAstInfo/runtime_context_with_error_blocks.ll +++ b/polly/test/IstAstInfo/runtime_context_with_error_blocks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; Verify we do not simplify the runtime check to "true" due to the domain ; constraints as the test contains an error block that influenced the domains diff --git a/polly/test/IstAstInfo/simple-run-time-condition.ll b/polly/test/IstAstInfo/simple-run-time-condition.ll index c6a6f027652f..5fb99f0676b7 100644 --- a/polly/test/IstAstInfo/simple-run-time-condition.ll +++ b/polly/test/IstAstInfo/simple-run-time-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-precise-inbounds -polly-precise-fold-accesses -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-precise-inbounds -polly-precise-fold-accesses -disable-output < %s | 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-n8:16:32:64-S128" diff --git a/polly/test/IstAstInfo/single_loop_strip_mine.ll b/polly/test/IstAstInfo/single_loop_strip_mine.ll index 4405ee1dc138..1c627f817b0b 100644 --- a/polly/test/IstAstInfo/single_loop_strip_mine.ll +++ b/polly/test/IstAstInfo/single_loop_strip_mine.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-ast-print-accesses -polly-ast-detect-parallel '-passes=polly-import-jscop,print' -disable-output < %s | FileCheck %s -check-prefix=CHECK-VECTOR +; RUN: opt %loadPolly -basic-aa -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-import-jscop -polly-ast-print-accesses -polly-ast-detect-parallel -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=CHECK-VECTOR ; for (i = 0; i < 1024; i++) ; A[i] = B[i]; diff --git a/polly/test/IstAstInfo/single_loop_uint_max_iterations.ll b/polly/test/IstAstInfo/single_loop_uint_max_iterations.ll index 3f673584a268..f1cd5dae11ce 100644 --- a/polly/test/IstAstInfo/single_loop_uint_max_iterations.ll +++ b/polly/test/IstAstInfo/single_loop_uint_max_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ; XFAIL: * ;#include "limits.h" diff --git a/polly/test/IstAstInfo/single_loop_ull_max_iterations.ll b/polly/test/IstAstInfo/single_loop_ull_max_iterations.ll index ff56cfb11780..d421e221240a 100644 --- a/polly/test/IstAstInfo/single_loop_ull_max_iterations.ll +++ b/polly/test/IstAstInfo/single_loop_ull_max_iterations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s ; XFAIL: * ;#include "limits.h" diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Bad-relation.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Bad-relation.ll index 545a88909bf6..d4a1a6222518 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Bad-relation.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Bad-relation.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: expecting other token ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-No-accesses-key.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-No-accesses-key.ll index f9f13b4cff58..43f9d3eda049 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-No-accesses-key.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-No-accesses-key.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: Statement from JScop file has no key name 'accesses' for index 1. ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-MemAcc.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-MemAcc.ll index 6031465cd03f..24ad03741216 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-MemAcc.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-MemAcc.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: The number of memory accesses in the JSop file and the number of memory accesses differ for index 0. ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-statements.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-statements.ll index fc67ec51f218..1060926e7fac 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-statements.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Not-enough-statements.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: The number of indices and the number of statements differ. ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Relation-mispelled.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Relation-mispelled.ll index 64b7b14c1939..07975976c38b 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Relation-mispelled.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Relation-mispelled.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: Memory access number 0 has no key name 'relation' for statement number 1. ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Statements-mispelled.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Statements-mispelled.ll index bd58cb3be5c3..9f7259633811 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Statements-mispelled.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Statements-mispelled.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: JScop file has no key name 'statements'. ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Undeclared-ScopArrayInfo.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Undeclared-ScopArrayInfo.ll index 565117584861..df7eb42da85f 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Undeclared-ScopArrayInfo.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Undeclared-ScopArrayInfo.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: JScop file contains access function with undeclared ScopArrayInfo ; diff --git a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Wrong-number-dimensions.ll b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Wrong-number-dimensions.ll index 4a7d51019133..61c1173db2e7 100644 --- a/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Wrong-number-dimensions.ll +++ b/polly/test/JSONExporter/ImportAccesses/ImportAccesses-Wrong-number-dimensions.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: JScop file changes the number of parameter dimensions. ; diff --git a/polly/test/JSONExporter/ImportArrays/ImportArrays-Mispelled-type.ll b/polly/test/JSONExporter/ImportArrays/ImportArrays-Mispelled-type.ll index 1dd71ba5816a..a14ae5c4d1bc 100644 --- a/polly/test/JSONExporter/ImportArrays/ImportArrays-Mispelled-type.ll +++ b/polly/test/JSONExporter/ImportArrays/ImportArrays-Mispelled-type.ll @@ -1,4 +1,4 @@ - ; RUN: not --crash opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s + ; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Array has not a valid type. ; diff --git a/polly/test/JSONExporter/ImportArrays/ImportArrays-Negative-size.ll b/polly/test/JSONExporter/ImportArrays/ImportArrays-Negative-size.ll index 5270cc8c680f..2a03197f1c1b 100644 --- a/polly/test/JSONExporter/ImportArrays/ImportArrays-Negative-size.ll +++ b/polly/test/JSONExporter/ImportArrays/ImportArrays-Negative-size.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -polly-stmt-granularity=bb -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s ; ; #define Ni 1056 ; #define Nj 1056 diff --git a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-name.ll b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-name.ll index 21c4a736a25e..45bb3495de08 100644 --- a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-name.ll +++ b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-name.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Array has no key 'name'. ; diff --git a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-sizes-key.ll b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-sizes-key.ll index 930bfce45df0..5bbb974346ba 100644 --- a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-sizes-key.ll +++ b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-sizes-key.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Array has no key 'sizes'. ; diff --git a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-type-key.ll b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-type-key.ll index eb13390dd2b9..af013992fca0 100644 --- a/polly/test/JSONExporter/ImportArrays/ImportArrays-No-type-key.ll +++ b/polly/test/JSONExporter/ImportArrays/ImportArrays-No-type-key.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Array has no key 'type'. ; diff --git a/polly/test/JSONExporter/ImportContext/ImportContext-Context-mispelled.ll b/polly/test/JSONExporter/ImportContext/ImportContext-Context-mispelled.ll index 79e175378af6..2490e44ec347 100644 --- a/polly/test/JSONExporter/ImportContext/ImportContext-Context-mispelled.ll +++ b/polly/test/JSONExporter/ImportContext/ImportContext-Context-mispelled.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: JScop file has no key named 'context'. ; diff --git a/polly/test/JSONExporter/ImportContext/ImportContext-Not-parameter-set.ll b/polly/test/JSONExporter/ImportContext/ImportContext-Not-parameter-set.ll index 96539188cdff..66ce6a6ed922 100644 --- a/polly/test/JSONExporter/ImportContext/ImportContext-Not-parameter-set.ll +++ b/polly/test/JSONExporter/ImportContext/ImportContext-Not-parameter-set.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: The isl_set is not a parameter set. ; diff --git a/polly/test/JSONExporter/ImportContext/ImportContext-Unvalid-Context.ll b/polly/test/JSONExporter/ImportContext/ImportContext-Unvalid-Context.ll index 0e80d3623c10..7bcc54dde52e 100644 --- a/polly/test/JSONExporter/ImportContext/ImportContext-Unvalid-Context.ll +++ b/polly/test/JSONExporter/ImportContext/ImportContext-Unvalid-Context.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: unexpected isl_token ; diff --git a/polly/test/JSONExporter/ImportContext/ImportContext-Wrong-dimension.ll b/polly/test/JSONExporter/ImportContext/ImportContext-Wrong-dimension.ll index 9a04d89b18d1..65cdcbdcdef6 100644 --- a/polly/test/JSONExporter/ImportContext/ImportContext-Wrong-dimension.ll +++ b/polly/test/JSONExporter/ImportContext/ImportContext-Wrong-dimension.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: Imported context has the wrong number of parameters : Found 2 Expected 1 ; diff --git a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-No-schedule-key.ll b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-No-schedule-key.ll index 6347d17da4cc..b52db0876cc5 100644 --- a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-No-schedule-key.ll +++ b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-No-schedule-key.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: Statement 0 has no 'schedule' key. ; diff --git a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Schedule-not-valid.ll b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Schedule-not-valid.ll index b6f4d188fad0..5ce3ad267bb0 100644 --- a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Schedule-not-valid.ll +++ b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Schedule-not-valid.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: expecting other token ; diff --git a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Statements-mispelled.ll b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Statements-mispelled.ll index 9c325f9bfb77..4329653899b2 100644 --- a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Statements-mispelled.ll +++ b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Statements-mispelled.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: JScop file has no key name 'statements'. ; diff --git a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Wrong-number-statements.ll b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Wrong-number-statements.ll index a6a3c7d35668..f66fc6c1e5d7 100644 --- a/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Wrong-number-statements.ll +++ b/polly/test/JSONExporter/ImportSchedule/ImportSchedule-Wrong-number-statements.ll @@ -1,4 +1,4 @@ -; RUN: not --crash opt %loadPolly '-passes=polly-import-jscop,print' -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s +; RUN: not --crash opt %loadPolly -polly-import-jscop -polly-ast -polly-ast-detect-parallel -disable-output < %s 2>&1 >/dev/null | FileCheck %s ; ; CHECK: The number of indices and the number of statements differ. ; diff --git a/polly/test/MaximalStaticExpansion/load_after_store_same_statement.ll b/polly/test/MaximalStaticExpansion/load_after_store_same_statement.ll index a3611f0b89f3..791210f7710d 100644 --- a/polly/test/MaximalStaticExpansion/load_after_store_same_statement.ll +++ b/polly/test/MaximalStaticExpansion/load_after_store_same_statement.ll @@ -1,5 +1,7 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1| FileCheck %s --check-prefix=MSE +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that the expansion of an array with load after store in a same statement is not done. ; diff --git a/polly/test/MaximalStaticExpansion/read_from_original.ll b/polly/test/MaximalStaticExpansion/read_from_original.ll index fe9c5850bc5f..59f9379516c7 100644 --- a/polly/test/MaximalStaticExpansion/read_from_original.ll +++ b/polly/test/MaximalStaticExpansion/read_from_original.ll @@ -1,5 +1,7 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1| FileCheck %s --check-prefix=MSE +; RUN: opt %loadNPMPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that Polly detects problems and does not expand the array ; diff --git a/polly/test/MaximalStaticExpansion/too_many_writes.ll b/polly/test/MaximalStaticExpansion/too_many_writes.ll index 01cdd2b46682..50a66cd11d0a 100644 --- a/polly/test/MaximalStaticExpansion/too_many_writes.ll +++ b/polly/test/MaximalStaticExpansion/too_many_writes.ll @@ -1,5 +1,7 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadNPMPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that Polly detects problems and does not expand the array ; diff --git a/polly/test/MaximalStaticExpansion/working_deps_between_inners.ll b/polly/test/MaximalStaticExpansion/working_deps_between_inners.ll index 3b9f951be2b4..8e2707cfee64 100644 --- a/polly/test/MaximalStaticExpansion/working_deps_between_inners.ll +++ b/polly/test/MaximalStaticExpansion/working_deps_between_inners.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s ; ; Verify that the accesses are correctly expanded for MemoryKind::Array ; diff --git a/polly/test/MaximalStaticExpansion/working_deps_between_inners_phi.ll b/polly/test/MaximalStaticExpansion/working_deps_between_inners_phi.ll index 32ed2b99bde2..2bf49b89db05 100644 --- a/polly/test/MaximalStaticExpansion/working_deps_between_inners_phi.ll +++ b/polly/test/MaximalStaticExpansion/working_deps_between_inners_phi.ll @@ -1,5 +1,7 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that the accesses are correctly expanded for MemoryKind::Array and MemoryKind::PHI. ; tmp_06_phi is not expanded because it need copy in. diff --git a/polly/test/MaximalStaticExpansion/working_expansion.ll b/polly/test/MaximalStaticExpansion/working_expansion.ll index 29ac90174f88..bb5b2360143f 100644 --- a/polly/test/MaximalStaticExpansion/working_expansion.ll +++ b/polly/test/MaximalStaticExpansion/working_expansion.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s ; ; Verify that the accesses are correctly expanded for MemoryKind::Array ; diff --git a/polly/test/MaximalStaticExpansion/working_expansion_multiple_dependences_per_statement.ll b/polly/test/MaximalStaticExpansion/working_expansion_multiple_dependences_per_statement.ll index 6ef2f298adb9..89ff7890fc7e 100644 --- a/polly/test/MaximalStaticExpansion/working_expansion_multiple_dependences_per_statement.ll +++ b/polly/test/MaximalStaticExpansion/working_expansion_multiple_dependences_per_statement.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s ; ; Verify that the accesses are correctly expanded ; diff --git a/polly/test/MaximalStaticExpansion/working_expansion_multiple_instruction_per_statement.ll b/polly/test/MaximalStaticExpansion/working_expansion_multiple_instruction_per_statement.ll index 6c7ea23d2f53..7ffd39f0f534 100644 --- a/polly/test/MaximalStaticExpansion/working_expansion_multiple_instruction_per_statement.ll +++ b/polly/test/MaximalStaticExpansion/working_expansion_multiple_instruction_per_statement.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s ; ; Verify that the accesses are correctly expanded ; diff --git a/polly/test/MaximalStaticExpansion/working_phi_expansion.ll b/polly/test/MaximalStaticExpansion/working_phi_expansion.ll index 0d4f18f21ade..43919c61b045 100644 --- a/polly/test/MaximalStaticExpansion/working_phi_expansion.ll +++ b/polly/test/MaximalStaticExpansion/working_phi_expansion.ll @@ -1,5 +1,7 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadNPMPolly "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that the accesses are correctly expanded for MemoryKind::PHI ; tmp_04 is not expanded because it need copy-in. diff --git a/polly/test/MaximalStaticExpansion/working_phi_two_scalars.ll b/polly/test/MaximalStaticExpansion/working_phi_two_scalars.ll index 93e984b95c95..a581a389e742 100644 --- a/polly/test/MaximalStaticExpansion/working_phi_two_scalars.ll +++ b/polly/test/MaximalStaticExpansion/working_phi_two_scalars.ll @@ -1,5 +1,7 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-mse -polly-print-scops -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -pass-remarks-analysis="polly-mse" -disable-output < %s 2>&1 | FileCheck %s --check-prefix=MSE ; ; Verify that the accesses are correctly expanded for MemoryKind::PHI ; tmp_05 and tmp2_06 are not expanded because they need copy-in. diff --git a/polly/test/MaximalStaticExpansion/working_value_expansion.ll b/polly/test/MaximalStaticExpansion/working_value_expansion.ll index 27c4304d2fe5..d54eff9e03ec 100644 --- a/polly/test/MaximalStaticExpansion/working_value_expansion.ll +++ b/polly/test/MaximalStaticExpansion/working_value_expansion.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-mse -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output < %s | FileCheck %s ; ; Verify that the accesses are correctly expanded for MemoryKind::Value ; diff --git a/polly/test/PruneUnprofitable/prune_only_scalardeps.ll b/polly/test/PruneUnprofitable/prune_only_scalardeps.ll index c64512fc3d7a..31db5560c051 100644 --- a/polly/test/PruneUnprofitable/prune_only_scalardeps.ll +++ b/polly/test/PruneUnprofitable/prune_only_scalardeps.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=false "-passes=scop(polly-prune-unprofitable)" -disable-output -stats < %s 2>&1 | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=false -polly-prune-unprofitable -disable-output -stats < %s 2>&1 | FileCheck -match-full-lines %s +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=false "-passes=scop(polly-prune-unprofitable)" -disable-output -stats < %s 2>&1 | FileCheck -match-full-lines %s ; REQUIRES: asserts ; ; Skip this SCoP for having scalar dependencies between all statements, diff --git a/polly/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll b/polly/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll index b9baa35b0cf8..5acc35343ac3 100644 --- a/polly/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll +++ b/polly/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -S < %s +; RUN: opt %loadPolly -polly-opt-isl -S < %s target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-a0:0-n32" define void @sdbout_label() nounwind { diff --git a/polly/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll b/polly/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll index e3e1d61f74c1..3f4237b330b2 100644 --- a/polly/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll +++ b/polly/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -S < %s +; RUN: opt %loadPolly -polly-opt-isl -S < %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-n8:16:32:64-S128" ; Check that we handle statements with an empty iteration domain correctly. diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-double.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-double.ll index b1acd130acb6..a61af2d092f3 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-double.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-double.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-first.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-first.ll index 4590b01f6112..185d5c5b8c25 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-first.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-first.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,OPT +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,OPT define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B, i32 %k) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-third.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-third.ll index a9afceac3880..f1eca0ede061 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-third.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-except-third.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B, i32 %k) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-carried.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-carried.ll index 16dc6d8bc673..35903ced7741 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-carried.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-carried.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,OPT +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,OPT define void @func(i32 %n, ptr noalias nonnull %A) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-third.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-third.ll index 54611c7a1cb8..1fb8c001069f 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-third.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner-third.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefixes=CHECK +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK,RAW +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefixes=CHECK define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B, i32 %k) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner.ll index 905a7804215f..2db6833fa897 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-inner.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s define void @func(i32 %n, ptr noalias nonnull %A) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-simple.ll b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-simple.ll index 32be9181c66b..49d008ba2cfa 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/fuse-simple.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/fuse-simple.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s define void @func(i32 %n, ptr noalias nonnull %A) { entry: diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-simple.ll b/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-simple.ll index d15d69e69fac..175b85997ec0 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-simple.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-simple.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s ; This could theoretically be fused by adjusting the offset of the second loop by %k (instead of relying on schedule dimensions). diff --git a/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-with-middle.ll b/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-with-middle.ll index 5dc5330db107..48ba20347d55 100644 --- a/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-with-middle.ll +++ b/polly/test/ScheduleOptimizer/GreedyFuse/nofuse-with-middle.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=0 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-reschedule=1 -polly-loopfusion-greedy=1 -polly-postopts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B, i32 %k) { entry: diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/disable_nonforced.ll b/polly/test/ScheduleOptimizer/ManualOptimization/disable_nonforced.ll index 8676b2dd7e18..537721f8718a 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/disable_nonforced.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/disable_nonforced.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-opt-isl -disable-output < %s | FileCheck %s -match-full-lines ; ; Check that the disable_nonforced metadata is honored; optimization ; heuristics/rescheduling must not be applied. diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_heuristic.ll b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_heuristic.ll index 90dc071ae8f6..aaf4d27f4c5e 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_heuristic.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_heuristic.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -polly-pragma-based-opts=1 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines --check-prefix=ON -; RUN: opt %loadPolly -polly-reschedule=0 -polly-pragma-based-opts=0 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines --check-prefix=OFF +; RUN: opt %loadPolly -polly-reschedule=0 -polly-pragma-based-opts=1 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines --check-prefix=ON +; RUN: opt %loadPolly -polly-reschedule=0 -polly-pragma-based-opts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines --check-prefix=OFF ; define void @func(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B) { entry: diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_looploc.ll b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_looploc.ll index f513835c60eb..b1e94227c9a5 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_looploc.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_looploc.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-reschedule=0 -polly-pragma-based-opts=1 -disable-output < %s 2>&1 | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-opt-isl -polly-reschedule=0 -polly-pragma-based-opts=1 -disable-output < %s 2>&1 | FileCheck %s --match-full-lines ; ; CHECK: warning: distribute_illegal.c:2:3: not applying loop fission/distribution: cannot ensure semantic equivalence due to possible dependency violations ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_pragmaloc.ll b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_pragmaloc.ll index c18b9bb72ad7..fc0df85b1346 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_pragmaloc.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/distribute_illegal_pragmaloc.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-reschedule=0 -polly-pragma-based-opts=1 -disable-output < %s 2>&1 | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-opt-isl -polly-reschedule=0 -polly-pragma-based-opts=1 -disable-output < %s 2>&1 | FileCheck %s --match-full-lines ; ; CHECK: warning: distribute_illegal.c:1:42: not applying loop fission/distribution: cannot ensure semantic equivalence due to possible dependency violations ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_disable.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_disable.ll index 20f5a4538b16..9537f3a9b0a8 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_disable.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_disable.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-pragma-based-opts=1 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-pragma-based-opts=1 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines ; ; Override unroll metadata with llvm.loop.unroll.disable. ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_double.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_double.ll index afc39a72da1d..b0310970f8d6 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_double.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_double.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines ; ; Apply two loop transformations. First partial, then full unrolling. ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_full.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_full.ll index a166421ca21a..b9a4c845477c 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_full.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_full.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines ; ; Full unroll of a loop with 5 iterations. ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_heuristic.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_heuristic.ll index 68ee147895cf..0387aecd683b 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_heuristic.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_heuristic.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-pragma-based-opts=1 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines -; RUN: opt %loadPolly -polly-pragma-based-opts=0 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-pragma-based-opts=1 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-pragma-based-opts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines ; ; Unrolling with heuristic factor. ; Currently not supported and expected to be handled by LLVM's unroll pass. diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial.ll index 042e1b4e088a..81e40f0a98bb 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-pragma-based-opts=1 '-passes=print' -disable-output < %s | FileCheck %s --match-full-lines -; RUN: opt %loadPolly -polly-pragma-based-opts=0 '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=OFF --match-full-lines +; RUN: opt %loadPolly -polly-pragma-based-opts=1 -polly-print-opt-isl -disable-output < %s | FileCheck %s --match-full-lines +; RUN: opt %loadPolly -polly-pragma-based-opts=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefix=OFF --match-full-lines ; ; Partial unroll by a factor of 4. ; diff --git a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial_followup.ll b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial_followup.ll index 893d40a41777..8665f68b99c1 100644 --- a/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial_followup.ll +++ b/polly/test/ScheduleOptimizer/ManualOptimization/unroll_partial_followup.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=OPT --match-full-lines -; RUN: opt %loadPolly '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s --check-prefix=AST --match-full-lines -; RUN: opt %loadPolly '-passes=scop(polly-opt-isl,polly-codegen),simplifycfg' -S < %s | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-opt-isl -disable-output < %s | FileCheck %s --check-prefix=OPT --match-full-lines +; RUN: opt %loadPolly -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST --match-full-lines +; RUN: opt %loadPolly -polly-opt-isl -polly-codegen -simplifycfg -S < %s | FileCheck %s --check-prefix=CODEGEN ; ; Partial unroll by a factor of 4. ; @@ -49,7 +49,7 @@ return: ; OPT-NEXT: - filter: "[n] -> { Stmt_body[i0] : (1 + i0) mod 4 = 0 }" -; AST-LABEL: :: isl ast :: func :: %for---%return +; AST-LABEL: Printing analysis 'Polly - Generate an AST of the SCoP (isl)'for => return' in function 'func': ; AST: // Loop with Metadata ; AST-NEXT: for (int c0 = 0; c0 < n; c0 += 4) { diff --git a/polly/test/ScheduleOptimizer/SIMDInParallelFor.ll b/polly/test/ScheduleOptimizer/SIMDInParallelFor.ll index b0385d50c6c6..8585634e10ff 100644 --- a/polly/test/ScheduleOptimizer/SIMDInParallelFor.ll +++ b/polly/test/ScheduleOptimizer/SIMDInParallelFor.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-parallel -polly-vectorizer=stripmine -passes=polly-codegen-verify '-passes=polly-opt-isl,print,polly-codegen' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-parallel -polly-vectorizer=stripmine -polly-codegen-verify -polly-opt-isl -polly-print-ast -polly-codegen -disable-output < %s | FileCheck %s ; ; Check that there are no nested #pragma omp parallel for inside a ; #pragma omp parallel for loop. diff --git a/polly/test/ScheduleOptimizer/computeout.ll b/polly/test/ScheduleOptimizer/computeout.ll index 1cf6513e7a5c..35e3416f91d1 100644 --- a/polly/test/ScheduleOptimizer/computeout.ll +++ b/polly/test/ScheduleOptimizer/computeout.ll @@ -1,5 +1,7 @@ -; RUN: opt -S %loadPolly "-passes=scop(polly-opt-isl,print)" -polly-isl-arg=--no-schedule-serialize-sccs -disable-output < %s | FileCheck %s -; RUN: opt -S %loadPolly "-passes=scop(polly-opt-isl,print)" -polly-isl-arg=--no-schedule-serialize-sccs -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT +; RUN: opt -S %loadPolly -basic-aa -polly-opt-isl -polly-isl-arg=--no-schedule-serialize-sccs -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt -S %loadNPMPolly "-passes=scop(polly-opt-isl,print)" -polly-isl-arg=--no-schedule-serialize-sccs -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -basic-aa -polly-opt-isl -polly-isl-arg=--schedule-serialize-sccs -polly-dependences-computeout=1 -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT +; RUN: opt -S %loadNPMPolly "-passes=scop(polly-opt-isl,print)" -polly-isl-arg=--no-schedule-serialize-sccs -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s -check-prefix=TIMEOUT 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-n8:16:32:64" ; for(i = 0; i < 100; i++ ) diff --git a/polly/test/ScheduleOptimizer/ensure-correct-tile-sizes.ll b/polly/test/ScheduleOptimizer/ensure-correct-tile-sizes.ll index 87f6c6c4eee6..43caca5372ad 100644 --- a/polly/test/ScheduleOptimizer/ensure-correct-tile-sizes.ll +++ b/polly/test/ScheduleOptimizer/ensure-correct-tile-sizes.ll @@ -1,9 +1,9 @@ ; RUN: opt %loadPolly -polly-process-unprofitable -polly-remarks-minimal \ -; RUN: '-passes=polly-opt-isl,print' -polly-pattern-matching-based-opts=true \ +; RUN: -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-target-throughput-vector-fma=1 \ ; RUN: -polly-target-latency-vector-fma=1 \ ; RUN: -polly-target-vector-register-bitwidth=4096 \ -; RUN: -polly-target-1st-cache-level-associativity=3 -disable-output < %s | FileCheck %s +; RUN: -polly-target-1st-cache-level-associativity=3 -polly-print-ast -disable-output < %s | FileCheck %s ; ; /* Test that Polly does not crash due to configurations that can lead to ; incorrect tile size computations. diff --git a/polly/test/ScheduleOptimizer/focaltech_test_detail_threshold-7bc17e.ll b/polly/test/ScheduleOptimizer/focaltech_test_detail_threshold-7bc17e.ll index 483737ee5928..daa1afdd0aa8 100644 --- a/polly/test/ScheduleOptimizer/focaltech_test_detail_threshold-7bc17e.ll +++ b/polly/test/ScheduleOptimizer/focaltech_test_detail_threshold-7bc17e.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -polly-vectorizer=stripmine -polly-invariant-load-hoisting -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-vectorizer=stripmine -polly-invariant-load-hoisting -polly-optimized-scops -polly-print-opt-isl -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly "-passes=scop(print)" -polly-vectorizer=stripmine -polly-invariant-load-hoisting -disable-output < %s | FileCheck %s ; ; llvm.org/PR46578 ; diff --git a/polly/test/ScheduleOptimizer/full_partial_tile_separation.ll b/polly/test/ScheduleOptimizer/full_partial_tile_separation.ll index 9c4627717ee8..06e86d7da1c6 100644 --- a/polly/test/ScheduleOptimizer/full_partial_tile_separation.ll +++ b/polly/test/ScheduleOptimizer/full_partial_tile_separation.ll @@ -1,4 +1,4 @@ -; RUN: opt -S %loadPolly -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s ; CHECK: // 1st level tiling - Tiles ; CHECK-NEXT: #pragma known-parallel ; CHECK-NEXT: for (int c0 = 0; c0 <= floord(ni - 1, 32); c0 += 1) diff --git a/polly/test/ScheduleOptimizer/line-tiling-2.ll b/polly/test/ScheduleOptimizer/line-tiling-2.ll index d3d11a7990a6..eb374cb07cf3 100644 --- a/polly/test/ScheduleOptimizer/line-tiling-2.ll +++ b/polly/test/ScheduleOptimizer/line-tiling-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-tile-sizes=1,64 '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-tile-sizes=1,64 -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s ; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1) ; CHECK: for (int c1 = 0; c1 <= 7; c1 += 1) diff --git a/polly/test/ScheduleOptimizer/line-tiling.ll b/polly/test/ScheduleOptimizer/line-tiling.ll index 273a27ba5931..2f14ac1d02a5 100644 --- a/polly/test/ScheduleOptimizer/line-tiling.ll +++ b/polly/test/ScheduleOptimizer/line-tiling.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-tile-sizes=64,1 '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-tile-sizes=64,1 -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s ; CHECK: for (int c0 = 0; c0 <= 15; c0 += 1) ; CHECK: for (int c1 = 0; c1 <= 511; c1 += 1) diff --git a/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout.ll b/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout.ll index 69dfd383060e..faf51e097a70 100644 --- a/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout.ll +++ b/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-target-throughput-vector-fma=1 \ ; RUN: -polly-target-latency-vector-fma=8 \ ; RUN: -polly-target-1st-cache-level-associativity=8 \ diff --git a/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout_2.ll b/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout_2.ll index fe1bc0518e2c..30b693a2e241 100644 --- a/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout_2.ll +++ b/polly/test/ScheduleOptimizer/mat_mul_pattern_data_layout_2.ll @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ -; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s ; ; /* C := alpha*A*B + beta*C */ ; /* _PB_NK % Kc != 0 */ @@ -18,7 +18,7 @@ ; C[i][j] += alpha * A[i][k] * B[k][j]; ; } ; -; CHECK-LABEL: :: isl ast :: kernel_gemm :: %bb8---%bb32 +; CHECK-LABEL: Printing analysis 'Polly - Generate an AST from the SCoP (isl)' for region: 'bb8 => bb32' in function 'kernel_gemm': ; CHECK: { ; CHECK-NEXT: // 1st level tiling - Tiles ; CHECK-NEXT: for (int c0 = 0; c0 <= 32; c0 += 1) diff --git a/polly/test/ScheduleOptimizer/one-dimensional-band.ll b/polly/test/ScheduleOptimizer/one-dimensional-band.ll index 594386662ef3..4592907a44ad 100644 --- a/polly/test/ScheduleOptimizer/one-dimensional-band.ll +++ b/polly/test/ScheduleOptimizer/one-dimensional-band.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s ; ; void jacobi1d(long T, long N, float *A, float *B) { ; long t, i, j; diff --git a/polly/test/ScheduleOptimizer/outer_coincidence.ll b/polly/test/ScheduleOptimizer/outer_coincidence.ll index 4a92f416fecc..2ab33edda86b 100644 --- a/polly/test/ScheduleOptimizer/outer_coincidence.ll +++ b/polly/test/ScheduleOptimizer/outer_coincidence.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-tiling=0 -polly-parallel -polly-opt-outer-coincidence=no '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-tiling=0 -polly-parallel -polly-opt-outer-coincidence=yes '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s --check-prefix=OUTER +; RUN: opt %loadPolly -polly-tiling=0 -polly-parallel -polly-opt-outer-coincidence=no -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-tiling=0 -polly-parallel -polly-opt-outer-coincidence=yes -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=OUTER ; By skewing, the diagonal can be made parallel. ISL does this when the Check ; the 'outer_coincidence' option is enabled. diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm.ll index 979df17632b2..66011168fcc1 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm.ll @@ -1,7 +1,7 @@ ; RUN: opt %loadPolly \ ; RUN: -polly-pattern-matching-based-opts=true \ -; RUN: '-passes=polly-optree,polly-delicm,polly-simplify,polly-opt-isl' \ -; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 \ +; RUN: -polly-optree -polly-delicm -polly-simplify \ +; RUN: -polly-opt-isl -polly-tc-opt=true -debug -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm_2.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm_2.ll index 80cae8554fdb..95da89f90755 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm_2.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts-after-delicm_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-delicm,polly-simplify,polly-opt-isl' \ +; RUN: opt %loadPolly -polly-delicm -polly-simplify -polly-opt-isl \ ; RUN: -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts.ll index 5e0bb81c5908..7604257f98e0 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts.ll @@ -1,8 +1,8 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=false \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=false \ ; RUN: -debug -polly-tc-opt -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true -debug -polly-tc-opt -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PATTERN-MATCHING-OPTS -; RUN: opt %loadPolly '-passes=polly-opt-isl,print' -polly-pattern-matching-based-opts=true -polly-ast-detect-parallel -disable-output < %s | FileCheck %s --check-prefix=PARALLEL-AST -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true -stats -disable-output < %s 2>&1 | FileCheck %s --check-prefix=STATS -match-full-lines +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true -debug -polly-tc-opt -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PATTERN-MATCHING-OPTS +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true -polly-ast-detect-parallel -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=PARALLEL-AST +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true -stats -disable-output < %s 2>&1 | FileCheck %s --check-prefix=STATS -match-full-lines ; REQUIRES: asserts ; ; /* C := alpha*A*B + beta*C */ diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_11.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_11.ll index 5c4391693b13..ccdb39b60d75 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_11.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_11.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-opt-isl' \ +; RUN: opt %loadPolly -polly-import-jscop \ ; RUN: -polly-import-jscop-postfix=transformed \ ; RUN: -polly-pattern-matching-based-opts=true \ ; RUN: -polly-target-throughput-vector-fma=1 \ @@ -8,7 +8,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -debug \ +; RUN: -polly-opt-isl -debug \ ; RUN: -polly-tc-opt=true -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_12.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_12.ll index b21a26b4772d..dd39fec5e21f 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_12.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_12.ll @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -passes=polly-opt-isl -disable-output < %s +; RUN: -polly-opt-isl -disable-output < %s ; ; Test whether isolation works as expected. ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_13.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_13.ll index a16ecf6af6ce..e086dd36c4d9 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_13.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_13.ll @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=128 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s ; ; Test whether isolation works as expected. ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_14.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_14.ll index 2c23ebbac43c..a4c71c2dace5 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_14.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_14.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,polly-opt-isl,polly-codegen' \ +; RUN: opt %loadPolly -polly-import-jscop -polly-opt-isl \ ; RUN: -polly-target-throughput-vector-fma=1 \ ; RUN: -polly-target-latency-vector-fma=8 \ ; RUN: -polly-target-1st-cache-level-associativity=8 \ @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-import-jscop-postfix=transformed -S < %s \ +; RUN: -polly-import-jscop-postfix=transformed -polly-codegen -S < %s \ ; RUN: | FileCheck %s ; ; Check that we disable the Loop Vectorizer. diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_15.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_15.ll index c8d8d295e8c8..a8da21955b63 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_15.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_15.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -debug-only=polly-opt-isl -disable-output \ ; RUN: -polly-tc-opt=true < %s 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_16.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_16.ll index 970b4a0cf932..c1ad3017a0d4 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_16.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_16.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_17.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_17.ll index e44e3bfa04c2..002816a4ae80 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_17.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_17.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_18.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_18.ll index 2612321b3d09..d5679c7ae2f7 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_18.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_18.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_19.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_19.ll index bd5f0ed40953..4e1620abd252 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_19.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_19.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_2.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_2.ll index 573c35256992..01e336ebc60f 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_2.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_20.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_20.ll index 78cc48d830c8..0be08d8d493c 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_20.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_20.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_21.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_21.ll index adfba0584a88..9b2df49698a1 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_21.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_21.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_22.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_22.ll index 54e03b301e69..3d3641df5098 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_22.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_22.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_24.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_24.ll index fee5027848a8..895961488014 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_24.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_24.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-reschedule=0 -passes=polly-opt-isl \ +; RUN: opt %loadPolly -polly-reschedule=0 -polly-opt-isl \ ; RUN: -polly-pattern-matching-based-opts=true -polly-tc-opt=true \ ; RUN: -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_25.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_25.ll index 029dcc491f02..8a3957909d9d 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_25.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_25.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-tc-opt=true -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; @@ -53,4 +53,4 @@ for.body8: ; preds = %for.body8, %for.con br i1 %exitcond.not, label %for.cond.cleanup7, label %for.body8 } -declare double @llvm.fmuladd.f64(double, double, double) +declare double @llvm.fmuladd.f64(double, double, double) \ No newline at end of file diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_3.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_3.ll index 46c8c7e35f2a..fab3ac5e58dc 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_3.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_3.ll @@ -3,7 +3,7 @@ ; RUN: -polly-target-latency-vector-fma=8 \ ; RUN: -polly-target-1st-cache-level-size=0 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ -; RUN: '-passes=polly-opt-isl,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s 2>&1 | FileCheck %s ; RUN: opt %loadPolly -polly-pattern-matching-based-opts=true \ ; RUN: -polly-target-throughput-vector-fma=1 \ @@ -13,7 +13,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: '-passes=polly-opt-isl,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=EXTRACTION-OF-MACRO-KERNEL +; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s 2>&1 | FileCheck %s --check-prefix=EXTRACTION-OF-MACRO-KERNEL ; ; /* C := alpha*A*B + beta*C */ ; for (i = 0; i < _PB_NI; i++) @@ -24,7 +24,7 @@ ; C[i][j] += alpha * A[i][k] * B[k][j]; ; } ; -; CHECK-LABEL: :: isl ast :: kernel_gemm :: %bb8---%bb32 +; CHECK-LABEL: Printing analysis 'Polly - Generate an AST from the SCoP (isl)' for region: 'bb8 => bb32' in function 'kernel_gemm': ; CHECK: { ; CHECK-NEXT: // 1st level tiling - Tiles ; CHECK-NEXT: for (int c0 = 0; c0 <= 32; c0 += 1) @@ -76,7 +76,7 @@ ; CHECK-NEXT: } ; CHECK-NEXT: } ; -; EXTRACTION-OF-MACRO-KERNEL-LABEL: :: isl ast :: kernel_gemm :: %bb8---%bb32 +; EXTRACTION-OF-MACRO-KERNEL-LABEL: Printing analysis 'Polly - Generate an AST from the SCoP (isl)' for region: 'bb8 => bb32' in function 'kernel_gemm': ; EXTRACTION-OF-MACRO-KERNEL: { ; EXTRACTION-OF-MACRO-KERNEL-NEXT: // 1st level tiling - Tiles ; EXTRACTION-OF-MACRO-KERNEL-NEXT: for (int c0 = 0; c0 <= 32; c0 += 1) diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_4.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_4.ll index ec1926ebb75f..dc0edc6c5a3b 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_4.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_4.ll @@ -1,12 +1,12 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -debug -polly-tc-opt=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=polly-opt-isl,print' -polly-pattern-matching-based-opts=true \ +; RUN: opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; RUN: -polly-target-throughput-vector-fma=1 \ ; RUN: -polly-target-latency-vector-fma=8 \ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ -; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -polly-tc-opt=true -disable-output < %s | \ +; RUN: -polly-target-2nd-cache-level-size=262144 -polly-print-ast \ +; RUN: -polly-tc-opt=true -disable-output -polly-opt-isl < %s | \ ; RUN: FileCheck %s --check-prefix=PATTERN-MATCHING-OPTS ; REQUIRES: asserts ; diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_5.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_5.ll index bfb378259210..6581566bf13f 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_5.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_5.ll @@ -6,12 +6,12 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s ; -; opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; -polly-target-throughput-vector-fma=1 \ ; -polly-target-latency-vector-fma=8 \ -; -passes=polly-codegen -polly-target-1st-cache-level-associativity=8 \ +; -polly-codegen -polly-target-1st-cache-level-associativity=8 \ ; -polly-target-2nd-cache-level-associativity=8 \ ; -polly-target-1st-cache-level-size=32768 \ ; -polly-target-vector-register-bitwidth=256 \ diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_6.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_6.ll index 684cd9be1728..bcf1fc9fe813 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_6.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_6.ll @@ -6,12 +6,12 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s ; -; opt %loadPolly -passes=polly-opt-isl -polly-pattern-matching-based-opts=true \ +; opt %loadPolly -polly-opt-isl -polly-pattern-matching-based-opts=true \ ; -polly-target-throughput-vector-fma=1 \ ; -polly-target-latency-vector-fma=8 \ -; -passes=polly-codegen -polly-target-1st-cache-level-associativity=8 \ +; -polly-codegen -polly-target-1st-cache-level-associativity=8 \ ; -polly-target-2nd-cache-level-associativity=8 \ ; -polly-target-1st-cache-level-size=32768 \ ; -polly-target-vector-register-bitwidth=256 \ diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_7.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_7.ll index b34b4f020ccb..77a3e02a0063 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_7.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_7.ll @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s ; ; /* C := A * B + C */ ; /* Elements of the matrices A, B, C have the float type. */ diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_8.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_8.ll index a65d92940665..d02bc359e79d 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_8.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_8.ll @@ -6,7 +6,7 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s ; ; /* C := A * B + C */ ; /* Elements of the matrices B, C have the double type. */ diff --git a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_9.ll b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_9.ll index 5a35e2c049f0..144abfd7622f 100644 --- a/polly/test/ScheduleOptimizer/pattern-matching-based-opts_9.ll +++ b/polly/test/ScheduleOptimizer/pattern-matching-based-opts_9.ll @@ -6,9 +6,9 @@ ; RUN: -polly-target-1st-cache-level-size=32768 \ ; RUN: -polly-target-vector-register-bitwidth=256 \ ; RUN: -polly-target-2nd-cache-level-size=262144 \ -; RUN: -passes=polly-opt-isl -disable-output < %s +; RUN: -polly-opt-isl -disable-output < %s ; -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=DEPENDENCES +; RUN: opt %loadPolly -polly-print-dependences -disable-output < %s | FileCheck %s --check-prefix=DEPENDENCES ; ; /* C := A * B + C */ ; /* Elements of the matrices A, B, C have the char type. */ diff --git a/polly/test/ScheduleOptimizer/pattern_matching_based_opts_splitmap.ll b/polly/test/ScheduleOptimizer/pattern_matching_based_opts_splitmap.ll index 05362c712a4d..5b9783d20bfc 100644 --- a/polly/test/ScheduleOptimizer/pattern_matching_based_opts_splitmap.ll +++ b/polly/test/ScheduleOptimizer/pattern_matching_based_opts_splitmap.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-import-jscop -polly-import-jscop-postfix=transformed -passes=polly-opt-isl -debug-only=polly-opt-isl -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-opt-isl -debug-only=polly-opt-isl -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; ; void pattern_matching_based_opts_splitmap(double C[static const restrict 2][2], double A[static const restrict 2][784], double B[static const restrict 784][2]) { diff --git a/polly/test/ScheduleOptimizer/prevectorization-without-tiling.ll b/polly/test/ScheduleOptimizer/prevectorization-without-tiling.ll index 5c44f73c287c..fea2155b1e4e 100644 --- a/polly/test/ScheduleOptimizer/prevectorization-without-tiling.ll +++ b/polly/test/ScheduleOptimizer/prevectorization-without-tiling.ll @@ -1,4 +1,4 @@ -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-tiling=false -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -basic-aa -polly-tiling=false -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" @C = common global [1536 x [1536 x float]] zeroinitializer, align 16 diff --git a/polly/test/ScheduleOptimizer/prevectorization.ll b/polly/test/ScheduleOptimizer/prevectorization.ll index 6a8ec549c784..385ebf14712a 100644 --- a/polly/test/ScheduleOptimizer/prevectorization.ll +++ b/polly/test/ScheduleOptimizer/prevectorization.ll @@ -1,5 +1,5 @@ -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s -; RUN: opt -S %loadPolly -aa-pipeline=basic-aa -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine -polly-prevect-width=16 '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s -check-prefix=VEC16 +; RUN: opt -S %loadPolly -basic-aa -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt -S %loadPolly -basic-aa -polly-pattern-matching-based-opts=false -polly-vectorizer=stripmine -polly-prevect-width=16 -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s -check-prefix=VEC16 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScheduleOptimizer/rectangular-tiling.ll b/polly/test/ScheduleOptimizer/rectangular-tiling.ll index 9d34c7c17a79..b527255ab5f7 100644 --- a/polly/test/ScheduleOptimizer/rectangular-tiling.ll +++ b/polly/test/ScheduleOptimizer/rectangular-tiling.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-tile-sizes=256,16 '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s -; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-tiling=false '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s --check-prefix=NOTILING -; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-2nd-level-tiling -polly-2nd-level-tile-sizes=16,8 '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s --check-prefix=TWOLEVEL -; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-2nd-level-tiling -polly-2nd-level-tile-sizes=16,8 -polly-register-tiling '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s --check-prefix=TWO-PLUS-REGISTER +; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-tiling=false -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=NOTILING +; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-2nd-level-tiling -polly-2nd-level-tile-sizes=16,8 -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=TWOLEVEL +; RUN: opt %loadPolly -polly-tile-sizes=256,16 -polly-2nd-level-tiling -polly-2nd-level-tile-sizes=16,8 -polly-register-tiling -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=TWO-PLUS-REGISTER ; CHECK: // 1st level tiling - Tiles ; CHECK: for (int c0 = 0; c0 <= 3; c0 += 1) diff --git a/polly/test/ScheduleOptimizer/schedule_computeout.ll b/polly/test/ScheduleOptimizer/schedule_computeout.ll index 6e60fe1cd6f3..acc8601a31a8 100644 --- a/polly/test/ScheduleOptimizer/schedule_computeout.ll +++ b/polly/test/ScheduleOptimizer/schedule_computeout.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -S -passes=polly-optree -passes=polly-delicm -passes=polly-opt-isl -polly-schedule-computeout=10000 -debug-only="polly-opt-isl" < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -S -polly-optree -polly-delicm -polly-opt-isl -polly-schedule-computeout=10000 -debug-only="polly-opt-isl" < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; Bailout if the computations of schedule compute exceeds the max scheduling quota. diff --git a/polly/test/ScheduleOptimizer/statistics.ll b/polly/test/ScheduleOptimizer/statistics.ll index 56bf06894dd4..472febea173f 100644 --- a/polly/test/ScheduleOptimizer/statistics.ll +++ b/polly/test/ScheduleOptimizer/statistics.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-opt-isl -stats -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-opt-isl -stats -disable-output < %s 2>&1 | FileCheck %s -match-full-lines ; REQUIRES: asserts diff --git a/polly/test/ScheduleOptimizer/tile_after_fusion.ll b/polly/test/ScheduleOptimizer/tile_after_fusion.ll index b834b354af4d..8e5849234af6 100644 --- a/polly/test/ScheduleOptimizer/tile_after_fusion.ll +++ b/polly/test/ScheduleOptimizer/tile_after_fusion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-isl-arg=--no-schedule-serialize-sccs '-passes=polly-opt-isl,print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-isl-arg=--no-schedule-serialize-sccs -polly-opt-isl -polly-print-ast -disable-output < %s | FileCheck %s ; ; ; void tf(int C[256][256][256], int A0[256][256][256], int A1[256][256][256]) { @@ -17,7 +17,7 @@ ; checks whether they are tiled after being fused when polly-opt-fusion equals ; "max". ; -; CHECK-LABEL: :: isl ast :: tf :: %for.cond---%for.end56 +; CHECK-LABEL: Printing analysis 'Polly - Generate an AST from the SCoP (isl)' for region: 'for.cond => for.end56' in function 'tf': ; CHECK: 1st level tiling - Tiles ; CHECK-NEXT: for (int c0 = 0; c0 <= 7; c0 += 1) ; CHECK-NEXT: for (int c1 = 0; c1 <= 7; c1 += 1) diff --git a/polly/test/ScheduleOptimizer/vivid-vbi-gen-vivid_vbi_gen_sliced-before-llvmreduced.ll b/polly/test/ScheduleOptimizer/vivid-vbi-gen-vivid_vbi_gen_sliced-before-llvmreduced.ll index bfa1f017b61a..d08595db8fce 100644 --- a/polly/test/ScheduleOptimizer/vivid-vbi-gen-vivid_vbi_gen_sliced-before-llvmreduced.ll +++ b/polly/test/ScheduleOptimizer/vivid-vbi-gen-vivid_vbi_gen_sliced-before-llvmreduced.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-vectorizer=stripmine -polly-isl-arg=--no-schedule-serialize-sccs -polly-tiling=0 '-passes=print' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-vectorizer=stripmine -polly-isl-arg=--no-schedule-serialize-sccs -polly-tiling=0 -polly-print-opt-isl -disable-output < %s | FileCheck %s ; isl_schedule_node_band_sink may sink into multiple children. ; https://llvm.org/PR52637 diff --git a/polly/test/ScopDetect/aliasing_parametric_simple_1.ll b/polly/test/ScopDetect/aliasing_parametric_simple_1.ll index 8a2317446d64..2eddbd4cb262 100644 --- a/polly/test/ScopDetect/aliasing_parametric_simple_1.ll +++ b/polly/test/ScopDetect/aliasing_parametric_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; CHECK: Valid Region for Scop: ; diff --git a/polly/test/ScopDetect/aliasing_parametric_simple_2.ll b/polly/test/ScopDetect/aliasing_parametric_simple_2.ll index df1d1f8d56bc..c111f686c462 100644 --- a/polly/test/ScopDetect/aliasing_parametric_simple_2.ll +++ b/polly/test/ScopDetect/aliasing_parametric_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; CHECK: Valid Region for Scop: ; diff --git a/polly/test/ScopDetect/aliasing_simple_1.ll b/polly/test/ScopDetect/aliasing_simple_1.ll index af5b7cf1dfb7..524ca19ae398 100644 --- a/polly/test/ScopDetect/aliasing_simple_1.ll +++ b/polly/test/ScopDetect/aliasing_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; CHECK: Valid Region for Scop: ; diff --git a/polly/test/ScopDetect/aliasing_simple_2.ll b/polly/test/ScopDetect/aliasing_simple_2.ll index cd3155ec613a..457df996c7b8 100644 --- a/polly/test/ScopDetect/aliasing_simple_2.ll +++ b/polly/test/ScopDetect/aliasing_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; CHECK: Valid Region for Scop: ; diff --git a/polly/test/ScopDetect/base_pointer_load_setNewAccessRelation.ll b/polly/test/ScopDetect/base_pointer_load_setNewAccessRelation.ll index ab56f344f093..0411aed6ae04 100644 --- a/polly/test/ScopDetect/base_pointer_load_setNewAccessRelation.ll +++ b/polly/test/ScopDetect/base_pointer_load_setNewAccessRelation.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true '-passes=print,scop(polly-import-jscop,polly-codegen)' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true -polly-scops -polly-print-import-jscop -polly-codegen -disable-output < %s | FileCheck %s ; ; This violated an assertion in setNewAccessRelation that assumed base pointers ; to be load-hoisted. Without this assertion, it codegen would generate invalid diff --git a/polly/test/ScopDetect/base_pointer_setNewAccessRelation.ll b/polly/test/ScopDetect/base_pointer_setNewAccessRelation.ll index df7f3d706fd3..ff9be6ea16e8 100644 --- a/polly/test/ScopDetect/base_pointer_setNewAccessRelation.ll +++ b/polly/test/ScopDetect/base_pointer_setNewAccessRelation.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,scop(polly-import-jscop,polly-codegen)' -disable-output < %s 2>&1 | FileCheck %s --allow-empty +; RUN: opt %loadPolly -disable-basic-aa -polly-detect -polly-print-import-jscop -polly-codegen -disable-output < %s | FileCheck %s --allow-empty ; ; Polly codegen used to generate invalid code (referring to %ptr from the ; original region) when regeneration of the access function is necessary. diff --git a/polly/test/ScopDetect/callbr.ll b/polly/test/ScopDetect/callbr.ll index 5183b9c1a085..d65ab934bf2e 100644 --- a/polly/test/ScopDetect/callbr.ll +++ b/polly/test/ScopDetect/callbr.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-detect-track-failures -disable-output -pass-remarks-missed=polly-detect < %s 2>&1 | FileCheck %s --check-prefix=REMARK -; RUN: opt %loadPolly '-passes=print' -polly-detect-track-failures -disable-output -stats < %s 2>&1 | FileCheck %s --check-prefix=STAT +; RUN: opt %loadPolly -polly-detect -polly-detect-track-failures -disable-output -pass-remarks-missed=polly-detect < %s 2>&1 | FileCheck %s --check-prefix=REMARK +; RUN: opt %loadPolly -polly-detect -polly-detect-track-failures -disable-output -stats < %s 2>&1 | FileCheck %s --check-prefix=STAT ; REQUIRES: asserts ; REMARK: Branch from indirect terminator. diff --git a/polly/test/ScopDetect/collective_invariant_loads.ll b/polly/test/ScopDetect/collective_invariant_loads.ll index 96f154f07d2e..f1d2eea520c6 100644 --- a/polly/test/ScopDetect/collective_invariant_loads.ll +++ b/polly/test/ScopDetect/collective_invariant_loads.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting -disable-output< %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting -disable-output< %s | FileCheck %s ;CHECK: Function: test_init_chpl ;CHECK-NEXT: Region: %bb1---%bb16 diff --git a/polly/test/ScopDetect/cross_loop_non_single_exit.ll b/polly/test/ScopDetect/cross_loop_non_single_exit.ll index e54d30fc2164..ae23930b92a6 100644 --- a/polly/test/ScopDetect/cross_loop_non_single_exit.ll +++ b/polly/test/ScopDetect/cross_loop_non_single_exit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/cross_loop_non_single_exit_2.ll b/polly/test/ScopDetect/cross_loop_non_single_exit_2.ll index f3bd0d097b71..5c25da66d7ef 100644 --- a/polly/test/ScopDetect/cross_loop_non_single_exit_2.ll +++ b/polly/test/ScopDetect/cross_loop_non_single_exit_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll b/polly/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll index 6d262a9a464b..12983d2321cc 100644 --- a/polly/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll +++ b/polly/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-detect -disable-output < %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" define void @f(ptr %A, i64 %N, i64 %M) nounwind { diff --git a/polly/test/ScopDetect/dot-scops-npm.ll b/polly/test/ScopDetect/dot-scops-npm.ll index 9de6a5e2e1a5..7c8be032fd4f 100644 --- a/polly/test/ScopDetect/dot-scops-npm.ll +++ b/polly/test/ScopDetect/dot-scops-npm.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-scop-printer' -disable-output < %s +; RUN: opt %loadNPMPolly "-passes=polly-scop-printer" -disable-output < %s ; RUN: FileCheck %s -input-file=scops.func_npm.dot ; ; Check that the ScopPrinter does not crash. diff --git a/polly/test/ScopDetect/dot-scops.ll b/polly/test/ScopDetect/dot-scops.ll index 2297fd3253ca..c31562e4c62d 100644 --- a/polly/test/ScopDetect/dot-scops.ll +++ b/polly/test/ScopDetect/dot-scops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,polly-scop-printer' -disable-output < %s +; RUN: opt %loadPolly -polly-scops -dot-scops -disable-output < %s ; ; Check that the ScopPrinter does not crash. ; ScopPrinter needs the ScopDetection pass, which should depend on diff --git a/polly/test/ScopDetect/error-block-always-executed.ll b/polly/test/ScopDetect/error-block-always-executed.ll index 312c48cfee96..894be2119941 100644 --- a/polly/test/ScopDetect/error-block-always-executed.ll +++ b/polly/test/ScopDetect/error-block-always-executed.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; CHECK-NOT: Valid Region for Scop: diff --git a/polly/test/ScopDetect/error-block-referenced-from-scop.ll b/polly/test/ScopDetect/error-block-referenced-from-scop.ll index d3e56472e497..085351482139 100644 --- a/polly/test/ScopDetect/error-block-referenced-from-scop.ll +++ b/polly/test/ScopDetect/error-block-referenced-from-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; CHECK-NOT: Valid Region for Scop: diff --git a/polly/test/ScopDetect/error-block-unreachable.ll b/polly/test/ScopDetect/error-block-unreachable.ll index 72d43004e322..48f6fe8e0547 100644 --- a/polly/test/ScopDetect/error-block-unreachable.ll +++ b/polly/test/ScopDetect/error-block-unreachable.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-detect -disable-output < %s ; Verify that the scop detection does not crash on inputs with unreachable ; blocks. Earlier we crashed when detecting error blocks. diff --git a/polly/test/ScopDetect/expand-region-correctly-2.ll b/polly/test/ScopDetect/expand-region-correctly-2.ll index b6632c643fdf..fadb503cff35 100644 --- a/polly/test/ScopDetect/expand-region-correctly-2.ll +++ b/polly/test/ScopDetect/expand-region-correctly-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; CHECK: Valid Region for Scop: if.end.1631 => for.cond.1647.outer ; diff --git a/polly/test/ScopDetect/expand-region-correctly.ll b/polly/test/ScopDetect/expand-region-correctly.ll index 022dfb68ecd9..72082a32fa79 100644 --- a/polly/test/ScopDetect/expand-region-correctly.ll +++ b/polly/test/ScopDetect/expand-region-correctly.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; CHECK: Valid Region for Scop: if.end.1631 => for.cond.1647.outer diff --git a/polly/test/ScopDetect/ignore_func_flag_regex.ll b/polly/test/ScopDetect/ignore_func_flag_regex.ll index 15b92b418bcb..224126ec010e 100644 --- a/polly/test/ScopDetect/ignore_func_flag_regex.ll +++ b/polly/test/ScopDetect/ignore_func_flag_regex.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-ignore-func=f.*,g.* '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-ignore-func=f.*,g.* -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that the flag `-polly-ignore-func` works with regexes. ; diff --git a/polly/test/ScopDetect/index_from_unpredictable_loop.ll b/polly/test/ScopDetect/index_from_unpredictable_loop.ll index e0be6243ebf8..27ed64da17e6 100644 --- a/polly/test/ScopDetect/index_from_unpredictable_loop.ll +++ b/polly/test/ScopDetect/index_from_unpredictable_loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=AFFINE -; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=AFFINE +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopDetect/index_from_unpredictable_loop2.ll b/polly/test/ScopDetect/index_from_unpredictable_loop2.ll index 4d4b6f988b69..9b5a3a4389d4 100644 --- a/polly/test/ScopDetect/index_from_unpredictable_loop2.ll +++ b/polly/test/ScopDetect/index_from_unpredictable_loop2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=AFFINE -; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=print' -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=AFFINE +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopDetect/indvars.ll b/polly/test/ScopDetect/indvars.ll index 023f68435988..2ba4d1f5aabf 100644 --- a/polly/test/ScopDetect/indvars.ll +++ b/polly/test/ScopDetect/indvars.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,scop(polly-codegen)' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -polly-codegen -disable-output < %s | 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-n8:16:32:64" diff --git a/polly/test/ScopDetect/intrinsics_1.ll b/polly/test/ScopDetect/intrinsics_1.ll index 61e1c1fc3d86..65d3968e247c 100644 --- a/polly/test/ScopDetect/intrinsics_1.ll +++ b/polly/test/ScopDetect/intrinsics_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s ; ; CHECK: Valid Region for Scop: for.cond => for.end ; diff --git a/polly/test/ScopDetect/intrinsics_2.ll b/polly/test/ScopDetect/intrinsics_2.ll index 0c2aa49c2d21..f0575511b2ef 100644 --- a/polly/test/ScopDetect/intrinsics_2.ll +++ b/polly/test/ScopDetect/intrinsics_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s ; ; Verify that we allow the lifetime markers for the tmp array. ; diff --git a/polly/test/ScopDetect/intrinsics_3.ll b/polly/test/ScopDetect/intrinsics_3.ll index 16d41d0550af..bce90d136a41 100644 --- a/polly/test/ScopDetect/intrinsics_3.ll +++ b/polly/test/ScopDetect/intrinsics_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s ; ; Verify that we allow the misc intrinsics. ; diff --git a/polly/test/ScopDetect/invalid-latch-conditions.ll b/polly/test/ScopDetect/invalid-latch-conditions.ll index 1264ba0483c0..eb8097470ecf 100644 --- a/polly/test/ScopDetect/invalid-latch-conditions.ll +++ b/polly/test/ScopDetect/invalid-latch-conditions.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NALOOPS -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=NALOOPS +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=PROFIT ; The latch conditions of the outer loop are not affine, thus the loop cannot ; handled by the domain generation and needs to be overapproximated. diff --git a/polly/test/ScopDetect/invalidate_scalar_evolution.ll b/polly/test/ScopDetect/invalidate_scalar_evolution.ll index c691c7a633d2..01d34c49e289 100644 --- a/polly/test/ScopDetect/invalidate_scalar_evolution.ll +++ b/polly/test/ScopDetect/invalidate_scalar_evolution.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=PHI +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=PHI ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/invariant-load-before-scop.ll b/polly/test/ScopDetect/invariant-load-before-scop.ll index ee2eba5e8ec6..f72085ff88a1 100644 --- a/polly/test/ScopDetect/invariant-load-before-scop.ll +++ b/polly/test/ScopDetect/invariant-load-before-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s -match-full-lines ; ; The LoadInst %.b761 is defined outside the SCoP, hence is always constant ; within it. It is no "required invariant load". diff --git a/polly/test/ScopDetect/keep_going_expansion.ll b/polly/test/ScopDetect/keep_going_expansion.ll index 7da7cd41c1f9..9bcfb3924f6a 100644 --- a/polly/test/ScopDetect/keep_going_expansion.ll +++ b/polly/test/ScopDetect/keep_going_expansion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-detect-track-failures -polly-detect-keep-going '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-detect-track-failures -polly-detect-keep-going -polly-print-detect -disable-output < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopDetect/mod_ref_read_pointer.ll b/polly/test/ScopDetect/mod_ref_read_pointer.ll index 7b185a87c821..95a4649f4705 100644 --- a/polly/test/ScopDetect/mod_ref_read_pointer.ll +++ b/polly/test/ScopDetect/mod_ref_read_pointer.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-modref-calls '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=MODREF -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-allow-modref-calls -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=MODREF +; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s ; ; CHECK-NOT: Valid Region for Scop: for.body => for.end ; MODREF: Valid Region for Scop: for.body => for.end diff --git a/polly/test/ScopDetect/more-than-one-loop.ll b/polly/test/ScopDetect/more-than-one-loop.ll index 5972fbf50889..bfd226c1bcfc 100644 --- a/polly/test/ScopDetect/more-than-one-loop.ll +++ b/polly/test/ScopDetect/more-than-one-loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-process-unprofitable=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable=true -polly-print-detect -disable-output < %s | FileCheck %s ; CHECK: Valid Region for Scop: diff --git a/polly/test/ScopDetect/multidim-with-undef-size.ll b/polly/test/ScopDetect/multidim-with-undef-size.ll index 2adf7bb00b42..9973c6c72169 100644 --- a/polly/test/ScopDetect/multidim-with-undef-size.ll +++ b/polly/test/ScopDetect/multidim-with-undef-size.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; CHECK: Valid Region for Scop: bb14 => bb17 diff --git a/polly/test/ScopDetect/multidim.ll b/polly/test/ScopDetect/multidim.ll index a1a6167a121e..f43698819f32 100644 --- a/polly/test/ScopDetect/multidim.ll +++ b/polly/test/ScopDetect/multidim.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; CHECK: Valid Region for Scop: bb19 => bb20 diff --git a/polly/test/ScopDetect/multidim_indirect_access.ll b/polly/test/ScopDetect/multidim_indirect_access.ll index 4a3012d1c93c..3e06251f5fd1 100644 --- a/polly/test/ScopDetect/multidim_indirect_access.ll +++ b/polly/test/ScopDetect/multidim_indirect_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; Check that we will recognize this SCoP. ; diff --git a/polly/test/ScopDetect/multidim_two_accesses_different_delinearization.ll b/polly/test/ScopDetect/multidim_two_accesses_different_delinearization.ll index 23d520ed58be..ed554a24a6d6 100644 --- a/polly/test/ScopDetect/multidim_two_accesses_different_delinearization.ll +++ b/polly/test/ScopDetect/multidim_two_accesses_different_delinearization.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/ScopDetect/nested_loop_single_exit.ll b/polly/test/ScopDetect/nested_loop_single_exit.ll index a794e2c48ff9..377e8088eedb 100644 --- a/polly/test/ScopDetect/nested_loop_single_exit.ll +++ b/polly/test/ScopDetect/nested_loop_single_exit.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -disable-output < %s ; void f(long A[], long N) { ; long i, j; diff --git a/polly/test/ScopDetect/non-affine-conditional.ll b/polly/test/ScopDetect/non-affine-conditional.ll index f69b6f8cd1ed..fc2d0c02d2da 100644 --- a/polly/test/ScopDetect/non-affine-conditional.ll +++ b/polly/test/ScopDetect/non-affine-conditional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-print-detect -disable-output < %s | FileCheck %s ; ; void f(int *A) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/ScopDetect/non-affine-float-compare.ll b/polly/test/ScopDetect/non-affine-float-compare.ll index 1e4c580fa00d..984f14aaff8f 100644 --- a/polly/test/ScopDetect/non-affine-float-compare.ll +++ b/polly/test/ScopDetect/non-affine-float-compare.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-print-detect -disable-output < %s | FileCheck %s ; ; void f(float *A) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access.ll b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access.ll index 443a0e13c6ca..068367fa1e3c 100644 --- a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access.ll +++ b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=PROFIT ; ; Here we have a non-affine loop but also a non-affine access which should ; be rejected as long as -polly-allow-nonaffine isn't given. diff --git a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_2.ll b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_2.ll index 77733a8d9b96..cd2140518b46 100644 --- a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_2.ll +++ b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_2.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES ; ; Here we have a non-affine loop (in the context of the loop nest) ; and also a non-affine access (A[k]). While we can always detect the diff --git a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_3.ll b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_3.ll index 034ab61fa03e..fb936216e45c 100644 --- a/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_3.ll +++ b/polly/test/ScopDetect/non-affine-loop-condition-dependent-access_3.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES ; ; Here we have a non-affine loop (in the context of the loop nest) ; and also a non-affine access (A[k]). While we can always detect the diff --git a/polly/test/ScopDetect/non-affine-loop.ll b/polly/test/ScopDetect/non-affine-loop.ll index d17fd39da701..d5f7ea128a79 100644 --- a/polly/test/ScopDetect/non-affine-loop.ll +++ b/polly/test/ScopDetect/non-affine-loop.ll @@ -1,8 +1,8 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINEREGIONSANDACCESSES -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=REJECTNONAFFINELOOPS +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-allow-nonaffine -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINEREGIONSANDACCESSES +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=ALLOWNONAFFINELOOPSANDACCESSES +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=PROFIT ; ; This function/region does contain a loop, however it is non-affine, hence the access ; A[i] is also. Furthermore, it is the only loop, thus when we over approximate diff --git a/polly/test/ScopDetect/non-beneficial-loops-small-trip-count.ll b/polly/test/ScopDetect/non-beneficial-loops-small-trip-count.ll index d5901b63dd37..43af1684dccb 100644 --- a/polly/test/ScopDetect/non-beneficial-loops-small-trip-count.ll +++ b/polly/test/ScopDetect/non-beneficial-loops-small-trip-count.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s ; ; CHECK-NOT: Valid ; diff --git a/polly/test/ScopDetect/non-constant-add-rec-start-expr.ll b/polly/test/ScopDetect/non-constant-add-rec-start-expr.ll index f39e774021a9..4cddcc916a76 100644 --- a/polly/test/ScopDetect/non-constant-add-rec-start-expr.ll +++ b/polly/test/ScopDetect/non-constant-add-rec-start-expr.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; CHECK: Valid Region for Scop: bb11 => bb25 diff --git a/polly/test/ScopDetect/non-simple-memory-accesses.ll b/polly/test/ScopDetect/non-simple-memory-accesses.ll index d1c2ce63059e..a82228982885 100644 --- a/polly/test/ScopDetect/non-simple-memory-accesses.ll +++ b/polly/test/ScopDetect/non-simple-memory-accesses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; Verify that we do not model atomic memory accesses. We did not reason about ; how to handle them correctly and the Alias Set Tracker models some of them diff --git a/polly/test/ScopDetect/non_affine_loop_condition.ll b/polly/test/ScopDetect/non_affine_loop_condition.ll index 1d67df58d9bb..f268442cd8ee 100644 --- a/polly/test/ScopDetect/non_affine_loop_condition.ll +++ b/polly/test/ScopDetect/non_affine_loop_condition.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-process-unprofitable=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-process-unprofitable=false -polly-print-detect -disable-output < %s | FileCheck %s --check-prefix=PROFIT ; ; void f(int *A) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/ScopDetect/only-one-affine-loop.ll b/polly/test/ScopDetect/only-one-affine-loop.ll index 3f4305ab83e7..d6d50bb611d9 100644 --- a/polly/test/ScopDetect/only-one-affine-loop.ll +++ b/polly/test/ScopDetect/only-one-affine-loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable=false -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable=false -polly-allow-nonaffine-loops -polly-print-detect -disable-output < %s | FileCheck %s ; ; Even if we allow non-affine loops we can only model the outermost loop, all ; other loops are boxed in non-affine regions. However, the inner loops can be diff --git a/polly/test/ScopDetect/only_func_flag.ll b/polly/test/ScopDetect/only_func_flag.ll index 35a38e875e12..d465cd0f50f7 100644 --- a/polly/test/ScopDetect/only_func_flag.ll +++ b/polly/test/ScopDetect/only_func_flag.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-only-func=f,g '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-only-func=f,g -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that the flag `-polly-only-func` limits analysis to `f` and `g`. ; diff --git a/polly/test/ScopDetect/only_func_flag_regex.ll b/polly/test/ScopDetect/only_func_flag_regex.ll index 3b577b100db3..e6675798eeb9 100644 --- a/polly/test/ScopDetect/only_func_flag_regex.ll +++ b/polly/test/ScopDetect/only_func_flag_regex.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-only-func=f.*,g.* '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-only-func=f.*,g.* -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that the flag `-polly-only-func` works with regexes. ; diff --git a/polly/test/ScopDetect/parametric-multiply-in-scev-2.ll b/polly/test/ScopDetect/parametric-multiply-in-scev-2.ll index 6cb8a9ee5125..fc957a7f912c 100644 --- a/polly/test/ScopDetect/parametric-multiply-in-scev-2.ll +++ b/polly/test/ScopDetect/parametric-multiply-in-scev-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; CHECK-NOT: Valid Region diff --git a/polly/test/ScopDetect/parametric-multiply-in-scev.ll b/polly/test/ScopDetect/parametric-multiply-in-scev.ll index bb6dd6c73593..9c6e5ccc8f52 100644 --- a/polly/test/ScopDetect/parametric-multiply-in-scev.ll +++ b/polly/test/ScopDetect/parametric-multiply-in-scev.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; foo(float *A, long n, long k) { ; if (true) diff --git a/polly/test/ScopDetect/phi_with_multi_exiting_edges.ll b/polly/test/ScopDetect/phi_with_multi_exiting_edges.ll index c88dcfd860f4..054de168d76b 100644 --- a/polly/test/ScopDetect/phi_with_multi_exiting_edges.ll +++ b/polly/test/ScopDetect/phi_with_multi_exiting_edges.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; Region with an exit node that has a PHI node multiple incoming edges from ; inside the region. Motivation for supporting such cases in Polly. diff --git a/polly/test/ScopDetect/profitability-large-basic-blocks.ll b/polly/test/ScopDetect/profitability-large-basic-blocks.ll index 7296812ad85c..e1650febf11c 100644 --- a/polly/test/ScopDetect/profitability-large-basic-blocks.ll +++ b/polly/test/ScopDetect/profitability-large-basic-blocks.ll @@ -1,12 +1,12 @@ ; RUN: opt %loadPolly -polly-process-unprofitable=false \ ; RUN: -polly-detect-profitability-min-per-loop-insts=40 \ -; RUN: '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=PROFITABLE +; RUN: -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=PROFITABLE ; RUN: opt %loadPolly -polly-process-unprofitable=true \ -; RUN: '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=PROFITABLE +; RUN: -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=PROFITABLE ; RUN: opt %loadPolly -polly-process-unprofitable=false \ -; RUN: '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=UNPROFITABLE +; RUN: -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=UNPROFITABLE ; UNPROFITABLE-NOT: Valid Region for Scop: ; PROFITABLE: Valid Region for Scop: diff --git a/polly/test/ScopDetect/profitability-two-nested-loops.ll b/polly/test/ScopDetect/profitability-two-nested-loops.ll index 9311fc87d378..525f91cbc2f4 100644 --- a/polly/test/ScopDetect/profitability-two-nested-loops.ll +++ b/polly/test/ScopDetect/profitability-two-nested-loops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; CHECK: Valid Region for Scop: next => bb3 ; diff --git a/polly/test/ScopDetect/remove_all_children.ll b/polly/test/ScopDetect/remove_all_children.ll index a6b211ccfe0b..6d5097b80607 100644 --- a/polly/test/ScopDetect/remove_all_children.ll +++ b/polly/test/ScopDetect/remove_all_children.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | 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-n8:16:32:64-S128" diff --git a/polly/test/ScopDetect/report-scop-location.ll b/polly/test/ScopDetect/report-scop-location.ll index 03043faedc34..750699cbe763 100644 --- a/polly/test/ScopDetect/report-scop-location.ll +++ b/polly/test/ScopDetect/report-scop-location.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-report -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-detect -polly-report -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-i64:64-f80:128-s:64-n8:16:32:64-S128" ; Function Attrs: nounwind uwtable diff --git a/polly/test/ScopDetect/restrict-undef-size-scopdetect.ll b/polly/test/ScopDetect/restrict-undef-size-scopdetect.ll index 04d6b151ebba..e94f1e7728c5 100644 --- a/polly/test/ScopDetect/restrict-undef-size-scopdetect.ll +++ b/polly/test/ScopDetect/restrict-undef-size-scopdetect.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; CHECK-NOT: Valid Region for Scop: target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopDetect/run_time_alias_check.ll b/polly/test/ScopDetect/run_time_alias_check.ll index aa6ba8698fe9..672f3dfa6365 100644 --- a/polly/test/ScopDetect/run_time_alias_check.ll +++ b/polly/test/ScopDetect/run_time_alias_check.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | 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" diff --git a/polly/test/ScopDetect/scev_remove_max.ll b/polly/test/ScopDetect/scev_remove_max.ll index 5aa121977cfe..5353e06bdf2f 100644 --- a/polly/test/ScopDetect/scev_remove_max.ll +++ b/polly/test/ScopDetect/scev_remove_max.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' < %s +; RUN: opt %loadPolly -polly-detect < %s ; This test case helps to determine wether SCEVRemoveMax::remove produces ; an infinite loop and a segmentation fault, if it processes, for example, diff --git a/polly/test/ScopDetect/sequential_loops.ll b/polly/test/ScopDetect/sequential_loops.ll index df10da3aac36..e6ac38aa1604 100644 --- a/polly/test/ScopDetect/sequential_loops.ll +++ b/polly/test/ScopDetect/sequential_loops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | 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" @@ -13,7 +13,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 ; } define void @f1(ptr %A, i64 %N) nounwind { -; CHECK-LABEL: Detected Scops in Function f1 +; CHECK-LABEL: 'Polly - Detect static control parts (SCoPs)' for function 'f1' entry: fence seq_cst br label %for.i.1 @@ -60,7 +60,7 @@ return: ; } define void @f2(ptr %A, i64 %N) nounwind { -; CHECK-LABEL: Detected Scops in Function f2 +; CHECK-LABEL: 'Polly - Detect static control parts (SCoPs)' for function 'f2' entry: fence seq_cst br label %for.i.1 diff --git a/polly/test/ScopDetect/simple_loop.ll b/polly/test/ScopDetect/simple_loop.ll index 376a7dfa9f9b..c8ed89a97d00 100644 --- a/polly/test/ScopDetect/simple_loop.ll +++ b/polly/test/ScopDetect/simple_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/simple_loop_non_single_entry.ll b/polly/test/ScopDetect/simple_loop_non_single_entry.ll index 64e2a084188d..22adec5d2039 100644 --- a/polly/test/ScopDetect/simple_loop_non_single_entry.ll +++ b/polly/test/ScopDetect/simple_loop_non_single_entry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/simple_loop_non_single_exit.ll b/polly/test/ScopDetect/simple_loop_non_single_exit.ll index 4c3a1aea1ad8..71ac830cae7d 100644 --- a/polly/test/ScopDetect/simple_loop_non_single_exit.ll +++ b/polly/test/ScopDetect/simple_loop_non_single_exit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/simple_loop_non_single_exit_2.ll b/polly/test/ScopDetect/simple_loop_non_single_exit_2.ll index ae4ffa7b4972..d9915dc130d5 100644 --- a/polly/test/ScopDetect/simple_loop_non_single_exit_2.ll +++ b/polly/test/ScopDetect/simple_loop_non_single_exit_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/simple_loop_two_phi_nodes.ll b/polly/test/ScopDetect/simple_loop_two_phi_nodes.ll index a6bca0ec9d73..867bd50513f0 100644 --- a/polly/test/ScopDetect/simple_loop_two_phi_nodes.ll +++ b/polly/test/ScopDetect/simple_loop_two_phi_nodes.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/simple_loop_with_param.ll b/polly/test/ScopDetect/simple_loop_with_param.ll index ab48709d290d..1ae5c6608739 100644 --- a/polly/test/ScopDetect/simple_loop_with_param.ll +++ b/polly/test/ScopDetect/simple_loop_with_param.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=PHI +; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s -check-prefix=PHI ; void f(long A[], long N, long *init_ptr) { ; long i, j; diff --git a/polly/test/ScopDetect/simple_loop_with_param_2.ll b/polly/test/ScopDetect/simple_loop_with_param_2.ll index baa647489543..1a4750621c19 100644 --- a/polly/test/ScopDetect/simple_loop_with_param_2.ll +++ b/polly/test/ScopDetect/simple_loop_with_param_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-detect -disable-output < %s | FileCheck %s ; void f(long A[], int N, int *init_ptr) { ; long i, j; diff --git a/polly/test/ScopDetect/simple_non_single_entry.ll b/polly/test/ScopDetect/simple_non_single_entry.ll index 1f1cc95147a5..a1995a427903 100644 --- a/polly/test/ScopDetect/simple_non_single_entry.ll +++ b/polly/test/ScopDetect/simple_non_single_entry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; void f(long A[], long N) { ; long i; diff --git a/polly/test/ScopDetect/skip_function_attribute.ll b/polly/test/ScopDetect/skip_function_attribute.ll index d30c042fb74e..e85dbd4c2b83 100644 --- a/polly/test/ScopDetect/skip_function_attribute.ll +++ b/polly/test/ScopDetect/skip_function_attribute.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; Verify polly skips this function ; diff --git a/polly/test/ScopDetect/srem_with_parametric_divisor.ll b/polly/test/ScopDetect/srem_with_parametric_divisor.ll index 9a6352b9afe6..4b5c3b04c2ce 100644 --- a/polly/test/ScopDetect/srem_with_parametric_divisor.ll +++ b/polly/test/ScopDetect/srem_with_parametric_divisor.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; ; CHECK-NOT: Valid Region for Scop: ; diff --git a/polly/test/ScopDetect/statistics.ll b/polly/test/ScopDetect/statistics.ll index 5789677325d8..64df3d081605 100644 --- a/polly/test/ScopDetect/statistics.ll +++ b/polly/test/ScopDetect/statistics.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -stats -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-detect -stats -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScopDetect/switch-in-loop-patch.ll b/polly/test/ScopDetect/switch-in-loop-patch.ll index 508f59ee398e..ab4729fc09a4 100644 --- a/polly/test/ScopDetect/switch-in-loop-patch.ll +++ b/polly/test/ScopDetect/switch-in-loop-patch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s ; CHECK-NOT: Valid diff --git a/polly/test/ScopDetectionDiagnostics/ReportAlias-01.ll b/polly/test/ScopDetectionDiagnostics/ReportAlias-01.ll index 8f575df22f84..97ba7f9634e9 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportAlias-01.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportAlias-01.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-use-runtime-alias-checks=false -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -polly-use-runtime-alias-checks=false -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1| FileCheck %s ;void f(int A[], int B[]) { ; for (int i=0; i<42; i++) diff --git a/polly/test/ScopDetectionDiagnostics/ReportEntry.ll b/polly/test/ScopDetectionDiagnostics/ReportEntry.ll index f80b48fc3b22..fc21e192f32c 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportEntry.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportEntry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -polly-detect -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s ; CHECK: remark: :0:0: Scop contains function entry (not yet supported). diff --git a/polly/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll b/polly/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll index 2d9175607ba4..abace4ba520d 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1 | FileCheck %s ; #define N 1024 ; double invalidCall(double A[N]); diff --git a/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegion.ll b/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegion.ll index 8f5f08fb27c1..8368a68b42f0 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegion.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ;void foo(int a, int b) { diff --git a/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegionWithoutDebugLoc.ll b/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegionWithoutDebugLoc.ll index f5ca683f0fd5..82c6c33e287c 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegionWithoutDebugLoc.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportIrreducibleRegionWithoutDebugLoc.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -polly-detect -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s ; CHECK: remark: :0:0: Irreducible region encountered in control flow. diff --git a/polly/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll b/polly/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll index 27d26e665193..35986b5e0b35 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll @@ -1,15 +1,15 @@ ; RUN: opt %loadPolly \ ; RUN: -pass-remarks-missed="polly-detect" -polly-detect-track-failures \ -; RUN: -polly-allow-nonaffine-loops=false '-passes=print' -disable-output \ +; RUN: -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output \ ; RUN: < %s 2>&1| FileCheck %s --check-prefix=REJECTNONAFFINELOOPS ; RUN: opt %loadPolly \ ; RUN: -pass-remarks-missed="polly-detect" -polly-detect-track-failures \ -; RUN: -polly-allow-nonaffine-loops=true '-passes=print' -disable-output \ +; RUN: -polly-allow-nonaffine-loops=true -polly-print-detect -disable-output \ ; RUN: < %s 2>&1| FileCheck %s --check-prefix=ALLOWNONAFFINELOOPS ; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" \ ; RUN: -polly-process-unprofitable=false \ ; RUN: -polly-detect-track-failures -polly-allow-nonaffine-loops=true \ -; RUN: -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 \ +; RUN: -polly-allow-nonaffine -polly-print-detect -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=ALLOWNONAFFINEALL ; void f(int A[], int n) { diff --git a/polly/test/ScopDetectionDiagnostics/ReportLoopHasNoExit.ll b/polly/test/ScopDetectionDiagnostics/ReportLoopHasNoExit.ll index a40b423f04fc..5dbeaded45c9 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportLoopHasNoExit.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportLoopHasNoExit.ll @@ -4,8 +4,8 @@ ; the PostDominatorTree. Infinite loops are postdominated ony by the virtual ; root, which causes them not to appear in regions in ScopDetection anymore. -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-allow-nonaffine-loops -polly-print-detect -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-allow-nonaffine-loops=false -polly-print-detect -disable-output < %s 2>&1 | FileCheck %s ; void func (int param0, int N, int *A) ; { diff --git a/polly/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll b/polly/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll index b5eaaea1327e..634b63e6d44d 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1| FileCheck %s -; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -polly-delinearize=false -polly-detect-keep-going -disable-output < %s 2>&1| FileCheck %s -check-prefix=ALL -; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1| FileCheck %s -check-prefix=DELIN -; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -polly-detect-keep-going -disable-output < %s 2>&1| FileCheck %s -check-prefix=DELIN-ALL -; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1| FileCheck %s -check-prefix=NONAFFINE -; RUN: opt %loadPolly -aa-pipeline=basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1| FileCheck %s -check-prefix=NONAFFINE +; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -polly-delinearize=false -polly-detect-keep-going -disable-output < %s 2>&1| FileCheck %s -check-prefix=ALL +; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1| FileCheck %s -check-prefix=DELIN +; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -polly-detect-keep-going -disable-output < %s 2>&1| FileCheck %s -check-prefix=DELIN-ALL +; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -polly-allow-nonaffine -disable-output < %s 2>&1| FileCheck %s -check-prefix=NONAFFINE +; RUN: opt %loadPolly -basic-aa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -polly-allow-nonaffine -disable-output < %s 2>&1| FileCheck %s -check-prefix=NONAFFINE ; 1 void manyaccesses(float A[restrict], long n, float B[restrict][n]) ; 2 { diff --git a/polly/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll b/polly/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll index 369a464a0f77..23d8c9c061c9 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1| FileCheck %s ; void f(int A[]) { ; for(int i=0; i<42; ++i) diff --git a/polly/test/ScopDetectionDiagnostics/ReportUnprofitable.ll b/polly/test/ScopDetectionDiagnostics/ReportUnprofitable.ll index c606fc2b6921..d35b7a28ba89 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportUnprofitable.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportUnprofitable.ll @@ -1,9 +1,9 @@ ; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" \ -; RUN: -polly-detect-track-failures '-passes=print' -disable-output \ +; RUN: -polly-detect-track-failures -polly-print-detect -disable-output \ ; RUN: -polly-process-unprofitable=false < %s 2>&1| FileCheck %s ; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" \ -; RUN: -polly-detect-track-failures '-passes=print' -disable-output \ +; RUN: -polly-detect-track-failures -polly-print-detect -disable-output \ ; RUN: -polly-process-unprofitable=false < %s 2>&1 -pass-remarks-output=%t.yaml ; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopDetectionDiagnostics/ReportUnreachableInExit.ll b/polly/test/ScopDetectionDiagnostics/ReportUnreachableInExit.ll index 5b20d6bea3dc..6c868db78ce7 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportUnreachableInExit.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportUnreachableInExit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s \ +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s \ ; RUN: -pass-remarks-missed="polly-detect" 2>&1 | FileCheck %s ; void f(long A[], long N) { diff --git a/polly/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll b/polly/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll index ca10b0ac0256..a82f56b7a5fa 100644 --- a/polly/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll +++ b/polly/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-print-detect -disable-output < %s 2>&1| FileCheck %s ; struct b { ; double **b; diff --git a/polly/test/ScopDetectionDiagnostics/loop_has_multiple_exits.ll b/polly/test/ScopDetectionDiagnostics/loop_has_multiple_exits.ll index 5d0a2bf8f1d5..a0f2704b1372 100644 --- a/polly/test/ScopDetectionDiagnostics/loop_has_multiple_exits.ll +++ b/polly/test/ScopDetectionDiagnostics/loop_has_multiple_exits.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures '-passes=print' -disable-output 2>&1 < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -disable-output 2>&1 < %s | FileCheck %s -match-full-lines ; ; Derived from test-suite/MultiSource/Benchmarks/BitBench/uuencode/uuencode.c ; diff --git a/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop-2.ll b/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop-2.ll index 4370380cb71e..667ed7d18ab5 100644 --- a/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop-2.ll +++ b/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s ; CHECK: remark: :0:0: Loop cannot be handled because not all latches are part of loop region. diff --git a/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop.ll b/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop.ll index 05bd165d38cf..9dce56a3a3c4 100644 --- a/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop.ll +++ b/polly/test/ScopDetectionDiagnostics/loop_partially_in_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -pass-remarks-missed="polly-detect" -disable-output < %s 2>&1| FileCheck %s ; CHECK: remark: :0:0: Loop cannot be handled because not all latches are part of loop region. ; CHECK: remark: :0:0: Loop cannot be handled because not all latches are part of loop region. diff --git a/polly/test/ScopInfo/20110312-Fail-without-basicaa.ll b/polly/test/ScopInfo/20110312-Fail-without-basicaa.ll index 6f08e433c4ee..94dd5824777c 100644 --- a/polly/test/ScopInfo/20110312-Fail-without-basicaa.ll +++ b/polly/test/ScopInfo/20110312-Fail-without-basicaa.ll @@ -1,5 +1,5 @@ ; This should be run without alias analysis enabled. -;RUN: opt %loadPolly '-passes=print' -disable-output < %s +;RUN: opt %loadPolly -polly-scops -disable-output < %s 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:32:32-n8:16:32" define i32 @main() nounwind { diff --git a/polly/test/ScopInfo/20111108-Parameter-not-detected.ll b/polly/test/ScopInfo/20111108-Parameter-not-detected.ll index 531e4149cffa..f80177cb90e7 100644 --- a/polly/test/ScopInfo/20111108-Parameter-not-detected.ll +++ b/polly/test/ScopInfo/20111108-Parameter-not-detected.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" declare void @foo() diff --git a/polly/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll b/polly/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll index d92b35de2de7..b55d635947e5 100644 --- a/polly/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll +++ b/polly/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-a0:0-n32" diff --git a/polly/test/ScopInfo/2015-10-04-Crash-in-domain-generation.ll b/polly/test/ScopInfo/2015-10-04-Crash-in-domain-generation.ll index 05165ed02a90..d4d931fd2e0c 100644 --- a/polly/test/ScopInfo/2015-10-04-Crash-in-domain-generation.ll +++ b/polly/test/ScopInfo/2015-10-04-Crash-in-domain-generation.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-scops -disable-output < %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/Alias-0.ll b/polly/test/ScopInfo/Alias-0.ll index 4e7e8fa11a08..0fc4ad91b7db 100644 --- a/polly/test/ScopInfo/Alias-0.ll +++ b/polly/test/ScopInfo/Alias-0.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA -; RUN: opt %loadPolly '-passes=print' -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA +; RUN: opt %loadPolly -polly-print-scops -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA ; REQUIRES: asserts 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/Alias-1.ll b/polly/test/ScopInfo/Alias-1.ll index 7a734f810976..eab8c062f4ba 100644 --- a/polly/test/ScopInfo/Alias-1.ll +++ b/polly/test/ScopInfo/Alias-1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA -; RUN: opt %loadPolly '-passes=print' -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA +; RUN: opt %loadPolly -polly-print-scops -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA ; REQUIRES: asserts 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/Alias-2.ll b/polly/test/ScopInfo/Alias-2.ll index 9d3d44826237..64f1e0bc919d 100644 --- a/polly/test/ScopInfo/Alias-2.ll +++ b/polly/test/ScopInfo/Alias-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA -; RUN: opt %loadPolly '-passes=print' -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA +; RUN: opt %loadPolly -polly-print-scops -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA ; REQUIRES: asserts 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/Alias-3.ll b/polly/test/ScopInfo/Alias-3.ll index 83d68ddf371b..5e9b94e692bc 100644 --- a/polly/test/ScopInfo/Alias-3.ll +++ b/polly/test/ScopInfo/Alias-3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA -; RUN: opt %loadPolly '-passes=print' -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA +; RUN: opt %loadPolly -polly-print-scops -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA ; REQUIRES: asserts 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/Alias-4.ll b/polly/test/ScopInfo/Alias-4.ll index bdcf729f4061..4d5a91abb96f 100644 --- a/polly/test/ScopInfo/Alias-4.ll +++ b/polly/test/ScopInfo/Alias-4.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline= '-passes=print,print' -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA -; RUN: opt %loadPolly -aa-pipeline= '-passes=print,print' -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA +; RUN: opt %loadPolly -disable-basic-aa -polly-print-scops -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA +; RUN: opt %loadPolly -disable-basic-aa -polly-print-scops -polly-use-runtime-alias-checks=false -disable-output < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA ; REQUIRES: asserts 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/BoundChecks/single-loop.ll b/polly/test/ScopInfo/BoundChecks/single-loop.ll index 0ada318baabf..bc96c907afc9 100644 --- a/polly/test/ScopInfo/BoundChecks/single-loop.ll +++ b/polly/test/ScopInfo/BoundChecks/single-loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST ; ; This only works after the post-dominator tree has been fixed. ; diff --git a/polly/test/ScopInfo/BoundChecks/two-loops.ll b/polly/test/ScopInfo/BoundChecks/two-loops.ll index 38ea23b80b9d..14e07f42a3ae 100644 --- a/polly/test/ScopInfo/BoundChecks/two-loops.ll +++ b/polly/test/ScopInfo/BoundChecks/two-loops.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output< %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -polly-print-scops -disable-output< %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST ; ; This only works after the post-dominator tree has fixed. ; XFAIL: * diff --git a/polly/test/ScopInfo/NonAffine/div_backedge.ll b/polly/test/ScopInfo/NonAffine/div_backedge.ll index 69af32d92325..a6aca032ef62 100644 --- a/polly/test/ScopInfo/NonAffine/div_backedge.ll +++ b/polly/test/ScopInfo/NonAffine/div_backedge.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void foo(float *A) { ; for (long i = 1;; i++) { diff --git a/polly/test/ScopInfo/NonAffine/div_domain.ll b/polly/test/ScopInfo/NonAffine/div_domain.ll index 27cc284f53c4..f61c4eb459ed 100644 --- a/polly/test/ScopInfo/NonAffine/div_domain.ll +++ b/polly/test/ScopInfo/NonAffine/div_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void foo(float *A) { ; for (long i = 0; i < 16; i++) { diff --git a/polly/test/ScopInfo/NonAffine/invariant_loads_dependent_in_non_affine_region.ll b/polly/test/ScopInfo/NonAffine/invariant_loads_dependent_in_non_affine_region.ll index 4cf60324f99b..f5d63dfb9d2c 100644 --- a/polly/test/ScopInfo/NonAffine/invariant_loads_dependent_in_non_affine_region.ll +++ b/polly/test/ScopInfo/NonAffine/invariant_loads_dependent_in_non_affine_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, int *B, int *C) { ; for (int i = 0; i < 1000; i++) diff --git a/polly/test/ScopInfo/NonAffine/modulo_backedge.ll b/polly/test/ScopInfo/NonAffine/modulo_backedge.ll index 322720ae0633..dec63ca6813d 100644 --- a/polly/test/ScopInfo/NonAffine/modulo_backedge.ll +++ b/polly/test/ScopInfo/NonAffine/modulo_backedge.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Domain := ; CHECK: { Stmt_for_body[i0] : 0 <= i0 <= 6 }; diff --git a/polly/test/ScopInfo/NonAffine/modulo_domain.ll b/polly/test/ScopInfo/NonAffine/modulo_domain.ll index cbd9d8901ce3..f5ebec2b0346 100644 --- a/polly/test/ScopInfo/NonAffine/modulo_domain.ll +++ b/polly/test/ScopInfo/NonAffine/modulo_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; TODO: The new domain generation cannot handle modulo domain constraints, ; hence modulo handling has been disabled completely. Once this is diff --git a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_1.ll b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_1.ll index e38de4ab6aba..837d9b21b16e 100644 --- a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_1.ll +++ b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=SCALAR -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-process-unprofitable=false '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=PROFIT +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=SCALAR +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-process-unprofitable=false -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=PROFIT ; ; SCALAR: Function: f ; SCALAR-NEXT: Region: %bb1---%bb13 diff --git a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_2.ll b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_2.ll index 4e792e5e4e50..e39569abc52d 100644 --- a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_2.ll +++ b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_2.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALL +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=ALL ; ; Here we have a non-affine loop (in the context of the loop nest) ; and also a non-affine access (A[k]). While we can always model the diff --git a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_3.ll b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_3.ll index 1845505a5a2d..75dd7ac26bb3 100644 --- a/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_3.ll +++ b/polly/test/ScopInfo/NonAffine/non-affine-loop-condition-dependent-access_3.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALL +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=false -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=ALL ; ; Here we have a non-affine loop (in the context of the loop nest) ; and also a non-affine access (A[k]). While we can always model the diff --git a/polly/test/ScopInfo/NonAffine/non_affine_access_with_range_2.ll b/polly/test/ScopInfo/NonAffine/non_affine_access_with_range_2.ll index 2ba4065770bd..34b04933af86 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_access_with_range_2.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_access_with_range_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A) { ; for (int i = 0; i < 128; i++) diff --git a/polly/test/ScopInfo/NonAffine/non_affine_but_sdiv.ll b/polly/test/ScopInfo/NonAffine/non_affine_but_sdiv.ll index 8ba1f013fda4..9955c88b2cfd 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_but_sdiv.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_but_sdiv.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_for_body diff --git a/polly/test/ScopInfo/NonAffine/non_affine_but_srem.ll b/polly/test/ScopInfo/NonAffine/non_affine_but_srem.ll index 059129168bad..b194ee762e9f 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_but_srem.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_but_srem.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void pos(float *A, long n) { ; for (long i = 0; i < 100; i++) diff --git a/polly/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll b/polly/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll index a25b27297b0f..1f55530b137d 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_affine_loop.ll b/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_affine_loop.ll index 1f66b8a096c9..3511362304b4 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_affine_loop.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_affine_loop.ll @@ -1,11 +1,11 @@ ; RUN: opt %loadPolly -polly-allow-nonaffine-branches \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -polly-allow-nonaffine-loops=true \ -; RUN: '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST +; RUN: -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST ; RUN: opt %loadPolly -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true \ -; RUN: '-passes=print' -disable-output < %s 2>&1 | FileCheck %s \ +; RUN: -polly-print-scops -disable-output < %s | FileCheck %s \ ; RUN: --check-prefix=ALL ; ; Negative test for INNERMOST. diff --git a/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_non_affine_loop.ll b/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_non_affine_loop.ll index 5127481dde29..c2e1e46f6f18 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_non_affine_loop.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_conditional_surrounding_non_affine_loop.ll @@ -1,16 +1,16 @@ ; RUN: opt %loadPolly -polly-allow-nonaffine-branches \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -polly-allow-nonaffine-loops=true \ -; RUN: '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=INNERMOST +; RUN: -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=INNERMOST ; RUN: opt %loadPolly -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true \ -; RUN: '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ALL +; RUN: -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=ALL ; RUN: opt %loadPolly -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -polly-process-unprofitable=false \ ; RUN: -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops=true \ -; RUN: '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT +; RUN: -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=PROFIT ; ; Negative test for INNERMOST. ; At the moment we will optimistically assume A[i] in the conditional before the inner diff --git a/polly/test/ScopInfo/NonAffine/non_affine_float_compare.ll b/polly/test/ScopInfo/NonAffine/non_affine_float_compare.ll index ced23ab8f8df..c62447b6c15c 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_float_compare.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_float_compare.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(float *A) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/ScopInfo/NonAffine/non_affine_loop_condition.ll b/polly/test/ScopInfo/NonAffine/non_affine_loop_condition.ll index ce00233fd7af..873b44b9c8cf 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_loop_condition.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_loop_condition.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-process-unprofitable=false '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT -; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-detect-reductions=false '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=NO-REDUCTION +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-process-unprofitable=false -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-detect-reductions=false -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=NO-REDUCTION ; ; void f(int *A, int *C) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/ScopInfo/NonAffine/non_affine_loop_used_later.ll b/polly/test/ScopInfo/NonAffine/non_affine_loop_used_later.ll index daf06a3b5f89..127bf80b9451 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_loop_used_later.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_loop_used_later.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-unprofitable-scalar-accs=true -polly-process-unprofitable=false '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=PROFIT +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-allow-nonaffine-branches -polly-allow-nonaffine-loops -polly-unprofitable-scalar-accs=true -polly-process-unprofitable=false -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=PROFIT ; ; Verify that we over approximate the read acces of A[j] in the last statement as j is ; computed in a non-affine loop we do not model. diff --git a/polly/test/ScopInfo/NonAffine/non_affine_parametric_loop.ll b/polly/test/ScopInfo/NonAffine/non_affine_parametric_loop.ll index be94e0e3307e..de011e29aeea 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_parametric_loop.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_parametric_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-allow-nonaffine -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" ; void foo(long n, double A[], int INDEX[]) { diff --git a/polly/test/ScopInfo/NonAffine/non_affine_region_guaranteed_non-entry.ll b/polly/test/ScopInfo/NonAffine/non_affine_region_guaranteed_non-entry.ll index a4daca4d9f36..7303b4ea47fd 100644 --- a/polly/test/ScopInfo/NonAffine/non_affine_region_guaranteed_non-entry.ll +++ b/polly/test/ScopInfo/NonAffine/non_affine_region_guaranteed_non-entry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-detect '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-detect -polly-print-scops -disable-output < %s | FileCheck %s ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/NonAffine/whole-scop-non-affine-subregion-in-loop.ll b/polly/test/ScopInfo/NonAffine/whole-scop-non-affine-subregion-in-loop.ll index ba9146a8eca7..4f54d03d43fb 100644 --- a/polly/test/ScopInfo/NonAffine/whole-scop-non-affine-subregion-in-loop.ll +++ b/polly/test/ScopInfo/NonAffine/whole-scop-non-affine-subregion-in-loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s ; ; Regression test that triggered a memory leak at some point (24947). ; diff --git a/polly/test/ScopInfo/aliasing_conditional_alias_groups_1.ll b/polly/test/ScopInfo/aliasing_conditional_alias_groups_1.ll index a2836c199514..dc59fbfc66a8 100644 --- a/polly/test/ScopInfo/aliasing_conditional_alias_groups_1.ll +++ b/polly/test/ScopInfo/aliasing_conditional_alias_groups_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that there is no alias group because we either access A or B never both. ; diff --git a/polly/test/ScopInfo/aliasing_conditional_alias_groups_2.ll b/polly/test/ScopInfo/aliasing_conditional_alias_groups_2.ll index 15cea1c4f8cb..a19d60dd9147 100644 --- a/polly/test/ScopInfo/aliasing_conditional_alias_groups_2.ll +++ b/polly/test/ScopInfo/aliasing_conditional_alias_groups_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that we create two alias groups since the minimal/maximal accesses ; depend on %b. diff --git a/polly/test/ScopInfo/aliasing_dead_access.ll b/polly/test/ScopInfo/aliasing_dead_access.ll index 400fea0573a1..2a725cf3c855 100644 --- a/polly/test/ScopInfo/aliasing_dead_access.ll +++ b/polly/test/ScopInfo/aliasing_dead_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that we do not create a SCoP if there is no statement executed. ; diff --git a/polly/test/ScopInfo/aliasing_many_arrays_to_compare.ll b/polly/test/ScopInfo/aliasing_many_arrays_to_compare.ll index a1b954cb63ee..937d4ada3ec9 100644 --- a/polly/test/ScopInfo/aliasing_many_arrays_to_compare.ll +++ b/polly/test/ScopInfo/aliasing_many_arrays_to_compare.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output \ -; RUN: < %s 2>&1 | FileCheck %s --check-prefix=FOUND -; RUN: opt %loadPolly '-passes=print,print' -disable-output \ -; RUN: -polly-rtc-max-arrays-per-group=3 < %s 2>&1 | FileCheck %s \ +; RUN: opt %loadPolly -polly-print-scops -disable-output \ +; RUN: < %s | FileCheck %s --check-prefix=FOUND +; RUN: opt %loadPolly -polly-print-scops -disable-output \ +; RUN: -polly-rtc-max-arrays-per-group=3 < %s | FileCheck %s \ ; RUN: --check-prefix=IGNORED ; ; FOUND: Function: foo diff --git a/polly/test/ScopInfo/aliasing_many_read_only_acesses.ll b/polly/test/ScopInfo/aliasing_many_read_only_acesses.ll index 9447744a12a8..c22cfe55e118 100644 --- a/polly/test/ScopInfo/aliasing_many_read_only_acesses.ll +++ b/polly/test/ScopInfo/aliasing_many_read_only_acesses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: { : } diff --git a/polly/test/ScopInfo/aliasing_multiple_alias_groups.ll b/polly/test/ScopInfo/aliasing_multiple_alias_groups.ll index 5c4a864ec777..16cb3dc0f5ac 100644 --- a/polly/test/ScopInfo/aliasing_multiple_alias_groups.ll +++ b/polly/test/ScopInfo/aliasing_multiple_alias_groups.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output -aa-pipeline= < %s 2>&1 | FileCheck %s --check-prefix=NOAA -; RUN: opt %loadPolly '-passes=print' -disable-output -aa-pipeline=tbaa < %s 2>&1 | FileCheck %s --check-prefix=TBAA +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=NOAA +; RUN: opt %loadPolly -polly-print-scops -disable-output -tbaa < %s | FileCheck %s --check-prefix=TBAA ; ; void jd(int *Int0, int *Int1, float *Float0, float *Float1) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/ScopInfo/aliasing_with_non_affine_access.ll b/polly/test/ScopInfo/aliasing_with_non_affine_access.ll index 76bc18e8ac53..056b644cd5ed 100644 --- a/polly/test/ScopInfo/aliasing_with_non_affine_access.ll +++ b/polly/test/ScopInfo/aliasing_with_non_affine_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-process-unprofitable -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -polly-process-unprofitable -polly-allow-nonaffine -disable-output < %s | FileCheck %s ; ; @test1 ; Make sure we generate the correct aliasing check for a fixed-size memset operation. diff --git a/polly/test/ScopInfo/allow-all-parameters-dereferencable.ll b/polly/test/ScopInfo/allow-all-parameters-dereferencable.ll index b37b560599ad..d170a50e26fc 100644 --- a/polly/test/ScopInfo/allow-all-parameters-dereferencable.ll +++ b/polly/test/ScopInfo/allow-all-parameters-dereferencable.ll @@ -1,14 +1,14 @@ ; RUN: opt %loadPolly -disable-output -polly-invariant-load-hoisting \ ; RUN: -polly-allow-dereference-of-all-function-parameters \ -; RUN: '-passes=print' < %s 2>&1 | FileCheck %s --check-prefix=SCOP +; RUN: -polly-print-scops < %s | FileCheck %s --check-prefix=SCOP ; RUN: opt %loadPolly -S -polly-invariant-load-hoisting \ -; RUN: -passes=polly-codegen < %s 2>&1 | FileCheck %s --check-prefix=CODE-RTC +; RUN: -polly-codegen < %s | FileCheck %s --check-prefix=CODE-RTC ; RUN: opt %loadPolly -S -polly-invariant-load-hoisting \ ; RUN: -polly-allow-dereference-of-all-function-parameters \ -; RUN: -passes=polly-codegen < %s 2>&1 | FileCheck %s --check-prefix=CODE +; RUN: -polly-codegen < %s | FileCheck %s --check-prefix=CODE ; SCOP: Function: hoge ; SCOP-NEXT: Region: %bb15---%bb37 diff --git a/polly/test/ScopInfo/assume_gep_bounds.ll b/polly/test/ScopInfo/assume_gep_bounds.ll index 7b7fd15e3346..d0ce47148071 100644 --- a/polly/test/ScopInfo/assume_gep_bounds.ll +++ b/polly/test/ScopInfo/assume_gep_bounds.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s ; void foo(float A[][20][30], long n, long m, long p) { ; for (long i = 0; i < n; i++) diff --git a/polly/test/ScopInfo/assume_gep_bounds_2.ll b/polly/test/ScopInfo/assume_gep_bounds_2.ll index 3ada0f817300..e327195da94c 100644 --- a/polly/test/ScopInfo/assume_gep_bounds_2.ll +++ b/polly/test/ScopInfo/assume_gep_bounds_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output < %s \ ; RUN: -polly-precise-inbounds | FileCheck %s ; ; void foo(float A[restrict][20], float B[restrict][20], long n, long m, diff --git a/polly/test/ScopInfo/assume_gep_bounds_many.ll b/polly/test/ScopInfo/assume_gep_bounds_many.ll index 2106b96ecd56..261491564fc2 100644 --- a/polly/test/ScopInfo/assume_gep_bounds_many.ll +++ b/polly/test/ScopInfo/assume_gep_bounds_many.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -disable-output '-passes=print' -polly-ignore-aliasing \ -; RUN: < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -disable-output -polly-print-scops -polly-ignore-aliasing \ +; RUN: < %s | FileCheck %s ; CHECK: Assumed Context: ; CHECK-NEXT: [n1_a, n1_b, n1_c, n1_d, n2_a, n2_b, n2_c, n2_d, n3_a, n3_b, n3_c, n3_d, n4_a, n4_b, n4_c, n4_d, n5_a, n5_b, n5_c, n5_d, n6_a, n6_b, n6_c, n6_d, n7_a, n7_b, n7_c, n7_d, n8_a, n8_b, n8_c, n8_d, n9_a, n9_b, n9_c, n9_d, p1_b, p1_c, p1_d, p2_b, p2_c, p2_d, p3_b, p3_c, p3_d, p4_b, p4_c, p4_d, p5_b, p5_c, p5_d, p6_b, p6_c, p6_d, p7_b, p7_c, p7_d, p8_b, p8_c, p8_d, p9_b, p9_c, p9_d] -> { : p1_b >= n1_b and p1_c >= n1_c and p1_d >= n1_d and p2_b >= n2_b and p2_c >= n2_c and p2_d >= n2_d and p3_b >= n3_b and p3_c >= n3_c and p3_d >= n3_d and p4_b >= n4_b and p4_c >= n4_c and p4_d >= n4_d and p5_b >= n5_b and p5_c >= n5_c and p5_d >= n5_d and p6_b >= n6_b and p6_c >= n6_c and p6_d >= n6_d and p7_b >= n7_b and p7_c >= n7_c and p7_d >= n7_d and p8_b >= n8_b and p8_c >= n8_c and p8_d >= n8_d and p9_b >= n9_b and p9_c >= n9_c and p9_d >= n9_d } diff --git a/polly/test/ScopInfo/avoid_new_parameters_from_geps.ll b/polly/test/ScopInfo/avoid_new_parameters_from_geps.ll index e81b791f9312..0e17eb1d3668 100644 --- a/polly/test/ScopInfo/avoid_new_parameters_from_geps.ll +++ b/polly/test/ScopInfo/avoid_new_parameters_from_geps.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that we do no introduce a parameter here that is actually not needed. ; diff --git a/polly/test/ScopInfo/bool-addrec.ll b/polly/test/ScopInfo/bool-addrec.ll index 51687cd9caa5..1924a4b5266b 100644 --- a/polly/test/ScopInfo/bool-addrec.ll +++ b/polly/test/ScopInfo/bool-addrec.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -disable-output '-passes=print' -polly-process-unprofitable < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -disable-output -polly-print-ast -polly-process-unprofitable < %s | FileCheck %s ; CHECK: for (int c0 = 0; c0 <= 19999; c0 += 1) { ; CHECK-NEXT: if (c0 % 2 == 0) diff --git a/polly/test/ScopInfo/bounded_loop_assumptions.ll b/polly/test/ScopInfo/bounded_loop_assumptions.ll index 6b8acfc97c60..d472c7586c53 100644 --- a/polly/test/ScopInfo/bounded_loop_assumptions.ll +++ b/polly/test/ScopInfo/bounded_loop_assumptions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; The assumed context is tricky here as the equality test for the inner loop ; allows an "unbounded" loop trip count. We assume that does not happen, thus diff --git a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-2.ll b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-2.ll index bbf151f0206a..5c5f264aab60 100644 --- a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-2.ll +++ b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-2.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | \ +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | \ ; RUN: FileCheck %s -check-prefix=DETECT -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | \ ; RUN: FileCheck %s -check-prefix=SCOP ; DETECT: Valid Region for Scop: loop => barrier diff --git a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-3.ll b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-3.ll index 9b72a74e8628..d69d3a16c0d7 100644 --- a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-3.ll +++ b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations-3.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | \ ; RUN: FileCheck %s -check-prefix=NONAFFINE -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output \ -; RUN: -polly-allow-nonaffine-branches=false < %s 2>&1 | \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output \ +; RUN: -polly-allow-nonaffine-branches=false < %s | \ ; RUN: FileCheck %s -check-prefix=NO-NONEAFFINE ; NONAFFINE: Statements { diff --git a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations.ll b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations.ll index c6b1cddeaf85..57918fa5c92d 100644 --- a/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations.ll +++ b/polly/test/ScopInfo/branch-references-loop-scev-with-unknown-iterations.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | \ ; RUN: FileCheck %s -check-prefix=NONAFFINE -; RUN: opt %loadPolly '-passes=print,print' -disable-output \ -; RUN: -polly-allow-nonaffine-branches=false < %s 2>&1 | \ +; RUN: opt %loadPolly -polly-print-scops -disable-output \ +; RUN: -polly-allow-nonaffine-branches=false < %s | \ ; RUN: FileCheck %s -check-prefix=NO-NONEAFFINE ; NONAFFINE-NOT: Statements diff --git a/polly/test/ScopInfo/bug_2010_10_22.ll b/polly/test/ScopInfo/bug_2010_10_22.ll index 2e492e7633a0..7ba996b6d0f1 100644 --- a/polly/test/ScopInfo/bug_2010_10_22.ll +++ b/polly/test/ScopInfo/bug_2010_10_22.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-scops -disable-output < %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-n8:16:32:64" diff --git a/polly/test/ScopInfo/bug_2011_1_5.ll b/polly/test/ScopInfo/bug_2011_1_5.ll index ce815e57e627..95c25f9d9cdb 100644 --- a/polly/test/ScopInfo/bug_2011_1_5.ll +++ b/polly/test/ScopInfo/bug_2011_1_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-scops -disable-output < %s ; Bug description: Alias Analysis thinks IntToPtrInst aliases with alloca instructions created by IndependentBlocks Pass. ; This will trigger the assertion when we are verifying the SCoP after IndependentBlocks. diff --git a/polly/test/ScopInfo/bug_scev_not_fully_eval.ll b/polly/test/ScopInfo/bug_scev_not_fully_eval.ll index 8711f8e58a21..89d5f318829e 100644 --- a/polly/test/ScopInfo/bug_scev_not_fully_eval.ll +++ b/polly/test/ScopInfo/bug_scev_not_fully_eval.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | not FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | not 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-n8:16:32:64" @edge.8265 = external global [72 x i32], align 32 ; [#uses=1] diff --git a/polly/test/ScopInfo/cfg_consequences.ll b/polly/test/ScopInfo/cfg_consequences.ll index bd23ec7fc3bf..84f94b135735 100644 --- a/polly/test/ScopInfo/cfg_consequences.ll +++ b/polly/test/ScopInfo/cfg_consequences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void consequences(int *A, int bool_cond, int lhs, int rhs) { ; diff --git a/polly/test/ScopInfo/complex-branch-structure.ll b/polly/test/ScopInfo/complex-branch-structure.ll index 69eb716e6877..24ebdcf213f8 100644 --- a/polly/test/ScopInfo/complex-branch-structure.ll +++ b/polly/test/ScopInfo/complex-branch-structure.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; We build a scop of the following form to check that the domain construction diff --git a/polly/test/ScopInfo/complex-condition.ll b/polly/test/ScopInfo/complex-condition.ll index 348446a40007..31d34b033725 100644 --- a/polly/test/ScopInfo/complex-condition.ll +++ b/polly/test/ScopInfo/complex-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/complex-expression.ll b/polly/test/ScopInfo/complex-expression.ll index 1340b0e0c981..1822c9de852a 100644 --- a/polly/test/ScopInfo/complex-expression.ll +++ b/polly/test/ScopInfo/complex-expression.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/complex-loop-nesting.ll b/polly/test/ScopInfo/complex-loop-nesting.ll index a0e4a1e92050..97a9bfd939d5 100644 --- a/polly/test/ScopInfo/complex-loop-nesting.ll +++ b/polly/test/ScopInfo/complex-loop-nesting.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/complex-successor-structure-2.ll b/polly/test/ScopInfo/complex-successor-structure-2.ll index eceadc818b48..6bb7bb14a8cc 100644 --- a/polly/test/ScopInfo/complex-successor-structure-2.ll +++ b/polly/test/ScopInfo/complex-successor-structure-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s diff --git a/polly/test/ScopInfo/complex-successor-structure-3.ll b/polly/test/ScopInfo/complex-successor-structure-3.ll index b5ba6958c57b..14c3fc1babeb 100644 --- a/polly/test/ScopInfo/complex-successor-structure-3.ll +++ b/polly/test/ScopInfo/complex-successor-structure-3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -disable-output '-passes=print' \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -disable-output -polly-print-scops \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; Check that propagation of domains from A(X) to A(X+1) will keep the ; domains small and concise. diff --git a/polly/test/ScopInfo/complex-successor-structure.ll b/polly/test/ScopInfo/complex-successor-structure.ll index f39ab9bfa29b..364344045a6a 100644 --- a/polly/test/ScopInfo/complex-successor-structure.ll +++ b/polly/test/ScopInfo/complex-successor-structure.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s diff --git a/polly/test/ScopInfo/complex_domain_binary_condition.ll b/polly/test/ScopInfo/complex_domain_binary_condition.ll index 4dd39733eae2..cec26855debb 100644 --- a/polly/test/ScopInfo/complex_domain_binary_condition.ll +++ b/polly/test/ScopInfo/complex_domain_binary_condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: Low complexity assumption: { : false } diff --git a/polly/test/ScopInfo/complex_execution_context.ll b/polly/test/ScopInfo/complex_execution_context.ll index c58d6fe9a50a..164254308fa9 100644 --- a/polly/test/ScopInfo/complex_execution_context.ll +++ b/polly/test/ScopInfo/complex_execution_context.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops \ ; RUN: -polly-invariant-load-hoisting=true \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/cond_constant_in_loop.ll b/polly/test/ScopInfo/cond_constant_in_loop.ll index 45cae34e1af2..ef7d857e1084 100644 --- a/polly/test/ScopInfo/cond_constant_in_loop.ll +++ b/polly/test/ScopInfo/cond_constant_in_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ;void f(long a[], long N, long M) { ; long i, j, k; diff --git a/polly/test/ScopInfo/cond_in_loop.ll b/polly/test/ScopInfo/cond_in_loop.ll index 2101b25e4799..2d435f6a6a93 100644 --- a/polly/test/ScopInfo/cond_in_loop.ll +++ b/polly/test/ScopInfo/cond_in_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ;void f(long a[], long N, long M) { ; long i, j, k; diff --git a/polly/test/ScopInfo/condition-after-error-block-2.ll b/polly/test/ScopInfo/condition-after-error-block-2.ll index e3025d0ca259..695d864e483c 100644 --- a/polly/test/ScopInfo/condition-after-error-block-2.ll +++ b/polly/test/ScopInfo/condition-after-error-block-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; Verify that we do not allow PHI nodes such as %phi, if they reference an error ; block and are used by anything else than a terminator instruction. diff --git a/polly/test/ScopInfo/condition-after-error-block-before-scop.ll b/polly/test/ScopInfo/condition-after-error-block-before-scop.ll index 7a4d1467de46..184be3642f0c 100644 --- a/polly/test/ScopInfo/condition-after-error-block-before-scop.ll +++ b/polly/test/ScopInfo/condition-after-error-block-before-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/polly/test/ScopInfo/condtion-after-error-block.ll b/polly/test/ScopInfo/condtion-after-error-block.ll index 1a8681f829e4..92e743e2d879 100644 --- a/polly/test/ScopInfo/condtion-after-error-block.ll +++ b/polly/test/ScopInfo/condtion-after-error-block.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; Verify that we allow scops containing uniform branch conditions, where all ; but one incoming block comes from an error condition. diff --git a/polly/test/ScopInfo/const_srem_sdiv.ll b/polly/test/ScopInfo/const_srem_sdiv.ll index cf243fc74a9a..3acca980da70 100644 --- a/polly/test/ScopInfo/const_srem_sdiv.ll +++ b/polly/test/ScopInfo/const_srem_sdiv.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; See http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf ; diff --git a/polly/test/ScopInfo/constant-non-integer-branch-condition.ll b/polly/test/ScopInfo/constant-non-integer-branch-condition.ll index 8c8beac8f304..fc95a4cc7891 100644 --- a/polly/test/ScopInfo/constant-non-integer-branch-condition.ll +++ b/polly/test/ScopInfo/constant-non-integer-branch-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; At some point this caused a problem in the domain generation as we ; assumed any constant branch condition to be valid. However, only constant diff --git a/polly/test/ScopInfo/constant_factor_in_parameter.ll b/polly/test/ScopInfo/constant_factor_in_parameter.ll index ca7d094be300..1f0173c0edf9 100644 --- a/polly/test/ScopInfo/constant_factor_in_parameter.ll +++ b/polly/test/ScopInfo/constant_factor_in_parameter.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -disable-output '-passes=print' < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -disable-output '-passes=print' < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -disable-output -polly-print-scops < %s | FileCheck %s +; RUN: opt %loadPolly -disable-output -polly-print-function-scops < %s | FileCheck %s ; ; Check that the constant part of the N * M * 4 expression is not part of the ; parameter but explicit in the access function. This can avoid existentially diff --git a/polly/test/ScopInfo/constant_functions_outside_scop_as_unknown.ll b/polly/test/ScopInfo/constant_functions_outside_scop_as_unknown.ll index afb8ec3eabed..38b2b8958e2f 100644 --- a/polly/test/ScopInfo/constant_functions_outside_scop_as_unknown.ll +++ b/polly/test/ScopInfo/constant_functions_outside_scop_as_unknown.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable -polly-print-scops -disable-output < %s | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" diff --git a/polly/test/ScopInfo/constant_start_integer.ll b/polly/test/ScopInfo/constant_start_integer.ll index 94e43b324f98..aa6640c98f73 100644 --- a/polly/test/ScopInfo/constant_start_integer.ll +++ b/polly/test/ScopInfo/constant_start_integer.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" ; void foo(float *input) { diff --git a/polly/test/ScopInfo/debug_call.ll b/polly/test/ScopInfo/debug_call.ll index ba74e68c9f36..93b5bc520a00 100644 --- a/polly/test/ScopInfo/debug_call.ll +++ b/polly/test/ScopInfo/debug_call.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-debug-func=dbg_printf '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-debug-func=dbg_printf -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines ; ; Check that the call to dbg_printf is accepted as a debug-function. ; diff --git a/polly/test/ScopInfo/delinearize-together-all-data-refs.ll b/polly/test/ScopInfo/delinearize-together-all-data-refs.ll index ac17ba005bd0..108392b27f07 100644 --- a/polly/test/ScopInfo/delinearize-together-all-data-refs.ll +++ b/polly/test/ScopInfo/delinearize-together-all-data-refs.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; void foo(long n, long m, long o, double A[n][m][o]) { ; for (long i = 0; i < n-3; i++) diff --git a/polly/test/ScopInfo/div_by_zero.ll b/polly/test/ScopInfo/div_by_zero.ll index 74380f7a4c71..2205b85a9ebc 100644 --- a/polly/test/ScopInfo/div_by_zero.ll +++ b/polly/test/ScopInfo/div_by_zero.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/do-not-model-error-block-accesses.ll b/polly/test/ScopInfo/do-not-model-error-block-accesses.ll index 563e5d11474b..997e0d4b37cf 100644 --- a/polly/test/ScopInfo/do-not-model-error-block-accesses.ll +++ b/polly/test/ScopInfo/do-not-model-error-block-accesses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s ; Check that we do not crash on this input. Earlier this indeed crashed as ; we tried to model the access functions in an error block. diff --git a/polly/test/ScopInfo/eager-binary-and-or-conditions.ll b/polly/test/ScopInfo/eager-binary-and-or-conditions.ll index ee846d3ca98c..e9ad63c51b85 100644 --- a/polly/test/ScopInfo/eager-binary-and-or-conditions.ll +++ b/polly/test/ScopInfo/eager-binary-and-or-conditions.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output< %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-print-scops -disable-output< %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -disable-output < %s ; ; void or(float *A, long n, long m) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/early_exit_for_complex_domains.ll b/polly/test/ScopInfo/early_exit_for_complex_domains.ll index 2a8e6d15fea4..a72ea031c236 100644 --- a/polly/test/ScopInfo/early_exit_for_complex_domains.ll +++ b/polly/test/ScopInfo/early_exit_for_complex_domains.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-scops -disable-output < %s ; ; Check we do not crash. ; diff --git a/polly/test/ScopInfo/error-blocks-1.ll b/polly/test/ScopInfo/error-blocks-1.ll index e0b59e01d13d..03353edf297a 100644 --- a/polly/test/ScopInfo/error-blocks-1.ll +++ b/polly/test/ScopInfo/error-blocks-1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Context: ; CHECK-NEXT: [N] -> { : -2147483648 <= N <= 2147483647 } diff --git a/polly/test/ScopInfo/error-blocks-2.ll b/polly/test/ScopInfo/error-blocks-2.ll index 59096e3315f5..29095dacacfb 100644 --- a/polly/test/ScopInfo/error-blocks-2.ll +++ b/polly/test/ScopInfo/error-blocks-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/escaping_empty_scop.ll b/polly/test/ScopInfo/escaping_empty_scop.ll index e27130af952a..8837e19eefe4 100644 --- a/polly/test/ScopInfo/escaping_empty_scop.ll +++ b/polly/test/ScopInfo/escaping_empty_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; ; void g(); ; int f(int *A) { diff --git a/polly/test/ScopInfo/exit-phi-1.ll b/polly/test/ScopInfo/exit-phi-1.ll index 41b56dde043a..8e6c5fb9e211 100644 --- a/polly/test/ScopInfo/exit-phi-1.ll +++ b/polly/test/ScopInfo/exit-phi-1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -passes=polly-codegen -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-codegen -S < %s | FileCheck %s --check-prefix=CODEGEN ; ; Check for correct code generation of exit PHIs, even if the same PHI value ; is used again inside the the SCoP. diff --git a/polly/test/ScopInfo/exit-phi-2.ll b/polly/test/ScopInfo/exit-phi-2.ll index c2b463f657ea..d218d5fa039b 100644 --- a/polly/test/ScopInfo/exit-phi-2.ll +++ b/polly/test/ScopInfo/exit-phi-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that there is no MK_ExitPHI READ access. ; diff --git a/polly/test/ScopInfo/exit_phi_accesses-2.ll b/polly/test/ScopInfo/exit_phi_accesses-2.ll index cfc385dc6aba..e376f0df9d54 100644 --- a/polly/test/ScopInfo/exit_phi_accesses-2.ll +++ b/polly/test/ScopInfo/exit_phi_accesses-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; CHECK-LABEL: Function: foo ; diff --git a/polly/test/ScopInfo/exit_phi_accesses.ll b/polly/test/ScopInfo/exit_phi_accesses.ll index c598e411739c..f4fbe31f6b24 100644 --- a/polly/test/ScopInfo/exit_phi_accesses.ll +++ b/polly/test/ScopInfo/exit_phi_accesses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; Check that PHI nodes only create PHI access and nothing else (e.g. unnecessary ; SCALAR accesses). In this case, for a PHI in the exit node, hence there is no diff --git a/polly/test/ScopInfo/expensive-boundary-context.ll b/polly/test/ScopInfo/expensive-boundary-context.ll index dd660c543f2c..7001b96acd21 100644 --- a/polly/test/ScopInfo/expensive-boundary-context.ll +++ b/polly/test/ScopInfo/expensive-boundary-context.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output \ -; RUN: < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output \ +; RUN: < %s | FileCheck %s ; CHECK-NOT: Assumed Context: target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/extract_constant_factor_introduces_new_parameter.ll b/polly/test/ScopInfo/extract_constant_factor_introduces_new_parameter.ll index 9475a870e4b5..89ca344fdf54 100644 --- a/polly/test/ScopInfo/extract_constant_factor_introduces_new_parameter.ll +++ b/polly/test/ScopInfo/extract_constant_factor_introduces_new_parameter.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-scops -disable-output < %s ; CHECK: Valid Region for Scop: bb10 => bb16 diff --git a/polly/test/ScopInfo/full-function.ll b/polly/test/ScopInfo/full-function.ll index bb2d12fb0e3f..670472576fe7 100644 --- a/polly/test/ScopInfo/full-function.ll +++ b/polly/test/ScopInfo/full-function.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output -polly-detect-full-functions < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-scops -disable-output -polly-detect-full-functions < %s \ ; RUN: | FileCheck %s -check-prefix=FULL -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ ; RUN: | FileCheck %s -check-prefix=WITHOUT-FULL ; FULL: Region: %bb---FunctionExit diff --git a/polly/test/ScopInfo/granularity_same_name.ll b/polly/test/ScopInfo/granularity_same_name.ll index 4e8dd1840890..1ebf5c6f71a2 100644 --- a/polly/test/ScopInfo/granularity_same_name.ll +++ b/polly/test/ScopInfo/granularity_same_name.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-use-llvm-names=0 '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=IDX -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-use-llvm-names=1 '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=BB -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-use-llvm-names=0 '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=IDX -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-use-llvm-names=1 '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines -check-prefix=BB +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-use-llvm-names=0 -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines -check-prefix=IDX +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-use-llvm-names=1 -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines -check-prefix=BB +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-use-llvm-names=0 -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines -check-prefix=IDX +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-use-llvm-names=1 -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines -check-prefix=BB ; ; Check that the statement has the same name, regardless of how the ; basic block is split into multiple statements. diff --git a/polly/test/ScopInfo/granularity_scalar-indep.ll b/polly/test/ScopInfo/granularity_scalar-indep.ll index b28060d87180..fe509b468272 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines ; ; Split a block into two independent statements that share no scalar. ; This case has the instructions of the two statements interleaved, such that diff --git a/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi1.ll b/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi1.ll index fb2bfa663ef2..56bc11aed28d 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi1.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines ; ; Two PHIs, cross-referencing each other. The PHI READs must be carried-out ; before the PHI WRITEs to ensure that the value when entering the block is diff --git a/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi2.ll b/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi2.ll index aa066b5cd46c..f46cf4e6a0a2 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi2.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_cross-referencing-phi2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines ; ; Two PHIs, cross-referencing each other. The PHI READs must be carried-out ; before the PHI WRITEs to ensure that the value when entering the block is diff --git a/polly/test/ScopInfo/granularity_scalar-indep_epilogue.ll b/polly/test/ScopInfo/granularity_scalar-indep_epilogue.ll index da326191762a..e202e38f0844 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_epilogue.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_epilogue.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines ; ; Split a block into two independent statements that share no scalar. ; This case has an independent statement just for PHI writes. diff --git a/polly/test/ScopInfo/granularity_scalar-indep_epilogue_last.ll b/polly/test/ScopInfo/granularity_scalar-indep_epilogue_last.ll index 19484319ee35..40af34bfb067 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_epilogue_last.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_epilogue_last.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines ; ; Check that the PHI Write of value that is defined in the same basic ; block is in the statement where it is defined. diff --git a/polly/test/ScopInfo/granularity_scalar-indep_noepilogue.ll b/polly/test/ScopInfo/granularity_scalar-indep_noepilogue.ll index 484156abdbcd..9a0d207c0c2a 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_noepilogue.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_noepilogue.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines ; ; This case has no explicit epilogue for PHI writes because it would ; have a scalar dependency to the previous statement. diff --git a/polly/test/ScopInfo/granularity_scalar-indep_ordered-2.ll b/polly/test/ScopInfo/granularity_scalar-indep_ordered-2.ll index ec69b8000bf5..d093806bc9cc 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_ordered-2.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_ordered-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines ; ; This case should be split into two statements because {X[0], Y[0]} ; and {A[0], B[0]} do not intersect. diff --git a/polly/test/ScopInfo/granularity_scalar-indep_ordered.ll b/polly/test/ScopInfo/granularity_scalar-indep_ordered.ll index a7f8e2697cac..b1d2936882aa 100644 --- a/polly/test/ScopInfo/granularity_scalar-indep_ordered.ll +++ b/polly/test/ScopInfo/granularity_scalar-indep_ordered.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines ; ; This case cannot be split into two statements because the order of ; loads and store would be violated. diff --git a/polly/test/ScopInfo/i1_params.ll b/polly/test/ScopInfo/i1_params.ll index 28eb838b56b0..1cb1329b08f9 100644 --- a/polly/test/ScopInfo/i1_params.ll +++ b/polly/test/ScopInfo/i1_params.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that both a signed as well as an unsigned extended i1 parameter ; is represented correctly. diff --git a/polly/test/ScopInfo/infeasible-rtc.ll b/polly/test/ScopInfo/infeasible-rtc.ll index 5540b2365ce3..ef96627e640e 100644 --- a/polly/test/ScopInfo/infeasible-rtc.ll +++ b/polly/test/ScopInfo/infeasible-rtc.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s \ ; RUN: | FileCheck %s -check-prefix=DETECT -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ ; RUN: | FileCheck %s -check-prefix=SCOPS 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-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/infeasible_invalid_context.ll b/polly/test/ScopInfo/infeasible_invalid_context.ll index 86ecb4053d5a..2c299f06c12e 100644 --- a/polly/test/ScopInfo/infeasible_invalid_context.ll +++ b/polly/test/ScopInfo/infeasible_invalid_context.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s \ ; RUN: | FileCheck %s -check-prefix=DETECT -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ ; RUN: | FileCheck %s -check-prefix=SCOPS ; DETECT: Valid Region for Scop: if.end116 => for.inc216 diff --git a/polly/test/ScopInfo/int2ptr_ptr2int.ll b/polly/test/ScopInfo/int2ptr_ptr2int.ll index f375e79e807d..9fadc5a8eb28 100644 --- a/polly/test/ScopInfo/int2ptr_ptr2int.ll +++ b/polly/test/ScopInfo/int2ptr_ptr2int.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -S -passes=polly-codegen < %s 2>&1 | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen < %s | FileCheck %s --check-prefix=IR ; ; void f(long *A, long *ptr, long val) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/int2ptr_ptr2int_2.ll b/polly/test/ScopInfo/int2ptr_ptr2int_2.ll index 1c8251361b51..97878f7091b1 100644 --- a/polly/test/ScopInfo/int2ptr_ptr2int_2.ll +++ b/polly/test/ScopInfo/int2ptr_ptr2int_2.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly '-passes=print' \ -; RUN: -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -S -passes=polly-codegen \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -polly-print-scops \ +; RUN: -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-codegen \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s --check-prefix=IR ; ; void f(long *A, long *B, long *ptr, long val) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/integers.ll b/polly/test/ScopInfo/integers.ll index 87bc31e214ff..b608bf84cffa 100644 --- a/polly/test/ScopInfo/integers.ll +++ b/polly/test/ScopInfo/integers.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; Check that we correctly convert integers to isl values. diff --git a/polly/test/ScopInfo/inter-error-bb-dependence.ll b/polly/test/ScopInfo/inter-error-bb-dependence.ll index 00f482267a0b..4e23de7e6a99 100644 --- a/polly/test/ScopInfo/inter-error-bb-dependence.ll +++ b/polly/test/ScopInfo/inter-error-bb-dependence.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 > /dev/null | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-print-scops -disable-output < %s 2>&1 > /dev/null | FileCheck %s ; ; Error statements (%bb33) do not require their uses to be verified. ; In this case it uses %tmp32 from %bb31 which is not available because diff --git a/polly/test/ScopInfo/inter_bb_scalar_dep.ll b/polly/test/ScopInfo/inter_bb_scalar_dep.ll index 0af814516038..456f7a773f04 100644 --- a/polly/test/ScopInfo/inter_bb_scalar_dep.ll +++ b/polly/test/ScopInfo/inter_bb_scalar_dep.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' \ -; RUN: -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-scops \ +; RUN: -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; void f(long A[], int N, int *init_ptr) { ; long i, j; diff --git a/polly/test/ScopInfo/intra-non-affine-stmt-phi-node.ll b/polly/test/ScopInfo/intra-non-affine-stmt-phi-node.ll index 0fc635abae45..859972b27402 100644 --- a/polly/test/ScopInfo/intra-non-affine-stmt-phi-node.ll +++ b/polly/test/ScopInfo/intra-non-affine-stmt-phi-node.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output \ -; RUN: < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output \ +; RUN: < %s | FileCheck %s ; CHECK: Statements { ; CHECK-NEXT: Stmt_loop__TO__backedge diff --git a/polly/test/ScopInfo/intra_and_inter_bb_scalar_dep.ll b/polly/test/ScopInfo/intra_and_inter_bb_scalar_dep.ll index 209c475b5bbb..37f4e0513ed3 100644 --- a/polly/test/ScopInfo/intra_and_inter_bb_scalar_dep.ll +++ b/polly/test/ScopInfo/intra_and_inter_bb_scalar_dep.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; void f(long A[], int N, int *init_ptr) { ; long i, j; diff --git a/polly/test/ScopInfo/intra_bb_scalar_dep.ll b/polly/test/ScopInfo/intra_bb_scalar_dep.ll index 8ad5ac175802..0252273d3107 100644 --- a/polly/test/ScopInfo/intra_bb_scalar_dep.ll +++ b/polly/test/ScopInfo/intra_bb_scalar_dep.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; void f(long A[], int N, int *init_ptr) { ; long i, j; diff --git a/polly/test/ScopInfo/intrinsics.ll b/polly/test/ScopInfo/intrinsics.ll index 8b484cc21b52..853429341381 100644 --- a/polly/test/ScopInfo/intrinsics.ll +++ b/polly/test/ScopInfo/intrinsics.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-print-instructions -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-print-instructions -disable-output < %s | FileCheck %s ; ; Verify that we remove the ignored intrinsics from the instruction list. ; diff --git a/polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll b/polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll index d9f64d5eba9c..8d0de03e9866 100644 --- a/polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll +++ b/polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s ; ; This crashed at some point as we place %1 and %4 in the same equivalence class ; for invariant loads and when we remap SCEVs to use %4 instead of %1 AddRec SCEVs diff --git a/polly/test/ScopInfo/invalidate_iterator_during_MA_removal.ll b/polly/test/ScopInfo/invalidate_iterator_during_MA_removal.ll index 0f48052a40e1..dcb0ad301ba3 100644 --- a/polly/test/ScopInfo/invalidate_iterator_during_MA_removal.ll +++ b/polly/test/ScopInfo/invalidate_iterator_during_MA_removal.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s ; ; Check that no invalidated iterator is accessed while elements from ; the list of MemoryAccesses are removed. diff --git a/polly/test/ScopInfo/invariant-load-instlist.ll b/polly/test/ScopInfo/invariant-load-instlist.ll index b65d843f0ab6..7f4cf050f064 100644 --- a/polly/test/ScopInfo/invariant-load-instlist.ll +++ b/polly/test/ScopInfo/invariant-load-instlist.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s ; The load is a required invariant load and at the same time used in a store. ; Polly used to add two MemoryAccesses for it which caused an assertion to fail. diff --git a/polly/test/ScopInfo/invariant-loads-leave-read-only-statements.ll b/polly/test/ScopInfo/invariant-loads-leave-read-only-statements.ll index 12a72bd47fdf..b97fe22e076e 100644 --- a/polly/test/ScopInfo/invariant-loads-leave-read-only-statements.ll +++ b/polly/test/ScopInfo/invariant-loads-leave-read-only-statements.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s ; CHECK: Statements { ; CHECK-NEXT: Stmt_L_4 diff --git a/polly/test/ScopInfo/invariant_load.ll b/polly/test/ScopInfo/invariant_load.ll index 47501022247e..fcea77e19b85 100644 --- a/polly/test/ScopInfo/invariant_load.ll +++ b/polly/test/ScopInfo/invariant_load.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type.ll b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type.ll index c402f90cbdd1..100a8db2a9d1 100644 --- a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type.ll +++ b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=CODEGEN ; ; struct { ; int a; diff --git a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_escaping.ll b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_escaping.ll index 435c9a575d73..e31deb6fd472 100644 --- a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_escaping.ll +++ b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_escaping.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=CODEGEN ; ; struct { ; int a; diff --git a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer.ll b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer.ll index a2f43f2348b8..bbf6d69a5fbb 100644 --- a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer.ll +++ b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=CODEGEN ; ; int U; ; void f(int *A) { diff --git a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer_escaping.ll b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer_escaping.ll index 412e62f26511..011c2fe3d549 100644 --- a/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer_escaping.ll +++ b/polly/test/ScopInfo/invariant_load_access_classes_different_base_type_same_pointer_escaping.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=CODEGEN ; ; int U; ; int f(int *A) { diff --git a/polly/test/ScopInfo/invariant_load_addrec_sum.ll b/polly/test/ScopInfo/invariant_load_addrec_sum.ll index 8026d351fdf7..09b158d342ed 100644 --- a/polly/test/ScopInfo/invariant_load_addrec_sum.ll +++ b/polly/test/ScopInfo/invariant_load_addrec_sum.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s | FileCheck %s ; ; CHECK: Region: %entry.split---%if.end ; CHECK: Invariant Accesses: { diff --git a/polly/test/ScopInfo/invariant_load_base_pointer.ll b/polly/test/ScopInfo/invariant_load_base_pointer.ll index 7bf9c5a44788..ddf11d892adb 100644 --- a/polly/test/ScopInfo/invariant_load_base_pointer.ll +++ b/polly/test/ScopInfo/invariant_load_base_pointer.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_base_pointer_conditional.ll b/polly/test/ScopInfo/invariant_load_base_pointer_conditional.ll index 42dfc7b3885a..07f2c3768b0a 100644 --- a/polly/test/ScopInfo/invariant_load_base_pointer_conditional.ll +++ b/polly/test/ScopInfo/invariant_load_base_pointer_conditional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -polly-ignore-aliasing -polly-process-unprofitable -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_base_pointer_in_conditional.ll b/polly/test/ScopInfo/invariant_load_base_pointer_in_conditional.ll index 68c60edce09c..d66d718d492a 100644 --- a/polly/test/ScopInfo/invariant_load_base_pointer_in_conditional.ll +++ b/polly/test/ScopInfo/invariant_load_base_pointer_in_conditional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-ignore-aliasing -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -polly-ignore-aliasing -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_branch_condition.ll b/polly/test/ScopInfo/invariant_load_branch_condition.ll index e8c18adee1f3..4f49d2969d86 100644 --- a/polly/test/ScopInfo/invariant_load_branch_condition.ll +++ b/polly/test/ScopInfo/invariant_load_branch_condition.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output \ -; RUN: -polly-invariant-load-hoisting < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output \ +; RUN: -polly-invariant-load-hoisting < %s | FileCheck %s ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs.ll index d19018db7967..c6a7faf2e355 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_2.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_2.ll index 556b50284f34..921dd4fbde5c 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_2.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_3.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_3.ll index 58c553023191..c15d11ca865d 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_3.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4.ll index 881003b15839..0495a330792c 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4b.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4b.ll index 6f4d40ec98f7..9144fcf186c3 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4b.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4b.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4c.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4c.ll index d1859cb54241..aefacff6b46f 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4c.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_4c.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_5.ll b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_5.ll index 74d6f1021124..ecc0c0a23014 100644 --- a/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_5.ll +++ b/polly/test/ScopInfo/invariant_load_canonicalize_array_baseptrs_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s \ ; RUN: -polly-invariant-load-hoisting \ ; RUN: | FileCheck %s diff --git a/polly/test/ScopInfo/invariant_load_complex_condition.ll b/polly/test/ScopInfo/invariant_load_complex_condition.ll index 34f5c45ac2b4..e721c222db5f 100644 --- a/polly/test/ScopInfo/invariant_load_complex_condition.ll +++ b/polly/test/ScopInfo/invariant_load_complex_condition.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -S '-passes=print' -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -S -polly-print-scops -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/invariant_load_condition.ll b/polly/test/ScopInfo/invariant_load_condition.ll index 7d14a398d874..84546984709e 100644 --- a/polly/test/ScopInfo/invariant_load_condition.ll +++ b/polly/test/ScopInfo/invariant_load_condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_dereferenceable.ll b/polly/test/ScopInfo/invariant_load_dereferenceable.ll index c590e4043f64..adba32d8d463 100644 --- a/polly/test/ScopInfo/invariant_load_dereferenceable.ll +++ b/polly/test/ScopInfo/invariant_load_dereferenceable.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly '-passes=print' '-passes=print' \ +; RUN: opt %loadPolly -polly-print-detect -polly-print-scops \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -disable-output < %s 2>&1 | FileCheck %s +; RUN: -disable-output < %s | FileCheck %s ; CHECK-NOT: Function: foo_undereferanceable diff --git a/polly/test/ScopInfo/invariant_load_distinct_parameter_valuations.ll b/polly/test/ScopInfo/invariant_load_distinct_parameter_valuations.ll index b9b55cc4ecb1..60b4a1daa824 100644 --- a/polly/test/ScopInfo/invariant_load_distinct_parameter_valuations.ll +++ b/polly/test/ScopInfo/invariant_load_distinct_parameter_valuations.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; Check that we do not consolidate the invariant loads to smp[order - 1] and ; smp[order - 2] in the blocks %0 and %16. While they have the same pointer diff --git a/polly/test/ScopInfo/invariant_load_in_non_affine.ll b/polly/test/ScopInfo/invariant_load_in_non_affine.ll index 08c8bd28caa7..d00bc2d642e0 100644 --- a/polly/test/ScopInfo/invariant_load_in_non_affine.ll +++ b/polly/test/ScopInfo/invariant_load_in_non_affine.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; CHECK-NOT: Valid Region for Scop ; diff --git a/polly/test/ScopInfo/invariant_load_loop_ub.ll b/polly/test/ScopInfo/invariant_load_loop_ub.ll index 009f036bcb62..856b6e4dd508 100644 --- a/polly/test/ScopInfo/invariant_load_loop_ub.ll +++ b/polly/test/ScopInfo/invariant_load_loop_ub.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-process-unprofitable -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -polly-process-unprofitable -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -polly-process-unprofitable -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -polly-invariant-load-hoisting=true -polly-process-unprofitable -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_ptr_ptr_noalias.ll b/polly/test/ScopInfo/invariant_load_ptr_ptr_noalias.ll index ba381dea72e9..69463d420aca 100644 --- a/polly/test/ScopInfo/invariant_load_ptr_ptr_noalias.ll +++ b/polly/test/ScopInfo/invariant_load_ptr_ptr_noalias.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=tbaa '-passes=print' -polly-invariant-load-hoisting=true -polly-ignore-aliasing \ -; RUN: -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -tbaa -polly-print-scops -polly-invariant-load-hoisting=true -polly-ignore-aliasing \ +; RUN: -disable-output < %s | FileCheck %s ; ; Note: The order of the invariant accesses is important because A is the ; base pointer of tmp3 and we will generate code in the same order as diff --git a/polly/test/ScopInfo/invariant_load_scalar_dep.ll b/polly/test/ScopInfo/invariant_load_scalar_dep.ll index ea0227d4a6e9..79a10426862a 100644 --- a/polly/test/ScopInfo/invariant_load_scalar_dep.ll +++ b/polly/test/ScopInfo/invariant_load_scalar_dep.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-process-unprofitable -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_load_stmt_domain.ll b/polly/test/ScopInfo/invariant_load_stmt_domain.ll index 31da46f40f8c..6cd71c85ea2f 100644 --- a/polly/test/ScopInfo/invariant_load_stmt_domain.ll +++ b/polly/test/ScopInfo/invariant_load_stmt_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; This test case verifies that the statement domain of the invariant access ; is the universe. In earlier versions of Polly, we accidentally computed an diff --git a/polly/test/ScopInfo/invariant_load_zext_parameter-2.ll b/polly/test/ScopInfo/invariant_load_zext_parameter-2.ll index 2bf6d1d4d8b1..e77515280241 100644 --- a/polly/test/ScopInfo/invariant_load_zext_parameter-2.ll +++ b/polly/test/ScopInfo/invariant_load_zext_parameter-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -scalar-evolution-max-value-compare-depth=3 '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -scalar-evolution-max-value-compare-depth=3 -passes=polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s +; RUN: opt %loadPolly -scalar-evolution-max-value-compare-depth=3 -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -scalar-evolution-max-value-compare-depth=3 -polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s ; ; Stress test for the code generation of invariant accesses. ; diff --git a/polly/test/ScopInfo/invariant_load_zext_parameter.ll b/polly/test/ScopInfo/invariant_load_zext_parameter.ll index 41559ff14efa..1bde70282d44 100644 --- a/polly/test/ScopInfo/invariant_load_zext_parameter.ll +++ b/polly/test/ScopInfo/invariant_load_zext_parameter.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=CODEGEN ; ; void f(int *I0, int *I1, int *V) { ; for (int i = 0; i < 1000; i++) { diff --git a/polly/test/ScopInfo/invariant_load_zextended_in_own_execution_context.ll b/polly/test/ScopInfo/invariant_load_zextended_in_own_execution_context.ll index 2ae99acd47ec..775369e55c92 100644 --- a/polly/test/ScopInfo/invariant_load_zextended_in_own_execution_context.ll +++ b/polly/test/ScopInfo/invariant_load_zextended_in_own_execution_context.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -disable-output < %s ; ; CHECK: Execution Context: [p_0_loaded_from_currpc] -> { : } ; diff --git a/polly/test/ScopInfo/invariant_loads_complicated_dependences.ll b/polly/test/ScopInfo/invariant_loads_complicated_dependences.ll index 9cee220d1f3c..1d54ccc69023 100644 --- a/polly/test/ScopInfo/invariant_loads_complicated_dependences.ll +++ b/polly/test/ScopInfo/invariant_loads_complicated_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_loads_cyclic_dependences.ll b/polly/test/ScopInfo/invariant_loads_cyclic_dependences.ll index 0434bbd34e4c..e97de0c936bc 100644 --- a/polly/test/ScopInfo/invariant_loads_cyclic_dependences.ll +++ b/polly/test/ScopInfo/invariant_loads_cyclic_dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; Negative test. If we assume UB[*V] to be invariant we get a cyclic ; dependence in the invariant loads that needs to be resolved by diff --git a/polly/test/ScopInfo/invariant_loop_bounds.ll b/polly/test/ScopInfo/invariant_loop_bounds.ll index 279199b805f1..4e1fd88fac30 100644 --- a/polly/test/ScopInfo/invariant_loop_bounds.ll +++ b/polly/test/ScopInfo/invariant_loop_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-1.ll b/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-1.ll index d8e293f7e6f3..3d5737bbe168 100644 --- a/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-1.ll +++ b/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; Verify that we only have one parameter and one invariant load for all ; three loads that occure in the region but actually access the same diff --git a/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-2.ll b/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-2.ll index e68f3be7fb30..e2de503eb83f 100644 --- a/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-2.ll +++ b/polly/test/ScopInfo/invariant_same_loop_bound_multiple_times-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; Verify that we only have one parameter and one invariant load for all ; three loads that occure in the region but actually access the same diff --git a/polly/test/ScopInfo/isl_aff_out_of_bounds.ll b/polly/test/ScopInfo/isl_aff_out_of_bounds.ll index 4f7a604272bb..ca1b235be358 100644 --- a/polly/test/ScopInfo/isl_aff_out_of_bounds.ll +++ b/polly/test/ScopInfo/isl_aff_out_of_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' < %s 2>&1 +; RUN: opt %loadPolly -basic-aa -polly-detect < %s ; Used to fail with: ; ../../isl/isl_aff.c:591: position out of bounds diff --git a/polly/test/ScopInfo/isl_trip_count_01.ll b/polly/test/ScopInfo/isl_trip_count_01.ll index 6ad4929888e3..fc6b79c5a68a 100644 --- a/polly/test/ScopInfo/isl_trip_count_01.ll +++ b/polly/test/ScopInfo/isl_trip_count_01.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: [M, N] -> { Stmt_while_body[i0] : i0 > 0 and 4i0 <= -M + N; Stmt_while_body[0] }; ; diff --git a/polly/test/ScopInfo/isl_trip_count_02.ll b/polly/test/ScopInfo/isl_trip_count_02.ll index b356fa9fdf22..9376cb415cec 100644 --- a/polly/test/ScopInfo/isl_trip_count_02.ll +++ b/polly/test/ScopInfo/isl_trip_count_02.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; TODO: We do not allow unbounded loops at the moment. ; diff --git a/polly/test/ScopInfo/isl_trip_count_03.ll b/polly/test/ScopInfo/isl_trip_count_03.ll index 886143114df6..f5b0048a0e0e 100644 --- a/polly/test/ScopInfo/isl_trip_count_03.ll +++ b/polly/test/ScopInfo/isl_trip_count_03.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Test comes from a bug (15771) or better a feature request. It was not allowed ; in Polly in the old domain generation as ScalarEvolution cannot figure out the diff --git a/polly/test/ScopInfo/isl_trip_count_multiple_exiting_blocks.ll b/polly/test/ScopInfo/isl_trip_count_multiple_exiting_blocks.ll index 8ddb26a6ac88..91bc19e2de44 100644 --- a/polly/test/ScopInfo/isl_trip_count_multiple_exiting_blocks.ll +++ b/polly/test/ScopInfo/isl_trip_count_multiple_exiting_blocks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/licm_load.ll b/polly/test/ScopInfo/licm_load.ll index c4695ecddaf7..ade640976d00 100644 --- a/polly/test/ScopInfo/licm_load.ll +++ b/polly/test/ScopInfo/licm_load.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -passes='loop(loop-rotate,indvars),polly-prepare,print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 \ +; RUN: opt %loadNPMPolly -passes='loop(loop-rotate,indvars),polly-prepare,print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s -; RUN: opt %loadPolly -passes='loop-mssa(loop-rotate,indvars,licm),polly-prepare,print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 \ +; RUN: opt %loadNPMPolly -passes='loop-mssa(loop-rotate,indvars,licm),polly-prepare,print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s ; ; void foo(int n, float A[static const restrict n], diff --git a/polly/test/ScopInfo/licm_potential_store.ll b/polly/test/ScopInfo/licm_potential_store.ll index fd19df793306..8a36ee84313a 100644 --- a/polly/test/ScopInfo/licm_potential_store.ll +++ b/polly/test/ScopInfo/licm_potential_store.ll @@ -1,8 +1,8 @@ -; RUN: opt %loadPolly -passes='sroa,instcombine,simplifycfg,reassociate,loop(loop-rotate),instcombine,indvars,polly-prepare,print' \ +; RUN: opt %loadNPMPolly -passes='sroa,instcombine,simplifycfg,reassociate,loop(loop-rotate),instcombine,indvars,polly-prepare,print' \ ; RUN: -tailcallopt -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=NOLICM -; RUN: opt %loadPolly -passes='sroa,instcombine,simplifycfg,reassociate,loop(loop-rotate),instcombine,indvars,loop-mssa(licm),polly-prepare,print' \ +; RUN: opt %loadNPMPolly -passes='sroa,instcombine,simplifycfg,reassociate,loop(loop-rotate),instcombine,indvars,loop-mssa(licm),polly-prepare,print' \ ; RUN: -tailcallopt -disable-output < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=LICM diff --git a/polly/test/ScopInfo/licm_reduction_nested.ll b/polly/test/ScopInfo/licm_reduction_nested.ll index 98d6dfcfa074..a3ba478cd9ff 100644 --- a/polly/test/ScopInfo/licm_reduction_nested.ll +++ b/polly/test/ScopInfo/licm_reduction_nested.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -loop-rotate -indvars -passes=polly-prepare '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -aa-pipeline=basic-aa -loop-rotate -indvars -licm -passes=polly-prepare '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -loop-rotate -indvars -polly-prepare -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -loop-rotate -indvars -licm -polly-prepare -polly-scops -disable-output < %s | FileCheck %s ; ; XFAIL: * ; diff --git a/polly/test/ScopInfo/long-compile-time-alias-analysis.ll b/polly/test/ScopInfo/long-compile-time-alias-analysis.ll index 5fa9a74d0fe3..1cbecf086968 100644 --- a/polly/test/ScopInfo/long-compile-time-alias-analysis.ll +++ b/polly/test/ScopInfo/long-compile-time-alias-analysis.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s ; Verify that the compilation of this test case does not take infinite time. ; At some point Polly tried to model this test case and got stuck in diff --git a/polly/test/ScopInfo/long-sequence-of-error-blocks-2.ll b/polly/test/ScopInfo/long-sequence-of-error-blocks-2.ll index 283a0bea7c49..c88ea1327389 100644 --- a/polly/test/ScopInfo/long-sequence-of-error-blocks-2.ll +++ b/polly/test/ScopInfo/long-sequence-of-error-blocks-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/polly/test/ScopInfo/long-sequence-of-error-blocks.ll b/polly/test/ScopInfo/long-sequence-of-error-blocks.ll index 812de273a7df..5b6ea9cc212d 100644 --- a/polly/test/ScopInfo/long-sequence-of-error-blocks.ll +++ b/polly/test/ScopInfo/long-sequence-of-error-blocks.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/polly/test/ScopInfo/loop-multiexit-succ-cond.ll b/polly/test/ScopInfo/loop-multiexit-succ-cond.ll index f8f47a332a13..350db05c6dc0 100644 --- a/polly/test/ScopInfo/loop-multiexit-succ-cond.ll +++ b/polly/test/ScopInfo/loop-multiexit-succ-cond.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -S < %s 2>&1 | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s --check-prefix=IR ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/loop_affine_bound_0.ll b/polly/test/ScopInfo/loop_affine_bound_0.ll index 77b0ebe8e494..33f49df7780f 100644 --- a/polly/test/ScopInfo/loop_affine_bound_0.ll +++ b/polly/test/ScopInfo/loop_affine_bound_0.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s ; void f(long a[][128], long N, long M) { ; long i, j; diff --git a/polly/test/ScopInfo/loop_affine_bound_1.ll b/polly/test/ScopInfo/loop_affine_bound_1.ll index 7c1eaa5dff8c..38e47b74465b 100644 --- a/polly/test/ScopInfo/loop_affine_bound_1.ll +++ b/polly/test/ScopInfo/loop_affine_bound_1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output< %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output< %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s ;void f(long a[][128], long N, long M) { ; long i, j; diff --git a/polly/test/ScopInfo/loop_affine_bound_2.ll b/polly/test/ScopInfo/loop_affine_bound_2.ll index 12d81c78b794..e34662f4e6ab 100644 --- a/polly/test/ScopInfo/loop_affine_bound_2.ll +++ b/polly/test/ScopInfo/loop_affine_bound_2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s ; void f(long a[][128], long N, long M) { ; long i, j; diff --git a/polly/test/ScopInfo/loop_carry.ll b/polly/test/ScopInfo/loop_carry.ll index 856efb730056..f7c1dca0919c 100644 --- a/polly/test/ScopInfo/loop_carry.ll +++ b/polly/test/ScopInfo/loop_carry.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/many-scalar-dependences.ll b/polly/test/ScopInfo/many-scalar-dependences.ll index 56e02d56254d..aaa02f581a1c 100644 --- a/polly/test/ScopInfo/many-scalar-dependences.ll +++ b/polly/test/ScopInfo/many-scalar-dependences.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(float a[100][100]) { ; float x; diff --git a/polly/test/ScopInfo/max-loop-depth.ll b/polly/test/ScopInfo/max-loop-depth.ll index 4da0f35121d0..3c7db4458604 100644 --- a/polly/test/ScopInfo/max-loop-depth.ll +++ b/polly/test/ScopInfo/max-loop-depth.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void bar(); ; void foo(int *A, int *B, long int N, long int M) { diff --git a/polly/test/ScopInfo/memcpy-raw-source.ll b/polly/test/ScopInfo/memcpy-raw-source.ll index c3ecce23cf5c..137ab8229220 100644 --- a/polly/test/ScopInfo/memcpy-raw-source.ll +++ b/polly/test/ScopInfo/memcpy-raw-source.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa,scoped-noalias-aa,tbaa '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -basic-aa -scoped-noalias-aa -tbaa -polly-print-scops -disable-output < %s ; ; Ensure that ScopInfo's alias analysis llvm.memcpy for, ; like the AliasSetTracker, preserves bitcasts. diff --git a/polly/test/ScopInfo/memcpy.ll b/polly/test/ScopInfo/memcpy.ll index 2e34b0d87a5f..705dea769e42 100644 --- a/polly/test/ScopInfo/memcpy.ll +++ b/polly/test/ScopInfo/memcpy.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-differing-element-types '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -S -aa-pipeline=basic-aa -polly-allow-differing-element-types -passes=polly-codegen < %s 2>&1 | FileCheck --check-prefix=IR %s +; RUN: opt %loadPolly -basic-aa -polly-allow-differing-element-types -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -S -basic-aa -polly-allow-differing-element-types -polly-codegen < %s | FileCheck --check-prefix=IR %s ; ; CHECK: Arrays { ; CHECK-NEXT: i8 MemRef_A[*]; // Element size 1 diff --git a/polly/test/ScopInfo/memmove.ll b/polly/test/ScopInfo/memmove.ll index 28a4ebeee7e2..15123422f419 100644 --- a/polly/test/ScopInfo/memmove.ll +++ b/polly/test/ScopInfo/memmove.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-differing-element-types '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -S -aa-pipeline=basic-aa -polly-allow-differing-element-types -passes=polly-codegen < %s 2>&1 | FileCheck --check-prefix=IR %s +; RUN: opt %loadPolly -basic-aa -polly-allow-differing-element-types -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -S -basic-aa -polly-allow-differing-element-types -polly-codegen < %s | FileCheck --check-prefix=IR %s ; ; CHECK: Arrays { ; CHECK-NEXT: i8 MemRef_A[*]; // Element size 1 diff --git a/polly/test/ScopInfo/memset.ll b/polly/test/ScopInfo/memset.ll index 163b58dc54dc..ef86b4c275e5 100644 --- a/polly/test/ScopInfo/memset.ll +++ b/polly/test/ScopInfo/memset.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-differing-element-types '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -S -polly-allow-differing-element-types -passes=polly-codegen < %s 2>&1 | FileCheck --check-prefix=IR %s +; RUN: opt %loadPolly -polly-allow-differing-element-types -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -S -polly-allow-differing-element-types -polly-codegen < %s | FileCheck --check-prefix=IR %s ; ; CHECK: Arrays { ; CHECK-NEXT: i8 MemRef_A[*]; // Element size 1 diff --git a/polly/test/ScopInfo/memset_null.ll b/polly/test/ScopInfo/memset_null.ll index 3d38fa1e6851..1608ff6ebef4 100644 --- a/polly/test/ScopInfo/memset_null.ll +++ b/polly/test/ScopInfo/memset_null.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-modref-calls '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-allow-modref-calls -S -passes=polly-codegen < %s +; RUN: opt %loadPolly -polly-allow-modref-calls -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-modref-calls -S -polly-codegen < %s ; ; Verify we can handle a memset to "null" and that we do not model it. ; TODO: FIXME: We could use the undefined memset to optimize the code further, diff --git a/polly/test/ScopInfo/mismatching-array-dimensions.ll b/polly/test/ScopInfo/mismatching-array-dimensions.ll index a2deef16eafd..a1c6d4e82127 100644 --- a/polly/test/ScopInfo/mismatching-array-dimensions.ll +++ b/polly/test/ScopInfo/mismatching-array-dimensions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; CHECK-NOT: AssumedContext diff --git a/polly/test/ScopInfo/mod_ref_access_pointee_arguments.ll b/polly/test/ScopInfo/mod_ref_access_pointee_arguments.ll index 202295abf57c..72889324e37e 100644 --- a/polly/test/ScopInfo/mod_ref_access_pointee_arguments.ll +++ b/polly/test/ScopInfo/mod_ref_access_pointee_arguments.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -polly-allow-modref-calls \ -; RUN: -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb -passes=polly-codegen -polly-allow-modref-calls \ +; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-scops -polly-allow-modref-calls \ +; RUN: -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-codegen -polly-allow-modref-calls \ ; RUN: -disable-output < %s ; ; Verify that we model the may-write access of the prefetch intrinsic diff --git a/polly/test/ScopInfo/mod_ref_read_pointee_arguments.ll b/polly/test/ScopInfo/mod_ref_read_pointee_arguments.ll index f1124f0a977b..2f6c6792fd9d 100644 --- a/polly/test/ScopInfo/mod_ref_read_pointee_arguments.ll +++ b/polly/test/ScopInfo/mod_ref_read_pointee_arguments.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -polly-allow-modref-calls \ -; RUN: -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -disable-output \ +; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-scops -polly-allow-modref-calls \ +; RUN: -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-codegen -disable-output \ ; RUN: -polly-allow-modref-calls < %s ; ; Verify that we model the read access of the gcread intrinsic diff --git a/polly/test/ScopInfo/mod_ref_read_pointer.ll b/polly/test/ScopInfo/mod_ref_read_pointer.ll index 24f276621532..657e37c68a7b 100644 --- a/polly/test/ScopInfo/mod_ref_read_pointer.ll +++ b/polly/test/ScopInfo/mod_ref_read_pointer.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-modref-calls '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-allow-modref-calls -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly -basic-aa -polly-allow-modref-calls -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-allow-modref-calls -polly-codegen -disable-output < %s ; ; Check that we assume the call to func has a read on the whole A array. ; diff --git a/polly/test/ScopInfo/mod_ref_read_pointers.ll b/polly/test/ScopInfo/mod_ref_read_pointers.ll index 260f759c1449..7ed3423a2aeb 100644 --- a/polly/test/ScopInfo/mod_ref_read_pointers.ll +++ b/polly/test/ScopInfo/mod_ref_read_pointers.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -polly-allow-modref-calls \ -; RUN: -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -aa-pipeline=basic-aa -passes=polly-codegen -disable-output \ +; RUN: opt %loadPolly -basic-aa -polly-print-scops -polly-allow-modref-calls \ +; RUN: -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-codegen -disable-output \ ; RUN: -polly-allow-modref-calls < %s ; ; Check that the call to func will "read" not only the A array but also the diff --git a/polly/test/ScopInfo/modulo_zext_1.ll b/polly/test/ScopInfo/modulo_zext_1.ll index 60083098eb08..d611ec4807b5 100644 --- a/polly/test/ScopInfo/modulo_zext_1.ll +++ b/polly/test/ScopInfo/modulo_zext_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/modulo_zext_2.ll b/polly/test/ScopInfo/modulo_zext_2.ll index 7ed70d085546..8d2321849174 100644 --- a/polly/test/ScopInfo/modulo_zext_2.ll +++ b/polly/test/ScopInfo/modulo_zext_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/modulo_zext_3.ll b/polly/test/ScopInfo/modulo_zext_3.ll index 67b26d813918..acb26dc1c77f 100644 --- a/polly/test/ScopInfo/modulo_zext_3.ll +++ b/polly/test/ScopInfo/modulo_zext_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/multi-scop.ll b/polly/test/ScopInfo/multi-scop.ll index 747f76bbf275..e26c8c7bae10 100644 --- a/polly/test/ScopInfo/multi-scop.ll +++ b/polly/test/ScopInfo/multi-scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-detect -polly-scops -disable-output < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; This test case contains two scops. diff --git a/polly/test/ScopInfo/multidim_2d-diagonal-matrix.ll b/polly/test/ScopInfo/multidim_2d-diagonal-matrix.ll index 8d023a671d86..278c06a2fdba 100644 --- a/polly/test/ScopInfo/multidim_2d-diagonal-matrix.ll +++ b/polly/test/ScopInfo/multidim_2d-diagonal-matrix.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/ScopInfo/multidim_2d_outer_parametric_offset.ll b/polly/test/ScopInfo/multidim_2d_outer_parametric_offset.ll index 6cd612d155cb..06a76466c25e 100644 --- a/polly/test/ScopInfo/multidim_2d_outer_parametric_offset.ll +++ b/polly/test/ScopInfo/multidim_2d_outer_parametric_offset.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll b/polly/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll index aed318b51b15..bfbe5682d44a 100644 --- a/polly/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll +++ b/polly/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/ScopInfo/multidim_2d_with_modref_call.ll b/polly/test/ScopInfo/multidim_2d_with_modref_call.ll index 872544d872cd..ba934adb675a 100644 --- a/polly/test/ScopInfo/multidim_2d_with_modref_call.ll +++ b/polly/test/ScopInfo/multidim_2d_with_modref_call.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-modref-calls \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-modref-calls \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-nonaffine \ +; RUN: -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -polly-allow-modref-calls -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NONAFFINE +; RUN: -polly-allow-modref-calls -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE ; TODO: We should delinearize the accesses despite the use in a call to a ; readonly function. For now we verify we do not delinearize them though. diff --git a/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll b/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll index add130e2087f..3da123fd1f60 100644 --- a/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll +++ b/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-modref-calls \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-modref-calls \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-nonaffine \ +; RUN: -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -polly-allow-modref-calls -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NONAFFINE +; RUN: -polly-allow-modref-calls -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE ; TODO: We should delinearize the accesses despite the use in a call to a ; readonly function. For now we verify we do not delinearize them though. diff --git a/polly/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll b/polly/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll index 5e0f58cb276b..988475575fec 100644 --- a/polly/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll +++ b/polly/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o]) { diff --git a/polly/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll b/polly/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll index 765077142df6..ddc35a46a633 100644 --- a/polly/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll +++ b/polly/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; #define N 400 ; diff --git a/polly/test/ScopInfo/multidim_fixedsize_multi_offset.ll b/polly/test/ScopInfo/multidim_fixedsize_multi_offset.ll index 8e26a2ad6a21..9c749f0c48c8 100644 --- a/polly/test/ScopInfo/multidim_fixedsize_multi_offset.ll +++ b/polly/test/ScopInfo/multidim_fixedsize_multi_offset.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Context: ; CHECK-NEXT: { : } diff --git a/polly/test/ScopInfo/multidim_fold_constant_dim.ll b/polly/test/ScopInfo/multidim_fold_constant_dim.ll index b142a2ab442f..e95d400a860c 100644 --- a/polly/test/ScopInfo/multidim_fold_constant_dim.ll +++ b/polly/test/ScopInfo/multidim_fold_constant_dim.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; struct com { ; double Real; diff --git a/polly/test/ScopInfo/multidim_fold_constant_dim_zero.ll b/polly/test/ScopInfo/multidim_fold_constant_dim_zero.ll index dac9dac1e7ad..57275e4024ab 100644 --- a/polly/test/ScopInfo/multidim_fold_constant_dim_zero.ll +++ b/polly/test/ScopInfo/multidim_fold_constant_dim_zero.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -debug -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -debug -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScopInfo/multidim_fortran_2d.ll b/polly/test/ScopInfo/multidim_fortran_2d.ll index ee13da875d4e..29279a4e886b 100644 --- a/polly/test/ScopInfo/multidim_fortran_2d.ll +++ b/polly/test/ScopInfo/multidim_fortran_2d.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' \ -; RUN: -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops \ +; RUN: -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; subroutine init_array(ni, nj, pi, pj, a) ; implicit none diff --git a/polly/test/ScopInfo/multidim_fortran_2d_params.ll b/polly/test/ScopInfo/multidim_fortran_2d_params.ll index f4978ecb35f7..93145b399ca5 100644 --- a/polly/test/ScopInfo/multidim_fortran_2d_params.ll +++ b/polly/test/ScopInfo/multidim_fortran_2d_params.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output \ +; RUN: opt %loadPolly -polly-print-scops -disable-output \ ; RUN: -polly-precise-fold-accesses \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; subroutine init_array(ni, nj, pi, pj, a) ; implicit none diff --git a/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll b/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll index f3a5e0ba9305..dff6a8be85cf 100644 --- a/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll +++ b/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-modref-calls \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-modref-calls \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-allow-nonaffine \ +; RUN: -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-allow-nonaffine \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -polly-allow-modref-calls -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NONAFFINE +; RUN: -polly-allow-modref-calls -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE ; TODO: We should delinearize the accesses despite the use in a call to a ; readonly function. For now we verify we do not delinearize them though. diff --git a/polly/test/ScopInfo/multidim_fortran_srem.ll b/polly/test/ScopInfo/multidim_fortran_srem.ll index fc65ff2954cf..8c24c5b8ee71 100644 --- a/polly/test/ScopInfo/multidim_fortran_srem.ll +++ b/polly/test/ScopInfo/multidim_fortran_srem.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" ; CHECK: Statements { diff --git a/polly/test/ScopInfo/multidim_gep_pointercast.ll b/polly/test/ScopInfo/multidim_gep_pointercast.ll index 6b69dd7bb571..20d59fa91eaf 100644 --- a/polly/test/ScopInfo/multidim_gep_pointercast.ll +++ b/polly/test/ScopInfo/multidim_gep_pointercast.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; The load access to A has a pointer-bitcast to another elements size before the ; GetElementPtr. Verify that we do not the GEP delinearization because it diff --git a/polly/test/ScopInfo/multidim_gep_pointercast2.ll b/polly/test/ScopInfo/multidim_gep_pointercast2.ll index 0c8139f7f8e1..deed9c7c3f57 100644 --- a/polly/test/ScopInfo/multidim_gep_pointercast2.ll +++ b/polly/test/ScopInfo/multidim_gep_pointercast2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Verfy that we do not use the GetElementPtr information to delinearize A ; because of the cast in-between. Use the single-dimensional modeling instead. diff --git a/polly/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll b/polly/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll index 4610f46ea082..9f7e6bc4a2a2 100644 --- a/polly/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll +++ b/polly/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o]) { diff --git a/polly/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll b/polly/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll index b64e0a99c73b..131bb7b3ebed 100644 --- a/polly/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll +++ b/polly/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-precise-fold-accesses '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-precise-fold-accesses -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o], long p, long q, long r) { diff --git a/polly/test/ScopInfo/multidim_many_references.ll b/polly/test/ScopInfo/multidim_many_references.ll index 0736fd947a31..b0483b267260 100644 --- a/polly/test/ScopInfo/multidim_many_references.ll +++ b/polly/test/ScopInfo/multidim_many_references.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-ignore-aliasing -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -polly-ignore-aliasing -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-ignore-aliasing -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -polly-ignore-aliasing -disable-output < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/multidim_nested_start_integer.ll b/polly/test/ScopInfo/multidim_nested_start_integer.ll index db99ab176a3a..741a0ef45c27 100644 --- a/polly/test/ScopInfo/multidim_nested_start_integer.ll +++ b/polly/test/ScopInfo/multidim_nested_start_integer.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o]) { diff --git a/polly/test/ScopInfo/multidim_nested_start_share_parameter.ll b/polly/test/ScopInfo/multidim_nested_start_share_parameter.ll index 0ecac3cdaaab..692746bad3d7 100644 --- a/polly/test/ScopInfo/multidim_nested_start_share_parameter.ll +++ b/polly/test/ScopInfo/multidim_nested_start_share_parameter.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o]) { diff --git a/polly/test/ScopInfo/multidim_only_ivs_2d.ll b/polly/test/ScopInfo/multidim_only_ivs_2d.ll index ccfa7a7de8e2..71245642e751 100644 --- a/polly/test/ScopInfo/multidim_only_ivs_2d.ll +++ b/polly/test/ScopInfo/multidim_only_ivs_2d.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" ; Derived from the following code: diff --git a/polly/test/ScopInfo/multidim_only_ivs_3d.ll b/polly/test/ScopInfo/multidim_only_ivs_3d.ll index 7a18aec573e8..a019d58b241d 100644 --- a/polly/test/ScopInfo/multidim_only_ivs_3d.ll +++ b/polly/test/ScopInfo/multidim_only_ivs_3d.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" ; void foo(long n, long m, long o, double A[n][m][o]) { diff --git a/polly/test/ScopInfo/multidim_only_ivs_3d_cast.ll b/polly/test/ScopInfo/multidim_only_ivs_3d_cast.ll index dd9c4d374f28..41577ef1a0be 100644 --- a/polly/test/ScopInfo/multidim_only_ivs_3d_cast.ll +++ b/polly/test/ScopInfo/multidim_only_ivs_3d_cast.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; void foo(int n, int m, int o, double A[n][m][o]) { ; diff --git a/polly/test/ScopInfo/multidim_only_ivs_3d_reverse.ll b/polly/test/ScopInfo/multidim_only_ivs_3d_reverse.ll index be1b1eb8fc8d..25907f2ee79c 100644 --- a/polly/test/ScopInfo/multidim_only_ivs_3d_reverse.ll +++ b/polly/test/ScopInfo/multidim_only_ivs_3d_reverse.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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-n8:16:32:64-S128" ; This test case checks for array access functions where the order in which the diff --git a/polly/test/ScopInfo/multidim_param_in_subscript-2.ll b/polly/test/ScopInfo/multidim_param_in_subscript-2.ll index f0cd1589b987..0790664f7129 100644 --- a/polly/test/ScopInfo/multidim_param_in_subscript-2.ll +++ b/polly/test/ScopInfo/multidim_param_in_subscript-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-precise-fold-accesses '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-precise-fold-accesses -polly-print-scops -disable-output < %s | FileCheck %s ; ; void foo(long n, long m, float A[][n][m]) { ; for (long i = 0; i < 100; i++) diff --git a/polly/test/ScopInfo/multidim_param_in_subscript.ll b/polly/test/ScopInfo/multidim_param_in_subscript.ll index ca423919e488..b8ec80b321fe 100644 --- a/polly/test/ScopInfo/multidim_param_in_subscript.ll +++ b/polly/test/ScopInfo/multidim_param_in_subscript.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; ; void foo(long n, float A[][n]) { diff --git a/polly/test/ScopInfo/multidim_parameter_addrec_product.ll b/polly/test/ScopInfo/multidim_parameter_addrec_product.ll index ec311d42386a..7db3e9dc3b5f 100644 --- a/polly/test/ScopInfo/multidim_parameter_addrec_product.ll +++ b/polly/test/ScopInfo/multidim_parameter_addrec_product.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s ; ; void foo(float *A, long *p) { ; for (long i = 0; i < 100; i++) diff --git a/polly/test/ScopInfo/multidim_single_and_multidim_array.ll b/polly/test/ScopInfo/multidim_single_and_multidim_array.ll index 0d51aa115559..1e302dec4861 100644 --- a/polly/test/ScopInfo/multidim_single_and_multidim_array.ll +++ b/polly/test/ScopInfo/multidim_single_and_multidim_array.ll @@ -1,11 +1,11 @@ -; RUN: opt %loadPolly '-passes=print' -polly-delinearize=false -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -polly-delinearize=false -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NONAFFINE -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=DELIN -; RUN: opt %loadPolly '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s --check-prefix=DELIN -; RUN: opt %loadPolly '-passes=print' -polly-delinearize=false -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -polly-delinearize=false -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s --check-prefix=NONAFFINE -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=DELIN -; RUN: opt %loadPolly '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s --check-prefix=DELIN +; RUN: opt %loadPolly -polly-print-scops -polly-delinearize=false -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-delinearize=false -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=DELIN +; RUN: opt %loadPolly -polly-print-scops -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=DELIN +; RUN: opt %loadPolly -polly-print-function-scops -polly-delinearize=false -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -polly-delinearize=false -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=NONAFFINE +; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s --check-prefix=DELIN +; RUN: opt %loadPolly -polly-print-function-scops -polly-allow-nonaffine -disable-output < %s | FileCheck %s --check-prefix=DELIN target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/multidim_srem.ll b/polly/test/ScopInfo/multidim_srem.ll index b4eee668207c..f89843f0a5bc 100644 --- a/polly/test/ScopInfo/multidim_srem.ll +++ b/polly/test/ScopInfo/multidim_srem.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void foo(long n, float A[][n][n]) { ; for (long i = 0; i < 200; i++) diff --git a/polly/test/ScopInfo/multidim_with_bitcast.ll b/polly/test/ScopInfo/multidim_with_bitcast.ll index 8af2e18265b0..b77ff689b953 100644 --- a/polly/test/ScopInfo/multidim_with_bitcast.ll +++ b/polly/test/ScopInfo/multidim_with_bitcast.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/multiple-binary-or-conditions.ll b/polly/test/ScopInfo/multiple-binary-or-conditions.ll index 481f799ed0fe..b905a11f577c 100644 --- a/polly/test/ScopInfo/multiple-binary-or-conditions.ll +++ b/polly/test/ScopInfo/multiple-binary-or-conditions.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -disable-output < %s ; ; void or(float *A, long n, long m) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/multiple-types-access-offset-not-dividable-by-element-size.ll b/polly/test/ScopInfo/multiple-types-access-offset-not-dividable-by-element-size.ll index 69b00402ba6b..2d03ad941c05 100644 --- a/polly/test/ScopInfo/multiple-types-access-offset-not-dividable-by-element-size.ll +++ b/polly/test/ScopInfo/multiple-types-access-offset-not-dividable-by-element-size.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -pass-remarks-analysis="polly-scops" \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -pass-remarks-analysis="polly-scops" \ ; RUN: -polly-allow-differing-element-types \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/multiple-types-non-affine-2.ll b/polly/test/ScopInfo/multiple-types-non-affine-2.ll index a7e9a31744b4..5b0aa5de1e71 100644 --- a/polly/test/ScopInfo/multiple-types-non-affine-2.ll +++ b/polly/test/ScopInfo/multiple-types-non-affine-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -passes=polly-codegen -polly-allow-nonaffine -disable-output +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -polly-print-scops -polly-allow-nonaffine -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -polly-codegen -polly-allow-nonaffine -disable-output ; ; // Check that accessing one array with different types works, ; // even though some accesses are non-affine. diff --git a/polly/test/ScopInfo/multiple-types-non-affine.ll b/polly/test/ScopInfo/multiple-types-non-affine.ll index e49612aa2791..8e4be4c86d5a 100644 --- a/polly/test/ScopInfo/multiple-types-non-affine.ll +++ b/polly/test/ScopInfo/multiple-types-non-affine.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types '-passes=print' -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -passes=polly-codegen -polly-allow-nonaffine -disable-output +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -polly-print-scops -polly-allow-nonaffine -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-differing-element-types -polly-codegen -polly-allow-nonaffine -disable-output ; ; // Check that accessing one array with different types works, ; // even though some accesses are non-affine. diff --git a/polly/test/ScopInfo/multiple-types-non-power-of-two-2.ll b/polly/test/ScopInfo/multiple-types-non-power-of-two-2.ll index 8347de936eff..01f5923457b4 100644 --- a/polly/test/ScopInfo/multiple-types-non-power-of-two-2.ll +++ b/polly/test/ScopInfo/multiple-types-non-power-of-two-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-allow-differing-element-types -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-allow-differing-element-types -disable-output < %s | FileCheck %s ; ; void multiple_types(i8 *A) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/multiple-types-non-power-of-two.ll b/polly/test/ScopInfo/multiple-types-non-power-of-two.ll index 077ff1a741ad..142a5ac395b3 100644 --- a/polly/test/ScopInfo/multiple-types-non-power-of-two.ll +++ b/polly/test/ScopInfo/multiple-types-non-power-of-two.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-allow-differing-element-types -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-allow-differing-element-types -disable-output < %s | FileCheck %s ; ; void multiple_types(i8 *A) { ; for (long i = 0; i < 100; i++) { diff --git a/polly/test/ScopInfo/multiple-types-two-dimensional-2.ll b/polly/test/ScopInfo/multiple-types-two-dimensional-2.ll index 431a0c1e966f..1e2e53e85c25 100644 --- a/polly/test/ScopInfo/multiple-types-two-dimensional-2.ll +++ b/polly/test/ScopInfo/multiple-types-two-dimensional-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-analysis="polly-scops" \ +; RUN: opt %loadPolly -polly-print-scops -pass-remarks-analysis="polly-scops" \ ; RUN: -polly-allow-differing-element-types \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/multiple-types-two-dimensional.ll b/polly/test/ScopInfo/multiple-types-two-dimensional.ll index 2cc2454ca6e4..21dc96e6f95d 100644 --- a/polly/test/ScopInfo/multiple-types-two-dimensional.ll +++ b/polly/test/ScopInfo/multiple-types-two-dimensional.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-analysis="polly-scops" \ +; RUN: opt %loadPolly -polly-print-scops -pass-remarks-analysis="polly-scops" \ ; RUN: -polly-allow-differing-element-types \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; diff --git a/polly/test/ScopInfo/multiple-types.ll b/polly/test/ScopInfo/multiple-types.ll index b7006c104426..16db191c522f 100644 --- a/polly/test/ScopInfo/multiple-types.ll +++ b/polly/test/ScopInfo/multiple-types.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' \ -; RUN: -polly-allow-differing-element-types -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops \ +; RUN: -polly-allow-differing-element-types -disable-output < %s | FileCheck %s ; ; // Check that accessing one array with different types works. ; void multiple_types(char *Short, char *Float, char *Double) { diff --git a/polly/test/ScopInfo/multiple_exiting_blocks.ll b/polly/test/ScopInfo/multiple_exiting_blocks.ll index a21a7252c2ff..f8e5d4106a16 100644 --- a/polly/test/ScopInfo/multiple_exiting_blocks.ll +++ b/polly/test/ScopInfo/multiple_exiting_blocks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/multiple_exiting_blocks_two_loop.ll b/polly/test/ScopInfo/multiple_exiting_blocks_two_loop.ll index e56c8b7094ea..c695f3c913db 100644 --- a/polly/test/ScopInfo/multiple_exiting_blocks_two_loop.ll +++ b/polly/test/ScopInfo/multiple_exiting_blocks_two_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/multiple_latch_blocks.ll b/polly/test/ScopInfo/multiple_latch_blocks.ll index c1a64ee1c3cb..d3949e7e2c3c 100644 --- a/polly/test/ScopInfo/multiple_latch_blocks.ll +++ b/polly/test/ScopInfo/multiple_latch_blocks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Domain := ; CHECK: [N, P] -> { Stmt_if_end[i0] : 0 <= i0 < N and (i0 > P or i0 < P) }; diff --git a/polly/test/ScopInfo/nested-loops.ll b/polly/test/ScopInfo/nested-loops.ll index 2819ae461fce..ed814f826829 100644 --- a/polly/test/ScopInfo/nested-loops.ll +++ b/polly/test/ScopInfo/nested-loops.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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" diff --git a/polly/test/ScopInfo/no-scalar-deps-in-non-affine-subregion.ll b/polly/test/ScopInfo/no-scalar-deps-in-non-affine-subregion.ll index 6fc364076750..7c55e242641c 100644 --- a/polly/test/ScopInfo/no-scalar-deps-in-non-affine-subregion.ll +++ b/polly/test/ScopInfo/no-scalar-deps-in-non-affine-subregion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that we do not generate any scalar dependences regarding x. It is ; defined and used on the non-affine subregion only, thus we do not need diff --git a/polly/test/ScopInfo/non-affine-region-phi.ll b/polly/test/ScopInfo/non-affine-region-phi.ll index 4de76c4adfb1..f99782b9a0ff 100644 --- a/polly/test/ScopInfo/non-affine-region-phi.ll +++ b/polly/test/ScopInfo/non-affine-region-phi.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -S < %s 2>&1 | FileCheck %s --check-prefix=CODE -; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -S < %s | FileCheck %s --check-prefix=CODE +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s ; ; Verify there is a phi in the non-affine region but it is not represented in ; the SCoP as all operands as well as the uses are inside the region too. diff --git a/polly/test/ScopInfo/non-affine-region-with-loop-2.ll b/polly/test/ScopInfo/non-affine-region-with-loop-2.ll index 9870b813d287..b673fda5ec3c 100644 --- a/polly/test/ScopInfo/non-affine-region-with-loop-2.ll +++ b/polly/test/ScopInfo/non-affine-region-with-loop-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-nonaffine-loops '-passes=print,print,scop(polly-codegen)' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-allow-nonaffine-loops -polly-print-scops -polly-codegen -disable-output < %s | FileCheck %s ; ; CHECK: Stmt_loop3 ; CHECK: Domain := diff --git a/polly/test/ScopInfo/non-affine-region-with-loop.ll b/polly/test/ScopInfo/non-affine-region-with-loop.ll index e1342e1b5257..32dde8b4a682 100644 --- a/polly/test/ScopInfo/non-affine-region-with-loop.ll +++ b/polly/test/ScopInfo/non-affine-region-with-loop.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine-loops -passes=polly-codegen -disable-output +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-codegen -disable-output ; ; CHECK: Domain := ; CHECK-NEXT: { Stmt_loop2__TO__loop[] }; diff --git a/polly/test/ScopInfo/non-precise-inv-load-1.ll b/polly/test/ScopInfo/non-precise-inv-load-1.ll index f35235d2de8f..5394206dd547 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-1.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; Verify we do hoist the invariant access to I with a execution context ; as the address computation might wrap in the original but not in our diff --git a/polly/test/ScopInfo/non-precise-inv-load-2.ll b/polly/test/ScopInfo/non-precise-inv-load-2.ll index c538c0e7bda0..5c0c56513a08 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-2.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; ; CHECK: Invariant Accesses: { diff --git a/polly/test/ScopInfo/non-precise-inv-load-3.ll b/polly/test/ScopInfo/non-precise-inv-load-3.ll index c16879a18562..09d09319656b 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-3.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/non-precise-inv-load-4.ll b/polly/test/ScopInfo/non-precise-inv-load-4.ll index 24f9d45d28e7..da5f656576d1 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-4.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; Verify we hoist I[0] without execution context even though it ; is executed in a statement with an invalid domain. diff --git a/polly/test/ScopInfo/non-precise-inv-load-5.ll b/polly/test/ScopInfo/non-precise-inv-load-5.ll index 17046685562d..bff5f59a3302 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-5.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; Verify we do not hoist I[c] without execution context because it ; is executed in a statement with an invalid domain and it depends diff --git a/polly/test/ScopInfo/non-precise-inv-load-6.ll b/polly/test/ScopInfo/non-precise-inv-load-6.ll index eeada91299f6..03540a8ead96 100644 --- a/polly/test/ScopInfo/non-precise-inv-load-6.ll +++ b/polly/test/ScopInfo/non-precise-inv-load-6.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; Check that we model the execution context correctly. ; diff --git a/polly/test/ScopInfo/non-pure-function-call.ll b/polly/test/ScopInfo/non-pure-function-call.ll index 974c9ba0527d..4ffb8d28865d 100644 --- a/polly/test/ScopInfo/non-pure-function-call.ll +++ b/polly/test/ScopInfo/non-pure-function-call.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll b/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll index 983c45bc7536..27998b50b74f 100644 --- a/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll +++ b/polly/test/ScopInfo/non-pure-function-calls-causes-dead-blocks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Error blocks are skipped during SCoP detection. We skip them during ; SCoP formation too as they might contain instructions we can not handle. diff --git a/polly/test/ScopInfo/non-pure-function-calls.ll b/polly/test/ScopInfo/non-pure-function-calls.ll index fd6a6dc3f8f1..3ecf75853773 100644 --- a/polly/test/ScopInfo/non-pure-function-calls.ll +++ b/polly/test/ScopInfo/non-pure-function-calls.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Allow the user to define function names that are treated as ; error functions and assumed not to be executed. diff --git a/polly/test/ScopInfo/non_affine_access.ll b/polly/test/ScopInfo/non_affine_access.ll index e20be38598db..a83c9484ad52 100644 --- a/polly/test/ScopInfo/non_affine_access.ll +++ b/polly/test/ScopInfo/non_affine_access.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print,print' -polly-allow-nonaffine -disable-output < %s 2>&1 | FileCheck %s -check-prefix=NONAFFINE +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-allow-nonaffine -disable-output < %s | FileCheck %s -check-prefix=NONAFFINE 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-n8:16:32:64-S128" ; void foo(long *A) { diff --git a/polly/test/ScopInfo/non_affine_region_1.ll b/polly/test/ScopInfo/non_affine_region_1.ll index 623d322c508c..7c4312599cf0 100644 --- a/polly/test/ScopInfo/non_affine_region_1.ll +++ b/polly/test/ScopInfo/non_affine_region_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-print-scops -disable-output < %s | FileCheck %s ; ; Verify only the incoming scalar x is modeled as a read in the non-affine ; region. diff --git a/polly/test/ScopInfo/non_affine_region_2.ll b/polly/test/ScopInfo/non_affine_region_2.ll index ba20d9e6cf6e..0bc467c92bcb 100644 --- a/polly/test/ScopInfo/non_affine_region_2.ll +++ b/polly/test/ScopInfo/non_affine_region_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Verify the scalar x defined in a non-affine subregion is written as it ; escapes the region. In this test the two conditionals inside the region diff --git a/polly/test/ScopInfo/non_affine_region_3.ll b/polly/test/ScopInfo/non_affine_region_3.ll index ff619b579355..6d5f94df6110 100644 --- a/polly/test/ScopInfo/non_affine_region_3.ll +++ b/polly/test/ScopInfo/non_affine_region_3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s ; ; Verify the scalar x defined in a non-affine subregion is written as it ; escapes the region. In this test the two conditionals inside the region diff --git a/polly/test/ScopInfo/non_affine_region_4.ll b/polly/test/ScopInfo/non_affine_region_4.ll index 70f40727849a..f37e0ecb89d1 100644 --- a/polly/test/ScopInfo/non_affine_region_4.ll +++ b/polly/test/ScopInfo/non_affine_region_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Verify that both scalars (x and y) are properly written in the non-affine ; region and read afterwards. diff --git a/polly/test/ScopInfo/nonaffine-buildMemoryAccess.ll b/polly/test/ScopInfo/nonaffine-buildMemoryAccess.ll index 246610ee5194..445dd164898b 100644 --- a/polly/test/ScopInfo/nonaffine-buildMemoryAccess.ll +++ b/polly/test/ScopInfo/nonaffine-buildMemoryAccess.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine-loops '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine-loops -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Domain := ; CHECK-NEXT: { Stmt_while_cond_i__TO__while_end_i[] }; diff --git a/polly/test/ScopInfo/not-a-reduction.ll b/polly/test/ScopInfo/not-a-reduction.ll index 7fe41332c67d..87909290fd71 100644 --- a/polly/test/ScopInfo/not-a-reduction.ll +++ b/polly/test/ScopInfo/not-a-reduction.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | not FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s 2>&1 | not FileCheck %s ;#define TYPE float ;#define NUM 4 diff --git a/polly/test/ScopInfo/opaque-struct.ll b/polly/test/ScopInfo/opaque-struct.ll index 1a0859f71f36..19fdd9bf9179 100644 --- a/polly/test/ScopInfo/opaque-struct.ll +++ b/polly/test/ScopInfo/opaque-struct.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-scops -disable-output < %s ; ; Check that we do not crash with unsized (opaque) types. ; diff --git a/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node-nonaffine-subregion.ll b/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node-nonaffine-subregion.ll index 58c2116ab9dc..394173bdc986 100644 --- a/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node-nonaffine-subregion.ll +++ b/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node-nonaffine-subregion.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-codegen -S < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s ; ; Check whether %newval is identified as escaping value, even though it is used ; in a phi that is in the region. Non-affine subregion case. diff --git a/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node.ll b/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node.ll index 7986399a6c7e..e17164e89372 100644 --- a/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node.ll +++ b/polly/test/ScopInfo/out-of-scop-use-in-region-entry-phi-node.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] ; CHECK-NEXT: [p_0] -> { Stmt_bb3[] -> MemRef_tmp5[] }; diff --git a/polly/test/ScopInfo/parameter-constant-division.ll b/polly/test/ScopInfo/parameter-constant-division.ll index f1e006e29454..cd6b9e3526aa 100644 --- a/polly/test/ScopInfo/parameter-constant-division.ll +++ b/polly/test/ScopInfo/parameter-constant-division.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' \ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops \ ; RUN: -polly-invariant-load-hoisting=true \ -; RUN: -disable-output < %s 2>&1 | FileCheck %s +; RUN: -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/parameter_in_dead_statement.ll b/polly/test/ScopInfo/parameter_in_dead_statement.ll index 13602515d46f..4b4a87f098d7 100644 --- a/polly/test/ScopInfo/parameter_in_dead_statement.ll +++ b/polly/test/ScopInfo/parameter_in_dead_statement.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -S \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -polly-print-scops -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -S \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s --check-prefix=IR ; ; Verify we do not create assumptions based on the parameter p_1 which is the ; load %0 and due to error-assumptions not "part of the SCoP". diff --git a/polly/test/ScopInfo/parameter_product.ll b/polly/test/ScopInfo/parameter_product.ll index 9783268f2a10..1ba7280f97c9 100644 --- a/polly/test/ScopInfo/parameter_product.ll +++ b/polly/test/ScopInfo/parameter_product.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; int n, m; ; void foo(char* __restrict a) diff --git a/polly/test/ScopInfo/parameter_with_constant_factor_in_add.ll b/polly/test/ScopInfo/parameter_with_constant_factor_in_add.ll index f750cf7f3320..72d580801573 100644 --- a/polly/test/ScopInfo/parameter_with_constant_factor_in_add.ll +++ b/polly/test/ScopInfo/parameter_with_constant_factor_in_add.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that the access function of the store is simple and concise ; diff --git a/polly/test/ScopInfo/partially_invariant_load_1.ll b/polly/test/ScopInfo/partially_invariant_load_1.ll index 5757e4d7095c..274a7873c782 100644 --- a/polly/test/ScopInfo/partially_invariant_load_1.ll +++ b/polly/test/ScopInfo/partially_invariant_load_1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -passes=polly-codegen -polly-invariant-load-hoisting=true -S < %s 2>&1 | FileCheck %s --check-prefix=IR +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-codegen -polly-invariant-load-hoisting=true -S < %s | FileCheck %s --check-prefix=IR ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/partially_invariant_load_2.ll b/polly/test/ScopInfo/partially_invariant_load_2.ll index e07d6d39132b..ee1092883f72 100644 --- a/polly/test/ScopInfo/partially_invariant_load_2.ll +++ b/polly/test/ScopInfo/partially_invariant_load_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-invariant-load-hoisting=true -disable-output < %s | FileCheck %s ; ; Check that we do not try to preload *I and assume p != 42. ; diff --git a/polly/test/ScopInfo/phi-in-non-affine-region.ll b/polly/test/ScopInfo/phi-in-non-affine-region.ll index c8e81fd1ba98..6ef24e3f1456 100644 --- a/polly/test/ScopInfo/phi-in-non-affine-region.ll +++ b/polly/test/ScopInfo/phi-in-non-affine-region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; Verify that 'tmp' is stored in bb1 and read by bb3, as it is needed as ; incoming value for the tmp11 PHI node. diff --git a/polly/test/ScopInfo/phi_after_error_block.ll b/polly/test/ScopInfo/phi_after_error_block.ll index 21d532b06d60..039fb86bec5b 100644 --- a/polly/test/ScopInfo/phi_after_error_block.ll +++ b/polly/test/ScopInfo/phi_after_error_block.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s declare void @bar() diff --git a/polly/test/ScopInfo/phi_condition_modeling_1.ll b/polly/test/ScopInfo/phi_condition_modeling_1.ll index ca87055630c6..a879c2005ad8 100644 --- a/polly/test/ScopInfo/phi_condition_modeling_1.ll +++ b/polly/test/ScopInfo/phi_condition_modeling_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, int c, int N) { ; int tmp; diff --git a/polly/test/ScopInfo/phi_condition_modeling_2.ll b/polly/test/ScopInfo/phi_condition_modeling_2.ll index 10511ef0009f..cedc140f8438 100644 --- a/polly/test/ScopInfo/phi_condition_modeling_2.ll +++ b/polly/test/ScopInfo/phi_condition_modeling_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, int c, int N) { ; int tmp; diff --git a/polly/test/ScopInfo/phi_conditional_simple_1.ll b/polly/test/ScopInfo/phi_conditional_simple_1.ll index 2a009dc26d24..90213a953767 100644 --- a/polly/test/ScopInfo/phi_conditional_simple_1.ll +++ b/polly/test/ScopInfo/phi_conditional_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void jd(int *A, int c) { ; for (int i = 0; i < 1024; i++) { diff --git a/polly/test/ScopInfo/phi_loop_carried_float.ll b/polly/test/ScopInfo/phi_loop_carried_float.ll index 5bb740154877..d8d2608329bc 100644 --- a/polly/test/ScopInfo/phi_loop_carried_float.ll +++ b/polly/test/ScopInfo/phi_loop_carried_float.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; float f(float *A, int N) { ; float tmp = 0; diff --git a/polly/test/ScopInfo/phi_not_grouped_at_top.ll b/polly/test/ScopInfo/phi_not_grouped_at_top.ll index 1ed22b3fec42..be082165b635 100644 --- a/polly/test/ScopInfo/phi_not_grouped_at_top.ll +++ b/polly/test/ScopInfo/phi_not_grouped_at_top.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -passes=polly-prepare -disable-output < %s +; RUN: opt %loadPolly -polly-prepare -disable-output < %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-n8:16:32:64" declare i32 @funa() align 2 diff --git a/polly/test/ScopInfo/phi_scalar_simple_1.ll b/polly/test/ScopInfo/phi_scalar_simple_1.ll index eab261b0d153..d042613c023f 100644 --- a/polly/test/ScopInfo/phi_scalar_simple_1.ll +++ b/polly/test/ScopInfo/phi_scalar_simple_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; The assumed context should be empty since the flags on the IV ; increments already guarantee that there is no wrap in the loop trip diff --git a/polly/test/ScopInfo/phi_scalar_simple_2.ll b/polly/test/ScopInfo/phi_scalar_simple_2.ll index 73bef9601f33..fb4292e05ca6 100644 --- a/polly/test/ScopInfo/phi_scalar_simple_2.ll +++ b/polly/test/ScopInfo/phi_scalar_simple_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; ; int jd(int *restrict A, int x, int N, int c) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/phi_with_invoke_edge.ll b/polly/test/ScopInfo/phi_with_invoke_edge.ll index 3d7b7d3d38d5..dbcf04c0561a 100644 --- a/polly/test/ScopInfo/phi_with_invoke_edge.ll +++ b/polly/test/ScopInfo/phi_with_invoke_edge.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-detect -disable-output < %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-n8:16:32:64" declare i32 @generic_personality_v0(i32, i64, ptr, ptr) diff --git a/polly/test/ScopInfo/pointer-comparison-no-nsw.ll b/polly/test/ScopInfo/pointer-comparison-no-nsw.ll index 40d2138f81d5..094c5ccab54d 100644 --- a/polly/test/ScopInfo/pointer-comparison-no-nsw.ll +++ b/polly/test/ScopInfo/pointer-comparison-no-nsw.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, int *B) { ; while (A != B) { diff --git a/polly/test/ScopInfo/pointer-comparison.ll b/polly/test/ScopInfo/pointer-comparison.ll index 960b9c5f3132..15ce0491209a 100644 --- a/polly/test/ScopInfo/pointer-comparison.ll +++ b/polly/test/ScopInfo/pointer-comparison.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; TODO: FIXME: Investigate why we need a InvalidContext here. ; diff --git a/polly/test/ScopInfo/pointer-type-expressions.ll b/polly/test/ScopInfo/pointer-type-expressions.ll index 919a9fd4000b..ebbb644340f6 100644 --- a/polly/test/ScopInfo/pointer-type-expressions.ll +++ b/polly/test/ScopInfo/pointer-type-expressions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; void f(int a[], int N, float *P) { ; int i; diff --git a/polly/test/ScopInfo/pointer-used-as-base-pointer-and-scalar-read.ll b/polly/test/ScopInfo/pointer-used-as-base-pointer-and-scalar-read.ll index 1eb053c83132..3ac86a3443af 100644 --- a/polly/test/ScopInfo/pointer-used-as-base-pointer-and-scalar-read.ll +++ b/polly/test/ScopInfo/pointer-used-as-base-pointer-and-scalar-read.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; In this test case we pass a pointer %A into a PHI node and also use this ; pointer as base pointer of an array store. As a result, we get both scalar diff --git a/polly/test/ScopInfo/polly-timeout-parameter-bounds.ll b/polly/test/ScopInfo/polly-timeout-parameter-bounds.ll index 7723c185e41c..8152010c2c99 100644 --- a/polly/test/ScopInfo/polly-timeout-parameter-bounds.ll +++ b/polly/test/ScopInfo/polly-timeout-parameter-bounds.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; CHECK: Statements { ; CHECK-NEXT: Stmt_bb9 diff --git a/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll b/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll index 3cc3e51ef013..4a68acd3d509 100644 --- a/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll +++ b/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" diff --git a/polly/test/ScopInfo/process_added_dimensions.ll b/polly/test/ScopInfo/process_added_dimensions.ll index 66c9ded40f7c..6cb270a071f4 100644 --- a/polly/test/ScopInfo/process_added_dimensions.ll +++ b/polly/test/ScopInfo/process_added_dimensions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; CHECK: Context: ; CHECK-NEXT: { : } diff --git a/polly/test/ScopInfo/pwaff-complexity-bailout.ll b/polly/test/ScopInfo/pwaff-complexity-bailout.ll index 5119334745bc..19dd156d27db 100644 --- a/polly/test/ScopInfo/pwaff-complexity-bailout.ll +++ b/polly/test/ScopInfo/pwaff-complexity-bailout.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-analysis=.* -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-scops -pass-remarks-analysis=.* -disable-output < %s 2>&1 | FileCheck %s ; Make sure we hit the complexity bailout, and don't crash. ; CHECK: Low complexity assumption: { : false } diff --git a/polly/test/ScopInfo/ranged_parameter.ll b/polly/test/ScopInfo/ranged_parameter.ll index b5cb77593352..4b04960ee845 100644 --- a/polly/test/ScopInfo/ranged_parameter.ll +++ b/polly/test/ScopInfo/ranged_parameter.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that the constraints on the parameter derived from the ; range metadata (see bottom of the file) are present: diff --git a/polly/test/ScopInfo/ranged_parameter_2.ll b/polly/test/ScopInfo/ranged_parameter_2.ll index 52933398f796..cd7d2bfb84d0 100644 --- a/polly/test/ScopInfo/ranged_parameter_2.ll +++ b/polly/test/ScopInfo/ranged_parameter_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output -polly-allow-nonaffine -polly-invariant-load-hoisting=true < %s \ +; RUN: opt %loadPolly -polly-print-scops -disable-output -polly-allow-nonaffine -polly-invariant-load-hoisting=true < %s \ ; RUN: -debug 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/polly/test/ScopInfo/ranged_parameter_wrap.ll b/polly/test/ScopInfo/ranged_parameter_wrap.ll index 724427fabfd1..173746352cf0 100644 --- a/polly/test/ScopInfo/ranged_parameter_wrap.ll +++ b/polly/test/ScopInfo/ranged_parameter_wrap.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that the constraints on the parameter derived from the ; __wrapping__ range metadata (see bottom of the file) are present: diff --git a/polly/test/ScopInfo/ranged_parameter_wrap_2.ll b/polly/test/ScopInfo/ranged_parameter_wrap_2.ll index 234c3edde14e..33f57f37a1e8 100644 --- a/polly/test/ScopInfo/ranged_parameter_wrap_2.ll +++ b/polly/test/ScopInfo/ranged_parameter_wrap_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that the context is built fast and does not explode due to us ; combining a large number of non-convex ranges. Instead, after a certain diff --git a/polly/test/ScopInfo/read-only-scalar-used-in-phi-2.ll b/polly/test/ScopInfo/read-only-scalar-used-in-phi-2.ll index 1ab8fe897308..23c7aa261ac0 100644 --- a/polly/test/ScopInfo/read-only-scalar-used-in-phi-2.ll +++ b/polly/test/ScopInfo/read-only-scalar-used-in-phi-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; float foo(float sum, float A[]) { ; diff --git a/polly/test/ScopInfo/read-only-scalar-used-in-phi.ll b/polly/test/ScopInfo/read-only-scalar-used-in-phi.ll index 358b51904c72..20f44c94251c 100644 --- a/polly/test/ScopInfo/read-only-scalar-used-in-phi.ll +++ b/polly/test/ScopInfo/read-only-scalar-used-in-phi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; float foo(float sum, float A[]) { ; diff --git a/polly/test/ScopInfo/read-only-scalars.ll b/polly/test/ScopInfo/read-only-scalars.ll index 43a456ea9977..71c2d21e357a 100644 --- a/polly/test/ScopInfo/read-only-scalars.ll +++ b/polly/test/ScopInfo/read-only-scalars.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-analyze-read-only-scalars=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-analyze-read-only-scalars=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=SCALARS +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-analyze-read-only-scalars=false -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-analyze-read-only-scalars=true -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=SCALARS ; CHECK-NOT: Memref_scalar diff --git a/polly/test/ScopInfo/read-only-statements.ll b/polly/test/ScopInfo/read-only-statements.ll index 3fa72789f4e1..a93063ea3ad6 100644 --- a/polly/test/ScopInfo/read-only-statements.ll +++ b/polly/test/ScopInfo/read-only-statements.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check we remove read only statements. ; diff --git a/polly/test/ScopInfo/reduction_alternating_base.ll b/polly/test/ScopInfo/reduction_alternating_base.ll index f44367f295ff..854e28023a3e 100644 --- a/polly/test/ScopInfo/reduction_alternating_base.ll +++ b/polly/test/ScopInfo/reduction_alternating_base.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; ; void f(int *A) { diff --git a/polly/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll b/polly/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll index 5636ee7ed828..fb0274972082 100644 --- a/polly/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll +++ b/polly/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Reduction Type: NONE ; diff --git a/polly/test/ScopInfo/reduction_different_index.ll b/polly/test/ScopInfo/reduction_different_index.ll index 7ed9e662a15c..575e5a16d7b2 100644 --- a/polly/test/ScopInfo/reduction_different_index.ll +++ b/polly/test/ScopInfo/reduction_different_index.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; Verify if the following case is not detected as reduction. ; ; void f(int *A,int *sum) { diff --git a/polly/test/ScopInfo/reduction_different_index1.ll b/polly/test/ScopInfo/reduction_different_index1.ll index f868bd657f3b..39bd3c4b9abe 100644 --- a/polly/test/ScopInfo/reduction_different_index1.ll +++ b/polly/test/ScopInfo/reduction_different_index1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; Verify if the following case is not detected as reduction. ; ; void f(int *A, int *sum, int i1, int i2) { diff --git a/polly/test/ScopInfo/reduction_disabled_multiplicative.ll b/polly/test/ScopInfo/reduction_disabled_multiplicative.ll index b031fd352323..7120740fbf34 100644 --- a/polly/test/ScopInfo/reduction_disabled_multiplicative.ll +++ b/polly/test/ScopInfo/reduction_disabled_multiplicative.ll @@ -1,4 +1,4 @@ -; RUN: opt -aa-pipeline=basic-aa %loadPolly -polly-stmt-granularity=bb '-passes=print' -polly-disable-multiplicative-reductions -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt -basic-aa %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-disable-multiplicative-reductions -disable-output < %s | FileCheck %s ; ; CHECK: ReadAccess := [Reduction Type: + ; CHECK: { Stmt_for_body[i0] -> MemRef_sum[0] }; diff --git a/polly/test/ScopInfo/reduction_escaping_intermediate.ll b/polly/test/ScopInfo/reduction_escaping_intermediate.ll index dbfa1f1b1d59..dde09108ecc4 100644 --- a/polly/test/ScopInfo/reduction_escaping_intermediate.ll +++ b/polly/test/ScopInfo/reduction_escaping_intermediate.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int N, int * restrict sums, int * restrict escape) { ; int i, j; diff --git a/polly/test/ScopInfo/reduction_escaping_intermediate_2.ll b/polly/test/ScopInfo/reduction_escaping_intermediate_2.ll index 1fa8bbcc53e0..702fc56025d9 100644 --- a/polly/test/ScopInfo/reduction_escaping_intermediate_2.ll +++ b/polly/test/ScopInfo/reduction_escaping_intermediate_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int N, int * restrict sums, int * restrict escape) { ; int i, j; diff --git a/polly/test/ScopInfo/reduction_invalid_different_operators.ll b/polly/test/ScopInfo/reduction_invalid_different_operators.ll index d1bfb71fbbd4..f47919dcad99 100644 --- a/polly/test/ScopInfo/reduction_invalid_different_operators.ll +++ b/polly/test/ScopInfo/reduction_invalid_different_operators.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output < %s | FileCheck %s ; ; int f() { ; int i, sum = 0, sth = 0; diff --git a/polly/test/ScopInfo/reduction_invalid_overlapping_accesses.ll b/polly/test/ScopInfo/reduction_invalid_overlapping_accesses.ll index 654475253799..be1d7b5bbbd9 100644 --- a/polly/test/ScopInfo/reduction_invalid_overlapping_accesses.ll +++ b/polly/test/ScopInfo/reduction_invalid_overlapping_accesses.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *sums) { ; int i, j; diff --git a/polly/test/ScopInfo/reduction_multiple_loops_array_sum.ll b/polly/test/ScopInfo/reduction_multiple_loops_array_sum.ll index a8167f1c38de..8d20fa13ffe5 100644 --- a/polly/test/ScopInfo/reduction_multiple_loops_array_sum.ll +++ b/polly/test/ScopInfo/reduction_multiple_loops_array_sum.ll @@ -1,4 +1,4 @@ -; RUN: opt -aa-pipeline=basic-aa %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt -basic-aa %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Stmt_for_body ; CHECK: Reduction Type: * diff --git a/polly/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll b/polly/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll index a0c54572b599..782332b56aad 100644 --- a/polly/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll +++ b/polly/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll @@ -1,4 +1,4 @@ -; RUN: opt -aa-pipeline=basic-aa %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt -basic-aa %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Stmt_for_body ; CHECK: Reduction Type: NONE diff --git a/polly/test/ScopInfo/reduction_multiple_simple_binary.ll b/polly/test/ScopInfo/reduction_multiple_simple_binary.ll index 3ed664050a0b..0f1a3ad90dac 100644 --- a/polly/test/ScopInfo/reduction_multiple_simple_binary.ll +++ b/polly/test/ScopInfo/reduction_multiple_simple_binary.ll @@ -1,4 +1,4 @@ -; RUN: opt -aa-pipeline=basic-aa %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt -basic-aa %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: ReadAccess := [Reduction Type: NONE ; CHECK: { Stmt_for_body[i0] -> MemRef_A[1 + i0] }; diff --git a/polly/test/ScopInfo/reduction_non_overlapping_chains.ll b/polly/test/ScopInfo/reduction_non_overlapping_chains.ll index 7c8c8616a1cd..4e3f841cd8e1 100644 --- a/polly/test/ScopInfo/reduction_non_overlapping_chains.ll +++ b/polly/test/ScopInfo/reduction_non_overlapping_chains.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Reduction Type: + ; CHECK: Reduction Type: + diff --git a/polly/test/ScopInfo/reduction_only_reduction_like_access.ll b/polly/test/ScopInfo/reduction_only_reduction_like_access.ll index 95cda973a9b0..0c61d63a2d45 100644 --- a/polly/test/ScopInfo/reduction_only_reduction_like_access.ll +++ b/polly/test/ScopInfo/reduction_only_reduction_like_access.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Reduction Type: + ; diff --git a/polly/test/ScopInfo/reduction_simple_fp.ll b/polly/test/ScopInfo/reduction_simple_fp.ll index 37693353376b..ba0a034a17e3 100644 --- a/polly/test/ScopInfo/reduction_simple_fp.ll +++ b/polly/test/ScopInfo/reduction_simple_fp.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Function: f_no_fast_math ; CHECK: Reduction Type: NONE diff --git a/polly/test/ScopInfo/reduction_simple_w_constant.ll b/polly/test/ScopInfo/reduction_simple_w_constant.ll index 550882300116..dc1f8550602d 100644 --- a/polly/test/ScopInfo/reduction_simple_w_constant.ll +++ b/polly/test/ScopInfo/reduction_simple_w_constant.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Reduction Type: + ; diff --git a/polly/test/ScopInfo/reduction_simple_w_iv.ll b/polly/test/ScopInfo/reduction_simple_w_iv.ll index 480c2ebf8d47..b6c3229d08d5 100644 --- a/polly/test/ScopInfo/reduction_simple_w_iv.ll +++ b/polly/test/ScopInfo/reduction_simple_w_iv.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Reduction Type: + ; diff --git a/polly/test/ScopInfo/reduction_two_identical_reads.ll b/polly/test/ScopInfo/reduction_two_identical_reads.ll index 7fce22d15c77..19d45a5f4ea9 100644 --- a/polly/test/ScopInfo/reduction_two_identical_reads.ll +++ b/polly/test/ScopInfo/reduction_two_identical_reads.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s ; ; CHECK: Reduction Type: NONE ; diff --git a/polly/test/ScopInfo/redundant_parameter_constraint.ll b/polly/test/ScopInfo/redundant_parameter_constraint.ll index 231cab0fda1f..c9d912191eed 100644 --- a/polly/test/ScopInfo/redundant_parameter_constraint.ll +++ b/polly/test/ScopInfo/redundant_parameter_constraint.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; The constraint that r2 has to be bigger than r1 is implicitly contained in ; the domain, hence we do not want to see it explicitly. diff --git a/polly/test/ScopInfo/region-with-instructions.ll b/polly/test/ScopInfo/region-with-instructions.ll index a3040636836f..39d4a72a7814 100644 --- a/polly/test/ScopInfo/region-with-instructions.ll +++ b/polly/test/ScopInfo/region-with-instructions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -polly-print-instructions -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -polly-print-instructions -disable-output < %s | FileCheck %s ; CHECK: Statements { ; CHECK: Stmt_bb46 diff --git a/polly/test/ScopInfo/remarks.ll b/polly/test/ScopInfo/remarks.ll index 0a6ef2f1e5f7..dcdeb58c7694 100644 --- a/polly/test/ScopInfo/remarks.ll +++ b/polly/test/ScopInfo/remarks.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops \ ; RUN: -polly-invariant-load-hoisting=true -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: remark: test/ScopInfo/remarks.c:4:7: SCoP begins here. diff --git a/polly/test/ScopInfo/required-invariant-loop-bounds.ll b/polly/test/ScopInfo/required-invariant-loop-bounds.ll index 19ed625a85db..248acbea6e68 100644 --- a/polly/test/ScopInfo/required-invariant-loop-bounds.ll +++ b/polly/test/ScopInfo/required-invariant-loop-bounds.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output \ -; RUN: -polly-invariant-load-hoisting=true < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output \ +; RUN: -polly-invariant-load-hoisting=true < %s | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] diff --git a/polly/test/ScopInfo/restriction_in_dead_block.ll b/polly/test/ScopInfo/restriction_in_dead_block.ll index 27df53f03b03..81d9b96be419 100644 --- a/polly/test/ScopInfo/restriction_in_dead_block.ll +++ b/polly/test/ScopInfo/restriction_in_dead_block.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Verify we do not generate an empty invalid context only because the wrap ; in the second conditional will always happen if the block is executed. diff --git a/polly/test/ScopInfo/run-time-check-many-array-disjuncts.ll b/polly/test/ScopInfo/run-time-check-many-array-disjuncts.ll index e84a1b3e5bc6..d36da2b2becf 100644 --- a/polly/test/ScopInfo/run-time-check-many-array-disjuncts.ll +++ b/polly/test/ScopInfo/run-time-check-many-array-disjuncts.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s \ ; RUN: | FileCheck %s -check-prefix=DETECT -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; DETECT: Valid Region for Scop: bb124 => bb176 ; diff --git a/polly/test/ScopInfo/run-time-check-many-parameters.ll b/polly/test/ScopInfo/run-time-check-many-parameters.ll index 540ea57fad0c..30f8d5fff34c 100644 --- a/polly/test/ScopInfo/run-time-check-many-parameters.ll +++ b/polly/test/ScopInfo/run-time-check-many-parameters.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; A valid Scop would print the list of it's statements, we check that we do not ; see that list. diff --git a/polly/test/ScopInfo/run-time-check-many-piecewise-aliasing.ll b/polly/test/ScopInfo/run-time-check-many-piecewise-aliasing.ll index cefda1eed0c6..487c803bba98 100644 --- a/polly/test/ScopInfo/run-time-check-many-piecewise-aliasing.ll +++ b/polly/test/ScopInfo/run-time-check-many-piecewise-aliasing.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 \ +; RUN: opt %loadPolly -polly-print-detect -disable-output < %s \ ; RUN: | FileCheck %s -check-prefix=DETECT -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; DETECT: Valid Region for Scop: for => return ; diff --git a/polly/test/ScopInfo/run-time-check-read-only-arrays.ll b/polly/test/ScopInfo/run-time-check-read-only-arrays.ll index 395622b12616..d590aaf00ddb 100644 --- a/polly/test/ScopInfo/run-time-check-read-only-arrays.ll +++ b/polly/test/ScopInfo/run-time-check-read-only-arrays.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void foo(float *A, float *B, float *C, long N) { ; for (long i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/same-base-address-scalar-and-array.ll b/polly/test/ScopInfo/same-base-address-scalar-and-array.ll index 22cf77636d10..a5f353e7ad2a 100644 --- a/polly/test/ScopInfo/same-base-address-scalar-and-array.ll +++ b/polly/test/ScopInfo/same-base-address-scalar-and-array.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Verify we introduce two ScopArrayInfo objects (or virtual arrays) for the %out variable ; as it is used as a memory base pointer (%0) but also as a scalar (%out.addr.0.lcssa). diff --git a/polly/test/ScopInfo/scalar.ll b/polly/test/ScopInfo/scalar.ll index 80493723bbfc..c38eaa853b9b 100644 --- a/polly/test/ScopInfo/scalar.ll +++ b/polly/test/ScopInfo/scalar.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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" diff --git a/polly/test/ScopInfo/scalar_dependence_cond_br.ll b/polly/test/ScopInfo/scalar_dependence_cond_br.ll index 940dabbc4cfc..3303bfb7c6c5 100644 --- a/polly/test/ScopInfo/scalar_dependence_cond_br.ll +++ b/polly/test/ScopInfo/scalar_dependence_cond_br.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output< %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output< %s | FileCheck %s ; ; void f(int *A, int c, int d) { ; for (int i = 0; i < 1024; i++) diff --git a/polly/test/ScopInfo/scalar_to_array.ll b/polly/test/ScopInfo/scalar_to_array.ll index 692a0dbd67c8..5c275108602a 100644 --- a/polly/test/ScopInfo/scalar_to_array.ll +++ b/polly/test/ScopInfo/scalar_to_array.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -aa-pipeline=basic-aa '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-print-function-scops -disable-output < %s | FileCheck %s ; ModuleID = 'scalar_to_array.ll' 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-n8:16:32:64" diff --git a/polly/test/ScopInfo/scev-div-with-evaluatable-divisor.ll b/polly/test/ScopInfo/scev-div-with-evaluatable-divisor.ll index f969176cee16..fc7a1bfc3d5e 100644 --- a/polly/test/ScopInfo/scev-div-with-evaluatable-divisor.ll +++ b/polly/test/ScopInfo/scev-div-with-evaluatable-divisor.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; Derived from test-suite/SingleSource/UnitTests/Vector/SSE/sse.stepfft.c diff --git a/polly/test/ScopInfo/scev-invalidated.ll b/polly/test/ScopInfo/scev-invalidated.ll index 921cb06a0cd5..97fc5ec3d4ca 100644 --- a/polly/test/ScopInfo/scev-invalidated.ll +++ b/polly/test/ScopInfo/scev-invalidated.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Region: %if.then6---%return ; diff --git a/polly/test/ScopInfo/schedule-const-post-dominator-walk-2.ll b/polly/test/ScopInfo/schedule-const-post-dominator-walk-2.ll index e956b0ed7cb9..2fdf7d66c3ad 100644 --- a/polly/test/ScopInfo/schedule-const-post-dominator-walk-2.ll +++ b/polly/test/ScopInfo/schedule-const-post-dominator-walk-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/schedule-const-post-dominator-walk.ll b/polly/test/ScopInfo/schedule-const-post-dominator-walk.ll index 325d19dd210d..92685858610c 100644 --- a/polly/test/ScopInfo/schedule-const-post-dominator-walk.ll +++ b/polly/test/ScopInfo/schedule-const-post-dominator-walk.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/schedule-constuction-endless-loop1.ll b/polly/test/ScopInfo/schedule-constuction-endless-loop1.ll index 0225c53faa9a..413d1d8ec556 100644 --- a/polly/test/ScopInfo/schedule-constuction-endless-loop1.ll +++ b/polly/test/ScopInfo/schedule-constuction-endless-loop1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that we do not build a SCoP and do not crash. ; diff --git a/polly/test/ScopInfo/schedule-constuction-endless-loop2.ll b/polly/test/ScopInfo/schedule-constuction-endless-loop2.ll index bc34070dcf46..be254477286f 100644 --- a/polly/test/ScopInfo/schedule-constuction-endless-loop2.ll +++ b/polly/test/ScopInfo/schedule-constuction-endless-loop2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Check that we do not build a SCoP and do not crash. ; diff --git a/polly/test/ScopInfo/schedule-incorrectly-contructed-in-case-of-infinite-loop.ll b/polly/test/ScopInfo/schedule-incorrectly-contructed-in-case-of-infinite-loop.ll index f8b3dfea844f..ff339e03fb5a 100644 --- a/polly/test/ScopInfo/schedule-incorrectly-contructed-in-case-of-infinite-loop.ll +++ b/polly/test/ScopInfo/schedule-incorrectly-contructed-in-case-of-infinite-loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-process-unprofitable '-passes=print' -disable-output < %s +; RUN: opt %loadPolly -polly-process-unprofitable -polly-scops -disable-output < %s ; ; This test contains a infinite loop (bb13) and crashed the domain generation ; at some point. Just verify it does not anymore. diff --git a/polly/test/ScopInfo/scop-affine-parameter-ordering.ll b/polly/test/ScopInfo/scop-affine-parameter-ordering.ll index 5a8019eabe9d..24c028a6764a 100644 --- a/polly/test/ScopInfo/scop-affine-parameter-ordering.ll +++ b/polly/test/ScopInfo/scop-affine-parameter-ordering.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s target datalayout = "e-m:e-i64:64-i128:128-n8:16:32:64-S128" target triple = "aarch64--linux-android" diff --git a/polly/test/ScopInfo/sign_wrapped_set.ll b/polly/test/ScopInfo/sign_wrapped_set.ll index 7b24f29563ea..23c9c8a3b84d 100644 --- a/polly/test/ScopInfo/sign_wrapped_set.ll +++ b/polly/test/ScopInfo/sign_wrapped_set.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-process-unprofitable '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-process-unprofitable -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Domain := ; CHECK-NEXT: [srcHeight] -> { Stmt_for_cond6_preheader_us[i0] : 0 <= i0 <= -3 + srcHeight }; diff --git a/polly/test/ScopInfo/simple_loop_1.ll b/polly/test/ScopInfo/simple_loop_1.ll index 4872b8e59ba9..2c3481facc02 100644 --- a/polly/test/ScopInfo/simple_loop_1.ll +++ b/polly/test/ScopInfo/simple_loop_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; void f(int a[], int N) { ; int i; diff --git a/polly/test/ScopInfo/simple_loop_2.ll b/polly/test/ScopInfo/simple_loop_2.ll index 120b5e790077..2f580094a147 100644 --- a/polly/test/ScopInfo/simple_loop_2.ll +++ b/polly/test/ScopInfo/simple_loop_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; void f(int a[], int N) { ; int i; diff --git a/polly/test/ScopInfo/simple_loop_unsigned.ll b/polly/test/ScopInfo/simple_loop_unsigned.ll index 6c0e8798a6cd..12903d9c1580 100644 --- a/polly/test/ScopInfo/simple_loop_unsigned.ll +++ b/polly/test/ScopInfo/simple_loop_unsigned.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; void f(int a[], unsigned N) { ; unsigned i; diff --git a/polly/test/ScopInfo/simple_loop_unsigned_2.ll b/polly/test/ScopInfo/simple_loop_unsigned_2.ll index 4b19a8c52c6b..1379180a6dd9 100644 --- a/polly/test/ScopInfo/simple_loop_unsigned_2.ll +++ b/polly/test/ScopInfo/simple_loop_unsigned_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/simple_loop_unsigned_3.ll b/polly/test/ScopInfo/simple_loop_unsigned_3.ll index fd974f219bec..7783c4681e1f 100644 --- a/polly/test/ScopInfo/simple_loop_unsigned_3.ll +++ b/polly/test/ScopInfo/simple_loop_unsigned_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; CHECK: Assumed Context: ; CHECK-NEXT: [N] -> { : } diff --git a/polly/test/ScopInfo/simple_nonaffine_loop_not.ll b/polly/test/ScopInfo/simple_nonaffine_loop_not.ll index d2aa22f8cca7..42eff85d8c9b 100644 --- a/polly/test/ScopInfo/simple_nonaffine_loop_not.ll +++ b/polly/test/ScopInfo/simple_nonaffine_loop_not.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | not FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | not 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-n8:16:32:64-S128" @.str = private unnamed_addr constant [17 x i8] c"Random Value: %d\00", align 1 diff --git a/polly/test/ScopInfo/smax.ll b/polly/test/ScopInfo/smax.ll index 502d52baaaef..b938e4e412da 100644 --- a/polly/test/ScopInfo/smax.ll +++ b/polly/test/ScopInfo/smax.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:32-n32-S64" define void @foo(ptr noalias %data, ptr noalias %ptr, i32 %x_pos, i32 %w) { diff --git a/polly/test/ScopInfo/statistics.ll b/polly/test/ScopInfo/statistics.ll index c69852e21875..3797b7d71df9 100644 --- a/polly/test/ScopInfo/statistics.ll +++ b/polly/test/ScopInfo/statistics.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -stats -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-scops -stats -disable-output < %s 2>&1 | FileCheck %s ; REQUIRES: asserts ; CHECK-DAG: 4 polly-scops - Maximal number of loops in scops diff --git a/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll b/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll index 1d4d3f19b571..d86d2418cf9b 100644 --- a/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll +++ b/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Region__TO__Stmt diff --git a/polly/test/ScopInfo/stmt_split_no_after_split.ll b/polly/test/ScopInfo/stmt_split_no_after_split.ll index e3e440584f25..f8339bd8ae94 100644 --- a/polly/test/ScopInfo/stmt_split_no_after_split.ll +++ b/polly/test/ScopInfo/stmt_split_no_after_split.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_split_no_dependence.ll b/polly/test/ScopInfo/stmt_split_no_dependence.ll index 0bf98c9b70be..7ad48f499792 100644 --- a/polly/test/ScopInfo/stmt_split_no_dependence.ll +++ b/polly/test/ScopInfo/stmt_split_no_dependence.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s ; void func(int *A, int *B){ ; for (int i = 0; i < 1024; i+=1) { diff --git a/polly/test/ScopInfo/stmt_split_on_store.ll b/polly/test/ScopInfo/stmt_split_on_store.ll index 82b1f5bbc3cd..6af3dc8633dd 100644 --- a/polly/test/ScopInfo/stmt_split_on_store.ll +++ b/polly/test/ScopInfo/stmt_split_on_store.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=store -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=store -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s ; void func(int *A, int *B){ ; for (int i = 0; i < 1024; i+=1) { diff --git a/polly/test/ScopInfo/stmt_split_on_synthesizable.ll b/polly/test/ScopInfo/stmt_split_on_synthesizable.ll index 323c83bc570e..92855cfd0124 100644 --- a/polly/test/ScopInfo/stmt_split_on_synthesizable.ll +++ b/polly/test/ScopInfo/stmt_split_on_synthesizable.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll b/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll index 7f72e672a1a6..ee6afa4638d2 100644 --- a/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll +++ b/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll b/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll index 9306cdc7615a..0a5f41d637e7 100644 --- a/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll +++ b/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_split_scalar_dependence.ll b/polly/test/ScopInfo/stmt_split_scalar_dependence.ll index efd5cf14def0..5b02d1b5d08a 100644 --- a/polly/test/ScopInfo/stmt_split_scalar_dependence.ll +++ b/polly/test/ScopInfo/stmt_split_scalar_dependence.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_split_within_loop.ll b/polly/test/ScopInfo/stmt_split_within_loop.ll index f24904df307c..3ed9bbbeaccb 100644 --- a/polly/test/ScopInfo/stmt_split_within_loop.ll +++ b/polly/test/ScopInfo/stmt_split_within_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-instructions -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Statements { ; CHECK-NEXT: Stmt_Stmt diff --git a/polly/test/ScopInfo/stmt_with_read_but_without_sideffect.ll b/polly/test/ScopInfo/stmt_with_read_but_without_sideffect.ll index 41f58844569f..73fc543a66e8 100644 --- a/polly/test/ScopInfo/stmt_with_read_but_without_sideffect.ll +++ b/polly/test/ScopInfo/stmt_with_read_but_without_sideffect.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-delicm -disable-output < %s | FileCheck %s ; ; The statement Stmt_for_if_else_1 should be removed because it has no ; sideeffects. But it has a use of MemRef_tmp21 that must also be diff --git a/polly/test/ScopInfo/switch-1.ll b/polly/test/ScopInfo/switch-1.ll index 6bc630834e93..0ea40a7ed251 100644 --- a/polly/test/ScopInfo/switch-1.ll +++ b/polly/test/ScopInfo/switch-1.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/switch-2.ll b/polly/test/ScopInfo/switch-2.ll index a64d133baae7..7956058c9de6 100644 --- a/polly/test/ScopInfo/switch-2.ll +++ b/polly/test/ScopInfo/switch-2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/switch-3.ll b/polly/test/ScopInfo/switch-3.ll index 3aa2d7811c77..aa7ada4edbb8 100644 --- a/polly/test/ScopInfo/switch-3.ll +++ b/polly/test/ScopInfo/switch-3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/switch-4.ll b/polly/test/ScopInfo/switch-4.ll index 567c3de030ea..6aeb7197e382 100644 --- a/polly/test/ScopInfo/switch-4.ll +++ b/polly/test/ScopInfo/switch-4.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/switch-5.ll b/polly/test/ScopInfo/switch-5.ll index b6a42d9da749..24cc92a0933d 100644 --- a/polly/test/ScopInfo/switch-5.ll +++ b/polly/test/ScopInfo/switch-5.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST ; ; The SCoP contains a loop with multiple exit blocks (BBs after leaving ; the loop). The current implementation of deriving their domain derives diff --git a/polly/test/ScopInfo/switch-6.ll b/polly/test/ScopInfo/switch-6.ll index 24538328c581..efb3df504d23 100644 --- a/polly/test/ScopInfo/switch-6.ll +++ b/polly/test/ScopInfo/switch-6.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST ; ; void f(int *A, int N) { ; for (int i = 0; i < N; i++) { diff --git a/polly/test/ScopInfo/switch-7.ll b/polly/test/ScopInfo/switch-7.ll index 99c1bed81874..2f0d034e84fe 100644 --- a/polly/test/ScopInfo/switch-7.ll +++ b/polly/test/ScopInfo/switch-7.ll @@ -1,5 +1,6 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=AST + +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-ast -disable-output < %s | FileCheck %s --check-prefix=AST ; ; void f(int *A, int c, int N) { ; switch (c) { diff --git a/polly/test/ScopInfo/tempscop-printing.ll b/polly/test/ScopInfo/tempscop-printing.ll index e99a6f2582ee..80c675d4c3d3 100644 --- a/polly/test/ScopInfo/tempscop-printing.ll +++ b/polly/test/ScopInfo/tempscop-printing.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -aa-pipeline=basic-aa -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -basic-aa -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s ; void f(long A[], int N, int *init_ptr) { ; long i, j; diff --git a/polly/test/ScopInfo/test-wrapping-in-condition.ll b/polly/test/ScopInfo/test-wrapping-in-condition.ll index 7c1301748c39..3ff978f7265e 100644 --- a/polly/test/ScopInfo/test-wrapping-in-condition.ll +++ b/polly/test/ScopInfo/test-wrapping-in-condition.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-function-scops -disable-output < %s | FileCheck %s ; ; CHECK: Invalid Context: ; CHECK: [N] -> { : N >= 129 } diff --git a/polly/test/ScopInfo/truncate-1.ll b/polly/test/ScopInfo/truncate-1.ll index b21755c67ac4..5c5fac150b4b 100644 --- a/polly/test/ScopInfo/truncate-1.ll +++ b/polly/test/ScopInfo/truncate-1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(char *A, short N) { ; for (char i = 0; i < (char)N; i++) diff --git a/polly/test/ScopInfo/truncate-2.ll b/polly/test/ScopInfo/truncate-2.ll index 0d4abb343993..e6c5f2cb32d0 100644 --- a/polly/test/ScopInfo/truncate-2.ll +++ b/polly/test/ScopInfo/truncate-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(char *A, short N) { ; for (short i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/truncate-3.ll b/polly/test/ScopInfo/truncate-3.ll index f9cdd0274f22..dd0fe489e990 100644 --- a/polly/test/ScopInfo/truncate-3.ll +++ b/polly/test/ScopInfo/truncate-3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -pass-remarks-analysis="polly-scops" \ +; RUN: opt %loadPolly -polly-scops -pass-remarks-analysis="polly-scops" \ ; RUN: -disable-output < %s 2>&1 | FileCheck %s ; CHECK: Signed-unsigned restriction: [p] -> { : p <= -129 or p >= 128 } diff --git a/polly/test/ScopInfo/two-loops-one-infinite.ll b/polly/test/ScopInfo/two-loops-one-infinite.ll index 02ad18e3d567..71f72383b048 100644 --- a/polly/test/ScopInfo/two-loops-one-infinite.ll +++ b/polly/test/ScopInfo/two-loops-one-infinite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Verify we do not create a SCoP in the presence of infinite loops. ; diff --git a/polly/test/ScopInfo/two-loops-right-after-each-other.ll b/polly/test/ScopInfo/two-loops-right-after-each-other.ll index 36ab13a68c1e..dd457c31afdd 100644 --- a/polly/test/ScopInfo/two-loops-right-after-each-other.ll +++ b/polly/test/ScopInfo/two-loops-right-after-each-other.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; CHECK: Statements { ; CHECK-NEXT: Stmt_loop_1 diff --git a/polly/test/ScopInfo/undef_in_cond.ll b/polly/test/ScopInfo/undef_in_cond.ll index 4bdcc1697068..5282a853c17a 100644 --- a/polly/test/ScopInfo/undef_in_cond.ll +++ b/polly/test/ScopInfo/undef_in_cond.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | 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-n8:16:32:64" define fastcc void @fix_operands() nounwind { diff --git a/polly/test/ScopInfo/unnamed_nonaffine.ll b/polly/test/ScopInfo/unnamed_nonaffine.ll index d9415eabab94..bf32cc7806f4 100644 --- a/polly/test/ScopInfo/unnamed_nonaffine.ll +++ b/polly/test/ScopInfo/unnamed_nonaffine.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-use-llvm-names=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-allow-nonaffine -polly-use-llvm-names=false '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -check-prefix=UNNAMED +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-use-llvm-names=true -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-allow-nonaffine -polly-use-llvm-names=false -polly-print-scops -disable-output < %s | FileCheck %s -check-prefix=UNNAMED ; ; void f(int *A, int b) { ; int x; diff --git a/polly/test/ScopInfo/unnamed_stmts.ll b/polly/test/ScopInfo/unnamed_stmts.ll index 0bd53d8c8425..686c0f87d9cf 100644 --- a/polly/test/ScopInfo/unnamed_stmts.ll +++ b/polly/test/ScopInfo/unnamed_stmts.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; This test case verifies that we generate numbered statement names in case ; no LLVM-IR names are used in the test case. We also verify, that we diff --git a/polly/test/ScopInfo/unpredictable_nonscop_loop.ll b/polly/test/ScopInfo/unpredictable_nonscop_loop.ll index c0e768216eb0..0656b77e3409 100644 --- a/polly/test/ScopInfo/unpredictable_nonscop_loop.ll +++ b/polly/test/ScopInfo/unpredictable_nonscop_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -disable-output < %s | FileCheck %s -match-full-lines ; Derived from test-suite/MultiSource/Applications/sgefa/blas.c ; ; The exit value of %i.0320 in land.rhs is not computable. diff --git a/polly/test/ScopInfo/unprofitable_scalar-accs.ll b/polly/test/ScopInfo/unprofitable_scalar-accs.ll index e7c8a57093b8..9703587091a7 100644 --- a/polly/test/ScopInfo/unprofitable_scalar-accs.ll +++ b/polly/test/ScopInfo/unprofitable_scalar-accs.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=false '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=true '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=HEURISTIC +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=false -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-process-unprofitable=false -polly-unprofitable-scalar-accs=true -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=HEURISTIC ; Check the effect of -polly-unprofitable-scalar-accs diff --git a/polly/test/ScopInfo/unsigned-condition.ll b/polly/test/ScopInfo/unsigned-condition.ll index 1dca9bab41ec..35673d1b6a36 100644 --- a/polly/test/ScopInfo/unsigned-condition.ll +++ b/polly/test/ScopInfo/unsigned-condition.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; void f(int a[], int N, unsigned P) { ; int i; diff --git a/polly/test/ScopInfo/unsigned-division-1.ll b/polly/test/ScopInfo/unsigned-division-1.ll index da080b3a306b..8c65062bd941 100644 --- a/polly/test/ScopInfo/unsigned-division-1.ll +++ b/polly/test/ScopInfo/unsigned-division-1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, unsigned N) { ; for (unsigned i = 0; i < N / 2; i++) diff --git a/polly/test/ScopInfo/unsigned-division-2.ll b/polly/test/ScopInfo/unsigned-division-2.ll index 2fe4207d1bd1..bf4ebce9099a 100644 --- a/polly/test/ScopInfo/unsigned-division-2.ll +++ b/polly/test/ScopInfo/unsigned-division-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, unsigned N) { ; for (unsigned i = 0; i < N / 2 + 3; i++) diff --git a/polly/test/ScopInfo/unsigned-division-3.ll b/polly/test/ScopInfo/unsigned-division-3.ll index aefb590b28df..47ba1f2ef09d 100644 --- a/polly/test/ScopInfo/unsigned-division-3.ll +++ b/polly/test/ScopInfo/unsigned-division-3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, unsigned char N) { ; for (unsigned i = 0; i <= N / -128; i++) diff --git a/polly/test/ScopInfo/unsigned-division-4.ll b/polly/test/ScopInfo/unsigned-division-4.ll index 9fe10d7440ef..edcd8a18a854 100644 --- a/polly/test/ScopInfo/unsigned-division-4.ll +++ b/polly/test/ScopInfo/unsigned-division-4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, unsigned char N) { ; for (unsigned i = 0; i < (N / -128) + 3; i++) diff --git a/polly/test/ScopInfo/unsigned-division-5.ll b/polly/test/ScopInfo/unsigned-division-5.ll index fb90345f477e..f9a3d39288a9 100644 --- a/polly/test/ScopInfo/unsigned-division-5.ll +++ b/polly/test/ScopInfo/unsigned-division-5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, unsigned N) { ; for (unsigned i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/unsigned_wrap_uge.ll b/polly/test/ScopInfo/unsigned_wrap_uge.ll index 3d54cad70285..89c50ee3764b 100644 --- a/polly/test/ScopInfo/unsigned_wrap_uge.ll +++ b/polly/test/ScopInfo/unsigned_wrap_uge.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Unsigned wrap-around check. ; diff --git a/polly/test/ScopInfo/unsigned_wrap_ugt.ll b/polly/test/ScopInfo/unsigned_wrap_ugt.ll index 8c98f13cfb72..3249123c9918 100644 --- a/polly/test/ScopInfo/unsigned_wrap_ugt.ll +++ b/polly/test/ScopInfo/unsigned_wrap_ugt.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Unsigned wrap-around check. ; diff --git a/polly/test/ScopInfo/unsigned_wrap_ule.ll b/polly/test/ScopInfo/unsigned_wrap_ule.ll index e0b0339475fc..3c6ea18b439c 100644 --- a/polly/test/ScopInfo/unsigned_wrap_ule.ll +++ b/polly/test/ScopInfo/unsigned_wrap_ule.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Unsigned wrap-around check. ; diff --git a/polly/test/ScopInfo/unsigned_wrap_ult.ll b/polly/test/ScopInfo/unsigned_wrap_ult.ll index cb15bc04669e..5d859f85d52b 100644 --- a/polly/test/ScopInfo/unsigned_wrap_ult.ll +++ b/polly/test/ScopInfo/unsigned_wrap_ult.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; Unsigned wrap-around check. ; diff --git a/polly/test/ScopInfo/user_context.ll b/polly/test/ScopInfo/user_context.ll index d67244e1ad95..46232cd59c03 100644 --- a/polly/test/ScopInfo/user_context.ll +++ b/polly/test/ScopInfo/user_context.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-context='[N] -> {: N = 1024}' '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=CTX -; RUN: opt %loadPolly -polly-context='[N,M] -> {: 1 = 0}' '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-context='[] -> {: 1 = 0}' '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-context='[N] -> {: N = 1024}' -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=CTX +; RUN: opt %loadPolly -polly-context='[N,M] -> {: 1 = 0}' -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-context='[] -> {: 1 = 0}' -polly-print-scops -disable-output < %s | FileCheck %s ; void f(int a[], int N) { ; int i; diff --git a/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed-conditional.ll b/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed-conditional.ll index 829d1ef10664..4bd02c96a3d2 100644 --- a/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed-conditional.ll +++ b/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed-conditional.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REMARK -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REMARK +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; REMARK: remark: :0:0: Use user assumption: [n, b] -> { : n <= 100 or (b = 0 and n >= 101) } ; diff --git a/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed.ll b/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed.ll index 8518a0ece23c..262bd1349a69 100644 --- a/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed.ll +++ b/polly/test/ScopInfo/user_provided_assumptions-in-bb-signed.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Context: ; CHECK-NEXT: [n] -> { : -9223372036854775808 <= n <= 100 } diff --git a/polly/test/ScopInfo/user_provided_assumptions-in-bb-unsigned.ll b/polly/test/ScopInfo/user_provided_assumptions-in-bb-unsigned.ll index 678be1c06d0a..4a10fcff929a 100644 --- a/polly/test/ScopInfo/user_provided_assumptions-in-bb-unsigned.ll +++ b/polly/test/ScopInfo/user_provided_assumptions-in-bb-unsigned.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REMARK -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops -disable-output < %s 2>&1 | FileCheck %s --check-prefix=REMARK +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; REMARK: remark: :0:0: SCoP begins here. ; REMARK-NEXT: remark: :0:0: Use user assumption: [n] -> { : n <= 100 } diff --git a/polly/test/ScopInfo/user_provided_assumptions.ll b/polly/test/ScopInfo/user_provided_assumptions.ll index e4556eb3a386..6640e4a65e36 100644 --- a/polly/test/ScopInfo/user_provided_assumptions.ll +++ b/polly/test/ScopInfo/user_provided_assumptions.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=SCOP ; ; CHECK: remark: :0:0: SCoP begins here. ; CHECK-NEXT: remark: :0:0: Use user assumption: [M, N] -> { : N <= 2147483647 - M } diff --git a/polly/test/ScopInfo/user_provided_assumptions_2.ll b/polly/test/ScopInfo/user_provided_assumptions_2.ll index 98057740eab3..994cd6f15103 100644 --- a/polly/test/ScopInfo/user_provided_assumptions_2.ll +++ b/polly/test/ScopInfo/user_provided_assumptions_2.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=SCOP ; ; CHECK: remark: :0:0: SCoP begins here. ; CHECK-NEXT: remark: :0:0: Use user assumption: { : } diff --git a/polly/test/ScopInfo/user_provided_assumptions_3.ll b/polly/test/ScopInfo/user_provided_assumptions_3.ll index de3fbba46e0a..2fcde8bd1826 100644 --- a/polly/test/ScopInfo/user_provided_assumptions_3.ll +++ b/polly/test/ScopInfo/user_provided_assumptions_3.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCOP +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s --check-prefix=SCOP ; ; CHECK: remark: :0:0: SCoP begins here. ; CHECK-NEXT: remark: :0:0: Use user assumption: [N] -> { : N >= 2 } diff --git a/polly/test/ScopInfo/user_provided_non_dominating_assumptions.ll b/polly/test/ScopInfo/user_provided_non_dominating_assumptions.ll index 4f3be408c9ef..1eb3c15810e4 100644 --- a/polly/test/ScopInfo/user_provided_non_dominating_assumptions.ll +++ b/polly/test/ScopInfo/user_provided_non_dominating_assumptions.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops \ ; RUN: -polly-precise-inbounds -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: remark: :0:0: SCoP begins here. @@ -18,7 +18,7 @@ ; -; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" '-passes=print' \ +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops \ ; RUN: -polly-precise-inbounds -disable-output < %s 2>&1 -pass-remarks-output=%t.yaml ; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s ; YAML: --- !Analysis diff --git a/polly/test/ScopInfo/variant_base_pointer.ll b/polly/test/ScopInfo/variant_base_pointer.ll index 3a6ea88d3473..321657c87e79 100644 --- a/polly/test/ScopInfo/variant_base_pointer.ll +++ b/polly/test/ScopInfo/variant_base_pointer.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true '-passes=print,print' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true -passes=polly-codegen -disable-output < %s +; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-ignore-aliasing -polly-invariant-load-hoisting=true -polly-codegen -disable-output < %s ; ; %tmp is added to the list of required hoists by -polly-scops and just ; assumed to be hoisted. Only -polly-scops recognizes it to be unhoistable diff --git a/polly/test/ScopInfo/variant_load_empty_domain.ll b/polly/test/ScopInfo/variant_load_empty_domain.ll index 4b91778a225b..0e685c3c7e73 100644 --- a/polly/test/ScopInfo/variant_load_empty_domain.ll +++ b/polly/test/ScopInfo/variant_load_empty_domain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Invariant Accesses: { ; CHECK-NEXT: } diff --git a/polly/test/ScopInfo/wraping_signed_expr_0.ll b/polly/test/ScopInfo/wraping_signed_expr_0.ll index bbb49bffe925..7ad0f64028b6 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_0.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_0.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, char N, char p) { ; for (char i = 0; i < N; i++) { diff --git a/polly/test/ScopInfo/wraping_signed_expr_1.ll b/polly/test/ScopInfo/wraping_signed_expr_1.ll index e43a691312a0..0a62b9cf542c 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_1.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(long *A, long N, long p) { ; for (long i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/wraping_signed_expr_2.ll b/polly/test/ScopInfo/wraping_signed_expr_2.ll index eef357acc582..f3b4665f7f37 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_2.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, int N, int p) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/wraping_signed_expr_3.ll b/polly/test/ScopInfo/wraping_signed_expr_3.ll index a0500eb48941..7a5cbba9436b 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_3.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_3.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(int *A, int N, int p) { ; for (int i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/wraping_signed_expr_4.ll b/polly/test/ScopInfo/wraping_signed_expr_4.ll index d21f321e4ac9..ec65f70a092f 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_4.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_4.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(char *A, char N, char p) { ; for (char i = 0; i < N; i++) diff --git a/polly/test/ScopInfo/wraping_signed_expr_5.ll b/polly/test/ScopInfo/wraping_signed_expr_5.ll index 395342d2f55a..5f3b09ba33c1 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_5.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_5.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; We should not generate runtime check for ((int)r1 + (int)r2) as it is known not ; to overflow. However (p + q) can, thus checks are needed. diff --git a/polly/test/ScopInfo/wraping_signed_expr_6.ll b/polly/test/ScopInfo/wraping_signed_expr_6.ll index 4147f7fa20cf..23258bb513bf 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_6.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_6.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Invalid Context: ; CHECK: [N] -> { : N >= 129 } diff --git a/polly/test/ScopInfo/wraping_signed_expr_7.ll b/polly/test/ScopInfo/wraping_signed_expr_7.ll index f41e89c07db0..0663d4e0bc10 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_7.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_7.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Invalid Context: ; CHECK: [N] -> { : N >= 129 } diff --git a/polly/test/ScopInfo/wraping_signed_expr_slow_1.ll b/polly/test/ScopInfo/wraping_signed_expr_slow_1.ll index ddaeed06874a..ec36d2c5fcde 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_slow_1.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_slow_1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; This checks that the no-wraps checks will be computed fast as some example ; already showed huge slowdowns even though the inbounds and nsw flags were diff --git a/polly/test/ScopInfo/wraping_signed_expr_slow_2.ll b/polly/test/ScopInfo/wraping_signed_expr_slow_2.ll index 798a5d0855b3..6db33ab166d5 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_slow_2.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_slow_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; This checks that the no-wraps checks will be computed fast as some example ; already showed huge slowdowns even though the inbounds and nsw flags were diff --git a/polly/test/ScopInfo/zero_ext_of_truncate.ll b/polly/test/ScopInfo/zero_ext_of_truncate.ll index bf5b6354a6d6..fc55df5e053c 100644 --- a/polly/test/ScopInfo/zero_ext_of_truncate.ll +++ b/polly/test/ScopInfo/zero_ext_of_truncate.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(unsigned *restrict I, unsigned *restrict A, unsigned N, unsigned M) { ; for (unsigned i = 0; i < N; i++) { diff --git a/polly/test/ScopInfo/zero_ext_of_truncate_2.ll b/polly/test/ScopInfo/zero_ext_of_truncate_2.ll index 595b21c71869..13e9c03ecd2d 100644 --- a/polly/test/ScopInfo/zero_ext_of_truncate_2.ll +++ b/polly/test/ScopInfo/zero_ext_of_truncate_2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-invariant-load-hoisting=true '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-invariant-load-hoisting=true -polly-print-scops -disable-output < %s | FileCheck %s ; ; void f(unsigned long *restrict I, unsigned *restrict A, unsigned N) { ; for (unsigned i = 0; i < N; i++) { diff --git a/polly/test/ScopInfo/zero_ext_space_mismatch.ll b/polly/test/ScopInfo/zero_ext_space_mismatch.ll index 0a329fdef8c2..835a8664b75e 100644 --- a/polly/test/ScopInfo/zero_ext_space_mismatch.ll +++ b/polly/test/ScopInfo/zero_ext_space_mismatch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-print-scops -disable-output < %s | FileCheck %s ; ; CHECK: Assumed Context: ; CHECK-NEXT: [dim] -> { : dim > 0 } diff --git a/polly/test/ScopInliner/invariant-load-func.ll b/polly/test/ScopInliner/invariant-load-func.ll index 8da50f90beba..38e4a15aab94 100644 --- a/polly/test/ScopInliner/invariant-load-func.ll +++ b/polly/test/ScopInliner/invariant-load-func.ll @@ -1,5 +1,5 @@ ; RUN: opt %loadPolly -polly-detect-full-functions -polly-scop-inliner \ -; RUN: -polly-invariant-load-hoisting '-passes=print' -disable-output < %s | FileCheck %s +; RUN: -polly-invariant-load-hoisting -polly-print-scops -disable-output < %s | FileCheck %s ; Check that we inline a function that requires invariant load hoisting ; correctly. diff --git a/polly/test/Simplify/coalesce_3partials.ll b/polly/test/Simplify/coalesce_3partials.ll index 937f655c344c..0c1556ff263a 100644 --- a/polly/test/Simplify/coalesce_3partials.ll +++ b/polly/test/Simplify/coalesce_3partials.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s ; ; Combine 3 partial accesses into one. ; diff --git a/polly/test/Simplify/coalesce_disjointelements.ll b/polly/test/Simplify/coalesce_disjointelements.ll index 6080ee4dde81..2f4cf4e3f920 100644 --- a/polly/test/Simplify/coalesce_disjointelements.ll +++ b/polly/test/Simplify/coalesce_disjointelements.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s ; ; Combine four partial stores into two. ; The stores write to the same array, but never the same element. diff --git a/polly/test/Simplify/coalesce_overlapping.ll b/polly/test/Simplify/coalesce_overlapping.ll index 3c52d44e8003..78ed21e9855b 100644 --- a/polly/test/Simplify/coalesce_overlapping.ll +++ b/polly/test/Simplify/coalesce_overlapping.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s ; ; Combine two partial stores (with overlapping domains) into one. ; diff --git a/polly/test/Simplify/coalesce_partial.ll b/polly/test/Simplify/coalesce_partial.ll index cec58a9121b2..c42aaa113035 100644 --- a/polly/test/Simplify/coalesce_partial.ll +++ b/polly/test/Simplify/coalesce_partial.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s ; ; Combine two partial stores (with disjoint domains) into one. ; diff --git a/polly/test/Simplify/dead_access_load.ll b/polly/test/Simplify/dead_access_load.ll index 5e0a9b574516..1804613c0a79 100644 --- a/polly/test/Simplify/dead_access_load.ll +++ b/polly/test/Simplify/dead_access_load.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Remove a dead load-instruction ; (an load whose result is not used anywhere) diff --git a/polly/test/Simplify/dead_access_phi.ll b/polly/test/Simplify/dead_access_phi.ll index 6044f7f50be7..d263b89aff58 100644 --- a/polly/test/Simplify/dead_access_phi.ll +++ b/polly/test/Simplify/dead_access_phi.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Remove a dead PHI write/read pair ; (accesses that are effectively not used) diff --git a/polly/test/Simplify/dead_access_value.ll b/polly/test/Simplify/dead_access_value.ll index a3b9d5ebe76a..6e3c211577f6 100644 --- a/polly/test/Simplify/dead_access_value.ll +++ b/polly/test/Simplify/dead_access_value.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Remove a dead value write/read pair ; (accesses that are effectively not used) diff --git a/polly/test/Simplify/dead_instruction.ll b/polly/test/Simplify/dead_instruction.ll index 2bf7f8571a46..4e693b0ccb44 100644 --- a/polly/test/Simplify/dead_instruction.ll +++ b/polly/test/Simplify/dead_instruction.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Remove a dead instruction ; (an instruction whose result is not used anywhere) diff --git a/polly/test/Simplify/emptyaccessdomain.ll b/polly/test/Simplify/emptyaccessdomain.ll index bf6d4d9dc8bd..54ac14ab398c 100644 --- a/polly/test/Simplify/emptyaccessdomain.ll +++ b/polly/test/Simplify/emptyaccessdomain.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines ; ; for (int j = 0; j < n; j += 1) { ; A[0] = 42.0; diff --git a/polly/test/Simplify/exit_phi_accesses-2.ll b/polly/test/Simplify/exit_phi_accesses-2.ll index 2116d8008aec..01748aa59bd3 100644 --- a/polly/test/Simplify/exit_phi_accesses-2.ll +++ b/polly/test/Simplify/exit_phi_accesses-2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,scop(print)' -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-scops -polly-print-simplify -disable-output < %s | FileCheck %s ; ; The use of %sum.next by %phi counts as an escaping use. ; Don't remove the scalar write of %sum.next. diff --git a/polly/test/Simplify/func-b320a7.ll b/polly/test/Simplify/func-b320a7.ll index c5afc37eb7de..c8a823a468d7 100644 --- a/polly/test/Simplify/func-b320a7.ll +++ b/polly/test/Simplify/func-b320a7.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print,polly-optree' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-simplify -polly-optree -disable-output < %s | FileCheck %s -match-full-lines ; llvm.org/PR47098 ; Use-after-free by reference to Stmt remaining in InstStmtMap after removing it has been removed by Scop::simplifyScop. diff --git a/polly/test/Simplify/gemm.ll b/polly/test/Simplify/gemm.ll index 4074078742fc..23f8de5573cd 100644 --- a/polly/test/Simplify/gemm.ll +++ b/polly/test/Simplify/gemm.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s ; ; void gemm(float A[][1024], float B[][1024], float C[][1024]) { ; for (long i = 0; i < 1024; i++) diff --git a/polly/test/Simplify/nocoalesce_differentvalues.ll b/polly/test/Simplify/nocoalesce_differentvalues.ll index d08c80ee0c06..68991d2eecf5 100644 --- a/polly/test/Simplify/nocoalesce_differentvalues.ll +++ b/polly/test/Simplify/nocoalesce_differentvalues.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s ; ; Do not combine stores that write different values. ; diff --git a/polly/test/Simplify/nocoalesce_elementmismatch.ll b/polly/test/Simplify/nocoalesce_elementmismatch.ll index af12e611fdbc..2bab360e6858 100644 --- a/polly/test/Simplify/nocoalesce_elementmismatch.ll +++ b/polly/test/Simplify/nocoalesce_elementmismatch.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s ; ; Do not combine stores that do not write to different elements in the ; same instance. diff --git a/polly/test/Simplify/nocoalesce_readbetween.ll b/polly/test/Simplify/nocoalesce_readbetween.ll index 1a71d2da4c1f..ada79dc18b87 100644 --- a/polly/test/Simplify/nocoalesce_readbetween.ll +++ b/polly/test/Simplify/nocoalesce_readbetween.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s ; ; Do not combine stores if there is a read between them. ; Note: The read between is unused, so will be removed by markAndSweep. diff --git a/polly/test/Simplify/nocoalesce_writebetween.ll b/polly/test/Simplify/nocoalesce_writebetween.ll index bc2c47a4c9ec..48e785ec2c26 100644 --- a/polly/test/Simplify/nocoalesce_writebetween.ll +++ b/polly/test/Simplify/nocoalesce_writebetween.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s ; ; Do not combine stores if there is a write between them. ; diff --git a/polly/test/Simplify/notdead_region_exitphi.ll b/polly/test/Simplify/notdead_region_exitphi.ll index a796f2a419ad..bd29fd578b97 100644 --- a/polly/test/Simplify/notdead_region_exitphi.ll +++ b/polly/test/Simplify/notdead_region_exitphi.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Do not remove dependencies of a phi node in a region's exit block. ; diff --git a/polly/test/Simplify/notdead_region_innerphi.ll b/polly/test/Simplify/notdead_region_innerphi.ll index c76485cb5019..a176a28af233 100644 --- a/polly/test/Simplify/notdead_region_innerphi.ll +++ b/polly/test/Simplify/notdead_region_innerphi.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Do not remove dependencies of a phi node within a region statement (%phi). ; diff --git a/polly/test/Simplify/notredundant_region_loop.ll b/polly/test/Simplify/notredundant_region_loop.ll index 0bf0dd531524..0ea9be7e9d2d 100644 --- a/polly/test/Simplify/notredundant_region_loop.ll +++ b/polly/test/Simplify/notredundant_region_loop.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -polly-allow-nonaffine-loops -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-allow-nonaffine-loops -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines ; ; Do not remove the store in region_entry. It can be executed multiple times ; due to being part of a non-affine loop. diff --git a/polly/test/Simplify/notredundant_region_middle.ll b/polly/test/Simplify/notredundant_region_middle.ll index 392dd48ae985..84598746e0bb 100644 --- a/polly/test/Simplify/notredundant_region_middle.ll +++ b/polly/test/Simplify/notredundant_region_middle.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Do not remove redundant stores in the middle of region statements. ; The store in region_true could be removed, but in practice we do try to diff --git a/polly/test/Simplify/notredundant_synthesizable_unknownit.ll b/polly/test/Simplify/notredundant_synthesizable_unknownit.ll index d522d5dd68ae..2affdbb2f1de 100644 --- a/polly/test/Simplify/notredundant_synthesizable_unknownit.ll +++ b/polly/test/Simplify/notredundant_synthesizable_unknownit.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Do not remove the scalar value write of %i.trunc in inner.for. ; It is used by body. diff --git a/polly/test/Simplify/out-of-scop-use-in-region-entry-phi-node.ll b/polly/test/Simplify/out-of-scop-use-in-region-entry-phi-node.ll index fe57a0ef6c9d..511f35a9388e 100644 --- a/polly/test/Simplify/out-of-scop-use-in-region-entry-phi-node.ll +++ b/polly/test/Simplify/out-of-scop-use-in-region-entry-phi-node.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb '-passes=print,scop(print)' -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-scops -polly-print-simplify -disable-output < %s | FileCheck %s ; ; %tmp5 must keep the Value WRITE MemoryAccess, because as an incoming value of ; %tmp4, it is an "external use". diff --git a/polly/test/Simplify/overwritten.ll b/polly/test/Simplify/overwritten.ll index b693e9c0db27..a32d6a8daeb0 100644 --- a/polly/test/Simplify/overwritten.ll +++ b/polly/test/Simplify/overwritten.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s ; ; Remove a store that is overwritten by another store in the same statement. ; diff --git a/polly/test/Simplify/overwritten_3phi.ll b/polly/test/Simplify/overwritten_3phi.ll index 84cf67fa7cdc..24758b9b7cf9 100644 --- a/polly/test/Simplify/overwritten_3phi.ll +++ b/polly/test/Simplify/overwritten_3phi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s ; ; Remove identical writes ; (two stores in the same statement that write the same value to the same diff --git a/polly/test/Simplify/overwritten_3store.ll b/polly/test/Simplify/overwritten_3store.ll index 72e9917b36a9..63eb5b54f931 100644 --- a/polly/test/Simplify/overwritten_3store.ll +++ b/polly/test/Simplify/overwritten_3store.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadNPMPolly -polly-stmt-granularity=bb "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s ; ; Remove a store that is overwritten by another store in the same statement. ; Check that even multiple stores are removed. diff --git a/polly/test/Simplify/overwritten_implicit_and_explicit.ll b/polly/test/Simplify/overwritten_implicit_and_explicit.ll index ba7c6d0f20b1..56c63b48f761 100644 --- a/polly/test/Simplify/overwritten_implicit_and_explicit.ll +++ b/polly/test/Simplify/overwritten_implicit_and_explicit.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s ; ; Remove a store that is overwritten by another store in the same statement. ; Check that this works even if one of the writes is a scalar MemoryKind. diff --git a/polly/test/Simplify/overwritten_loadbetween.ll b/polly/test/Simplify/overwritten_loadbetween.ll index f271b4559dc8..b31f45d5db62 100644 --- a/polly/test/Simplify/overwritten_loadbetween.ll +++ b/polly/test/Simplify/overwritten_loadbetween.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck -match-full-lines %s ; ; Do not remove overwrites when the value is read before. ; diff --git a/polly/test/Simplify/overwritten_scalar.ll b/polly/test/Simplify/overwritten_scalar.ll index 41c5c6fa2470..d55ea7712c36 100644 --- a/polly/test/Simplify/overwritten_scalar.ll +++ b/polly/test/Simplify/overwritten_scalar.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck -match-full-lines %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck -match-full-lines %s ; ; Remove identical writes ; (two stores in the same statement that write the same value to the same diff --git a/polly/test/Simplify/pass_existence.ll b/polly/test/Simplify/pass_existence.ll index a8fc184b1616..fc5287ed2ee2 100644 --- a/polly/test/Simplify/pass_existence.ll +++ b/polly/test/Simplify/pass_existence.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly -disable-output "-passes=scop(print)" < %s -aa-pipeline=basic-aa < %s | FileCheck %s +; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly -disable-output "-passes=scop(print)" < %s -aa-pipeline=basic-aa < %s | FileCheck %s ; ; Simple test for the existence of the Simplify pass. ; diff --git a/polly/test/Simplify/phi_in_regionstmt.ll b/polly/test/Simplify/phi_in_regionstmt.ll index 4c6a8744e200..32bb75427589 100644 --- a/polly/test/Simplify/phi_in_regionstmt.ll +++ b/polly/test/Simplify/phi_in_regionstmt.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; The PHINode %cond91.sink.sink.us.sink.6 is in the middle of a region ; statement. diff --git a/polly/test/Simplify/pr33323.ll b/polly/test/Simplify/pr33323.ll index de2e00e8e2e9..751f0bff5961 100644 --- a/polly/test/Simplify/pr33323.ll +++ b/polly/test/Simplify/pr33323.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s ; ; llvm.org/PR33323 ; diff --git a/polly/test/Simplify/redundant.ll b/polly/test/Simplify/redundant.ll index 720f2e3d0ef2..e85352bc889f 100644 --- a/polly/test/Simplify/redundant.ll +++ b/polly/test/Simplify/redundant.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Remove redundant store (a store that writes the same value already ; at the destination) diff --git a/polly/test/Simplify/redundant_differentindex.ll b/polly/test/Simplify/redundant_differentindex.ll index c79364608e58..23531c24344f 100644 --- a/polly/test/Simplify/redundant_differentindex.ll +++ b/polly/test/Simplify/redundant_differentindex.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; A store that has a different index than the load it is storing is ; not redundant. diff --git a/polly/test/Simplify/redundant_region.ll b/polly/test/Simplify/redundant_region.ll index d5c9586283de..dbcb420ac2f3 100644 --- a/polly/test/Simplify/redundant_region.ll +++ b/polly/test/Simplify/redundant_region.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines ; ; Remove redundant store (a store that writes the same value already ; at the destination) in a region. diff --git a/polly/test/Simplify/redundant_region_scalar.ll b/polly/test/Simplify/redundant_region_scalar.ll index ab07126fe268..95a581ad6f57 100644 --- a/polly/test/Simplify/redundant_region_scalar.ll +++ b/polly/test/Simplify/redundant_region_scalar.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines ; ; Remove redundant store (a store that writes the same value already ; at the destination) in a region. diff --git a/polly/test/Simplify/redundant_scalarwrite.ll b/polly/test/Simplify/redundant_scalarwrite.ll index c09be5f61837..e2f7bbedc023 100644 --- a/polly/test/Simplify/redundant_scalarwrite.ll +++ b/polly/test/Simplify/redundant_scalarwrite.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines ; ; Remove redundant scalar stores. ; diff --git a/polly/test/Simplify/redundant_storebetween.ll b/polly/test/Simplify/redundant_storebetween.ll index f87c1126cd26..f624b6e5b995 100644 --- a/polly/test/Simplify/redundant_storebetween.ll +++ b/polly/test/Simplify/redundant_storebetween.ll @@ -1,4 +1,5 @@ -; RUN: opt %loadPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadNPMPolly "-passes=scop(print)" -disable-output -aa-pipeline=basic-aa < %s | FileCheck %s -match-full-lines ; ; Don't remove store where there is another store to the same target ; in-between them. diff --git a/polly/test/Simplify/scalability1.ll b/polly/test/Simplify/scalability1.ll index a91574e2b274..0ef99ce1ad8e 100644 --- a/polly/test/Simplify/scalability1.ll +++ b/polly/test/Simplify/scalability1.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-ignore-inbounds '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-ignore-inbounds -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines ; ; Test scalability. ; diff --git a/polly/test/Simplify/scalability2.ll b/polly/test/Simplify/scalability2.ll index 4e4874df219e..bac0810b0afa 100644 --- a/polly/test/Simplify/scalability2.ll +++ b/polly/test/Simplify/scalability2.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly -polly-ignore-inbounds '-passes=print' -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-ignore-inbounds -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines ; ; Test scalability. ; diff --git a/polly/test/Simplify/sweep_mapped_phi.ll b/polly/test/Simplify/sweep_mapped_phi.ll index 3b9e61c72b4d..add1681cdf36 100644 --- a/polly/test/Simplify/sweep_mapped_phi.ll +++ b/polly/test/Simplify/sweep_mapped_phi.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines ; ; Map %phi to A[j], so the scalar write in Stmt_for_bodyA can be removed. ; diff --git a/polly/test/Simplify/sweep_mapped_value.ll b/polly/test/Simplify/sweep_mapped_value.ll index 5992e2401ca5..2e2f9c37febe 100644 --- a/polly/test/Simplify/sweep_mapped_value.ll +++ b/polly/test/Simplify/sweep_mapped_value.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-import-jscop,print' -polly-import-jscop-postfix=transformed -disable-output < %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-print-simplify -disable-output < %s | FileCheck %s -match-full-lines ; ; Map %val to A[j], so the scalar write on Stmt_for_bodyB can be removed. ; diff --git a/polly/test/Simplify/ununsed_read_in_region_entry.ll b/polly/test/Simplify/ununsed_read_in_region_entry.ll index 111c19f706b9..9b2d4521e2d6 100644 --- a/polly/test/Simplify/ununsed_read_in_region_entry.ll +++ b/polly/test/Simplify/ununsed_read_in_region_entry.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output< %s | FileCheck %s -match-full-lines -; RUN: opt %loadPolly '-passes=polly-simplify,polly-codegen' -S < %s | FileCheck %s -check-prefix=CODEGEN +; RUN: opt %loadPolly -polly-print-simplify -disable-output< %s | FileCheck %s -match-full-lines +; RUN: opt %loadPolly -polly-simplify -polly-codegen -S < %s | FileCheck %s -check-prefix=CODEGEN ; ; for (int i = 0; i < n; i+=1) { ; (void)A[0]; diff --git a/polly/test/Support/Plugins.ll b/polly/test/Support/Plugins.ll index c4579470192b..cee878f1c6ac 100644 --- a/polly/test/Support/Plugins.ll +++ b/polly/test/Support/Plugins.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=polly-prepare,scop(print)' -S < %s \ +; RUN: opt %loadNPMPolly -passes='polly-prepare,scop(print)' -S < %s \ ; RUN: | FileCheck %s ; This testcase tests plugin registration. Check-lines below serve to verify diff --git a/polly/test/Support/defaultpipelines.ll b/polly/test/Support/defaultpipelines.ll index 6681042727c6..ab0329a70327 100644 --- a/polly/test/Support/defaultpipelines.ll +++ b/polly/test/Support/defaultpipelines.ll @@ -1,9 +1,9 @@ -; RUN: opt %loadPolly -polly -O0 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF -; RUN: opt %loadPolly -polly -O1 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON -; RUN: opt %loadPolly -polly -O2 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON -; RUN: opt %loadPolly -polly -O3 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON -; RUN: opt %loadPolly -polly -Os -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF -; RUN: opt %loadPolly -polly -Oz -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF +; RUN: opt %loadNPMPolly -polly -O0 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF +; RUN: opt %loadNPMPolly -polly -O1 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON +; RUN: opt %loadNPMPolly -polly -O2 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON +; RUN: opt %loadNPMPolly -polly -O3 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ON +; RUN: opt %loadNPMPolly -polly -Os -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF +; RUN: opt %loadNPMPolly -polly -Oz -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OFF ; ; Check that Polly's default pipeline works from detection to code generation ; with either pass manager. diff --git a/polly/test/Support/dumpfunction.ll b/polly/test/Support/dumpfunction.ll index e99261508f1a..863212b2ef7d 100644 --- a/polly/test/Support/dumpfunction.ll +++ b/polly/test/Support/dumpfunction.ll @@ -1,9 +1,9 @@ ; New pass manager -; RUN: opt %loadPolly -O3 -polly -polly-position=before-vectorizer -polly-dump-before --disable-output %s +; RUN: opt %loadNPMPolly -O3 -polly -polly-position=before-vectorizer -polly-dump-before --disable-output %s ; RUN: FileCheck --input-file=dumpfunction-callee-before.ll --check-prefix=CHECK --check-prefix=CALLEE %s ; RUN: FileCheck --input-file=dumpfunction-caller-before.ll --check-prefix=CHECK --check-prefix=CALLER %s ; -; RUN: opt %loadPolly -O3 -polly -polly-position=before-vectorizer -polly-dump-after --disable-output %s +; RUN: opt %loadNPMPolly -O3 -polly -polly-position=before-vectorizer -polly-dump-after --disable-output %s ; RUN: FileCheck --input-file=dumpfunction-callee-after.ll --check-prefix=CHECK --check-prefix=CALLEE %s ; RUN: FileCheck --input-file=dumpfunction-caller-after.ll --check-prefix=CHECK --check-prefix=CALLER %s diff --git a/polly/test/Support/dumpmodule.ll b/polly/test/Support/dumpmodule.ll index d7aa88439f64..693fe4bc6cde 100644 --- a/polly/test/Support/dumpmodule.ll +++ b/polly/test/Support/dumpmodule.ll @@ -1,5 +1,5 @@ -; RUN: opt %loadPolly -O3 -polly -polly-position=early -polly-dump-before-file=%t-npm-before-early.ll --disable-output < %s && FileCheck --input-file=%t-npm-before-early.ll --check-prefix=EARLY %s -; RUN: opt %loadPolly -O3 -polly -polly-position=early -polly-dump-after-file=%t-npm-after-early.ll --disable-output < %s && FileCheck --input-file=%t-npm-after-early.ll --check-prefix=EARLY --check-prefix=AFTEREARLY %s +; RUN: opt %loadNPMPolly -O3 -polly -polly-position=early -polly-dump-before-file=%t-npm-before-early.ll --disable-output < %s && FileCheck --input-file=%t-npm-before-early.ll --check-prefix=EARLY %s +; RUN: opt %loadNPMPolly -O3 -polly -polly-position=early -polly-dump-after-file=%t-npm-after-early.ll --disable-output < %s && FileCheck --input-file=%t-npm-after-early.ll --check-prefix=EARLY --check-prefix=AFTEREARLY %s ; ; Check the module dumping before Polly at specific positions in the ; pass pipeline. diff --git a/polly/test/Support/exportjson.ll b/polly/test/Support/exportjson.ll index 22ba845bafc2..22cfea23534c 100644 --- a/polly/test/Support/exportjson.ll +++ b/polly/test/Support/exportjson.ll @@ -1,6 +1,6 @@ ; RUN: rm -rf %t ; RUN: mkdir -p %t -; RUN: opt %loadPolly -polly-import-jscop-dir=%t -polly -O2 -polly-export -S < %s +; RUN: opt %loadNPMPolly -polly-import-jscop-dir=%t -polly -O2 -polly-export -S < %s ; RUN: FileCheck %s -input-file %t/exportjson___%entry.split---%return.jscop ; ; for (int j = 0; j < n; j += 1) { diff --git a/polly/test/Support/isl-args.ll b/polly/test/Support/isl-args.ll index 442742d55f81..efa94194bc3f 100644 --- a/polly/test/Support/isl-args.ll +++ b/polly/test/Support/isl-args.ll @@ -1,7 +1,7 @@ -; RUN: opt %loadPolly '-passes=print' -disable-output -polly-isl-arg=-V < %s | FileCheck %s -match-full-lines --check-prefix=VERSION -; RUN: opt %loadPolly '-passes=print' -disable-output -polly-isl-arg=-h < %s | FileCheck %s -match-full-lines --check-prefix=HELP -; RUN: not opt %loadPolly '-passes=print' -disable-output -polly-isl-arg=-asdf < %s 2>&1| FileCheck %s -match-full-lines --check-prefix=UNKNOWN -; RUN: opt %loadPolly '-passes=print' -disable-output -polly-isl-arg=--schedule-algorithm=feautrier < %s +; RUN: opt %loadPolly -polly-scops -disable-output -polly-isl-arg=-V < %s | FileCheck %s -match-full-lines --check-prefix=VERSION +; RUN: opt %loadPolly -polly-scops -disable-output -polly-isl-arg=-h < %s | FileCheck %s -match-full-lines --check-prefix=HELP +; RUN: not opt %loadPolly -polly-scops -disable-output -polly-isl-arg=-asdf < %s 2>&1| FileCheck %s -match-full-lines --check-prefix=UNKNOWN +; RUN: opt %loadPolly -polly-scops -disable-output -polly-isl-arg=--schedule-algorithm=feautrier < %s ; VERSION: isl-{{.*}}-IMath-32 ; HELP: Usage: -polly-isl-arg [OPTION...] diff --git a/polly/test/Support/pipelineposition.ll b/polly/test/Support/pipelineposition.ll index 757af91011fb..a4506ba1d64e 100644 --- a/polly/test/Support/pipelineposition.ll +++ b/polly/test/Support/pipelineposition.ll @@ -1,6 +1,6 @@ -; RUN: opt %loadPolly -O3 -polly -polly-position=early -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=NOINLINE -; RUN: opt %loadPolly -O3 -polly -polly-position=early -polly-run-inliner -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=INLINED1 -; RUN: opt %loadPolly -O3 -polly -polly-position=before-vectorizer -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=INLINED3 +; RUN: opt %loadNPMPolly -O3 -polly -polly-position=early -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=NOINLINE +; RUN: opt %loadNPMPolly -O3 -polly -polly-position=early -polly-run-inliner -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=INLINED1 +; RUN: opt %loadNPMPolly -O3 -polly -polly-position=before-vectorizer -disable-output -debug-only=polly-scops < %s 2>&1 | FileCheck %s --check-prefix=INLINED3 ; ; REQUIRES: asserts ; diff --git a/polly/test/Support/pollyDebug.ll b/polly/test/Support/pollyDebug.ll index e5e327c3976e..ada079023b6c 100644 --- a/polly/test/Support/pollyDebug.ll +++ b/polly/test/Support/pollyDebug.ll @@ -1,5 +1,5 @@ ; Test if "polly-debug" flag enables debug prints from different parts of polly -; RUN: opt %loadPolly -O3 -polly -polly-debug --disable-output < %s 2>&1 | FileCheck %s +; RUN: opt %loadNPMPolly -O3 -polly -polly-debug --disable-output < %s 2>&1 | FileCheck %s ; ; REQUIRES: asserts diff --git a/polly/test/lit.site.cfg.in b/polly/test/lit.site.cfg.in index 703752896239..b44061260834 100644 --- a/polly/test/lit.site.cfg.in +++ b/polly/test/lit.site.cfg.in @@ -38,11 +38,16 @@ if config.llvm_polly_link_into_tools == '' or \ config.llvm_polly_link_into_tools.lower() == 'false' or \ config.llvm_polly_link_into_tools.lower() == 'notfound' or \ config.llvm_polly_link_into_tools.lower() == 'llvm_polly_link_into_tools-notfound': - config.substitutions.append(('%loadPolly', '-load-pass-plugin ' + config.substitutions.append(('%loadPolly', '-load ' + + config.polly_lib_dir + '/LLVMPolly@LLVM_SHLIBEXT@' + + commonOpts )) + config.substitutions.append(('%loadNPMPolly', '-load-pass-plugin ' + config.polly_lib_dir + '/LLVMPolly@LLVM_SHLIBEXT@' + commonOpts )) else: config.substitutions.append(('%loadPolly', commonOpts )) + config.substitutions.append(('%loadNPMPolly', commonOpts )) + import lit.llvm lit.llvm.initialize(lit_config, config) diff --git a/polly/test/polly.ll b/polly/test/polly.ll index 6654468470a6..f78cceacfb12 100644 --- a/polly/test/polly.ll +++ b/polly/test/polly.ll @@ -1,4 +1,4 @@ -; RUN: opt %loadPolly '-passes=print' -S < %s 2>&1 | FileCheck %s +; RUN: opt %loadPolly -polly-scops -S < %s | 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-n8:16:32:64" define void @foo() nounwind { start: -- GitLab From 24180ea0c295856a696992f072c36259a266226b Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Tue, 14 May 2024 22:16:06 -0700 Subject: [PATCH 307/578] [analyzer] Treat break, continue, goto, and label statements as trivial in WebKit checkers. (#91873) Also allow CXXBindTemporaryExpr, which creates a temporary object with a non-trivial destructor, and add a few more std and WTF functions to the explicitly allowed list. --- .../Checkers/WebKit/PtrTypesSemantics.cpp | 23 +++++- .../Checkers/WebKit/uncounted-obj-arg.cpp | 78 +++++++++++++++++-- 2 files changed, 94 insertions(+), 7 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index ad493587affa..950d35a090a3 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -308,6 +308,12 @@ public: bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); } bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); } + // break, continue, goto, and label statements are always trivial. + bool VisitBreakStmt(const BreakStmt *) { return true; } + bool VisitContinueStmt(const ContinueStmt *) { return true; } + bool VisitGotoStmt(const GotoStmt *) { return true; } + bool VisitLabelStmt(const LabelStmt *) { return true; } + bool VisitUnaryOperator(const UnaryOperator *UO) { // Unary operators are trivial if its operand is trivial except co_await. return UO->getOpcode() != UO_Coawait && Visit(UO->getSubExpr()); @@ -349,12 +355,17 @@ public: return false; const auto &Name = safeGetName(Callee); + if (Callee->isInStdNamespace() && + (Name == "addressof" || Name == "forward" || Name == "move")) + return true; + if (Name == "WTFCrashWithInfo" || Name == "WTFBreakpointTrap" || + Name == "WTFCrashWithSecurityImplication" || Name == "WTFCrash" || Name == "WTFReportAssertionFailure" || Name == "isMainThread" || Name == "isMainThreadOrGCThread" || Name == "isMainRunLoop" || Name == "isWebThread" || Name == "isUIThread" || - Name == "compilerFenceForCrash" || Name == "bitwise_cast" || - Name == "addressof" || Name.find("__builtin") == 0) + Name == "mayBeGCThread" || Name == "compilerFenceForCrash" || + Name == "bitwise_cast" || Name.find("__builtin") == 0) return true; return TrivialFunctionAnalysis::isTrivialImpl(Callee, Cache); @@ -445,6 +456,14 @@ public: return Visit(VMT->getSubExpr()); } + bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE) { + if (auto *Temp = BTE->getTemporary()) { + if (!TrivialFunctionAnalysis::isTrivialImpl(Temp->getDestructor(), Cache)) + return false; + } + return Visit(BTE->getSubExpr()); + } + bool VisitExprWithCleanups(const ExprWithCleanups *EWC) { return Visit(EWC->getSubExpr()); } diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp index 073f3252160e..ed37671df3d3 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp @@ -7,6 +7,9 @@ void WTFBreakpointTrap(); void WTFCrashWithInfo(int, const char*, const char*, int); void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion); +void WTFCrash(void); +void WTFCrashWithSecurityImplication(void); + inline void compilerFenceForCrash() { asm volatile("" ::: "memory"); @@ -62,14 +65,25 @@ void WTFCrashWithInfo(int line, const char* file, const char* function, int coun template ToType bitwise_cast(FromType from); +namespace std { + template T* addressof(T& arg); +template +T&& forward(T& arg); + +template +T&& move( T&& t ); + +} // namespace std + bool isMainThread(); bool isMainThreadOrGCThread(); bool isMainRunLoop(); bool isWebThread(); bool isUIThread(); +bool mayBeGCThread(); enum class Flags : unsigned short { Flag1 = 1 << 0, @@ -161,16 +175,42 @@ private: class ComplexNumber { public: - ComplexNumber() : real(0), complex(0) { } + ComplexNumber() : realPart(0), complexPart(0) { } ComplexNumber(const ComplexNumber&); - ComplexNumber& operator++() { real.someMethod(); return *this; } + ComplexNumber& operator++() { realPart.someMethod(); return *this; } ComplexNumber operator++(int); ComplexNumber& operator<<(int); ComplexNumber& operator+(); + const Number& real() const { return realPart; } + private: - Number real; - Number complex; + Number realPart; + Number complexPart; +}; + +class ObjectWithNonTrivialDestructor { +public: + ObjectWithNonTrivialDestructor() { } + ObjectWithNonTrivialDestructor(unsigned v) : v(v) { } + ~ObjectWithNonTrivialDestructor() { } + + unsigned value() const { return v; } + +private: + unsigned v { 0 }; +}; + +class ObjectWithMutatingDestructor { +public: + ObjectWithMutatingDestructor() : n(0) { } + ObjectWithMutatingDestructor(int n) : n(n) { } + ~ObjectWithMutatingDestructor() { n.someMethod(); } + + unsigned value() const { return n.value(); } + +private: + Number n; }; class RefCounted { @@ -248,7 +288,7 @@ public: int trivial40() { return v << 2; } unsigned trivial41() { v = ++s_v; return v; } unsigned trivial42() { return bitwise_cast(nullptr); } - Number* trivial43() { return addressof(*number); } + Number* trivial43() { return std::addressof(*number); } Number* trivial44() { return new Number(1); } ComplexNumber* trivial45() { return new ComplexNumber(); } void trivial46() { ASSERT(isMainThread()); } @@ -256,6 +296,21 @@ public: void trivial48() { ASSERT(isMainRunLoop()); } void trivial49() { ASSERT(isWebThread()); } void trivial50() { ASSERT(isUIThread()); } + void trivial51() { ASSERT(mayBeGCThread()); } + void trivial52() { WTFCrash(); } + void trivial53() { WTFCrashWithSecurityImplication(); } + unsigned trivial54() { return ComplexNumber().real().value(); } + Number&& trivial55() { return std::forward(*number); } + unsigned trivial56() { Number n { 5 }; return std::move(n).value(); } + void trivial57() { do { break; } while (1); } + void trivial58() { do { continue; } while (0); } + void trivial59() { + do { goto label; } + while (0); + label: + return; + } + unsigned trivial60() { return ObjectWithNonTrivialDestructor { 5 }.value(); } static RefCounted& singleton() { static RefCounted s_RefCounted; @@ -335,6 +390,7 @@ public: ComplexNumber nonTrivial17() { return complex << 2; } ComplexNumber nonTrivial18() { return +complex; } ComplexNumber* nonTrivial19() { return new ComplexNumber(complex); } + unsigned nonTrivial20() { return ObjectWithMutatingDestructor { 7 }.value(); } static unsigned s_v; unsigned v { 0 }; @@ -413,6 +469,16 @@ public: getFieldTrivial().trivial48(); // no-warning getFieldTrivial().trivial49(); // no-warning getFieldTrivial().trivial50(); // no-warning + getFieldTrivial().trivial51(); // no-warning + getFieldTrivial().trivial52(); // no-warning + getFieldTrivial().trivial53(); // no-warning + getFieldTrivial().trivial54(); // no-warning + getFieldTrivial().trivial55(); // no-warning + getFieldTrivial().trivial56(); // no-warning + getFieldTrivial().trivial57(); // no-warning + getFieldTrivial().trivial58(); // no-warning + getFieldTrivial().trivial59(); // no-warning + getFieldTrivial().trivial60(); // no-warning RefCounted::singleton().trivial18(); // no-warning RefCounted::singleton().someFunction(); // no-warning @@ -457,6 +523,8 @@ public: // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} getFieldTrivial().nonTrivial19(); // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + getFieldTrivial().nonTrivial20(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} } }; -- GitLab From 0980f715cf7c3d78be6ba64e902bd2dfad3ebc75 Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Wed, 15 May 2024 07:26:23 +0200 Subject: [PATCH 308/578] [libc][errno] Remove previously added errno numbers (#92163) Introduced in https://github.com/llvm/llvm-project/pull/91150. Not needed anymore as https://github.com/llvm/llvm-project/pull/92041 fixed the root cause. `ENAMETOOLONG` and `EOVERFLOW` are well defined in ``. Post mortem: Due to the previously missing inclusion of `` (fixed with https://github.com/llvm/llvm-project/pull/92041), I misinterpreted an undefined macro issue during the development of https://github.com/llvm/llvm-project/pull/91150 as being caused by a missing definition rather than by the missing inclusion of the linux header. I realized too late that `ENAMETOOLONG` and `EOVERFLOW` were correctly defined in `` and that it was my missing inclusion that caused the problem. --- libc/include/llvm-libc-macros/generic-error-number-macros.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libc/include/llvm-libc-macros/generic-error-number-macros.h b/libc/include/llvm-libc-macros/generic-error-number-macros.h index cb4411fbac66..59b121ef1481 100644 --- a/libc/include/llvm-libc-macros/generic-error-number-macros.h +++ b/libc/include/llvm-libc-macros/generic-error-number-macros.h @@ -43,7 +43,5 @@ #define EPIPE 32 #define EDOM 33 #define ERANGE 34 -#define ENAMETOOLONG 36 -#define EOVERFLOW 75 #endif // LLVM_LIBC_MACROS_GENERIC_ERROR_NUMBER_MACROS_H -- GitLab From d7bb0723fe79d2b75d41789d2ffadda3567dd94e Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 15 May 2024 07:41:28 +0200 Subject: [PATCH 309/578] InstCombine: Emit ldexp intrinsic in exp2->ldexp combine (#92039) Prefer to emit the intrinsic over a libcall in the intrinsic or no-math-errno case. --- .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 17 +- llvm/test/Transforms/InstCombine/exp2-1.ll | 123 ++++++++++++-- .../Transforms/InstCombine/exp2-to-ldexp.ll | 150 ++++++++++++++++++ 3 files changed, 272 insertions(+), 18 deletions(-) create mode 100644 llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 174cc7a3c778..9cb8e20b4806 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -2389,12 +2389,21 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { if ((isa(Op) || isa(Op)) && hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { if (Value *Exp = getIntToFPVal(Op, B, TLI->getIntSize())) { + Constant *One = ConstantFP::get(Ty, 1.0); + + // TODO: Emitting the intrinsic should not depend on whether the libcall + // is available. + if (CI->doesNotAccessMemory()) { + return copyFlags(*CI, B.CreateIntrinsic(Intrinsic::ldexp, + {Ty, Exp->getType()}, + {One, Exp}, CI)); + } + IRBuilderBase::FastMathFlagGuard Guard(B); B.setFastMathFlags(CI->getFastMathFlags()); - return copyFlags( - *CI, emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), Exp, TLI, - LibFunc_ldexp, LibFunc_ldexpf, - LibFunc_ldexpl, B, AttributeList())); + return copyFlags(*CI, emitBinaryFloatFnCall( + One, Exp, TLI, LibFunc_ldexp, LibFunc_ldexpf, + LibFunc_ldexpl, B, AttributeList())); } } diff --git a/llvm/test/Transforms/InstCombine/exp2-1.ll b/llvm/test/Transforms/InstCombine/exp2-1.ll index 8419854d3ec6..5bf70320d9ec 100644 --- a/llvm/test/Transforms/InstCombine/exp2-1.ll +++ b/llvm/test/Transforms/InstCombine/exp2-1.ll @@ -14,6 +14,7 @@ declare float @exp2f(float) declare double @llvm.exp2.f64(double) declare float @llvm.exp2.f32(float) declare <2 x float> @llvm.exp2.v2f32(<2 x float>) +declare fp128 @exp2l(fp128) ; Check exp2(sitofp(x)) -> ldexp(1.0, sext(x)). @@ -227,18 +228,18 @@ define float @test_simplify8(i8 zeroext %x) { define double @test_simplify9(i8 zeroext %x) { ; LDEXP32-LABEL: @test_simplify9( ; LDEXP32-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 -; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) -; LDEXP32-NEXT: ret double [[LDEXP]] +; LDEXP32-NEXT: [[RET:%.*]] = call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 [[TMP1]]) +; LDEXP32-NEXT: ret double [[RET]] ; ; LDEXP16-LABEL: @test_simplify9( ; LDEXP16-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i16 -; LDEXP16-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i16 [[TMP1]]) -; LDEXP16-NEXT: ret double [[LDEXP]] +; LDEXP16-NEXT: [[RET:%.*]] = call double @llvm.ldexp.f64.i16(double 1.000000e+00, i16 [[TMP1]]) +; LDEXP16-NEXT: ret double [[RET]] ; ; NOLDEXPF-LABEL: @test_simplify9( ; NOLDEXPF-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 -; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]]) -; NOLDEXPF-NEXT: ret double [[LDEXP]] +; NOLDEXPF-NEXT: [[RET:%.*]] = call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 [[TMP1]]) +; NOLDEXPF-NEXT: ret double [[RET]] ; ; NOLDEXP-LABEL: @test_simplify9( ; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to double @@ -253,13 +254,13 @@ define double @test_simplify9(i8 zeroext %x) { define float @test_simplify10(i8 zeroext %x) { ; LDEXP32-LABEL: @test_simplify10( ; LDEXP32-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32 -; LDEXP32-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[TMP1]]) -; LDEXP32-NEXT: ret float [[LDEXPF]] +; LDEXP32-NEXT: [[RET:%.*]] = call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) +; LDEXP32-NEXT: ret float [[RET]] ; ; LDEXP16-LABEL: @test_simplify10( ; LDEXP16-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i16 -; LDEXP16-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i16 [[TMP1]]) -; LDEXP16-NEXT: ret float [[LDEXPF]] +; LDEXP16-NEXT: [[RET:%.*]] = call float @llvm.ldexp.f32.i16(float 1.000000e+00, i16 [[TMP1]]) +; LDEXP16-NEXT: ret float [[RET]] ; ; NOLDEXPF-LABEL: @test_simplify10( ; NOLDEXPF-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to float @@ -279,13 +280,13 @@ define float @test_simplify10(i8 zeroext %x) { define float @sitofp_scalar_intrinsic_with_FMF(i8 %x) { ; LDEXP32-LABEL: @sitofp_scalar_intrinsic_with_FMF( ; LDEXP32-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i32 -; LDEXP32-NEXT: [[LDEXPF:%.*]] = tail call nnan float @ldexpf(float 1.000000e+00, i32 [[TMP1]]) -; LDEXP32-NEXT: ret float [[LDEXPF]] +; LDEXP32-NEXT: [[R:%.*]] = tail call nnan float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) +; LDEXP32-NEXT: ret float [[R]] ; ; LDEXP16-LABEL: @sitofp_scalar_intrinsic_with_FMF( ; LDEXP16-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i16 -; LDEXP16-NEXT: [[LDEXPF:%.*]] = tail call nnan float @ldexpf(float 1.000000e+00, i16 [[TMP1]]) -; LDEXP16-NEXT: ret float [[LDEXPF]] +; LDEXP16-NEXT: [[R:%.*]] = tail call nnan float @llvm.ldexp.f32.i16(float 1.000000e+00, i16 [[TMP1]]) +; LDEXP16-NEXT: ret float [[R]] ; ; NOLDEXPF-LABEL: @sitofp_scalar_intrinsic_with_FMF( ; NOLDEXPF-NEXT: [[S:%.*]] = sitofp i8 [[X:%.*]] to float @@ -330,3 +331,97 @@ define <2 x float> @sitofp_vector_intrinsic_with_FMF(<2 x i8> %x) { %r = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> %s) ret <2 x float> %r } + +define double @test_readonly_exp2_f64_of_sitofp(i32 %x) { +; LDEXP32-LABEL: @test_readonly_exp2_f64_of_sitofp( +; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[X:%.*]]) +; LDEXP32-NEXT: ret double [[LDEXP]] +; +; LDEXP16-LABEL: @test_readonly_exp2_f64_of_sitofp( +; LDEXP16-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to double +; LDEXP16-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) #[[ATTR2:[0-9]+]] +; LDEXP16-NEXT: ret double [[RET]] +; +; NOLDEXPF-LABEL: @test_readonly_exp2_f64_of_sitofp( +; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[X:%.*]]) +; NOLDEXPF-NEXT: ret double [[LDEXP]] +; +; NOLDEXP-LABEL: @test_readonly_exp2_f64_of_sitofp( +; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to double +; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]]) #[[ATTR1:[0-9]+]] +; NOLDEXP-NEXT: ret double [[RET]] +; + %conv = sitofp i32 %x to double + %ret = call double @exp2(double %conv) readonly + ret double %ret +} + +define float @test_readonly_exp2f_f32_of_sitofp(i32 %x) { +; LDEXP32-LABEL: @test_readonly_exp2f_f32_of_sitofp( +; LDEXP32-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) +; LDEXP32-NEXT: ret float [[LDEXPF]] +; +; LDEXP16-LABEL: @test_readonly_exp2f_f32_of_sitofp( +; LDEXP16-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float +; LDEXP16-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]]) #[[ATTR2]] +; LDEXP16-NEXT: ret float [[RET]] +; +; NOLDEXPF-LABEL: @test_readonly_exp2f_f32_of_sitofp( +; NOLDEXPF-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float +; NOLDEXPF-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]]) #[[ATTR2:[0-9]+]] +; NOLDEXPF-NEXT: ret float [[RET]] +; +; NOLDEXP-LABEL: @test_readonly_exp2f_f32_of_sitofp( +; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float +; NOLDEXP-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]]) #[[ATTR1]] +; NOLDEXP-NEXT: ret float [[RET]] +; + %conv = sitofp i32 %x to float + %ret = call float @exp2f(float %conv) readonly + ret float %ret +} + +define fp128 @test_readonly_exp2l_fp128_of_sitofp(i32 %x) { +; LDEXP32-LABEL: @test_readonly_exp2l_fp128_of_sitofp( +; LDEXP32-NEXT: [[LDEXPL:%.*]] = call fp128 @ldexpl(fp128 0xL00000000000000003FFF000000000000, i32 [[X:%.*]]) +; LDEXP32-NEXT: ret fp128 [[LDEXPL]] +; +; LDEXP16-LABEL: @test_readonly_exp2l_fp128_of_sitofp( +; LDEXP16-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to fp128 +; LDEXP16-NEXT: [[RET:%.*]] = call fp128 @exp2l(fp128 [[CONV]]) #[[ATTR2]] +; LDEXP16-NEXT: ret fp128 [[RET]] +; +; NOLDEXP-LABEL: @test_readonly_exp2l_fp128_of_sitofp( +; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to fp128 +; NOLDEXP-NEXT: [[RET:%.*]] = call fp128 @exp2l(fp128 [[CONV]]) #[[ATTR1]] +; NOLDEXP-NEXT: ret fp128 [[RET]] +; + %conv = sitofp i32 %x to fp128 + %ret = call fp128 @exp2l(fp128 %conv) readonly + ret fp128 %ret +} + +define float @test_readonly_exp2f_f32_of_sitofp_flags(i32 %x) { +; LDEXP32-LABEL: @test_readonly_exp2f_f32_of_sitofp_flags( +; LDEXP32-NEXT: [[LDEXPF:%.*]] = call nnan ninf float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) +; LDEXP32-NEXT: ret float [[LDEXPF]] +; +; LDEXP16-LABEL: @test_readonly_exp2f_f32_of_sitofp_flags( +; LDEXP16-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float +; LDEXP16-NEXT: [[RET:%.*]] = call nnan ninf float @exp2f(float [[CONV]]) #[[ATTR2]] +; LDEXP16-NEXT: ret float [[RET]] +; +; NOLDEXPF-LABEL: @test_readonly_exp2f_f32_of_sitofp_flags( +; NOLDEXPF-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float +; NOLDEXPF-NEXT: [[RET:%.*]] = call nnan ninf float @exp2f(float [[CONV]]) #[[ATTR2]] +; NOLDEXPF-NEXT: ret float [[RET]] +; +; NOLDEXP-LABEL: @test_readonly_exp2f_f32_of_sitofp_flags( +; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float +; NOLDEXP-NEXT: [[RET:%.*]] = call nnan ninf float @exp2f(float [[CONV]]) #[[ATTR1]] +; NOLDEXP-NEXT: ret float [[RET]] +; + %conv = sitofp i32 %x to float + %ret = call nnan ninf float @exp2f(float %conv) readonly + ret float %ret +} diff --git a/llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll b/llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll new file mode 100644 index 000000000000..3069ee65e238 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll @@ -0,0 +1,150 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes=instcombine %s | FileCheck -check-prefixes=CHECK,LDEXP %s +; RUN: opt -S -passes=instcombine -disable-builtin=ldexpf -disable-builtin=ldexp -disable-builtin=ldexpl %s | FileCheck -check-prefixes=CHECK,NOLDEXP %s + +define float @exp2_f32_sitofp_i8(i8 %x) { +; LDEXP-LABEL: define float @exp2_f32_sitofp_i8( +; LDEXP-SAME: i8 [[X:%.*]]) { +; LDEXP-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 +; LDEXP-NEXT: [[LDEXPF:%.*]] = call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) +; LDEXP-NEXT: ret float [[LDEXPF]] +; +; NOLDEXP-LABEL: define float @exp2_f32_sitofp_i8( +; NOLDEXP-SAME: i8 [[X:%.*]]) { +; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp i8 [[X]] to float +; NOLDEXP-NEXT: [[EXP2:%.*]] = call float @llvm.exp2.f32(float [[ITOFP]]) +; NOLDEXP-NEXT: ret float [[EXP2]] +; + %itofp = sitofp i8 %x to float + %exp2 = call float @llvm.exp2.f32(float %itofp) + ret float %exp2 +} + +define float @exp2_f32_sitofp_i8_flags(i8 %x) { +; LDEXP-LABEL: define float @exp2_f32_sitofp_i8_flags( +; LDEXP-SAME: i8 [[X:%.*]]) { +; LDEXP-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 +; LDEXP-NEXT: [[LDEXPF:%.*]] = call nnan ninf float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) +; LDEXP-NEXT: ret float [[LDEXPF]] +; +; NOLDEXP-LABEL: define float @exp2_f32_sitofp_i8_flags( +; NOLDEXP-SAME: i8 [[X:%.*]]) { +; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp i8 [[X]] to float +; NOLDEXP-NEXT: [[EXP2:%.*]] = call nnan ninf float @llvm.exp2.f32(float [[ITOFP]]) +; NOLDEXP-NEXT: ret float [[EXP2]] +; + %itofp = sitofp i8 %x to float + %exp2 = call nnan ninf float @llvm.exp2.f32(float %itofp) + ret float %exp2 +} + +define <2 x float> @exp2_v2f32_sitofp_v2i8(<2 x i8> %x) { +; CHECK-LABEL: define <2 x float> @exp2_v2f32_sitofp_v2i8( +; CHECK-SAME: <2 x i8> [[X:%.*]]) { +; CHECK-NEXT: [[ITOFP:%.*]] = sitofp <2 x i8> [[X]] to <2 x float> +; CHECK-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[ITOFP]]) +; CHECK-NEXT: ret <2 x float> [[EXP2]] +; + %itofp = sitofp <2 x i8> %x to <2 x float> + %exp2 = call <2 x float> @llvm.exp2.v2f32(<2 x float> %itofp) + ret <2 x float> %exp2 +} + +define float @exp2_f32_uitofp_i8(i8 %x) { +; LDEXP-LABEL: define float @exp2_f32_uitofp_i8( +; LDEXP-SAME: i8 [[X:%.*]]) { +; LDEXP-NEXT: [[TMP1:%.*]] = zext i8 [[X]] to i32 +; LDEXP-NEXT: [[LDEXPF:%.*]] = call float @llvm.ldexp.f32.i32(float 1.000000e+00, i32 [[TMP1]]) +; LDEXP-NEXT: ret float [[LDEXPF]] +; +; NOLDEXP-LABEL: define float @exp2_f32_uitofp_i8( +; NOLDEXP-SAME: i8 [[X:%.*]]) { +; NOLDEXP-NEXT: [[ITOFP:%.*]] = uitofp i8 [[X]] to float +; NOLDEXP-NEXT: [[EXP2:%.*]] = call float @llvm.exp2.f32(float [[ITOFP]]) +; NOLDEXP-NEXT: ret float [[EXP2]] +; + %itofp = uitofp i8 %x to float + %exp2 = call float @llvm.exp2.f32(float %itofp) + ret float %exp2 +} + +define half @exp2_f16_sitofp_i8(i8 %x) { +; CHECK-LABEL: define half @exp2_f16_sitofp_i8( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[ITOFP:%.*]] = sitofp i8 [[X]] to half +; CHECK-NEXT: [[EXP2:%.*]] = call half @llvm.exp2.f16(half [[ITOFP]]) +; CHECK-NEXT: ret half [[EXP2]] +; + %itofp = sitofp i8 %x to half + %exp2 = call half @llvm.exp2.f16(half %itofp) + ret half %exp2 +} + +define double @exp2_f64_sitofp_i8(i8 %x) { +; LDEXP-LABEL: define double @exp2_f64_sitofp_i8( +; LDEXP-SAME: i8 [[X:%.*]]) { +; LDEXP-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 +; LDEXP-NEXT: [[LDEXP:%.*]] = call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 [[TMP1]]) +; LDEXP-NEXT: ret double [[LDEXP]] +; +; NOLDEXP-LABEL: define double @exp2_f64_sitofp_i8( +; NOLDEXP-SAME: i8 [[X:%.*]]) { +; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp i8 [[X]] to double +; NOLDEXP-NEXT: [[EXP2:%.*]] = call double @llvm.exp2.f64(double [[ITOFP]]) +; NOLDEXP-NEXT: ret double [[EXP2]] +; + %itofp = sitofp i8 %x to double + %exp2 = call double @llvm.exp2.f64(double %itofp) + ret double %exp2 +} + +define fp128 @exp2_fp128_sitofp_i8(i8 %x) { +; LDEXP-LABEL: define fp128 @exp2_fp128_sitofp_i8( +; LDEXP-SAME: i8 [[X:%.*]]) { +; LDEXP-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 +; LDEXP-NEXT: [[LDEXPL:%.*]] = call fp128 @llvm.ldexp.f128.i32(fp128 0xL00000000000000003FFF000000000000, i32 [[TMP1]]) +; LDEXP-NEXT: ret fp128 [[LDEXPL]] +; +; NOLDEXP-LABEL: define fp128 @exp2_fp128_sitofp_i8( +; NOLDEXP-SAME: i8 [[X:%.*]]) { +; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp i8 [[X]] to fp128 +; NOLDEXP-NEXT: [[EXP2:%.*]] = call fp128 @llvm.exp2.f128(fp128 [[ITOFP]]) +; NOLDEXP-NEXT: ret fp128 [[EXP2]] +; + %itofp = sitofp i8 %x to fp128 + %exp2 = call fp128 @llvm.exp2.fp128(fp128 %itofp) + ret fp128 %exp2 +} + +define @exp2_nxv4f32_sitofp_i8( %x) { +; CHECK-LABEL: define @exp2_nxv4f32_sitofp_i8( +; CHECK-SAME: [[X:%.*]]) { +; CHECK-NEXT: [[ITOFP:%.*]] = sitofp [[X]] to +; CHECK-NEXT: [[EXP2:%.*]] = call @llvm.exp2.nxv4f32( [[ITOFP]]) +; CHECK-NEXT: ret [[EXP2]] +; + %itofp = sitofp %x to + %exp2 = call @llvm.exp2.nxv4f32( %itofp) + ret %exp2 +} + +; FIXME: This asserts +; define bfloat @exp2_bf16_sitofp_i8(i8 %x) { +; %itofp = sitofp i8 %x to bfloat +; %exp2 = call bfloat @llvm.exp2.bf16(bfloat %itofp) +; ret bfloat %exp2 +; } + +; FIXME: This asserts +; define ppc_fp128 @exp2_ppc_fp128_sitofp_i8(i8 %x) { +; %itofp = sitofp i8 %x to ppc_fp128 +; %exp2 = call ppc_fp128 @llvm.exp2.ppcf128(ppc_fp128 %itofp) +; ret ppc_fp128 %exp2 +; } + +; FIXME: This asserts +; define x86_fp80 @exp2_x86_fp80_sitofp_i8(i8 %x) { +; %itofp = sitofp i8 %x to x86_fp80 +; %exp2 = call x86_fp80 @llvm.exp2.f80(x86_fp80 %itofp) +; ret x86_fp80 %exp2 +; } -- GitLab From e6216906f528b948018b883068cef0fd4157bfd1 Mon Sep 17 00:00:00 2001 From: Christian Ulmann Date: Wed, 15 May 2024 08:31:09 +0200 Subject: [PATCH 310/578] [MLIR][LLVM] Improve atomic verifier to properly support larger types (#92120) This commit extends the verifier for atomics to properly verify larger types. Beforehand, the verifier strictly rejected larger integer types, while it now consults the data layout to determine if their bitsize is a power of two. This behavior reflects what LLVM's verifier is checking for. --- mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 37 ++++++++++------------ mlir/test/Dialect/LLVMIR/invalid.mlir | 14 ++++++++ mlir/test/Dialect/LLVMIR/roundtrip.mlir | 6 +++- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp index 7d33d05feb65..dcf3f3b52a60 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -839,25 +839,19 @@ void LoadOp::getEffects( } /// Returns true if the given type is supported by atomic operations. All -/// integer and float types with limited bit width are supported. Additionally, -/// depending on the operation pointers may be supported as well. -static bool isTypeCompatibleWithAtomicOp(Type type, bool isPointerTypeAllowed) { - if (llvm::isa(type)) - return isPointerTypeAllowed; - - std::optional bitWidth; - if (auto floatType = llvm::dyn_cast(type)) { +/// integer, float, and pointer types with a power-of-two bitsize and a minimal +/// size of 8 bits are supported. +static bool isTypeCompatibleWithAtomicOp(Type type, + const DataLayout &dataLayout) { + if (!isa(type)) if (!isCompatibleFloatingPointType(type)) return false; - bitWidth = floatType.getWidth(); - } - if (auto integerType = llvm::dyn_cast(type)) - bitWidth = integerType.getWidth(); - // The type is neither an integer, float, or pointer type. - if (!bitWidth) + + llvm::TypeSize bitWidth = dataLayout.getTypeSizeInBits(type); + if (bitWidth.isScalable()) return false; - return *bitWidth == 8 || *bitWidth == 16 || *bitWidth == 32 || - *bitWidth == 64; + // Needs to be at least 8 bits and a power of two. + return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0; } /// Verifies the attributes and the type of atomic memory access operations. @@ -865,8 +859,8 @@ template LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType, ArrayRef unsupportedOrderings) { if (memOp.getOrdering() != AtomicOrdering::not_atomic) { - if (!isTypeCompatibleWithAtomicOp(valueType, - /*isPointerTypeAllowed=*/true)) + DataLayout dataLayout = DataLayout::closest(memOp); + if (!isTypeCompatibleWithAtomicOp(valueType, dataLayout)) return memOp.emitOpError("unsupported type ") << valueType << " for atomic access"; if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering())) @@ -2694,7 +2688,8 @@ LogicalResult AtomicRMWOp::verify() { if (!mlir::LLVM::isCompatibleFloatingPointType(valType)) return emitOpError("expected LLVM IR floating point type"); } else if (getBinOp() == AtomicBinOp::xchg) { - if (!isTypeCompatibleWithAtomicOp(valType, /*isPointerTypeAllowed=*/true)) + DataLayout dataLayout = DataLayout::closest(*this); + if (!isTypeCompatibleWithAtomicOp(valType, dataLayout)) return emitOpError("unexpected LLVM IR type for 'xchg' bin_op"); } else { auto intType = llvm::dyn_cast(valType); @@ -2741,8 +2736,8 @@ LogicalResult AtomicCmpXchgOp::verify() { if (!ptrType) return emitOpError("expected LLVM IR pointer type for operand #0"); auto valType = getVal().getType(); - if (!isTypeCompatibleWithAtomicOp(valType, - /*isPointerTypeAllowed=*/true)) + DataLayout dataLayout = DataLayout::closest(*this); + if (!isTypeCompatibleWithAtomicOp(valType, dataLayout)) return emitOpError("unexpected LLVM IR type"); if (getSuccessOrdering() < AtomicOrdering::monotonic || getFailureOrdering() < AtomicOrdering::monotonic) diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir index 0914f0023210..a1d340910948 100644 --- a/mlir/test/Dialect/LLVMIR/invalid.mlir +++ b/mlir/test/Dialect/LLVMIR/invalid.mlir @@ -160,6 +160,13 @@ func.func @load_unsupported_type(%ptr : !llvm.ptr) { // ----- +func.func @load_unsupported_type(%ptr : !llvm.ptr) { + // expected-error@below {{unsupported type 'i33' for atomic access}} + %1 = llvm.load %ptr atomic monotonic {alignment = 16 : i64} : !llvm.ptr -> i33 +} + +// ----- + func.func @load_unaligned_atomic(%ptr : !llvm.ptr) { // expected-error@below {{expected alignment for atomic access}} %1 = llvm.load %ptr atomic monotonic : !llvm.ptr -> f32 @@ -195,6 +202,13 @@ func.func @store_unsupported_type(%val : i1, %ptr : !llvm.ptr) { // ----- +func.func @store_unsupported_type(%val : i48, %ptr : !llvm.ptr) { + // expected-error@below {{unsupported type 'i48' for atomic access}} + llvm.store %val, %ptr atomic monotonic {alignment = 16 : i64} : i48, !llvm.ptr +} + +// ----- + func.func @store_unaligned_atomic(%val : f32, %ptr : !llvm.ptr) { // expected-error@below {{expected alignment for atomic access}} llvm.store %val, %ptr atomic monotonic : f32, !llvm.ptr diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir index 410122df1c14..2386dde19301 100644 --- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir @@ -385,15 +385,19 @@ func.func @atomic_load(%ptr : !llvm.ptr) { %0 = llvm.load %ptr atomic monotonic {alignment = 4 : i64} : !llvm.ptr -> f32 // CHECK: llvm.load volatile %{{.*}} atomic syncscope("singlethread") monotonic {alignment = 16 : i64} : !llvm.ptr -> f32 %1 = llvm.load volatile %ptr atomic syncscope("singlethread") monotonic {alignment = 16 : i64} : !llvm.ptr -> f32 + // CHECK: llvm.load %{{.*}} atomic monotonic {alignment = 4 : i64} : !llvm.ptr -> i128 + %2 = llvm.load %ptr atomic monotonic {alignment = 4 : i64} : !llvm.ptr -> i128 llvm.return } // CHECK-LABEL: @atomic_store -func.func @atomic_store(%val : f32, %ptr : !llvm.ptr) { +func.func @atomic_store(%val : f32, %large_val : i256, %ptr : !llvm.ptr) { // CHECK: llvm.store %{{.*}}, %{{.*}} atomic monotonic {alignment = 4 : i64} : f32, !llvm.ptr llvm.store %val, %ptr atomic monotonic {alignment = 4 : i64} : f32, !llvm.ptr // CHECK: llvm.store volatile %{{.*}}, %{{.*}} atomic syncscope("singlethread") monotonic {alignment = 16 : i64} : f32, !llvm.ptr llvm.store volatile %val, %ptr atomic syncscope("singlethread") monotonic {alignment = 16 : i64} : f32, !llvm.ptr + // CHECK: llvm.store %{{.*}}, %{{.*}} atomic monotonic {alignment = 4 : i64} : i256, !llvm.ptr + llvm.store %large_val, %ptr atomic monotonic {alignment = 4 : i64} : i256, !llvm.ptr llvm.return } -- GitLab From d6ee7e8481fbaee30f37d82778ef12e135db5e67 Mon Sep 17 00:00:00 2001 From: Jonas Paulsson Date: Wed, 15 May 2024 08:36:26 +0200 Subject: [PATCH 311/578] [SystemZ] Handle address clobbering in splitMove(). (#92105) When expanding an L128 (which is used to reload i128) it is possible that the quadword destination register clobbers an address register. This patch adds an assertion against the case where both of the expanded parts clobber the address, and in the case where one of the expanded parts do so puts it last. Fixes #91437 --- llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp | 65 +++++++++++-------- .../CodeGen/SystemZ/splitMove_addressReg.mir | 26 ++++++++ 2 files changed, 65 insertions(+), 26 deletions(-) create mode 100644 llvm/test/CodeGen/SystemZ/splitMove_addressReg.mir diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index 0a29b4f79c7d..16bbfd44ef8a 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -70,49 +70,62 @@ void SystemZInstrInfo::splitMove(MachineBasicBlock::iterator MI, MachineBasicBlock *MBB = MI->getParent(); MachineFunction &MF = *MBB->getParent(); - // Get two load or store instructions. Use the original instruction for one - // of them (arbitrarily the second here) and create a clone for the other. - MachineInstr *EarlierMI = MF.CloneMachineInstr(&*MI); - MBB->insert(MI, EarlierMI); + // Get two load or store instructions. Use the original instruction for + // one of them and create a clone for the other. + MachineInstr *HighPartMI = MF.CloneMachineInstr(&*MI); + MachineInstr *LowPartMI = &*MI; + MBB->insert(LowPartMI, HighPartMI); // Set up the two 64-bit registers and remember super reg and its flags. - MachineOperand &HighRegOp = EarlierMI->getOperand(0); - MachineOperand &LowRegOp = MI->getOperand(0); + MachineOperand &HighRegOp = HighPartMI->getOperand(0); + MachineOperand &LowRegOp = LowPartMI->getOperand(0); Register Reg128 = LowRegOp.getReg(); unsigned Reg128Killed = getKillRegState(LowRegOp.isKill()); unsigned Reg128Undef = getUndefRegState(LowRegOp.isUndef()); HighRegOp.setReg(RI.getSubReg(HighRegOp.getReg(), SystemZ::subreg_h64)); LowRegOp.setReg(RI.getSubReg(LowRegOp.getReg(), SystemZ::subreg_l64)); - if (MI->mayStore()) { - // Add implicit uses of the super register in case one of the subregs is - // undefined. We could track liveness and skip storing an undefined - // subreg, but this is hopefully rare (discovered with llvm-stress). - // If Reg128 was killed, set kill flag on MI. - unsigned Reg128UndefImpl = (Reg128Undef | RegState::Implicit); - MachineInstrBuilder(MF, EarlierMI).addReg(Reg128, Reg128UndefImpl); - MachineInstrBuilder(MF, MI).addReg(Reg128, (Reg128UndefImpl | Reg128Killed)); - } - // The address in the first (high) instruction is already correct. // Adjust the offset in the second (low) instruction. - MachineOperand &HighOffsetOp = EarlierMI->getOperand(2); - MachineOperand &LowOffsetOp = MI->getOperand(2); + MachineOperand &HighOffsetOp = HighPartMI->getOperand(2); + MachineOperand &LowOffsetOp = LowPartMI->getOperand(2); LowOffsetOp.setImm(LowOffsetOp.getImm() + 8); - // Clear the kill flags on the registers in the first instruction. - if (EarlierMI->getOperand(0).isReg() && EarlierMI->getOperand(0).isUse()) - EarlierMI->getOperand(0).setIsKill(false); - EarlierMI->getOperand(1).setIsKill(false); - EarlierMI->getOperand(3).setIsKill(false); - // Set the opcodes. unsigned HighOpcode = getOpcodeForOffset(NewOpcode, HighOffsetOp.getImm()); unsigned LowOpcode = getOpcodeForOffset(NewOpcode, LowOffsetOp.getImm()); assert(HighOpcode && LowOpcode && "Both offsets should be in range"); + HighPartMI->setDesc(get(HighOpcode)); + LowPartMI->setDesc(get(LowOpcode)); + + MachineInstr *FirstMI = HighPartMI; + if (MI->mayStore()) { + FirstMI->getOperand(0).setIsKill(false); + // Add implicit uses of the super register in case one of the subregs is + // undefined. We could track liveness and skip storing an undefined + // subreg, but this is hopefully rare (discovered with llvm-stress). + // If Reg128 was killed, set kill flag on MI. + unsigned Reg128UndefImpl = (Reg128Undef | RegState::Implicit); + MachineInstrBuilder(MF, HighPartMI).addReg(Reg128, Reg128UndefImpl); + MachineInstrBuilder(MF, LowPartMI).addReg(Reg128, (Reg128UndefImpl | Reg128Killed)); + } else { + // If HighPartMI clobbers any of the address registers, it needs to come + // after LowPartMI. + auto overlapsAddressReg = [&](Register Reg) -> bool { + return RI.regsOverlap(Reg, MI->getOperand(1).getReg()) || + RI.regsOverlap(Reg, MI->getOperand(3).getReg()); + }; + if (overlapsAddressReg(HighRegOp.getReg())) { + assert(!overlapsAddressReg(LowRegOp.getReg()) && + "Both loads clobber address!"); + MBB->splice(HighPartMI, MBB, LowPartMI); + FirstMI = LowPartMI; + } + } - EarlierMI->setDesc(get(HighOpcode)); - MI->setDesc(get(LowOpcode)); + // Clear the kill flags on the address registers in the first instruction. + FirstMI->getOperand(1).setIsKill(false); + FirstMI->getOperand(3).setIsKill(false); } // Split ADJDYNALLOC instruction MI. diff --git a/llvm/test/CodeGen/SystemZ/splitMove_addressReg.mir b/llvm/test/CodeGen/SystemZ/splitMove_addressReg.mir new file mode 100644 index 000000000000..64ed2d8f2c00 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/splitMove_addressReg.mir @@ -0,0 +1,26 @@ +# RUN: llc -mtriple=s390x-linux-gnu -run-pass=postrapseudos \ +# RUN: %s -o - -verify-machineinstrs | FileCheck %s +# +# Test that a L128 reload do not overwrite an address register prematurely +# after being split into two LGs. + +--- | + target triple = "s390x-unknown-unknown" + + define void @fun() { + ret void + } + +... + +# CHECK: name: fun + +--- +name: 'fun' +body: | + bb.0: + liveins: $r4d, $r15d + $r4q = L128 $r15d, 14920, killed $r4d + Return + +... -- GitLab From 45726c1a3a3d89ff9f6ebe657c3cb7bcd59b88db Mon Sep 17 00:00:00 2001 From: Daniel Kiss Date: Wed, 15 May 2024 08:40:16 +0200 Subject: [PATCH 312/578] [LLVM] Make sanitizers respect the disable_santizer_instrumentation attribute. (#91732) `disable_sanitizer_instrumetation` is attached to functions that shall not be instrumented e.g. ifunc resolver because those run before everything is initialised. Some sanitizer already handles this attribute, this patch adds it to DataFLow and Coverage too. --- .../Instrumentation/DataFlowSanitizer.cpp | 3 +- .../Instrumentation/SanitizerCoverage.cpp | 2 + ...aflow-disable-sanitizer-instrumentation.ll | 47 +++++++++++++++++++ ...erage-disable-sanitizer-instrumentation.ll | 46 ++++++++++++++++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Instrumentation/DataFlowSanitizer/dataflow-disable-sanitizer-instrumentation.ll create mode 100644 llvm/test/Instrumentation/SanitizerCoverage/coverage-disable-sanitizer-instrumentation.ll diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index 851edb4ce829..20d11e0ab55f 100644 --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -1546,7 +1546,8 @@ bool DataFlowSanitizer::runImpl( SmallPtrSet PersonalityFns; for (Function &F : M) if (!F.isIntrinsic() && !DFSanRuntimeFunctions.contains(&F) && - !LibAtomicFunction(F)) { + !LibAtomicFunction(F) && + !F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) { FnsToInstrument.push_back(&F); if (F.hasPersonalityFn()) PersonalityFns.insert(F.getPersonalityFn()->stripPointerCasts()); diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 56d4907ae47a..6a89cee9aaf6 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -631,6 +631,8 @@ void ModuleSanitizerCoverage::instrumentFunction(Function &F) { return; if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return; + if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) + return; if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) { SplitAllCriticalEdges( F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/dataflow-disable-sanitizer-instrumentation.ll b/llvm/test/Instrumentation/DataFlowSanitizer/dataflow-disable-sanitizer-instrumentation.ll new file mode 100644 index 000000000000..3fb922736d02 --- /dev/null +++ b/llvm/test/Instrumentation/DataFlowSanitizer/dataflow-disable-sanitizer-instrumentation.ll @@ -0,0 +1,47 @@ + +; This test checks that we are not instrumenting sanitizer code. +; RUN: opt < %s -passes='module(msan)' -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function with sanitize_memory is instrumented. +; Function Attrs: nounwind uwtable +define void @instr_sa(ptr %a) sanitize_memory { +entry: + %tmp1 = load i32, ptr %a, align 4 + %tmp2 = add i32 %tmp1, 1 + store i32 %tmp2, ptr %a, align 4 + ret void +} + +; CHECK-LABEL: @instr_sa +; CHECK: %0 = load i64, ptr @__msan_param_tls + + +; Function with disable_sanitizer_instrumentation is not instrumented. +; Function Attrs: nounwind uwtable +define void @noinstr_dsi(ptr %a) disable_sanitizer_instrumentation { +entry: + %tmp1 = load i32, ptr %a, align 4 + %tmp2 = add i32 %tmp1, 1 + store i32 %tmp2, ptr %a, align 4 + ret void +} + +; CHECK-LABEL: @noinstr_dsi +; CHECK-NOT: %0 = load i64, ptr @__msan_param_tls + + +; disable_sanitizer_instrumentation takes precedence over sanitize_memory. +; Function Attrs: nounwind uwtable +define void @noinstr_dsi_sa(ptr %a) disable_sanitizer_instrumentation sanitize_memory { +entry: + %tmp1 = load i32, ptr %a, align 4 + %tmp2 = add i32 %tmp1, 1 + store i32 %tmp2, ptr %a, align 4 + ret void +} + +; CHECK-LABEL: @noinstr_dsi_sa +; CHECK-NOT: %0 = load i64, ptr @__msan_param_tls diff --git a/llvm/test/Instrumentation/SanitizerCoverage/coverage-disable-sanitizer-instrumentation.ll b/llvm/test/Instrumentation/SanitizerCoverage/coverage-disable-sanitizer-instrumentation.ll new file mode 100644 index 000000000000..dc3d48622015 --- /dev/null +++ b/llvm/test/Instrumentation/SanitizerCoverage/coverage-disable-sanitizer-instrumentation.ll @@ -0,0 +1,46 @@ +; This test checks that we are not instrumenting sanitizer code. +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function with sanitize_address is instrumented. +; Function Attrs: nounwind uwtable +define void @instr_sa(ptr %a) sanitize_address { +entry: + %tmp1 = load i32, ptr %a, align 4 + %tmp2 = add i32 %tmp1, 1 + store i32 %tmp2, ptr %a, align 4 + ret void +} + +; CHECK-LABEL: @instr_sa +; CHECK: call void @__sanitizer_cov_trace_pc_guard( + + +; Function with disable_sanitizer_instrumentation is not instrumented. +; Function Attrs: nounwind uwtable +define void @noinstr_dsi(ptr %a) disable_sanitizer_instrumentation { +entry: + %tmp1 = load i32, ptr %a, align 4 + %tmp2 = add i32 %tmp1, 1 + store i32 %tmp2, ptr %a, align 4 + ret void +} + +; CHECK-LABEL: @noinstr_dsi +; CHECK-NOT: call void @__sanitizer_cov_trace_pc_guard( + + +; disable_sanitizer_instrumentation takes precedence over sanitize_address. +; Function Attrs: nounwind uwtable +define void @noinstr_dsi_sa(ptr %a) disable_sanitizer_instrumentation sanitize_address { +entry: + %tmp1 = load i32, ptr %a, align 4 + %tmp2 = add i32 %tmp1, 1 + store i32 %tmp2, ptr %a, align 4 + ret void +} + +; CHECK-LABEL: @noinstr_dsi_sa +; CHECK-NOT: call void @__sanitizer_cov_trace_pc_guard( -- GitLab From 4688df68f9d022dd8bc102675a9e86ad274355d6 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Wed, 15 May 2024 08:58:14 +0200 Subject: [PATCH 313/578] Avoid partial munmap (#92109) ...which caused issues like > ==42==ERROR: AddressSanitizer failed to deallocate 0x32 (50) bytes at address 0x117e0000 (error code: 28) > ==42==Cannot dump memory map on emscriptenAddressSanitizer: CHECK failed: sanitizer_common.cpp:81 "((0 && "unable to unmmap")) != (0)" (0x0, 0x0) (tid=288045824) > #0 0x14f73b0c in __asan::CheckUnwind()+0x14f73b0c (this.program+0x14f73b0c) > #1 0x14f8a3c2 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long)+0x14f8a3c2 (this.program+0x14f8a3c2) > #2 0x14f7d6e1 in __sanitizer::ReportMunmapFailureAndDie(void*, unsigned long, int, bool)+0x14f7d6e1 (this.program+0x14f7d6e1) > #3 0x14f81fbd in __sanitizer::UnmapOrDie(void*, unsigned long)+0x14f81fbd (this.program+0x14f81fbd) > #4 0x14f875df in __sanitizer::SuppressionContext::ParseFromFile(char const*)+0x14f875df (this.program+0x14f875df) > #5 0x14f74eab in __asan::InitializeSuppressions()+0x14f74eab (this.program+0x14f74eab) > #6 0x14f73a1a in __asan::AsanInitInternal()+0x14f73a1a (this.program+0x14f73a1a) when trying to use an ASan suppressions file under Emscripten: Even though it would be considered OK by SUSv4, the Emscripten runtime states "We don't support partial munmapping" (see "Implement MAP_ANONYMOUS on top of malloc in STANDALONE_WASM mode (#16289)"). Co-authored-by: Stephan Bergmann --- compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cpp index 9c8c4bf9d1a4..62ebbb38feae 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cpp @@ -86,7 +86,7 @@ void SuppressionContext::ParseFromFile(const char *filename) { } Parse(file_contents); - UnmapOrDie(file_contents, contents_size); + UnmapOrDie(file_contents, buffer_size); } bool SuppressionContext::Match(const char *str, const char *type, -- GitLab From 73324cbc9c5892541aa82d466799748b435ece29 Mon Sep 17 00:00:00 2001 From: Enna1 Date: Wed, 15 May 2024 15:04:34 +0800 Subject: [PATCH 314/578] [ASan] Remove COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION. (#91832) Since the set of COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION is removed in commit 8421fa5d536aadf42c0e54c566bc439a40ebdb8e, cleanup the use of COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION. --- compiler-rt/lib/asan/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt index 601750f72175..463ea233b37a 100644 --- a/compiler-rt/lib/asan/CMakeLists.txt +++ b/compiler-rt/lib/asan/CMakeLists.txt @@ -88,7 +88,7 @@ set(ASAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) append_list_if(MSVC /Zl ASAN_CFLAGS) -set(ASAN_COMMON_DEFINITIONS ${COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION}) +set(ASAN_COMMON_DEFINITIONS "") append_rtti_flag(OFF ASAN_CFLAGS) -- GitLab From 7f3ac51b946bf6d6fa8c8443457ebee219879302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 14 May 2024 16:41:28 +0200 Subject: [PATCH 315/578] [clang][Interp] Only accept constant variables in c++98 --- clang/lib/AST/Interp/Interp.cpp | 14 +++++++------- clang/test/AST/Interp/cxx98.cpp | 5 +++++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 2607e0743251..3e4da487e43c 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -302,7 +302,9 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { QualType T = VD->getType(); if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11) - return T->isSignedIntegerOrEnumerationType() || T->isUnsignedIntegerOrEnumerationType(); + return (T->isSignedIntegerOrEnumerationType() || + T->isUnsignedIntegerOrEnumerationType()) && + T.isConstQualified(); if (T.isConstQualified()) return true; @@ -316,12 +318,10 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { return false; }; - if (const auto *D = Desc->asValueDecl()) { - if (const auto *VD = dyn_cast(D); - VD && VD->hasGlobalStorage() && !IsConstType(VD)) { - diagnoseNonConstVariable(S, OpPC, VD); - return S.inConstantContext(); - } + if (const auto *D = Desc->asVarDecl(); + D && D->hasGlobalStorage() && !IsConstType(D)) { + diagnoseNonConstVariable(S, OpPC, D); + return S.inConstantContext(); } return true; diff --git a/clang/test/AST/Interp/cxx98.cpp b/clang/test/AST/Interp/cxx98.cpp index ba6bcd97d920..be81735329db 100644 --- a/clang/test/AST/Interp/cxx98.cpp +++ b/clang/test/AST/Interp/cxx98.cpp @@ -45,3 +45,8 @@ struct C0 { }; const int c0_test = C0::Data; _Static_assert(c0_test == 0, ""); + + +int a = 0; // both-note {{declared here}} +_Static_assert(a == 0, ""); // both-error {{static assertion expression is not an integral constant expression}} \ + // both-note {{read of non-const variable 'a' is not allowed in a constant expression}} -- GitLab From d12c48cad52798f4846dd8ef882af0f854118d16 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Wed, 15 May 2024 10:02:24 +0200 Subject: [PATCH 316/578] [lldb/aarch64] Allow unaligned PC addresses below a trap handler (#92093) The stack validation heuristic is counter-productive in this case, as the unaligned address is most likely the thing that caused the signal in the first place. --- lldb/source/Target/UnwindLLDB.cpp | 7 ++++- .../Shell/Unwind/Inputs/unaligned-pc-sigbus.c | 21 +++++++++++++ .../Shell/Unwind/unaligned-pc-sigbus.test | 31 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 lldb/test/Shell/Unwind/Inputs/unaligned-pc-sigbus.c create mode 100644 lldb/test/Shell/Unwind/unaligned-pc-sigbus.test diff --git a/lldb/source/Target/UnwindLLDB.cpp b/lldb/source/Target/UnwindLLDB.cpp index 1d8bf2f88ae6..f43e940492b0 100644 --- a/lldb/source/Target/UnwindLLDB.cpp +++ b/lldb/source/Target/UnwindLLDB.cpp @@ -261,7 +261,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } - if (abi && !abi->CodeAddressIsValid(cursor_sp->start_pc)) { + + // Invalid code addresses should not appear on the stack *unless* we're + // directly below a trap handler frame (in this case, the invalid address is + // likely the cause of the trap). + if (abi && !abi->CodeAddressIsValid(cursor_sp->start_pc) && + !prev_frame->reg_ctx_lldb_sp->IsTrapHandlerFrame()) { // If the RegisterContextUnwind has a fallback UnwindPlan, it will switch to // that and return true. Subsequent calls to TryFallbackUnwindPlan() will // return false. diff --git a/lldb/test/Shell/Unwind/Inputs/unaligned-pc-sigbus.c b/lldb/test/Shell/Unwind/Inputs/unaligned-pc-sigbus.c new file mode 100644 index 000000000000..b4818de3b7fb --- /dev/null +++ b/lldb/test/Shell/Unwind/Inputs/unaligned-pc-sigbus.c @@ -0,0 +1,21 @@ +#include +#include +#include + +void sigbus_handler(int signo) { _exit(47); } + +int target_function() { return 47; } + +int main() { + signal(SIGBUS, sigbus_handler); + + // Generate a SIGBUS by deliverately calling through an unaligned function + // pointer. + union { + int (*t)(); + uintptr_t p; + } u; + u.t = target_function; + u.p |= 1; + return u.t(); +} diff --git a/lldb/test/Shell/Unwind/unaligned-pc-sigbus.test b/lldb/test/Shell/Unwind/unaligned-pc-sigbus.test new file mode 100644 index 000000000000..5ebfba54301e --- /dev/null +++ b/lldb/test/Shell/Unwind/unaligned-pc-sigbus.test @@ -0,0 +1,31 @@ +# REQUIRES: (target-aarch64 || target-arm) && native +# UNSUPPORTED: system-windows +# llvm.org/pr91610, rdar://128031075 +# XFAIL: system-darwin + +# RUN: %clang_host %S/Inputs/unaligned-pc-sigbus.c -o %t +# RUN: %lldb -s %s -o exit %t | FileCheck %s + +# Convert EXC_BAD_ACCESS into SIGBUS on darwin. +settings set platform.plugin.darwin.ignored-exceptions EXC_BAD_ACCESS + +breakpoint set -n sigbus_handler +# CHECK: Breakpoint 1: where = {{.*}}`sigbus_handler + +run +# CHECK: thread #1, {{.*}} stop reason = signal SIGBUS + +thread backtrace +# CHECK: (lldb) thread backtrace +# CHECK: frame #0: [[TARGET:0x[0-9a-fA-F]*]] {{.*}}`target_function + +continue +# CHECK: thread #1, {{.*}} stop reason = breakpoint 1 + + +thread backtrace +# CHECK: (lldb) thread backtrace +# CHECK: frame #0: {{.*}}`sigbus_handler +# Unknown number of signal trampoline frames +# CHECK: frame #{{[0-9]+}}: [[TARGET]] {{.*}}`target_function + -- GitLab From 6479e3cb66895754089dc017a33478e9eb4b8d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 15 May 2024 08:05:24 +0200 Subject: [PATCH 317/578] [clang][Interp] Use proper type for non-primitive reference dummies --- clang/lib/AST/Interp/Program.cpp | 3 +-- clang/test/AST/Interp/bitfields.cpp | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index 31a64e13d2b1..e3d48d5a8ddb 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -152,8 +152,7 @@ std::optional Program::getOrCreateDummy(const ValueDecl *VD) { if (std::optional T = Ctx.classify(QT)) Desc = createDescriptor(VD, *T, std::nullopt, true, false); else - Desc = createDescriptor(VD, VD->getType().getTypePtr(), std::nullopt, true, - false); + Desc = createDescriptor(VD, QT.getTypePtr(), std::nullopt, true, false); if (!Desc) Desc = allocateDescriptor(VD); diff --git a/clang/test/AST/Interp/bitfields.cpp b/clang/test/AST/Interp/bitfields.cpp index d3a8a083063a..5fc34bb1229d 100644 --- a/clang/test/AST/Interp/bitfields.cpp +++ b/clang/test/AST/Interp/bitfields.cpp @@ -102,3 +102,24 @@ namespace Compound { } static_assert(div() == 1, ""); } + +namespace test0 { + extern int int_source(); + struct A { + int aField; + int bField; + }; + + struct B { + int onebit : 2; + int twobit : 6; + int intField; + }; + + struct C : A, B { + }; + + void b(C &c) { + c.onebit = int_source(); + } +} -- GitLab From 1d43ec8191e55d6efd552a1510ce63dbdea00cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 15 May 2024 08:21:17 +0200 Subject: [PATCH 318/578] [clang][Interp][NFC] Remove unnecessary if condition This is already in a if(isBlockPointer()) block. --- clang/lib/AST/Interp/Pointer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index d2e34f2c7f09..ee8cedccb8d4 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -191,7 +191,7 @@ void Pointer::print(llvm::raw_ostream &OS) const { else OS << Offset << ", "; - if (isBlockPointer() && PointeeStorage.BS.Pointee) + if (PointeeStorage.BS.Pointee) OS << PointeeStorage.BS.Pointee->getSize(); else OS << "nullptr"; -- GitLab From afba3daf822c839db1be40464041307679c803a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 15 May 2024 10:16:23 +0200 Subject: [PATCH 319/578] [clang][Interp] Add basic support for AddrLabelExprs Just create a local variable for them. --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 10 ++++++++++ clang/lib/AST/Interp/ByteCodeExprGen.h | 1 + clang/test/AST/Interp/c.c | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 7b10482dff23..1da74ac7c8bd 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2488,6 +2488,16 @@ bool ByteCodeExprGen::VisitRecoveryExpr(const RecoveryExpr *E) { return this->emitError(E); } +template +bool ByteCodeExprGen::VisitAddrLabelExpr(const AddrLabelExpr *E) { + assert(E->getType()->isVoidPointerType()); + + unsigned Offset = allocateLocalPrimitive( + E->getLabel(), PT_Ptr, /*IsConst=*/true, /*IsExtended=*/false); + + return this->emitGetLocal(PT_Ptr, Offset, E); +} + template bool ByteCodeExprGen::discard(const Expr *E) { OptionScope Scope(this, /*NewDiscardResult=*/true, /*NewInitializing=*/false); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 9f83d173bbae..6039a54d32a5 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -122,6 +122,7 @@ public: bool VisitPseudoObjectExpr(const PseudoObjectExpr *E); bool VisitPackIndexingExpr(const PackIndexingExpr *E); bool VisitRecoveryExpr(const RecoveryExpr *E); + bool VisitAddrLabelExpr(const AddrLabelExpr *E); protected: bool visitExpr(const Expr *E) override; diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index 2c675f4418ef..2a75457a4693 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -273,3 +273,8 @@ int test3(void) { /// This tests that we have full type info, even for values we cannot read. int dummyarray[5]; _Static_assert(&dummyarray[0] < &dummyarray[1], ""); // pedantic-warning {{GNU extension}} + +void addrlabelexpr(void) { + a0: ; + static void *ps[] = { &&a0 }; // pedantic-warning {{use of GNU address-of-label extension}} +} -- GitLab From ca4a405232cf170f20a2f111bf72beab82095935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= Date: Wed, 15 May 2024 10:53:54 +0200 Subject: [PATCH 320/578] [analyzer] Refactor recognition of the errno getter functions (#91531) There are many environments where `errno` is a macro that expands to something like `(*__errno())` (different standard library implementations use different names instead of "__errno"). In these environments the ErrnoModeling checker creates a symbolic region which will be used to represent the return value of this "get the location of errno" function. Previously this symbol was only created when the checker was able to find the declaration of the "get the location of errno" function; but this commit eliminates the complex logic that was responsible for this and always creates the symbolic region when `errno` is not available as a "regular" global variable. This significantly simplifies a code and only introduces a minimal performance reduction (one extra symbol) in the case when `errno` is not declared (neither as a variable nor as a function). In addition to this simplification, this commit specifies that the `CallDescription`s for the "get the location of errno" functions are matched in `CDM::CLibrary` mode. (This was my original goal, but I was sidetracked by resolving a FIXME above the `CallDescriptionSet` in `ErrnoModeling.cpp`.) This change is very close to being NFC, but it fixes weird corner cases like the handling of a C++ method that happens to be named "__errno()" (previously it could've been recognized as an errno location getter function). --- .../StaticAnalyzer/Checkers/ErrnoChecker.cpp | 2 +- .../StaticAnalyzer/Checkers/ErrnoModeling.cpp | 131 ++++++------------ .../StaticAnalyzer/Checkers/ErrnoModeling.h | 9 +- clang/test/Analysis/memory-model.cpp | 18 +-- 4 files changed, 56 insertions(+), 104 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp index 18e718e08553..72fd6781a756 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp @@ -205,7 +205,7 @@ void ErrnoChecker::checkPreCall(const CallEvent &Call, // Probably 'strerror'? if (CallF->isExternC() && CallF->isGlobal() && C.getSourceManager().isInSystemHeader(CallF->getLocation()) && - !isErrno(CallF)) { + !isErrnoLocationCall(Call)) { if (getErrnoState(C.getState()) == MustBeChecked) { std::optional ErrnoLoc = getErrnoLoc(C.getState()); assert(ErrnoLoc && "ErrnoLoc should exist if an errno state is set."); diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp index 1b34ea0e056e..6ffc05f06742 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp @@ -39,10 +39,15 @@ namespace { // Name of the "errno" variable. // FIXME: Is there a system where it is not called "errno" but is a variable? const char *ErrnoVarName = "errno"; + // Names of functions that return a location of the "errno" value. // FIXME: Are there other similar function names? -const char *ErrnoLocationFuncNames[] = {"__errno_location", "___errno", - "__errno", "_errno", "__error"}; +CallDescriptionSet ErrnoLocationCalls{ + {CDM::CLibrary, {"__errno_location"}, 0, 0}, + {CDM::CLibrary, {"___errno"}, 0, 0}, + {CDM::CLibrary, {"__errno"}, 0, 0}, + {CDM::CLibrary, {"_errno"}, 0, 0}, + {CDM::CLibrary, {"__error"}, 0, 0}}; class ErrnoModeling : public Checker, check::BeginFunction, @@ -54,16 +59,10 @@ public: void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const; bool evalCall(const CallEvent &Call, CheckerContext &C) const; - // The declaration of an "errno" variable or "errno location" function. - mutable const Decl *ErrnoDecl = nullptr; - private: - // FIXME: Names from `ErrnoLocationFuncNames` are used to build this set. - CallDescriptionSet ErrnoLocationCalls{{{"__errno_location"}, 0, 0}, - {{"___errno"}, 0, 0}, - {{"__errno"}, 0, 0}, - {{"_errno"}, 0, 0}, - {{"__error"}, 0, 0}}; + // The declaration of an "errno" variable on systems where errno is + // represented by a variable (and not a function that queries its location). + mutable const VarDecl *ErrnoDecl = nullptr; }; } // namespace @@ -74,9 +73,13 @@ REGISTER_TRAIT_WITH_PROGRAMSTATE(ErrnoRegion, const MemRegion *) REGISTER_TRAIT_WITH_PROGRAMSTATE(ErrnoState, errno_modeling::ErrnoCheckState) -/// Search for a variable called "errno" in the AST. -/// Return nullptr if not found. -static const VarDecl *getErrnoVar(ASTContext &ACtx) { +void ErrnoModeling::checkASTDecl(const TranslationUnitDecl *D, + AnalysisManager &Mgr, BugReporter &BR) const { + // Try to find the declaration of the external variable `int errno;`. + // There are also C library implementations, where the `errno` location is + // accessed via a function that returns its address; in those environments + // this callback has no effect. + ASTContext &ACtx = Mgr.getASTContext(); IdentifierInfo &II = ACtx.Idents.get(ErrnoVarName); auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II); auto Found = llvm::find_if(LookupRes, [&ACtx](const Decl *D) { @@ -86,47 +89,8 @@ static const VarDecl *getErrnoVar(ASTContext &ACtx) { VD->getType().getCanonicalType() == ACtx.IntTy; return false; }); - if (Found == LookupRes.end()) - return nullptr; - - return cast(*Found); -} - -/// Search for a function with a specific name that is used to return a pointer -/// to "errno". -/// Return nullptr if no such function was found. -static const FunctionDecl *getErrnoFunc(ASTContext &ACtx) { - SmallVector LookupRes; - for (StringRef ErrnoName : ErrnoLocationFuncNames) { - IdentifierInfo &II = ACtx.Idents.get(ErrnoName); - llvm::append_range(LookupRes, ACtx.getTranslationUnitDecl()->lookup(&II)); - } - - auto Found = llvm::find_if(LookupRes, [&ACtx](const Decl *D) { - if (auto *FD = dyn_cast(D)) - return ACtx.getSourceManager().isInSystemHeader(FD->getLocation()) && - FD->isExternC() && FD->getNumParams() == 0 && - FD->getReturnType().getCanonicalType() == - ACtx.getPointerType(ACtx.IntTy); - return false; - }); - if (Found == LookupRes.end()) - return nullptr; - - return cast(*Found); -} - -void ErrnoModeling::checkASTDecl(const TranslationUnitDecl *D, - AnalysisManager &Mgr, BugReporter &BR) const { - // Try to find an usable `errno` value. - // It can be an external variable called "errno" or a function that returns a - // pointer to the "errno" value. This function can have different names. - // The actual case is dependent on the C library implementation, we - // can only search for a match in one of these variations. - // We assume that exactly one of these cases might be true. - ErrnoDecl = getErrnoVar(Mgr.getASTContext()); - if (!ErrnoDecl) - ErrnoDecl = getErrnoFunc(Mgr.getASTContext()); + if (Found != LookupRes.end()) + ErrnoDecl = cast(*Found); } void ErrnoModeling::checkBeginFunction(CheckerContext &C) const { @@ -136,25 +100,18 @@ void ErrnoModeling::checkBeginFunction(CheckerContext &C) const { ASTContext &ACtx = C.getASTContext(); ProgramStateRef State = C.getState(); - if (const auto *ErrnoVar = dyn_cast_or_null(ErrnoDecl)) { - // There is an external 'errno' variable. - // Use its memory region. - // The memory region for an 'errno'-like variable is allocated in system - // space by MemRegionManager. - const MemRegion *ErrnoR = - State->getRegion(ErrnoVar, C.getLocationContext()); + const MemRegion *ErrnoR = nullptr; + + if (ErrnoDecl) { + // There is an external 'errno' variable, so we can simply use the memory + // region that's associated with it. + ErrnoR = State->getRegion(ErrnoDecl, C.getLocationContext()); assert(ErrnoR && "Memory region should exist for the 'errno' variable."); - State = State->set(ErrnoR); - State = - errno_modeling::setErrnoValue(State, C, 0, errno_modeling::Irrelevant); - C.addTransition(State); - } else if (ErrnoDecl) { - assert(isa(ErrnoDecl) && "Invalid errno location function."); - // There is a function that returns the location of 'errno'. - // We must create a memory region for it in system space. - // Currently a symbolic region is used with an artifical symbol. - // FIXME: It is better to have a custom (new) kind of MemRegion for such - // cases. + } else { + // There is no 'errno' variable, so create a new symbolic memory region + // that can be used to model the return value of the "get the location of + // errno" internal functions. + // NOTE: this `SVal` is created even if errno is not defined or used. SValBuilder &SVB = C.getSValBuilder(); MemRegionManager &RMgr = C.getStateManager().getRegionManager(); @@ -162,27 +119,31 @@ void ErrnoModeling::checkBeginFunction(CheckerContext &C) const { RMgr.getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind); // Create an artifical symbol for the region. - // It is not possible to associate a statement or expression in this case. + // Note that it is not possible to associate a statement or expression in + // this case and the `symbolTag` (opaque pointer tag) is just the address + // of the data member `ErrnoDecl` of the singleton `ErrnoModeling` checker + // object. const SymbolConjured *Sym = SVB.conjureSymbol( nullptr, C.getLocationContext(), ACtx.getLValueReferenceType(ACtx.IntTy), C.blockCount(), &ErrnoDecl); // The symbolic region is untyped, create a typed sub-region in it. // The ElementRegion is used to make the errno region a typed region. - const MemRegion *ErrnoR = RMgr.getElementRegion( + ErrnoR = RMgr.getElementRegion( ACtx.IntTy, SVB.makeZeroArrayIndex(), RMgr.getSymbolicRegion(Sym, GlobalSystemSpace), C.getASTContext()); - State = State->set(ErrnoR); - State = - errno_modeling::setErrnoValue(State, C, 0, errno_modeling::Irrelevant); - C.addTransition(State); } + assert(ErrnoR); + State = State->set(ErrnoR); + State = + errno_modeling::setErrnoValue(State, C, 0, errno_modeling::Irrelevant); + C.addTransition(State); } bool ErrnoModeling::evalCall(const CallEvent &Call, CheckerContext &C) const { // Return location of "errno" at a call to an "errno address returning" // function. - if (ErrnoLocationCalls.contains(Call)) { + if (errno_modeling::isErrnoLocationCall(Call)) { ProgramStateRef State = C.getState(); const MemRegion *ErrnoR = State->get(); @@ -260,14 +221,8 @@ ProgramStateRef clearErrnoState(ProgramStateRef State) { return setErrnoState(State, Irrelevant); } -bool isErrno(const Decl *D) { - if (const auto *VD = dyn_cast_or_null(D)) - if (const IdentifierInfo *II = VD->getIdentifier()) - return II->getName() == ErrnoVarName; - if (const auto *FD = dyn_cast_or_null(D)) - if (const IdentifierInfo *II = FD->getIdentifier()) - return llvm::is_contained(ErrnoLocationFuncNames, II->getName()); - return false; +bool isErrnoLocationCall(const CallEvent &CE) { + return ErrnoLocationCalls.contains(CE); } const NoteTag *getErrnoNoteTag(CheckerContext &C, const std::string &Message) { diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h index 6b53572fe5e2..95da8a28d325 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h +++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h @@ -71,12 +71,9 @@ ProgramStateRef setErrnoState(ProgramStateRef State, ErrnoCheckState EState); /// Clear state of errno (make it irrelevant). ProgramStateRef clearErrnoState(ProgramStateRef State); -/// Determine if a `Decl` node related to 'errno'. -/// This is true if the declaration is the errno variable or a function -/// that returns a pointer to the 'errno' value (usually the 'errno' macro is -/// defined with this function). \p D is not required to be a canonical -/// declaration. -bool isErrno(const Decl *D); +/// Determine if `Call` is a call to an internal function that returns the +/// location of `errno` (in environments where errno is accessed this way). +bool isErrnoLocationCall(const CallEvent &Call); /// Create a NoteTag that displays the message if the 'errno' memory region is /// marked as interesting, and resets the interestingness. diff --git a/clang/test/Analysis/memory-model.cpp b/clang/test/Analysis/memory-model.cpp index fd5a286acb60..cd42e8c72b8b 100644 --- a/clang/test/Analysis/memory-model.cpp +++ b/clang/test/Analysis/memory-model.cpp @@ -34,9 +34,9 @@ void var_simple_ref() { } void var_simple_ptr(int *a) { - clang_analyzer_dump(a); // expected-warning {{SymRegion{reg_$0}}} - clang_analyzer_dumpExtent(a); // expected-warning {{extent_$1{SymRegion{reg_$0}}}} - clang_analyzer_dumpElementCount(a); // expected-warning {{(extent_$1{SymRegion{reg_$0}}) / 4}} + clang_analyzer_dump(a); // expected-warning {{SymRegion{reg_$1}}} + clang_analyzer_dumpExtent(a); // expected-warning {{extent_$2{SymRegion{reg_$1}}}} + clang_analyzer_dumpElementCount(a); // expected-warning {{(extent_$2{SymRegion{reg_$1}}) / 4}} } void var_array() { @@ -53,9 +53,9 @@ void string() { } void struct_simple_ptr(S *a) { - clang_analyzer_dump(a); // expected-warning {{SymRegion{reg_$0}}} - clang_analyzer_dumpExtent(a); // expected-warning {{extent_$1{SymRegion{reg_$0}}}} - clang_analyzer_dumpElementCount(a); // expected-warning {{(extent_$1{SymRegion{reg_$0}}) / 4}} + clang_analyzer_dump(a); // expected-warning {{SymRegion{reg_$1}}} + clang_analyzer_dumpExtent(a); // expected-warning {{extent_$2{SymRegion{reg_$1}}}} + clang_analyzer_dumpElementCount(a); // expected-warning {{(extent_$2{SymRegion{reg_$1}}) / 4}} } void field_ref(S a) { @@ -65,9 +65,9 @@ void field_ref(S a) { } void field_ptr(S *a) { - clang_analyzer_dump(&a->f); // expected-warning {{Element{SymRegion{reg_$0},0 S64b,struct S}.f}} - clang_analyzer_dumpExtent(&a->f); // expected-warning {{extent_$1{SymRegion{reg_$0}}}} - clang_analyzer_dumpElementCount(&a->f); // expected-warning {{(extent_$1{SymRegion{reg_$0}}) / 4U}} + clang_analyzer_dump(&a->f); // expected-warning {{Element{SymRegion{reg_$1},0 S64b,struct S}.f}} + clang_analyzer_dumpExtent(&a->f); // expected-warning {{extent_$2{SymRegion{reg_$1}}}} + clang_analyzer_dumpElementCount(&a->f); // expected-warning {{(extent_$2{SymRegion{reg_$1}}) / 4U}} } void symbolic_array() { -- GitLab From f090801a9651cf4f0d05cc361a2a1b14805b62bf Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Wed, 15 May 2024 09:18:42 +0000 Subject: [PATCH 321/578] [lldb] Disable unaligned-pc-sigbus.test on arm(32) I though the test could work there as well, but (of course) it does not, because the lowest bit just means "run the code as thumb". --- lldb/test/Shell/Unwind/unaligned-pc-sigbus.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/test/Shell/Unwind/unaligned-pc-sigbus.test b/lldb/test/Shell/Unwind/unaligned-pc-sigbus.test index 5ebfba54301e..49f771cae95b 100644 --- a/lldb/test/Shell/Unwind/unaligned-pc-sigbus.test +++ b/lldb/test/Shell/Unwind/unaligned-pc-sigbus.test @@ -1,4 +1,4 @@ -# REQUIRES: (target-aarch64 || target-arm) && native +# REQUIRES: target-aarch64 && native # UNSUPPORTED: system-windows # llvm.org/pr91610, rdar://128031075 # XFAIL: system-darwin -- GitLab From 2f6c0e6e180c81087c26f4afac2155ea70472ec6 Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Wed, 15 May 2024 10:25:51 +0100 Subject: [PATCH 322/578] [flang][Alias Analysis] not all block arguments are dummy arguments (#92156) Arguments to openmp regions should not be tagged as dummy arguments. This is particularly unsafe because these openmp blocks will eventually be inlined into the calling function, where they will trivially alias with other values inside of the calling function. This is probably a theoretical issue because the calls to openmp runtime function calls would act as barriers, preventing optimizations that are too aggressive. But a lot more thought would need to go into a bet like that. This came out of discussion on https://github.com/llvm/llvm-project/pull/92036 --- .../lib/Optimizer/Analysis/AliasAnalysis.cpp | 6 ++- .../lib/Optimizer/Transforms/AddAliasTags.cpp | 1 + flang/test/Transforms/tbaa.fir | 37 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp index f723e8f66e3e..ed1101dc5e8d 100644 --- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp +++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp @@ -33,7 +33,11 @@ static bool isDummyArgument(mlir::Value v) { if (!blockArg) return false; - return blockArg.getOwner()->isEntryBlock(); + mlir::Block *owner = blockArg.getOwner(); + if (!owner->isEntryBlock() || + !mlir::isa(owner->getParentOp())) + return false; + return true; } /// Temporary function to skip through all the no op operations diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp index 684aa4462915..3642a812096d 100644 --- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp +++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp @@ -105,6 +105,7 @@ static std::string getFuncArgName(mlir::Value arg) { "arg is a function argument"); mlir::FunctionOpInterface func = mlir::dyn_cast( blockArg.getOwner()->getParentOp()); + assert(func && "This is not a function argument"); mlir::StringAttr attr = func.getArgAttrOfType( blockArg.getArgNumber(), "fir.bindc_name"); if (!attr) diff --git a/flang/test/Transforms/tbaa.fir b/flang/test/Transforms/tbaa.fir index 7825ae60c71e..f94bbe4bf948 100644 --- a/flang/test/Transforms/tbaa.fir +++ b/flang/test/Transforms/tbaa.fir @@ -173,3 +173,40 @@ // CHECK: fir.store %[[VAL_8]] to %[[VAL_12]] : !fir.ref // CHECK: return // CHECK: } + +// ----- + +// Make sure we don't mistake other block arguments as dummy arguments: + +omp.declare_reduction @add_reduction_i32 : i32 init { +^bb0(%arg0: i32): + %c0_i32 = arith.constant 0 : i32 + omp.yield(%c0_i32 : i32) +} combiner { +^bb0(%arg0: i32, %arg1: i32): + %0 = arith.addi %arg0, %arg1 : i32 + omp.yield(%0 : i32) +} + +func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { + %c10_i32 = arith.constant 10 : i32 + %c6_i32 = arith.constant 6 : i32 + %c-1_i32 = arith.constant -1 : i32 + %0 = fir.address_of(@_QFEi) : !fir.ref + %1 = fir.declare %0 {uniq_name = "_QFEi"} : (!fir.ref) -> !fir.ref + omp.parallel reduction(@add_reduction_i32 %1 -> %arg0 : !fir.ref) { +// CHECK: omp.parallel reduction({{.*}}) { + %8 = fir.declare %arg0 {uniq_name = "_QFEi"} : (!fir.ref) -> !fir.ref +// CHECK-NEXT: %[[DECL:.*]] = fir.declare + fir.store %c-1_i32 to %8 : !fir.ref +// CHECK-NOT: fir.store %{{.*}} to %[[DECL]] {tbaa = %{{.*}}} : !fir.ref +// CHECK: fir.store %{{.*}} to %[[DECL]] : !fir.ref + omp.terminator + } + return +} + +fir.global internal @_QFEi : i32 { + %c0_i32 = arith.constant 0 : i32 + fir.has_value %c0_i32 : i32 +} -- GitLab From f39e75b45160ae69222d6ae197ee20c365146717 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 15 May 2024 11:35:02 +0200 Subject: [PATCH 323/578] [CodeGen][ARM64EC][NFC] Factor out emitFunctionAlias and getSymbolFromMetadata in emitFunctionEntryLabel. (#92098) --- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 71 +++++++++---------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index ee39c6355c29..3ce766fc173c 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -1161,52 +1161,45 @@ void AArch64AsmPrinter::emitFunctionEntryLabel() { TS->emitDirectiveVariantPCS(CurrentFnSym); } + AsmPrinter::emitFunctionEntryLabel(); + if (TM.getTargetTriple().isWindowsArm64EC() && !MF->getFunction().hasLocalLinkage()) { // For ARM64EC targets, a function definition's name is mangled differently - // from the normal symbol. We emit the alias from the unmangled symbol to - // mangled symbol name here. - if (MDNode *Unmangled = - MF->getFunction().getMetadata("arm64ec_unmangled_name")) { - AsmPrinter::emitFunctionEntryLabel(); - - if (MDNode *ECMangled = - MF->getFunction().getMetadata("arm64ec_ecmangled_name")) { - StringRef UnmangledStr = - cast(Unmangled->getOperand(0))->getString(); - MCSymbol *UnmangledSym = - MMI->getContext().getOrCreateSymbol(UnmangledStr); - StringRef ECMangledStr = - cast(ECMangled->getOperand(0))->getString(); - MCSymbol *ECMangledSym = - MMI->getContext().getOrCreateSymbol(ECMangledStr); - OutStreamer->emitSymbolAttribute(UnmangledSym, MCSA_WeakAntiDep); - OutStreamer->emitAssignment( - UnmangledSym, - MCSymbolRefExpr::create(ECMangledSym, MCSymbolRefExpr::VK_WEAKREF, - MMI->getContext())); - OutStreamer->emitSymbolAttribute(ECMangledSym, MCSA_WeakAntiDep); - OutStreamer->emitAssignment( - ECMangledSym, - MCSymbolRefExpr::create(CurrentFnSym, MCSymbolRefExpr::VK_WEAKREF, - MMI->getContext())); - return; + // from the normal symbol, emit required aliases here. + auto emitFunctionAlias = [&](MCSymbol *Src, MCSymbol *Dst) { + OutStreamer->emitSymbolAttribute(Src, MCSA_WeakAntiDep); + OutStreamer->emitAssignment( + Src, MCSymbolRefExpr::create(Dst, MCSymbolRefExpr::VK_WEAKREF, + MMI->getContext())); + }; + + auto getSymbolFromMetadata = [&](StringRef Name) { + MCSymbol *Sym = nullptr; + if (MDNode *Node = MF->getFunction().getMetadata(Name)) { + StringRef NameStr = cast(Node->getOperand(0))->getString(); + Sym = MMI->getContext().getOrCreateSymbol(NameStr); + } + return Sym; + }; + + if (MCSymbol *UnmangledSym = + getSymbolFromMetadata("arm64ec_unmangled_name")) { + MCSymbol *ECMangledSym = getSymbolFromMetadata("arm64ec_ecmangled_name"); + + if (ECMangledSym) { + // An external function, emit the alias from the unmangled symbol to + // mangled symbol name and the alias from the mangled symbol to guest + // exit thunk. + emitFunctionAlias(UnmangledSym, ECMangledSym); + emitFunctionAlias(ECMangledSym, CurrentFnSym); } else { - StringRef UnmangledStr = - cast(Unmangled->getOperand(0))->getString(); - MCSymbol *UnmangledSym = - MMI->getContext().getOrCreateSymbol(UnmangledStr); - OutStreamer->emitSymbolAttribute(UnmangledSym, MCSA_WeakAntiDep); - OutStreamer->emitAssignment( - UnmangledSym, - MCSymbolRefExpr::create(CurrentFnSym, MCSymbolRefExpr::VK_WEAKREF, - MMI->getContext())); - return; + // A function implementation, emit the alias from the unmangled symbol + // to mangled symbol name. + emitFunctionAlias(UnmangledSym, CurrentFnSym); } } } - - return AsmPrinter::emitFunctionEntryLabel(); } /// Small jump tables contain an unsigned byte or half, representing the offset -- GitLab From 421862f8e4ffddf57e210a205984a0ee39c57d96 Mon Sep 17 00:00:00 2001 From: Lukacma Date: Wed, 15 May 2024 10:51:32 +0100 Subject: [PATCH 324/578] [Clang] Fix incorrect passing of _BitInt args (#90741) This patch removes incorrect `byval` attribute from pointer argument passed with >128 bit long _BitInt types. --- clang/lib/CodeGen/Targets/AArch64.cpp | 2 +- clang/test/CodeGen/ext-int-cc.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index e32b060ebeb9..0a4711fb2170 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -317,7 +317,7 @@ AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadic, if (const auto *EIT = Ty->getAs()) if (EIT->getNumBits() > 128) - return getNaturalAlignIndirect(Ty); + return getNaturalAlignIndirect(Ty, false); return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS() ? ABIArgInfo::getExtend(Ty) diff --git a/clang/test/CodeGen/ext-int-cc.c b/clang/test/CodeGen/ext-int-cc.c index 001e866d34b4..508728172ab4 100644 --- a/clang/test/CodeGen/ext-int-cc.c +++ b/clang/test/CodeGen/ext-int-cc.c @@ -22,9 +22,9 @@ // RUN: %clang_cc1 -no-enable-noundef-analysis -triple systemz -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=SYSTEMZ // RUN: %clang_cc1 -no-enable-noundef-analysis -triple ppc64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=PPC64 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple ppc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=PPC32 -// RUN: %clang_cc1 -no-enable-noundef-analysis -triple aarch64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64 +// RUN: %clang_cc1 -no-enable-noundef-analysis -triple aarch64 -O3 -disable-llvm-passes -fexperimental-max-bitint-width=1024 -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple aarch64 -target-abi darwinpcs -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64DARWIN -// RUN: %clang_cc1 -no-enable-noundef-analysis -triple arm64_32-apple-ios -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64 +// RUN: %clang_cc1 -no-enable-noundef-analysis -triple arm64_32-apple-ios -O3 -disable-llvm-passes -fexperimental-max-bitint-width=1024 -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple arm64_32-apple-ios -target-abi darwinpcs -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64DARWIN // RUN: %clang_cc1 -no-enable-noundef-analysis -triple arm -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=ARM // RUN: %clang_cc1 -no-enable-noundef-analysis -triple loongarch64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=LA64 @@ -135,6 +135,7 @@ void ParamPassing4(_BitInt(129) a) {} // WIN64: define dso_local void @ParamPassing4(ptr %{{.+}}) // LIN32: define{{.*}} void @ParamPassing4(ptr %{{.+}}) // WIN32: define dso_local void @ParamPassing4(ptr %{{.+}}) +// AARCH64: define{{.*}} void @ParamPassing4(ptr %{{.+}}) // NACL-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) // NVPTX64-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) // NVPTX-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) @@ -155,7 +156,6 @@ void ParamPassing4(_BitInt(129) a) {} // SYSTEMZ-NOT: define{{.*}} void @ParamPassing4(ptr %{{.+}}) // PPC64-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) // PPC32-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) -// AARCH64-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) // AARCH64DARWIN-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) // ARM-NOT: define{{.*}} arm_aapcscc void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) // LA64-NOT: define{{.*}} void @ParamPassing4(ptr %{{.+}}) @@ -294,6 +294,7 @@ _BitInt(129) ReturnPassing5(void){} // WIN64: define dso_local void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // LIN32: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // WIN32: define dso_local void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// AARCH64: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // NACL-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // NVPTX64-NOT: define{{.*}} i129 @ReturnPassing5( // NVPTX-NOT: define{{.*}} i129 @ReturnPassing5( @@ -314,7 +315,6 @@ _BitInt(129) ReturnPassing5(void){} // SYSTEMZ-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // PPC64-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // PPC32-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret -// AARCH64-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // AARCH64DARWIN-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // ARM-NOT: define{{.*}} arm_aapcscc void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // LA64-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret -- GitLab From d187005cad8c2cb7d44ba3dd6b01c5f0e4c14ae7 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 15 May 2024 11:00:14 +0100 Subject: [PATCH 325/578] [VPlan] Update VPBlendRecipe codegen for for first-lane only. Update VPBlendRecipe::execute to support generating code for first-lane only. This fixes a crash in the newly added test @test_not_first_lane_only_wide_compare_incoming_order_swapped. --- .../lib/Transforms/Vectorize/VPlanRecipes.cpp | 35 +++--- ...ruction-or-drop-poison-generating-flags.ll | 8 +- .../Transforms/LoopVectorize/uniform-blend.ll | 20 +--- .../unused-blend-mask-for-first-operand.ll | 105 +++++++++++++++++- 4 files changed, 125 insertions(+), 43 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index fa634e774b5c..5eb99ffd1e10 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -1506,24 +1506,25 @@ void VPBlendRecipe::execute(VPTransformState &State) { // Note that Mask0 is never used: lanes for which no path reaches this phi and // are essentially undef are taken from In0. VectorParts Entry(State.UF); - for (unsigned In = 0; In < NumIncoming; ++In) { - for (unsigned Part = 0; Part < State.UF; ++Part) { - // We might have single edge PHIs (blocks) - use an identity - // 'select' for the first PHI operand. - Value *In0 = State.get(getIncomingValue(In), Part); - if (In == 0) - Entry[Part] = In0; // Initialize with the first incoming value. - else { - // Select between the current value and the previous incoming edge - // based on the incoming mask. - Value *Cond = State.get(getMask(In), Part); - Entry[Part] = - State.Builder.CreateSelect(Cond, In0, Entry[Part], "predphi"); - } - } - } + bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this); + for (unsigned In = 0; In < NumIncoming; ++In) { + for (unsigned Part = 0; Part < State.UF; ++Part) { + // We might have single edge PHIs (blocks) - use an identity + // 'select' for the first PHI operand. + Value *In0 = State.get(getIncomingValue(In), Part, OnlyFirstLaneUsed); + if (In == 0) + Entry[Part] = In0; // Initialize with the first incoming value. + else { + // Select between the current value and the previous incoming edge + // based on the incoming mask. + Value *Cond = State.get(getMask(In), Part, OnlyFirstLaneUsed); + Entry[Part] = + State.Builder.CreateSelect(Cond, In0, Entry[Part], "predphi"); + } + } + } for (unsigned Part = 0; Part < State.UF; ++Part) - State.set(this, Entry[Part], Part); + State.set(this, Entry[Part], Part, OnlyFirstLaneUsed); } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll b/llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll index 4e38630209b2..5f8141600371 100644 --- a/llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll +++ b/llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll @@ -40,8 +40,6 @@ define void @pr87378_vpinstruction_or_drop_poison_generating_flags(ptr %arg, i64 ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[VEC_IND:%.*]] = phi [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[BROADCAST_SPLATINSERT5:%.*]] = insertelement poison, i64 [[TMP12]], i64 0 -; CHECK-NEXT: [[BROADCAST_SPLAT6:%.*]] = shufflevector [[BROADCAST_SPLATINSERT5]], poison, zeroinitializer ; CHECK-NEXT: [[TMP13:%.*]] = icmp ule [[VEC_IND]], [[BROADCAST_SPLAT]] ; CHECK-NEXT: [[TMP14:%.*]] = icmp ule [[VEC_IND]], [[BROADCAST_SPLAT2]] ; CHECK-NEXT: [[TMP15:%.*]] = select [[TMP13]], [[TMP14]], zeroinitializer @@ -52,9 +50,9 @@ define void @pr87378_vpinstruction_or_drop_poison_generating_flags(ptr %arg, i64 ; CHECK-NEXT: [[TMP20:%.*]] = xor [[TMP14]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) ; CHECK-NEXT: [[TMP21:%.*]] = select [[TMP13]], [[TMP20]], zeroinitializer ; CHECK-NEXT: [[TMP22:%.*]] = or [[TMP19]], [[TMP21]] -; CHECK-NEXT: [[PREDPHI:%.*]] = select [[TMP19]], [[BROADCAST_SPLAT6]], shufflevector ( insertelement ( poison, i64 poison, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP23:%.*]] = extractelement [[PREDPHI]], i32 0 -; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i16, ptr [[ARG]], i64 [[TMP23]] +; CHECK-NEXT: [[EXT:%.+]] = extractelement [[TMP19]], i32 0 +; CHECK-NEXT: [[PREDPHI:%.*]] = select i1 [[EXT]], i64 [[TMP12]], i64 poison +; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i16, ptr [[ARG]], i64 [[PREDPHI]] ; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i16, ptr [[TMP24]], i32 0 ; CHECK-NEXT: call void @llvm.masked.store.nxv8i16.p0( zeroinitializer, ptr [[TMP25]], i32 2, [[TMP22]]) ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP5]] diff --git a/llvm/test/Transforms/LoopVectorize/uniform-blend.ll b/llvm/test/Transforms/LoopVectorize/uniform-blend.ll index 71eed3b2985d..19cbcac6090c 100644 --- a/llvm/test/Transforms/LoopVectorize/uniform-blend.ll +++ b/llvm/test/Transforms/LoopVectorize/uniform-blend.ll @@ -4,19 +4,12 @@ define void @blend_uniform_iv_trunc(i1 %c) { ; CHECK-LABEL: @blend_uniform_iv_trunc( -; CHECK: vector.ph: -; CHECK-NEXT: [[MASK0:%.*]] = insertelement <4 x i1> poison, i1 %c, i64 0 -; CHECK-NEXT: [[MASK1:%.*]] = shufflevector <4 x i1> [[MASK0]], <4 x i1> poison, <4 x i32> zeroinitializer - ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ] ; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDEX]] to i16 ; CHECK-NEXT: [[TMP2:%.*]] = add i16 [[TMP1]], 0 -; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i16> poison, i16 [[TMP2]], i64 0 -; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT1]], <4 x i16> poison, <4 x i32> zeroinitializer -; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[MASK1]], <4 x i16> [[BROADCAST_SPLAT2]], <4 x i16> undef -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x i16> [[PREDPHI]], i32 0 -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [32 x i16], ptr @dst, i16 0, i16 [[TMP4]] +; CHECK-NEXT: [[PREDPHI:%.*]] = select i1 %c, i16 [[TMP2]], i16 undef +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [32 x i16], ptr @dst, i16 0, i16 [[PREDPHI]] ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, ptr [[TMP5]], i32 0 ; CHECK-NEXT: store <4 x i16> zeroinitializer, ptr [[TMP6]], align 2 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 @@ -49,17 +42,12 @@ exit: ; preds = %loop.latch define void @blend_uniform_iv(i1 %c) { ; CHECK-LABEL: @blend_uniform_iv( ; CHECK: vector.ph: -; CHECK-NEXT: [[MASK0:%.*]] = insertelement <4 x i1> poison, i1 %c, i64 0 -; CHECK-NEXT: [[MASK1:%.*]] = shufflevector <4 x i1> [[MASK0]], <4 x i1> poison, <4 x i32> zeroinitializer ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ] ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i64> poison, i64 [[TMP0]], i64 0 -; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT1]], <4 x i64> poison, <4 x i32> zeroinitializer -; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[MASK1]], <4 x i64> [[BROADCAST_SPLAT2]], <4 x i64> undef -; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i64> [[PREDPHI]], i32 0 -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [32 x i16], ptr @dst, i16 0, i64 [[TMP2]] +; CHECK-NEXT: [[PREDPHI:%.*]] = select i1 %c, i64 [[TMP0]], i64 undef +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [32 x i16], ptr @dst, i16 0, i64 [[PREDPHI]] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i16, ptr [[TMP3]], i32 0 ; CHECK-NEXT: store <4 x i16> zeroinitializer, ptr [[TMP4]], align 2 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 diff --git a/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll b/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll index d0c74897f264..0f7bd3d71feb 100644 --- a/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll +++ b/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll @@ -16,7 +16,7 @@ define void @test_not_first_lane_only_constant(ptr %A, ptr noalias %B) { ; CHECK-NEXT: [[OFFSET_IDX:%.*]] = trunc i32 [[INDEX]] to i16 ; CHECK-NEXT: [[TMP0:%.*]] = add i16 [[OFFSET_IDX]], 0 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[A]], i16 [[TMP0]] -; CHECK-NEXT: [[TMP13:%.*]] = load i16, ptr %B, align 2 +; CHECK-NEXT: [[TMP13:%.*]] = load i16, ptr [[B]], align 2 ; CHECK-NEXT: [[BROADCAST_SPLATINSERT5:%.*]] = insertelement <4 x i16> poison, i16 [[TMP13]], i64 0 ; CHECK-NEXT: [[BROADCAST_SPLAT6:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT5]], <4 x i16> poison, <4 x i32> zeroinitializer ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0 @@ -86,8 +86,6 @@ define void @test_not_first_lane_only_wide_compare(ptr %A, ptr noalias %B, i16 % ; CHECK: vector.ph: ; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i16> poison, i16 [[X]], i64 0 ; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT]], <4 x i16> poison, <4 x i32> zeroinitializer -; CHECK-NEXT: [[BROADCAST_SPLATINSERT3:%.*]] = insertelement <4 x ptr> poison, ptr [[B]], i64 0 -; CHECK-NEXT: [[BROADCAST_SPLAT4:%.*]] = shufflevector <4 x ptr> [[BROADCAST_SPLATINSERT3]], <4 x ptr> poison, <4 x i32> zeroinitializer ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] @@ -97,8 +95,8 @@ define void @test_not_first_lane_only_wide_compare(ptr %A, ptr noalias %B, i16 % ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0 ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[TMP2]], align 2 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ult <4 x i16> [[WIDE_LOAD]], [[BROADCAST_SPLAT2]] -; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP5]], <4 x ptr> poison, <4 x ptr> [[BROADCAST_SPLAT4]] -; CHECK-NEXT: [[TMP12:%.*]] = extractelement <4 x ptr> [[PREDPHI]], i32 0 +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x i1> [[TMP5]], i32 0 +; CHECK-NEXT: [[TMP12:%.*]] = select i1 [[TMP4]], ptr poison, ptr [[B]] ; CHECK-NEXT: [[TMP13:%.*]] = load i16, ptr [[TMP12]], align 2 ; CHECK-NEXT: [[BROADCAST_SPLATINSERT5:%.*]] = insertelement <4 x i16> poison, i16 [[TMP13]], i64 0 ; CHECK-NEXT: [[BROADCAST_SPLAT6:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT5]], <4 x i16> poison, <4 x i32> zeroinitializer @@ -162,6 +160,101 @@ loop.latch: %c.2 = icmp eq i16 %iv.next, 1000 br i1 %c.2, label %exit, label %loop.header +exit: + ret void +} + +define void @test_not_first_lane_only_wide_compare_incoming_order_swapped(ptr %A, ptr noalias %B, i16 %x, i16 %y) { +; CHECK-LABEL: define void @test_not_first_lane_only_wide_compare_incoming_order_swapped( +; CHECK-SAME: ptr [[A:%.*]], ptr noalias [[B:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i16> poison, i16 [[X]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT]], <4 x i16> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i16> poison, i16 [[Y]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT1]], <4 x i16> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = trunc i32 [[INDEX]] to i16 +; CHECK-NEXT: [[TMP0:%.*]] = add i16 [[OFFSET_IDX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[A]], i16 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[TMP2]], align 2 +; CHECK-NEXT: [[TMP3:%.*]] = icmp ult <4 x i16> [[WIDE_LOAD]], [[BROADCAST_SPLAT]] +; CHECK-NEXT: [[TMP4:%.*]] = xor <4 x i1> [[TMP3]], +; CHECK-NEXT: [[TMP5:%.*]] = icmp ult <4 x i16> [[WIDE_LOAD]], [[BROADCAST_SPLAT2]] +; CHECK-NEXT: [[TMP6:%.*]] = select <4 x i1> [[TMP4]], <4 x i1> [[TMP5]], <4 x i1> zeroinitializer +; CHECK-NEXT: [[TMP7:%.*]] = xor <4 x i1> [[TMP5]], +; CHECK-NEXT: [[TMP8:%.*]] = select <4 x i1> [[TMP4]], <4 x i1> [[TMP7]], <4 x i1> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x i1> [[TMP6]], i32 0 +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i1> [[TMP8]], i32 0 +; CHECK-NEXT: [[TMP11:%.*]] = or i1 [[TMP9]], [[TMP10]] +; CHECK-NEXT: [[PREDPHI:%.*]] = select i1 [[TMP11]], ptr [[B]], ptr poison +; CHECK-NEXT: [[TMP12:%.*]] = load i16, ptr [[PREDPHI]], align 2 +; CHECK-NEXT: [[BROADCAST_SPLATINSERT3:%.*]] = insertelement <4 x i16> poison, i16 [[TMP12]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT4:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT3]], <4 x i16> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: store <4 x i16> [[BROADCAST_SPLAT4]], ptr [[TMP2]], align 2 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 +; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i32 [[INDEX_NEXT]], 1000 +; CHECK-NEXT: br i1 [[TMP13]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i16 [ 1000, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i16 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i16, ptr [[A]], i16 [[IV]] +; CHECK-NEXT: [[L_0:%.*]] = load i16, ptr [[GEP_A]], align 2 +; CHECK-NEXT: [[C_0:%.*]] = icmp ult i16 [[L_0]], [[X]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[ELSE_1:%.*]] +; CHECK: else.1: +; CHECK-NEXT: [[C_1:%.*]] = icmp ult i16 [[L_0]], [[Y]] +; CHECK-NEXT: br i1 [[C_1]], label [[THEN_2:%.*]], label [[ELSE_2:%.*]] +; CHECK: then.2: +; CHECK-NEXT: br label [[ELSE_2]] +; CHECK: else.2: +; CHECK-NEXT: br label [[LOOP_LATCH]] +; CHECK: loop.latch: +; CHECK-NEXT: [[MERGE:%.*]] = phi ptr [ poison, [[LOOP_HEADER]] ], [ [[B]], [[ELSE_2]] ] +; CHECK-NEXT: [[L:%.*]] = load i16, ptr [[MERGE]], align 2 +; CHECK-NEXT: [[IV_NEXT]] = add i16 [[IV]], 1 +; CHECK-NEXT: store i16 [[L]], ptr [[GEP_A]], align 2 +; CHECK-NEXT: [[C_2:%.*]] = icmp eq i16 [[IV_NEXT]], 1000 +; CHECK-NEXT: br i1 [[C_2]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP7:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop.header + +loop.header: + %iv = phi i16 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep.A = getelementptr inbounds i16, ptr %A, i16 %iv + %l.0 = load i16, ptr %gep.A + %c.0 = icmp ult i16 %l.0, %x + br i1 %c.0, label %loop.latch, label %else.1 + +else.1: + %c.1 = icmp ult i16 %l.0, %y + br i1 %c.1, label %then.2, label %else.2 + +then.2: + br label %else.2 + +else.2: + br label %loop.latch + +loop.latch: + %merge = phi ptr [ poison, %loop.header ], [ %B, %else.2 ] + %l = load i16, ptr %merge, align 2 + %iv.next = add i16 %iv, 1 + store i16 %l, ptr %gep.A + %c.2 = icmp eq i16 %iv.next, 1000 + br i1 %c.2, label %exit, label %loop.header + exit: ret void } @@ -172,4 +265,6 @@ exit: ; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]} ; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]} ; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META2]], [[META1]]} +; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]]} +; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META1]]} ;. -- GitLab From b0a1ae2cca4a438753e093df2f949e73a313dbe2 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 15 May 2024 11:17:23 +0100 Subject: [PATCH 326/578] [LV] Add additional variants of tests with udiv/urem/sdiv/srem in TC. Add additional tests with udiv/urem/sdiv/srem in trip counts, where the divisor is constant. For https://github.com/llvm/llvm-project/pull/92177. --- .../trip-count-expansion-may-introduce-ub.ll | 553 +++++++++++++++++- 1 file changed, 539 insertions(+), 14 deletions(-) diff --git a/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll b/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll index 85fad6fb3632..ce5d4427fa01 100644 --- a/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll +++ b/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll @@ -4,8 +4,8 @@ ; Test cases with trip counts containing UDIV expressions for ; https://github.com/llvm/llvm-project/issues/89958. -define i64 @multi_exit_1_exit_count_with_udiv_in_header(ptr %dst, i64 %N) { -; CHECK-LABEL: define i64 @multi_exit_1_exit_count_with_udiv_in_header( +define i64 @multi_exit_1_exit_count_with_udiv_by_value_in_header(ptr %dst, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_1_exit_count_with_udiv_by_value_in_header( ; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) @@ -70,8 +70,74 @@ exit: ret i64 %p } -define i64 @multi_exit_2_exit_count_with_udiv_in_block_executed_unconditionally(ptr %A, i64 %N) { -; CHECK-LABEL: define i64 @multi_exit_2_exit_count_with_udiv_in_block_executed_unconditionally( +define i64 @multi_exit_1_exit_count_with_udiv_by_constant_in_header(ptr %dst, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_1_exit_count_with_udiv_by_constant_in_header( +; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) +; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 [[N]], 42 +; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[TMP0]]) +; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 +; CHECK-NEXT: store <4 x i32> , ptr [[TMP6]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: [[D:%.*]] = udiv i64 [[N]], 42 +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %dst, i64 %iv + store i32 1, ptr %gep + %d = udiv i64 %N, 42 + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.latch, label %exit + +loop.latch: + %iv.next = add i64 %iv, 1 + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] + ret i64 %p +} + +define i64 @multi_exit_2_exit_count_with_udiv_by_value_in_block_executed_unconditionally(ptr %A, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_2_exit_count_with_udiv_by_value_in_block_executed_unconditionally( ; CHECK-SAME: ptr [[A:%.*]], i64 [[N:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) @@ -126,7 +192,7 @@ define i64 @multi_exit_2_exit_count_with_udiv_in_block_executed_unconditionally( ; CHECK: pred.store.continue6: ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP19:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP19]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP19]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: br label [[SCALAR_PH]] ; CHECK: scalar.ph: @@ -148,7 +214,7 @@ define i64 @multi_exit_2_exit_count_with_udiv_in_block_executed_unconditionally( ; CHECK: loop.latch: ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 ; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] -; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP7:![0-9]+]] ; CHECK: exit: ; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[CONTINUE]] ], [ 0, [[LOOP_LATCH]] ] ; CHECK-NEXT: ret i64 [[P]] @@ -182,8 +248,120 @@ exit: ret i64 %p } -define i64 @multi_exit_3_exit_count_with_udiv_in_block_executed_conditionally(ptr %A, i64 %N) { -; CHECK-LABEL: define i64 @multi_exit_3_exit_count_with_udiv_in_block_executed_conditionally( +define i64 @multi_exit_2_exit_count_with_udiv_by_constant_in_block_executed_unconditionally(ptr %A, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_2_exit_count_with_udiv_by_constant_in_block_executed_unconditionally( +; CHECK-SAME: ptr [[A:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) +; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 [[N]], 42 +; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[TMP0]]) +; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE6:%.*]] ] +; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP6]], align 4 +; CHECK-NEXT: [[TMP7:%.*]] = icmp eq <4 x i32> [[WIDE_LOAD]], +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP7]], i32 0 +; CHECK-NEXT: br i1 [[TMP8]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] +; CHECK: pred.store.if: +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP4]] +; CHECK-NEXT: store i32 1, ptr [[TMP9]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]] +; CHECK: pred.store.continue: +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i1> [[TMP7]], i32 1 +; CHECK-NEXT: br i1 [[TMP10]], label [[PRED_STORE_IF1:%.*]], label [[PRED_STORE_CONTINUE2:%.*]] +; CHECK: pred.store.if1: +; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[INDEX]], 1 +; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP11]] +; CHECK-NEXT: store i32 1, ptr [[TMP12]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE2]] +; CHECK: pred.store.continue2: +; CHECK-NEXT: [[TMP13:%.*]] = extractelement <4 x i1> [[TMP7]], i32 2 +; CHECK-NEXT: br i1 [[TMP13]], label [[PRED_STORE_IF3:%.*]], label [[PRED_STORE_CONTINUE4:%.*]] +; CHECK: pred.store.if3: +; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP14]] +; CHECK-NEXT: store i32 1, ptr [[TMP15]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE4]] +; CHECK: pred.store.continue4: +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[TMP7]], i32 3 +; CHECK-NEXT: br i1 [[TMP16]], label [[PRED_STORE_IF5:%.*]], label [[PRED_STORE_CONTINUE6]] +; CHECK: pred.store.if5: +; CHECK-NEXT: [[TMP17:%.*]] = add i64 [[INDEX]], 3 +; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP17]] +; CHECK-NEXT: store i32 1, ptr [[TMP18]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE6]] +; CHECK: pred.store.continue6: +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP19:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP19]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]] +; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP]], align 4 +; CHECK-NEXT: [[C_2:%.*]] = icmp eq i32 [[L]], 10 +; CHECK-NEXT: br i1 [[C_2]], label [[THEN:%.*]], label [[CONTINUE:%.*]] +; CHECK: then: +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: br label [[CONTINUE]] +; CHECK: continue: +; CHECK-NEXT: [[D:%.*]] = udiv i64 [[N]], 42 +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP9:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[CONTINUE]] ], [ 0, [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %A, i64 %iv + %l = load i32, ptr %gep + %c.2 = icmp eq i32 %l, 10 + br i1 %c.2, label %then, label %continue + +then: + store i32 1, ptr %gep + br label %continue + +continue: + %d = udiv i64 %N, 42 + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.latch, label %exit + +loop.latch: + %iv.next = add i64 %iv, 1 + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %continue ], [ 0, %loop.latch] + ret i64 %p +} + +define i64 @multi_exit_3_exit_count_with_udiv_by_value_in_block_executed_conditionally(ptr %A, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_3_exit_count_with_udiv_by_value_in_block_executed_conditionally( ; CHECK-SAME: ptr [[A:%.*]], i64 [[N:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] @@ -232,10 +410,59 @@ exit: ret i64 %p } +define i64 @multi_exit_3_exit_count_with_udiv_by_constant_in_block_executed_conditionally(ptr %A, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_3_exit_count_with_udiv_by_constant_in_block_executed_conditionally( +; CHECK-SAME: ptr [[A:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[D:%.*]] = udiv i64 [[N]], 42 +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IV]] +; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[GEP]], align 4 +; CHECK-NEXT: [[C_2:%.*]] = icmp ne i32 [[L]], 10 +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C_2]], i1 true, i1 [[C_1]] +; CHECK-NEXT: br i1 [[OR_COND]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_HEADER]], label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 0, [[LOOP_LATCH]] ], [ 1, [[LOOP_HEADER]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %A, i64 %iv + %l = load i32, ptr %gep + %c.2 = icmp eq i32 %l, 10 + br i1 %c.2, label %then, label %loop.latch + +then: + %d = udiv i64 %N, 42 + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.latch, label %exit + +loop.latch: + store i32 1, ptr %gep + %iv.next = add i64 %iv, 1 + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %then ], [ 0, %loop.latch] + ret i64 %p +} + ; FIXME: Currently miscompiled as we unconditionally execute udiv after ; vectorization. -define i64 @multi_exit_4_exit_count_with_udiv_in_latch(ptr %dst, i64 %N) { -; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_udiv_in_latch( +define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch(ptr %dst, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch( ; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) @@ -258,7 +485,7 @@ define i64 @multi_exit_4_exit_count_with_udiv_in_latch(ptr %dst, i64 %N) { ; CHECK-NEXT: store <4 x i32> , ptr [[TMP6]], align 4 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: br label [[SCALAR_PH]] ; CHECK: scalar.ph: @@ -274,7 +501,7 @@ define i64 @multi_exit_4_exit_count_with_udiv_in_latch(ptr %dst, i64 %N) { ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 ; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] ; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] -; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP7:![0-9]+]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP11:![0-9]+]] ; CHECK: exit: ; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] ; CHECK-NEXT: ret i64 [[P]] @@ -300,6 +527,72 @@ exit: ret i64 %p } +define i64 @multi_exit_4_exit_count_with_udiv_by_constant_in_latch(ptr %dst, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_udiv_by_constant_in_latch( +; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) +; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 [[N]], 42 +; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[TMP0]]) +; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[UMIN]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0 +; CHECK-NEXT: store <4 x i32> , ptr [[TMP6]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[D:%.*]] = udiv i64 [[N]], 42 +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP13:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %dst, i64 %iv + store i32 1, ptr %gep + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.latch, label %exit + +loop.latch: + %iv.next = add i64 %iv, 1 + %d = udiv i64 %N, 42 + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] + ret i64 %p +} + define void @single_exit_tc_with_udiv(ptr %dst, i64 %N) { ; CHECK-LABEL: define void @single_exit_tc_with_udiv( ; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { @@ -320,7 +613,7 @@ define void @single_exit_tc_with_udiv(ptr %dst, i64 %N) { ; CHECK-NEXT: store <4 x i32> , ptr [[TMP4]], align 4 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP14:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP1]], [[N_VEC]] ; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] @@ -334,7 +627,7 @@ define void @single_exit_tc_with_udiv(ptr %dst, i64 %N) { ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 ; CHECK-NEXT: [[D:%.*]] = udiv i64 42, [[N]] ; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] -; CHECK-NEXT: br i1 [[C_1]], label [[LOOP]], label [[EXIT]], !llvm.loop [[LOOP9:![0-9]+]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP]], label [[EXIT]], !llvm.loop [[LOOP15:![0-9]+]] ; CHECK: exit: ; CHECK-NEXT: ret void ; @@ -354,6 +647,228 @@ exit: ret void } +; FIXME: Currently miscompiled as we unconditionally execute udiv after +; vectorization. +define i64 @multi_exit_4_exit_count_with_urem_by_value_in_latch(ptr %dst, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_urem_by_value_in_latch( +; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) +; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 42, [[N]] +; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i64 [[N]], [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = sub i64 42, [[TMP1]] +; CHECK-NEXT: [[SMAX1:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP2]], i64 0) +; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[SMAX1]]) +; CHECK-NEXT: [[TMP3:%.*]] = add nuw i64 [[UMIN]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP3]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP3]], 4 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[TMP5]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[TMP7]], i32 0 +; CHECK-NEXT: store <4 x i32> , ptr [[TMP8]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[D:%.*]] = urem i64 42, [[N]] +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP17:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %dst, i64 %iv + store i32 1, ptr %gep + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.latch, label %exit + +loop.latch: + %iv.next = add i64 %iv, 1 + %d = urem i64 42, %N + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] + ret i64 %p +} + +define i64 @multi_exit_4_exit_count_with_urem_by_constant_in_latch(ptr %dst, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_urem_by_constant_in_latch( +; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 0) +; CHECK-NEXT: [[TMP0:%.*]] = udiv i64 [[N]], 42 +; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i64 [[TMP0]], 42 +; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[N]], [[TMP1]] +; CHECK-NEXT: [[SMAX1:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP2]], i64 0) +; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SMAX]], i64 [[SMAX1]]) +; CHECK-NEXT: [[TMP3:%.*]] = add nuw i64 [[UMIN]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP3]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP3]], 4 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[TMP5]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[TMP7]], i32 0 +; CHECK-NEXT: store <4 x i32> , ptr [[TMP8]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP18:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[D:%.*]] = urem i64 [[N]], 42 +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]], !llvm.loop [[LOOP19:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %dst, i64 %iv + store i32 1, ptr %gep + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.latch, label %exit + +loop.latch: + %iv.next = add i64 %iv, 1 + %d = urem i64 %N, 42 + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] + ret i64 %p +} + +define i64 @multi_exit_4_exit_count_with_srem_by_value_in_latch(ptr %dst, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_srem_by_value_in_latch( +; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[D:%.*]] = srem i64 42, [[N]] +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %dst, i64 %iv + store i32 1, ptr %gep + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.latch, label %exit + +loop.latch: + %iv.next = add i64 %iv, 1 + %d = srem i64 42, %N + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] + ret i64 %p +} + +define i64 @multi_exit_4_exit_count_with_sdiv_by_value_in_latch(ptr %dst, i64 %N) { +; CHECK-LABEL: define i64 @multi_exit_4_exit_count_with_sdiv_by_value_in_latch( +; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]] +; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 +; CHECK-NEXT: [[C_0:%.*]] = icmp slt i64 [[IV]], [[N]] +; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[D:%.*]] = sdiv i64 42, [[N]] +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV]], [[D]] +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_HEADER]], label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i64 [ 1, [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i64 [[P]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %gep = getelementptr inbounds i32, ptr %dst, i64 %iv + store i32 1, ptr %gep + %c.0 = icmp slt i64 %iv, %N + br i1 %c.0, label %loop.latch, label %exit + +loop.latch: + %iv.next = add i64 %iv, 1 + %d = sdiv i64 42, %N + %c.1 = icmp slt i64 %iv, %d + br i1 %c.1, label %loop.header, label %exit + +exit: + %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch] + ret i64 %p +} + ;. ; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} ; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} @@ -365,4 +880,14 @@ exit: ; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META1]]} ; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META1]], [[META2]]} ; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META2]], [[META1]]} +; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META1]], [[META2]]} +; CHECK: [[LOOP11]] = distinct !{[[LOOP11]], [[META2]], [[META1]]} +; CHECK: [[LOOP12]] = distinct !{[[LOOP12]], [[META1]], [[META2]]} +; CHECK: [[LOOP13]] = distinct !{[[LOOP13]], [[META2]], [[META1]]} +; CHECK: [[LOOP14]] = distinct !{[[LOOP14]], [[META1]], [[META2]]} +; CHECK: [[LOOP15]] = distinct !{[[LOOP15]], [[META2]], [[META1]]} +; CHECK: [[LOOP16]] = distinct !{[[LOOP16]], [[META1]], [[META2]]} +; CHECK: [[LOOP17]] = distinct !{[[LOOP17]], [[META2]], [[META1]]} +; CHECK: [[LOOP18]] = distinct !{[[LOOP18]], [[META1]], [[META2]]} +; CHECK: [[LOOP19]] = distinct !{[[LOOP19]], [[META2]], [[META1]]} ;. -- GitLab From b6f050fa129b08b6bc35168f0b8010742cd1ed9d Mon Sep 17 00:00:00 2001 From: David Spickett Date: Wed, 15 May 2024 11:20:58 +0100 Subject: [PATCH 327/578] [lldb] Document some more packets (#92124) Comparing a bit of the mock GDB server code to what was in the document I found these: * QLaunchArch * qSpeedTest * qSymbol qSymbol is the most mysterious but it did have some examples in a comment so I've adapted that. --- lldb/docs/resources/lldbgdbremote.md | 87 ++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/lldb/docs/resources/lldbgdbremote.md b/lldb/docs/resources/lldbgdbremote.md index 1467723fb79d..7076a75032da 100644 --- a/lldb/docs/resources/lldbgdbremote.md +++ b/lldb/docs/resources/lldbgdbremote.md @@ -867,6 +867,22 @@ error replies. **Priority To Implement:** Low. Only needed if the remote target wants to provide strings that are human readable along with an error code. +## QLaunchArch + +Set the architecture to use when launching a process for hosts that can run +multiple architecture slices that are contained in a single universal program +file. + +``` +send packet: $QLaunchArch: +``` + +The response is `OK` if the value in `` was recognised as valid +and will be used for the next launch request. `E63` if not. + +**Priority To Implement:** Only required for hosts that support program files +that contain code for multiple architectures. + ## QListThreadsInStopReply Enable the `threads:` and `thread-pcs:` data in the question-mark packet @@ -1883,6 +1899,77 @@ some platforms know, or can find out where this information is. Low if you have a debug target where all object and symbol files contain static load addresses. +## qSpeedTest + +Test the maximum speed at which packets can be sent and received. + +``` +send packet: qSpeedTest:response_size:; +read packet: data: +``` + +`` is a hex encoded unsigned number up to 64 bits in size. +The remote will respond with `data:` followed by a block of `a` characters +whose size should match ``, if the connection is stable. + +If there is an error parsing the packet, the response is `E79`. + +This packet is used by LLDB to discover how reliable the connection is by +varying the amount of data requested by `` and checking whether +the expected amount and values were received. + +**Priority to Implemment:** Not required for debugging on the same host, otherwise +low unless you know your connection quality is variable. + +## qSymbol + +Notify the remote that LLDB is ready to do symbol lookups on behalf of the +debug server. The response is the symbol name the debug server wants to know the +value of, or `OK` if the debug server does not need to know any more symbol values. + +The exchange always begins with: +``` +send packet: qSymbol:: +``` + +The `::` are delimiters for fields that may be filled in future responses. These +delimiters must be included even in the first packet sent. + +The debug server can reply one of two ways. If it doesn't need any symbol values: +``` +read packet: OK +``` + +If it does need a symbol value, it includes the ASCII hex encoded name of the +symbol: +``` +read packet: qSymbol:6578616D706C65 +``` + +This should be looked up by LLDB then sent back to the server. Include the name +again, with the vaue as a hex number: +``` +read packet: qSymbol:6578616D706C65:CAFEF00D +``` + +If LLDB cannot find the value, it should respond with only the name. Note that +the second `:` is not included here, whereas it is in the initial packet. +``` +read packet: qSymbol:6578616D706C65 +``` + +If LLDB is asked for any symbols that it cannot find, it should send the +initial `qSymbol::` again at any point where new libraries are loaded. In case +the symbol can now be resolved. + +If the debug server has requested all the symbols it wants, the final response +will be `OK` (whether they were all found or not). + +If LLDB did find all the symbols and recieves an `OK` it does not need to send +`qSymbol::` again during the debug session. + +**Priority To Implement:** Low, this is rarely used. + ## qThreadStopInfo\ Get information about why a thread, whose ID is ``, is stopped. -- GitLab From 03bdfb65617e3cf714a106fdf7a6ae7551d17bce Mon Sep 17 00:00:00 2001 From: David Spickett Date: Wed, 15 May 2024 11:25:15 +0100 Subject: [PATCH 328/578] [lldb][test][FreeBSD] Fix some concurrent event tests (#84155) A lot of `TestConcurrent*.py` expect one of the threads to crash, but we weren't checking for it properly. Possibly because signal reporting got better on FreeBSD at some point, and it now shows the same info as Linux does. ``` lldb-api :: functionalities/inferior-changed/TestInferiorChanged.py lldb-api :: functionalities/inferior-crashing/TestInferiorCrashing.py lldb-api :: functionalities/inferior-crashing/TestInferiorCrashingStep.py lldb-api :: functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py lldb-api :: functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferiorStep.py lldb-api :: functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py lldb-api :: functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py lldb-api :: functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py lldb-api :: functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py ``` Fixes #48777 `TestConcurrentTwoBreakpointsOneSignal.py` no longer fails, at least on an AWS instance, so I've removed the xfail there. --- lldb/packages/Python/lldbsuite/test/lldbutil.py | 2 +- .../concurrent_events/TestConcurrentTwoBreakpointsOneSignal.py | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/lldbutil.py b/lldb/packages/Python/lldbsuite/test/lldbutil.py index 1ec036f885e7..02ec65170f20 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbutil.py @@ -809,7 +809,7 @@ def is_thread_crashed(test, thread): thread.GetStopReason() == lldb.eStopReasonException and "EXC_BAD_ACCESS" in thread.GetStopDescription(100) ) - elif test.getPlatform() == "linux": + elif test.getPlatform() in ["linux", "freebsd"]: return ( thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex(0) diff --git a/lldb/test/API/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneSignal.py b/lldb/test/API/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneSignal.py index c66905af9e92..4960c4b241fb 100644 --- a/lldb/test/API/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneSignal.py +++ b/lldb/test/API/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointsOneSignal.py @@ -8,9 +8,6 @@ class ConcurrentTwoBreakpointsOneSignal(ConcurrentEventsBase): # Atomic sequences are not supported yet for MIPS in LLDB. @skipIf(triple="^mips") @expectedFlakeyNetBSD - @expectedFailureAll( - archs=["aarch64"], oslist=["freebsd"], bugnumber="llvm.org/pr49433" - ) def test(self): """Test two threads that trigger a breakpoint and one signal thread.""" self.build() -- GitLab From e67080df999c035d764c42aaa6d85417331ac52c Mon Sep 17 00:00:00 2001 From: Jacques Pienaar Date: Wed, 15 May 2024 03:25:51 -0700 Subject: [PATCH 329/578] [mlir][ods] Populate properties in generated builder (#90430) Previously this was only populated in the create method later. This resolves some of invalid builder paths. This may also be sufficient that type inference functions no longer have to consider whether property conversion has happened (but haven't verified that yet). This also makes Attributes corresponding to Properties as optional inside the set from attributes method. Today that is in effect what happens with Property value initialization and folks use it to define custom C++ types whose default initialization is what they want. This is the behavior users get if they use properties directly. Propagating Attributes without allowing partial setting would require iterating over the dictionary attribute considering the properties of the op type that will be created. This could also have been an additional method generated or optional behavior on the set method. But doing it consistently seems better. In terms of whats lost, it doesn't seem like anything compared to the pure Property path where Property is default value initialized and then partially overwritten (this doesn't seem to buy anything else verification wise). Default valued Properties (as specified ODS side rather than C++ side) triggered error as the containing class was not yet complete but referenced nested class, so that we couldn't have default initializer for them in the parent class. Added an additional forwarding builder to avoid needing to update call sites. This could be split out to separate change. Inlined templated function in unit test that was only used once. Moved initialization earlier where seen. --- mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 4 +- .../mlir/Dialect/MemRef/IR/MemRefOps.td | 2 +- .../mlir/Dialect/Tensor/IR/TensorOps.td | 2 +- mlir/include/mlir/IR/Operation.h | 5 +- .../Func/Transforms/OneToNFuncConversions.cpp | 6 +- mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp | 8 +- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 12 +- mlir/test/Dialect/OpenMP/invalid.mlir | 14 +-- mlir/test/Dialect/OpenMP/ops.mlir | 4 +- mlir/test/lib/Dialect/Test/TestOps.td | 7 ++ mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp | 104 ++++++++++++---- mlir/unittests/TableGen/OpBuildGen.cpp | 114 ++++++++++++++---- 12 files changed, 207 insertions(+), 75 deletions(-) diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index 4b91708ea1aa..84e67d2c11db 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -65,13 +65,13 @@ class LLVM_IntArithmeticOpWithOverflowFlag().overflowFlags = overflowFlags; + build($_builder, $_state, type, lhs, rhs); }]>, OpBuilder<(ins "Value":$lhs, "Value":$rhs, "IntegerOverflowFlags":$overflowFlags), [{ - build($_builder, $_state, lhs, rhs); $_state.getOrAddProperties().overflowFlags = overflowFlags; + build($_builder, $_state, lhs, rhs); }]> ]; diff --git a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td index 5738b6ca51c1..63e6ed059deb 100644 --- a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td +++ b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td @@ -1764,9 +1764,9 @@ def MemRef_CollapseShapeOp : MemRef_ReassociativeReshapeOp<"collapse_shape", [ "ArrayRef":$reassociation, CArg<"ArrayRef", "{}">:$attrs), [{ - build($_builder, $_state, resultType, src, attrs); $_state.addAttribute("reassociation", getReassociationIndicesAttribute($_builder, reassociation)); + build($_builder, $_state, resultType, src, attrs); }]>, OpBuilder<(ins "Type":$resultType, "Value":$src, "ArrayRef":$reassociation, diff --git a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td index a403e89a39f9..cafc3d91fd1e 100644 --- a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td +++ b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td @@ -1216,9 +1216,9 @@ def Tensor_CollapseShapeOp : Tensor_ReassociativeReshapeOp<"collapse_shape"> { "ArrayRef":$reassociation, CArg<"ArrayRef", "{}">:$attrs), [{ - build($_builder, $_state, resultType, src, attrs); $_state.addAttribute("reassociation", getReassociationIndicesAttribute($_builder, reassociation)); + build($_builder, $_state, resultType, src, attrs); }]>, OpBuilder<(ins "Type":$resultType, "Value":$src, "ArrayRef":$reassociation, diff --git a/mlir/include/mlir/IR/Operation.h b/mlir/include/mlir/IR/Operation.h index c52a6fcac10c..f0dd7c517805 100644 --- a/mlir/include/mlir/IR/Operation.h +++ b/mlir/include/mlir/IR/Operation.h @@ -916,11 +916,12 @@ public: /// operation. Returns an empty attribute if no properties are present. Attribute getPropertiesAsAttribute(); - /// Set the properties from the provided attribute. + /// Set the properties from the provided attribute. /// This is an expensive operation that can fail if the attribute is not /// matching the expectations of the properties for this operation. This is /// mostly useful for unregistered operations or used when parsing the - /// generic format. An optional diagnostic can be passed in for richer errors. + /// generic format. An optional diagnostic emitter can be passed in for richer + /// errors, if none is passed then behavior is undefined in error case. LogicalResult setPropertiesFromAttribute(Attribute attr, function_ref emitError); diff --git a/mlir/lib/Dialect/Func/Transforms/OneToNFuncConversions.cpp b/mlir/lib/Dialect/Func/Transforms/OneToNFuncConversions.cpp index c04986cad84f..a5b88338e638 100644 --- a/mlir/lib/Dialect/Func/Transforms/OneToNFuncConversions.cpp +++ b/mlir/lib/Dialect/Func/Transforms/OneToNFuncConversions.cpp @@ -40,9 +40,9 @@ public: return failure(); // Create new CallOp. - auto newOp = rewriter.create(loc, resultMapping.getConvertedTypes(), - adaptor.getFlatOperands()); - newOp->setAttrs(op->getAttrs()); + auto newOp = + rewriter.create(loc, resultMapping.getConvertedTypes(), + adaptor.getFlatOperands(), op->getAttrs()); rewriter.replaceOp(op, newOp->getResults(), resultMapping); return success(); diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp index 199e7330a233..45f39c80041c 100644 --- a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp @@ -1806,11 +1806,11 @@ void ReinterpretCastOp::build(OpBuilder &b, OperationState &result, dispatchIndexOpFoldResults(offset, dynamicOffsets, staticOffsets); dispatchIndexOpFoldResults(sizes, dynamicSizes, staticSizes); dispatchIndexOpFoldResults(strides, dynamicStrides, staticStrides); + result.addAttributes(attrs); build(b, result, resultType, source, dynamicOffsets, dynamicSizes, dynamicStrides, b.getDenseI64ArrayAttr(staticOffsets), b.getDenseI64ArrayAttr(staticSizes), b.getDenseI64ArrayAttr(staticStrides)); - result.addAttributes(attrs); } void ReinterpretCastOp::build(OpBuilder &b, OperationState &result, @@ -2483,9 +2483,9 @@ void CollapseShapeOp::build(OpBuilder &b, OperationState &result, Value src, auto srcType = llvm::cast(src.getType()); MemRefType resultType = CollapseShapeOp::computeCollapsedType(srcType, reassociation); - build(b, result, resultType, src, attrs); result.addAttribute(::mlir::getReassociationAttrName(), getReassociationIndicesAttribute(b, reassociation)); + build(b, result, resultType, src, attrs); } LogicalResult CollapseShapeOp::verify() { @@ -2781,11 +2781,11 @@ void SubViewOp::build(OpBuilder &b, OperationState &result, resultType = llvm::cast(SubViewOp::inferResultType( sourceMemRefType, staticOffsets, staticSizes, staticStrides)); } + result.addAttributes(attrs); build(b, result, resultType, source, dynamicOffsets, dynamicSizes, dynamicStrides, b.getDenseI64ArrayAttr(staticOffsets), b.getDenseI64ArrayAttr(staticSizes), b.getDenseI64ArrayAttr(staticStrides)); - result.addAttributes(attrs); } // Build a SubViewOp with mixed static and dynamic entries and inferred result @@ -3320,8 +3320,8 @@ void TransposeOp::build(OpBuilder &b, OperationState &result, Value in, // Compute result type. MemRefType resultType = inferTransposeResultType(memRefType, permutationMap); - build(b, result, resultType, in, attrs); result.addAttribute(TransposeOp::getPermutationAttrStrName(), permutation); + build(b, result, resultType, in, attrs); } // transpose $in $permutation attr-dict : type($in) `to` type(results) diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index 414bd7459af8..d3b1754cbe1c 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -1743,9 +1743,9 @@ void CollapseShapeOp::build(OpBuilder &b, OperationState &result, Value src, llvm::cast(src.getType()), getSymbolLessAffineMaps( convertReassociationIndicesToExprs(b.getContext(), reassociation))); - build(b, result, resultType, src, attrs); result.addAttribute(getReassociationAttrStrName(), getReassociationIndicesAttribute(b, reassociation)); + build(b, result, resultType, src, attrs); } template (ExtractSliceOp::inferResultType( sourceRankedTensorType, staticOffsets, staticSizes, staticStrides)); } + result.addAttributes(attrs); build(b, result, resultType, source, dynamicOffsets, dynamicSizes, dynamicStrides, b.getDenseI64ArrayAttr(staticOffsets), b.getDenseI64ArrayAttr(staticSizes), b.getDenseI64ArrayAttr(staticStrides)); - result.addAttributes(attrs); } /// Build an ExtractSliceOp with mixed static and dynamic entries and inferred @@ -2499,11 +2499,11 @@ void InsertSliceOp::build(OpBuilder &b, OperationState &result, Value source, dispatchIndexOpFoldResults(offsets, dynamicOffsets, staticOffsets); dispatchIndexOpFoldResults(sizes, dynamicSizes, staticSizes); dispatchIndexOpFoldResults(strides, dynamicStrides, staticStrides); + result.addAttributes(attrs); build(b, result, dest.getType(), source, dest, dynamicOffsets, dynamicSizes, dynamicStrides, b.getDenseI64ArrayAttr(staticOffsets), b.getDenseI64ArrayAttr(staticSizes), b.getDenseI64ArrayAttr(staticStrides)); - result.addAttributes(attrs); } /// Build an InsertSliceOp with mixed static and dynamic entries packed into a @@ -2967,10 +2967,10 @@ void PadOp::build(OpBuilder &b, OperationState &result, Type resultType, auto sourceType = llvm::cast(source.getType()); if (!resultType) resultType = inferResultType(sourceType, staticLow, staticHigh); + result.addAttributes(attrs); build(b, result, resultType, source, low, high, b.getDenseI64ArrayAttr(staticLow), b.getDenseI64ArrayAttr(staticHigh), nofold ? b.getUnitAttr() : UnitAttr()); - result.addAttributes(attrs); } void PadOp::build(OpBuilder &b, OperationState &result, Type resultType, @@ -3000,10 +3000,10 @@ void PadOp::build(OpBuilder &b, OperationState &result, Type resultType, resultType = PadOp::inferResultType(sourceType, staticLow, staticHigh); } assert(llvm::isa(resultType)); + result.addAttributes(attrs); build(b, result, resultType, source, dynamicLow, dynamicHigh, b.getDenseI64ArrayAttr(staticLow), b.getDenseI64ArrayAttr(staticHigh), nofold ? b.getUnitAttr() : UnitAttr()); - result.addAttributes(attrs); } void PadOp::build(OpBuilder &b, OperationState &result, Type resultType, @@ -3447,11 +3447,11 @@ void ParallelInsertSliceOp::build(OpBuilder &b, OperationState &result, dispatchIndexOpFoldResults(offsets, dynamicOffsets, staticOffsets); dispatchIndexOpFoldResults(sizes, dynamicSizes, staticSizes); dispatchIndexOpFoldResults(strides, dynamicStrides, staticStrides); + result.addAttributes(attrs); build(b, result, {}, source, dest, dynamicOffsets, dynamicSizes, dynamicStrides, b.getDenseI64ArrayAttr(staticOffsets), b.getDenseI64ArrayAttr(staticSizes), b.getDenseI64ArrayAttr(staticStrides)); - result.addAttributes(attrs); } /// Build an ParallelInsertSliceOp with mixed static and dynamic entries diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir index 138c2c9d418d..aee79264313e 100644 --- a/mlir/test/Dialect/OpenMP/invalid.mlir +++ b/mlir/test/Dialect/OpenMP/invalid.mlir @@ -2113,23 +2113,23 @@ func.func @omp_distribute_allocate(%data_var : memref) -> () { func.func @omp_distribute_wrapper() -> () { // expected-error @below {{op must be a loop wrapper}} - "omp.distribute"() ({ + omp.distribute { %0 = arith.constant 0 : i32 "omp.terminator"() : () -> () - }) : () -> () + } } // ----- func.func @omp_distribute_nested_wrapper(%data_var : memref) -> () { // expected-error @below {{only supported nested wrappers are 'omp.parallel' and 'omp.simd'}} - "omp.distribute"() ({ - "omp.wsloop"() ({ - %0 = arith.constant 0 : i32 - "omp.terminator"() : () -> () - }) : () -> () + omp.distribute { + "omp.wsloop"() ({ + %0 = arith.constant 0 : i32 "omp.terminator"() : () -> () }) : () -> () + "omp.terminator"() : () -> () + } } // ----- diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir index 420cb226d593..fc6d1c316531 100644 --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -521,13 +521,13 @@ func.func @omp_wsloop_pretty(%lb : index, %ub : index, %step : index, %data_var // CHECK-LABEL: omp_simd func.func @omp_simd(%lb : index, %ub : index, %step : index) -> () { // CHECK: omp.simd - "omp.simd" () ({ + omp.simd { "omp.loop_nest" (%lb, %ub, %step) ({ ^bb1(%iv2: index): "omp.yield"() : () -> () }) : (index, index, index) -> () "omp.terminator"() : () -> () - }) : () -> () + } return } diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td index befe6aa6cede..c5d0341b7de7 100644 --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -2402,6 +2402,13 @@ def TableGenBuildOp5 : TableGenBuildInferReturnTypeBaseOp< let regions = (region AnyRegion:$body); } +// Two variadic args, non variadic results, with AttrSizedOperandSegments +// Test build method generation for property conversion & type inference. +def TableGenBuildOp6 : TEST_Op<"tblgen_build_6", [AttrSizedOperandSegments]> { + let arguments = (ins Variadic:$a, Variadic:$b); + let results = (outs F32:$result); +} + //===----------------------------------------------------------------------===// // Test BufferPlacement //===----------------------------------------------------------------------===// diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp index 63fe5a809907..e013ccac5dd0 100644 --- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp +++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp @@ -1311,22 +1311,24 @@ void OpEmitter::genPropertiesSupport() { return ::mlir::failure(); } )decl"; - // TODO: properties might be optional as well. - const char *propFromAttrFmt = R"decl(; - {{ + const char *propFromAttrFmt = R"decl( auto setFromAttr = [] (auto &propStorage, ::mlir::Attribute propAttr, ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) {{ - {0}; + {0} }; {2}; - if (!attr) {{ - emitError() << "expected key entry for {1} in DictionaryAttr to set " - "Properties."; +)decl"; + const char *attrGetNoDefaultFmt = R"decl(; + if (attr && ::mlir::failed(setFromAttr(prop.{0}, attr, emitError))) return ::mlir::failure(); +)decl"; + const char *attrGetDefaultFmt = R"decl(; + if (attr) {{ + if (::mlir::failed(setFromAttr(prop.{0}, attr, emitError))) + return ::mlir::failure(); + } else {{ + prop.{0} = {1}; } - if (::mlir::failed(setFromAttr(prop.{1}, attr, emitError))) - return ::mlir::failure(); - } )decl"; for (const auto &attrOrProp : attrOrProperties) { @@ -1349,13 +1351,20 @@ void OpEmitter::genPropertiesSupport() { } os.flush(); - setPropMethod << formatv(propFromAttrFmt, + setPropMethod << "{\n" + << formatv(propFromAttrFmt, tgfmt(prop.getConvertFromAttributeCall(), &fctx.addSubst("_attr", propertyAttr) .addSubst("_storage", propertyStorage) .addSubst("_diag", propertyDiag)), name, getAttr); - + if (prop.hasDefaultValue()) { + setPropMethod << formatv(attrGetDefaultFmt, name, + prop.getDefaultValue()); + } else { + setPropMethod << formatv(attrGetNoDefaultFmt, name); + } + setPropMethod << " }\n"; } else { const auto *namedAttr = llvm::dyn_cast_if_present(attrOrProp); @@ -1376,13 +1385,8 @@ void OpEmitter::genPropertiesSupport() { setPropMethod << formatv(R"decl( {{ auto &propStorage = prop.{0}; - {2} - if (attr || /*isRequired=*/{1}) {{ - if (!attr) {{ - emitError() << "expected key entry for {0} in DictionaryAttr to set " - "Properties."; - return ::mlir::failure(); - } + {1} + if (attr) {{ auto convertedAttr = ::llvm::dyn_cast>(attr); if (convertedAttr) {{ propStorage = convertedAttr; @@ -1393,7 +1397,7 @@ void OpEmitter::genPropertiesSupport() { } } )decl", - name, namedAttr->isRequired, getAttr); + name, getAttr); } } setPropMethod << " return ::mlir::success();\n"; @@ -2650,6 +2654,21 @@ void OpEmitter::genInferredTypeCollectiveParamBuilder() { } // Result types + if (emitHelper.hasProperties()) { + // Initialize the properties from Attributes before invoking the infer + // function. + body << formatv(R"( + if (!attributes.empty()) { + ::mlir::OpaqueProperties properties = + &{1}.getOrAddProperties<{0}::Properties>(); + std::optional<::mlir::RegisteredOperationName> info = + {1}.name.getRegisteredInfo(); + if (failed(info->setOpPropertiesFromAttribute({1}.name, properties, + {1}.attributes.getDictionary({1}.getContext()), nullptr))) + ::llvm::report_fatal_error("Property conversion failed."); + })", + opClass.getClassName(), builderOpState); + } body << formatv(R"( ::llvm::SmallVector<::mlir::Type, 2> inferredReturnTypes; if (::mlir::succeeded({0}::inferReturnTypes(odsBuilder.getContext(), @@ -2879,6 +2898,22 @@ void OpEmitter::genCollectiveParamBuilder() { << "u && \"mismatched number of return types\");\n"; body << " " << builderOpState << ".addTypes(resultTypes);\n"; + if (emitHelper.hasProperties()) { + // Initialize the properties from Attributes before invoking the infer + // function. + body << formatv(R"( + if (!attributes.empty()) { + ::mlir::OpaqueProperties properties = + &{1}.getOrAddProperties<{0}::Properties>(); + std::optional<::mlir::RegisteredOperationName> info = + {1}.name.getRegisteredInfo(); + if (failed(info->setOpPropertiesFromAttribute({1}.name, properties, + {1}.attributes.getDictionary({1}.getContext()), nullptr))) + ::llvm::report_fatal_error("Property conversion failed."); + })", + opClass.getClassName(), builderOpState); + } + // Generate builder that infers type too. // TODO: Expand to handle successors. if (canInferType(op) && op.getNumSuccessors() == 0) @@ -4054,13 +4089,17 @@ OpOperandAdaptorEmitter::OpOperandAdaptorEmitter( op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments"); { SmallVector paramList; - paramList.emplace_back("::mlir::DictionaryAttr", "attrs", - attrSizedOperands ? "" : "nullptr"); - if (useProperties) - paramList.emplace_back("const Properties &", "properties", "{}"); - else + if (useProperties) { + // Properties can't be given a default constructor here due to Properties + // struct being defined in the enclosing class which isn't complete by + // here. + paramList.emplace_back("::mlir::DictionaryAttr", "attrs"); + paramList.emplace_back("const Properties &", "properties"); + } else { + paramList.emplace_back("::mlir::DictionaryAttr", "attrs", "{}"); paramList.emplace_back("const ::mlir::EmptyProperties &", "properties", "{}"); + } paramList.emplace_back("::mlir::RegionRange", "regions", "{}"); auto *baseConstructor = genericAdaptorBase.addConstructor(paramList); baseConstructor->addMemberInitializer("odsAttrs", "attrs"); @@ -4102,6 +4141,21 @@ OpOperandAdaptorEmitter::OpOperandAdaptorEmitter( "::mlir::EmptyProperties{}), " "regions"); } + + // Add forwarding constructor that constructs Properties. + if (useProperties) { + SmallVector paramList; + paramList.emplace_back("RangeT", "values"); + paramList.emplace_back("::mlir::DictionaryAttr", "attrs", + attrSizedOperands ? "" : "nullptr"); + auto *noPropertiesConstructor = + genericAdaptor.addConstructor(std::move(paramList)); + noPropertiesConstructor->addMemberInitializer( + genericAdaptor.getClassName(), "values, " + "attrs, " + "Properties{}, " + "{}"); + } } // Create constructors constructing the adaptor from an instance of the op. diff --git a/mlir/unittests/TableGen/OpBuildGen.cpp b/mlir/unittests/TableGen/OpBuildGen.cpp index c83ac9088114..94fbfa28803c 100644 --- a/mlir/unittests/TableGen/OpBuildGen.cpp +++ b/mlir/unittests/TableGen/OpBuildGen.cpp @@ -66,29 +66,44 @@ protected: EXPECT_EQ(op->getAttr(attrs[idx].getName().strref()), attrs[idx].getValue()); + EXPECT_TRUE(mlir::succeeded(concreteOp.verify())); concreteOp.erase(); } - // Helper method to test ops with inferred result types and single variadic - // input. template - void testSingleVariadicInputInferredType() { - // Test separate arg, separate param build method. - auto op = builder.create(loc, i32Ty, ValueRange{*cstI32, *cstI32}); - verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs); - - // Test collective params build method. - op = builder.create(loc, TypeRange{i32Ty}, - ValueRange{*cstI32, *cstI32}); - verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs); - - // Test build method with no result types, default value of attributes. - op = builder.create(loc, ValueRange{*cstI32, *cstI32}); - verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs); - - // Test build method with no result types and supplied attributes. - op = builder.create(loc, ValueRange{*cstI32, *cstI32}, attrs); - verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, attrs); + void verifyOp(OpTy &&concreteOp, std::vector resultTypes, + std::vector operands1, std::vector operands2, + std::vector attrs) { + ASSERT_NE(concreteOp, nullptr); + Operation *op = concreteOp.getOperation(); + + EXPECT_EQ(op->getNumResults(), resultTypes.size()); + for (unsigned idx : llvm::seq(0U, op->getNumResults())) + EXPECT_EQ(op->getResult(idx).getType(), resultTypes[idx]); + + auto operands = llvm::to_vector(llvm::concat(operands1, operands2)); + EXPECT_EQ(op->getNumOperands(), operands.size()); + for (unsigned idx : llvm::seq(0U, op->getNumOperands())) + EXPECT_EQ(op->getOperand(idx), operands[idx]); + + EXPECT_EQ(op->getAttrs().size(), attrs.size()); + if (op->getAttrs().size() != attrs.size()) { + // Simple export where there is mismatch count. + llvm::errs() << "Op attrs:\n"; + for (auto it : op->getAttrs()) + llvm::errs() << "\t" << it.getName() << " = " << it.getValue() << "\n"; + + llvm::errs() << "Expected attrs:\n"; + for (auto it : attrs) + llvm::errs() << "\t" << it.getName() << " = " << it.getValue() << "\n"; + } else { + for (unsigned idx : llvm::seq(0U, attrs.size())) + EXPECT_EQ(op->getAttr(attrs[idx].getName().strref()), + attrs[idx].getValue()); + } + + EXPECT_TRUE(mlir::succeeded(concreteOp.verify())); + concreteOp.erase(); } protected: @@ -205,13 +220,31 @@ TEST_F(OpBuildGenTest, verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, attrs); } -// The next test checks supression of ambiguous build methods for ops that +// The next test checks suppression of ambiguous build methods for ops that // have a single variadic input, and single non-variadic result, and which -// support the SameOperandsAndResultType trait and and optionally the +// support the SameOperandsAndResultType trait and optionally the // InferOpTypeInterface interface. For such ops, the ODS framework generates // build methods with no result types as they are inferred from the input types. TEST_F(OpBuildGenTest, BuildMethodsSameOperandsAndResultTypeSuppression) { - testSingleVariadicInputInferredType(); + // Test separate arg, separate param build method. + auto op = builder.create( + loc, i32Ty, ValueRange{*cstI32, *cstI32}); + verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs); + + // Test collective params build method. + op = builder.create(loc, TypeRange{i32Ty}, + ValueRange{*cstI32, *cstI32}); + verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs); + + // Test build method with no result types, default value of attributes. + op = + builder.create(loc, ValueRange{*cstI32, *cstI32}); + verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs); + + // Test build method with no result types and supplied attributes. + op = builder.create(loc, ValueRange{*cstI32, *cstI32}, + attrs); + verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, attrs); } TEST_F(OpBuildGenTest, BuildMethodsRegionsAndInferredType) { @@ -221,4 +254,41 @@ TEST_F(OpBuildGenTest, BuildMethodsRegionsAndInferredType) { verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, noAttrs); } +TEST_F(OpBuildGenTest, BuildMethodsVariadicProperties) { + // Account for conversion as part of getAttrs(). + std::vector noAttrsStorage; + auto segmentSize = builder.getNamedAttr("operandSegmentSizes", + builder.getDenseI32ArrayAttr({1, 1})); + noAttrsStorage.push_back(segmentSize); + ArrayRef noAttrs(noAttrsStorage); + std::vector attrsStorage = this->attrStorage; + attrsStorage.push_back(segmentSize); + ArrayRef attrs(attrsStorage); + + // Test separate arg, separate param build method. + auto op = builder.create( + loc, f32Ty, ValueRange{*cstI32}, ValueRange{*cstI32}); + verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs); + + // Test build method with no result types, default value of attributes. + op = builder.create(loc, ValueRange{*cstI32}, + ValueRange{*cstI32}); + verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs); + + // Test collective params build method. + op = builder.create( + loc, TypeRange{f32Ty}, ValueRange{*cstI32}, ValueRange{*cstI32}); + verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs); + + // Test build method with result types, supplied attributes. + op = builder.create( + loc, TypeRange{f32Ty}, ValueRange{*cstI32, *cstI32}, attrs); + verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, attrs); + + // Test build method with no result types and supplied attributes. + op = builder.create(loc, ValueRange{*cstI32, *cstI32}, + attrs); + verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, attrs); +} + } // namespace mlir -- GitLab From 7621a0d36465cf870769cd54035d254d409c2ce4 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Wed, 15 May 2024 11:27:06 +0100 Subject: [PATCH 330/578] [LLVM][CodeGen][SVE] Improve custom lowering for EXTRACT_SUBVECTOR. (#90963) We can extract any legal fixed length vector from a scalable vector by using VECTOR_SPLICE. --- .../Target/AArch64/AArch64ISelLowering.cpp | 59 ++++---- .../sve-extract-fixed-from-scalable-vector.ll | 48 ++---- .../AArch64/sve-extract-fixed-vector.ll | 142 +++--------------- ...e-streaming-mode-fixed-length-int-to-fp.ll | 30 ++-- 4 files changed, 77 insertions(+), 202 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 2ec9f66214b6..afa023220d35 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -13912,45 +13912,52 @@ AArch64TargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op, SDValue AArch64TargetLowering::LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG) const { - assert(Op.getValueType().isFixedLengthVector() && + EVT VT = Op.getValueType(); + assert(VT.isFixedLengthVector() && "Only cases that extract a fixed length vector are supported!"); - EVT InVT = Op.getOperand(0).getValueType(); - unsigned Idx = Op.getConstantOperandVal(1); - unsigned Size = Op.getValueSizeInBits(); // If we don't have legal types yet, do nothing - if (!DAG.getTargetLoweringInfo().isTypeLegal(InVT)) + if (!isTypeLegal(InVT)) return SDValue(); - if (InVT.isScalableVector()) { - // This will be matched by custom code during ISelDAGToDAG. - if (Idx == 0 && isPackedVectorType(InVT, DAG)) + if (InVT.is128BitVector()) { + assert(VT.is64BitVector() && "Extracting unexpected vector type!"); + unsigned Idx = Op.getConstantOperandVal(1); + + // This will get lowered to an appropriate EXTRACT_SUBREG in ISel. + if (Idx == 0) return Op; - return SDValue(); + // If this is extracting the upper 64-bits of a 128-bit vector, we match + // that directly. + if (Idx * InVT.getScalarSizeInBits() == 64 && Subtarget->isNeonAvailable()) + return Op; } - // This will get lowered to an appropriate EXTRACT_SUBREG in ISel. - if (Idx == 0 && InVT.getSizeInBits() <= 128) - return Op; - - // If this is extracting the upper 64-bits of a 128-bit vector, we match - // that directly. - if (Size == 64 && Idx * InVT.getScalarSizeInBits() == 64 && - InVT.getSizeInBits() == 128 && Subtarget->isNeonAvailable()) - return Op; - - if (useSVEForFixedLengthVectorVT(InVT, !Subtarget->isNeonAvailable())) { + if (InVT.isScalableVector() || + useSVEForFixedLengthVectorVT(InVT, !Subtarget->isNeonAvailable())) { SDLoc DL(Op); + SDValue Vec = Op.getOperand(0); + SDValue Idx = Op.getOperand(1); - EVT ContainerVT = getContainerForFixedLengthVector(DAG, InVT); - SDValue NewInVec = - convertToScalableVector(DAG, ContainerVT, Op.getOperand(0)); + EVT PackedVT = getPackedSVEVectorVT(InVT.getVectorElementType()); + if (PackedVT != InVT) { + // Pack input into the bottom part of an SVE register and try again. + SDValue Container = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, PackedVT, + DAG.getUNDEF(PackedVT), Vec, + DAG.getVectorIdxConstant(0, DL)); + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Container, Idx); + } + + // This will get matched by custom code during ISelDAGToDAG. + if (isNullConstant(Idx)) + return Op; - SDValue Splice = DAG.getNode(ISD::VECTOR_SPLICE, DL, ContainerVT, NewInVec, - NewInVec, DAG.getConstant(Idx, DL, MVT::i64)); - return convertFromScalableVector(DAG, Op.getValueType(), Splice); + assert(InVT.isScalableVector() && "Unexpected vector type!"); + // Move requested subvector to the start of the vector and try again. + SDValue Splice = DAG.getNode(ISD::VECTOR_SPLICE, DL, InVT, Vec, Vec, Idx); + return convertFromScalableVector(DAG, VT, Splice); } return SDValue(); diff --git a/llvm/test/CodeGen/AArch64/sve-extract-fixed-from-scalable-vector.ll b/llvm/test/CodeGen/AArch64/sve-extract-fixed-from-scalable-vector.ll index e91aac430110..641050ae69d9 100644 --- a/llvm/test/CodeGen/AArch64/sve-extract-fixed-from-scalable-vector.ll +++ b/llvm/test/CodeGen/AArch64/sve-extract-fixed-from-scalable-vector.ll @@ -143,15 +143,8 @@ define <4 x float> @extract_v4f32_nxv16f32_12( %arg) { define <2 x float> @extract_v2f32_nxv16f32_2( %arg) { ; CHECK-LABEL: extract_v2f32_nxv16f32_2: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG -; CHECK-NEXT: .cfi_offset w29, -16 -; CHECK-NEXT: ptrue p0.s -; CHECK-NEXT: st1w { z0.s }, p0, [sp] -; CHECK-NEXT: ldr d0, [sp, #8] -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #8 +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0 ; CHECK-NEXT: ret %ext = call <2 x float> @llvm.vector.extract.v2f32.nxv16f32( %arg, i64 2) ret <2 x float> %ext @@ -274,15 +267,8 @@ define <4 x i3> @extract_v4i3_nxv32i3_16( %arg) { define <2 x i32> @extract_v2i32_nxv16i32_2( %arg) { ; CHECK-LABEL: extract_v2i32_nxv16i32_2: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG -; CHECK-NEXT: .cfi_offset w29, -16 -; CHECK-NEXT: ptrue p0.s -; CHECK-NEXT: st1w { z0.s }, p0, [sp] -; CHECK-NEXT: ldr d0, [sp, #8] -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #8 +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0 ; CHECK-NEXT: ret %ext = call <2 x i32> @llvm.vector.extract.v2i32.nxv16i32( %arg, i64 2) ret <2 x i32> %ext @@ -314,16 +300,9 @@ define <4 x half> @extract_v4f16_nxv2f16_0( %arg) { ; CHECK-NEXT: addvl sp, sp, #-1 ; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG ; CHECK-NEXT: .cfi_offset w29, -16 -; CHECK-NEXT: cntd x8 ; CHECK-NEXT: ptrue p0.d -; CHECK-NEXT: addpl x9, sp, #6 -; CHECK-NEXT: subs x8, x8, #4 -; CHECK-NEXT: csel x8, xzr, x8, lo -; CHECK-NEXT: st1h { z0.d }, p0, [sp, #3, mul vl] -; CHECK-NEXT: cmp x8, #0 -; CHECK-NEXT: csel x8, x8, xzr, lo -; CHECK-NEXT: lsl x8, x8, #1 -; CHECK-NEXT: ldr d0, [x9, x8] +; CHECK-NEXT: st1h { z0.d }, p0, [sp] +; CHECK-NEXT: ldr d0, [sp] ; CHECK-NEXT: addvl sp, sp, #1 ; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret @@ -338,17 +317,12 @@ define <4 x half> @extract_v4f16_nxv2f16_4( %arg) { ; CHECK-NEXT: addvl sp, sp, #-1 ; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG ; CHECK-NEXT: .cfi_offset w29, -16 -; CHECK-NEXT: cntd x8 -; CHECK-NEXT: mov w9, #4 // =0x4 ; CHECK-NEXT: ptrue p0.d -; CHECK-NEXT: subs x8, x8, #4 -; CHECK-NEXT: csel x8, xzr, x8, lo -; CHECK-NEXT: st1h { z0.d }, p0, [sp, #3, mul vl] -; CHECK-NEXT: cmp x8, #4 -; CHECK-NEXT: csel x8, x8, x9, lo -; CHECK-NEXT: addpl x9, sp, #6 -; CHECK-NEXT: lsl x8, x8, #1 -; CHECK-NEXT: ldr d0, [x9, x8] +; CHECK-NEXT: ptrue p1.h +; CHECK-NEXT: st1h { z0.d }, p0, [sp] +; CHECK-NEXT: ld1h { z0.h }, p1/z, [sp] +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #8 +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0 ; CHECK-NEXT: addvl sp, sp, #1 ; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/sve-extract-fixed-vector.ll b/llvm/test/CodeGen/AArch64/sve-extract-fixed-vector.ll index 88268104889f..b05b46a75b69 100644 --- a/llvm/test/CodeGen/AArch64/sve-extract-fixed-vector.ll +++ b/llvm/test/CodeGen/AArch64/sve-extract-fixed-vector.ll @@ -15,20 +15,8 @@ define <2 x i64> @extract_v2i64_nxv2i64( %vec) nounwind { define <2 x i64> @extract_v2i64_nxv2i64_idx2( %vec) nounwind { ; CHECK-LABEL: extract_v2i64_nxv2i64_idx2: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: cntd x8 -; CHECK-NEXT: mov w9, #2 // =0x2 -; CHECK-NEXT: ptrue p0.d -; CHECK-NEXT: sub x8, x8, #2 -; CHECK-NEXT: cmp x8, #2 -; CHECK-NEXT: st1d { z0.d }, p0, [sp] -; CHECK-NEXT: csel x8, x8, x9, lo -; CHECK-NEXT: mov x9, sp -; CHECK-NEXT: lsl x8, x8, #3 -; CHECK-NEXT: ldr q0, [x9, x8] -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #16 +; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 ; CHECK-NEXT: ret %retval = call <2 x i64> @llvm.vector.extract.v2i64.nxv2i64( %vec, i64 2) ret <2 x i64> %retval @@ -48,20 +36,8 @@ define <4 x i32> @extract_v4i32_nxv4i32( %vec) nounwind { define <4 x i32> @extract_v4i32_nxv4i32_idx4( %vec) nounwind { ; CHECK-LABEL: extract_v4i32_nxv4i32_idx4: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: cntw x8 -; CHECK-NEXT: mov w9, #4 // =0x4 -; CHECK-NEXT: ptrue p0.s -; CHECK-NEXT: sub x8, x8, #4 -; CHECK-NEXT: cmp x8, #4 -; CHECK-NEXT: st1w { z0.s }, p0, [sp] -; CHECK-NEXT: csel x8, x8, x9, lo -; CHECK-NEXT: mov x9, sp -; CHECK-NEXT: lsl x8, x8, #2 -; CHECK-NEXT: ldr q0, [x9, x8] -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #16 +; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 ; CHECK-NEXT: ret %retval = call <4 x i32> @llvm.vector.extract.v4i32.nxv4i32( %vec, i64 4) ret <4 x i32> %retval @@ -82,18 +58,9 @@ define <4 x i32> @extract_v4i32_nxv2i32( %vec) nounwind #1 { define <4 x i32> @extract_v4i32_nxv2i32_idx4( %vec) nounwind #1 { ; CHECK-LABEL: extract_v4i32_nxv2i32_idx4: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: ptrue p0.d -; CHECK-NEXT: mov x8, #4 // =0x4 -; CHECK-NEXT: mov x9, sp -; CHECK-NEXT: ptrue p1.d, vl4 -; CHECK-NEXT: st1d { z0.d }, p0, [sp] -; CHECK-NEXT: ld1d { z0.d }, p1/z, [x9, x8, lsl #3] +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #32 ; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s ; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret %retval = call <4 x i32> @llvm.vector.extract.v4i32.nxv2i32( %vec, i64 4) ret <4 x i32> %retval @@ -113,20 +80,8 @@ define <8 x i16> @extract_v8i16_nxv8i16( %vec) nounwind { define <8 x i16> @extract_v8i16_nxv8i16_idx8( %vec) nounwind { ; CHECK-LABEL: extract_v8i16_nxv8i16_idx8: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: cnth x8 -; CHECK-NEXT: mov w9, #8 // =0x8 -; CHECK-NEXT: ptrue p0.h -; CHECK-NEXT: sub x8, x8, #8 -; CHECK-NEXT: cmp x8, #8 -; CHECK-NEXT: st1h { z0.h }, p0, [sp] -; CHECK-NEXT: csel x8, x8, x9, lo -; CHECK-NEXT: mov x9, sp -; CHECK-NEXT: lsl x8, x8, #1 -; CHECK-NEXT: ldr q0, [x9, x8] -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #16 +; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 ; CHECK-NEXT: ret %retval = call <8 x i16> @llvm.vector.extract.v8i16.nxv8i16( %vec, i64 8) ret <8 x i16> %retval @@ -147,18 +102,9 @@ define <8 x i16> @extract_v8i16_nxv4i16( %vec) nounwind #1 { define <8 x i16> @extract_v8i16_nxv4i16_idx8( %vec) nounwind #1 { ; CHECK-LABEL: extract_v8i16_nxv4i16_idx8: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: ptrue p0.s -; CHECK-NEXT: mov x8, #8 // =0x8 -; CHECK-NEXT: mov x9, sp -; CHECK-NEXT: ptrue p1.s, vl8 -; CHECK-NEXT: st1w { z0.s }, p0, [sp] -; CHECK-NEXT: ld1w { z0.s }, p1/z, [x9, x8, lsl #2] +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #32 ; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h ; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret %retval = call <8 x i16> @llvm.vector.extract.v8i16.nxv4i16( %vec, i64 8) ret <8 x i16> %retval @@ -180,19 +126,10 @@ define <8 x i16> @extract_v8i16_nxv2i16( %vec) nounwind #1 { define <8 x i16> @extract_v8i16_nxv2i16_idx8( %vec) nounwind #1 { ; CHECK-LABEL: extract_v8i16_nxv2i16_idx8: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: ptrue p0.d -; CHECK-NEXT: mov x8, #8 // =0x8 -; CHECK-NEXT: mov x9, sp -; CHECK-NEXT: ptrue p1.d, vl8 -; CHECK-NEXT: st1d { z0.d }, p0, [sp] -; CHECK-NEXT: ld1d { z0.d }, p1/z, [x9, x8, lsl #3] +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #64 ; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s ; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h ; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret %retval = call <8 x i16> @llvm.vector.extract.v8i16.nxv2i16( %vec, i64 8) ret <8 x i16> %retval @@ -212,19 +149,8 @@ define <16 x i8> @extract_v16i8_nxv16i8( %vec) nounwind { define <16 x i8> @extract_v16i8_nxv16i8_idx16( %vec) nounwind { ; CHECK-LABEL: extract_v16i8_nxv16i8_idx16: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: rdvl x8, #1 -; CHECK-NEXT: ptrue p0.b -; CHECK-NEXT: mov w9, #16 // =0x10 -; CHECK-NEXT: sub x8, x8, #16 -; CHECK-NEXT: cmp x8, #16 -; CHECK-NEXT: st1b { z0.b }, p0, [sp] -; CHECK-NEXT: csel x8, x8, x9, lo -; CHECK-NEXT: mov x9, sp -; CHECK-NEXT: ldr q0, [x9, x8] -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #16 +; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 ; CHECK-NEXT: ret %retval = call <16 x i8> @llvm.vector.extract.v16i8.nxv16i8( %vec, i64 16) ret <16 x i8> %retval @@ -245,18 +171,9 @@ define <16 x i8> @extract_v16i8_nxv8i8( %vec) nounwind #1 { define <16 x i8> @extract_v16i8_nxv8i8_idx16( %vec) nounwind #1 { ; CHECK-LABEL: extract_v16i8_nxv8i8_idx16: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: ptrue p0.h -; CHECK-NEXT: mov x8, #16 // =0x10 -; CHECK-NEXT: mov x9, sp -; CHECK-NEXT: ptrue p1.h, vl16 -; CHECK-NEXT: st1h { z0.h }, p0, [sp] -; CHECK-NEXT: ld1h { z0.h }, p1/z, [x9, x8, lsl #1] +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #32 ; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b ; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret %retval = call <16 x i8> @llvm.vector.extract.v16i8.nxv8i8( %vec, i64 16) ret <16 x i8> %retval @@ -278,19 +195,10 @@ define <16 x i8> @extract_v16i8_nxv4i8( %vec) nounwind #1 { define <16 x i8> @extract_v16i8_nxv4i8_idx16( %vec) nounwind #1 { ; CHECK-LABEL: extract_v16i8_nxv4i8_idx16: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: ptrue p0.s -; CHECK-NEXT: mov x8, #16 // =0x10 -; CHECK-NEXT: mov x9, sp -; CHECK-NEXT: ptrue p1.s, vl16 -; CHECK-NEXT: st1w { z0.s }, p0, [sp] -; CHECK-NEXT: ld1w { z0.s }, p1/z, [x9, x8, lsl #2] +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #64 ; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h ; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b ; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret %retval = call <16 x i8> @llvm.vector.extract.v16i8.nxv4i8( %vec, i64 16) ret <16 x i8> %retval @@ -313,17 +221,11 @@ define <16 x i8> @extract_v16i8_nxv2i8( %vec) nounwind #1 { define <16 x i8> @extract_v16i8_nxv2i8_idx16( %vec) nounwind #1 { ; CHECK-LABEL: extract_v16i8_nxv2i8_idx16: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: ptrue p0.d -; CHECK-NEXT: st1d { z0.d }, p0, [sp] -; CHECK-NEXT: ld1d { z0.d }, p0/z, [sp] +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #128 ; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s ; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h ; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b ; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret %retval = call <16 x i8> @llvm.vector.extract.v16i8.nxv2i8( %vec, i64 16) ret <16 x i8> %retval @@ -434,13 +336,8 @@ define <16 x i1> @extract_v16i1_nxv16i1( %inmask) { define <2 x i64> @extract_fixed_v2i64_nxv2i64( %vec) nounwind #0 { ; CHECK-LABEL: extract_fixed_v2i64_nxv2i64: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 -; CHECK-NEXT: ptrue p0.d -; CHECK-NEXT: st1d { z0.d }, p0, [sp] -; CHECK-NEXT: ldr q0, [sp, #16] -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #16 +; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 ; CHECK-NEXT: ret %retval = call <2 x i64> @llvm.vector.extract.v2i64.nxv2i64( %vec, i64 2) ret <2 x i64> %retval @@ -449,14 +346,9 @@ define <2 x i64> @extract_fixed_v2i64_nxv2i64( %vec) nounwind define void @extract_fixed_v4i64_nxv2i64( %vec, ptr %p) nounwind #0 { ; CHECK-LABEL: extract_fixed_v4i64_nxv2i64: ; CHECK: // %bb.0: -; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: ext z0.b, z0.b, z0.b, #32 ; CHECK-NEXT: ptrue p0.d -; CHECK-NEXT: st1d { z0.d }, p0, [sp] -; CHECK-NEXT: ld1d { z0.d }, p0/z, [sp] ; CHECK-NEXT: st1d { z0.d }, p0, [x0] -; CHECK-NEXT: addvl sp, sp, #1 -; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret %retval = call <4 x i64> @llvm.vector.extract.v4i64.nxv2i64( %vec, i64 4) store <4 x i64> %retval, ptr %p 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 b285659258f3..a9b52c93006d 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 @@ -177,18 +177,19 @@ define void @ucvtf_v8i16_v8f64(ptr %a, ptr %b) { ; CHECK-NEXT: uunpklo z1.s, z0.h ; CHECK-NEXT: ext z0.b, z0.b, z0.b, #8 ; CHECK-NEXT: uunpklo z0.s, z0.h -; CHECK-NEXT: uunpklo z2.d, z1.s -; CHECK-NEXT: ext z1.b, z1.b, z1.b, #8 -; CHECK-NEXT: uunpklo z3.d, z0.s +; CHECK-NEXT: mov z3.d, z1.d +; CHECK-NEXT: uunpklo z2.d, z0.s ; CHECK-NEXT: ext z0.b, z0.b, z0.b, #8 +; CHECK-NEXT: ext z3.b, z3.b, z1.b, #8 ; CHECK-NEXT: uunpklo z1.d, z1.s -; CHECK-NEXT: ucvtf z2.d, p0/m, z2.d ; CHECK-NEXT: uunpklo z0.d, z0.s -; CHECK-NEXT: ucvtf z3.d, p0/m, z3.d +; CHECK-NEXT: uunpklo z3.d, z3.s +; CHECK-NEXT: ucvtf z2.d, p0/m, z2.d ; CHECK-NEXT: ucvtf z1.d, p0/m, z1.d ; CHECK-NEXT: ucvtf z0.d, p0/m, z0.d -; CHECK-NEXT: stp q2, q1, [x1] -; CHECK-NEXT: stp q3, q0, [x1, #32] +; CHECK-NEXT: ucvtf z3.d, p0/m, z3.d +; CHECK-NEXT: stp q1, q3, [x1] +; CHECK-NEXT: stp q2, q0, [x1, #32] ; CHECK-NEXT: ret %op1 = load <8 x i16>, ptr %a %res = uitofp <8 x i16> %op1 to <8 x double> @@ -750,18 +751,19 @@ define void @scvtf_v8i16_v8f64(ptr %a, ptr %b) { ; CHECK-NEXT: sunpklo z1.s, z0.h ; CHECK-NEXT: ext z0.b, z0.b, z0.b, #8 ; CHECK-NEXT: sunpklo z0.s, z0.h -; CHECK-NEXT: sunpklo z2.d, z1.s -; CHECK-NEXT: ext z1.b, z1.b, z1.b, #8 -; CHECK-NEXT: sunpklo z3.d, z0.s +; CHECK-NEXT: mov z3.d, z1.d +; CHECK-NEXT: sunpklo z2.d, z0.s ; CHECK-NEXT: ext z0.b, z0.b, z0.b, #8 +; CHECK-NEXT: ext z3.b, z3.b, z1.b, #8 ; CHECK-NEXT: sunpklo z1.d, z1.s -; CHECK-NEXT: scvtf z2.d, p0/m, z2.d ; CHECK-NEXT: sunpklo z0.d, z0.s -; CHECK-NEXT: scvtf z3.d, p0/m, z3.d +; CHECK-NEXT: sunpklo z3.d, z3.s +; CHECK-NEXT: scvtf z2.d, p0/m, z2.d ; CHECK-NEXT: scvtf z1.d, p0/m, z1.d ; CHECK-NEXT: scvtf z0.d, p0/m, z0.d -; CHECK-NEXT: stp q2, q1, [x1] -; CHECK-NEXT: stp q3, q0, [x1, #32] +; CHECK-NEXT: scvtf z3.d, p0/m, z3.d +; CHECK-NEXT: stp q1, q3, [x1] +; CHECK-NEXT: stp q2, q0, [x1, #32] ; CHECK-NEXT: ret %op1 = load <8 x i16>, ptr %a %res = sitofp <8 x i16> %op1 to <8 x double> -- GitLab From eacefba9aa3d1a5181d3d49823df24aca0d2b344 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Wed, 15 May 2024 14:44:24 +0400 Subject: [PATCH 331/578] [lldb][Windows] Fixed tests TestPty and TestPtyServer (#92090) The tests TestPty and TestPtyServer use the Unix specific python builtin module termios. They are failed in case of Windows host and Linux target. Disable them for Windows host too. --- lldb/test/API/functionalities/gdb_remote_client/TestPty.py | 2 +- lldb/test/API/tools/lldb-server/TestPtyServer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestPty.py b/lldb/test/API/functionalities/gdb_remote_client/TestPty.py index 4d4dd489b294..94eeb6e3ba11 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestPty.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestPty.py @@ -5,7 +5,7 @@ from lldbsuite.test.gdbclientutils import * from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase -@skipIfWindows +@skipIf(hostoslist=["windows"]) class TestPty(GDBRemoteTestBase): server_socket_class = PtyServerSocket diff --git a/lldb/test/API/tools/lldb-server/TestPtyServer.py b/lldb/test/API/tools/lldb-server/TestPtyServer.py index aa5bd635650a..4bfcf70bfa01 100644 --- a/lldb/test/API/tools/lldb-server/TestPtyServer.py +++ b/lldb/test/API/tools/lldb-server/TestPtyServer.py @@ -7,7 +7,7 @@ from lldbgdbserverutils import * import xml.etree.ElementTree as ET -@skipIfWindows +@skipIf(hostoslist=["windows"]) class PtyServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): def setUp(self): super().setUp() -- GitLab From 3c3f6d877623d0d821f59f4ec6038b27f27ee01d Mon Sep 17 00:00:00 2001 From: Ivan Kosarev Date: Wed, 15 May 2024 13:53:38 +0300 Subject: [PATCH 332/578] [AMDGPU][AsmParser][NFC] Eliminate Match_PreferE32. (#92159) Was added in 88e0b251815563016ad50241dd592e304bc03ee5 and is unused since fcef407aa21ad5a79d66a088e6f2a66a5745725d. --- .../AMDGPU/AsmParser/AMDGPUAsmParser.cpp | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index d47a5f8ebb81..c08c35c45984 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1388,9 +1388,6 @@ private: bool IsAtomic); public: - enum AMDGPUMatchResultTy { - Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY - }; enum OperandMode { OperandMode_Default, OperandMode_NSA, @@ -5262,15 +5259,11 @@ bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, Variant); // We order match statuses from least to most specific. We use most specific // status as resulting - // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32 - if ((R == Match_Success) || - (R == Match_PreferE32) || - (R == Match_MissingFeature && Result != Match_PreferE32) || - (R == Match_InvalidOperand && Result != Match_MissingFeature - && Result != Match_PreferE32) || - (R == Match_MnemonicFail && Result != Match_InvalidOperand - && Result != Match_MissingFeature - && Result != Match_PreferE32)) { + // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature + if (R == Match_Success || R == Match_MissingFeature || + (R == Match_InvalidOperand && Result != Match_MissingFeature) || + (R == Match_MnemonicFail && Result != Match_InvalidOperand && + Result != Match_MissingFeature)) { Result = R; ErrorInfo = EI; } @@ -5316,9 +5309,6 @@ bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return Error(ErrorLoc, "invalid operand for instruction"); } - case Match_PreferE32: - return Error(IDLoc, "internal error: instruction without _e64 suffix " - "should be encoded as e32"); case Match_MnemonicFail: llvm_unreachable("Invalid instructions should have been handled already"); } -- GitLab From de18f5ecf80ef7183625c80b04445c614a17c483 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 15 May 2024 06:23:34 -0500 Subject: [PATCH 333/578] [flang][OpenMP] Remove `allocate` from `taskgroup` in test (#92173) Remove the `allocate`, because it needs to be used together with a privatizing clause. The only such clause for `taskgroup` is `task_reduction`, but it's not yet supported. --- flang/test/Lower/OpenMP/taskgroup.f90 | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/flang/test/Lower/OpenMP/taskgroup.f90 b/flang/test/Lower/OpenMP/taskgroup.f90 index 76458f1f1127..d9d262bdd2c0 100644 --- a/flang/test/Lower/OpenMP/taskgroup.f90 +++ b/flang/test/Lower/OpenMP/taskgroup.f90 @@ -1,17 +1,14 @@ -! REQUIRES: openmp_runtime - !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s +! The "allocate" clause has been removed, because it needs to be used +! together with a privatizing clause. The only such clause for "taskgroup" +! is "task_reduction", but it's not yet supported. + !CHECK-LABEL: @_QPomp_taskgroup subroutine omp_taskgroup -use omp_lib -integer :: allocated_x -!CHECK: %[[ALLOC_X_REF:.*]] = fir.alloca i32 {bindc_name = "allocated_x", uniq_name = "_QFomp_taskgroupEallocated_x"} -!CHECK-NEXT: %[[ALLOC_X_DECL:.*]]:2 = hlfir.declare %[[ALLOC_X_REF]] {uniq_name = "_QFomp_taskgroupEallocated_x"} : (!fir.ref) -> (!fir.ref, !fir.ref) -!CHECK: %[[C4:.*]] = arith.constant 4 : i64 - -!CHECK: omp.taskgroup allocate(%[[C4]] : i64 -> %[[ALLOC_X_DECL]]#1 : !fir.ref) -!$omp taskgroup allocate(omp_high_bw_mem_alloc: allocated_x) +!CHECK: omp.taskgroup +!$omp taskgroup +!CHECK: omp.task !$omp task !CHECK: fir.call @_QPwork() {{.*}}: () -> () call work() -- GitLab From e6ef836f23aa44520e0823c38e44b2f58eb5a52f Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 15 May 2024 06:45:57 -0500 Subject: [PATCH 334/578] [flang][OpenMP] Add -fopenmp-version=52 to teams.f90 (#92180) One of the functions in the test has `teams if(...)`. The `if` clause was only allowed on the `teams` directive in OpenMP 5.2. --- flang/test/Lower/OpenMP/teams.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flang/test/Lower/OpenMP/teams.f90 b/flang/test/Lower/OpenMP/teams.f90 index f122a578a6e1..b1b2e7080676 100644 --- a/flang/test/Lower/OpenMP/teams.f90 +++ b/flang/test/Lower/OpenMP/teams.f90 @@ -1,6 +1,6 @@ ! REQUIRES: openmp_runtime -! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s ! CHECK-LABEL: func @_QPteams_simple subroutine teams_simple() -- GitLab From ccbf908b0836d8e3945f9331fd3679cbc6be0be1 Mon Sep 17 00:00:00 2001 From: Jan Patrick Lehr Date: Wed, 15 May 2024 14:06:40 +0200 Subject: [PATCH 335/578] [libc] Fix GPU test build error (#92235) This fixes a build error on the AMDGPU buildbot introduced in PR https://github.com/llvm/llvm-project/pull/92172 --- libc/src/__support/StringUtil/tables/stdc_errors.h | 3 +-- libc/test/src/string/strerror_test.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libc/src/__support/StringUtil/tables/stdc_errors.h b/libc/src/__support/StringUtil/tables/stdc_errors.h index a9c152783455..6873d6bd5107 100644 --- a/libc/src/__support/StringUtil/tables/stdc_errors.h +++ b/libc/src/__support/StringUtil/tables/stdc_errors.h @@ -15,11 +15,10 @@ namespace LIBC_NAMESPACE { -LIBC_INLINE_VAR constexpr const MsgTable<4> STDC_ERRORS = { +LIBC_INLINE_VAR constexpr const MsgTable<3> STDC_ERRORS = { MsgMapping(0, "Success"), MsgMapping(EDOM, "Numerical argument out of domain"), MsgMapping(ERANGE, "Numerical result out of range"), - MsgMapping(EILSEQ, "Invalid or incomplete multibyte or wide character"), }; } // namespace LIBC_NAMESPACE diff --git a/libc/test/src/string/strerror_test.cpp b/libc/test/src/string/strerror_test.cpp index ec9827b75cfc..2d6c230573a4 100644 --- a/libc/test/src/string/strerror_test.cpp +++ b/libc/test/src/string/strerror_test.cpp @@ -97,7 +97,7 @@ TEST(LlvmLibcStrErrorTest, KnownErrors) { ".lib section in a.out corrupted", "Attempting to link in too many shared libraries", "Cannot exec a shared library directly", - "Invalid or incomplete multibyte or wide character", + "Unknown Error 84", // Unknown "Interrupted system call should be restarted", "Streams pipe error", "Too many users", -- GitLab From 1650f1b3d7f97ca95eb930984e74bdfd91b02b4e Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Wed, 15 May 2024 13:10:16 +0100 Subject: [PATCH 336/578] Fix typo "indicies" (#92232) --- clang/include/clang/AST/VTTBuilder.h | 6 +- clang/lib/AST/VTTBuilder.cpp | 2 +- clang/lib/CodeGen/CGVTT.cpp | 17 ++--- clang/lib/CodeGen/CGVTables.h | 6 +- .../command/commands/DexExpectStepOrder.py | 2 +- flang/docs/HighLevelFIR.md | 2 +- flang/test/Lower/HLFIR/forall.f90 | 2 +- libc/src/stdio/printf_core/parser.h | 2 +- .../views/mdspan/CustomTestLayouts.h | 2 +- llvm/docs/GlobalISel/GenericOpcode.rst | 4 +- llvm/include/llvm/Target/Target.td | 4 +- llvm/lib/Analysis/DependenceAnalysis.cpp | 10 +-- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 12 ++-- llvm/lib/Bitcode/Writer/ValueEnumerator.cpp | 2 +- llvm/lib/Bitcode/Writer/ValueEnumerator.h | 2 +- .../LiveDebugValues/VarLocBasedImpl.cpp | 2 +- llvm/lib/CodeGen/MLRegAllocEvictAdvisor.cpp | 2 +- llvm/lib/CodeGen/PrologEpilogInserter.cpp | 2 +- llvm/lib/Support/ELFAttributeParser.cpp | 10 +-- .../Target/AArch64/AArch64ISelLowering.cpp | 2 +- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 2 +- .../DirectX/DXILWriter/DXILBitcodeWriter.cpp | 10 +-- .../DXILWriter/DXILValueEnumerator.cpp | 2 +- .../DirectX/DXILWriter/DXILValueEnumerator.h | 2 +- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 2 +- .../Transforms/InstCombine/InstCombinePHI.cpp | 4 +- .../Scalar/SeparateConstOffsetFromGEP.cpp | 2 +- .../Utils/SampleProfileInference.cpp | 2 +- .../Transforms/Vectorize/SLPVectorizer.cpp | 64 +++++++++---------- llvm/test/CodeGen/X86/avx-vperm2x128.ll | 2 +- .../test/DebugInfo/PDB/Inputs/every-type.yaml | 4 +- ...h-directive-personalityindex-diagnostics.s | 6 +- .../InstCombine/phi-extractvalue.ll | 8 +-- .../InstCombine/phi-of-insertvalues.ll | 6 +- .../VectorCombine/X86/scalarize-vector-gep.ll | 12 ++-- .../Linalg/Transforms/Vectorization.cpp | 6 +- 36 files changed, 114 insertions(+), 113 deletions(-) diff --git a/clang/include/clang/AST/VTTBuilder.h b/clang/include/clang/AST/VTTBuilder.h index 4acbc1f9e96b..3c19e61a8701 100644 --- a/clang/include/clang/AST/VTTBuilder.h +++ b/clang/include/clang/AST/VTTBuilder.h @@ -92,7 +92,7 @@ class VTTBuilder { using AddressPointsMapTy = llvm::DenseMap; /// The sub-VTT indices for the bases of the most derived class. - llvm::DenseMap SubVTTIndicies; + llvm::DenseMap SubVTTIndices; /// The secondary virtual pointer indices of all subobjects of /// the most derived class. @@ -148,8 +148,8 @@ public: } /// Returns a reference to the sub-VTT indices. - const llvm::DenseMap &getSubVTTIndicies() const { - return SubVTTIndicies; + const llvm::DenseMap &getSubVTTIndices() const { + return SubVTTIndices; } /// Returns a reference to the secondary virtual pointer indices. diff --git a/clang/lib/AST/VTTBuilder.cpp b/clang/lib/AST/VTTBuilder.cpp index d58e87517785..464a2014c430 100644 --- a/clang/lib/AST/VTTBuilder.cpp +++ b/clang/lib/AST/VTTBuilder.cpp @@ -189,7 +189,7 @@ void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) { if (!IsPrimaryVTT) { // Remember the sub-VTT index. - SubVTTIndicies[Base] = VTTComponents.size(); + SubVTTIndices[Base] = VTTComponents.size(); } uint64_t VTableIndex = VTTVTables.size(); diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp index d2376b14dd58..4cebb750c89e 100644 --- a/clang/lib/CodeGen/CGVTT.cpp +++ b/clang/lib/CodeGen/CGVTT.cpp @@ -138,23 +138,24 @@ uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD, BaseSubobject Base) { BaseSubobjectPairTy ClassSubobjectPair(RD, Base); - SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassSubobjectPair); - if (I != SubVTTIndicies.end()) + SubVTTIndicesMapTy::iterator I = SubVTTIndices.find(ClassSubobjectPair); + if (I != SubVTTIndices.end()) return I->second; VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); - for (llvm::DenseMap::const_iterator I = - Builder.getSubVTTIndicies().begin(), - E = Builder.getSubVTTIndicies().end(); I != E; ++I) { + for (llvm::DenseMap::const_iterator + I = Builder.getSubVTTIndices().begin(), + E = Builder.getSubVTTIndices().end(); + I != E; ++I) { // Insert all indices. BaseSubobjectPairTy ClassSubobjectPair(RD, I->first); - SubVTTIndicies.insert(std::make_pair(ClassSubobjectPair, I->second)); + SubVTTIndices.insert(std::make_pair(ClassSubobjectPair, I->second)); } - I = SubVTTIndicies.find(ClassSubobjectPair); - assert(I != SubVTTIndicies.end() && "Did not find index!"); + I = SubVTTIndices.find(ClassSubobjectPair); + assert(I != SubVTTIndices.end() && "Did not find index!"); return I->second; } diff --git a/clang/lib/CodeGen/CGVTables.h b/clang/lib/CodeGen/CGVTables.h index 9d4223547050..c06bf7a525d9 100644 --- a/clang/lib/CodeGen/CGVTables.h +++ b/clang/lib/CodeGen/CGVTables.h @@ -38,10 +38,10 @@ class CodeGenVTables { typedef VTableLayout::AddressPointsMapTy VTableAddressPointsMapTy; typedef std::pair BaseSubobjectPairTy; - typedef llvm::DenseMap SubVTTIndiciesMapTy; + typedef llvm::DenseMap SubVTTIndicesMapTy; - /// SubVTTIndicies - Contains indices into the various sub-VTTs. - SubVTTIndiciesMapTy SubVTTIndicies; + /// SubVTTIndices - Contains indices into the various sub-VTTs. + SubVTTIndicesMapTy SubVTTIndices; typedef llvm::DenseMap SecondaryVirtualPointerIndicesMapTy; diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectStepOrder.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectStepOrder.py index cb5579b523dc..d6954a440f1a 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectStepOrder.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectStepOrder.py @@ -12,7 +12,7 @@ from dex.dextIR import ValueIR class DexExpectStepOrder(CommandBase): """Expect the line every `DexExpectStepOrder` is found on to be stepped on - in `order`. Each instance must have a set of unique ascending indicies. + in `order`. Each instance must have a set of unique ascending indices. DexExpectStepOrder(*order) diff --git a/flang/docs/HighLevelFIR.md b/flang/docs/HighLevelFIR.md index de8dc5a1959b..2399efcdeacd 100644 --- a/flang/docs/HighLevelFIR.md +++ b/flang/docs/HighLevelFIR.md @@ -590,7 +590,7 @@ Syntax: Note that %indices are not operands, they are the elemental region block arguments, representing the array iteration space in a one based fashion. -The choice of using one based indicies is to match Fortran default for +The choice of using one based indices is to match Fortran default for array variables, so that there is no need to generate bound adjustments when working with one based array variables in an expression. diff --git a/flang/test/Lower/HLFIR/forall.f90 b/flang/test/Lower/HLFIR/forall.f90 index 9941ed194010..c12f0c6a826b 100644 --- a/flang/test/Lower/HLFIR/forall.f90 +++ b/flang/test/Lower/HLFIR/forall.f90 @@ -144,7 +144,7 @@ subroutine test_nested_foralls() ! ifoo and ibar could depend on x since it is a module ! variable use associated. The calls in the control value ! computation cannot be hoisted from the outer forall - ! even when they do not depend on outer forall indicies. + ! even when they do not depend on outer forall indices. forall (integer(8)::j=jfoo():jbar()) x(i, j) = x(j, i) end forall diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h index eda978a83ea8..b9a8f303dd67 100644 --- a/libc/src/stdio/printf_core/parser.h +++ b/libc/src/stdio/printf_core/parser.h @@ -496,7 +496,7 @@ private: // the type of index, and returns a TypeDesc describing that type. It does not // modify cur_pos. LIBC_INLINE TypeDesc get_type_desc(size_t index) { - // index mode is assumed, and the indicies start at 1, so an index + // index mode is assumed, and the indices start at 1, so an index // of 0 is invalid. size_t local_pos = 0; diff --git a/libcxx/test/std/containers/views/mdspan/CustomTestLayouts.h b/libcxx/test/std/containers/views/mdspan/CustomTestLayouts.h index 3ac142cce3a3..588a5e9774a5 100644 --- a/libcxx/test/std/containers/views/mdspan/CustomTestLayouts.h +++ b/libcxx/test/std/containers/views/mdspan/CustomTestLayouts.h @@ -29,7 +29,7 @@ #include // Layout that wraps indices to test some idiosyncratic behavior -// - basically it is a layout_left where indicies are first wrapped i.e. i%Wrap +// - basically it is a layout_left where indices are first wrapped i.e. i%Wrap // - only accepts integers as indices // - is_always_strided and is_always_unique are false // - is_strided and is_unique are true if all extents are smaller than Wrap diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst index 52dc039df777..5c28c6fcd30f 100644 --- a/llvm/docs/GlobalISel/GenericOpcode.rst +++ b/llvm/docs/GlobalISel/GenericOpcode.rst @@ -644,7 +644,7 @@ source vector should be inserted into. The index must be a constant multiple of the second source vector's minimum vector length. If the vectors are scalable, then the index is first scaled by the runtime scaling factor. The indices inserted in the source vector must be -valid indicies of that vector. If this condition cannot be determined statically +valid indices of that vector. If this condition cannot be determined statically but is false at runtime, then the result vector is undefined. .. code-block:: none @@ -661,7 +661,7 @@ the source vector. The index must be a constant multiple of the source vector's minimum vector length. If the source vector is a scalable vector, then the index is first scaled by the runtime scaling factor. The indices extracted from the source -vector must be valid indicies of that vector. If this condition cannot be +vector must be valid indices of that vector. If this condition cannot be determined statically but is false at runtime, then the result vector is undefined. diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index 1f7dc6922f13..343323860858 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -765,8 +765,8 @@ class Instruction : InstructionEncoding { /// Should generate helper functions that help you to map a logical operand's /// index to the underlying MIOperand's index. - /// In most architectures logical operand indicies are equal to - /// MIOperand indicies, but for some CISC architectures, a logical operand + /// In most architectures logical operand indices are equal to + /// MIOperand indices, but for some CISC architectures, a logical operand /// might be consist of multiple MIOperand (e.g. a logical operand that /// uses complex address mode). bit UseLogicalOperandMappings = false; diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp index 1bce9aae09bb..e0e7dd18cd8d 100644 --- a/llvm/lib/Analysis/DependenceAnalysis.cpp +++ b/llvm/lib/Analysis/DependenceAnalysis.cpp @@ -3444,9 +3444,9 @@ bool DependenceInfo::tryDelinearizeFixedSize( // iff the subscripts are positive and are less than the range of the // dimension. if (!DisableDelinearizationChecks) { - auto AllIndiciesInRange = [&](SmallVector &DimensionSizes, - SmallVectorImpl &Subscripts, - Value *Ptr) { + auto AllIndicesInRange = [&](SmallVector &DimensionSizes, + SmallVectorImpl &Subscripts, + Value *Ptr) { size_t SSize = Subscripts.size(); for (size_t I = 1; I < SSize; ++I) { const SCEV *S = Subscripts[I]; @@ -3462,8 +3462,8 @@ bool DependenceInfo::tryDelinearizeFixedSize( return true; }; - if (!AllIndiciesInRange(SrcSizes, SrcSubscripts, SrcPtr) || - !AllIndiciesInRange(DstSizes, DstSubscripts, DstPtr)) { + if (!AllIndicesInRange(SrcSizes, SrcSubscripts, SrcPtr) || + !AllIndicesInRange(DstSizes, DstSubscripts, DstPtr)) { SrcSubscripts.clear(); DstSubscripts.clear(); return false; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 6d01e3b4d821..c4cea3d6eef2 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -986,7 +986,7 @@ void ModuleBitcodeWriter::writeTypeTable() { Stream.EnterSubblock(bitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */); SmallVector TypeVals; - uint64_t NumBits = VE.computeBitsRequiredForTypeIndicies(); + uint64_t NumBits = VE.computeBitsRequiredForTypeIndices(); // Abbrev for TYPE_CODE_OPAQUE_POINTER. auto Abbv = std::make_shared(); @@ -3721,7 +3721,7 @@ void ModuleBitcodeWriter::writeBlockInfo() { auto Abbv = std::make_shared(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_SETTYPE)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != CONSTANTS_SETTYPE_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); @@ -3741,7 +3741,7 @@ void ModuleBitcodeWriter::writeBlockInfo() { Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // cast opc Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // typeid - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != @@ -3763,7 +3763,7 @@ void ModuleBitcodeWriter::writeBlockInfo() { Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_LOAD)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Ptr Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Align Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // volatile if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != @@ -3815,7 +3815,7 @@ void ModuleBitcodeWriter::writeBlockInfo() { Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != FUNCTION_INST_CAST_ABBREV) @@ -3826,7 +3826,7 @@ void ModuleBitcodeWriter::writeBlockInfo() { Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // flags if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp index e6787e245a49..631f31cba976 100644 --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -1191,6 +1191,6 @@ unsigned ValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const { return getGlobalBasicBlockID(BB); } -uint64_t ValueEnumerator::computeBitsRequiredForTypeIndicies() const { +uint64_t ValueEnumerator::computeBitsRequiredForTypeIndices() const { return Log2_32_Ceil(getTypes().size() + 1); } diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.h b/llvm/lib/Bitcode/Writer/ValueEnumerator.h index 4b45503595f6..8348d6728a5c 100644 --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.h +++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.h @@ -234,7 +234,7 @@ public: void incorporateFunction(const Function &F); void purgeFunction(); - uint64_t computeBitsRequiredForTypeIndicies() const; + uint64_t computeBitsRequiredForTypeIndices() const; private: void OptimizeConstants(unsigned CstStart, unsigned CstEnd); diff --git a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp index bf730be00a9a..e146fb7e5768 100644 --- a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp @@ -86,7 +86,7 @@ /// lookup the VarLoc in the VarLocMap. Rather than operate directly on machine /// locations, the dataflow analysis in this pass identifies locations by their /// indices in the VarLocMap, meaning all the variable locations in a block can -/// be described by a sparse vector of VarLocMap indicies. +/// be described by a sparse vector of VarLocMap indices. /// /// All the storage for the dataflow analysis is local to the ExtendRanges /// method and passed down to helper methods. "OutLocs" and "InLocs" record the diff --git a/llvm/lib/CodeGen/MLRegAllocEvictAdvisor.cpp b/llvm/lib/CodeGen/MLRegAllocEvictAdvisor.cpp index 114e7910dc27..f3a961f88351 100644 --- a/llvm/lib/CodeGen/MLRegAllocEvictAdvisor.cpp +++ b/llvm/lib/CodeGen/MLRegAllocEvictAdvisor.cpp @@ -212,7 +212,7 @@ static const std::vector PerLiveRangeShape{1, NumberOfInterferences}; M(float, mbb_frequencies, MBBFrequencyShape, \ "A vector of machine basic block frequencies") \ M(int64_t, mbb_mapping, InstructionsShape, \ - "A vector of indicies mapping instructions to MBBs") + "A vector of indices mapping instructions to MBBs") #else #define RA_EVICT_FIRST_DEVELOPMENT_FEATURE(M) #define RA_EVICT_REST_DEVELOPMENT_FEATURES(M) diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index eaf96ec5cbde..6a72797de493 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -1444,7 +1444,7 @@ bool PEI::replaceFrameIndexDebugInstr(MachineFunction &MF, MachineInstr &MI, // pointer as the base register. if (MI.getOpcode() == TargetOpcode::STATEPOINT) { assert((!MI.isDebugValue() || OpIdx == 0) && - "Frame indicies can only appear as the first operand of a " + "Frame indices can only appear as the first operand of a " "DBG_VALUE machine instruction"); Register Reg; MachineOperand &Offset = MI.getOperand(OpIdx + 1); diff --git a/llvm/lib/Support/ELFAttributeParser.cpp b/llvm/lib/Support/ELFAttributeParser.cpp index d3100c9ebb21..26c3d54e17ad 100644 --- a/llvm/lib/Support/ELFAttributeParser.cpp +++ b/llvm/lib/Support/ELFAttributeParser.cpp @@ -154,7 +154,7 @@ Error ELFAttributeParser::parseSubsection(uint32_t length) { Twine::utohexstr(cursor.tell() - 5)); StringRef scopeName, indexName; - SmallVector indicies; + SmallVector indices; switch (tag) { case ELFAttrs::File: scopeName = "FileAttributes"; @@ -162,12 +162,12 @@ Error ELFAttributeParser::parseSubsection(uint32_t length) { case ELFAttrs::Section: scopeName = "SectionAttributes"; indexName = "Sections"; - parseIndexList(indicies); + parseIndexList(indices); break; case ELFAttrs::Symbol: scopeName = "SymbolAttributes"; indexName = "Symbols"; - parseIndexList(indicies); + parseIndexList(indices); break; default: return createStringError(errc::invalid_argument, @@ -178,8 +178,8 @@ Error ELFAttributeParser::parseSubsection(uint32_t length) { if (sw) { DictScope scope(*sw, scopeName); - if (!indicies.empty()) - sw->printList(indexName, indicies); + if (!indices.empty()) + sw->printList(indexName, indices); if (Error e = parseAttributeList(size - 5)) return e; } else if (Error e = parseAttributeList(size - 5)) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index afa023220d35..6223c211b33b 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -23881,7 +23881,7 @@ static SDValue performScatterStoreCombine(SDNode *N, SelectionDAG &DAG, // For "scalar + vector of indices", just scale the indices. This only // applies to non-temporal scatters because there's no instruction that takes - // indicies. + // indices. if (Opcode == AArch64ISD::SSTNT1_INDEX_PRED) { Offset = getScaledOffsetForBitWidth(DAG, Offset, DL, SrcElVT.getSizeInBits()); diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 8f741ffc58a8..89e83babcfef 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -7053,7 +7053,7 @@ SDValue SITargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op, SDValue ExtVal = DAG.getNode(ISD::BITCAST, SL, IntVT, DAG.getSplatBuildVector(VecVT, SL, InsVal)); - // 2. Mask off all other indicies except the required index within (1). + // 2. Mask off all other indices except the required index within (1). SDValue LHS = DAG.getNode(ISD::AND, SL, IntVT, BFM, ExtVal); // 3. Mask off the required index within the target vector. diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp index ebb269c6e6e0..87297ac86b9d 100644 --- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp +++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp @@ -958,7 +958,7 @@ void DXILBitcodeWriter::writeTypeTable() { Stream.EnterSubblock(bitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */); SmallVector TypeVals; - uint64_t NumBits = VE.computeBitsRequiredForTypeIndicies(); + uint64_t NumBits = VE.computeBitsRequiredForTypeIndices(); // Abbrev for TYPE_CODE_POINTER. auto Abbv = std::make_shared(); @@ -2747,7 +2747,7 @@ void DXILBitcodeWriter::writeBlockInfo() { auto Abbv = std::make_shared(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_SETTYPE)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, std::move(Abbv)) != CONSTANTS_SETTYPE_ABBREV) assert(false && "Unexpected abbrev ordering!"); @@ -2767,7 +2767,7 @@ void DXILBitcodeWriter::writeBlockInfo() { Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // cast opc Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // typeid - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, std::move(Abbv)) != @@ -2789,7 +2789,7 @@ void DXILBitcodeWriter::writeBlockInfo() { Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_LOAD)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Ptr Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Align Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // volatile if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, std::move(Abbv)) != @@ -2822,7 +2822,7 @@ void DXILBitcodeWriter::writeBlockInfo() { Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, std::move(Abbv)) != (unsigned)FUNCTION_INST_CAST_ABBREV) diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.cpp index d90ab968c5d3..9a8d0afa6292 100644 --- a/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.cpp +++ b/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.cpp @@ -1140,6 +1140,6 @@ unsigned ValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const { return getGlobalBasicBlockID(BB); } -uint64_t ValueEnumerator::computeBitsRequiredForTypeIndicies() const { +uint64_t ValueEnumerator::computeBitsRequiredForTypeIndices() const { return Log2_32_Ceil(getTypes().size() + 1); } diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.h b/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.h index 66a5d96080bc..f0f91c6182e3 100644 --- a/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.h +++ b/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.h @@ -236,7 +236,7 @@ public: void incorporateFunction(const Function &F); void purgeFunction(); - uint64_t computeBitsRequiredForTypeIndicies() const; + uint64_t computeBitsRequiredForTypeIndices() const; void EnumerateType(Type *T); diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 0a7483fc45b2..ad86c393ba79 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -14945,7 +14945,7 @@ static SDValue combineBVOfVecSExt(SDNode *N, SelectionDAG &DAG) { } } - // If the vector extract indicies are not correct, add the appropriate + // If the vector extract indices are not correct, add the appropriate // vector_shuffle. int TgtElemArrayIdx; int InputSize = Input.getValueType().getScalarSizeInBits(); diff --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp index 52803e9bea45..dd8eb4688d3c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -331,7 +331,7 @@ Instruction * InstCombinerImpl::foldPHIArgInsertValueInstructionIntoPHI(PHINode &PN) { auto *FirstIVI = cast(PN.getIncomingValue(0)); - // Scan to see if all operands are `insertvalue`'s with the same indicies, + // Scan to see if all operands are `insertvalue`'s with the same indices, // and all have a single use. for (Value *V : drop_begin(PN.incoming_values())) { auto *I = dyn_cast(V); @@ -371,7 +371,7 @@ Instruction * InstCombinerImpl::foldPHIArgExtractValueInstructionIntoPHI(PHINode &PN) { auto *FirstEVI = cast(PN.getIncomingValue(0)); - // Scan to see if all operands are `extractvalue`'s with the same indicies, + // Scan to see if all operands are `extractvalue`'s with the same indices, // and all have a single use. for (Value *V : drop_begin(PN.incoming_values())) { auto *I = dyn_cast(V); diff --git a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp index 9f85396cde25..1a9eaf28f6e4 100644 --- a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp +++ b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp @@ -1008,7 +1008,7 @@ bool SeparateConstOffsetFromGEP::reorderGEP(GetElementPtrInst *GEP, } IRBuilder<> Builder(GEP); - // For trivial GEP chains, we can swap the indicies. + // For trivial GEP chains, we can swap the indices. Value *NewSrc = Builder.CreateGEP( GEP->getSourceElementType(), PtrGEP->getPointerOperand(), SmallVector(GEP->indices()), "", IsChainInBounds); diff --git a/llvm/lib/Transforms/Utils/SampleProfileInference.cpp b/llvm/lib/Transforms/Utils/SampleProfileInference.cpp index 101b70d8def4..54d46117729c 100644 --- a/llvm/lib/Transforms/Utils/SampleProfileInference.cpp +++ b/llvm/lib/Transforms/Utils/SampleProfileInference.cpp @@ -1061,7 +1061,7 @@ void initializeNetwork(const ProfiParams &Params, MinCostMaxFlow &Network, assert(NumJumps > 0 && "Too few jumps in a function"); // Introducing dummy source/sink pairs to allow flow circulation. - // The nodes corresponding to blocks of the function have indicies in + // The nodes corresponding to blocks of the function have indices in // the range [0 .. 2 * NumBlocks); the dummy sources/sinks are indexed by the // next four values. uint64_t S = 2 * NumBlocks; diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 2e0a39c4b4fd..d21b5e1cc041 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -6485,7 +6485,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, const EdgeInfo &UserTreeIdx) { assert((allConstant(VL) || allSameType(VL)) && "Invalid types!"); - SmallVector ReuseShuffleIndicies; + SmallVector ReuseShuffleIndices; SmallVector UniqueValues; SmallVector NonUniqueValueVL; auto TryToFindDuplicates = [&](const InstructionsState &S, @@ -6494,19 +6494,19 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, DenseMap UniquePositions(VL.size()); for (Value *V : VL) { if (isConstant(V)) { - ReuseShuffleIndicies.emplace_back( + ReuseShuffleIndices.emplace_back( isa(V) ? PoisonMaskElem : UniqueValues.size()); UniqueValues.emplace_back(V); continue; } auto Res = UniquePositions.try_emplace(V, UniqueValues.size()); - ReuseShuffleIndicies.emplace_back(Res.first->second); + ReuseShuffleIndices.emplace_back(Res.first->second); if (Res.second) UniqueValues.emplace_back(V); } size_t NumUniqueScalarValues = UniqueValues.size(); if (NumUniqueScalarValues == VL.size()) { - ReuseShuffleIndicies.clear(); + ReuseShuffleIndices.clear(); } else { // FIXME: Reshuffing scalars is not supported yet for non-power-of-2 ops. if (UserTreeIdx.UserTE && UserTreeIdx.UserTE->isNonPowOf2Vec()) { @@ -6532,7 +6532,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, })) { unsigned PWSz = PowerOf2Ceil(UniqueValues.size()); if (PWSz == VL.size()) { - ReuseShuffleIndicies.clear(); + ReuseShuffleIndices.clear(); } else { NonUniqueValueVL.assign(UniqueValues.begin(), UniqueValues.end()); NonUniqueValueVL.append(PWSz - UniqueValues.size(), @@ -6579,7 +6579,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, LLVM_DEBUG(dbgs() << "SLP: Gathering due to max recursion depth.\n"); if (TryToFindDuplicates(S)) newTreeEntry(VL, std::nullopt /*not vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); return; } @@ -6590,7 +6590,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, LLVM_DEBUG(dbgs() << "SLP: Gathering due to scalable vector type.\n"); if (TryToFindDuplicates(S)) newTreeEntry(VL, std::nullopt /*not vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); return; } @@ -6694,7 +6694,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, LLVM_DEBUG(dbgs() << "SLP: Gathering due to C,S,B,O, small shuffle. \n"); if (TryToFindDuplicates(S)) newTreeEntry(VL, std::nullopt /*not vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); return; } @@ -6722,7 +6722,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, LLVM_DEBUG(dbgs() << "SLP: Gathering due to partial overlap.\n"); if (TryToFindDuplicates(S)) newTreeEntry(VL, std::nullopt /*not vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); return; } } else { @@ -6745,7 +6745,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, << ") is already in tree.\n"); if (TryToFindDuplicates(S)) newTreeEntry(VL, std::nullopt /*not vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); return; } } @@ -6757,7 +6757,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, LLVM_DEBUG(dbgs() << "SLP: Gathering due to gathered scalar.\n"); if (TryToFindDuplicates(S)) newTreeEntry(VL, std::nullopt /*not vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); return; } } @@ -6810,7 +6810,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, S, VL, IsScatterVectorizeUserTE, CurrentOrder, PointerOps); if (State == TreeEntry::NeedToGather) { newTreeEntry(VL, std::nullopt /*not vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); return; } @@ -6832,7 +6832,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, !BS.getScheduleData(VL0)->isPartOfBundle()) && "tryScheduleBundle should cancelScheduling on failure"); newTreeEntry(VL, std::nullopt /*not vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); NonScheduledFirst.insert(VL.front()); return; } @@ -6845,7 +6845,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, auto *PH = cast(VL0); TreeEntry *TE = - newTreeEntry(VL, Bundle, S, UserTreeIdx, ReuseShuffleIndicies); + newTreeEntry(VL, Bundle, S, UserTreeIdx, ReuseShuffleIndices); LLVM_DEBUG(dbgs() << "SLP: added a vector of PHINodes.\n"); // Keeps the reordered operands to avoid code duplication. @@ -6862,7 +6862,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, if (CurrentOrder.empty()) { LLVM_DEBUG(dbgs() << "SLP: Reusing or shuffling extract sequence.\n"); newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + 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; @@ -6881,7 +6881,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, // 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, - ReuseShuffleIndicies, CurrentOrder); + ReuseShuffleIndices, CurrentOrder); // 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; @@ -6890,7 +6890,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, return; } case Instruction::InsertElement: { - assert(ReuseShuffleIndicies.empty() && "All inserts should be unique"); + assert(ReuseShuffleIndices.empty() && "All inserts should be unique"); auto OrdCompare = [](const std::pair &P1, const std::pair &P2) { @@ -6941,12 +6941,12 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, if (CurrentOrder.empty()) { // Original loads are consecutive and does not require reordering. TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); LLVM_DEBUG(dbgs() << "SLP: added a vector of loads.\n"); } else { // Need to reorder. TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies, CurrentOrder); + ReuseShuffleIndices, CurrentOrder); LLVM_DEBUG(dbgs() << "SLP: added a vector of jumbled loads.\n"); } TE->setOperandsInOrder(); @@ -6955,10 +6955,10 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, // Vectorizing non-consecutive loads with `llvm.masked.gather`. if (CurrentOrder.empty()) { TE = newTreeEntry(VL, TreeEntry::StridedVectorize, Bundle, S, - UserTreeIdx, ReuseShuffleIndicies); + UserTreeIdx, ReuseShuffleIndices); } else { TE = newTreeEntry(VL, TreeEntry::StridedVectorize, Bundle, S, - UserTreeIdx, ReuseShuffleIndicies, CurrentOrder); + UserTreeIdx, ReuseShuffleIndices, CurrentOrder); } TE->setOperandsInOrder(); LLVM_DEBUG(dbgs() << "SLP: added a vector of strided loads.\n"); @@ -6966,7 +6966,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, case TreeEntry::ScatterVectorize: // Vectorizing non-consecutive loads with `llvm.masked.gather`. TE = newTreeEntry(VL, TreeEntry::ScatterVectorize, Bundle, S, - UserTreeIdx, ReuseShuffleIndicies); + UserTreeIdx, ReuseShuffleIndices); TE->setOperandsInOrder(); buildTree_rec(PointerOps, Depth + 1, {TE, 0}); LLVM_DEBUG(dbgs() << "SLP: added a vector of non-consecutive loads.\n"); @@ -7020,7 +7020,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, ExtraBitWidthNodes.insert(VectorizableTree.size() + 1); } TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); LLVM_DEBUG(dbgs() << "SLP: added a vector of casts.\n"); TE->setOperandsInOrder(); @@ -7039,7 +7039,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, // Check that all of the compares have the same predicate. CmpInst::Predicate P0 = cast(VL0)->getPredicate(); TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); LLVM_DEBUG(dbgs() << "SLP: added a vector of compares.\n"); ValueList Left, Right; @@ -7100,7 +7100,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, case Instruction::Or: case Instruction::Xor: { TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); LLVM_DEBUG(dbgs() << "SLP: added a vector of un/bin op.\n"); // Sort operands of the instructions so that each side is more likely to @@ -7128,7 +7128,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, } case Instruction::GetElementPtr: { TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); LLVM_DEBUG(dbgs() << "SLP: added a vector of GEPs.\n"); SmallVector Operands(2); // Prepare the operand vector for pointer operands. @@ -7194,14 +7194,14 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, if (CurrentOrder.empty()) { // Original stores are consecutive and does not require reordering. TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); TE->setOperandsInOrder(); buildTree_rec(Operands, Depth + 1, {TE, 0}); LLVM_DEBUG(dbgs() << "SLP: added a vector of stores.\n"); } else { fixupOrderingIndices(CurrentOrder); TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies, CurrentOrder); + ReuseShuffleIndices, CurrentOrder); TE->setOperandsInOrder(); buildTree_rec(Operands, Depth + 1, {TE, 0}); LLVM_DEBUG(dbgs() << "SLP: added a vector of jumbled stores.\n"); @@ -7215,7 +7215,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI); TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); // Sort operands of the instructions so that each side is more likely to // have the same opcode. if (isCommutative(VL0)) { @@ -7261,7 +7261,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, } case Instruction::ShuffleVector: { TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndicies); + ReuseShuffleIndices); LLVM_DEBUG(dbgs() << "SLP: added a ShuffleVector op.\n"); // Reorder operands if reordering would enable vectorization. @@ -12107,8 +12107,8 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy, unsigned VF = E->getVectorFactor(); bool NeedFreeze = false; - SmallVector ReuseShuffleIndicies(E->ReuseShuffleIndices.begin(), - E->ReuseShuffleIndices.end()); + SmallVector ReuseShuffleIndices(E->ReuseShuffleIndices.begin(), + E->ReuseShuffleIndices.end()); SmallVector GatheredScalars(E->Scalars.begin(), E->Scalars.end()); // Build a mask out of the reorder indices and reorder scalars per this // mask. diff --git a/llvm/test/CodeGen/X86/avx-vperm2x128.ll b/llvm/test/CodeGen/X86/avx-vperm2x128.ll index a11b92a663c4..60fab8bc6737 100644 --- a/llvm/test/CodeGen/X86/avx-vperm2x128.ll +++ b/llvm/test/CodeGen/X86/avx-vperm2x128.ll @@ -234,7 +234,7 @@ entry: ret <16 x i16> %shuffle } -;;;; Cases with undef indicies mixed in the mask +;;;; Cases with undef indices mixed in the mask define <8 x float> @shuffle_v8f32_uu67u9ub(<8 x float> %a, <8 x float> %b) nounwind uwtable readnone ssp { ; ALL-LABEL: shuffle_v8f32_uu67u9ub: diff --git a/llvm/test/DebugInfo/PDB/Inputs/every-type.yaml b/llvm/test/DebugInfo/PDB/Inputs/every-type.yaml index 191c49042be6..4cd3034fe40a 100644 --- a/llvm/test/DebugInfo/PDB/Inputs/every-type.yaml +++ b/llvm/test/DebugInfo/PDB/Inputs/every-type.yaml @@ -19,11 +19,11 @@ TpiStream: # (int, char **) [Index: 0x1003] - Kind: LF_ARGLIST ArgList: - ArgIndicies: [ 116, 0x1002 ] + ArgIndices: [ 116, 0x1002 ] # (int, double) [Index: 0x1004] - Kind: LF_ARGLIST ArgList: - ArgIndicies: [ 116, 65 ] # (int, double) + ArgIndices: [ 116, 65 ] # (int, double) # int main(int argc, char **argv) [Index: 0x1005] - Kind: LF_PROCEDURE Procedure: diff --git a/llvm/test/MC/ARM/eh-directive-personalityindex-diagnostics.s b/llvm/test/MC/ARM/eh-directive-personalityindex-diagnostics.s index 2dc2c8045a65..0158035c682c 100644 --- a/llvm/test/MC/ARM/eh-directive-personalityindex-diagnostics.s +++ b/llvm/test/MC/ARM/eh-directive-personalityindex-diagnostics.s @@ -65,10 +65,10 @@ multiple_personality: @ CHECK: .personalityindex 0 @ CHECK: ^ - .global multiple_personality_indicies - .type multiple_personality_indicies,%function + .global multiple_personality_indices + .type multiple_personality_indices,%function .thumb_func -multiple_personality_indicies: +multiple_personality_indices: .fnstart .personalityindex 0 .personalityindex 1 diff --git a/llvm/test/Transforms/InstCombine/phi-extractvalue.ll b/llvm/test/Transforms/InstCombine/phi-extractvalue.ll index 75fd4718721c..26893c178f59 100644 --- a/llvm/test/Transforms/InstCombine/phi-extractvalue.ll +++ b/llvm/test/Transforms/InstCombine/phi-extractvalue.ll @@ -131,7 +131,7 @@ end: ret i32 %r } -; But the indicies must match +; But the indices must match define i32 @test4({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) { ; CHECK-LABEL: @test4( ; CHECK-NEXT: entry: @@ -162,7 +162,7 @@ end: ret i32 %r } -; More complex aggregates are fine, too, as long as indicies match. +; More complex aggregates are fine, too, as long as indices match. define i32 @test5({{ i32, i32 }, { i32, i32 }} %agg_left, {{ i32, i32 }, { i32, i32 }} %agg_right, i1 %c) { ; CHECK-LABEL: @test5( ; CHECK-NEXT: entry: @@ -192,7 +192,7 @@ end: ret i32 %r } -; The indicies must fully match, on all levels. +; The indices must fully match, on all levels. define i32 @test6({{ i32, i32 }, { i32, i32 }} %agg_left, {{ i32, i32 }, { i32, i32 }} %agg_right, i1 %c) { ; CHECK-LABEL: @test6( ; CHECK-NEXT: entry: @@ -282,7 +282,7 @@ end: } ; Also, unlike PHI-of-insertvalues, here the base aggregates of extractvalue -; can have different types, and just checking the indicies is not enough. +; can have different types, and just checking the indices is not enough. define i32 @test9({ i32, i32 } %agg_left, { i32, { i32, i32 } } %agg_right, i1 %c) { ; CHECK-LABEL: @test9( ; CHECK-NEXT: entry: diff --git a/llvm/test/Transforms/InstCombine/phi-of-insertvalues.ll b/llvm/test/Transforms/InstCombine/phi-of-insertvalues.ll index 548fb3bc9ddb..3596ef198303 100644 --- a/llvm/test/Transforms/InstCombine/phi-of-insertvalues.ll +++ b/llvm/test/Transforms/InstCombine/phi-of-insertvalues.ll @@ -192,7 +192,7 @@ end: ret { i32, i32 } %r } -; But the indicies must match +; But the indices must match define { i32, i32 } @test6({ i32, i32 } %agg, i32 %val_left, i32 %val_right, i1 %c) { ; CHECK-LABEL: @test6( ; CHECK-NEXT: entry: @@ -223,7 +223,7 @@ end: ret { i32, i32 } %r } -; More complex aggregates are fine, too, as long as indicies match. +; More complex aggregates are fine, too, as long as indices match. define {{ i32, i32 }, { i32, i32 }} @test7({{ i32, i32 }, { i32, i32 }} %agg, i32 %val_left, i32 %val_right, i1 %c) { ; CHECK-LABEL: @test7( ; CHECK-NEXT: entry: @@ -253,7 +253,7 @@ end: ret {{ i32, i32 }, { i32, i32 }} %r } -; The indicies must fully match, on all levels. +; The indices must fully match, on all levels. define {{ i32, i32 }, { i32, i32 }} @test8({{ i32, i32 }, { i32, i32 }} %agg, i32 %val_left, i32 %val_right, i1 %c) { ; CHECK-LABEL: @test8( ; CHECK-NEXT: entry: diff --git a/llvm/test/Transforms/VectorCombine/X86/scalarize-vector-gep.ll b/llvm/test/Transforms/VectorCombine/X86/scalarize-vector-gep.ll index e227e9911bc3..ccdc007f674f 100644 --- a/llvm/test/Transforms/VectorCombine/X86/scalarize-vector-gep.ll +++ b/llvm/test/Transforms/VectorCombine/X86/scalarize-vector-gep.ll @@ -85,8 +85,8 @@ define void @both_operands_need_extraction.4elts(<4 x ptr> %baseptrs, <4 x i64> ;------------------------------------------------------------------------------- -define void @indicies_need_extraction.2elts(ptr %baseptr, <2 x i64> %indices) { -; CHECK-LABEL: @indicies_need_extraction.2elts( +define void @indices_need_extraction.2elts(ptr %baseptr, <2 x i64> %indices) { +; CHECK-LABEL: @indices_need_extraction.2elts( ; CHECK-NEXT: [[PTRS:%.*]] = getelementptr inbounds i64, ptr [[BASEPTR:%.*]], <2 x i64> [[INDICES:%.*]] ; CHECK-NEXT: [[PTR_0:%.*]] = extractelement <2 x ptr> [[PTRS]], i64 0 ; CHECK-NEXT: call void @use(ptr [[PTR_0]]) @@ -105,8 +105,8 @@ define void @indicies_need_extraction.2elts(ptr %baseptr, <2 x i64> %indices) { ret void } -define void @indicies_need_extraction.3elts(ptr %baseptr, <3 x i64> %indices) { -; CHECK-LABEL: @indicies_need_extraction.3elts( +define void @indices_need_extraction.3elts(ptr %baseptr, <3 x i64> %indices) { +; CHECK-LABEL: @indices_need_extraction.3elts( ; CHECK-NEXT: [[PTRS:%.*]] = getelementptr inbounds i64, ptr [[BASEPTR:%.*]], <3 x i64> [[INDICES:%.*]] ; CHECK-NEXT: [[PTR_0:%.*]] = extractelement <3 x ptr> [[PTRS]], i64 0 ; CHECK-NEXT: call void @use(ptr [[PTR_0]]) @@ -130,8 +130,8 @@ define void @indicies_need_extraction.3elts(ptr %baseptr, <3 x i64> %indices) { ret void } -define void @indicies_need_extraction.4elts(ptr %baseptr, <4 x i64> %indices) { -; CHECK-LABEL: @indicies_need_extraction.4elts( +define void @indices_need_extraction.4elts(ptr %baseptr, <4 x i64> %indices) { +; CHECK-LABEL: @indices_need_extraction.4elts( ; CHECK-NEXT: [[PTRS:%.*]] = getelementptr inbounds i64, ptr [[BASEPTR:%.*]], <4 x i64> [[INDICES:%.*]] ; CHECK-NEXT: [[PTR_0:%.*]] = extractelement <4 x ptr> [[PTRS]], i64 0 ; CHECK-NEXT: call void @use(ptr [[PTR_0]]) diff --git a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp index 7b4507c52e02..511835a226e7 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp @@ -3385,13 +3385,13 @@ struct Conv1DGenerator auto rhsSize = cast(rhs.getType()).getShape()[0]; auto resSize = cast(res.getType()).getShape()[1]; - SmallVector indicies; + SmallVector indices; for (int i = 0; i < resSize / rhsSize; ++i) { for (int j = 0; j < rhsSize; ++j) - indicies.push_back(j); + indices.push_back(j); } - rhs = rewriter.create(loc, rhs, rhs, indicies); + rhs = rewriter.create(loc, rhs, rhs, indices); } // Broadcast the filter to match the output vector rhs = rewriter.create( -- GitLab From 398162ddbcf741c49e86bef2ef4aaa3fd0213916 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 15 May 2024 07:12:25 -0500 Subject: [PATCH 337/578] [libc] Fix typo in test message --- libc/test/src/string/strerror_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/test/src/string/strerror_test.cpp b/libc/test/src/string/strerror_test.cpp index 2d6c230573a4..cfc79481699b 100644 --- a/libc/test/src/string/strerror_test.cpp +++ b/libc/test/src/string/strerror_test.cpp @@ -97,7 +97,7 @@ TEST(LlvmLibcStrErrorTest, KnownErrors) { ".lib section in a.out corrupted", "Attempting to link in too many shared libraries", "Cannot exec a shared library directly", - "Unknown Error 84", // Unknown + "Unknown error 84", // Unknown "Interrupted system call should be restarted", "Streams pipe error", "Too many users", -- GitLab From 3b5a121a2478e586f59e3277d04d17fb63be5d76 Mon Sep 17 00:00:00 2001 From: Julian Schmidt Date: Wed, 15 May 2024 14:35:07 +0200 Subject: [PATCH 338/578] [clang-tidy][NFC] replace comparison of begin and end iterators with range empty (#91994) Improves readability by changing comparisons of `*_begin` and `*_end` iterators into `.empty()` on their range. --- .../clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp | 3 +-- .../MisleadingCaptureDefaultByValueCheck.cpp | 3 +-- clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp | 4 +--- .../clang-tidy/modernize/UseConstraintsCheck.cpp | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp index ca1ae551cc63..2fca7ae2e7ee 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp @@ -171,8 +171,7 @@ void SuspiciousEnumUsageCheck::check(const MatchFinder::MatchResult &Result) { // Skip when one of the parameters is an empty enum. The // hasDisjointValueRange function could not decide the values properly in // case of an empty enum. - if (EnumDec->enumerator_begin() == EnumDec->enumerator_end() || - OtherEnumDec->enumerator_begin() == OtherEnumDec->enumerator_end()) + if (EnumDec->enumerators().empty() || OtherEnumDec->enumerators().empty()) return; if (!hasDisjointValueRange(EnumDec, OtherEnumDec)) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MisleadingCaptureDefaultByValueCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MisleadingCaptureDefaultByValueCheck.cpp index 00dfa17a1ccf..5dee7f91a934 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MisleadingCaptureDefaultByValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MisleadingCaptureDefaultByValueCheck.cpp @@ -67,8 +67,7 @@ static std::string createReplacementText(const LambdaExpr *Lambda) { AppendName("this"); } } - if (!Replacement.empty() && - Lambda->explicit_capture_begin() != Lambda->explicit_capture_end()) { + if (!Replacement.empty() && !Lambda->explicit_captures().empty()) { // Add back separator if we are adding explicit capture variables. Stream << ", "; } diff --git a/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp index 3f1d2f9f5809..c2d9286312dc 100644 --- a/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp @@ -192,9 +192,7 @@ void UnusedParametersCheck::check(const MatchFinder::MatchResult &Result) { // In non-strict mode ignore function definitions with empty bodies // (constructor initializer counts for non-empty body). - if (StrictMode || - (Function->getBody()->child_begin() != - Function->getBody()->child_end()) || + if (StrictMode || !Function->getBody()->children().empty() || (isa(Function) && cast(Function)->getNumCtorInitializers() > 0)) warnOnUnusedParameter(Result, Function, I); diff --git a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp index 6d7d1d6b87c6..1585925ee996 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp @@ -254,7 +254,7 @@ findInsertionForConstraint(const FunctionDecl *Function, ASTContext &Context) { return utils::lexer::findPreviousTokenKind(Init->getSourceLocation(), SM, LangOpts, tok::colon); } - if (Constructor->init_begin() != Constructor->init_end()) + if (!Constructor->inits().empty()) return std::nullopt; } if (Function->isDeleted()) { -- GitLab From 8a71284cb9463a90fab0d9e8edbeb5d879531e32 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 15 May 2024 13:43:27 +0100 Subject: [PATCH 339/578] [MC][X86] Cleanup check prefixes identified in #92248 Avoid using numbers as check prefix - replace with actual triple config names where possible --- llvm/test/MC/X86/abs8.s | 12 +- .../test/MC/X86/align-branch-variant-symbol.s | 33 ++-- llvm/test/MC/X86/data-prefix-fail.s | 34 ++-- llvm/test/MC/X86/displacement-overflow.s | 12 +- llvm/test/MC/X86/dwarf-segment-register.s | 28 +-- llvm/test/MC/X86/index-operations.s | 162 ++++++++-------- llvm/test/MC/X86/ret.s | 182 +++++++++--------- llvm/test/MC/X86/x86_errors.s | 158 +++++++-------- 8 files changed, 310 insertions(+), 311 deletions(-) diff --git a/llvm/test/MC/X86/abs8.s b/llvm/test/MC/X86/abs8.s index b933c9ddff90..71936acb3740 100644 --- a/llvm/test/MC/X86/abs8.s +++ b/llvm/test/MC/X86/abs8.s @@ -1,8 +1,8 @@ -// RUN: llvm-mc -filetype=obj %s -o - -triple i686-pc-linux | llvm-objdump --no-print-imm-hex -d -r - | FileCheck --check-prefix=32 %s -// RUN: llvm-mc -filetype=obj %s -o - -triple x86_64-pc-linux | llvm-objdump --no-print-imm-hex -d -r - | FileCheck --check-prefix=64 %s +// RUN: llvm-mc -filetype=obj %s -o - -triple i686-pc-linux | llvm-objdump --no-print-imm-hex -d -r - | FileCheck --check-prefix=X86 %s +// RUN: llvm-mc -filetype=obj %s -o - -triple x86_64-pc-linux | llvm-objdump --no-print-imm-hex -d -r - | FileCheck --check-prefix=X64 %s -// 32: 0: 83 ff 00 cmpl $0, %edi -// 32: 00000002: R_386_8 foo -// 64: 0: 83 ff 00 cmpl $0, %edi -// 64: 0000000000000002: R_X86_64_8 foo +// X86: 0: 83 ff 00 cmpl $0, %edi +// X86: 00000002: R_386_8 foo +// X64: 0: 83 ff 00 cmpl $0, %edi +// X64: 0000000000000002: R_X86_64_8 foo cmp $foo@ABS8, %edi diff --git a/llvm/test/MC/X86/align-branch-variant-symbol.s b/llvm/test/MC/X86/align-branch-variant-symbol.s index 53afdf58bff3..a1b7b895a354 100644 --- a/llvm/test/MC/X86/align-branch-variant-symbol.s +++ b/llvm/test/MC/X86/align-branch-variant-symbol.s @@ -1,6 +1,5 @@ -# RUN: llvm-mc -filetype=obj -triple x86_64 --x86-align-branch-boundary=32 --x86-align-branch=call+indirect %s | llvm-objdump -d --no-show-raw-insn - | FileCheck %s --check-prefixes=64BIT,CHECK - -# RUN: llvm-mc -filetype=obj -triple i386 --x86-align-branch-boundary=32 --x86-align-branch=call+indirect %s | llvm-objdump -d --no-show-raw-insn - | FileCheck %s --check-prefixes=32BIT,CHECK +# RUN: llvm-mc -filetype=obj -triple x86_64 --x86-align-branch-boundary=32 --x86-align-branch=call+indirect %s | llvm-objdump -d --no-show-raw-insn - | FileCheck %s --check-prefixes=CHECK,X64 +# RUN: llvm-mc -filetype=obj -triple i386 --x86-align-branch-boundary=32 --x86-align-branch=call+indirect %s | llvm-objdump -d --no-show-raw-insn - | FileCheck %s --check-prefixes=CHECK,X86 # Exercise cases where the instruction to be aligned has a variant symbol # operand, and we can't add before it since linker may rewrite it. @@ -14,8 +13,8 @@ foo: int3 .endr # CHECK: 1d: int3 - # 64BIT: 1e: callq - # 32BIT: 1e: calll + # X64: 1e: callq + # X86: 1e: calll # CHECK: 23: int3 call ___tls_get_addr@PLT int3 @@ -25,10 +24,10 @@ foo: int3 .endr # CHECK: 5d: int3 - # 64BIT: 5e: callq *(%ecx) - # 64BIT: 65: int3 - # 32BIT: 5e: calll *(%ecx) - # 32BIT: 64: int3 + # X64: 5e: callq *(%ecx) + # X64: 65: int3 + # X86: 5e: calll *(%ecx) + # X86: 64: int3 call *___tls_get_addr@GOT(%ecx) int3 @@ -37,10 +36,10 @@ foo: int3 .endr # CHECK: 9d: int3 - # 64BIT: 9e: callq *(%eax) - # 64BIT: a1: int3 - # 32BIT: 9e: calll *(%eax) - # 32BIT: a0: int3 + # X64: 9e: callq *(%eax) + # X64: a1: int3 + # X86: 9e: calll *(%eax) + # X86: a0: int3 call *foo@tlscall(%eax) int3 @@ -49,9 +48,9 @@ foo: int3 .endr # CHECK: dd: int3 - # 64BIT: de: jmpq *(%eax) - # 64BIT: e1: int3 - # 32BIT: de: jmpl *(%eax) - # 32BIT: e0: int3 + # X64: de: jmpq *(%eax) + # X64: e1: int3 + # X86: de: jmpl *(%eax) + # X86: e0: int3 jmp *foo@tlscall(%eax) int3 diff --git a/llvm/test/MC/X86/data-prefix-fail.s b/llvm/test/MC/X86/data-prefix-fail.s index bd5b62ddc9be..3088864fc909 100644 --- a/llvm/test/MC/X86/data-prefix-fail.s +++ b/llvm/test/MC/X86/data-prefix-fail.s @@ -1,30 +1,30 @@ -// RUN: not llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=64 %s +// RUN: not llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=X86-64 %s // RUN: FileCheck --check-prefix=ERR64 < %t.err %s -// RUN: not llvm-mc -triple i386-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=32 %s +// RUN: not llvm-mc -triple i386-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=X86-32 %s // RUN: FileCheck --check-prefix=ERR32 < %t.err %s -// RUN: not llvm-mc -triple i386-unknown-unknown-code16 --show-encoding %s 2> %t.err | FileCheck --check-prefix=16 %s +// RUN: not llvm-mc -triple i386-unknown-unknown-code16 --show-encoding %s 2> %t.err | FileCheck --check-prefix=X86-16 %s // RUN: FileCheck --check-prefix=ERR16 < %t.err %s // ERR64: error: 'data32' is not supported in 64-bit mode // ERR32: error: redundant data32 prefix -// 16: lgdtl 0 -// 16-SAME: encoding: [0x66,0x0f,0x01,0x16,0x00,0x00] +// X86-16: lgdtl 0 +// X86-16-SAME: encoding: [0x66,0x0f,0x01,0x16,0x00,0x00] data32 lgdt 0 -// 64: data16 -// 64: encoding: [0x66] -// 64: lgdtq 0 -// 64: encoding: [0x0f,0x01,0x14,0x25,0x00,0x00,0x00,0x00] -// 32: data16 -// 32: encoding: [0x66] -// 32: lgdtl 0 -// 32: encoding: [0x0f,0x01,0x15,0x00,0x00,0x00,0x00] +// X86-64: data16 +// X86-64: encoding: [0x66] +// X86-64: lgdtq 0 +// X86-64: encoding: [0x0f,0x01,0x14,0x25,0x00,0x00,0x00,0x00] +// X86-32: data16 +// X86-32: encoding: [0x66] +// X86-32: lgdtl 0 +// X86-32: encoding: [0x0f,0x01,0x15,0x00,0x00,0x00,0x00] // ERR16: error: redundant data16 prefix data16 lgdt 0 -// 64: data16 # encoding: [0x66] -// 64-NEXT: callq 0 # encoding: [0xe8,A,A,A,A] -// 32: data16 # encoding: [0x66] -// 32-NEXT: calll 0 # encoding: [0xe8,A,A,A,A] +// X86-64: data16 # encoding: [0x66] +// X86-64-NEXT: callq 0 # encoding: [0xe8,A,A,A,A] +// X86-32: data16 # encoding: [0x66] +// X86-32-NEXT: calll 0 # encoding: [0xe8,A,A,A,A] // ERR16: {{.*}}.s:[[#@LINE+1]]:1: error: redundant data16 prefix data16 call 0 diff --git a/llvm/test/MC/X86/displacement-overflow.s b/llvm/test/MC/X86/displacement-overflow.s index 2882147af482..933f98cb21fc 100644 --- a/llvm/test/MC/X86/displacement-overflow.s +++ b/llvm/test/MC/X86/displacement-overflow.s @@ -1,14 +1,14 @@ -# RUN: not llvm-mc -triple=x86_64 %s 2>&1 | FileCheck %s --check-prefixes=CHECK,64 --implicit-check-not=error: --implicit-check-not=warning: -# RUN: llvm-mc -triple=i686 --defsym A16=1 %s 2>&1 | FileCheck %s --check-prefixes=CHECK,32 --implicit-check-not=error: --implicit-check-not=warning: +# RUN: not llvm-mc -triple=x86_64 %s 2>&1 | FileCheck %s --check-prefixes=CHECK,X64 --implicit-check-not=error: --implicit-check-not=warning: +# RUN: llvm-mc -triple=i686 --defsym A16=1 %s 2>&1 | FileCheck %s --check-prefixes=CHECK,X86 --implicit-check-not=error: --implicit-check-not=warning: .ifndef A16 movq 0x80000000-1(%rip), %rax leaq -0x80000000(%rip), %rax -# 64: [[#@LINE+1]]:17: error: displacement 2147483648 is not within [-2147483648, 2147483647] +# X64: [[#@LINE+1]]:17: error: displacement 2147483648 is not within [-2147483648, 2147483647] movq 0x80000000(%rip), %rax -# 64: [[#@LINE+1]]:18: error: displacement -2147483649 is not within [-2147483648, 2147483647] +# X64: [[#@LINE+1]]:18: error: displacement -2147483649 is not within [-2147483648, 2147483647] leaq -0x80000001(%rip), %rax .endif @@ -31,8 +31,8 @@ leal -0xffffffff-2(%eax), %eax movw $0, 0xffff(%bp) movw $0, -0xffff(%si) -# 32: [[#@LINE+1]]:19: warning: displacement 65536 shortened to 16-bit signed 0 +# X86: [[#@LINE+1]]:19: warning: displacement 65536 shortened to 16-bit signed 0 movw $0, 0xffff+1(%bp) -# 32: [[#@LINE+1]]:20: warning: displacement -65536 shortened to 16-bit signed 0 +# X86: [[#@LINE+1]]:20: warning: displacement -65536 shortened to 16-bit signed 0 movw $0, -0xffff-1(%si) .endif diff --git a/llvm/test/MC/X86/dwarf-segment-register.s b/llvm/test/MC/X86/dwarf-segment-register.s index a68576807470..5482588df821 100644 --- a/llvm/test/MC/X86/dwarf-segment-register.s +++ b/llvm/test/MC/X86/dwarf-segment-register.s @@ -1,7 +1,7 @@ // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t.64 -// RUN: llvm-objdump --dwarf=frames %t.64 | FileCheck %s --check-prefixes=64,CHECK +// RUN: llvm-objdump --dwarf=frames %t.64 | FileCheck %s --check-prefixes=X64,CHECK // RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -o %t.32 -// RUN: llvm-objdump --dwarf=frames %t.32 | FileCheck %s --check-prefixes=32,CHECK +// RUN: llvm-objdump --dwarf=frames %t.32 | FileCheck %s --check-prefixes=X86,CHECK .cfi_startproc .cfi_offset %cs, -40 @@ -12,26 +12,26 @@ .cfi_offset %gs, 0 .cfi_endproc -// 64: reg51 -// 32: reg41 +// X64: reg51 +// X86: reg41 // CHECK-SAME: -40 -// 64: reg53 -// 32: reg43 +// X64: reg53 +// X86: reg43 // CHECK-SAME: -32 -// 64: reg52 -// 32: reg42 +// X64: reg52 +// X86: reg42 // CHECK-SAME: -24 -// 64: reg50 -// 32: reg40 +// X64: reg50 +// X86: reg40 // CHECK-SAME: -16 -// 64: reg54 -// 32: reg44 +// X64: reg54 +// X86: reg44 // CHECK-SAME: -8 -// 64: reg55 -// 32: reg45 +// X64: reg55 +// X86: reg45 // CHECK-SAME: 0 diff --git a/llvm/test/MC/X86/index-operations.s b/llvm/test/MC/X86/index-operations.s index 59498b0ced12..c425ba8057c5 100644 --- a/llvm/test/MC/X86/index-operations.s +++ b/llvm/test/MC/X86/index-operations.s @@ -1,34 +1,34 @@ -// RUN: not llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=64 %s +// RUN: not llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=X86-64 %s // RUN: FileCheck --input-file=%t.err %s --check-prefix=ERR64 --implicit-check-not=error: -// RUN: not llvm-mc -triple i386-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=32 %s +// RUN: not llvm-mc -triple i386-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=X86-32 %s // RUN: FileCheck --check-prefix=ERR32 < %t.err %s -// RUN: not llvm-mc -triple i386-unknown-unknown-code16 --show-encoding %s 2> %t.err | FileCheck --check-prefix=16 %s +// RUN: not llvm-mc -triple i386-unknown-unknown-code16 --show-encoding %s 2> %t.err | FileCheck --check-prefix=X86-16 %s // RUN: FileCheck --check-prefix=ERR16 < %t.err %s lodsb -// 64: lodsb (%rsi), %al # encoding: [0xac] -// 32: lodsb (%esi), %al # encoding: [0xac] -// 16: lodsb (%si), %al # encoding: [0xac] +// X86-64: lodsb (%rsi), %al # encoding: [0xac] +// X86-32: lodsb (%esi), %al # encoding: [0xac] +// X86-16: lodsb (%si), %al # encoding: [0xac] lodsb (%rsi), %al -// 64: lodsb (%rsi), %al # encoding: [0xac] +// X86-64: lodsb (%rsi), %al # encoding: [0xac] // ERR32: 64-bit // ERR16: 64-bit lodsb (%esi), %al -// 64: lodsb (%esi), %al # encoding: [0x67,0xac] -// 32: lodsb (%esi), %al # encoding: [0xac] -// 16: lodsb (%esi), %al # encoding: [0x67,0xac] +// X86-64: lodsb (%esi), %al # encoding: [0x67,0xac] +// X86-32: lodsb (%esi), %al # encoding: [0xac] +// X86-16: lodsb (%esi), %al # encoding: [0x67,0xac] lodsb (%si), %al // ERR64: [[#@LINE-1]]:[[#]]: error: invalid 16-bit base register -// 32: lodsb (%si), %al # encoding: [0x67,0xac] -// 16: lodsb (%si), %al # encoding: [0xac] +// X86-32: lodsb (%si), %al # encoding: [0x67,0xac] +// X86-16: lodsb (%si), %al # encoding: [0xac] lodsl %gs:(%esi) -// 64: lodsl %gs:(%esi), %eax # encoding: [0x67,0x65,0xad] -// 32: lodsl %gs:(%esi), %eax # encoding: [0x65,0xad] -// 16: lodsl %gs:(%esi), %eax # encoding: [0x67,0x65,0x66,0xad] +// X86-64: lodsl %gs:(%esi), %eax # encoding: [0x67,0x65,0xad] +// X86-32: lodsl %gs:(%esi), %eax # encoding: [0x65,0xad] +// X86-16: lodsl %gs:(%esi), %eax # encoding: [0x67,0x65,0x66,0xad] lodsl (%edi), %eax // ERR64: [[#@LINE-1]]:[[#]]: error: invalid operand @@ -41,19 +41,19 @@ lodsl 44(%edi), %eax // ERR16: invalid operand lods (%esi), %ax -// 64: lodsw (%esi), %ax # encoding: [0x67,0x66,0xad] -// 32: lodsw (%esi), %ax # encoding: [0x66,0xad] -// 16: lodsw (%esi), %ax # encoding: [0x67,0xad] +// X86-64: lodsw (%esi), %ax # encoding: [0x67,0x66,0xad] +// X86-32: lodsw (%esi), %ax # encoding: [0x66,0xad] +// X86-16: lodsw (%esi), %ax # encoding: [0x67,0xad] stosw -// 64: stosw %ax, %es:(%rdi) # encoding: [0x66,0xab] -// 32: stosw %ax, %es:(%edi) # encoding: [0x66,0xab] -// 16: stosw %ax, %es:(%di) # encoding: [0xab] +// X86-64: stosw %ax, %es:(%rdi) # encoding: [0x66,0xab] +// X86-32: stosw %ax, %es:(%edi) # encoding: [0x66,0xab] +// X86-16: stosw %ax, %es:(%di) # encoding: [0xab] stos %eax, (%edi) -// 64: stosl %eax, %es:(%edi) # encoding: [0x67,0xab] -// 32: stosl %eax, %es:(%edi) # encoding: [0xab] -// 16: stosl %eax, %es:(%edi) # encoding: [0x67,0x66,0xab] +// X86-64: stosl %eax, %es:(%edi) # encoding: [0x67,0xab] +// X86-32: stosl %eax, %es:(%edi) # encoding: [0xab] +// X86-16: stosl %eax, %es:(%edi) # encoding: [0x67,0x66,0xab] stosb %al, %fs:(%edi) // ERR64: [[#@LINE-1]]:[[#]]: error: invalid operand for instruction @@ -61,27 +61,27 @@ stosb %al, %fs:(%edi) // ERR16: invalid operand for instruction stosb %al, %es:(%edi) -// 64: stosb %al, %es:(%edi) # encoding: [0x67,0xaa] -// 32: stosb %al, %es:(%edi) # encoding: [0xaa] -// 16: stosb %al, %es:(%edi) # encoding: [0x67,0xaa] +// X86-64: stosb %al, %es:(%edi) # encoding: [0x67,0xaa] +// X86-32: stosb %al, %es:(%edi) # encoding: [0xaa] +// X86-16: stosb %al, %es:(%edi) # encoding: [0x67,0xaa] stosq -// 64: stosq %rax, %es:(%rdi) # encoding: [0x48,0xab] +// X86-64: stosq %rax, %es:(%rdi) # encoding: [0x48,0xab] // ERR32: 64-bit // ERR16: 64-bit stos %rax, (%edi) -// 64: stosq %rax, %es:(%edi) # encoding: [0x67,0x48,0xab] +// X86-64: stosq %rax, %es:(%edi) # encoding: [0x67,0x48,0xab] // ERR32: only available in 64-bit mode // ERR16: only available in 64-bit mode scas %es:(%edi), %al -// 64: scasb %es:(%edi), %al # encoding: [0x67,0xae] -// 32: scasb %es:(%edi), %al # encoding: [0xae] -// 16: scasb %es:(%edi), %al # encoding: [0x67,0xae] +// X86-64: scasb %es:(%edi), %al # encoding: [0x67,0xae] +// X86-32: scasb %es:(%edi), %al # encoding: [0xae] +// X86-16: scasb %es:(%edi), %al # encoding: [0x67,0xae] scasq %es:(%edi) -// 64: scasq %es:(%edi), %rax # encoding: [0x67,0x48,0xaf] +// X86-64: scasq %es:(%edi), %rax # encoding: [0x67,0x48,0xaf] // ERR32: 64-bit // ERR16: 64-bit @@ -92,18 +92,18 @@ scasl %es:(%edi), %al scas %es:(%di), %ax // ERR64: [[#@LINE-1]]:[[#]]: error: invalid 16-bit base register -// 16: scasw %es:(%di), %ax # encoding: [0xaf] -// 32: scasw %es:(%di), %ax # encoding: [0x67,0x66,0xaf] +// X86-16: scasw %es:(%di), %ax # encoding: [0xaf] +// X86-32: scasw %es:(%di), %ax # encoding: [0x67,0x66,0xaf] cmpsb -// 64: cmpsb %es:(%rdi), (%rsi) # encoding: [0xa6] -// 32: cmpsb %es:(%edi), (%esi) # encoding: [0xa6] -// 16: cmpsb %es:(%di), (%si) # encoding: [0xa6] +// X86-64: cmpsb %es:(%rdi), (%rsi) # encoding: [0xa6] +// X86-32: cmpsb %es:(%edi), (%esi) # encoding: [0xa6] +// X86-16: cmpsb %es:(%di), (%si) # encoding: [0xa6] cmpsw (%edi), (%esi) -// 64: cmpsw %es:(%edi), (%esi) # encoding: [0x67,0x66,0xa7] -// 32: cmpsw %es:(%edi), (%esi) # encoding: [0x66,0xa7] -// 16: cmpsw %es:(%edi), (%esi) # encoding: [0x67,0xa7] +// X86-64: cmpsw %es:(%edi), (%esi) # encoding: [0x67,0x66,0xa7] +// X86-32: cmpsw %es:(%edi), (%esi) # encoding: [0x66,0xa7] +// X86-16: cmpsw %es:(%edi), (%esi) # encoding: [0x67,0xa7] cmpsb (%di), (%esi) // ERR64: [[#@LINE-1]]:[[#]]: error: invalid 16-bit base register @@ -111,52 +111,52 @@ cmpsb (%di), (%esi) // ERR16: mismatching source and destination cmpsl %es:(%edi), %ss:(%esi) -// 64: cmpsl %es:(%edi), %ss:(%esi) # encoding: [0x67,0x36,0xa7] -// 32: cmpsl %es:(%edi), %ss:(%esi) # encoding: [0x36,0xa7] -// 16: cmpsl %es:(%edi), %ss:(%esi) # encoding: [0x67,0x36,0x66,0xa7] +// X86-64: cmpsl %es:(%edi), %ss:(%esi) # encoding: [0x67,0x36,0xa7] +// X86-32: cmpsl %es:(%edi), %ss:(%esi) # encoding: [0x36,0xa7] +// X86-16: cmpsl %es:(%edi), %ss:(%esi) # encoding: [0x67,0x36,0x66,0xa7] cmpsq (%rdi), (%rsi) -// 64: cmpsq %es:(%rdi), (%rsi) # encoding: [0x48,0xa7] +// X86-64: cmpsq %es:(%rdi), (%rsi) # encoding: [0x48,0xa7] // ERR32: 64-bit // ERR16: 64-bit movsb (%esi), (%edi) -// 64: movsb (%esi), %es:(%edi) # encoding: [0x67,0xa4] -// 32: movsb (%esi), %es:(%edi) # encoding: [0xa4] -// 16: movsb (%esi), %es:(%edi) # encoding: [0x67,0xa4] +// X86-64: movsb (%esi), %es:(%edi) # encoding: [0x67,0xa4] +// X86-32: movsb (%esi), %es:(%edi) # encoding: [0xa4] +// X86-16: movsb (%esi), %es:(%edi) # encoding: [0x67,0xa4] movsl %gs:(%esi), (%edi) -// 64: movsl %gs:(%esi), %es:(%edi) # encoding: [0x67,0x65,0xa5] -// 32: movsl %gs:(%esi), %es:(%edi) # encoding: [0x65,0xa5] -// 16: movsl %gs:(%esi), %es:(%edi) # encoding: [0x67,0x65,0x66,0xa5] +// X86-64: movsl %gs:(%esi), %es:(%edi) # encoding: [0x67,0x65,0xa5] +// X86-32: movsl %gs:(%esi), %es:(%edi) # encoding: [0x65,0xa5] +// X86-16: movsl %gs:(%esi), %es:(%edi) # encoding: [0x67,0x65,0x66,0xa5] outsb -// 64: outsb (%rsi), %dx # encoding: [0x6e] -// 32: outsb (%esi), %dx # encoding: [0x6e] -// 16: outsb (%si), %dx # encoding: [0x6e] +// X86-64: outsb (%rsi), %dx # encoding: [0x6e] +// X86-32: outsb (%esi), %dx # encoding: [0x6e] +// X86-16: outsb (%si), %dx # encoding: [0x6e] outsw %fs:(%esi), %dx -// 64: outsw %fs:(%esi), %dx # encoding: [0x67,0x64,0x66,0x6f] -// 32: outsw %fs:(%esi), %dx # encoding: [0x64,0x66,0x6f] -// 16: outsw %fs:(%esi), %dx # encoding: [0x67,0x64,0x6f] +// X86-64: outsw %fs:(%esi), %dx # encoding: [0x67,0x64,0x66,0x6f] +// X86-32: outsw %fs:(%esi), %dx # encoding: [0x64,0x66,0x6f] +// X86-16: outsw %fs:(%esi), %dx # encoding: [0x67,0x64,0x6f] insw %dx, (%edi) -// 64: insw %dx, %es:(%edi) # encoding: [0x67,0x66,0x6d] -// 32: insw %dx, %es:(%edi) # encoding: [0x66,0x6d] -// 16: insw %dx, %es:(%edi) # encoding: [0x67,0x6d] +// X86-64: insw %dx, %es:(%edi) # encoding: [0x67,0x66,0x6d] +// X86-32: insw %dx, %es:(%edi) # encoding: [0x66,0x6d] +// X86-16: insw %dx, %es:(%edi) # encoding: [0x67,0x6d] insw %dx, (%bx) // ERR64: [[#@LINE-1]]:[[#]]: error: invalid 16-bit base register -// 32: insw %dx, %es:(%di) # encoding: [0x67,0x66,0x6d] -// 16: insw %dx, %es:(%di) # encoding: [0x6d] +// X86-32: insw %dx, %es:(%di) # encoding: [0x67,0x66,0x6d] +// X86-16: insw %dx, %es:(%di) # encoding: [0x6d] insw %dx, (%ebx) -// 64: insw %dx, %es:(%edi) # encoding: [0x67,0x66,0x6d] -// 32: insw %dx, %es:(%edi) # encoding: [0x66,0x6d] -// 16: insw %dx, %es:(%edi) # encoding: [0x67,0x6d] +// X86-64: insw %dx, %es:(%edi) # encoding: [0x67,0x66,0x6d] +// X86-32: insw %dx, %es:(%edi) # encoding: [0x66,0x6d] +// X86-16: insw %dx, %es:(%edi) # encoding: [0x67,0x6d] insw %dx, (%rbx) -// 64: insw %dx, %es:(%rdi) # encoding: [0x66,0x6d] +// X86-64: insw %dx, %es:(%rdi) # encoding: [0x66,0x6d] // ERR32: 64-bit // ERR16: 64-bit @@ -177,17 +177,17 @@ movdir64b (%edx), %r15 // ERR64: [[#@LINE-1]]:[[#]]: error: invalid operand movdir64b (%eip), %ebx -// 64: movdir64b (%eip), %ebx # encoding: [0x67,0x66,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] +// X86-64: movdir64b (%eip), %ebx # encoding: [0x67,0x66,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] movdir64b (%rip), %rbx -// 64: movdir64b (%rip), %rbx # encoding: [0x66,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] +// X86-64: movdir64b (%rip), %rbx # encoding: [0x66,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] movdir64b 291(%esi, %eiz, 4), %ebx -// 64: movdir64b 291(%esi,%eiz,4), %ebx # encoding: [0x67,0x66,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] -// 32: movdir64b 291(%esi,%eiz,4), %ebx # encoding: [0x66,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] +// X86-64: movdir64b 291(%esi,%eiz,4), %ebx # encoding: [0x67,0x66,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] +// X86-32: movdir64b 291(%esi,%eiz,4), %ebx # encoding: [0x66,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] movdir64b 291(%rsi, %riz, 4), %rbx -// 64: movdir64b 291(%rsi,%riz,4), %rbx # encoding: [0x66,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] +// X86-64: movdir64b 291(%rsi,%riz,4), %rbx # encoding: [0x66,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] enqcmd 291(%si), %ecx // ERR64: error: invalid 16-bit base register @@ -206,17 +206,17 @@ enqcmd (%edx), %r15 // ERR64: [[#@LINE-1]]:[[#]]: error: invalid operand enqcmd (%eip), %ebx -// 64: enqcmd (%eip), %ebx # encoding: [0x67,0xf2,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] +// X86-64: enqcmd (%eip), %ebx # encoding: [0x67,0xf2,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] enqcmd (%rip), %rbx -// 64: enqcmd (%rip), %rbx # encoding: [0xf2,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] +// X86-64: enqcmd (%rip), %rbx # encoding: [0xf2,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] enqcmd 291(%esi, %eiz, 4), %ebx -// 64: enqcmd 291(%esi,%eiz,4), %ebx # encoding: [0x67,0xf2,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] -// 32: enqcmd 291(%esi,%eiz,4), %ebx # encoding: [0xf2,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] +// X86-64: enqcmd 291(%esi,%eiz,4), %ebx # encoding: [0x67,0xf2,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] +// X86-32: enqcmd 291(%esi,%eiz,4), %ebx # encoding: [0xf2,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] enqcmd 291(%rsi, %riz, 4), %rbx -// 64: enqcmd 291(%rsi,%riz,4), %rbx # encoding: [0xf2,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] +// X86-64: enqcmd 291(%rsi,%riz,4), %rbx # encoding: [0xf2,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] enqcmds 291(%si), %ecx // ERR64: error: invalid 16-bit base register @@ -235,14 +235,14 @@ enqcmds (%edx), %r15 // ERR64: [[#@LINE-1]]:[[#]]: error: invalid operand enqcmds (%eip), %ebx -// 64: enqcmds (%eip), %ebx # encoding: [0x67,0xf3,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] +// X86-64: enqcmds (%eip), %ebx # encoding: [0x67,0xf3,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] enqcmds (%rip), %rbx -// 64: enqcmds (%rip), %rbx # encoding: [0xf3,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] +// X86-64: enqcmds (%rip), %rbx # encoding: [0xf3,0x0f,0x38,0xf8,0x1d,0x00,0x00,0x00,0x00] enqcmds 291(%esi, %eiz, 4), %ebx -// 64: enqcmds 291(%esi,%eiz,4), %ebx # encoding: [0x67,0xf3,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] -// 32: enqcmds 291(%esi,%eiz,4), %ebx # encoding: [0xf3,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] +// X86-64: enqcmds 291(%esi,%eiz,4), %ebx # encoding: [0x67,0xf3,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] +// X86-32: enqcmds 291(%esi,%eiz,4), %ebx # encoding: [0xf3,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] enqcmds 291(%rsi, %riz, 4), %rbx -// 64: enqcmds 291(%rsi,%riz,4), %rbx # encoding: [0xf3,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] +// X86-64: enqcmds 291(%rsi,%riz,4), %rbx # encoding: [0xf3,0x0f,0x38,0xf8,0x9c,0xa6,0x23,0x01,0x00,0x00] diff --git a/llvm/test/MC/X86/ret.s b/llvm/test/MC/X86/ret.s index 142a4614ba4f..7b5bcd4ad990 100644 --- a/llvm/test/MC/X86/ret.s +++ b/llvm/test/MC/X86/ret.s @@ -1,129 +1,129 @@ -// RUN: not llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=64 %s +// RUN: not llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=X86-64 %s // RUN: FileCheck --check-prefix=ERR64 < %t.err %s -// RUN: not llvm-mc -triple i386-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=32 %s +// RUN: not llvm-mc -triple i386-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=X86-32 %s // RUN: FileCheck --check-prefix=ERR32 < %t.err %s -// RUN: not llvm-mc -triple i386-unknown-unknown-code16 --show-encoding %s 2> %t.err | FileCheck --check-prefix=16 %s +// RUN: not llvm-mc -triple i386-unknown-unknown-code16 --show-encoding %s 2> %t.err | FileCheck --check-prefix=X86-16 %s // RUN: FileCheck --check-prefix=ERR16 < %t.err %s ret -// 64: retq -// 64: encoding: [0xc3] -// 32: retl -// 32: encoding: [0xc3] -// 16: retw -// 16: encoding: [0xc3] +// X86-64: retq +// X86-64: encoding: [0xc3] +// X86-32: retl +// X86-32: encoding: [0xc3] +// X86-16: retw +// X86-16: encoding: [0xc3] retw -// 64: retw -// 64: encoding: [0x66,0xc3] -// 32: retw -// 32: encoding: [0x66,0xc3] -// 16: retw -// 16: encoding: [0xc3] +// X86-64: retw +// X86-64: encoding: [0x66,0xc3] +// X86-32: retw +// X86-32: encoding: [0x66,0xc3] +// X86-16: retw +// X86-16: encoding: [0xc3] retl // ERR64: error: instruction requires: Not 64-bit mode -// 32: retl -// 32: encoding: [0xc3] -// 16: retl -// 16: encoding: [0x66,0xc3] +// X86-32: retl +// X86-32: encoding: [0xc3] +// X86-16: retl +// X86-16: encoding: [0x66,0xc3] retq -// 64: retq -// 64: encoding: [0xc3] +// X86-64: retq +// X86-64: encoding: [0xc3] // ERR32: error: instruction requires: 64-bit mode // ERR16: error: instruction requires: 64-bit mode ret $0 -// 64: retq $0 -// 64: encoding: [0xc2,0x00,0x00] -// 32: retl $0 -// 32: encoding: [0xc2,0x00,0x00] -// 16: retw $0 -// 16: encoding: [0xc2,0x00,0x00] +// X86-64: retq $0 +// X86-64: encoding: [0xc2,0x00,0x00] +// X86-32: retl $0 +// X86-32: encoding: [0xc2,0x00,0x00] +// X86-16: retw $0 +// X86-16: encoding: [0xc2,0x00,0x00] retw $0 -// 64: retw $0 -// 64: encoding: [0x66,0xc2,0x00,0x00] -// 32: retw $0 -// 32: encoding: [0x66,0xc2,0x00,0x00] -// 16: retw $0 -// 16: encoding: [0xc2,0x00,0x00] +// X86-64: retw $0 +// X86-64: encoding: [0x66,0xc2,0x00,0x00] +// X86-32: retw $0 +// X86-32: encoding: [0x66,0xc2,0x00,0x00] +// X86-16: retw $0 +// X86-16: encoding: [0xc2,0x00,0x00] retl $0 // ERR64: error: instruction requires: Not 64-bit mode -// 32: retl $0 -// 32: encoding: [0xc2,0x00,0x00] -// 16: retl $0 -// 16: encoding: [0x66,0xc2,0x00,0x00] +// X86-32: retl $0 +// X86-32: encoding: [0xc2,0x00,0x00] +// X86-16: retl $0 +// X86-16: encoding: [0x66,0xc2,0x00,0x00] retq $0 -// 64: retq $0 -// 64: encoding: [0xc2,0x00,0x00] +// X86-64: retq $0 +// X86-64: encoding: [0xc2,0x00,0x00] // ERR32: error: instruction requires: 64-bit mode // ERR16: error: instruction requires: 64-bit mode retn -// 64: retq -// 64: encoding: [0xc3] -// 32: retl -// 32: encoding: [0xc3] -// 16: retw -// 16: encoding: [0xc3] +// X86-64: retq +// X86-64: encoding: [0xc3] +// X86-32: retl +// X86-32: encoding: [0xc3] +// X86-16: retw +// X86-16: encoding: [0xc3] retn $0 -// 64: retq $0 -// 64: encoding: [0xc2,0x00,0x00] -// 32: retl $0 -// 32: encoding: [0xc2,0x00,0x00] -// 16: retw $0 -// 16: encoding: [0xc2,0x00,0x00] +// X86-64: retq $0 +// X86-64: encoding: [0xc2,0x00,0x00] +// X86-32: retl $0 +// X86-32: encoding: [0xc2,0x00,0x00] +// X86-16: retw $0 +// X86-16: encoding: [0xc2,0x00,0x00] lret -// 64: lretl -// 64: encoding: [0xcb] -// 32: lretl -// 32: encoding: [0xcb] -// 16: lretw -// 16: encoding: [0xcb] +// X86-64: lretl +// X86-64: encoding: [0xcb] +// X86-32: lretl +// X86-32: encoding: [0xcb] +// X86-16: lretw +// X86-16: encoding: [0xcb] lretw -// 64: lretw -// 64: encoding: [0x66,0xcb] -// 32: lretw -// 32: encoding: [0x66,0xcb] -// 16: lretw -// 16: encoding: [0xcb] +// X86-64: lretw +// X86-64: encoding: [0x66,0xcb] +// X86-32: lretw +// X86-32: encoding: [0x66,0xcb] +// X86-16: lretw +// X86-16: encoding: [0xcb] lretl -// 64: lretl -// 64: encoding: [0xcb] -// 32: lretl -// 32: encoding: [0xcb] -// 16: lretl -// 16: encoding: [0x66,0xcb] +// X86-64: lretl +// X86-64: encoding: [0xcb] +// X86-32: lretl +// X86-32: encoding: [0xcb] +// X86-16: lretl +// X86-16: encoding: [0x66,0xcb] lretq -// 64: lretq -// 64: encoding: [0x48,0xcb] +// X86-64: lretq +// X86-64: encoding: [0x48,0xcb] // ERR32: error: instruction requires: 64-bit mode // ERR16: error: instruction requires: 64-bit mode lret $0 -// 64: lretl $0 -// 64: encoding: [0xca,0x00,0x00] -// 32: lretl $0 -// 32: encoding: [0xca,0x00,0x00] -// 16: lretw $0 -// 16: encoding: [0xca,0x00,0x00] +// X86-64: lretl $0 +// X86-64: encoding: [0xca,0x00,0x00] +// X86-32: lretl $0 +// X86-32: encoding: [0xca,0x00,0x00] +// X86-16: lretw $0 +// X86-16: encoding: [0xca,0x00,0x00] lretw $0 -// 64: lretw $0 -// 64: encoding: [0x66,0xca,0x00,0x00] -// 32: lretw $0 -// 32: encoding: [0x66,0xca,0x00,0x00] -// 16: lretw $0 -// 16: encoding: [0xca,0x00,0x00] +// X86-64: lretw $0 +// X86-64: encoding: [0x66,0xca,0x00,0x00] +// X86-32: lretw $0 +// X86-32: encoding: [0x66,0xca,0x00,0x00] +// X86-16: lretw $0 +// X86-16: encoding: [0xca,0x00,0x00] lretl $0 -// 64: lretl $0 -// 64: encoding: [0xca,0x00,0x00] -// 32: lretl $0 -// 32: encoding: [0xca,0x00,0x00] -// 16: lretl $0 -// 16: encoding: [0x66,0xca,0x00,0x00] +// X86-64: lretl $0 +// X86-64: encoding: [0xca,0x00,0x00] +// X86-32: lretl $0 +// X86-32: encoding: [0xca,0x00,0x00] +// X86-16: lretl $0 +// X86-16: encoding: [0x66,0xca,0x00,0x00] lretq $0 -// 64: lretq $0 -// 64: encoding: [0x48,0xca,0x00,0x00] +// X86-64: lretq $0 +// X86-64: encoding: [0x48,0xca,0x00,0x00] // ERR32: error: instruction requires: 64-bit mode // ERR16: error: instruction requires: 64-bit mode diff --git a/llvm/test/MC/X86/x86_errors.s b/llvm/test/MC/X86/x86_errors.s index f1c7110fde1f..da8659f3621e 100644 --- a/llvm/test/MC/X86/x86_errors.s +++ b/llvm/test/MC/X86/x86_errors.s @@ -1,122 +1,122 @@ // RUN: not llvm-mc -triple x86_64-unknown-unknown %s 2> %t.err -// RUN: FileCheck --check-prefix=64 < %t.err %s +// RUN: FileCheck --check-prefix=X64 < %t.err %s // RUN: not llvm-mc -triple i386-unknown-unknown %s 2> %t.err -// RUN: FileCheck --check-prefix=32 < %t.err %s +// RUN: FileCheck --check-prefix=X86 < %t.err %s // rdar://8204588 -// 64: error: ambiguous instructions require an explicit suffix (could be 'cmpb', 'cmpw', 'cmpl', or 'cmpq') +// X64: error: ambiguous instructions require an explicit suffix (could be 'cmpb', 'cmpw', 'cmpl', or 'cmpq') cmp $0, 0(%eax) -// 32: error: register %rax is only available in 64-bit mode +// X86: error: register %rax is only available in 64-bit mode addl $0, 0(%rax) -// 32: test.s:8:2: error: invalid instruction mnemonic 'movi' +// X86: test.s:8:2: error: invalid instruction mnemonic 'movi' # 8 "test.s" movi $8,%eax movl 0(%rax), 0(%edx) // error: invalid operand for instruction -// 32: error: instruction requires: 64-bit mode +// X86: error: instruction requires: 64-bit mode sysexitq // rdar://10710167 -// 64: error: expected scale expression +// X64: error: expected scale expression lea (%rsp, %rbp, $4), %rax // rdar://10423777 -// 64: error: base register is 64-bit, but index register is not +// X64: error: base register is 64-bit, but index register is not movq (%rsi,%ecx),%xmm0 -// 64: error: invalid 16-bit base register +// X64: error: invalid 16-bit base register movl %eax,(%bp,%si) -// 32: error: scale factor in 16-bit address must be 1 +// X86: error: scale factor in 16-bit address must be 1 movl %eax,(%bp,%si,2) -// 32: error: invalid 16-bit base register +// X86: error: invalid 16-bit base register movl %eax,(%cx) -// 32: error: invalid 16-bit base/index register combination +// X86: error: invalid 16-bit base/index register combination movl %eax,(%bp,%bx) -// 32: error: 16-bit memory operand may not include only index register +// X86: error: 16-bit memory operand may not include only index register movl %eax,(,%bx) -// 32: error: invalid operand for instruction +// X86: error: invalid operand for instruction outb al, 4 -// 32: error: invalid segment register -// 64: error: invalid segment register +// X86: error: invalid segment register +// X64: error: invalid segment register movl %eax:0x00, %ebx -// 32: error: invalid operand for instruction -// 64: error: invalid operand for instruction +// X86: error: invalid operand for instruction +// X64: error: invalid operand for instruction cmpps $-129, %xmm0, %xmm0 -// 32: error: invalid operand for instruction -// 64: error: invalid operand for instruction +// X86: error: invalid operand for instruction +// X64: error: invalid operand for instruction cmppd $256, %xmm0, %xmm0 -// 32: error: instruction requires: 64-bit mode +// X86: error: instruction requires: 64-bit mode jrcxz 1 -// 64: error: instruction requires: Not 64-bit mode +// X64: error: instruction requires: Not 64-bit mode jcxz 1 -// 32: error: register %cr8 is only available in 64-bit mode +// X86: error: register %cr8 is only available in 64-bit mode movl %edx, %cr8 -// 32: error: register %dr8 is only available in 64-bit mode +// X86: error: register %dr8 is only available in 64-bit mode movl %edx, %dr8 -// 32: error: register %rip is only available in 64-bit mode -// 64: error: %rip can only be used as a base register +// X86: error: register %rip is only available in 64-bit mode +// X64: error: %rip can only be used as a base register mov %rip, %rax -// 32: error: register %rax is only available in 64-bit mode -// 64: error: %rip is not allowed as an index register +// X86: error: register %rax is only available in 64-bit mode +// X64: error: %rip is not allowed as an index register mov (%rax,%rip), %rbx -// 32: error: instruction requires: 64-bit mode +// X86: error: instruction requires: 64-bit mode ljmpq *(%eax) -// 32: error: register %rax is only available in 64-bit mode -// 64: error: invalid base+index expression +// X86: error: register %rax is only available in 64-bit mode +// X64: error: invalid base+index expression leaq (%rax,%rsp), %rax -// 32: error: invalid base+index expression -// 64: error: invalid base+index expression +// X86: error: invalid base+index expression +// X64: error: invalid base+index expression leaq (%eax,%esp), %eax -// 32: error: invalid 16-bit base/index register combination -// 64: error: invalid 16-bit base register +// X86: error: invalid 16-bit base/index register combination +// X64: error: invalid 16-bit base register lea (%si,%bp), %ax -// 32: error: invalid 16-bit base/index register combination -// 64: error: invalid 16-bit base register +// X86: error: invalid 16-bit base/index register combination +// X64: error: invalid 16-bit base register lea (%di,%bp), %ax -// 32: error: invalid 16-bit base/index register combination -// 64: error: invalid 16-bit base register +// X86: error: invalid 16-bit base/index register combination +// X64: error: invalid 16-bit base register lea (%si,%bx), %ax -// 32: error: invalid 16-bit base/index register combination -// 64: error: invalid 16-bit base register +// X86: error: invalid 16-bit base/index register combination +// X64: error: invalid 16-bit base register lea (%di,%bx), %ax -// 32: error: invalid base+index expression -// 64: error: invalid base+index expression +// X86: error: invalid base+index expression +// X64: error: invalid base+index expression mov (,%eip), %rbx -// 32: error: invalid base+index expression -// 64: error: invalid base+index expression +// X86: error: invalid base+index expression +// X64: error: invalid base+index expression mov (%eip,%eax), %rbx -// 32: error: register %rax is only available in 64-bit mode -// 64: error: base register is 64-bit, but index register is not +// X86: error: register %rax is only available in 64-bit mode +// X64: error: base register is 64-bit, but index register is not mov (%rax,%eiz), %ebx -// 32: error: register %riz is only available in 64-bit mode -// 64: error: base register is 32-bit, but index register is not +// X86: error: register %riz is only available in 64-bit mode +// X64: error: base register is 32-bit, but index register is not mov (%eax,%riz), %ebx @@ -128,68 +128,68 @@ v_gs = %gs v_imm = 4 $test = %ebx -// 32: 7: error: expected register here -// 64: 7: error: expected register here +// X86: 7: error: expected register here +// X64: 7: error: expected register here mov 4(4), %eax -// 32: 7: error: expected register here -// 64: 7: error: expected register here +// X86: 7: error: expected register here +// X64: 7: error: expected register here mov 5(v_imm), %eax -// 32: 7: error: invalid register name -// 64: 7: error: invalid register name +// X86: 7: error: invalid register name +// X64: 7: error: invalid register name mov 6(%v_imm), %eax -// 32: 8: warning: scale factor without index register is ignored -// 64: 8: warning: scale factor without index register is ignored +// X86: 8: warning: scale factor without index register is ignored +// X64: 8: warning: scale factor without index register is ignored mov 7(,v_imm), %eax -// 64: 6: error: expected immediate expression +// X64: 6: error: expected immediate expression mov $%eax, %ecx -// 32: 6: error: expected immediate expression -// 64: 6: error: expected immediate expression +// X86: 6: error: expected immediate expression +// X64: 6: error: expected immediate expression mov $v_eax, %ecx -// 32: error: unexpected token in argument list -// 64: error: unexpected token in argument list +// X86: error: unexpected token in argument list +// X64: error: unexpected token in argument list mov v_ecx(%eax), %ecx -// 32: 7: error: invalid operand for instruction -// 64: 7: error: invalid operand for instruction +// X86: 7: error: invalid operand for instruction +// X64: 7: error: invalid operand for instruction addb (%dx), %al -// 32: error: instruction requires: 64-bit mode +// X86: error: instruction requires: 64-bit mode cqto -// 32: error: instruction requires: 64-bit mode +// X86: error: instruction requires: 64-bit mode cltq -// 32: error: instruction requires: 64-bit mode +// X86: error: instruction requires: 64-bit mode cmpxchg16b (%eax) -// 32: error: unsupported instruction -// 64: error: unsupported instruction +// X86: error: unsupported instruction +// X64: error: unsupported instruction {vex} vmovdqu32 %xmm0, %xmm0 -// 32: error: unsupported instruction -// 64: error: unsupported instruction +// X86: error: unsupported instruction +// X64: error: unsupported instruction {vex2} vmovdqu32 %xmm0, %xmm0 -// 32: error: unsupported instruction -// 64: error: unsupported instruction +// X86: error: unsupported instruction +// X64: error: unsupported instruction {vex3} vmovdqu32 %xmm0, %xmm0 -// 32: error: unsupported instruction -// 64: error: unsupported instruction +// X86: error: unsupported instruction +// X64: error: unsupported instruction {evex} vmovdqu %xmm0, %xmm0 -// 32: 12: error: immediate must be an integer in range [0, 15] -// 64: 12: error: immediate must be an integer in range [0, 15] +// X86: 12: error: immediate must be an integer in range [0, 15] +// X64: 12: error: immediate must be an integer in range [0, 15] vpermil2pd $16, %xmm3, %xmm5, %xmm1, %xmm2 -// 32: error: instruction requires: 64-bit mode +// X86: error: instruction requires: 64-bit mode pbndkb -// 32: error: register %r16d is only available in 64-bit mode +// X86: error: register %r16d is only available in 64-bit mode movl %eax, %r16d -- GitLab From 89873694654a635cabdd861ddebd61a041d8342f Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 15 May 2024 13:49:39 +0100 Subject: [PATCH 340/578] [X86] sibcall - cleanup check prefixes identified in #92248 Avoid using numbers as check prefix - replace with actual triple config names --- llvm/test/CodeGen/X86/sibcall-2.ll | 36 +++++++++++++------------- llvm/test/CodeGen/X86/sibcall-byval.ll | 20 +++++++------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/llvm/test/CodeGen/X86/sibcall-2.ll b/llvm/test/CodeGen/X86/sibcall-2.ll index a4345cf28335..ca42fbafde14 100644 --- a/llvm/test/CodeGen/X86/sibcall-2.ll +++ b/llvm/test/CodeGen/X86/sibcall-2.ll @@ -1,48 +1,48 @@ -; RUN: llc -verify-machineinstrs < %s -mtriple=i386-apple-darwin -frame-pointer=all | FileCheck %s -check-prefix=32 -; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-apple-darwin -frame-pointer=all | FileCheck %s -check-prefix=64 +; RUN: llc -verify-machineinstrs < %s -mtriple=i386-apple-darwin -frame-pointer=all | FileCheck %s -check-prefix=X86 +; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-apple-darwin -frame-pointer=all | FileCheck %s -check-prefix=X64 ; Tail call should not use ebp / rbp after it's popped. Use esp / rsp. define void @t1(ptr nocapture %value) nounwind { entry: -; 32-LABEL: t1: -; 32: jmpl *4(%esp) +; X86-LABEL: t1: +; X86: jmpl *4(%esp) -; 64-LABEL: t1: -; 64: jmpq *%rdi +; X64-LABEL: t1: +; X64: jmpq *%rdi tail call void %value() nounwind ret void } define void @t2(i32 %a, ptr nocapture %value) nounwind { entry: -; 32-LABEL: t2: -; 32: jmpl *8(%esp) +; X86-LABEL: t2: +; X86: jmpl *8(%esp) -; 64-LABEL: t2: -; 64: jmpq *%rsi +; X64-LABEL: t2: +; X64: jmpq *%rsi tail call void %value() nounwind ret void } define void @t3(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, ptr nocapture %value) nounwind { entry: -; 32-LABEL: t3: -; 32: jmpl *28(%esp) +; X86-LABEL: t3: +; X86: jmpl *28(%esp) -; 64-LABEL: t3: -; 64: jmpq *8(%rsp) +; X64-LABEL: t3: +; X64: jmpq *8(%rsp) tail call void %value() nounwind ret void } define void @t4(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, ptr nocapture %value) nounwind { entry: -; 32-LABEL: t4: -; 32: jmpl *32(%esp) +; X86-LABEL: t4: +; X86: jmpl *32(%esp) -; 64-LABEL: t4: -; 64: jmpq *16(%rsp) +; X64-LABEL: t4: +; X64: jmpq *16(%rsp) tail call void %value() nounwind ret void } diff --git a/llvm/test/CodeGen/X86/sibcall-byval.ll b/llvm/test/CodeGen/X86/sibcall-byval.ll index 12dbac1389a0..0e06833ad70b 100644 --- a/llvm/test/CodeGen/X86/sibcall-byval.ll +++ b/llvm/test/CodeGen/X86/sibcall-byval.ll @@ -1,15 +1,15 @@ -; RUN: llc < %s -mtriple=i386-apple-darwin9 | FileCheck %s -check-prefix=32 -; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s -check-prefix=64 +; RUN: llc < %s -mtriple=i386-apple-darwin9 | FileCheck %s -check-prefix=X86 +; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s -check-prefix=X64 %struct.p = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } define i32 @f(ptr byval(%struct.p) align 4 %q) nounwind ssp { entry: -; 32: _f: -; 32: jmp _g +; X86: _f: +; X86: jmp _g -; 64: _f: -; 64: jmp _g +; X64: _f: +; X64: jmp _g %call = tail call i32 @g(ptr byval(%struct.p) align 4 %q) nounwind ret i32 %call } @@ -18,11 +18,11 @@ declare i32 @g(ptr byval(%struct.p) align 4) define i32 @h(ptr byval(%struct.p) align 4 %q, i32 %r) nounwind ssp { entry: -; 32: _h: -; 32: jmp _i +; X86: _h: +; X86: jmp _i -; 64: _h: -; 64: jmp _i +; X64: _h: +; X64: jmp _i %call = tail call i32 @i(ptr byval(%struct.p) align 4 %q, i32 %r) nounwind ret i32 %call -- GitLab From 932f0de43a9e334e161a69a50bd6b01cd51e238e Mon Sep 17 00:00:00 2001 From: Julian Schmidt Date: Wed, 15 May 2024 14:52:32 +0200 Subject: [PATCH 341/578] [clang-tidy] fix crash due to assumed callee in min-max-use-initializer-list (#91992) Previously, the call to `findArgs` for a `CallExpr` inside of a `min` or `max` call would call `findArgs` before checking if the argument is a call to `min` or `max`, which is what `findArgs` is expecting. The fix moves the name checking before the call to `findArgs`, such that only a `min` or `max` function call is used as an argument. Fixes #91982 Fixes #92249 --- .../MinMaxUseInitializerListCheck.cpp | 10 ++++----- .../min-max-use-initializer-list.cpp | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp index 45f7700463d5..418699ffbc4d 100644 --- a/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp @@ -129,17 +129,17 @@ generateReplacements(const MatchFinder::MatchResult &Match, continue; } + // if the nested call is not the same as the top call + if (InnerCall->getDirectCallee()->getQualifiedNameAsString() != + TopCall->getDirectCallee()->getQualifiedNameAsString()) + continue; + const FindArgsResult InnerResult = findArgs(InnerCall); // if the nested call doesn't have arguments skip it if (!InnerResult.First || !InnerResult.Last) continue; - // if the nested call is not the same as the top call - if (InnerCall->getDirectCallee()->getQualifiedNameAsString() != - TopCall->getDirectCallee()->getQualifiedNameAsString()) - continue; - // if the nested call doesn't have the same compare function if ((Result.Compare || InnerResult.Compare) && !utils::areStatementsIdentical(Result.Compare, InnerResult.Compare, diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/min-max-use-initializer-list.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/min-max-use-initializer-list.cpp index 51ab9bda975f..1f2dad2b933c 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/min-max-use-initializer-list.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/min-max-use-initializer-list.cpp @@ -300,6 +300,27 @@ B maxTT2 = std::max(B(), std::max(B(), B())); B maxTT3 = std::max(B(), std::max(B(), B()), [](const B &lhs, const B &rhs) { return lhs.a[0] < rhs.a[0]; }); // CHECK-FIXES: B maxTT3 = std::max(B(), std::max(B(), B()), [](const B &lhs, const B &rhs) { return lhs.a[0] < rhs.a[0]; }); +struct GH91982 { + int fun0Args(); + int fun1Arg(int a); + int fun2Args(int a, int b); + int fun3Args(int a, int b, int c); + int fun4Args(int a, int b, int c, int d); + + int foo() { + return std::max( + fun0Args(), + std::max(fun1Arg(0), + std::max(fun2Args(0, 1), + std::max(fun3Args(0, 1, 2), fun4Args(0, 1, 2, 3))))); +// CHECK-MESSAGES: :[[@LINE-5]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] +// CHECK-FIXES: return std::max( +// CHECK-FIXES-NEXT: {fun0Args(), +// CHECK-FIXES-NEXT: fun1Arg(0), +// CHECK-FIXES-NEXT: fun2Args(0, 1), +// CHECK-FIXES-NEXT: fun3Args(0, 1, 2), fun4Args(0, 1, 2, 3)}); + } +}; } // namespace -- GitLab From 83d9aa27680b6a7f3556fcf13ada70b4be95bab2 Mon Sep 17 00:00:00 2001 From: Pietro Ghiglio Date: Wed, 15 May 2024 15:03:21 +0200 Subject: [PATCH 342/578] [VPlan] Add scalar inferencing support for addrspace cast (#92107) Fixes https://github.com/llvm/llvm-project/issues/91434 PR: https://github.com/llvm/llvm-project/pull/92107 --- .../Transforms/Vectorize/VPlanAnalysis.cpp | 1 + llvm/test/Transforms/LoopVectorize/as_cast.ll | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 llvm/test/Transforms/LoopVectorize/as_cast.ll diff --git a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp index 5f93339083f0..efe8c21874a3 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp @@ -171,6 +171,7 @@ Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPReplicateRecipe *R) { case Instruction::ICmp: case Instruction::FCmp: return IntegerType::get(Ctx, 1); + case Instruction::AddrSpaceCast: case Instruction::Alloca: case Instruction::BitCast: case Instruction::Trunc: diff --git a/llvm/test/Transforms/LoopVectorize/as_cast.ll b/llvm/test/Transforms/LoopVectorize/as_cast.ll new file mode 100644 index 000000000000..58a8c3d078f0 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/as_cast.ll @@ -0,0 +1,40 @@ +; RUN: opt -passes=loop-vectorize %s -force-vector-width=1 -force-vector-interleave=2 -S -o - | FileCheck %s + +define void @foo(ptr addrspace(1) %in) { +entry: + br label %loop + +loop: + %iter = phi i64 [ %next, %loop ], [ 0, %entry ] + %ascast = addrspacecast ptr addrspace(1) %in to ptr + %next = add i64 %iter, 1 + %arrayidx = getelementptr inbounds i64, ptr %ascast, i64 %next + store i64 %next, ptr %arrayidx, align 4 + +; check that we find the two interleaved blocks with ascast, gep and store: +; CHECK: pred.store.if: +; CHECK: [[ID1:%.*]] = add i64 %{{.*}}, 1 +; CHECK: [[AS1:%.*]] = addrspacecast ptr addrspace(1) %{{.*}} to ptr +; CHECK: [[GEP1:%.*]] = getelementptr inbounds i64, ptr [[AS1]], i64 [[ID1]] +; CHECK: store i64 [[ID1]], ptr [[GEP1]] + +; CHECK: pred.store.if1: +; CHECK: [[ID2:%.*]] = add i64 %{{.*}}, 1 +; CHECK: [[AS2:%.*]] = addrspacecast ptr addrspace(1) %in to ptr +; CHECK: [[GEP2:%.*]] = getelementptr inbounds i64, ptr [[AS2]], i64 [[ID2]] +; CHECK: store i64 [[ID2]], ptr %9, align 4 + + %cmp = icmp eq i64 %next, 7 + br i1 %cmp, label %exit, label %loop + +; check that we branch to the exit block +; CHECK: middle.block: +; CHECK: br i1 true, label %exit, label %scalar.ph + +exit: + ret void +; CHECK: exit: +; CHECK: ret void +} + +; CHECK: !{{[0-9]*}} = !{!"llvm.loop.isvectorized", i32 1} -- GitLab From d06270ee00e37b247eb99268fb2f106dbeee08ff Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Wed, 15 May 2024 06:08:29 -0700 Subject: [PATCH 343/578] [workflows] Fix libclang-abi-tests to work with new version scheme (#91865) --- .github/workflows/libclang-abi-tests.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/libclang-abi-tests.yml b/.github/workflows/libclang-abi-tests.yml index ccfc1e5fb8a7..972d21c3bced 100644 --- a/.github/workflows/libclang-abi-tests.yml +++ b/.github/workflows/libclang-abi-tests.yml @@ -33,7 +33,6 @@ jobs: ABI_HEADERS: ${{ steps.vars.outputs.ABI_HEADERS }} ABI_LIBS: ${{ steps.vars.outputs.ABI_LIBS }} BASELINE_VERSION_MAJOR: ${{ steps.vars.outputs.BASELINE_VERSION_MAJOR }} - BASELINE_VERSION_MINOR: ${{ steps.vars.outputs.BASELINE_VERSION_MINOR }} LLVM_VERSION_MAJOR: ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} LLVM_VERSION_MINOR: ${{ steps.version.outputs.LLVM_VERSION_MINOR }} LLVM_VERSION_PATCH: ${{ steps.version.outputs.LLVM_VERSION_PATCH }} @@ -51,9 +50,9 @@ jobs: id: vars run: | remote_repo='https://github.com/llvm/llvm-project' - if [ ${{ steps.version.outputs.LLVM_VERSION_MINOR }} -ne 0 ] || [ ${{ steps.version.outputs.LLVM_VERSION_PATCH }} -eq 0 ]; then + if [ ${{ steps.version.outputs.LLVM_VERSION_PATCH }} -eq 0 ]; then major_version=$(( ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - 1)) - baseline_ref="llvmorg-$major_version.0.0" + baseline_ref="llvmorg-$major_version.1.0" # If there is a minor release, we want to use that as the base line. minor_ref=$(git ls-remote --refs -t "$remote_repo" llvmorg-"$major_version".[1-9].[0-9] | tail -n1 | grep -o 'llvmorg-.\+' || true) @@ -75,7 +74,7 @@ jobs: else { echo "BASELINE_VERSION_MAJOR=${{ steps.version.outputs.LLVM_VERSION_MAJOR }}" - echo "BASELINE_REF=llvmorg-${{ steps.version.outputs.LLVM_VERSION_MAJOR }}.0.0" + echo "BASELINE_REF=llvmorg-${{ steps.version.outputs.LLVM_VERSION_MAJOR }}.1.0" echo "ABI_HEADERS=." echo "ABI_LIBS=libclang.so libclang-cpp.so" } >> "$GITHUB_OUTPUT" -- GitLab From 97418bb519d90542aad3c1f82c80264381a5758e Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 15 May 2024 14:03:13 +0100 Subject: [PATCH 344/578] [X86] patchable functions - cleanup check prefixes identified in #92248 Avoid using numbers as check prefix - replace with actual triple config names --- .../X86/patchable-function-entry-ibt.ll | 44 +++--- .../CodeGen/X86/patchable-function-entry.ll | 62 ++++---- llvm/test/CodeGen/X86/patchable-prologue.ll | 134 +++++++++--------- 3 files changed, 120 insertions(+), 120 deletions(-) diff --git a/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll b/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll index d0a9bee7878c..bcb1106de749 100644 --- a/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll +++ b/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll @@ -1,5 +1,5 @@ -; RUN: llc -mtriple=i686 %s -o - | FileCheck --check-prefixes=CHECK,32 %s -; RUN: llc -mtriple=x86_64 %s -o - | FileCheck --check-prefixes=CHECK,64 %s +; RUN: llc -mtriple=i686 %s -o - | FileCheck --check-prefixes=CHECK,X86 %s +; RUN: llc -mtriple=x86_64 %s -o - | FileCheck --check-prefixes=CHECK,X64 %s ;; -fpatchable-function-entry=0 -fcf-protection=branch define void @f0() "patchable-function-entry"="0" { @@ -7,8 +7,8 @@ define void @f0() "patchable-function-entry"="0" { ; CHECK-NEXT: .Lfunc_begin0: ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: # %bb.0: -; 32-NEXT: endbr32 -; 64-NEXT: endbr64 +; X86-NEXT: endbr32 +; X64-NEXT: endbr64 ; CHECK-NEXT: ret ; CHECK-NOT: .section __patchable_function_entries ret void @@ -22,16 +22,16 @@ define void @f1() "patchable-function-entry"="1" { ; CHECK-NEXT: .Lfunc_begin1: ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: # %bb.0: -; 32-NEXT: endbr32 -; 64-NEXT: endbr64 +; X86-NEXT: endbr32 +; X64-NEXT: endbr64 ; CHECK-NEXT: .Lpatch0: ; CHECK-NEXT: nop ; CHECK-NEXT: ret ; CHECK: .section __patchable_function_entries,"awo",@progbits,f1{{$}} -; 32-NEXT: .p2align 2 -; 32-NEXT: .long .Lpatch0 -; 64-NEXT: .p2align 3 -; 64-NEXT: .quad .Lpatch0 +; X86-NEXT: .p2align 2 +; X86-NEXT: .long .Lpatch0 +; X64-NEXT: .p2align 3 +; X64-NEXT: .quad .Lpatch0 ret void } @@ -44,17 +44,17 @@ define void @f2_1() "patchable-function-entry"="1" "patchable-function-prefix"=" ; CHECK-NEXT: .Lfunc_begin2: ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: # %bb.0: -; 32-NEXT: endbr32 -; 64-NEXT: endbr64 +; X86-NEXT: endbr32 +; X64-NEXT: endbr64 ; CHECK-NEXT: nop ; CHECK-NEXT: ret ; CHECK: .Lfunc_end2: ; CHECK-NEXT: .size f2_1, .Lfunc_end2-f2_1 ; CHECK: .section __patchable_function_entries,"awo",@progbits,f2_1{{$}} -; 32-NEXT: .p2align 2 -; 32-NEXT: .long .Ltmp0 -; 64-NEXT: .p2align 3 -; 64-NEXT: .quad .Ltmp0 +; X86-NEXT: .p2align 2 +; X86-NEXT: .long .Ltmp0 +; X64-NEXT: .p2align 3 +; X64-NEXT: .quad .Ltmp0 ret void } @@ -74,10 +74,10 @@ define internal void @f1i() "patchable-function-entry"="1" { ;; Another basic block has ENDBR, but it doesn't affect our decision to not create .Lpatch0 ; CHECK: endbr ; CHECK: .section __patchable_function_entries,"awo",@progbits,f1i{{$}} -; 32-NEXT: .p2align 2 -; 32-NEXT: .long .Lfunc_begin3 -; 64-NEXT: .p2align 3 -; 64-NEXT: .quad .Lfunc_begin3 +; X86-NEXT: .p2align 2 +; X86-NEXT: .long .Lfunc_begin3 +; X64-NEXT: .p2align 3 +; X64-NEXT: .quad .Lfunc_begin3 entry: tail call i32 @llvm.eh.sjlj.setjmp(ptr @buf) ret void @@ -93,8 +93,8 @@ entry: ; CHECK-NEXT: .Lfunc_begin{{.*}}: ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: # %bb.0: -; 32-NEXT: endbr32 -; 64-NEXT: endbr64 +; X86-NEXT: endbr32 +; X64-NEXT: endbr64 ; CHECK-NEXT: nop ; CHECK-NEXT: ret define void @sanitize_function(ptr noundef %x) "patchable-function-prefix"="1" "patchable-function-entry"="1" !func_sanitize !1 { diff --git a/llvm/test/CodeGen/X86/patchable-function-entry.ll b/llvm/test/CodeGen/X86/patchable-function-entry.ll index 8c37f5451080..54ecd8b1e5da 100644 --- a/llvm/test/CodeGen/X86/patchable-function-entry.ll +++ b/llvm/test/CodeGen/X86/patchable-function-entry.ll @@ -1,6 +1,6 @@ -; RUN: llc -mtriple=i386 %s -o - | FileCheck --check-prefixes=CHECK,32 %s -; RUN: llc -mtriple=x86_64 %s -o - | FileCheck --check-prefixes=CHECK,64 %s -; RUN: llc -mtriple=x86_64 -function-sections %s -o - | FileCheck --check-prefixes=CHECK,64 %s +; RUN: llc -mtriple=i386 %s -o - | FileCheck --check-prefixes=CHECK,X86 %s +; RUN: llc -mtriple=x86_64 %s -o - | FileCheck --check-prefixes=CHECK,X64 %s +; RUN: llc -mtriple=x86_64 -function-sections %s -o - | FileCheck --check-prefixes=CHECK,X64 %s define void @f0() "patchable-function-entry"="0" { ; CHECK-LABEL: f0: @@ -17,10 +17,10 @@ define void @f1() "patchable-function-entry"="1" { ; CHECK: nop ; CHECK-NEXT: ret ; CHECK: .section __patchable_function_entries,"awo",@progbits,f1{{$}} -; 32: .p2align 2 -; 32-NEXT: .long .Lfunc_begin1 -; 64: .p2align 3 -; 64-NEXT: .quad .Lfunc_begin1 +; X86: .p2align 2 +; X86-NEXT: .long .Lfunc_begin1 +; X64: .p2align 3 +; X64-NEXT: .quad .Lfunc_begin1 ret void } @@ -31,14 +31,14 @@ define void @f1() "patchable-function-entry"="1" { define void @f2() "patchable-function-entry"="2" { ; CHECK-LABEL: f2: ; CHECK-NEXT: .Lfunc_begin2: -; 32: xchgw %ax, %ax -; 64: xchgw %ax, %ax +; X86: xchgw %ax, %ax +; X64: xchgw %ax, %ax ; CHECK-NEXT: ret ; CHECK: .section __patchable_function_entries,"awo",@progbits,f2{{$}} -; 32: .p2align 2 -; 32-NEXT: .long .Lfunc_begin2 -; 64: .p2align 3 -; 64-NEXT: .quad .Lfunc_begin2 +; X86: .p2align 2 +; X86-NEXT: .long .Lfunc_begin2 +; X64: .p2align 3 +; X64-NEXT: .quad .Lfunc_begin2 ret void } @@ -46,15 +46,15 @@ $f3 = comdat any define void @f3() "patchable-function-entry"="3" comdat { ; CHECK-LABEL: f3: ; CHECK-NEXT: .Lfunc_begin3: -; 32: xchgw %ax, %ax -; 32-NEXT: nop -; 64: nopl (%rax) +; X86: xchgw %ax, %ax +; X86-NEXT: nop +; X64: nopl (%rax) ; CHECK: ret ; CHECK: .section __patchable_function_entries,"awoG",@progbits,f3,f3,comdat{{$}} -; 32: .p2align 2 -; 32-NEXT: .long .Lfunc_begin3 -; 64: .p2align 3 -; 64-NEXT: .quad .Lfunc_begin3 +; X86: .p2align 2 +; X86-NEXT: .long .Lfunc_begin3 +; X64: .p2align 3 +; X64-NEXT: .quad .Lfunc_begin3 ret void } @@ -62,15 +62,15 @@ $f5 = comdat any define void @f5() "patchable-function-entry"="5" comdat { ; CHECK-LABEL: f5: ; CHECK-NEXT: .Lfunc_begin4: -; 32-COUNT-2: xchgw %ax, %ax -; 32-NEXT: nop -; 64: nopl 8(%rax,%rax) +; X86-COUNT-2: xchgw %ax, %ax +; X86-NEXT: nop +; X64: nopl 8(%rax,%rax) ; CHECK-NEXT: ret ; CHECK: .section __patchable_function_entries,"awoG",@progbits,f5,f5,comdat{{$}} -; 32: .p2align 2 -; 32-NEXT: .long .Lfunc_begin4 -; 64: .p2align 3 -; 64-NEXT: .quad .Lfunc_begin4 +; X86: .p2align 2 +; X86-NEXT: .long .Lfunc_begin4 +; X64: .p2align 3 +; X64-NEXT: .quad .Lfunc_begin4 ret void } @@ -91,10 +91,10 @@ define void @f3_2() "patchable-function-entry"="1" "patchable-function-prefix"=" ; CHECK: .Lfunc_end5: ; CHECK-NEXT: .size f3_2, .Lfunc_end5-f3_2 ; CHECK: .section __patchable_function_entries,"awo",@progbits,f3_2{{$}} -; 32: .p2align 2 -; 32-NEXT: .long .Ltmp0 -; 64: .p2align 3 -; 64-NEXT: .quad .Ltmp0 +; X86: .p2align 2 +; X86-NEXT: .long .Ltmp0 +; X64: .p2align 3 +; X64-NEXT: .quad .Ltmp0 %frame = alloca i8, i32 16 ret void } diff --git a/llvm/test/CodeGen/X86/patchable-prologue.ll b/llvm/test/CodeGen/X86/patchable-prologue.ll index 43761e3d1e1e..aec76a359d26 100644 --- a/llvm/test/CodeGen/X86/patchable-prologue.ll +++ b/llvm/test/CodeGen/X86/patchable-prologue.ll @@ -1,10 +1,10 @@ ; RUN: llc -verify-machineinstrs -filetype=obj -o - -mtriple=x86_64-apple-macosx < %s | llvm-objdump --no-print-imm-hex --triple=x86_64-apple-macosx -d - | FileCheck %s ; RUN: llc -verify-machineinstrs -mtriple=x86_64-apple-macosx < %s | FileCheck %s --check-prefix=CHECK-ALIGN -; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386 < %s | FileCheck %s --check-prefixes=32,32CFI,XCHG -; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386-windows-msvc < %s | FileCheck %s --check-prefixes=32,MOV -; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386-windows-msvc -mcpu=pentium3 < %s | FileCheck %s --check-prefixes=32,MOV -; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386-windows-msvc -mcpu=pentium4 < %s | FileCheck %s --check-prefixes=32,XCHG -; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=x86_64-windows-msvc < %s | FileCheck %s --check-prefix=64 +; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386 < %s | FileCheck %s --check-prefixes=X86,X86CFI,XCHG +; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386-windows-msvc < %s | FileCheck %s --check-prefixes=X86,MOV +; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386-windows-msvc -mcpu=pentium3 < %s | FileCheck %s --check-prefixes=X86,MOV +; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386-windows-msvc -mcpu=pentium4 < %s | FileCheck %s --check-prefixes=X86,XCHG +; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=x86_64-windows-msvc < %s | FileCheck %s --check-prefix=X64 declare void @callee(ptr) @@ -15,18 +15,18 @@ define void @f0() "patchable-function"="prologue-short-redirect" { ; CHECK-ALIGN: .p2align 4, 0x90 ; CHECK-ALIGN: _f0: -; 32: f0: -; 32CFI-NEXT: .cfi_startproc -; 32-NEXT: # %bb.0: +; X86: f0: +; X86CFI-NEXT: .cfi_startproc +; X86-NEXT: # %bb.0: ; XCHG-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90] ; MOV-NEXT: movl %edi, %edi # encoding: [0x8b,0xff] -; 32-NEXT: retl +; X86-NEXT: retl + +; X64: f0: +; X64-NEXT: # %bb.0: +; X64-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90] +; X64-NEXT: retq -; 64: f0: -; 64-NEXT: # %bb.0: -; 64-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90] -; 64-NEXT: retq - ret void } @@ -38,19 +38,19 @@ define void @f1() "patchable-function"="prologue-short-redirect" "frame-pointer" ; CHECK-ALIGN: .p2align 4, 0x90 ; CHECK-ALIGN: _f1: -; 32: f1: -; 32CFI-NEXT: .cfi_startproc -; 32-NEXT: # %bb.0: +; X86: f1: +; X86CFI-NEXT: .cfi_startproc +; X86-NEXT: # %bb.0: ; XCHG-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90] ; MOV-NEXT: movl %edi, %edi # encoding: [0x8b,0xff] -; 32-NEXT: pushl %ebp - -; 64: f1: -; 64-NEXT: .seh_proc f1 -; 64-NEXT: # %bb.0: -; 64-NEXT: xchgw %ax, %ax -; 64-NEXT: pushq %rbp - +; X86-NEXT: pushl %ebp + +; X64: f1: +; X64-NEXT: .seh_proc f1 +; X64-NEXT: # %bb.0: +; X64-NEXT: xchgw %ax, %ax +; X64-NEXT: pushq %rbp + ret void } @@ -61,18 +61,18 @@ define void @f2() "patchable-function"="prologue-short-redirect" { ; CHECK-ALIGN: .p2align 4, 0x90 ; CHECK-ALIGN: _f2: -; 32: f2: -; 32CFI-NEXT: .cfi_startproc -; 32-NEXT: # %bb.0: +; X86: f2: +; X86CFI-NEXT: .cfi_startproc +; X86-NEXT: # %bb.0: ; XCHG-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90] ; MOV-NEXT: movl %edi, %edi # encoding: [0x8b,0xff] -; 32-NEXT: pushl %ebp +; X86-NEXT: pushl %ebp + +; X64: f2: +; X64-NEXT: .seh_proc f2 +; X64-NEXT: # %bb.0: +; X64-NEXT: subq $200, %rsp -; 64: f2: -; 64-NEXT: .seh_proc f2 -; 64-NEXT: # %bb.0: -; 64-NEXT: subq $200, %rsp - %ptr = alloca i64, i32 20 call void @callee(ptr %ptr) ret void @@ -85,17 +85,17 @@ define void @f3() "patchable-function"="prologue-short-redirect" optsize { ; CHECK-ALIGN: .p2align 4, 0x90 ; CHECK-ALIGN: _f3: -; 32: f3: -; 32CFI-NEXT: .cfi_startproc -; 32-NEXT: # %bb.0: +; X86: f3: +; X86CFI-NEXT: .cfi_startproc +; X86-NEXT: # %bb.0: ; XCHG-NEXT: xchgw %ax, %ax ; MOV-NEXT: movl %edi, %edi -; 32-NEXT: retl +; X86-NEXT: retl -; 64: f3: -; 64-NEXT: # %bb.0: -; 64-NEXT: xchgw %ax, %ax -; 64-NEXT: retq +; X64: f3: +; X64-NEXT: # %bb.0: +; X64-NEXT: xchgw %ax, %ax +; X64-NEXT: retq ret void } @@ -105,16 +105,16 @@ define void @f3() "patchable-function"="prologue-short-redirect" optsize { ; patchable one. ; CHECK-LABEL: f4{{>?}}: ; CHECK-NEXT: 8b 0c 37 movl (%rdi,%rsi), %ecx -; 32: f4: -; 32CFI-NEXT: .cfi_startproc -; 32-NEXT: # %bb.0: +; X86: f4: +; X86CFI-NEXT: .cfi_startproc +; X86-NEXT: # %bb.0: ; XCHG-NEXT: xchgw %ax, %ax ; MOV-NEXT: movl %edi, %edi -; 32-NEXT: pushl %ebx +; X86-NEXT: pushl %ebx -; 64: f4: -; 64-NEXT: # %bb.0: -; 64-NOT: xchgw %ax, %ax +; X64: f4: +; X64-NEXT: # %bb.0: +; X64-NOT: xchgw %ax, %ax define i32 @f4(ptr %arg1, i64 %arg2, i32 %arg3) "patchable-function"="prologue-short-redirect" { bb: @@ -143,15 +143,15 @@ bb21: ; CHECK-ALIGN: .p2align 4, 0x90 ; CHECK-ALIGN: _emptyfunc: -; 32: emptyfunc: -; 32CFI-NEXT: .cfi_startproc -; 32-NEXT: # %bb.0: +; X86: emptyfunc: +; X86CFI-NEXT: .cfi_startproc +; X86-NEXT: # %bb.0: ; XCHG-NEXT: xchgw %ax, %ax ; MOV-NEXT: movl %edi, %edi -; 64: emptyfunc: -; 64-NEXT: # %bb.0: -; 64-NEXT: xchgw %ax, %ax +; X64: emptyfunc: +; X64-NEXT: # %bb.0: +; X64-NEXT: xchgw %ax, %ax ; From code: int emptyfunc() {} define i32 @emptyfunc() "patchable-function"="prologue-short-redirect" { @@ -169,15 +169,15 @@ define i32 @emptyfunc() "patchable-function"="prologue-short-redirect" { ; CHECK-ALIGN: .p2align 4, 0x90 ; CHECK-ALIGN: _jmp_to_start: -; 32: jmp_to_start: -; 32CFI-NEXT: .cfi_startproc -; 32-NEXT: # %bb.0: +; X86: jmp_to_start: +; X86CFI-NEXT: .cfi_startproc +; X86-NEXT: # %bb.0: ; XCHG-NEXT: xchgw %ax, %ax ; MOV-NEXT: movl %edi, %edi -; 64: jmp_to_start: -; 64-NEXT: # %bb.0: -; 64-NEXT: xchgw %ax, %ax +; X64: jmp_to_start: +; X64-NEXT: # %bb.0: +; X64-NEXT: xchgw %ax, %ax define dso_local void @jmp_to_start(ptr inreg nocapture noundef %b) "patchable-function"="prologue-short-redirect" { entry: @@ -198,12 +198,12 @@ do.end: ; preds = %do.body ; Test that inline asm is properly hotpatched. We currently don't examine the ; asm instruction when printing it, thus we always emit patching NOPs. -; 64: inline_asm: -; 64-NEXT: # %bb.0: -; 64-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90] -; 64-NEXT: #APP -; 64-NEXT: int3 # encoding: [0xcc] -; 64-NEXT: #NO_APP +; X64: inline_asm: +; X64-NEXT: # %bb.0: +; X64-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90] +; X64-NEXT: #APP +; X64-NEXT: int3 # encoding: [0xcc] +; X64-NEXT: #NO_APP define dso_local void @inline_asm() "patchable-function"="prologue-short-redirect" { entry: -- GitLab From 96ac2e3af78a45c4fdf4ecc3f9a76cc00663cac7 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 15 May 2024 14:04:42 +0100 Subject: [PATCH 345/578] [X86] cmpxchg-clobber-flags.ll - cleanup check prefixes identified in #92248 Avoid using numbers as check prefix - replace with actual triple config names --- .../test/CodeGen/X86/cmpxchg-clobber-flags.ll | 394 +++++++++--------- 1 file changed, 197 insertions(+), 197 deletions(-) diff --git a/llvm/test/CodeGen/X86/cmpxchg-clobber-flags.ll b/llvm/test/CodeGen/X86/cmpxchg-clobber-flags.ll index 7738ce49a763..29751dcfca5d 100644 --- a/llvm/test/CodeGen/X86/cmpxchg-clobber-flags.ll +++ b/llvm/test/CodeGen/X86/cmpxchg-clobber-flags.ll @@ -1,12 +1,12 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=i386-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=32-ALL,32-GOOD-RA -; RUN: llc -mtriple=i386-linux-gnu -verify-machineinstrs -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefixes=32-ALL,32-FAST-RA +; RUN: llc -mtriple=i386-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=X86-ALL,X86-GOOD-RA +; RUN: llc -mtriple=i386-linux-gnu -verify-machineinstrs -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefixes=X86-ALL,X86-FAST-RA -; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=64-ALL -; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefix=64-ALL -; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mattr=+sahf %s -o - | FileCheck %s --check-prefix=64-ALL -; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mattr=+sahf -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefix=64-ALL -; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mcpu=corei7 %s -o - | FileCheck %s --check-prefix=64-ALL +; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=X64-ALL +; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefix=X64-ALL +; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mattr=+sahf %s -o - | FileCheck %s --check-prefix=X64-ALL +; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mattr=+sahf -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefix=X64-ALL +; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mcpu=corei7 %s -o - | FileCheck %s --check-prefix=X64-ALL declare i32 @foo() declare i32 @bar(i64) @@ -24,86 +24,86 @@ declare i32 @bar(i64) ; repeated saving and restoring logic and can be trivially managed by the ; register allocator. define i64 @test_intervening_call(ptr %foo, i64 %bar, i64 %baz) nounwind { -; 32-GOOD-RA-LABEL: test_intervening_call: -; 32-GOOD-RA: # %bb.0: # %entry -; 32-GOOD-RA-NEXT: pushl %ebx -; 32-GOOD-RA-NEXT: pushl %esi -; 32-GOOD-RA-NEXT: pushl %eax -; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %eax -; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %edx -; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %ebx -; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx -; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %esi -; 32-GOOD-RA-NEXT: lock cmpxchg8b (%esi) -; 32-GOOD-RA-NEXT: setne %bl -; 32-GOOD-RA-NEXT: subl $8, %esp -; 32-GOOD-RA-NEXT: pushl %edx -; 32-GOOD-RA-NEXT: pushl %eax -; 32-GOOD-RA-NEXT: calll bar@PLT -; 32-GOOD-RA-NEXT: addl $16, %esp -; 32-GOOD-RA-NEXT: testb %bl, %bl -; 32-GOOD-RA-NEXT: jne .LBB0_3 -; 32-GOOD-RA-NEXT: # %bb.1: # %t -; 32-GOOD-RA-NEXT: movl $42, %eax -; 32-GOOD-RA-NEXT: jmp .LBB0_2 -; 32-GOOD-RA-NEXT: .LBB0_3: # %f -; 32-GOOD-RA-NEXT: xorl %eax, %eax -; 32-GOOD-RA-NEXT: .LBB0_2: # %t -; 32-GOOD-RA-NEXT: xorl %edx, %edx -; 32-GOOD-RA-NEXT: addl $4, %esp -; 32-GOOD-RA-NEXT: popl %esi -; 32-GOOD-RA-NEXT: popl %ebx -; 32-GOOD-RA-NEXT: retl +; X86-GOOD-RA-LABEL: test_intervening_call: +; X86-GOOD-RA: # %bb.0: # %entry +; X86-GOOD-RA-NEXT: pushl %ebx +; X86-GOOD-RA-NEXT: pushl %esi +; X86-GOOD-RA-NEXT: pushl %eax +; X86-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-GOOD-RA-NEXT: lock cmpxchg8b (%esi) +; X86-GOOD-RA-NEXT: setne %bl +; X86-GOOD-RA-NEXT: subl $8, %esp +; X86-GOOD-RA-NEXT: pushl %edx +; X86-GOOD-RA-NEXT: pushl %eax +; X86-GOOD-RA-NEXT: calll bar@PLT +; X86-GOOD-RA-NEXT: addl $16, %esp +; X86-GOOD-RA-NEXT: testb %bl, %bl +; X86-GOOD-RA-NEXT: jne .LBB0_3 +; X86-GOOD-RA-NEXT: # %bb.1: # %t +; X86-GOOD-RA-NEXT: movl $42, %eax +; X86-GOOD-RA-NEXT: jmp .LBB0_2 +; X86-GOOD-RA-NEXT: .LBB0_3: # %f +; X86-GOOD-RA-NEXT: xorl %eax, %eax +; X86-GOOD-RA-NEXT: .LBB0_2: # %t +; X86-GOOD-RA-NEXT: xorl %edx, %edx +; X86-GOOD-RA-NEXT: addl $4, %esp +; X86-GOOD-RA-NEXT: popl %esi +; X86-GOOD-RA-NEXT: popl %ebx +; X86-GOOD-RA-NEXT: retl ; -; 32-FAST-RA-LABEL: test_intervening_call: -; 32-FAST-RA: # %bb.0: # %entry -; 32-FAST-RA-NEXT: pushl %ebx -; 32-FAST-RA-NEXT: pushl %esi -; 32-FAST-RA-NEXT: pushl %eax -; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %esi -; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %ebx -; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx -; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %eax -; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %edx -; 32-FAST-RA-NEXT: lock cmpxchg8b (%esi) -; 32-FAST-RA-NEXT: setne %bl -; 32-FAST-RA-NEXT: subl $8, %esp -; 32-FAST-RA-NEXT: pushl %edx -; 32-FAST-RA-NEXT: pushl %eax -; 32-FAST-RA-NEXT: calll bar@PLT -; 32-FAST-RA-NEXT: addl $16, %esp -; 32-FAST-RA-NEXT: testb %bl, %bl -; 32-FAST-RA-NEXT: jne .LBB0_3 -; 32-FAST-RA-NEXT: # %bb.1: # %t -; 32-FAST-RA-NEXT: movl $42, %eax -; 32-FAST-RA-NEXT: jmp .LBB0_2 -; 32-FAST-RA-NEXT: .LBB0_3: # %f -; 32-FAST-RA-NEXT: xorl %eax, %eax -; 32-FAST-RA-NEXT: .LBB0_2: # %t -; 32-FAST-RA-NEXT: xorl %edx, %edx -; 32-FAST-RA-NEXT: addl $4, %esp -; 32-FAST-RA-NEXT: popl %esi -; 32-FAST-RA-NEXT: popl %ebx -; 32-FAST-RA-NEXT: retl +; X86-FAST-RA-LABEL: test_intervening_call: +; X86-FAST-RA: # %bb.0: # %entry +; X86-FAST-RA-NEXT: pushl %ebx +; X86-FAST-RA-NEXT: pushl %esi +; X86-FAST-RA-NEXT: pushl %eax +; X86-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-FAST-RA-NEXT: lock cmpxchg8b (%esi) +; X86-FAST-RA-NEXT: setne %bl +; X86-FAST-RA-NEXT: subl $8, %esp +; X86-FAST-RA-NEXT: pushl %edx +; X86-FAST-RA-NEXT: pushl %eax +; X86-FAST-RA-NEXT: calll bar@PLT +; X86-FAST-RA-NEXT: addl $16, %esp +; X86-FAST-RA-NEXT: testb %bl, %bl +; X86-FAST-RA-NEXT: jne .LBB0_3 +; X86-FAST-RA-NEXT: # %bb.1: # %t +; X86-FAST-RA-NEXT: movl $42, %eax +; X86-FAST-RA-NEXT: jmp .LBB0_2 +; X86-FAST-RA-NEXT: .LBB0_3: # %f +; X86-FAST-RA-NEXT: xorl %eax, %eax +; X86-FAST-RA-NEXT: .LBB0_2: # %t +; X86-FAST-RA-NEXT: xorl %edx, %edx +; X86-FAST-RA-NEXT: addl $4, %esp +; X86-FAST-RA-NEXT: popl %esi +; X86-FAST-RA-NEXT: popl %ebx +; X86-FAST-RA-NEXT: retl ; -; 64-ALL-LABEL: test_intervening_call: -; 64-ALL: # %bb.0: # %entry -; 64-ALL-NEXT: pushq %rbx -; 64-ALL-NEXT: movq %rsi, %rax -; 64-ALL-NEXT: lock cmpxchgq %rdx, (%rdi) -; 64-ALL-NEXT: setne %bl -; 64-ALL-NEXT: movq %rax, %rdi -; 64-ALL-NEXT: callq bar@PLT -; 64-ALL-NEXT: testb %bl, %bl -; 64-ALL-NEXT: jne .LBB0_2 -; 64-ALL-NEXT: # %bb.1: # %t -; 64-ALL-NEXT: movl $42, %eax -; 64-ALL-NEXT: popq %rbx -; 64-ALL-NEXT: retq -; 64-ALL-NEXT: .LBB0_2: # %f -; 64-ALL-NEXT: xorl %eax, %eax -; 64-ALL-NEXT: popq %rbx -; 64-ALL-NEXT: retq +; X64-ALL-LABEL: test_intervening_call: +; X64-ALL: # %bb.0: # %entry +; X64-ALL-NEXT: pushq %rbx +; X64-ALL-NEXT: movq %rsi, %rax +; X64-ALL-NEXT: lock cmpxchgq %rdx, (%rdi) +; X64-ALL-NEXT: setne %bl +; X64-ALL-NEXT: movq %rax, %rdi +; X64-ALL-NEXT: callq bar@PLT +; X64-ALL-NEXT: testb %bl, %bl +; X64-ALL-NEXT: jne .LBB0_2 +; X64-ALL-NEXT: # %bb.1: # %t +; X64-ALL-NEXT: movl $42, %eax +; X64-ALL-NEXT: popq %rbx +; X64-ALL-NEXT: retq +; X64-ALL-NEXT: .LBB0_2: # %f +; X64-ALL-NEXT: xorl %eax, %eax +; X64-ALL-NEXT: popq %rbx +; X64-ALL-NEXT: retq entry: %cx = cmpxchg ptr %foo, i64 %bar, i64 %baz seq_cst seq_cst %v = extractvalue { i64, i1 } %cx, 0 @@ -120,61 +120,61 @@ f: ; Interesting in producing a clobber without any function calls. define i32 @test_control_flow(ptr %p, i32 %i, i32 %j) nounwind { -; 32-ALL-LABEL: test_control_flow: -; 32-ALL: # %bb.0: # %entry -; 32-ALL-NEXT: movl {{[0-9]+}}(%esp), %eax -; 32-ALL-NEXT: cmpl {{[0-9]+}}(%esp), %eax -; 32-ALL-NEXT: jle .LBB1_6 -; 32-ALL-NEXT: # %bb.1: # %loop_start -; 32-ALL-NEXT: movl {{[0-9]+}}(%esp), %ecx -; 32-ALL-NEXT: .p2align 4, 0x90 -; 32-ALL-NEXT: .LBB1_2: # %while.condthread-pre-split.i -; 32-ALL-NEXT: # =>This Loop Header: Depth=1 -; 32-ALL-NEXT: # Child Loop BB1_3 Depth 2 -; 32-ALL-NEXT: movl (%ecx), %edx -; 32-ALL-NEXT: .p2align 4, 0x90 -; 32-ALL-NEXT: .LBB1_3: # %while.cond.i -; 32-ALL-NEXT: # Parent Loop BB1_2 Depth=1 -; 32-ALL-NEXT: # => This Inner Loop Header: Depth=2 -; 32-ALL-NEXT: movl %edx, %eax -; 32-ALL-NEXT: xorl %edx, %edx -; 32-ALL-NEXT: testl %eax, %eax -; 32-ALL-NEXT: je .LBB1_3 -; 32-ALL-NEXT: # %bb.4: # %while.body.i -; 32-ALL-NEXT: # in Loop: Header=BB1_2 Depth=1 -; 32-ALL-NEXT: lock cmpxchgl %eax, (%ecx) -; 32-ALL-NEXT: jne .LBB1_2 -; 32-ALL-NEXT: # %bb.5: -; 32-ALL-NEXT: xorl %eax, %eax -; 32-ALL-NEXT: .LBB1_6: # %cond.end -; 32-ALL-NEXT: retl +; X86-ALL-LABEL: test_control_flow: +; X86-ALL: # %bb.0: # %entry +; X86-ALL-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-ALL-NEXT: cmpl {{[0-9]+}}(%esp), %eax +; X86-ALL-NEXT: jle .LBB1_6 +; X86-ALL-NEXT: # %bb.1: # %loop_start +; X86-ALL-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-ALL-NEXT: .p2align 4, 0x90 +; X86-ALL-NEXT: .LBB1_2: # %while.condthread-pre-split.i +; X86-ALL-NEXT: # =>This Loop Header: Depth=1 +; X86-ALL-NEXT: # Child Loop BB1_3 Depth 2 +; X86-ALL-NEXT: movl (%ecx), %edx +; X86-ALL-NEXT: .p2align 4, 0x90 +; X86-ALL-NEXT: .LBB1_3: # %while.cond.i +; X86-ALL-NEXT: # Parent Loop BB1_2 Depth=1 +; X86-ALL-NEXT: # => This Inner Loop Header: Depth=2 +; X86-ALL-NEXT: movl %edx, %eax +; X86-ALL-NEXT: xorl %edx, %edx +; X86-ALL-NEXT: testl %eax, %eax +; X86-ALL-NEXT: je .LBB1_3 +; X86-ALL-NEXT: # %bb.4: # %while.body.i +; X86-ALL-NEXT: # in Loop: Header=BB1_2 Depth=1 +; X86-ALL-NEXT: lock cmpxchgl %eax, (%ecx) +; X86-ALL-NEXT: jne .LBB1_2 +; X86-ALL-NEXT: # %bb.5: +; X86-ALL-NEXT: xorl %eax, %eax +; X86-ALL-NEXT: .LBB1_6: # %cond.end +; X86-ALL-NEXT: retl ; -; 64-ALL-LABEL: test_control_flow: -; 64-ALL: # %bb.0: # %entry -; 64-ALL-NEXT: movl %esi, %eax -; 64-ALL-NEXT: cmpl %edx, %esi -; 64-ALL-NEXT: jle .LBB1_5 -; 64-ALL-NEXT: .p2align 4, 0x90 -; 64-ALL-NEXT: .LBB1_1: # %while.condthread-pre-split.i -; 64-ALL-NEXT: # =>This Loop Header: Depth=1 -; 64-ALL-NEXT: # Child Loop BB1_2 Depth 2 -; 64-ALL-NEXT: movl (%rdi), %ecx -; 64-ALL-NEXT: .p2align 4, 0x90 -; 64-ALL-NEXT: .LBB1_2: # %while.cond.i -; 64-ALL-NEXT: # Parent Loop BB1_1 Depth=1 -; 64-ALL-NEXT: # => This Inner Loop Header: Depth=2 -; 64-ALL-NEXT: movl %ecx, %eax -; 64-ALL-NEXT: xorl %ecx, %ecx -; 64-ALL-NEXT: testl %eax, %eax -; 64-ALL-NEXT: je .LBB1_2 -; 64-ALL-NEXT: # %bb.3: # %while.body.i -; 64-ALL-NEXT: # in Loop: Header=BB1_1 Depth=1 -; 64-ALL-NEXT: lock cmpxchgl %eax, (%rdi) -; 64-ALL-NEXT: jne .LBB1_1 -; 64-ALL-NEXT: # %bb.4: -; 64-ALL-NEXT: xorl %eax, %eax -; 64-ALL-NEXT: .LBB1_5: # %cond.end -; 64-ALL-NEXT: retq +; X64-ALL-LABEL: test_control_flow: +; X64-ALL: # %bb.0: # %entry +; X64-ALL-NEXT: movl %esi, %eax +; X64-ALL-NEXT: cmpl %edx, %esi +; X64-ALL-NEXT: jle .LBB1_5 +; X64-ALL-NEXT: .p2align 4, 0x90 +; X64-ALL-NEXT: .LBB1_1: # %while.condthread-pre-split.i +; X64-ALL-NEXT: # =>This Loop Header: Depth=1 +; X64-ALL-NEXT: # Child Loop BB1_2 Depth 2 +; X64-ALL-NEXT: movl (%rdi), %ecx +; X64-ALL-NEXT: .p2align 4, 0x90 +; X64-ALL-NEXT: .LBB1_2: # %while.cond.i +; X64-ALL-NEXT: # Parent Loop BB1_1 Depth=1 +; X64-ALL-NEXT: # => This Inner Loop Header: Depth=2 +; X64-ALL-NEXT: movl %ecx, %eax +; X64-ALL-NEXT: xorl %ecx, %ecx +; X64-ALL-NEXT: testl %eax, %eax +; X64-ALL-NEXT: je .LBB1_2 +; X64-ALL-NEXT: # %bb.3: # %while.body.i +; X64-ALL-NEXT: # in Loop: Header=BB1_1 Depth=1 +; X64-ALL-NEXT: lock cmpxchgl %eax, (%rdi) +; X64-ALL-NEXT: jne .LBB1_1 +; X64-ALL-NEXT: # %bb.4: +; X64-ALL-NEXT: xorl %eax, %eax +; X64-ALL-NEXT: .LBB1_5: # %cond.end +; X64-ALL-NEXT: retq entry: %cmp = icmp sgt i32 %i, %j br i1 %cmp, label %loop_start, label %cond.end @@ -208,66 +208,66 @@ cond.end: ; This one is an interesting case because CMOV doesn't have a chain ; operand. Naive attempts to limit cmpxchg EFLAGS use are likely to fail here. define i32 @test_feed_cmov(ptr %addr, i32 %desired, i32 %new) nounwind { -; 32-GOOD-RA-LABEL: test_feed_cmov: -; 32-GOOD-RA: # %bb.0: # %entry -; 32-GOOD-RA-NEXT: pushl %ebx -; 32-GOOD-RA-NEXT: pushl %esi -; 32-GOOD-RA-NEXT: pushl %eax -; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %eax -; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %esi -; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx -; 32-GOOD-RA-NEXT: lock cmpxchgl %esi, (%ecx) -; 32-GOOD-RA-NEXT: sete %bl -; 32-GOOD-RA-NEXT: calll foo@PLT -; 32-GOOD-RA-NEXT: testb %bl, %bl -; 32-GOOD-RA-NEXT: jne .LBB2_2 -; 32-GOOD-RA-NEXT: # %bb.1: # %entry -; 32-GOOD-RA-NEXT: movl %eax, %esi -; 32-GOOD-RA-NEXT: .LBB2_2: # %entry -; 32-GOOD-RA-NEXT: movl %esi, %eax -; 32-GOOD-RA-NEXT: addl $4, %esp -; 32-GOOD-RA-NEXT: popl %esi -; 32-GOOD-RA-NEXT: popl %ebx -; 32-GOOD-RA-NEXT: retl +; X86-GOOD-RA-LABEL: test_feed_cmov: +; X86-GOOD-RA: # %bb.0: # %entry +; X86-GOOD-RA-NEXT: pushl %ebx +; X86-GOOD-RA-NEXT: pushl %esi +; X86-GOOD-RA-NEXT: pushl %eax +; X86-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-GOOD-RA-NEXT: lock cmpxchgl %esi, (%ecx) +; X86-GOOD-RA-NEXT: sete %bl +; X86-GOOD-RA-NEXT: calll foo@PLT +; X86-GOOD-RA-NEXT: testb %bl, %bl +; X86-GOOD-RA-NEXT: jne .LBB2_2 +; X86-GOOD-RA-NEXT: # %bb.1: # %entry +; X86-GOOD-RA-NEXT: movl %eax, %esi +; X86-GOOD-RA-NEXT: .LBB2_2: # %entry +; X86-GOOD-RA-NEXT: movl %esi, %eax +; X86-GOOD-RA-NEXT: addl $4, %esp +; X86-GOOD-RA-NEXT: popl %esi +; X86-GOOD-RA-NEXT: popl %ebx +; X86-GOOD-RA-NEXT: retl ; -; 32-FAST-RA-LABEL: test_feed_cmov: -; 32-FAST-RA: # %bb.0: # %entry -; 32-FAST-RA-NEXT: pushl %ebx -; 32-FAST-RA-NEXT: pushl %esi -; 32-FAST-RA-NEXT: pushl %eax -; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx -; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %esi -; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %eax -; 32-FAST-RA-NEXT: lock cmpxchgl %esi, (%ecx) -; 32-FAST-RA-NEXT: sete %bl -; 32-FAST-RA-NEXT: calll foo@PLT -; 32-FAST-RA-NEXT: testb %bl, %bl -; 32-FAST-RA-NEXT: jne .LBB2_2 -; 32-FAST-RA-NEXT: # %bb.1: # %entry -; 32-FAST-RA-NEXT: movl %eax, %esi -; 32-FAST-RA-NEXT: .LBB2_2: # %entry -; 32-FAST-RA-NEXT: movl %esi, %eax -; 32-FAST-RA-NEXT: addl $4, %esp -; 32-FAST-RA-NEXT: popl %esi -; 32-FAST-RA-NEXT: popl %ebx -; 32-FAST-RA-NEXT: retl +; X86-FAST-RA-LABEL: test_feed_cmov: +; X86-FAST-RA: # %bb.0: # %entry +; X86-FAST-RA-NEXT: pushl %ebx +; X86-FAST-RA-NEXT: pushl %esi +; X86-FAST-RA-NEXT: pushl %eax +; X86-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-FAST-RA-NEXT: lock cmpxchgl %esi, (%ecx) +; X86-FAST-RA-NEXT: sete %bl +; X86-FAST-RA-NEXT: calll foo@PLT +; X86-FAST-RA-NEXT: testb %bl, %bl +; X86-FAST-RA-NEXT: jne .LBB2_2 +; X86-FAST-RA-NEXT: # %bb.1: # %entry +; X86-FAST-RA-NEXT: movl %eax, %esi +; X86-FAST-RA-NEXT: .LBB2_2: # %entry +; X86-FAST-RA-NEXT: movl %esi, %eax +; X86-FAST-RA-NEXT: addl $4, %esp +; X86-FAST-RA-NEXT: popl %esi +; X86-FAST-RA-NEXT: popl %ebx +; X86-FAST-RA-NEXT: retl ; -; 64-ALL-LABEL: test_feed_cmov: -; 64-ALL: # %bb.0: # %entry -; 64-ALL-NEXT: pushq %rbp -; 64-ALL-NEXT: pushq %rbx -; 64-ALL-NEXT: pushq %rax -; 64-ALL-NEXT: movl %edx, %ebx -; 64-ALL-NEXT: movl %esi, %eax -; 64-ALL-NEXT: lock cmpxchgl %edx, (%rdi) -; 64-ALL-NEXT: sete %bpl -; 64-ALL-NEXT: callq foo@PLT -; 64-ALL-NEXT: testb %bpl, %bpl -; 64-ALL-NEXT: cmovnel %ebx, %eax -; 64-ALL-NEXT: addq $8, %rsp -; 64-ALL-NEXT: popq %rbx -; 64-ALL-NEXT: popq %rbp -; 64-ALL-NEXT: retq +; X64-ALL-LABEL: test_feed_cmov: +; X64-ALL: # %bb.0: # %entry +; X64-ALL-NEXT: pushq %rbp +; X64-ALL-NEXT: pushq %rbx +; X64-ALL-NEXT: pushq %rax +; X64-ALL-NEXT: movl %edx, %ebx +; X64-ALL-NEXT: movl %esi, %eax +; X64-ALL-NEXT: lock cmpxchgl %edx, (%rdi) +; X64-ALL-NEXT: sete %bpl +; X64-ALL-NEXT: callq foo@PLT +; X64-ALL-NEXT: testb %bpl, %bpl +; X64-ALL-NEXT: cmovnel %ebx, %eax +; X64-ALL-NEXT: addq $8, %rsp +; X64-ALL-NEXT: popq %rbx +; X64-ALL-NEXT: popq %rbp +; X64-ALL-NEXT: retq entry: %res = cmpxchg ptr %addr, i32 %desired, i32 %new seq_cst seq_cst %success = extractvalue { i32, i1 } %res, 1 -- GitLab From e26eacf771fed3226058a84d5d83f94994f583b2 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 15 May 2024 14:10:56 +0100 Subject: [PATCH 346/578] [X86] prefetch.ll - cleanup check prefixes identified in #92248 Avoid using leading numbers in check prefixes - replace with actual triple config names (and makes it easier to add X64 test coverage in a future commit). --- llvm/test/CodeGen/X86/prefetch.ll | 138 +++++++++++++++--------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/llvm/test/CodeGen/X86/prefetch.ll b/llvm/test/CodeGen/X86/prefetch.ll index 3cfa0e3efcb1..404d49b63f25 100644 --- a/llvm/test/CodeGen/X86/prefetch.ll +++ b/llvm/test/CodeGen/X86/prefetch.ll @@ -1,16 +1,16 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=i686-- -mattr=+sse | FileCheck %s --check-prefix=SSE -; RUN: llc < %s -mtriple=i686-- -mattr=+avx | FileCheck %s --check-prefix=SSE -; RUN: llc < %s -mtriple=i686-- -mattr=+sse,+prfchw | FileCheck %s -check-prefix=PRFCHWSSE -; RUN: llc < %s -mtriple=i686-- -mattr=+prfchw | FileCheck %s -check-prefix=PRFCHWSSE -; RUN: llc < %s -mtriple=i686-- -mcpu=slm | FileCheck %s -check-prefix=PRFCHWSSE -; RUN: llc < %s -mtriple=i686-- -mcpu=btver2 | FileCheck %s -check-prefix=PRFCHWSSE -; RUN: llc < %s -mtriple=i686-- -mcpu=btver2 -mattr=-prfchw | FileCheck %s -check-prefix=SSE -; RUN: llc < %s -mtriple=i686-- -mattr=+sse,+prefetchwt1 | FileCheck %s -check-prefix=PREFETCHWT1 -; RUN: llc < %s -mtriple=i686-- -mattr=-sse,+prefetchwt1 | FileCheck %s -check-prefix=PREFETCHWT1 -; RUN: llc < %s -mtriple=i686-- -mattr=-sse,+3dnow,+prefetchwt1 | FileCheck %s -check-prefix=PREFETCHWT1 -; RUN: llc < %s -mtriple=i686-- -mattr=+3dnow | FileCheck %s -check-prefix=3DNOW -; RUN: llc < %s -mtriple=i686-- -mattr=+3dnow,+prfchw | FileCheck %s -check-prefix=3DNOW +; RUN: llc < %s -mtriple=i686-- -mattr=+sse | FileCheck %s --check-prefix=X86-SSE +; RUN: llc < %s -mtriple=i686-- -mattr=+avx | FileCheck %s --check-prefix=X86-SSE +; RUN: llc < %s -mtriple=i686-- -mattr=+sse,+prfchw | FileCheck %s -check-prefix=X86-PRFCHWSSE +; RUN: llc < %s -mtriple=i686-- -mattr=+prfchw | FileCheck %s -check-prefix=X86-PRFCHWSSE +; RUN: llc < %s -mtriple=i686-- -mcpu=slm | FileCheck %s -check-prefix=X86-PRFCHWSSE +; RUN: llc < %s -mtriple=i686-- -mcpu=btver2 | FileCheck %s -check-prefix=X86-PRFCHWSSE +; RUN: llc < %s -mtriple=i686-- -mcpu=btver2 -mattr=-prfchw | FileCheck %s -check-prefix=X86-SSE +; RUN: llc < %s -mtriple=i686-- -mattr=+sse,+prefetchwt1 | FileCheck %s -check-prefix=X86-PREFETCHWT1 +; RUN: llc < %s -mtriple=i686-- -mattr=-sse,+prefetchwt1 | FileCheck %s -check-prefix=X86-PREFETCHWT1 +; RUN: llc < %s -mtriple=i686-- -mattr=-sse,+3dnow,+prefetchwt1 | FileCheck %s -check-prefix=X86-PREFETCHWT1 +; RUN: llc < %s -mtriple=i686-- -mattr=+3dnow | FileCheck %s -check-prefix=X86-3DNOW +; RUN: llc < %s -mtriple=i686-- -mattr=+3dnow,+prfchw | FileCheck %s -check-prefix=X86-3DNOW ; Rules: ; 3dnow by itself get you just the single prefetch instruction with no hints @@ -22,67 +22,67 @@ ; rdar://10538297 define void @t(ptr %ptr) nounwind { -; SSE-LABEL: t: -; SSE: # %bb.0: # %entry -; SSE-NEXT: movl {{[0-9]+}}(%esp), %eax -; SSE-NEXT: prefetcht2 (%eax) -; SSE-NEXT: prefetcht1 (%eax) -; SSE-NEXT: prefetcht0 (%eax) -; SSE-NEXT: prefetchnta (%eax) -; SSE-NEXT: prefetcht2 (%eax) -; SSE-NEXT: prefetcht1 (%eax) -; SSE-NEXT: prefetcht0 (%eax) -; SSE-NEXT: prefetchnta (%eax) -; SSE-NEXT: retl +; X86-SSE-LABEL: t: +; X86-SSE: # %bb.0: # %entry +; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE-NEXT: prefetcht2 (%eax) +; X86-SSE-NEXT: prefetcht1 (%eax) +; X86-SSE-NEXT: prefetcht0 (%eax) +; X86-SSE-NEXT: prefetchnta (%eax) +; X86-SSE-NEXT: prefetcht2 (%eax) +; X86-SSE-NEXT: prefetcht1 (%eax) +; X86-SSE-NEXT: prefetcht0 (%eax) +; X86-SSE-NEXT: prefetchnta (%eax) +; X86-SSE-NEXT: retl ; -; PRFCHWSSE-LABEL: t: -; PRFCHWSSE: # %bb.0: # %entry -; PRFCHWSSE-NEXT: movl {{[0-9]+}}(%esp), %eax -; PRFCHWSSE-NEXT: prefetcht2 (%eax) -; PRFCHWSSE-NEXT: prefetcht1 (%eax) -; PRFCHWSSE-NEXT: prefetcht0 (%eax) -; PRFCHWSSE-NEXT: prefetchnta (%eax) -; PRFCHWSSE-NEXT: prefetchw (%eax) -; PRFCHWSSE-NEXT: prefetchw (%eax) -; PRFCHWSSE-NEXT: prefetchw (%eax) -; PRFCHWSSE-NEXT: prefetchw (%eax) -; PRFCHWSSE-NEXT: retl +; X86-PRFCHWSSE-LABEL: t: +; X86-PRFCHWSSE: # %bb.0: # %entry +; X86-PRFCHWSSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-PRFCHWSSE-NEXT: prefetcht2 (%eax) +; X86-PRFCHWSSE-NEXT: prefetcht1 (%eax) +; X86-PRFCHWSSE-NEXT: prefetcht0 (%eax) +; X86-PRFCHWSSE-NEXT: prefetchnta (%eax) +; X86-PRFCHWSSE-NEXT: prefetchw (%eax) +; X86-PRFCHWSSE-NEXT: prefetchw (%eax) +; X86-PRFCHWSSE-NEXT: prefetchw (%eax) +; X86-PRFCHWSSE-NEXT: prefetchw (%eax) +; X86-PRFCHWSSE-NEXT: retl ; -; PREFETCHWT1-LABEL: t: -; PREFETCHWT1: # %bb.0: # %entry -; PREFETCHWT1-NEXT: movl {{[0-9]+}}(%esp), %eax -; PREFETCHWT1-NEXT: prefetcht2 (%eax) -; PREFETCHWT1-NEXT: prefetcht1 (%eax) -; PREFETCHWT1-NEXT: prefetcht0 (%eax) -; PREFETCHWT1-NEXT: prefetchnta (%eax) -; PREFETCHWT1-NEXT: prefetchwt1 (%eax) -; PREFETCHWT1-NEXT: prefetchwt1 (%eax) -; PREFETCHWT1-NEXT: prefetchw (%eax) -; PREFETCHWT1-NEXT: prefetchwt1 (%eax) -; PREFETCHWT1-NEXT: retl +; X86-PREFETCHWT1-LABEL: t: +; X86-PREFETCHWT1: # %bb.0: # %entry +; X86-PREFETCHWT1-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-PREFETCHWT1-NEXT: prefetcht2 (%eax) +; X86-PREFETCHWT1-NEXT: prefetcht1 (%eax) +; X86-PREFETCHWT1-NEXT: prefetcht0 (%eax) +; X86-PREFETCHWT1-NEXT: prefetchnta (%eax) +; X86-PREFETCHWT1-NEXT: prefetchwt1 (%eax) +; X86-PREFETCHWT1-NEXT: prefetchwt1 (%eax) +; X86-PREFETCHWT1-NEXT: prefetchw (%eax) +; X86-PREFETCHWT1-NEXT: prefetchwt1 (%eax) +; X86-PREFETCHWT1-NEXT: retl ; -; 3DNOW-LABEL: t: -; 3DNOW: # %bb.0: # %entry -; 3DNOW-NEXT: movl {{[0-9]+}}(%esp), %eax -; 3DNOW-NEXT: prefetch (%eax) -; 3DNOW-NEXT: prefetch (%eax) -; 3DNOW-NEXT: prefetch (%eax) -; 3DNOW-NEXT: prefetch (%eax) -; 3DNOW-NEXT: prefetchw (%eax) -; 3DNOW-NEXT: prefetchw (%eax) -; 3DNOW-NEXT: prefetchw (%eax) -; 3DNOW-NEXT: prefetchw (%eax) -; 3DNOW-NEXT: retl +; X86-3DNOW-LABEL: t: +; X86-3DNOW: # %bb.0: # %entry +; X86-3DNOW-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-3DNOW-NEXT: prefetch (%eax) +; X86-3DNOW-NEXT: prefetch (%eax) +; X86-3DNOW-NEXT: prefetch (%eax) +; X86-3DNOW-NEXT: prefetch (%eax) +; X86-3DNOW-NEXT: prefetchw (%eax) +; X86-3DNOW-NEXT: prefetchw (%eax) +; X86-3DNOW-NEXT: prefetchw (%eax) +; X86-3DNOW-NEXT: prefetchw (%eax) +; X86-3DNOW-NEXT: retl entry: - tail call void @llvm.prefetch( ptr %ptr, i32 0, i32 1, i32 1 ) - tail call void @llvm.prefetch( ptr %ptr, i32 0, i32 2, i32 1 ) - tail call void @llvm.prefetch( ptr %ptr, i32 0, i32 3, i32 1 ) - tail call void @llvm.prefetch( ptr %ptr, i32 0, i32 0, i32 1 ) - tail call void @llvm.prefetch( ptr %ptr, i32 1, i32 1, i32 1 ) - tail call void @llvm.prefetch( ptr %ptr, i32 1, i32 2, i32 1 ) - tail call void @llvm.prefetch( ptr %ptr, i32 1, i32 3, i32 1 ) - tail call void @llvm.prefetch( ptr %ptr, i32 1, i32 0, i32 1 ) - ret void + tail call void @llvm.prefetch( ptr %ptr, i32 0, i32 1, i32 1 ) + tail call void @llvm.prefetch( ptr %ptr, i32 0, i32 2, i32 1 ) + tail call void @llvm.prefetch( ptr %ptr, i32 0, i32 3, i32 1 ) + tail call void @llvm.prefetch( ptr %ptr, i32 0, i32 0, i32 1 ) + tail call void @llvm.prefetch( ptr %ptr, i32 1, i32 1, i32 1 ) + tail call void @llvm.prefetch( ptr %ptr, i32 1, i32 2, i32 1 ) + tail call void @llvm.prefetch( ptr %ptr, i32 1, i32 3, i32 1 ) + tail call void @llvm.prefetch( ptr %ptr, i32 1, i32 0, i32 1 ) + ret void } declare void @llvm.prefetch(ptr, i32, i32, i32) nounwind -- GitLab From 3f07430c383dffad77a120c91df79cbc7d99313c Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 15 May 2024 14:23:46 +0100 Subject: [PATCH 347/578] [X86] avoid-sfb-g-no-change.mir - cleanup check prefixes identified in #92248 Don't include "-LABEL" (or any other FileCheck modifier) in the core check prefix name --- llvm/test/CodeGen/X86/avoid-sfb-g-no-change.mir | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm/test/CodeGen/X86/avoid-sfb-g-no-change.mir b/llvm/test/CodeGen/X86/avoid-sfb-g-no-change.mir index 679a908893f6..93292990dee0 100644 --- a/llvm/test/CodeGen/X86/avoid-sfb-g-no-change.mir +++ b/llvm/test/CodeGen/X86/avoid-sfb-g-no-change.mir @@ -1,5 +1,5 @@ -# RUN: llc %s -run-pass x86-avoid-SFB -mtriple=x86_64-unknown-linux-gnu -o - | FileCheck %s -check-prefixes DEBUG-LABEL,CHECK -# RUN: llc %s -run-pass x86-avoid-SFB -mtriple=x86_64-unknown-linux-gnu -o - | FileCheck %s -check-prefixes NODEBUG-LABEL,CHECK +# RUN: llc %s -run-pass x86-avoid-SFB -mtriple=x86_64-unknown-linux-gnu -o - | FileCheck %s -check-prefixes=CHECK,DEBUG +# RUN: llc %s -run-pass x86-avoid-SFB -mtriple=x86_64-unknown-linux-gnu -o - | FileCheck %s -check-prefixes=CHECK,NODEBUG # # This was generated from: # @@ -202,8 +202,8 @@ body: | MOVAPSmr %1, 1, $noreg, 0, $noreg, killed %2 :: (store (s128) into %ir.p2) RET 0 - ; DEBUG-LABEL: name: debug - ; NODEBUG-LABEL: name: nodebug + ; DEBUG: name: debug + ; NODEBUG: name: nodebug ; CHECK: %1:gr64 = COPY ; CHECK: %0:gr64 = COPY ; CHECK: MOV8mi @@ -218,5 +218,5 @@ body: | ; CHECK: %7:gr8 = MOV8rm ; CHECK: MOV8mr ; CHECK: RET 0 - ; DEBUG-LABEL: name: nodebug + ; DEBUG: name: nodebug ... -- GitLab From f8395f8420cee8fc0854f43c9e88819c0ed54696 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 15 May 2024 14:25:29 +0100 Subject: [PATCH 348/578] [X86] Cleanup check prefixes identified in #92248 Avoid using leading numbers in check prefixes - replace with actual triple config names. --- .../align-branch-boundary-suppressions-tls.ll | 22 +-- llvm/test/CodeGen/X86/asm-modifier.ll | 30 +-- llvm/test/CodeGen/X86/pr32345.ll | 180 +++++++++--------- llvm/test/CodeGen/X86/x32-va_start.ll | 46 ++--- 4 files changed, 139 insertions(+), 139 deletions(-) diff --git a/llvm/test/CodeGen/X86/align-branch-boundary-suppressions-tls.ll b/llvm/test/CodeGen/X86/align-branch-boundary-suppressions-tls.ll index fd58cfeb65fd..0e2e6f3ef81d 100644 --- a/llvm/test/CodeGen/X86/align-branch-boundary-suppressions-tls.ll +++ b/llvm/test/CodeGen/X86/align-branch-boundary-suppressions-tls.ll @@ -2,8 +2,8 @@ ;; sequence. It uses prefixes to allow linker relaxation. We need to disable ;; prefix or nop padding for it. For simplicity and consistency, disable for ;; Local Dynamic and 32-bit as well. -; RUN: llc -mtriple=i386 -relocation-model=pic -x86-branches-within-32B-boundaries < %s | FileCheck --check-prefixes=CHECK,32 %s -; RUN: llc -mtriple=x86_64 -relocation-model=pic -x86-branches-within-32B-boundaries < %s | FileCheck --check-prefixes=CHECK,64 %s +; RUN: llc -mtriple=i386 -relocation-model=pic -x86-branches-within-32B-boundaries < %s | FileCheck --check-prefixes=CHECK,X86 %s +; RUN: llc -mtriple=x86_64 -relocation-model=pic -x86-branches-within-32B-boundaries < %s | FileCheck --check-prefixes=CHECK,X64 %s @gd = external thread_local global i32 @ld = internal thread_local global i32 0 @@ -11,17 +11,17 @@ define i32 @tls_get_addr() { ; CHECK-LABEL: tls_get_addr: ; CHECK: #noautopadding -; 32: leal gd@TLSGD(,%ebx), %eax -; 32: calll ___tls_get_addr@PLT -; 64: data16 -; 64: leaq gd@TLSGD(%rip), %rdi -; 64: callq __tls_get_addr@PLT +; X86: leal gd@TLSGD(,%ebx), %eax +; X86: calll ___tls_get_addr@PLT +; X64: data16 +; X64: leaq gd@TLSGD(%rip), %rdi +; X64: callq __tls_get_addr@PLT ; CHECK: #autopadding ; CHECK: #noautopadding -; 32: leal ld@TLSLDM(%ebx), %eax -; 32: calll ___tls_get_addr@PLT -; 64: leaq ld@TLSLD(%rip), %rdi -; 64: callq __tls_get_addr@PLT +; X86: leal ld@TLSLDM(%ebx), %eax +; X86: calll ___tls_get_addr@PLT +; X64: leaq ld@TLSLD(%rip), %rdi +; X64: callq __tls_get_addr@PLT ; CHECK: #autopadding %1 = load i32, ptr @gd %2 = load i32, ptr @ld diff --git a/llvm/test/CodeGen/X86/asm-modifier.ll b/llvm/test/CodeGen/X86/asm-modifier.ll index c121b46f8450..9a69402d2216 100644 --- a/llvm/test/CodeGen/X86/asm-modifier.ll +++ b/llvm/test/CodeGen/X86/asm-modifier.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 -; RUN: llc -mtriple=i686 < %s | FileCheck %s --check-prefixes=CHECK,32 -; RUN: llc -mtriple=x86_64 < %s | FileCheck %s --check-prefixes=CHECK,64 +; RUN: llc -mtriple=i686 < %s | FileCheck %s --check-prefixes=CHECK,X86 +; RUN: llc -mtriple=x86_64 < %s | FileCheck %s --check-prefixes=CHECK,X64 @var = internal global i32 0, align 4 @@ -43,20 +43,20 @@ entry: } define void @test_V(ptr %p) { -; 32-LABEL: test_V: -; 32: # %bb.0: # %entry -; 32-NEXT: movl {{[0-9]+}}(%esp), %eax -; 32-NEXT: #APP -; 32-NEXT: calll __x86_indirect_thunk_eax -; 32-NEXT: #NO_APP -; 32-NEXT: retl +; X86-LABEL: test_V: +; X86: # %bb.0: # %entry +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: #APP +; X86-NEXT: calll __x86_indirect_thunk_eax +; X86-NEXT: #NO_APP +; X86-NEXT: retl ; -; 64-LABEL: test_V: -; 64: # %bb.0: # %entry -; 64-NEXT: #APP -; 64-NEXT: callq __x86_indirect_thunk_rdi -; 64-NEXT: #NO_APP -; 64-NEXT: retq +; X64-LABEL: test_V: +; X64: # %bb.0: # %entry +; X64-NEXT: #APP +; X64-NEXT: callq __x86_indirect_thunk_rdi +; X64-NEXT: #NO_APP +; X64-NEXT: retq entry: tail call void asm sideeffect "call __x86_indirect_thunk_${0:V}", "r,~{dirflag},~{fpsr},~{flags}"(ptr %p) ret void diff --git a/llvm/test/CodeGen/X86/pr32345.ll b/llvm/test/CodeGen/X86/pr32345.ll index 2745cb8bb908..c7405e982660 100644 --- a/llvm/test/CodeGen/X86/pr32345.ll +++ b/llvm/test/CodeGen/X86/pr32345.ll @@ -1,74 +1,74 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -O0 -mtriple=x86_64-unknown-linux-gnu -o - %s | FileCheck %s -check-prefix=X640 -; RUN: llc -O0 -mtriple=i686-unknown -o - %s | FileCheck %s -check-prefix=6860 -; RUN: llc -mtriple=x86_64-unknown-linux-gnu -o - %s | FileCheck %s -check-prefix=X64 -; RUN: llc -mtriple=i686-unknown -o - %s | FileCheck %s -check-prefix=686 +; RUN: llc -O0 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s -check-prefix=X64-O0 +; RUN: llc -O0 -mtriple=i686-unknown < %s | FileCheck %s -check-prefix=X86-O0 +; RUN: llc -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s -check-prefix=X64 +; RUN: llc -mtriple=i686-unknown < %s | FileCheck %s -check-prefix=X86 @var_22 = external dso_local global i16, align 2 @var_27 = external dso_local global i16, align 2 define void @foo() { -; X640-LABEL: foo: -; X640: # %bb.0: # %bb -; X640-NEXT: movzwl var_22, %eax -; X640-NEXT: movzwl var_27, %ecx -; X640-NEXT: xorl %ecx, %eax -; X640-NEXT: movzwl var_27, %ecx -; X640-NEXT: xorl %ecx, %eax -; X640-NEXT: cltq -; X640-NEXT: movq %rax, -{{[0-9]+}}(%rsp) -; X640-NEXT: movzwl var_22, %eax -; X640-NEXT: movzwl var_27, %ecx -; X640-NEXT: xorl %ecx, %eax -; X640-NEXT: movzwl var_27, %ecx -; X640-NEXT: xorl %ecx, %eax -; X640-NEXT: cltq -; X640-NEXT: movzwl var_27, %ecx -; X640-NEXT: subl $16610, %ecx # imm = 0x40E2 -; X640-NEXT: movl %ecx, %ecx -; X640-NEXT: # kill: def $rcx killed $ecx -; X640-NEXT: # kill: def $cl killed $rcx -; X640-NEXT: sarq %cl, %rax -; X640-NEXT: movb %al, %cl -; X640-NEXT: # implicit-def: $rax -; X640-NEXT: movb %cl, (%rax) -; X640-NEXT: retq +; X64-O0-LABEL: foo: +; X64-O0: # %bb.0: # %bb +; X64-O0-NEXT: movzwl var_22, %eax +; X64-O0-NEXT: movzwl var_27, %ecx +; X64-O0-NEXT: xorl %ecx, %eax +; X64-O0-NEXT: movzwl var_27, %ecx +; X64-O0-NEXT: xorl %ecx, %eax +; X64-O0-NEXT: cltq +; X64-O0-NEXT: movq %rax, -{{[0-9]+}}(%rsp) +; X64-O0-NEXT: movzwl var_22, %eax +; X64-O0-NEXT: movzwl var_27, %ecx +; X64-O0-NEXT: xorl %ecx, %eax +; X64-O0-NEXT: movzwl var_27, %ecx +; X64-O0-NEXT: xorl %ecx, %eax +; X64-O0-NEXT: cltq +; X64-O0-NEXT: movzwl var_27, %ecx +; X64-O0-NEXT: subl $16610, %ecx # imm = 0x40E2 +; X64-O0-NEXT: movl %ecx, %ecx +; X64-O0-NEXT: # kill: def $rcx killed $ecx +; X64-O0-NEXT: # kill: def $cl killed $rcx +; X64-O0-NEXT: sarq %cl, %rax +; X64-O0-NEXT: movb %al, %cl +; X64-O0-NEXT: # implicit-def: $rax +; X64-O0-NEXT: movb %cl, (%rax) +; X64-O0-NEXT: retq ; -; 6860-LABEL: foo: -; 6860: # %bb.0: # %bb -; 6860-NEXT: pushl %ebp -; 6860-NEXT: .cfi_def_cfa_offset 8 -; 6860-NEXT: .cfi_offset %ebp, -8 -; 6860-NEXT: movl %esp, %ebp -; 6860-NEXT: .cfi_def_cfa_register %ebp -; 6860-NEXT: andl $-8, %esp -; 6860-NEXT: subl $24, %esp -; 6860-NEXT: movzwl var_22, %eax -; 6860-NEXT: movl %eax, {{[0-9]+}}(%esp) -; 6860-NEXT: movl $0, {{[0-9]+}}(%esp) -; 6860-NEXT: movzwl var_22, %edx -; 6860-NEXT: movb var_27, %cl -; 6860-NEXT: addb $30, %cl -; 6860-NEXT: movb %cl, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill -; 6860-NEXT: xorl %eax, %eax -; 6860-NEXT: shrdl %cl, %eax, %edx -; 6860-NEXT: movb {{[-0-9]+}}(%e{{[sb]}}p), %cl # 1-byte Reload -; 6860-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; 6860-NEXT: testb $32, %cl -; 6860-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; 6860-NEXT: jne .LBB0_2 -; 6860-NEXT: # %bb.1: # %bb -; 6860-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload -; 6860-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; 6860-NEXT: .LBB0_2: # %bb -; 6860-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload -; 6860-NEXT: movb %al, %cl -; 6860-NEXT: # implicit-def: $eax -; 6860-NEXT: movb %cl, (%eax) -; 6860-NEXT: movl %ebp, %esp -; 6860-NEXT: popl %ebp -; 6860-NEXT: .cfi_def_cfa %esp, 4 -; 6860-NEXT: retl +; X86-O0-LABEL: foo: +; X86-O0: # %bb.0: # %bb +; X86-O0-NEXT: pushl %ebp +; X86-O0-NEXT: .cfi_def_cfa_offset 8 +; X86-O0-NEXT: .cfi_offset %ebp, -8 +; X86-O0-NEXT: movl %esp, %ebp +; X86-O0-NEXT: .cfi_def_cfa_register %ebp +; X86-O0-NEXT: andl $-8, %esp +; X86-O0-NEXT: subl $24, %esp +; X86-O0-NEXT: movzwl var_22, %eax +; X86-O0-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-O0-NEXT: movl $0, {{[0-9]+}}(%esp) +; X86-O0-NEXT: movzwl var_22, %edx +; X86-O0-NEXT: movb var_27, %cl +; X86-O0-NEXT: addb $30, %cl +; X86-O0-NEXT: movb %cl, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill +; X86-O0-NEXT: xorl %eax, %eax +; X86-O0-NEXT: shrdl %cl, %eax, %edx +; X86-O0-NEXT: movb {{[-0-9]+}}(%e{{[sb]}}p), %cl # 1-byte Reload +; X86-O0-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-O0-NEXT: testb $32, %cl +; X86-O0-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-O0-NEXT: jne .LBB0_2 +; X86-O0-NEXT: # %bb.1: # %bb +; X86-O0-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-O0-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-O0-NEXT: .LBB0_2: # %bb +; X86-O0-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-O0-NEXT: movb %al, %cl +; X86-O0-NEXT: # implicit-def: $eax +; X86-O0-NEXT: movb %cl, (%eax) +; X86-O0-NEXT: movl %ebp, %esp +; X86-O0-NEXT: popl %ebp +; X86-O0-NEXT: .cfi_def_cfa %esp, 4 +; X86-O0-NEXT: retl ; ; X64-LABEL: foo: ; X64: # %bb.0: # %bb @@ -80,32 +80,32 @@ define void @foo() { ; X64-NEXT: movb %al, (%rax) ; X64-NEXT: retq ; -; 686-LABEL: foo: -; 686: # %bb.0: # %bb -; 686-NEXT: pushl %ebp -; 686-NEXT: .cfi_def_cfa_offset 8 -; 686-NEXT: .cfi_offset %ebp, -8 -; 686-NEXT: movl %esp, %ebp -; 686-NEXT: .cfi_def_cfa_register %ebp -; 686-NEXT: andl $-8, %esp -; 686-NEXT: subl $8, %esp -; 686-NEXT: movzbl var_27, %ecx -; 686-NEXT: movzwl var_22, %eax -; 686-NEXT: movl %eax, (%esp) -; 686-NEXT: movl $0, {{[0-9]+}}(%esp) -; 686-NEXT: addb $30, %cl -; 686-NEXT: xorl %edx, %edx -; 686-NEXT: shrdl %cl, %edx, %eax -; 686-NEXT: testb $32, %cl -; 686-NEXT: jne .LBB0_2 -; 686-NEXT: # %bb.1: # %bb -; 686-NEXT: movl %eax, %edx -; 686-NEXT: .LBB0_2: # %bb -; 686-NEXT: movb %dl, (%eax) -; 686-NEXT: movl %ebp, %esp -; 686-NEXT: popl %ebp -; 686-NEXT: .cfi_def_cfa %esp, 4 -; 686-NEXT: retl +; X86-LABEL: foo: +; X86: # %bb.0: # %bb +; X86-NEXT: pushl %ebp +; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: .cfi_offset %ebp, -8 +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: .cfi_def_cfa_register %ebp +; X86-NEXT: andl $-8, %esp +; X86-NEXT: subl $8, %esp +; X86-NEXT: movzbl var_27, %ecx +; X86-NEXT: movzwl var_22, %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) +; X86-NEXT: addb $30, %cl +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: shrdl %cl, %edx, %eax +; X86-NEXT: testb $32, %cl +; X86-NEXT: jne .LBB0_2 +; X86-NEXT: # %bb.1: # %bb +; X86-NEXT: movl %eax, %edx +; X86-NEXT: .LBB0_2: # %bb +; X86-NEXT: movb %dl, (%eax) +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp +; X86-NEXT: .cfi_def_cfa %esp, 4 +; X86-NEXT: retl bb: %tmp = alloca i64, align 8 %tmp1 = load i16, ptr @var_22, align 2 diff --git a/llvm/test/CodeGen/X86/x32-va_start.ll b/llvm/test/CodeGen/X86/x32-va_start.ll index e61e5765f124..31c8aee3fdde 100644 --- a/llvm/test/CodeGen/X86/x32-va_start.ll +++ b/llvm/test/CodeGen/X86/x32-va_start.ll @@ -1,8 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-linux-gnux32 | FileCheck %s -check-prefix=SSE ; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -mattr=-sse | FileCheck %s -check-prefix=NOSSE -; RUN: llc < %s -mtriple=i386-linux-gnux32 | FileCheck %s -check-prefix=32BITABI -; RUN: llc < %s -mtriple=i686-linux-gnux32 | FileCheck %s -check-prefix=32BITABI +; RUN: llc < %s -mtriple=i386-linux-gnux32 | FileCheck %s -check-prefix=X32BITABI +; RUN: llc < %s -mtriple=i686-linux-gnux32 | FileCheck %s -check-prefix=X32BITABI ; ; Verifies that x32 va_start lowering is sane. To regenerate this test, use ; cat < Date: Wed, 15 May 2024 18:57:49 +0530 Subject: [PATCH 349/578] Revert "[ExceptionDemo] Correct and update example ExceptionDemo" (#92257) Reverts llvm/llvm-project#69485 --- llvm/examples/ExceptionDemo/CMakeLists.txt | 4 +- llvm/examples/ExceptionDemo/ExceptionDemo.cpp | 181 ++++++++++-------- 2 files changed, 108 insertions(+), 77 deletions(-) diff --git a/llvm/examples/ExceptionDemo/CMakeLists.txt b/llvm/examples/ExceptionDemo/CMakeLists.txt index 0a60ad848dd4..793cf291ca6f 100644 --- a/llvm/examples/ExceptionDemo/CMakeLists.txt +++ b/llvm/examples/ExceptionDemo/CMakeLists.txt @@ -1,7 +1,9 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine - ORCJIT + MC + MCJIT + RuntimeDyld Support Target nativecodegen diff --git a/llvm/examples/ExceptionDemo/ExceptionDemo.cpp b/llvm/examples/ExceptionDemo/ExceptionDemo.cpp index 41fa0cf626bf..0afc6b30d140 100644 --- a/llvm/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/llvm/examples/ExceptionDemo/ExceptionDemo.cpp @@ -49,9 +49,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/ExecutionEngine/Orc/Core.h" -#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" -#include "llvm/ExecutionEngine/Orc/LLJIT.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" @@ -85,8 +84,6 @@ #define USE_GLOBAL_STR_CONSTS true #endif -llvm::ExitOnError ExitOnErr; - // // Example types // @@ -145,7 +142,6 @@ static llvm::ConstantInt *ourExceptionCaughtState; typedef std::vector ArgNames; typedef std::vector ArgTypes; -typedef llvm::ArrayRef TypeArray; // // Code Generation Utilities @@ -896,10 +892,13 @@ void generateStringPrint(llvm::LLVMContext &context, /// generated, and is used to hold the constant string. A value of /// false indicates that the constant string will be stored on the /// stack. -void generateIntegerPrint(llvm::LLVMContext &context, llvm::Module &module, +void generateIntegerPrint(llvm::LLVMContext &context, + llvm::Module &module, llvm::IRBuilder<> &builder, - llvm::Function &printFunct, llvm::Value *toPrint, - std::string format, bool useGlobal = true) { + llvm::Function &printFunct, + llvm::Value &toPrint, + std::string format, + bool useGlobal = true) { llvm::Constant *stringConstant = llvm::ConstantDataArray::getString(context, format); llvm::Value *stringVar; @@ -921,9 +920,10 @@ void generateIntegerPrint(llvm::LLVMContext &context, llvm::Module &module, llvm::Value *cast = builder.CreateBitCast(stringVar, builder.getPtrTy()); - builder.CreateCall(&printFunct, {toPrint, cast}); + builder.CreateCall(&printFunct, {&toPrint, cast}); } + /// Generates code to handle finally block type semantics: always runs /// regardless of whether a thrown exception is passing through or the /// parent function is simply exiting. In addition to printing some state @@ -997,10 +997,10 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context, bufferToPrint.str(), USE_GLOBAL_STR_CONSTS); - llvm::SwitchInst *theSwitch = builder.CreateSwitch( - builder.CreateLoad(ourExceptionNotThrownState->getType(), - *exceptionCaughtFlag), - &terminatorBlock, 2); + llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad( + *exceptionCaughtFlag), + &terminatorBlock, + 2); theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock); theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock); @@ -1186,7 +1186,7 @@ static llvm::Function *createCatchWrappedInvokeFunction( // Note: function handles NULL exceptions builder.CreateCall(deleteOurException, - builder.CreateLoad(builder.getPtrTy(), exceptionStorage)); + builder.CreateLoad(exceptionStorage)); builder.CreateRetVoid(); // Normal Block @@ -1206,8 +1206,7 @@ static llvm::Function *createCatchWrappedInvokeFunction( builder.SetInsertPoint(unwindResumeBlock); - builder.CreateResume( - builder.CreateLoad(ourCaughtResultType, caughtResultStorage)); + builder.CreateResume(builder.CreateLoad(caughtResultStorage)); // Exception Block @@ -1242,9 +1241,8 @@ static llvm::Function *createCatchWrappedInvokeFunction( // Retrieve exception_class member from thrown exception // (_Unwind_Exception instance). This member tells us whether or not // the exception is foreign. - llvm::Value *unwindExceptionClass = builder.CreateLoad( - builder.getInt64Ty(), - builder.CreateStructGEP( + llvm::Value *unwindExceptionClass = + builder.CreateLoad(builder.CreateStructGEP( ourUnwindExceptionType, builder.CreatePointerCast(unwindException, ourUnwindExceptionType->getPointerTo()), @@ -1280,9 +1278,9 @@ static llvm::Function *createCatchWrappedInvokeFunction( // // Note: ourBaseFromUnwindOffset is usually negative llvm::Value *typeInfoThrown = builder.CreatePointerCast( - builder.CreateConstGEP1_64(builder.getPtrTy(), unwindException, - ourBaseFromUnwindOffset), - ourExceptionType->getPointerTo()); + builder.CreateConstGEP1_64(unwindException, + ourBaseFromUnwindOffset), + ourExceptionType->getPointerTo()); // Retrieve thrown exception type info type // @@ -1291,15 +1289,17 @@ static llvm::Function *createCatchWrappedInvokeFunction( typeInfoThrown = builder.CreateStructGEP(ourExceptionType, typeInfoThrown, 0); llvm::Value *typeInfoThrownType = - builder.CreateStructGEP(ourTypeInfoType, typeInfoThrown, 0); + builder.CreateStructGEP(builder.getPtrTy(), typeInfoThrown, 0); - llvm::Value *ti8 = - builder.CreateLoad(builder.getInt8Ty(), typeInfoThrownType); - generateIntegerPrint(context, module, builder, *toPrint32Int, - builder.CreateZExt(ti8, builder.getInt32Ty()), + generateIntegerPrint(context, + module, + builder, + *toPrint32Int, + *(builder.CreateLoad(typeInfoThrownType)), "Gen: Exception type <%d> received (stack unwound) " " in " + - ourId + ".\n", + ourId + + ".\n", USE_GLOBAL_STR_CONSTS); // Route to matched type info catch block or run cleanup finally block @@ -1311,7 +1311,8 @@ static llvm::Function *createCatchWrappedInvokeFunction( for (unsigned i = 1; i <= numExceptionsToCatch; ++i) { nextTypeToCatch = i - 1; - switchToCatchBlock->addCase(llvm::ConstantInt::get(builder.getInt32Ty(), i), + switchToCatchBlock->addCase(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(context), i), catchBlocks[nextTypeToCatch]); } @@ -1386,10 +1387,14 @@ createThrowExceptionFunction(llvm::Module &module, llvm::IRBuilder<> &builder, builder.SetInsertPoint(entryBlock); llvm::Function *toPrint32Int = module.getFunction("print32Int"); - generateIntegerPrint(context, module, builder, *toPrint32Int, - builder.CreateZExt(exceptionType, builder.getInt32Ty()), - "\nGen: About to throw exception type <%d> in " + ourId + - ".\n", + generateIntegerPrint(context, + module, + builder, + *toPrint32Int, + *exceptionType, + "\nGen: About to throw exception type <%d> in " + + ourId + + ".\n", USE_GLOBAL_STR_CONSTS); // Switches on runtime type info type value to determine whether or not @@ -1541,13 +1546,15 @@ typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow); /// @param function generated test function to run /// @param typeToThrow type info type of generated exception to throw, or /// indicator to cause foreign exception to be thrown. -static void runExceptionThrow(llvm::orc::LLJIT *JIT, std::string function, - int32_t typeToThrow) { +static +void runExceptionThrow(llvm::ExecutionEngine *engine, + llvm::Function *function, + int32_t typeToThrow) { // Find test's function pointer OurExceptionThrowFunctType functPtr = - reinterpret_cast(reinterpret_cast( - ExitOnErr(JIT->lookup(function)).getValue())); + reinterpret_cast( + reinterpret_cast(engine->getPointerToFunction(function))); try { // Run test @@ -1576,6 +1583,8 @@ static void runExceptionThrow(llvm::orc::LLJIT *JIT, std::string function, // End test functions // +typedef llvm::ArrayRef TypeArray; + /// This initialization routine creates type info globals and /// adds external function declarations to module. /// @param numTypeInfos number of linear type info associated type info types @@ -1885,73 +1894,93 @@ int main(int argc, char *argv[]) { return(0); } + // If not set, exception handling will not be turned on + llvm::TargetOptions Opts; + llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); - auto Context = std::make_unique(); - llvm::IRBuilder<> theBuilder(*Context); + llvm::LLVMContext Context; + llvm::IRBuilder<> theBuilder(Context); // Make the module, which holds all the code. std::unique_ptr Owner = - std::make_unique("my cool jit", *Context); + std::make_unique("my cool jit", Context); llvm::Module *module = Owner.get(); - // Build LLJIT - std::unique_ptr JIT = - ExitOnErr(llvm::orc::LLJITBuilder().create()); + std::unique_ptr MemMgr(new llvm::SectionMemoryManager()); - // Set up the optimizer pipeline. - llvm::legacy::FunctionPassManager fpm(module); + // Build engine with JIT + llvm::EngineBuilder factory(std::move(Owner)); + factory.setEngineKind(llvm::EngineKind::JIT); + factory.setTargetOptions(Opts); + factory.setMCJITMemoryManager(std::move(MemMgr)); + llvm::ExecutionEngine *executionEngine = factory.create(); - // Optimizations turned on + { + llvm::legacy::FunctionPassManager fpm(module); + + // Set up the optimizer pipeline. + // Start with registering info about how the + // target lays out data structures. + module->setDataLayout(executionEngine->getDataLayout()); + + // Optimizations turned on #ifdef ADD_OPT_PASSES - // Basic AliasAnslysis support for GVN. - fpm.add(llvm::createBasicAliasAnalysisPass()); + // Basic AliasAnslysis support for GVN. + fpm.add(llvm::createBasicAliasAnalysisPass()); - // Promote allocas to registers. - fpm.add(llvm::createPromoteMemoryToRegisterPass()); + // Promote allocas to registers. + fpm.add(llvm::createPromoteMemoryToRegisterPass()); - // Do simple "peephole" optimizations and bit-twiddling optzns. - fpm.add(llvm::createInstructionCombiningPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + fpm.add(llvm::createInstructionCombiningPass()); - // Reassociate expressions. - fpm.add(llvm::createReassociatePass()); + // Reassociate expressions. + fpm.add(llvm::createReassociatePass()); - // Eliminate Common SubExpressions. - fpm.add(llvm::createGVNPass()); + // Eliminate Common SubExpressions. + fpm.add(llvm::createGVNPass()); - // Simplify the control flow graph (deleting unreachable - // blocks, etc). - fpm.add(llvm::createCFGSimplificationPass()); + // Simplify the control flow graph (deleting unreachable + // blocks, etc). + fpm.add(llvm::createCFGSimplificationPass()); #endif // ADD_OPT_PASSES - fpm.doInitialization(); + fpm.doInitialization(); - // Generate test code using function throwCppException(...) as - // the function which throws foreign exceptions. - createUnwindExceptionTest(*module, theBuilder, fpm, "throwCppException"); + // Generate test code using function throwCppException(...) as + // the function which throws foreign exceptions. + llvm::Function *toRun = + createUnwindExceptionTest(*module, + theBuilder, + fpm, + "throwCppException"); - ExitOnErr(JIT->addIRModule( - llvm::orc::ThreadSafeModule(std::move(Owner), std::move(Context)))); + executionEngine->finalizeObject(); #ifndef NDEBUG - fprintf(stderr, "\nBegin module dump:\n\n"); + fprintf(stderr, "\nBegin module dump:\n\n"); - module->print(llvm::errs(), nullptr); + module->dump(); - fprintf(stderr, "\nEnd module dump:\n"); + fprintf(stderr, "\nEnd module dump:\n"); #endif - fprintf(stderr, "\n\nBegin Test:\n"); - std::string toRun = "outerCatchFunct"; + fprintf(stderr, "\n\nBegin Test:\n"); + + for (int i = 1; i < argc; ++i) { + // Run test for each argument whose value is the exception + // type to throw. + runExceptionThrow(executionEngine, + toRun, + (unsigned) strtoul(argv[i], NULL, 10)); + } - for (int i = 1; i < argc; ++i) { - // Run test for each argument whose value is the exception - // type to throw. - runExceptionThrow(JIT.get(), toRun, (unsigned)strtoul(argv[i], NULL, 10)); + fprintf(stderr, "\nEnd Test:\n\n"); } - fprintf(stderr, "\nEnd Test:\n\n"); + delete executionEngine; return 0; } -- GitLab From 3bb39690d729d85cd93c9dd6e750d82d6f367541 Mon Sep 17 00:00:00 2001 From: Hans Date: Wed, 15 May 2024 15:29:08 +0200 Subject: [PATCH 350/578] [coro] Lower `llvm.coro.await.suspend.handle` to resume with tail call (#89751) The C++ standard requires that symmetric transfer from one coroutine to another is performed via a tail call. Failure to do so is a miscompile and often breaks programs by quickly overflowing the stack. Until now, the coro split pass tried to ensure this in the `addMustTailToCoroResumes()` function by searching for `llvm.coro.resume` calls to lower as tail calls if the conditions were right: the right function arguments, attributes, calling convention etc., and if a `ret void` was sure to be reached after traversal with some ad-hoc constant folding following the call. This was brittle, as the kind of implicit variants required for a tail call to happen could easily be broken by other passes (e.g. if some instruction got in between the `resume` and `ret`), see for example 9d1cb18d19862fc0627e4a56e1e491a498e84c71 and 284da049f5feb62b40f5abc41dda7895e3d81d72. Also the logic seemed backwards: instead of searching for possible tail call candidates and doing them if the circumstances are right, it seems better to start with the intention of making the tail calls we need, and forcing the circumstances to be right. Now that we have the `llvm.coro.await.suspend.handle` intrinsic (since f78688134026686288a8d310b493d9327753a022) which corresponds exactly to symmetric transfer, change the lowering of that to also include the `resume` part, always lowered as a tail call. --- clang/lib/CodeGen/CGCoroutine.cpp | 11 +- clang/test/CodeGenCoroutines/coro-await.cpp | 4 +- .../coro-symmetric-transfer-01.cpp | 54 ---- .../coro-symmetric-transfer-02.cpp | 6 +- llvm/docs/Coroutines.rst | 19 +- llvm/include/llvm/IR/Intrinsics.td | 2 +- llvm/lib/Transforms/Coroutines/CoroInternal.h | 3 +- llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 240 +++++------------- llvm/lib/Transforms/Coroutines/Coroutines.cpp | 4 +- .../coro-await-suspend-lower-invoke.ll | 5 +- .../Coroutines/coro-await-suspend-lower.ll | 5 +- .../Coroutines/coro-preserve-final.ll | 131 ---------- ...-split-musttail-chain-pgo-counter-promo.ll | 9 +- .../Coroutines/coro-split-musttail.ll | 17 +- .../Coroutines/coro-split-musttail1.ll | 35 ++- .../Coroutines/coro-split-musttail10.ll | 6 +- .../Coroutines/coro-split-musttail2.ll | 15 +- .../Coroutines/coro-split-musttail3.ll | 36 ++- .../Coroutines/coro-split-musttail4.ll | 8 +- .../Coroutines/coro-split-musttail5.ll | 8 +- .../Coroutines/coro-split-musttail6.ll | 11 +- .../Coroutines/coro-split-musttail7.ll | 17 +- 22 files changed, 168 insertions(+), 478 deletions(-) delete mode 100644 clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp delete mode 100644 llvm/test/Transforms/Coroutines/coro-preserve-final.ll diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index 567e85a02dc6..b4c724422c14 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -278,7 +278,11 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co llvm::Function *AwaitSuspendIntrinsic = CGF.CGM.getIntrinsic(AwaitSuspendIID); - const auto AwaitSuspendCanThrow = StmtCanThrow(S.getSuspendExpr()); + // SuspendHandle might throw since it also resumes the returned handle. + const bool AwaitSuspendCanThrow = + SuspendReturnType == + CoroutineSuspendExpr::SuspendReturnType::SuspendHandle || + StmtCanThrow(S.getSuspendExpr()); llvm::CallBase *SuspendRet = nullptr; // FIXME: add call attributes? @@ -307,10 +311,7 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co break; } case CoroutineSuspendExpr::SuspendReturnType::SuspendHandle: { - assert(SuspendRet->getType()->isPointerTy()); - - auto ResumeIntrinsic = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_resume); - Builder.CreateCall(ResumeIntrinsic, SuspendRet); + assert(SuspendRet->getType()->isVoidTy()); break; } } diff --git a/clang/test/CodeGenCoroutines/coro-await.cpp b/clang/test/CodeGenCoroutines/coro-await.cpp index 65bfb0994688..c7a09e8b8bc7 100644 --- a/clang/test/CodeGenCoroutines/coro-await.cpp +++ b/clang/test/CodeGenCoroutines/coro-await.cpp @@ -370,8 +370,8 @@ extern "C" void TestTailcall() { // --------------------------- // Call coro.await.suspend // --------------------------- - // CHECK-NEXT: %[[RESUMED:.+]] = call ptr @llvm.coro.await.suspend.handle(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @TestTailcall.__await_suspend_wrapper__await) - // CHECK-NEXT: call void @llvm.coro.resume(ptr %[[RESUMED]]) + // Note: The call must not be nounwind since the resumed function could throw. + // CHECK-NEXT: call void @llvm.coro.await.suspend.handle(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @TestTailcall.__await_suspend_wrapper__await){{$}} // CHECK-NEXT: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false) // CHECK-NEXT: switch i8 %[[OUTCOME]], label %[[RET_BB:.+]] [ // CHECK-NEXT: i8 0, label %[[READY_BB]] diff --git a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp deleted file mode 100644 index da30e12c63cf..000000000000 --- a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O0 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s -// RUN: %clang -std=c++20 -O0 -emit-llvm -c %s -o %t -Xclang -disable-llvm-passes && %clang -c %t - -#include "Inputs/coroutine.h" - -struct detached_task { - struct promise_type { - detached_task get_return_object() noexcept { - return detached_task{std::coroutine_handle::from_promise(*this)}; - } - - void return_void() noexcept {} - - struct final_awaiter { - bool await_ready() noexcept { return false; } - std::coroutine_handle<> await_suspend(std::coroutine_handle h) noexcept { - h.destroy(); - return {}; - } - void await_resume() noexcept {} - }; - - void unhandled_exception() noexcept {} - - final_awaiter final_suspend() noexcept { return {}; } - - std::suspend_always initial_suspend() noexcept { return {}; } - }; - - ~detached_task() { - if (coro_) { - coro_.destroy(); - coro_ = {}; - } - } - - void start() && { - auto tmp = coro_; - coro_ = {}; - tmp.resume(); - } - - std::coroutine_handle coro_; -}; - -detached_task foo() { - co_return; -} - -// check that the lifetime of the coroutine handle used to obtain the address is contained within single basic block, and hence does not live across suspension points. -// CHECK-LABEL: final.suspend: -// CHECK: %{{.+}} = call token @llvm.coro.save(ptr null) -// CHECK: %[[HDL_TRANSFER:.+]] = call ptr @llvm.coro.await.suspend.handle -// CHECK: call void @llvm.coro.resume(ptr %[[HDL_TRANSFER]]) diff --git a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp index ca6cf74115a3..f36f89926505 100644 --- a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp +++ b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp @@ -89,8 +89,7 @@ Task bar() { // CHECK: br i1 %{{.+}}, label %[[CASE1_AWAIT_READY:.+]], label %[[CASE1_AWAIT_SUSPEND:.+]] // CHECK: [[CASE1_AWAIT_SUSPEND]]: // CHECK-NEXT: %{{.+}} = call token @llvm.coro.save(ptr null) -// CHECK-NEXT: %[[HANDLE1_PTR:.+]] = call ptr @llvm.coro.await.suspend.handle -// CHECK-NEXT: call void @llvm.coro.resume(ptr %[[HANDLE1_PTR]]) +// CHECK-NEXT: call void @llvm.coro.await.suspend.handle // CHECK-NEXT: %{{.+}} = call i8 @llvm.coro.suspend // CHECK-NEXT: switch i8 %{{.+}}, label %coro.ret [ // CHECK-NEXT: i8 0, label %[[CASE1_AWAIT_READY]] @@ -104,8 +103,7 @@ Task bar() { // CHECK: br i1 %{{.+}}, label %[[CASE2_AWAIT_READY:.+]], label %[[CASE2_AWAIT_SUSPEND:.+]] // CHECK: [[CASE2_AWAIT_SUSPEND]]: // CHECK-NEXT: %{{.+}} = call token @llvm.coro.save(ptr null) -// CHECK-NEXT: %[[HANDLE2_PTR:.+]] = call ptr @llvm.coro.await.suspend.handle -// CHECK-NEXT: call void @llvm.coro.resume(ptr %[[HANDLE2_PTR]]) +// CHECK-NEXT: call void @llvm.coro.await.suspend.handle // CHECK-NEXT: %{{.+}} = call i8 @llvm.coro.suspend // CHECK-NEXT: switch i8 %{{.+}}, label %coro.ret [ // CHECK-NEXT: i8 0, label %[[CASE2_AWAIT_READY]] diff --git a/llvm/docs/Coroutines.rst b/llvm/docs/Coroutines.rst index 83369d93c309..36092325e536 100644 --- a/llvm/docs/Coroutines.rst +++ b/llvm/docs/Coroutines.rst @@ -1922,7 +1922,7 @@ Example: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: - declare ptr @llvm.coro.await.suspend.handle( + declare void @llvm.coro.await.suspend.handle( ptr , ptr , ptr ) @@ -1967,7 +1967,9 @@ The intrinsic must be used between corresponding `coro.save`_ and `await_suspend_function` call during `CoroSplit`_ pass. `await_suspend_function` must return a pointer to a valid -coroutine frame, which is immediately resumed +coroutine frame. The intrinsic will be lowered to a tail call resuming the +returned coroutine frame. It will be marked `musttail` on targets that support +that. Instructions following the intrinsic will become unreachable. Example: """""""" @@ -1977,11 +1979,10 @@ Example: ; before lowering await.suspend: %save = call token @llvm.coro.save(ptr %hdl) - %next = call ptr @llvm.coro.await.suspend.handle( - ptr %awaiter, - ptr %hdl, - ptr @await_suspend_function) - call void @llvm.coro.resume(%next) + call void @llvm.coro.await.suspend.handle( + ptr %awaiter, + ptr %hdl, + ptr @await_suspend_function) %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) ... @@ -1992,8 +1993,8 @@ Example: %next = call ptr @await_suspend_function( ptr %awaiter, ptr %hdl) - call void @llvm.coro.resume(%next) - %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + musttail call void @llvm.coro.resume(%next) + ret void ... ; wrapper function example diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index f1c7d950f927..78f0dbec863e 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1717,7 +1717,7 @@ def int_coro_await_suspend_bool : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], [Throws]>; -def int_coro_await_suspend_handle : Intrinsic<[llvm_ptr_ty], +def int_coro_await_suspend_handle : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], [Throws]>; diff --git a/llvm/lib/Transforms/Coroutines/CoroInternal.h b/llvm/lib/Transforms/Coroutines/CoroInternal.h index 84fd88806154..5716fd0ea4ab 100644 --- a/llvm/lib/Transforms/Coroutines/CoroInternal.h +++ b/llvm/lib/Transforms/Coroutines/CoroInternal.h @@ -47,7 +47,7 @@ struct LowererBase { ConstantPointerNull *const NullPtr; LowererBase(Module &M); - Value *makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt); + CallInst *makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt); }; enum class ABI { @@ -85,6 +85,7 @@ struct LLVM_LIBRARY_VISIBILITY Shape { SmallVector CoroSuspends; SmallVector SwiftErrorOps; SmallVector CoroAwaitSuspends; + SmallVector SymmetricTransfers; // Field indexes for special fields in the switch lowering. struct SwitchFieldIndex { diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 4eb6e75d09fa..450ea8234371 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -113,21 +113,24 @@ private: /// ABIs. AnyCoroSuspendInst *ActiveSuspend = nullptr; + TargetTransformInfo &TTI; + public: /// Create a cloner for a switch lowering. CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, - Kind FKind) + Kind FKind, TargetTransformInfo &TTI) : OrigF(OrigF), NewF(nullptr), Suffix(Suffix), Shape(Shape), FKind(FKind), - Builder(OrigF.getContext()) { + Builder(OrigF.getContext()), TTI(TTI) { assert(Shape.ABI == coro::ABI::Switch); } /// Create a cloner for a continuation lowering. CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, - Function *NewF, AnyCoroSuspendInst *ActiveSuspend) + Function *NewF, AnyCoroSuspendInst *ActiveSuspend, + TargetTransformInfo &TTI) : OrigF(OrigF), NewF(NewF), Suffix(Suffix), Shape(Shape), FKind(Shape.ABI == coro::ABI::Async ? Kind::Async : Kind::Continuation), - Builder(OrigF.getContext()), ActiveSuspend(ActiveSuspend) { + Builder(OrigF.getContext()), ActiveSuspend(ActiveSuspend), TTI(TTI) { assert(Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async); assert(NewF && "need existing function for continuation"); @@ -171,7 +174,8 @@ private: // Lower the intrinisc in CoroEarly phase if coroutine frame doesn't escape // and it is known that other transformations, for example, sanitizers // won't lead to incorrect code. -static void lowerAwaitSuspend(IRBuilder<> &Builder, CoroAwaitSuspendInst *CB) { +static void lowerAwaitSuspend(IRBuilder<> &Builder, CoroAwaitSuspendInst *CB, + coro::Shape &Shape) { auto Wrapper = CB->getWrapperFunction(); auto Awaiter = CB->getAwaiter(); auto FramePtr = CB->getFrame(); @@ -206,6 +210,31 @@ static void lowerAwaitSuspend(IRBuilder<> &Builder, CoroAwaitSuspendInst *CB) { llvm_unreachable("Unexpected coro_await_suspend invocation method"); } + if (CB->getCalledFunction()->getIntrinsicID() == + Intrinsic::coro_await_suspend_handle) { + // Follow the lowered await_suspend call above with a lowered resume call + // to the returned coroutine. + if (auto *Invoke = dyn_cast(CB)) { + // If the await_suspend call is an invoke, we continue in the next block. + Builder.SetInsertPoint(Invoke->getNormalDest()->getFirstInsertionPt()); + } + + coro::LowererBase LB(*Wrapper->getParent()); + auto *ResumeAddr = LB.makeSubFnCall(NewCall, CoroSubFnInst::ResumeIndex, + &*Builder.GetInsertPoint()); + + LLVMContext &Ctx = Builder.getContext(); + FunctionType *ResumeTy = FunctionType::get( + Type::getVoidTy(Ctx), PointerType::getUnqual(Ctx), false); + auto *ResumeCall = Builder.CreateCall(ResumeTy, ResumeAddr, {NewCall}); + + // We can't insert the 'ret' instruction and adjust the cc until the + // function has been split, so remember this for later. + Shape.SymmetricTransfers.push_back(ResumeCall); + + NewCall = ResumeCall; + } + CB->replaceAllUsesWith(NewCall); CB->eraseFromParent(); } @@ -213,7 +242,7 @@ static void lowerAwaitSuspend(IRBuilder<> &Builder, CoroAwaitSuspendInst *CB) { static void lowerAwaitSuspends(Function &F, coro::Shape &Shape) { IRBuilder<> Builder(F.getContext()); for (auto *AWS : Shape.CoroAwaitSuspends) - lowerAwaitSuspend(Builder, AWS); + lowerAwaitSuspend(Builder, AWS, Shape); } static void maybeFreeRetconStorage(IRBuilder<> &Builder, @@ -1056,6 +1085,25 @@ void CoroCloner::create() { // Set up the new entry block. replaceEntryBlock(); + // Turn symmetric transfers into musttail calls. + for (CallInst *ResumeCall : Shape.SymmetricTransfers) { + ResumeCall = cast(VMap[ResumeCall]); + ResumeCall->setCallingConv(NewF->getCallingConv()); + if (TTI.supportsTailCallFor(ResumeCall)) { + // FIXME: Could we support symmetric transfer effectively without + // musttail? + ResumeCall->setTailCallKind(CallInst::TCK_MustTail); + } + + // Put a 'ret void' after the call, and split any remaining instructions to + // an unreachable block. + BasicBlock *BB = ResumeCall->getParent(); + BB->splitBasicBlock(ResumeCall->getNextNode()); + Builder.SetInsertPoint(BB->getTerminator()); + Builder.CreateRetVoid(); + BB->getTerminator()->eraseFromParent(); + } + Builder.SetInsertPoint(&NewF->getEntryBlock().front()); NewFramePtr = deriveNewFramePointer(); @@ -1186,130 +1234,6 @@ scanPHIsAndUpdateValueMap(Instruction *Prev, BasicBlock *NewBlock, } } -// Replace a sequence of branches leading to a ret, with a clone of a ret -// instruction. Suspend instruction represented by a switch, track the PHI -// values and select the correct case successor when possible. -static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst) { - // There is nothing to simplify. - if (isa(InitialInst)) - return false; - - DenseMap ResolvedValues; - assert(InitialInst->getModule()); - const DataLayout &DL = InitialInst->getModule()->getDataLayout(); - - auto TryResolveConstant = [&ResolvedValues](Value *V) { - auto It = ResolvedValues.find(V); - if (It != ResolvedValues.end()) - V = It->second; - return dyn_cast(V); - }; - - Instruction *I = InitialInst; - while (true) { - if (isa(I)) { - assert(!cast(I)->getReturnValue()); - ReplaceInstWithInst(InitialInst, I->clone()); - return true; - } - - if (auto *BR = dyn_cast(I)) { - unsigned SuccIndex = 0; - if (BR->isConditional()) { - // Handle the case the condition of the conditional branch is constant. - // e.g., - // - // br i1 false, label %cleanup, label %CoroEnd - // - // It is possible during the transformation. We could continue the - // simplifying in this case. - ConstantInt *Cond = TryResolveConstant(BR->getCondition()); - if (!Cond) - return false; - - SuccIndex = Cond->isOne() ? 0 : 1; - } - - BasicBlock *Succ = BR->getSuccessor(SuccIndex); - scanPHIsAndUpdateValueMap(I, Succ, ResolvedValues); - I = Succ->getFirstNonPHIOrDbgOrLifetime(); - continue; - } - - if (auto *Cmp = dyn_cast(I)) { - // If the case number of suspended switch instruction is reduced to - // 1, then it is simplified to CmpInst in llvm::ConstantFoldTerminator. - // Try to constant fold it. - ConstantInt *Cond0 = TryResolveConstant(Cmp->getOperand(0)); - ConstantInt *Cond1 = TryResolveConstant(Cmp->getOperand(1)); - if (Cond0 && Cond1) { - ConstantInt *Result = - dyn_cast_or_null(ConstantFoldCompareInstOperands( - Cmp->getPredicate(), Cond0, Cond1, DL)); - if (Result) { - ResolvedValues[Cmp] = Result; - I = I->getNextNode(); - continue; - } - } - } - - if (auto *SI = dyn_cast(I)) { - ConstantInt *Cond = TryResolveConstant(SI->getCondition()); - if (!Cond) - return false; - - BasicBlock *Succ = SI->findCaseValue(Cond)->getCaseSuccessor(); - scanPHIsAndUpdateValueMap(I, Succ, ResolvedValues); - I = Succ->getFirstNonPHIOrDbgOrLifetime(); - continue; - } - - if (I->isDebugOrPseudoInst() || I->isLifetimeStartOrEnd() || - wouldInstructionBeTriviallyDead(I)) { - // We can skip instructions without side effects. If their values are - // needed, we'll notice later, e.g. when hitting a conditional branch. - I = I->getNextNode(); - continue; - } - - break; - } - - return false; -} - -// Check whether CI obeys the rules of musttail attribute. -static bool shouldBeMustTail(const CallInst &CI, const Function &F) { - if (CI.isInlineAsm()) - return false; - - // Match prototypes and calling conventions of resume function. - FunctionType *CalleeTy = CI.getFunctionType(); - if (!CalleeTy->getReturnType()->isVoidTy() || (CalleeTy->getNumParams() != 1)) - return false; - - Type *CalleeParmTy = CalleeTy->getParamType(0); - if (!CalleeParmTy->isPointerTy() || - (CalleeParmTy->getPointerAddressSpace() != 0)) - return false; - - if (CI.getCallingConv() != F.getCallingConv()) - return false; - - // CI should not has any ABI-impacting function attributes. - static const Attribute::AttrKind ABIAttrs[] = { - Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca, - Attribute::Preallocated, Attribute::InReg, Attribute::Returned, - Attribute::SwiftSelf, Attribute::SwiftError}; - AttributeList Attrs = CI.getAttributes(); - for (auto AK : ABIAttrs) - if (Attrs.hasParamAttr(0, AK)) - return false; - - return true; -} - // Coroutine has no suspend points. Remove heap allocation for the coroutine // frame if possible. static void handleNoSuspendCoroutine(coro::Shape &Shape) { @@ -1523,24 +1447,16 @@ struct SwitchCoroutineSplitter { createResumeEntryBlock(F, Shape); auto *ResumeClone = - createClone(F, ".resume", Shape, CoroCloner::Kind::SwitchResume); + createClone(F, ".resume", Shape, CoroCloner::Kind::SwitchResume, TTI); auto *DestroyClone = - createClone(F, ".destroy", Shape, CoroCloner::Kind::SwitchUnwind); + createClone(F, ".destroy", Shape, CoroCloner::Kind::SwitchUnwind, TTI); auto *CleanupClone = - createClone(F, ".cleanup", Shape, CoroCloner::Kind::SwitchCleanup); + createClone(F, ".cleanup", Shape, CoroCloner::Kind::SwitchCleanup, TTI); postSplitCleanup(*ResumeClone); postSplitCleanup(*DestroyClone); postSplitCleanup(*CleanupClone); - // Adding musttail call to support symmetric transfer. - // Skip targets which don't support tail call. - // - // FIXME: Could we support symmetric transfer effectively without musttail - // call? - if (TTI.supportsTailCalls()) - addMustTailToCoroResumes(*ResumeClone, TTI); - // Store addresses resume/destroy/cleanup functions in the coroutine frame. updateCoroFrame(Shape, ResumeClone, DestroyClone, CleanupClone); @@ -1560,8 +1476,9 @@ private: // new entry block and replacing coro.suspend an appropriate value to force // resume or cleanup pass for every suspend point. static Function *createClone(Function &F, const Twine &Suffix, - coro::Shape &Shape, CoroCloner::Kind FKind) { - CoroCloner Cloner(F, Suffix, Shape, FKind); + coro::Shape &Shape, CoroCloner::Kind FKind, + TargetTransformInfo &TTI) { + CoroCloner Cloner(F, Suffix, Shape, FKind, TTI); Cloner.create(); return Cloner.getFunction(); } @@ -1662,34 +1579,6 @@ private: Shape.SwitchLowering.ResumeEntryBlock = NewEntry; } - // Add musttail to any resume instructions that is immediately followed by a - // suspend (i.e. ret). We do this even in -O0 to support guaranteed tail call - // for symmetrical coroutine control transfer (C++ Coroutines TS extension). - // This transformation is done only in the resume part of the coroutine that - // has identical signature and calling convention as the coro.resume call. - static void addMustTailToCoroResumes(Function &F, TargetTransformInfo &TTI) { - bool Changed = false; - - // Collect potential resume instructions. - SmallVector Resumes; - for (auto &I : instructions(F)) - if (auto *Call = dyn_cast(&I)) - if (shouldBeMustTail(*Call, F)) - Resumes.push_back(Call); - - // Set musttail on those that are followed by a ret instruction. - for (CallInst *Call : Resumes) - // Skip targets which don't support tail call on the specific case. - if (TTI.supportsTailCallFor(Call) && - simplifyTerminatorLeadingToRet(Call->getNextNode())) { - Call->setTailCallKind(CallInst::TCK_MustTail); - Changed = true; - } - - if (Changed) - removeUnreachableBlocks(F); - } - // Store addresses of Resume/Destroy/Cleanup functions in the coroutine frame. static void updateCoroFrame(coro::Shape &Shape, Function *ResumeFn, Function *DestroyFn, Function *CleanupFn) { @@ -1893,12 +1782,13 @@ static void splitAsyncCoroutine(Function &F, coro::Shape &Shape, auto *Suspend = Shape.CoroSuspends[Idx]; auto *Clone = Clones[Idx]; - CoroCloner(F, "resume." + Twine(Idx), Shape, Clone, Suspend).create(); + CoroCloner(F, "resume." + Twine(Idx), Shape, Clone, Suspend, TTI).create(); } } static void splitRetconCoroutine(Function &F, coro::Shape &Shape, - SmallVectorImpl &Clones) { + SmallVectorImpl &Clones, + TargetTransformInfo &TTI) { assert(Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce); assert(Clones.empty()); @@ -2021,7 +1911,7 @@ static void splitRetconCoroutine(Function &F, coro::Shape &Shape, auto Suspend = Shape.CoroSuspends[i]; auto Clone = Clones[i]; - CoroCloner(F, "resume." + Twine(i), Shape, Clone, Suspend).create(); + CoroCloner(F, "resume." + Twine(i), Shape, Clone, Suspend, TTI).create(); } } @@ -2073,7 +1963,7 @@ splitCoroutine(Function &F, SmallVectorImpl &Clones, break; case coro::ABI::Retcon: case coro::ABI::RetconOnce: - splitRetconCoroutine(F, Shape, Clones); + splitRetconCoroutine(F, Shape, Clones, TTI); break; } } diff --git a/llvm/lib/Transforms/Coroutines/Coroutines.cpp b/llvm/lib/Transforms/Coroutines/Coroutines.cpp index a1c78d6a44ef..1a92bc163625 100644 --- a/llvm/lib/Transforms/Coroutines/Coroutines.cpp +++ b/llvm/lib/Transforms/Coroutines/Coroutines.cpp @@ -47,8 +47,8 @@ coro::LowererBase::LowererBase(Module &M) // // call ptr @llvm.coro.subfn.addr(ptr %Arg, i8 %index) -Value *coro::LowererBase::makeSubFnCall(Value *Arg, int Index, - Instruction *InsertPt) { +CallInst *coro::LowererBase::makeSubFnCall(Value *Arg, int Index, + Instruction *InsertPt) { auto *IndexVal = ConstantInt::get(Type::getInt8Ty(Context), Index); auto *Fn = Intrinsic::getDeclaration(&TheModule, Intrinsic::coro_subfn_addr); diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll index fbc4a2c006f8..fd3b7bd81530 100644 --- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll +++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll @@ -58,14 +58,13 @@ suspend.cond: ; CHECK-NEXT: to label %[[STEP2_CONT:[^ ]+]] unwind label %[[PAD]] step2: %save2 = call token @llvm.coro.save(ptr null) - %resume.handle = invoke ptr @llvm.coro.await.suspend.handle(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_handle) + invoke void @llvm.coro.await.suspend.handle(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_handle) to label %step2.continue unwind label %pad ; CHECK: [[STEP2_CONT]]: ; CHECK-NEXT: %[[NEXT_RESUME:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[NEXT_HDL]], i8 0) ; CHECK-NEXT: musttail call {{.*}} void %[[NEXT_RESUME]](ptr %[[NEXT_HDL]]) step2.continue: - call void @llvm.coro.resume(ptr %resume.handle) %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) switch i8 %suspend2, label %ret [ i8 0, label %step3 @@ -112,7 +111,7 @@ declare i1 @llvm.coro.alloc(token) declare ptr @llvm.coro.begin(token, ptr) declare void @llvm.coro.await.suspend.void(ptr, ptr, ptr) declare i1 @llvm.coro.await.suspend.bool(ptr, ptr, ptr) -declare ptr @llvm.coro.await.suspend.handle(ptr, ptr, ptr) +declare void @llvm.coro.await.suspend.handle(ptr, ptr, ptr) declare i1 @llvm.coro.end(ptr, i1, token) declare ptr @__cxa_begin_catch(ptr) diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll index 0f574c4acc26..8d019e695462 100644 --- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll +++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll @@ -49,8 +49,7 @@ suspend.cond: ; CHECK-NEXT: musttail call {{.*}} void %[[CONT]](ptr %[[NEXT_HDL]]) step2: %save2 = call token @llvm.coro.save(ptr null) - %resume.handle = call ptr @llvm.coro.await.suspend.handle(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_handle) - call void @llvm.coro.resume(ptr %resume.handle) + call void @llvm.coro.await.suspend.handle(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_handle) %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) switch i8 %suspend2, label %ret [ i8 0, label %step3 @@ -89,7 +88,7 @@ declare i1 @llvm.coro.alloc(token) declare ptr @llvm.coro.begin(token, ptr) declare void @llvm.coro.await.suspend.void(ptr, ptr, ptr) declare i1 @llvm.coro.await.suspend.bool(ptr, ptr, ptr) -declare ptr @llvm.coro.await.suspend.handle(ptr, ptr, ptr) +declare void @llvm.coro.await.suspend.handle(ptr, ptr, ptr) declare i1 @llvm.coro.end(ptr, i1, token) declare noalias ptr @malloc(i32) diff --git a/llvm/test/Transforms/Coroutines/coro-preserve-final.ll b/llvm/test/Transforms/Coroutines/coro-preserve-final.ll deleted file mode 100644 index 16eeb84e7915..000000000000 --- a/llvm/test/Transforms/Coroutines/coro-preserve-final.ll +++ /dev/null @@ -1,131 +0,0 @@ -; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s - -%"struct.std::__n4861::noop_coroutine_promise" = type { i8 } -%struct.Promise = type { %"struct.std::__n4861::coroutine_handle" } -%"struct.std::__n4861::coroutine_handle" = type { ptr } - -define dso_local ptr @_Z5Outerv() #1 { -entry: - %__promise = alloca %struct.Promise, align 8 - %0 = call token @llvm.coro.id(i32 16, ptr nonnull %__promise, ptr nonnull @_Z5Outerv, ptr null) - %1 = call i1 @llvm.coro.alloc(token %0) - br i1 %1, label %coro.alloc, label %init.suspend - -coro.alloc: ; preds = %entry - %2 = tail call i64 @llvm.coro.size.i64() - %call = call noalias noundef nonnull ptr @_Znwm(i64 noundef %2) #12 - br label %init.suspend - -init.suspend: ; preds = %entry, %coro.alloc - %3 = phi ptr [ null, %entry ], [ %call, %coro.alloc ] - %4 = call ptr @llvm.coro.begin(token %0, ptr %3) #13 - call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %__promise) #3 - store ptr null, ptr %__promise, align 8 - %5 = call token @llvm.coro.save(ptr null) - %6 = call i8 @llvm.coro.suspend(token %5, i1 false) - switch i8 %6, label %coro.ret [ - i8 0, label %await.suspend - i8 1, label %cleanup62 - ] - -await.suspend: ; preds = %init.suspend - %7 = call token @llvm.coro.save(ptr null) - %8 = call ptr @llvm.coro.subfn.addr(ptr %4, i8 0) - call fastcc void %8(ptr %4) #3 - %9 = call i8 @llvm.coro.suspend(token %7, i1 false) - switch i8 %9, label %coro.ret [ - i8 0, label %await2.suspend - i8 1, label %cleanup62 - ] - -await2.suspend: ; preds = %await.suspend - %call27 = call ptr @_Z5Innerv() #3 - %10 = call token @llvm.coro.save(ptr null) - %11 = getelementptr inbounds i8, ptr %__promise, i64 -16 - store ptr %11, ptr %call27, align 8 - %12 = getelementptr inbounds i8, ptr %call27, i64 -16 - %13 = call ptr @llvm.coro.subfn.addr(ptr nonnull %12, i8 0) - call fastcc void %13(ptr nonnull %12) #3 - %14 = call i8 @llvm.coro.suspend(token %10, i1 false) - switch i8 %14, label %coro.ret [ - i8 0, label %final.suspend - i8 1, label %cleanup62 - ] - -final.suspend: ; preds = %await2.suspend - %15 = call ptr @llvm.coro.subfn.addr(ptr nonnull %12, i8 1) - call fastcc void %15(ptr nonnull %12) #3 - %16 = call token @llvm.coro.save(ptr null) - %retval.sroa.0.0.copyload.i = load ptr, ptr %__promise, align 8 - %17 = call ptr @llvm.coro.subfn.addr(ptr %retval.sroa.0.0.copyload.i, i8 0) - call fastcc void %17(ptr %retval.sroa.0.0.copyload.i) #3 - %18 = call i8 @llvm.coro.suspend(token %16, i1 true) #13 - switch i8 %18, label %coro.ret [ - i8 0, label %final.ready - i8 1, label %cleanup62 - ] - -final.ready: ; preds = %final.suspend - call void @_Z5_exiti(i32 noundef 1) #14 - unreachable - -cleanup62: ; preds = %await2.suspend, %await.suspend, %init.suspend, %final.suspend - call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %__promise) #3 - %19 = call ptr @llvm.coro.free(token %0, ptr %4) - %.not = icmp eq ptr %19, null - br i1 %.not, label %coro.ret, label %coro.free - -coro.free: ; preds = %cleanup62 - call void @_ZdlPv(ptr noundef nonnull %19) #3 - br label %coro.ret - -coro.ret: ; preds = %coro.free, %cleanup62, %final.suspend, %await2.suspend, %await.suspend, %init.suspend - %20 = call i1 @llvm.coro.end(ptr null, i1 false, token none) #13 - ret ptr %__promise -} - -declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #2 -declare i1 @llvm.coro.alloc(token) #3 -declare dso_local noundef nonnull ptr @_Znwm(i64 noundef) local_unnamed_addr #4 -declare i64 @llvm.coro.size.i64() #5 -declare ptr @llvm.coro.begin(token, ptr writeonly) #3 -declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #6 -declare token @llvm.coro.save(ptr) #7 -declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #6 -declare i8 @llvm.coro.suspend(token, i1) #3 -declare dso_local ptr @_Z5Innerv() local_unnamed_addr #8 -declare dso_local void @_ZdlPv(ptr noundef) local_unnamed_addr #9 -declare ptr @llvm.coro.free(token, ptr nocapture readonly) #2 -declare i1 @llvm.coro.end(ptr, i1, token) #3 -declare dso_local void @_Z5_exiti(i32 noundef) local_unnamed_addr #10 -declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #11 - -attributes #0 = { mustprogress nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -attributes #1 = { nounwind presplitcoroutine uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -attributes #2 = { argmemonly nofree nounwind readonly } -attributes #3 = { nounwind } -attributes #4 = { nobuiltin allocsize(0) "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -attributes #5 = { nofree nosync nounwind readnone } -attributes #6 = { argmemonly mustprogress nocallback nofree nosync nounwind willreturn } -attributes #7 = { nomerge nounwind } -attributes #8 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -attributes #9 = { nobuiltin nounwind "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -attributes #10 = { noreturn "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -attributes #11 = { argmemonly nounwind readonly } -attributes #12 = { nounwind allocsize(0) } -attributes #13 = { noduplicate } -attributes #14 = { noreturn nounwind } - -; CHECK: define{{.*}}@_Z5Outerv.resume( -; CHECK: entry.resume: -; CHECK: switch i2 %index -; CHECK-NEXT: i2 0, label %await2.suspend -; CHECK-NEXT: i2 1, label %final.suspend -; -; CHECK: await2.suspend: -; CHECK: musttail call -; CHECK-NEXT: ret void -; -; CHECK: final.suspend: -; CHECK: musttail call -; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail-chain-pgo-counter-promo.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail-chain-pgo-counter-promo.ll index ddd293eed240..e2ed205f2c2f 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail-chain-pgo-counter-promo.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail-chain-pgo-counter-promo.ll @@ -90,10 +90,7 @@ define ptr @f(i32 %0) presplitcoroutine align 32 { %25 = getelementptr inbounds { ptr, ptr }, ptr %5, i64 0, i32 1 store ptr %24, ptr %25, align 8 %26 = call token @llvm.coro.save(ptr null) - %27 = call ptr @await_transform_await_suspend(ptr noundef nonnull align 8 dereferenceable(16) %5, ptr %14) - %28 = call ptr @llvm.coro.subfn.addr(ptr %27, i8 0) - %29 = ptrtoint ptr %28 to i64 - call fastcc void %28(ptr %27) #9 + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_transform_await_suspend) %30 = call i8 @llvm.coro.suspend(token %26, i1 false) switch i8 %30, label %60 [ i8 0, label %31 @@ -123,9 +120,7 @@ define ptr @f(i32 %0) presplitcoroutine align 32 { br i1 %42, label %43, label %46 43: ; preds = %36 - %44 = call ptr @llvm.coro.subfn.addr(ptr nonnull %14, i8 1) - %45 = ptrtoint ptr %44 to i64 - call fastcc void %44(ptr nonnull %14) #9 + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_transform_await_suspend) br label %47 46: ; preds = %36 diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail.ll index 825e44471db2..70f29f4a9a4d 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail.ll @@ -1,7 +1,6 @@ -; Tests that coro-split will convert coro.resume followed by a suspend to a -; musttail call. -; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK,NOPGO %s -; RUN: opt < %s -passes='pgo-instr-gen,cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK,PGO %s +; Tests that coro-split will convert coro.await.suspend.handle to a musttail call. +; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK %s +; RUN: opt < %s -passes='pgo-instr-gen,cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK %s define void @f() #0 { entry: @@ -20,8 +19,7 @@ entry: ] await.ready: %save2 = call token @llvm.coro.save(ptr null) - %addr2 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0) - call fastcc void %addr2(ptr null) + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function) %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) switch i8 %suspend2, label %exit [ @@ -40,10 +38,8 @@ exit: ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @f.resume( -; CHECK: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0) -; NOPGO-NEXT: musttail call fastcc void %[[addr2]](ptr null) -; PGO: call void @llvm.instrprof -; PGO-NEXT: musttail call fastcc void %[[addr2]](ptr null) +; CHECK: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr +; CHECK-NEXT: musttail call fastcc void %[[addr2]] ; CHECK-NEXT: ret void declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1 @@ -57,6 +53,7 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1 declare i1 @llvm.coro.end(ptr, i1, token) #2 declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1 declare ptr @malloc(i64) +declare ptr @await_suspend_function(ptr %awaiter, ptr %hdl) attributes #0 = { presplitcoroutine } attributes #1 = { argmemonly nounwind readonly } diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail1.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail1.ll index d0d11fc4495e..3edb8728d855 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail1.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail1.ll @@ -1,7 +1,6 @@ -; Tests that coro-split will convert coro.resume followed by a suspend to a -; musttail call. -; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK,NOPGO %s -; RUN: opt < %s -passes='pgo-instr-gen,cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK,PGO %s +; Tests that coro-split will convert coro.await.suspend.handle to a musttail call. +; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK %s +; RUN: opt < %s -passes='pgo-instr-gen,cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK %s define void @f() #0 { entry: @@ -28,17 +27,14 @@ await.suspend: ] await.resume1: %hdl = call ptr @g() - %addr2 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0) - call fastcc void %addr2(ptr %hdl) + call void @llvm.coro.await.suspend.handle(ptr null, ptr %hdl, ptr @await_suspend_function) br label %final.suspend await.resume2: %hdl2 = call ptr @h() - %addr3 = call ptr @llvm.coro.subfn.addr(ptr %hdl2, i8 0) - call fastcc void %addr3(ptr %hdl2) + call void @llvm.coro.await.suspend.handle(ptr null, ptr %hdl2, ptr @await_suspend_function) br label %final.suspend await.resume3: - %addr4 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0) - call fastcc void %addr4(ptr null) + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function) br label %final.suspend final.suspend: %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) @@ -63,18 +59,18 @@ unreach: ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @f.resume( ; CHECK: %[[hdl:.+]] = call ptr @g() -; CHECK-NEXT: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[hdl]], i8 0) -; NOPGO-NEXT: musttail call fastcc void %[[addr2]](ptr %[[hdl]]) -; PGO: musttail call fastcc void %[[addr2]](ptr %[[hdl]]) +; CHECK-NEXT: call ptr @await_suspend_function +; CHECK-NEXT: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr +; CHECK-NEXT: musttail call fastcc void %[[addr2]] ; CHECK-NEXT: ret void ; CHECK: %[[hdl2:.+]] = call ptr @h() -; CHECK-NEXT: %[[addr3:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[hdl2]], i8 0) -; NOPGO-NEXT: musttail call fastcc void %[[addr3]](ptr %[[hdl2]]) -; PGO: musttail call fastcc void %[[addr3]](ptr %[[hdl2]]) +; CHECK-NEXT: call ptr @await_suspend_function +; CHECK-NEXT: %[[addr3:.+]] = call ptr @llvm.coro.subfn.addr +; CHECK-NEXT: musttail call fastcc void %[[addr3]] ; CHECK-NEXT: ret void -; CHECK: %[[addr4:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0) -; NOPGO-NEXT: musttail call fastcc void %[[addr4]](ptr null) -; PGO: musttail call fastcc void %[[addr4]](ptr null) +; CHECK: call ptr @await_suspend_function +; CHECK: %[[addr4:.+]] = call ptr @llvm.coro.subfn.addr +; CHECK-NEXT: musttail call fastcc void %[[addr4]] ; CHECK-NEXT: ret void @@ -93,6 +89,7 @@ declare ptr @malloc(i64) declare i8 @switch_result() declare ptr @g() declare ptr @h() +declare ptr @await_suspend_function(ptr %awaiter, ptr %hdl) attributes #0 = { presplitcoroutine } attributes #1 = { argmemonly nounwind readonly } diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail10.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail10.ll index 3e91b79c10f7..a55b3d16e2de 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail10.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail10.ll @@ -1,4 +1,4 @@ -; Tests that we would convert coro.resume to a musttail call if the target is +; Tests that coro-split will convert coro.await.suspend.handle to a musttail call if the target is ; Wasm64 or Wasm32 with tail-call support. ; REQUIRES: webassembly-registered-target @@ -25,8 +25,7 @@ entry: ] await.ready: %save2 = call token @llvm.coro.save(ptr null) - %addr2 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0) - call fastcc void %addr2(ptr null) + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function) %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) switch i8 %suspend2, label %exit [ @@ -51,6 +50,7 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1 declare i1 @llvm.coro.end(ptr, i1, token) #2 declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1 declare ptr @malloc(i64) +declare ptr @await_suspend_function(ptr %awaiter, ptr %hdl) attributes #0 = { presplitcoroutine "target-features"="+tail-call" } attributes #1 = { argmemonly nounwind readonly } diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail2.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail2.ll index 2f27f79480ab..ca1611e19b9f 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail2.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail2.ll @@ -1,5 +1,4 @@ -; Tests that coro-split will convert coro.resume followed by a suspend to a -; musttail call. +; Tests that coro-split will convert coro.await.suspend.handle to a musttail call. ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s ; RUN: opt < %s -passes='pgo-instr-gen,cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s @@ -8,11 +7,6 @@ entry: ret void; } -define void @fakeresume2(ptr align 8) { -entry: - ret void; -} - define void @g() #0 { entry: %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) @@ -29,7 +23,7 @@ entry: ] await.ready: %save2 = call token @llvm.coro.save(ptr null) - call fastcc void @fakeresume2(ptr align 8 null) + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function) %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) switch i8 %suspend2, label %exit [ @@ -47,7 +41,9 @@ exit: ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @g.resume( -; CHECK: musttail call fastcc void @fakeresume2(ptr align 8 null) +; CHECK: call ptr @await_suspend_function +; CHECK-NEXT: call ptr @llvm.coro.subfn.addr +; CHECK-NEXT: musttail call fastcc void ; CHECK-NEXT: ret void declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1 @@ -61,6 +57,7 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1 declare i1 @llvm.coro.end(ptr, i1, token) #2 declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1 declare ptr @malloc(i64) +declare ptr @await_suspend_function(ptr %awaiter, ptr %hdl) attributes #0 = { presplitcoroutine } attributes #1 = { argmemonly nounwind readonly } diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail3.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail3.ll index 4778e3dcaf99..84cdac17beeb 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail3.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail3.ll @@ -1,7 +1,6 @@ -; Tests that coro-split will convert coro.resume followed by a suspend to a -; musttail call. -; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK,NOPGO %s -; RUN: opt < %s -passes='pgo-instr-gen,cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK,PGO %s +; Tests that coro-split will convert coro.await.suspend.handle to a musttail call. +; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK %s +; RUN: opt < %s -passes='pgo-instr-gen,cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK %s define void @f() #0 { entry: @@ -26,17 +25,14 @@ await.suspend: ] await.resume1: %hdl = call ptr @g() - %addr2 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0) - call fastcc void %addr2(ptr %hdl) + call void @llvm.coro.await.suspend.handle(ptr null, ptr %hdl, ptr @await_suspend_function) br label %final.suspend await.resume2: %hdl2 = call ptr @h() - %addr3 = call ptr @llvm.coro.subfn.addr(ptr %hdl2, i8 0) - call fastcc void %addr3(ptr %hdl2) + call void @llvm.coro.await.suspend.handle(ptr null, ptr %hdl2, ptr @await_suspend_function) br label %final.suspend await.resume3: - %addr4 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0) - call fastcc void %addr4(ptr null) + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function) br label %final.suspend final.suspend: %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) @@ -59,22 +55,21 @@ unreach: ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @f.resume( ; CHECK: %[[hdl:.+]] = call ptr @g() -; CHECK-NEXT: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[hdl]], i8 0) -; NOPGO-NEXT: musttail call fastcc void %[[addr2]](ptr %[[hdl]]) -; PGO: musttail call fastcc void %[[addr2]](ptr %[[hdl]]) +; CHECK-NEXT: call ptr @await_suspend_function +; CHECK-NEXT: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr +; CHECK-NEXT: musttail call fastcc void %[[addr2]] ; CHECK-NEXT: ret void ; CHECK: %[[hdl2:.+]] = call ptr @h() -; CHECK-NEXT: %[[addr3:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[hdl2]], i8 0) -; NOPGO-NEXT: musttail call fastcc void %[[addr3]](ptr %[[hdl2]]) -; PGO: musttail call fastcc void %[[addr3]](ptr %[[hdl2]]) +; CHECK-NEXT: call ptr @await_suspend_function +; CHECK-NEXT: %[[addr3:.+]] = call ptr @llvm.coro.subfn.addr +; CHECK-NEXT: musttail call fastcc void %[[addr3]] ; CHECK-NEXT: ret void -; CHECK: %[[addr4:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0) -; NOPGO-NEXT: musttail call fastcc void %[[addr4]](ptr null) -; PGO: musttail call fastcc void %[[addr4]](ptr null) +; CHECK: call ptr @await_suspend_function +; CHECK: %[[addr4:.+]] = call ptr @llvm.coro.subfn.addr +; CHECK-NEXT: musttail call fastcc void %[[addr4]] ; CHECK-NEXT: ret void - declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1 declare i1 @llvm.coro.alloc(token) #2 declare i64 @llvm.coro.size.i64() #3 @@ -89,6 +84,7 @@ declare ptr @malloc(i64) declare i8 @switch_result() declare ptr @g() declare ptr @h() +declare ptr @await_suspend_function(ptr %awaiter, ptr %hdl) attributes #0 = { presplitcoroutine } attributes #1 = { argmemonly nounwind readonly } diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail4.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail4.ll index 00ee422ce586..b647bd2e4a20 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail4.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail4.ll @@ -1,5 +1,4 @@ -; Tests that coro-split will convert a call before coro.suspend to a musttail call -; while the user of the coro.suspend is a icmpinst. +; Tests that coro-split will convert coro.await.suspend.handle to a musttail call. ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s ; RUN: opt < %s -passes='pgo-instr-gen,cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s @@ -24,7 +23,7 @@ entry: await.ready: %save2 = call token @llvm.coro.save(ptr null) - call fastcc void @fakeresume1(ptr align 8 null) + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function) %suspend = call i8 @llvm.coro.suspend(token %save2, i1 true) %switch = icmp ult i8 %suspend, 2 br i1 %switch, label %cleanup, label %coro.end @@ -44,7 +43,7 @@ coro.end: } ; CHECK-LABEL: @f.resume( -; CHECK: musttail call fastcc void @fakeresume1( +; CHECK: musttail call fastcc void ; CHECK-NEXT: ret void declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1 @@ -59,6 +58,7 @@ declare i1 @llvm.coro.end(ptr, i1, token) #2 declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1 declare ptr @malloc(i64) declare void @delete(ptr nonnull) #2 +declare ptr @await_suspend_function(ptr %awaiter, ptr %hdl) attributes #0 = { presplitcoroutine } attributes #1 = { argmemonly nounwind readonly } diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail5.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail5.ll index 9afc79abbe88..7c1a13fd83ce 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail5.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail5.ll @@ -1,5 +1,4 @@ -; Tests that sinked lifetime markers wouldn't provent optimization -; to convert a resuming call to a musttail call. +; Tests that coro-split will convert coro.await.suspend.handle to a musttail call. ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s ; RUN: opt < %s -passes='pgo-instr-gen,cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s @@ -22,7 +21,7 @@ entry: ] await.suspend: %save2 = call token @llvm.coro.save(ptr null) - call fastcc void @fakeresume1(ptr align 8 null) + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function) %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) switch i8 %suspend2, label %exit [ i8 0, label %await.ready @@ -39,7 +38,7 @@ exit: ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @g.resume( -; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null) +; CHECK: musttail call fastcc void ; CHECK-NEXT: ret void declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1 @@ -56,6 +55,7 @@ declare ptr @malloc(i64) declare void @consume(ptr) declare void @llvm.lifetime.start.p0(i64, ptr nocapture) declare void @llvm.lifetime.end.p0(i64, ptr nocapture) +declare ptr @await_suspend_function(ptr %awaiter, ptr %hdl) attributes #0 = { presplitcoroutine } attributes #1 = { argmemonly nounwind readonly } diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll index d9dba92ec4eb..e05169a72916 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll @@ -1,5 +1,5 @@ ; Tests that sinked lifetime markers wouldn't provent optimization -; to convert a resuming call to a musttail call. +; to convert a coro.await.suspend.handle call to a musttail call. ; The difference between this and coro-split-musttail5.ll is that there is ; an extra bitcast instruction in the path, which makes it harder to ; optimize. @@ -25,7 +25,7 @@ entry: ] await.suspend: %save2 = call token @llvm.coro.save(ptr null) - call fastcc void @fakeresume1(ptr align 8 null) + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function) %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) switch i8 %suspend2, label %exit [ i8 0, label %await.ready @@ -42,7 +42,7 @@ exit: ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @g.resume( -; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null) +; CHECK: musttail call fastcc void ; CHECK-NEXT: ret void ; It has a cleanup bb. @@ -63,7 +63,7 @@ entry: ] await.suspend: %save2 = call token @llvm.coro.save(ptr null) - call fastcc void @fakeresume1(ptr align 8 null) + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function) %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) switch i8 %suspend2, label %exit [ i8 0, label %await.ready @@ -90,7 +90,7 @@ exit: ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @f.resume( -; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null) +; CHECK: musttail call fastcc void ; CHECK-NEXT: ret void declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1 @@ -108,6 +108,7 @@ declare void @delete(ptr nonnull) #2 declare void @consume(ptr) declare void @llvm.lifetime.start.p0(i64, ptr nocapture) declare void @llvm.lifetime.end.p0(i64, ptr nocapture) +declare ptr @await_suspend_function(ptr %awaiter, ptr %hdl) attributes #0 = { presplitcoroutine } attributes #1 = { argmemonly nounwind readonly } diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll index d0d5005587bd..8ceb0dda94f6 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll @@ -1,13 +1,11 @@ ; Tests that sinked lifetime markers wouldn't provent optimization -; to convert a resuming call to a musttail call. +; to convert a coro.await.suspend.handle call to a musttail call. ; The difference between this and coro-split-musttail5.ll and coro-split-musttail6.ll ; is that this contains dead instruction generated during the transformation, ; which makes the optimization harder. ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s ; RUN: opt < %s -passes='pgo-instr-gen,cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s -declare void @fakeresume1(ptr align 8) - define i64 @g() #0 { entry: %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) @@ -25,7 +23,7 @@ entry: ] await.suspend: %save2 = call token @llvm.coro.save(ptr null) - call fastcc void @fakeresume1(ptr align 8 null) + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function) %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) ; These (non-trivially) dead instructions are in the way. @@ -48,7 +46,9 @@ exit: ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @g.resume( -; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null) +; CHECK: %[[FRAME:[0-9]+]] = call ptr @await_suspend_function(ptr null, ptr null) +; CHECK: %[[RESUMEADDR:[0-9]+]] = call ptr @llvm.coro.subfn.addr(ptr %[[FRAME]], i8 0) +; CHECK: musttail call fastcc void %[[RESUMEADDR]](ptr %[[FRAME]]) ; CHECK-NEXT: ret void ; It has a cleanup bb. @@ -69,7 +69,7 @@ entry: ] await.suspend: %save2 = call token @llvm.coro.save(ptr null) - call fastcc void @fakeresume1(ptr align 8 null) + call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function) %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) switch i8 %suspend2, label %exit [ i8 0, label %await.ready @@ -96,7 +96,9 @@ exit: ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @f.resume( -; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null) +; CHECK: %[[FRAME:[0-9]+]] = call ptr @await_suspend_function(ptr null, ptr null) +; CHECK: %[[RESUMEADDR:[0-9]+]] = call ptr @llvm.coro.subfn.addr(ptr %[[FRAME]], i8 0) +; CHECK: musttail call fastcc void %[[RESUMEADDR]](ptr %[[FRAME]]) ; CHECK-NEXT: ret void declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1 @@ -114,6 +116,7 @@ declare void @delete(ptr nonnull) #2 declare void @consume(ptr) declare void @llvm.lifetime.start.p0(i64, ptr nocapture) declare void @llvm.lifetime.end.p0(i64, ptr nocapture) +declare ptr @await_suspend_function(ptr %awaiter, ptr %hdl) attributes #0 = { presplitcoroutine } attributes #1 = { argmemonly nounwind readonly } -- GitLab From 95e307caeb17c080724921564d96e1b8457264bc Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 15 May 2024 08:07:17 -0500 Subject: [PATCH 351/578] Fix bolt build with -DBUILD_SHARED_LIBS=ON after 71fbbb69d Commit 71fbbb69d63c461f391cbabf1e32cd9977c4ce68 moved getGUID out of line in llvm/IR/GlobalValue, now users have to link LLVMCore to have the definition of it. /usr/bin/ld: CMakeFiles/LLVMBOLTRewrite.dir/PseudoProbeRewriter.cpp.o: in function `(anonymous namespace)::PseudoProbeRewriter::parsePseudoProbe()': PseudoProbeRewriter.cpp:(.text._ZN12_GLOBAL__N_119PseudoProbeRewriter16parsePseudoProbeEv+0x3d0): undefined reference to `llvm::GlobalValue::getGUID(llvm::StringRef)' /usr/bin/ld: CMakeFiles/LLVMBOLTRewrite.dir/PseudoProbeRewriter.cpp.o: in function `(anonymous namespace)::PseudoProbeRewriter::encodePseudoProbes()': PseudoProbeRewriter.cpp:(.text._ZN12_GLOBAL__N_119PseudoProbeRewriter18encodePseudoProbesEv+0x11a1): undefined reference to `llvm::GlobalValue::getGUID(llvm::StringRef)' collect2: error: ld returned 1 exit status make[2]: *** [tools/bolt/lib/Rewrite/CMakeFiles/LLVMBOLTRewrite.dir/build.make:275: lib/libLLVMBOLTRewrite.so.19.0git] Error 1 --- bolt/lib/Rewrite/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/bolt/lib/Rewrite/CMakeLists.txt b/bolt/lib/Rewrite/CMakeLists.txt index 6890f52e2b28..578f1763bfe4 100644 --- a/bolt/lib/Rewrite/CMakeLists.txt +++ b/bolt/lib/Rewrite/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + Core DebugInfoDWARF DWP JITLink -- GitLab From c2fba6df944e11e2c9a7073405c6a817fdba14e3 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Wed, 15 May 2024 20:49:28 +0700 Subject: [PATCH 352/578] [clang][SPARC] Treat empty structs as if it's a one-bit type in the CC (#90338) Make sure that empty structs are treated as if it has a size of one bit in function parameters and return types so that it occupies a full argument and/or return register slot. This fixes crashes and miscompilations when passing and/or returning empty structs. Reviewed by: @s-barannikov --- clang/lib/CodeGen/Targets/Sparc.cpp | 5 ++- clang/test/CodeGen/sparcv9-abi.c | 41 +++++++++++++++++++++ clang/test/CodeGen/sparcv9-class-return.cpp | 24 ++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGen/sparcv9-class-return.cpp diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index 9025a633f328..b82e9a69e196 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -263,7 +263,10 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { CoerceBuilder CB(getVMContext(), getDataLayout()); CB.addStruct(0, StrTy); - CB.pad(llvm::alignTo(CB.DL.getTypeSizeInBits(StrTy), 64)); + // All structs, even empty ones, should take up a register argument slot, + // so pin the minimum struct size to one bit. + CB.pad(llvm::alignTo( + std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), 1UL), 64)); // Try to use the original type for coercion. llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType(); diff --git a/clang/test/CodeGen/sparcv9-abi.c b/clang/test/CodeGen/sparcv9-abi.c index 5e74a9a883ce..616e24e7c519 100644 --- a/clang/test/CodeGen/sparcv9-abi.c +++ b/clang/test/CodeGen/sparcv9-abi.c @@ -21,6 +21,47 @@ char f_int_4(char x) { return x; } // CHECK-LABEL: define{{.*}} fp128 @f_ld(fp128 noundef %x) long double f_ld(long double x) { return x; } +// Zero-sized structs reserves an argument register slot if passed directly. +struct empty {}; +struct emptyarr { struct empty a[10]; }; + +// CHECK-LABEL: define{{.*}} i64 @f_empty(i64 %x.coerce) +struct empty f_empty(struct empty x) { return x; } + +// CHECK-LABEL: define{{.*}} i64 @f_emptyarr(i64 %x.coerce) +struct empty f_emptyarr(struct emptyarr x) { return x.a[0]; } + +// CHECK-LABEL: define{{.*}} i64 @f_emptyvar(i32 noundef zeroext %count, ...) +long f_emptyvar(unsigned count, ...) { + long ret; + va_list args; + va_start(args, count); + +// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %args +// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8 +// CHECK-DAG: store ptr %[[NXT]], ptr %args + va_arg(args, struct empty); + +// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %args +// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8 +// CHECK-DAG: store ptr %[[NXT]], ptr %args +// CHECK-DAG: load i64, ptr %[[CUR]] + ret = va_arg(args, long); + va_end(args); + return ret; +} + +// If the zero-sized struct is contained in a non-zero-sized struct, +// though, it doesn't reserve any registers. +struct emptymixed { struct empty a; long b; }; +struct emptyflex { unsigned count; struct empty data[10]; }; + +// CHECK-LABEL: define{{.*}} i64 @f_emptymixed(i64 %x.coerce) +long f_emptymixed(struct emptymixed x) { return x.b; } + +// CHECK-LABEL: define{{.*}} i64 @f_emptyflex(i64 %x.coerce, i64 noundef %y) +long f_emptyflex(struct emptyflex x, long y) { return y; } + // Small structs are passed in registers. struct small { int *a, *b; diff --git a/clang/test/CodeGen/sparcv9-class-return.cpp b/clang/test/CodeGen/sparcv9-class-return.cpp new file mode 100644 index 000000000000..2428219422d8 --- /dev/null +++ b/clang/test/CodeGen/sparcv9-class-return.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s + +class Empty { +}; + +class Long : public Empty { +public: + long l; +}; + +// CHECK: define{{.*}} i64 @_Z4foo15Empty(i64 %e.coerce) +Empty foo1(Empty e) { + return e; +} + +// CHECK: define{{.*}} %class.Long @_Z4foo24Long(i64 %l.coerce) +Long foo2(Long l) { + return l; +} + +// CHECK: define{{.*}} i64 @_Z4foo34Long(i64 %l.coerce) +long foo3(Long l) { + return l.l; +} -- GitLab From 97a30448f9477e0196f9340303aa20d544f1629a Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 15 May 2024 08:57:45 -0500 Subject: [PATCH 353/578] [flang][OpenMP] Add `private` to `allocate` in parallel-sections.f90 (#92185) Add a privatizing clause to the construct that uses `allocate` clause. Amend the CHECK lines to reflect the expected output. --- flang/test/Lower/OpenMP/parallel-sections.f90 | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/flang/test/Lower/OpenMP/parallel-sections.f90 b/flang/test/Lower/OpenMP/parallel-sections.f90 index 2f78dd4562b0..285102e06cad 100644 --- a/flang/test/Lower/OpenMP/parallel-sections.f90 +++ b/flang/test/Lower/OpenMP/parallel-sections.f90 @@ -39,13 +39,10 @@ end subroutine omp_parallel_sections subroutine omp_parallel_sections_allocate(x, y) use omp_lib integer, intent(inout) :: x, y + !CHECK: omp.parallel !CHECK: %[[allocator_1:.*]] = arith.constant 4 : i64 - !CHECK: %[[allocator_2:.*]] = arith.constant 4 : i64 - !CHECK: omp.parallel allocate( - !CHECK: %[[allocator_2]] : i64 -> %{{.*}} : !fir.ref) { - !CHECK: omp.sections allocate( - !CHECK: %[[allocator_1]] : i64 -> %{{.*}} : !fir.ref) { - !$omp parallel sections allocate(omp_high_bw_mem_alloc: x) + !CHECK: omp.sections allocate(%[[allocator_1]] : i64 -> %{{.*}} : !fir.ref) { + !$omp parallel sections allocate(omp_high_bw_mem_alloc: x) private(x, y) !CHECK: omp.section { !$omp section x = x + 12 -- GitLab From 4ec4a8e7fe463852e197d4ff396f4911ccce7449 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 15 May 2024 09:04:07 -0500 Subject: [PATCH 354/578] [Frontend][OpenMP] Privatizing clauses in construct decomposition (#92176) Add remaining clauses with the "privatizing" property to construct decomposition, specifically to the part handling the `allocate` clause. --------- Co-authored-by: Tom Eccles --- .../Frontend/OpenMP/ConstructCompositionT.h | 20 ++- .../Frontend/OpenMP/ConstructDecompositionT.h | 5 + .../Frontend/OpenMPDecompositionTest.cpp | 123 ++++++++++++++++-- 3 files changed, 139 insertions(+), 9 deletions(-) diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h index 9dcb115a0c51..f6ee963bd885 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ConstructCompositionT.h @@ -343,13 +343,31 @@ template void ConstructCompositionT::mergeDSA() { } } - // Check reductions as well, clear "shared" if set. + // Check other privatizing clauses as well, clear "shared" if set. + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_in_reduction]) { + using InReductionTy = tomp::clause::InReductionT; + using ListTy = typename InReductionTy::List; + for (auto &object : std::get(std::get(clause.u).t)) + getDsa(object).second &= ~DSA::Shared; + } + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_linear]) { + using LinearTy = tomp::clause::LinearT; + using ListTy = typename LinearTy::List; + for (auto &object : std::get(std::get(clause.u).t)) + getDsa(object).second &= ~DSA::Shared; + } for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_reduction]) { using ReductionTy = tomp::clause::ReductionT; using ListTy = typename ReductionTy::List; for (auto &object : std::get(std::get(clause.u).t)) getDsa(object).second &= ~DSA::Shared; } + for (auto &clause : clauseSets[llvm::omp::Clause::OMPC_task_reduction]) { + using TaskReductionTy = tomp::clause::TaskReductionT; + using ListTy = typename TaskReductionTy::List; + for (auto &object : std::get(std::get(clause.u).t)) + getDsa(object).second &= ~DSA::Shared; + } tomp::ListT privateObj, sharedObj, firstpObj, lastpObj, lastpcObj; for (auto &[object, dsa] : objectDsa) { diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h index 5f12c62b832f..02c88a58e099 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h @@ -793,9 +793,14 @@ bool ConstructDecompositionT::applyClause( // [5.2:340:33] auto canMakePrivateCopy = [](llvm::omp::Clause id) { switch (id) { + // Clauses with "privatization" property: case llvm::omp::Clause::OMPC_firstprivate: + case llvm::omp::Clause::OMPC_in_reduction: case llvm::omp::Clause::OMPC_lastprivate: + case llvm::omp::Clause::OMPC_linear: case llvm::omp::Clause::OMPC_private: + case llvm::omp::Clause::OMPC_reduction: + case llvm::omp::Clause::OMPC_task_reduction: return true; default: return false; diff --git a/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp b/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp index df48e9cc0ff4..8157e41e833a 100644 --- a/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp +++ b/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp @@ -288,6 +288,14 @@ std::string stringify(const omp::DirectiveWithClauses &DWC) { // --- Tests ---------------------------------------------------------- +namespace red { +// Make it easier to construct reduction operators from built-in intrinsics. +omp::clause::ReductionOperator +makeOp(omp::clause::DefinedOperator::IntrinsicOperator Op) { + return omp::clause::ReductionOperator{omp::clause::DefinedOperator{Op}}; +} +} // namespace red + namespace { using namespace llvm::omp; @@ -699,6 +707,92 @@ TEST_F(OpenMPDecompositionTest, Order1) { TEST_F(OpenMPDecompositionTest, Allocate1) { omp::Object x{"x"}; + // Allocate + firstprivate + omp::List Clauses{ + {OMPC_allocate, + omp::clause::Allocate{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, + {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (33) + ASSERT_EQ(Dir1, "sections firstprivate(x) allocate(, , , (x))"); // (33) +} + +TEST_F(OpenMPDecompositionTest, Allocate2) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + // Allocate + in_reduction + omp::List Clauses{ + {OMPC_allocate, + omp::clause::Allocate{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, + {OMPC_in_reduction, omp::clause::InReduction{{{Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "target in_reduction((3), (x)) allocate(, , , (x))"); // (33) + ASSERT_EQ(Dir1, "parallel"); // (33) +} + +TEST_F(OpenMPDecompositionTest, Allocate3) { + omp::Object x{"x"}; + + // Allocate + linear + omp::List Clauses{ + {OMPC_allocate, + omp::clause::Allocate{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, + {OMPC_linear, + omp::clause::Linear{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_for, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + // The "shared" clause is duplicated---this isn't harmful, but it + // should be fixed eventually. + ASSERT_EQ(Dir0, "parallel shared(x) shared(x)"); // (33) + ASSERT_EQ(Dir1, "for linear(, , , (x)) firstprivate(x) lastprivate(, (x)) " + "allocate(, , , (x))"); // (33) +} + +TEST_F(OpenMPDecompositionTest, Allocate4) { + omp::Object x{"x"}; + + // Allocate + lastprivate + omp::List Clauses{ + {OMPC_allocate, + omp::clause::Allocate{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, + {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (33) + ASSERT_EQ(Dir1, "sections lastprivate(, (x)) allocate(, , , (x))"); // (33) +} + +TEST_F(OpenMPDecompositionTest, Allocate5) { + omp::Object x{"x"}; + + // Allocate + private omp::List Clauses{ {OMPC_allocate, omp::clause::Allocate{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, @@ -715,6 +809,27 @@ TEST_F(OpenMPDecompositionTest, Allocate1) { ASSERT_EQ(Dir1, "sections private(x) allocate(, , , (x))"); // (33) } +TEST_F(OpenMPDecompositionTest, Allocate6) { + omp::Object x{"x"}; + auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); + + // Allocate + reduction + omp::List Clauses{ + {OMPC_allocate, + omp::clause::Allocate{{std::nullopt, std::nullopt, std::nullopt, {x}}}}, + {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, + }; + + omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, + Clauses); + ASSERT_EQ(Dec.output.size(), 2u); + + std::string Dir0 = stringify(Dec.output[0]); + std::string Dir1 = stringify(Dec.output[1]); + ASSERT_EQ(Dir0, "parallel shared(x)"); // (33) + ASSERT_EQ(Dir1, "sections reduction(, (3), (x)) allocate(, , , (x))"); // (33) +} + // REDUCTION // [5.2:134:17-18] // Directives: do, for, loop, parallel, scope, sections, simd, taskloop, teams @@ -741,14 +856,6 @@ TEST_F(OpenMPDecompositionTest, Allocate1) { // clause on the construct, then the effect is as if the list item in the // reduction clause appears as a list item in a map clause with a map-type of // tofrom. -namespace red { -// Make is easier to construct reduction operators from built-in intrinsics. -omp::clause::ReductionOperator -makeOp(omp::clause::DefinedOperator::IntrinsicOperator Op) { - return omp::clause::ReductionOperator{omp::clause::DefinedOperator{Op}}; -} -} // namespace red - TEST_F(OpenMPDecompositionTest, Reduction1) { omp::Object x{"x"}; auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); -- GitLab From 8d386c63a8d38bc50acba8dba2cd5f0daca57012 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 15 May 2024 09:05:02 -0500 Subject: [PATCH 355/578] [Frontend][OpenMP] Reduction modifier must be applied somewhere (#92160) Detect the case when a reduction modifier ends up not being applied after construct decomposition, treat it as an error. This fixes a regression in the gfortran test suite after PR90098. --- .../Lower/OpenMP/invalid-reduction-modifier.f90 | 14 ++++++++++++++ .../llvm/Frontend/OpenMP/ConstructDecompositionT.h | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 diff --git a/flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 b/flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 new file mode 100644 index 000000000000..817c5b731c62 --- /dev/null +++ b/flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 @@ -0,0 +1,14 @@ +!Remove the --crash below once we can diagnose the issue more gracefully. +!RUN: not --crash %flang_fc1 -fopenmp -emit-hlfir -o - %s + +! Check that we reject the "task" reduction modifier on the "simd" directive. + +subroutine fred(x) + integer, intent(inout) :: x + + !$omp simd reduction(task, +:x) + do i = 1, 100 + x = foo(i) + enddo + !$omp end simd +end diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h index 02c88a58e099..3fa27608ead9 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h @@ -935,7 +935,8 @@ bool ConstructDecompositionT::applyClause( // Apply clause without modifier. leaf.clauses.push_back(unmodified); } - applied = true; + // The modifier must be applied to some construct. + applied = effectiveApplied; } if (!applied) -- GitLab From 7c8176ebd39c357fc4fa488861318409cd87d8f2 Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Wed, 15 May 2024 22:08:17 +0800 Subject: [PATCH 356/578] [Coroutines] Remove unused function (NFC) llvm-project/llvm/lib/Transforms/Coroutines/CoroSplit.cpp:1223:1: error: unused function 'scanPHIsAndUpdateValueMap' [-Werror,-Wunused-function] scanPHIsAndUpdateValueMap(Instruction *Prev, BasicBlock *NewBlock, ^ 1 error generated. --- llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 450ea8234371..1d9cf185b75a 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -1217,23 +1217,6 @@ static void postSplitCleanup(Function &F) { #endif } -// Assuming we arrived at the block NewBlock from Prev instruction, store -// PHI's incoming values in the ResolvedValues map. -static void -scanPHIsAndUpdateValueMap(Instruction *Prev, BasicBlock *NewBlock, - DenseMap &ResolvedValues) { - auto *PrevBB = Prev->getParent(); - for (PHINode &PN : NewBlock->phis()) { - auto V = PN.getIncomingValueForBlock(PrevBB); - // See if we already resolved it. - auto VI = ResolvedValues.find(V); - if (VI != ResolvedValues.end()) - V = VI->second; - // Remember the value. - ResolvedValues[&PN] = V; - } -} - // Coroutine has no suspend points. Remove heap allocation for the coroutine // frame if possible. static void handleNoSuspendCoroutine(coro::Shape &Shape) { -- GitLab From 466d266945196ebbdefd8d72f654551d54d68600 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Wed, 15 May 2024 15:13:53 +0100 Subject: [PATCH 357/578] [AMDGPU] Fix GFX90x check prefixes in tests (#92254) --- llvm/test/CodeGen/AMDGPU/agpr-register-count.ll | 6 ++---- llvm/test/CodeGen/AMDGPU/spill-vgpr.ll | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/agpr-register-count.ll b/llvm/test/CodeGen/AMDGPU/agpr-register-count.ll index f84d476fc122..bd5dc6e20709 100644 --- a/llvm/test/CodeGen/AMDGPU/agpr-register-count.ll +++ b/llvm/test/CodeGen/AMDGPU/agpr-register-count.ll @@ -157,10 +157,8 @@ declare void @undef_func() ; GFX908: .amdhsa_next_free_vgpr 32 ; GFX90A: .amdhsa_next_free_vgpr 64 ; GFX90A: .amdhsa_accum_offset 32 -; GCN908: NumVgprs: 128 -; GCN908: NumAgprs: 128 -; GCN90A: NumVgprs: 256 -; GCN90A: NumAgprs: 256 +; GCN: NumVgprs: 32 +; GCN: NumAgprs: 32 ; GFX908: TotalNumVgprs: 32 ; GFX90A: TotalNumVgprs: 64 ; GFX908: VGPRBlocks: 7 diff --git a/llvm/test/CodeGen/AMDGPU/spill-vgpr.ll b/llvm/test/CodeGen/AMDGPU/spill-vgpr.ll index 9eacb88066c0..1cc5b7f7d14e 100644 --- a/llvm/test/CodeGen/AMDGPU/spill-vgpr.ll +++ b/llvm/test/CodeGen/AMDGPU/spill-vgpr.ll @@ -88,8 +88,8 @@ define amdgpu_kernel void @max_10_vgprs_spill_v32(ptr addrspace(1) %p) #0 { ; GFX900: ScratchSize: 132 ; GFX908: NumVgprs: 252 ; GFX908: ScratchSize: 0 -; GCN900: VGPRBlocks: 63 -; GCN908: VGPRBlocks: 62 +; GFX900: VGPRBlocks: 63 +; GFX908: VGPRBlocks: 62 ; GFX900: NumVGPRsForWavesPerEU: 256 ; GFX908: NumVGPRsForWavesPerEU: 252 define amdgpu_kernel void @max_256_vgprs_spill_9x32(ptr addrspace(1) %p) #1 { -- GitLab From 61da6366d043792d7db280ce9edd2db62516e0e8 Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Wed, 15 May 2024 15:20:27 +0100 Subject: [PATCH 358/578] [flang] Initial debug info support for local variables. (#90905) We need the information in the `DeclareOp` to generate debug information for variables. Currently, cg-rewrite removes the `DeclareOp`. As `AddDebugInfo` runs after that, it cannot process the `DeclareOp`. My initial plan was to make the `AddDebugInfo` pass run before the cg-rewrite but that has few issues. 1. Initially I was thinking to use the memref op to carry the variable attr. But as @tblah suggested in the #86939, it makes more sense to carry that information on `DeclareOp`. It also makes it easy to handle it in codegen and there is no special handling needed for arguments. For this reason, we need to preserve the `DeclareOp` till the codegen. 2. Running earlier, we will miss the changes in passes that run between cg-rewrite and codegen. But not removing the DeclareOp in cg-rewrite has the issue that ShapeOp remains and it causes errors during codegen. To solve this problem, I convert DeclareOp to XDeclareOp in cg-rewrite instead of removing it. This was mentioned as possible solution by @jeanPerier in https://reviews.llvm.org/D136254 The conversion follows similar logic as used for other operators in that file. The FortranAttr and CudaAttr are currently not converted but left as TODO when the need arise. Now `AddDebugInfo` pass can extracts information about local variables from `XDeclareOp` and creates `DILocalVariableAttr`. These are attached to `XDeclareOp` using `FusedLoc` approach. Codegen can use them to create `DbgDeclareOp`. I have added tests that checks the debug information in mlir from and also in llvm ir. Currently we only handle very limited types. Rest are given a place holder type. The previous placeholder type was basic type with `DW_ATE_address` encoding. When variables are added, it started causing assertions in the llvm debug info generation logic for some types. It has been changed to an interger type to prevent these issues until we handle those types properly. --- .../flang}/Optimizer/CodeGen/CGOps.h | 1 + .../include/flang/Optimizer/CodeGen/CGOps.td | 34 +++++++ .../flang/Optimizer/CodeGen/CGPasses.td | 4 + .../include/flang/Optimizer/CodeGen/CodeGen.h | 6 +- flang/include/flang/Tools/CLOptions.inc | 11 ++- flang/lib/Optimizer/CodeGen/CGOps.cpp | 2 +- flang/lib/Optimizer/CodeGen/CodeGen.cpp | 50 +++++++--- flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp | 49 ++++++++-- .../lib/Optimizer/Transforms/AddDebugInfo.cpp | 56 +++++++++++- .../Transforms/DebugTypeGenerator.cpp | 10 +- flang/test/Fir/declare-codegen.fir | 22 +++-- flang/test/Fir/dummy-scope-codegen.fir | 11 ++- flang/test/Transforms/debug-local-var-2.f90 | 91 +++++++++++++++++++ flang/test/Transforms/debug-local-var.f90 | 54 +++++++++++ 14 files changed, 354 insertions(+), 47 deletions(-) rename flang/{lib => include/flang}/Optimizer/CodeGen/CGOps.h (94%) create mode 100644 flang/test/Transforms/debug-local-var-2.f90 create mode 100644 flang/test/Transforms/debug-local-var.f90 diff --git a/flang/lib/Optimizer/CodeGen/CGOps.h b/flang/include/flang/Optimizer/CodeGen/CGOps.h similarity index 94% rename from flang/lib/Optimizer/CodeGen/CGOps.h rename to flang/include/flang/Optimizer/CodeGen/CGOps.h index b5a6d5bb9a9e..df909d9ee81c 100644 --- a/flang/lib/Optimizer/CodeGen/CGOps.h +++ b/flang/include/flang/Optimizer/CodeGen/CGOps.h @@ -13,6 +13,7 @@ #ifndef OPTIMIZER_CODEGEN_CGOPS_H #define OPTIMIZER_CODEGEN_CGOPS_H +#include "flang/Optimizer/Dialect/FIRAttr.h" #include "flang/Optimizer/Dialect/FIRType.h" #include "mlir/Dialect/Func/IR/FuncOps.h" diff --git a/flang/include/flang/Optimizer/CodeGen/CGOps.td b/flang/include/flang/Optimizer/CodeGen/CGOps.td index 35e70fa2ffa3..c375edee1fa7 100644 --- a/flang/include/flang/Optimizer/CodeGen/CGOps.td +++ b/flang/include/flang/Optimizer/CodeGen/CGOps.td @@ -16,6 +16,8 @@ include "mlir/IR/SymbolInterfaces.td" include "flang/Optimizer/Dialect/FIRTypes.td" +include "flang/Optimizer/Dialect/FIRAttr.td" +include "mlir/IR/BuiltinAttributes.td" def fircg_Dialect : Dialect { let name = "fircg"; @@ -202,4 +204,36 @@ def fircg_XArrayCoorOp : fircg_Op<"ext_array_coor", [AttrSizedOperandSegments]> }]; } +// Extended Declare operation. +def fircg_XDeclareOp : fircg_Op<"ext_declare", [AttrSizedOperandSegments]> { + let summary = "for internal conversion only"; + + let description = [{ + Prior to lowering to LLVM IR dialect, a DeclareOp will + be converted to an extended DeclareOp. + }]; + + let arguments = (ins + AnyRefOrBox:$memref, + Variadic:$shape, + Variadic:$shift, + Variadic:$typeparams, + Optional:$dummy_scope, + Builtin_StringAttr:$uniq_name + ); + let results = (outs AnyRefOrBox); + + let assemblyFormat = [{ + $memref (`(` $shape^ `)`)? (`origin` $shift^)? (`typeparams` $typeparams^)? + (`dummy_scope` $dummy_scope^)? + attr-dict `:` functional-type(operands, results) + }]; + + let extraClassDeclaration = [{ + // Shape is optional, but if it exists, it will be at offset 1. + unsigned shapeOffset() { return 1; } + unsigned shiftOffset() { return shapeOffset() + getShape().size(); } + }]; +} + #endif diff --git a/flang/include/flang/Optimizer/CodeGen/CGPasses.td b/flang/include/flang/Optimizer/CodeGen/CGPasses.td index f524fb423734..565920e55e6a 100644 --- a/flang/include/flang/Optimizer/CodeGen/CGPasses.td +++ b/flang/include/flang/Optimizer/CodeGen/CGPasses.td @@ -47,6 +47,10 @@ def CodeGenRewrite : Pass<"cg-rewrite", "mlir::ModuleOp"> { let dependentDialects = [ "fir::FIROpsDialect", "fir::FIRCodeGenDialect" ]; + let options = [ + Option<"preserveDeclare", "preserve-declare", "bool", /*default=*/"false", + "Preserve DeclareOp during pre codegen re-write."> + ]; let statistics = [ Statistic<"numDCE", "num-dce'd", "Number of operations eliminated"> ]; diff --git a/flang/include/flang/Optimizer/CodeGen/CodeGen.h b/flang/include/flang/Optimizer/CodeGen/CodeGen.h index 26097dabf56c..4d2b191b46d0 100644 --- a/flang/include/flang/Optimizer/CodeGen/CodeGen.h +++ b/flang/include/flang/Optimizer/CodeGen/CodeGen.h @@ -30,7 +30,8 @@ struct NameUniquer; /// Prerequiste pass for code gen. Perform intermediate rewrites to perform /// the code gen (to LLVM-IR dialect) conversion. -std::unique_ptr createFirCodeGenRewritePass(); +std::unique_ptr createFirCodeGenRewritePass( + CodeGenRewriteOptions Options = CodeGenRewriteOptions{}); /// FirTargetRewritePass options. struct TargetRewriteOptions { @@ -88,7 +89,8 @@ void populateFIRToLLVMConversionPatterns(fir::LLVMTypeConverter &converter, fir::FIRToLLVMPassOptions &options); /// Populate the pattern set with the PreCGRewrite patterns. -void populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns); +void populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns, + bool preserveDeclare); // declarative passes #define GEN_PASS_REGISTRATION diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc index cc3431d5b71d..761315e0abc8 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -169,9 +169,11 @@ inline void addMemoryAllocationOpt(mlir::PassManager &pm) { } #if !defined(FLANG_EXCLUDE_CODEGEN) -inline void addCodeGenRewritePass(mlir::PassManager &pm) { - addPassConditionally( - pm, disableCodeGenRewrite, fir::createFirCodeGenRewritePass); +inline void addCodeGenRewritePass(mlir::PassManager &pm, bool preserveDeclare) { + fir::CodeGenRewriteOptions options; + options.preserveDeclare = preserveDeclare; + addPassConditionally(pm, disableCodeGenRewrite, + [&]() { return fir::createFirCodeGenRewritePass(options); }); } inline void addTargetRewritePass(mlir::PassManager &pm) { @@ -353,7 +355,8 @@ inline void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig config, llvm::StringRef inputFilename = {}) { fir::addBoxedProcedurePass(pm); addNestedPassToAllTopLevelOperations(pm, fir::createAbstractResultOpt); - fir::addCodeGenRewritePass(pm); + fir::addCodeGenRewritePass( + pm, (config.DebugInfo != llvm::codegenoptions::NoDebugInfo)); fir::addTargetRewritePass(pm); fir::addExternalNameConversionPass(pm, config.Underscoring); fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename); diff --git a/flang/lib/Optimizer/CodeGen/CGOps.cpp b/flang/lib/Optimizer/CodeGen/CGOps.cpp index 44d07d26dd2b..6b8ba7452555 100644 --- a/flang/lib/Optimizer/CodeGen/CGOps.cpp +++ b/flang/lib/Optimizer/CodeGen/CGOps.cpp @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -#include "CGOps.h" +#include "flang/Optimizer/CodeGen/CGOps.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 21154902d23f..72172f63888e 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -12,7 +12,7 @@ #include "flang/Optimizer/CodeGen/CodeGen.h" -#include "CGOps.h" +#include "flang/Optimizer/CodeGen/CGOps.h" #include "flang/Optimizer/CodeGen/CodeGenOpenMP.h" #include "flang/Optimizer/CodeGen/FIROpPatterns.h" #include "flang/Optimizer/CodeGen/TypeConverter.h" @@ -170,6 +170,28 @@ genAllocationScaleSize(OP op, mlir::Type ity, return nullptr; } +namespace { +struct DeclareOpConversion : public fir::FIROpConversion { +public: + using FIROpConversion::FIROpConversion; + mlir::LogicalResult + matchAndRewrite(fir::cg::XDeclareOp declareOp, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + auto memRef = adaptor.getOperands()[0]; + if (auto fusedLoc = mlir::dyn_cast(declareOp.getLoc())) { + if (auto varAttr = + mlir::dyn_cast_or_null( + fusedLoc.getMetadata())) { + rewriter.create(memRef.getLoc(), memRef, + varAttr, nullptr); + } + } + rewriter.replaceOp(declareOp, memRef); + return mlir::success(); + } +}; +} // namespace + namespace { /// convert to LLVM IR dialect `alloca` struct AllocaOpConversion : public fir::FIROpConversion { @@ -3714,19 +3736,19 @@ void fir::populateFIRToLLVMConversionPatterns( BoxOffsetOpConversion, BoxProcHostOpConversion, BoxRankOpConversion, BoxTypeCodeOpConversion, BoxTypeDescOpConversion, CallOpConversion, CmpcOpConversion, ConstcOpConversion, ConvertOpConversion, - CoordinateOpConversion, DTEntryOpConversion, DivcOpConversion, - EmboxOpConversion, EmboxCharOpConversion, EmboxProcOpConversion, - ExtractValueOpConversion, FieldIndexOpConversion, FirEndOpConversion, - FreeMemOpConversion, GlobalLenOpConversion, GlobalOpConversion, - HasValueOpConversion, InsertOnRangeOpConversion, InsertValueOpConversion, - IsPresentOpConversion, LenParamIndexOpConversion, LoadOpConversion, - MulcOpConversion, NegcOpConversion, NoReassocOpConversion, - SelectCaseOpConversion, SelectOpConversion, SelectRankOpConversion, - SelectTypeOpConversion, ShapeOpConversion, ShapeShiftOpConversion, - ShiftOpConversion, SliceOpConversion, StoreOpConversion, - StringLitOpConversion, SubcOpConversion, TypeDescOpConversion, - TypeInfoOpConversion, UnboxCharOpConversion, UnboxProcOpConversion, - UndefOpConversion, UnreachableOpConversion, + CoordinateOpConversion, DTEntryOpConversion, DeclareOpConversion, + DivcOpConversion, EmboxOpConversion, EmboxCharOpConversion, + EmboxProcOpConversion, ExtractValueOpConversion, FieldIndexOpConversion, + FirEndOpConversion, FreeMemOpConversion, GlobalLenOpConversion, + GlobalOpConversion, HasValueOpConversion, InsertOnRangeOpConversion, + InsertValueOpConversion, IsPresentOpConversion, LenParamIndexOpConversion, + LoadOpConversion, MulcOpConversion, NegcOpConversion, + NoReassocOpConversion, SelectCaseOpConversion, SelectOpConversion, + SelectRankOpConversion, SelectTypeOpConversion, ShapeOpConversion, + ShapeShiftOpConversion, ShiftOpConversion, SliceOpConversion, + StoreOpConversion, StringLitOpConversion, SubcOpConversion, + TypeDescOpConversion, TypeInfoOpConversion, UnboxCharOpConversion, + UnboxProcOpConversion, UndefOpConversion, UnreachableOpConversion, UnrealizedConversionCastOpConversion, XArrayCoorOpConversion, XEmboxOpConversion, XReboxOpConversion, ZeroOpConversion>(converter, options); diff --git a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp index 5bd3ec8d1845..c54a7457db76 100644 --- a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp +++ b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp @@ -12,8 +12,8 @@ #include "flang/Optimizer/CodeGen/CodeGen.h" -#include "CGOps.h" #include "flang/Optimizer/Builder/Todo.h" // remove when TODO's are done +#include "flang/Optimizer/CodeGen/CGOps.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" @@ -270,13 +270,43 @@ public: }; class DeclareOpConversion : public mlir::OpRewritePattern { + bool preserveDeclare; + public: using OpRewritePattern::OpRewritePattern; + DeclareOpConversion(mlir::MLIRContext *ctx, bool preserveDecl) + : OpRewritePattern(ctx), preserveDeclare(preserveDecl) {} mlir::LogicalResult matchAndRewrite(fir::DeclareOp declareOp, mlir::PatternRewriter &rewriter) const override { - rewriter.replaceOp(declareOp, declareOp.getMemref()); + if (!preserveDeclare) { + rewriter.replaceOp(declareOp, declareOp.getMemref()); + return mlir::success(); + } + auto loc = declareOp.getLoc(); + llvm::SmallVector shapeOpers; + llvm::SmallVector shiftOpers; + if (auto shapeVal = declareOp.getShape()) { + if (auto shapeOp = mlir::dyn_cast(shapeVal.getDefiningOp())) + populateShape(shapeOpers, shapeOp); + else if (auto shiftOp = + mlir::dyn_cast(shapeVal.getDefiningOp())) + populateShapeAndShift(shapeOpers, shiftOpers, shiftOp); + else if (auto shiftOp = + mlir::dyn_cast(shapeVal.getDefiningOp())) + populateShift(shiftOpers, shiftOp); + else + return mlir::failure(); + } + // FIXME: Add FortranAttrs and CudaAttrs + auto xDeclOp = rewriter.create( + loc, declareOp.getType(), declareOp.getMemref(), shapeOpers, shiftOpers, + declareOp.getTypeparams(), declareOp.getDummyScope(), + declareOp.getUniqName()); + LLVM_DEBUG(llvm::dbgs() + << "rewriting " << declareOp << " to " << xDeclOp << '\n'); + rewriter.replaceOp(declareOp, xDeclOp.getOperation()->getResults()); return mlir::success(); } }; @@ -297,6 +327,7 @@ public: class CodeGenRewrite : public fir::impl::CodeGenRewriteBase { public: + CodeGenRewrite(fir::CodeGenRewriteOptions opts) : Base(opts) {} void runOnOperation() override final { mlir::ModuleOp mod = getOperation(); @@ -314,7 +345,7 @@ public: mlir::cast(embox.getType()).getEleTy())); }); mlir::RewritePatternSet patterns(&context); - fir::populatePreCGRewritePatterns(patterns); + fir::populatePreCGRewritePatterns(patterns, preserveDeclare); if (mlir::failed( mlir::applyPartialConversion(mod, target, std::move(patterns)))) { mlir::emitError(mlir::UnknownLoc::get(&context), @@ -330,12 +361,14 @@ public: } // namespace -std::unique_ptr fir::createFirCodeGenRewritePass() { - return std::make_unique(); +std::unique_ptr +fir::createFirCodeGenRewritePass(fir::CodeGenRewriteOptions Options) { + return std::make_unique(Options); } -void fir::populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns) { +void fir::populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns, + bool preserveDeclare) { patterns.insert( - patterns.getContext()); + DummyScopeOpConversion>(patterns.getContext()); + patterns.add(patterns.getContext(), preserveDeclare); } diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 908c8fc96f63..cfad366cb5cb 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -15,6 +15,7 @@ #include "flang/Common/Version.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/CodeGen/CGOps.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" @@ -45,13 +46,59 @@ namespace fir { namespace { class AddDebugInfoPass : public fir::impl::AddDebugInfoBase { + void handleDeclareOp(fir::cg::XDeclareOp declOp, + mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scopeAttr, + fir::DebugTypeGenerator &typeGen); + public: AddDebugInfoPass(fir::AddDebugInfoOptions options) : Base(options) {} void runOnOperation() override; }; +static uint32_t getLineFromLoc(mlir::Location loc) { + uint32_t line = 1; + if (auto fileLoc = mlir::dyn_cast(loc)) + line = fileLoc.getLine(); + return line; +} + } // namespace +void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp, + mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scopeAttr, + fir::DebugTypeGenerator &typeGen) { + mlir::MLIRContext *context = &getContext(); + mlir::OpBuilder builder(context); + auto result = fir::NameUniquer::deconstruct(declOp.getUniqName()); + + if (result.first != fir::NameUniquer::NameKind::VARIABLE) + return; + + // Only accept local variables. + if (result.second.procs.empty()) + return; + + // FIXME: There may be cases where an argument is processed a bit before + // DeclareOp is generated. In that case, DeclareOp may point to an + // intermediate op and not to BlockArgument. We need to find those cases and + // walk the chain to get to the actual argument. + + unsigned argNo = 0; + if (auto Arg = llvm::dyn_cast(declOp.getMemref())) + argNo = Arg.getArgNumber() + 1; + + auto tyAttr = typeGen.convertType(fir::unwrapRefType(declOp.getType()), + fileAttr, scopeAttr, declOp.getLoc()); + + auto localVarAttr = mlir::LLVM::DILocalVariableAttr::get( + context, scopeAttr, mlir::StringAttr::get(context, result.second.name), + fileAttr, getLineFromLoc(declOp.getLoc()), argNo, /* alignInBits*/ 0, + tyAttr); + declOp->setLoc(builder.getFusedLoc({declOp->getLoc()}, localVarAttr)); +} + void AddDebugInfoPass::runOnOperation() { mlir::ModuleOp module = getOperation(); mlir::MLIRContext *context = &getContext(); @@ -144,14 +191,15 @@ void AddDebugInfoPass::runOnOperation() { subprogramFlags = subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition; } - unsigned line = 1; - if (auto funcLoc = mlir::dyn_cast(l)) - line = funcLoc.getLine(); - + unsigned line = getLineFromLoc(l); auto spAttr = mlir::LLVM::DISubprogramAttr::get( context, id, compilationUnit, fileAttr, funcName, fullName, funcFileAttr, line, line, subprogramFlags, subTypeAttr); funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr)); + + funcOp.walk([&](fir::cg::XDeclareOp declOp) { + handleDeclareOp(declOp, fileAttr, spAttr, typeGen); + }); }); } diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp index e5b4050dfb24..64c6547e06e0 100644 --- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp @@ -24,11 +24,6 @@ DebugTypeGenerator::DebugTypeGenerator(mlir::ModuleOp m) LLVM_DEBUG(llvm::dbgs() << "DITypeAttr generator\n"); } -static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) { - return mlir::LLVM::DIBasicTypeAttr::get( - context, llvm::dwarf::DW_TAG_base_type, "void", 32, 1); -} - static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context, mlir::StringAttr name, unsigned bitSize, @@ -37,6 +32,11 @@ static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context, context, llvm::dwarf::DW_TAG_base_type, name, bitSize, decoding); } +static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) { + return genBasicType(context, mlir::StringAttr::get(context, "integer"), 32, + llvm::dwarf::DW_ATE_signed); +} + mlir::LLVM::DITypeAttr DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scope, diff --git a/flang/test/Fir/declare-codegen.fir b/flang/test/Fir/declare-codegen.fir index 9d68d3b2f9d4..c5879facb157 100644 --- a/flang/test/Fir/declare-codegen.fir +++ b/flang/test/Fir/declare-codegen.fir @@ -1,5 +1,7 @@ // Test rewrite of fir.declare. The result is replaced by the memref operand. -// RUN: fir-opt --cg-rewrite %s -o - | FileCheck %s +// RUN: fir-opt --cg-rewrite="preserve-declare=true" %s -o - | FileCheck %s --check-prefixes DECL +// RUN: fir-opt --cg-rewrite="preserve-declare=false" %s -o - | FileCheck %s --check-prefixes NODECL +// RUN: fir-opt --cg-rewrite %s -o - | FileCheck %s --check-prefixes NODECL func.func @test(%arg0: !fir.ref>) { @@ -15,9 +17,14 @@ func.func @test(%arg0: !fir.ref>) { func.func private @bar(%arg0: !fir.ref>) -// CHECK-LABEL: func.func @test( -// CHECK-SAME: %[[arg0:.*]]: !fir.ref>) { -// CHECK-NEXT: fir.call @bar(%[[arg0]]) : (!fir.ref>) -> () +// NODECL-LABEL: func.func @test( +// NODECL-SAME: %[[arg0:.*]]: !fir.ref>) { +// NODECL-NEXT: fir.call @bar(%[[arg0]]) : (!fir.ref>) -> () + +// DECL-LABEL: func.func @test( +// DECL-SAME: %[[arg0:.*]]: !fir.ref>) { +// DECL: fircg.ext_declare + func.func @useless_shape_with_duplicate_extent_operand(%arg0: !fir.ref>) { %c3 = arith.constant 3 : index @@ -26,5 +33,8 @@ func.func @useless_shape_with_duplicate_extent_operand(%arg0: !fir.ref) { %scope = fir.dummy_scope : !fir.dscope %0 = fir.declare %arg0 dummy_scope %scope {uniq_name = "x"} : (!fir.ref, !fir.dscope) -> !fir.ref return } -// CHECK-LABEL: func.func @dummy_scope( -// CHECK-NEXT: return +// DECL-LABEL: func.func @dummy_scope( +// DECL: fircg.ext_declare + +// NODECL-LABEL: func.func @dummy_scope( +// NODECL-NEXT: return \ No newline at end of file diff --git a/flang/test/Transforms/debug-local-var-2.f90 b/flang/test/Transforms/debug-local-var-2.f90 new file mode 100644 index 000000000000..15b9b148492e --- /dev/null +++ b/flang/test/Transforms/debug-local-var-2.f90 @@ -0,0 +1,91 @@ +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s + +! This tests checks the debug information for local variables in llvm IR. + +! CHECK-LABEL: define void @_QQmain +! CHECK-DAG: %[[AL11:.*]] = alloca i32 +! CHECK-DAG: %[[AL12:.*]] = alloca i64 +! CHECK-DAG: %[[AL13:.*]] = alloca i8 +! CHECK-DAG: %[[AL14:.*]] = alloca i32 +! CHECK-DAG: %[[AL15:.*]] = alloca float +! CHECK-DAG: %[[AL16:.*]] = alloca double +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL11]], metadata ![[I4:.*]], metadata !DIExpression()) +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL12]], metadata ![[I8:.*]], metadata !DIExpression()) +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL13]], metadata ![[L1:.*]], metadata !DIExpression()) +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL14]], metadata ![[L4:.*]], metadata !DIExpression()) +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL15]], metadata ![[R4:.*]], metadata !DIExpression()) +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL16]], metadata ![[R8:.*]], metadata !DIExpression()) +! CHECK-LABEL: } + +! CHECK-LABEL: define {{.*}}i64 @_QFPfn1 +! CHECK-SAME: (ptr %[[ARG1:.*]], ptr %[[ARG2:.*]], ptr %[[ARG3:.*]]) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[ARG1]], metadata ![[A1:.*]], metadata !DIExpression()) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[ARG2]], metadata ![[B1:.*]], metadata !DIExpression()) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[ARG3]], metadata ![[C1:.*]], metadata !DIExpression()) +! CHECK-DAG: %[[AL2:.*]] = alloca i64 +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[AL2]], metadata ![[RES1:.*]], metadata !DIExpression()) +! CHECK-LABEL: } + +! CHECK-LABEL: define {{.*}}i32 @_QFPfn2 +! CHECK-SAME: (ptr %[[FN2ARG1:.*]], ptr %[[FN2ARG2:.*]], ptr %[[FN2ARG3:.*]]) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[FN2ARG1]], metadata ![[A2:.*]], metadata !DIExpression()) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[FN2ARG2]], metadata ![[B2:.*]], metadata !DIExpression()) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[FN2ARG3]], metadata ![[C2:.*]], metadata !DIExpression()) +! CHECK-DAG: %[[AL3:.*]] = alloca i32 +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[AL3]], metadata ![[RES2:.*]], metadata !DIExpression()) +! CHECK-LABEL: } + +program mn +! CHECK-DAG: ![[MAIN:.*]] = distinct !DISubprogram(name: "_QQmain", {{.*}}) + +! CHECK-DAG: ![[TYI32:.*]] = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed) +! CHECK-DAG: ![[TYI64:.*]] = !DIBasicType(name: "integer", size: 64, encoding: DW_ATE_signed) +! CHECK-DAG: ![[TYL8:.*]] = !DIBasicType(name: "logical", size: 8, encoding: DW_ATE_boolean) +! CHECK-DAG: ![[TYL32:.*]] = !DIBasicType(name: "logical", size: 32, encoding: DW_ATE_boolean) +! CHECK-DAG: ![[TYR32:.*]] = !DIBasicType(name: "real", size: 32, encoding: DW_ATE_float) +! CHECK-DAG: ![[TYR64:.*]] = !DIBasicType(name: "real", size: 64, encoding: DW_ATE_float) + +! CHECK-DAG: ![[I4]] = !DILocalVariable(name: "i4", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYI32]]) +! CHECK-DAG: ![[I8]] = !DILocalVariable(name: "i8", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYI64]]) +! CHECK-DAG: ![[R4]] = !DILocalVariable(name: "r4", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYR32]]) +! CHECK-DAG: ![[R8]] = !DILocalVariable(name: "r8", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYR64]]) +! CHECK-DAG: ![[L1]] = !DILocalVariable(name: "l1", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYL8]]) +! CHECK-DAG: ![[L4]] = !DILocalVariable(name: "l4", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYL32]]) + integer(kind=4) :: i4 + integer(kind=8) :: i8 + real(kind=4) :: r4 + real(kind=8) :: r8 + logical(kind=1) :: l1 + logical(kind=4) :: l4 + + i8 = fn1(i4, r8, l1) + i4 = fn2(i8, r4, l4) +contains +! CHECK-DAG: ![[FN1:.*]] = distinct !DISubprogram(name: "fn1", {{.*}}) +! CHECK-DAG: ![[A1]] = !DILocalVariable(name: "a1", arg: 1, scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI32]]) +! CHECK-DAG: ![[B1]] = !DILocalVariable(name: "b1", arg: 2, scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYR64]]) +! CHECK-DAG: ![[C1]] = !DILocalVariable(name: "c1", arg: 3, scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYL8]]) +! CHECK-DAG: ![[RES1]] = !DILocalVariable(name: "res1", scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI64]]) + function fn1(a1, b1, c1) result (res1) + integer(kind=4), intent(in) :: a1 + real(kind=8), intent(in) :: b1 + logical(kind=1), intent(in) :: c1 + integer(kind=8) :: res1 + + res1 = a1 + b1 + end function + +! CHECK-DAG: ![[FN2:.*]] = distinct !DISubprogram(name: "fn2", {{.*}}) +! CHECK-DAG: ![[A2]] = !DILocalVariable(name: "a2", arg: 1, scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI64]]) +! CHECK-DAG: ![[B2]] = !DILocalVariable(name: "b2", arg: 2, scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYR32]]) +! CHECK-DAG: ![[C2]] = !DILocalVariable(name: "c2", arg: 3, scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYL32]]) +! CHECK-DAG: ![[RES2]] = !DILocalVariable(name: "res2", scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI32]]) + function fn2(a2, b2, c2) result (res2) + integer(kind=8), intent(in) :: a2 + real(kind=4), intent(in) :: b2 + logical(kind=4), intent(in) :: c2 + integer(kind=4) :: res2 + + res2 = a2 + b2 + end function +end program diff --git a/flang/test/Transforms/debug-local-var.f90 b/flang/test/Transforms/debug-local-var.f90 new file mode 100644 index 000000000000..96dc111ad308 --- /dev/null +++ b/flang/test/Transforms/debug-local-var.f90 @@ -0,0 +1,54 @@ +! RUN: %flang_fc1 -emit-fir -debug-info-kind=standalone -mmlir --mlir-print-debuginfo %s -o - | \ +! RUN: fir-opt --cg-rewrite="preserve-declare=true" --mlir-print-debuginfo | fir-opt --add-debug-info --mlir-print-debuginfo | FileCheck %s + +! CHECK-DAG: #[[INT8:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[INT4:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[REAL8:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[LOG1:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[REAL4:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[LOG4:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[MAIN:.*]] = #llvm.di_subprogram<{{.*}}name = "_QQmain"{{.*}}> +! CHECK-DAG: #[[FN1:.*]] = #llvm.di_subprogram<{{.*}}name = "fn1"{{.*}}> +! CHECK-DAG: #[[FN2:.*]] = #llvm.di_subprogram<{{.*}}name = "fn2"{{.*}}> + +program mn +! CHECK-DAG: #[[I4:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[I8:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[R4:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[R8:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[L1:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[L4:.*]] = #llvm.di_local_variable + integer(kind=4) :: i4 + integer(kind=8) :: i8 + real(kind=4) :: r4 + real(kind=8) :: r8 + logical(kind=1) :: l1 + logical(kind=4) :: l4 + i8 = fn1(i4, r8, l1) + i4 = fn2(i8, r4, l4) +contains + function fn1(a1, b1, c1) result (res1) +! CHECK-DAG: #[[A1:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[B1:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[C1:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[RES1:.*]] = #llvm.di_local_variable + integer(kind=4), intent(in) :: a1 + real(kind=8), intent(in) :: b1 + logical(kind=1), intent(in) :: c1 + integer(kind=8) :: res1 + res1 = a1 + b1 + end function + + function fn2(a2, b2, c2) result (res2) + implicit none +! CHECK-DAG: #[[A2:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[B2:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[C2:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[RES2:.*]] = #llvm.di_local_variable + integer(kind=8), intent(in) :: a2 + real(kind=4), intent(in) :: b2 + logical(kind=4), intent(in) :: c2 + integer(kind=4) :: res2 + res2 = a2 + b2 + end function +end program -- GitLab From eda098aadea3e542f95b5f0d4173f00eae42dc72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= Date: Wed, 15 May 2024 16:26:17 +0200 Subject: [PATCH 359/578] [clang][analyzer] Fix a crash in alpha.unix.BlockInCriticalSection (#90030) When analyzing C code with function pointers the checker crashes because of how the implementation extracts `IdentifierInfo`. Without the fix, this test crashes. --- .../Checkers/BlockInCriticalSectionChecker.cpp | 5 ++--- clang/test/Analysis/block-in-critical-section.c | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 clang/test/Analysis/block-in-critical-section.c diff --git a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp index e138debd1361..92347f8fafc0 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp @@ -103,9 +103,8 @@ class RAIIMutexDescriptor { // this function is called instead of early returning it. To avoid this, a // bool variable (IdentifierInfoInitialized) is used and the function will // be run only once. - Guard = &Call.getCalleeAnalysisDeclContext()->getASTContext().Idents.get( - GuardName); - IdentifierInfoInitialized = true; + const auto &ASTCtx = Call.getState()->getStateManager().getContext(); + Guard = &ASTCtx.Idents.get(GuardName); } } diff --git a/clang/test/Analysis/block-in-critical-section.c b/clang/test/Analysis/block-in-critical-section.c new file mode 100644 index 000000000000..1e174af541b1 --- /dev/null +++ b/clang/test/Analysis/block-in-critical-section.c @@ -0,0 +1,6 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.unix.BlockInCriticalSection -verify %s +// expected-no-diagnostics + +// This should not crash +int (*a)(void); +void b(void) { a(); } -- GitLab From da116bd82c0a78d2022c34b56e45cf6e4f91eaed Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 15 May 2024 15:37:51 +0100 Subject: [PATCH 360/578] [Clang] Use ULL for std::max constant argument to fix build failure. getKnownMinValue returns uint64_t, use ULL to make sure the second arg is also 64 bit. --- clang/lib/CodeGen/Targets/Sparc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index b82e9a69e196..13e9550781d1 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -266,7 +266,7 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { // All structs, even empty ones, should take up a register argument slot, // so pin the minimum struct size to one bit. CB.pad(llvm::alignTo( - std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), 1UL), 64)); + std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), 1ULL), 64)); // Try to use the original type for coercion. llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType(); -- GitLab From b42d245b77a83f8f6ca88c2dc441a96a5e8d5b52 Mon Sep 17 00:00:00 2001 From: AdityaK Date: Wed, 15 May 2024 07:44:34 -0700 Subject: [PATCH 361/578] [GVNHoist] Replace combineKnownMetadata with combineMetadataForCSE (#92197) There is no reason to call combineMetadata directly with a list of MD_ nodes. The combineMetadataForCSE function handles all the metadata correctly Partially fixes: #30866 --- llvm/lib/Transforms/Scalar/GVNHoist.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/GVNHoist.cpp b/llvm/lib/Transforms/Scalar/GVNHoist.cpp index 261c1259c9c9..b5333c532280 100644 --- a/llvm/lib/Transforms/Scalar/GVNHoist.cpp +++ b/llvm/lib/Transforms/Scalar/GVNHoist.cpp @@ -238,18 +238,6 @@ public: const VNtoInsns &getStoreVNTable() const { return VNtoCallsStores; } }; -static void combineKnownMetadata(Instruction *ReplInst, Instruction *I) { - static const unsigned KnownIDs[] = {LLVMContext::MD_tbaa, - LLVMContext::MD_alias_scope, - LLVMContext::MD_noalias, - LLVMContext::MD_range, - LLVMContext::MD_fpmath, - LLVMContext::MD_invariant_load, - LLVMContext::MD_invariant_group, - LLVMContext::MD_access_group}; - combineMetadata(ReplInst, I, KnownIDs, true); -} - // This pass hoists common computations across branches sharing common // dominator. The primary goal is to reduce the code size, and in some // cases reduce critical path (by exposing more ILP). @@ -996,8 +984,8 @@ unsigned GVNHoist::rauw(const SmallVecInsn &Candidates, Instruction *Repl, MSSAUpdater->removeMemoryAccess(OldMA); } + combineMetadataForCSE(Repl, I, true); Repl->andIRFlags(I); - combineKnownMetadata(Repl, I); I->replaceAllUsesWith(Repl); // Also invalidate the Alias Analysis cache. MD->removeInstruction(I); -- GitLab From 8a4cbeada930bf11fe740a2038bd5a3230712284 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 15 May 2024 15:48:22 +0100 Subject: [PATCH 362/578] [Clang] Unbreak build take 2 using uint64_t() explicitly. --- clang/lib/CodeGen/Targets/Sparc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index 13e9550781d1..561f0b514d90 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -266,7 +266,8 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { // All structs, even empty ones, should take up a register argument slot, // so pin the minimum struct size to one bit. CB.pad(llvm::alignTo( - std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), 1ULL), 64)); + std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), uint64_t(1)), + 64)); // Try to use the original type for coercion. llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType(); -- GitLab From dceaa0f4491ebe30c0b0f1bc7fa5ec365b60ced6 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Wed, 15 May 2024 10:55:34 -0400 Subject: [PATCH 363/578] [Support] Use malloc instead of non-throwing new (#92157) When allocating a memory buffer, we use a non-throwing new so that we can explicitly handle memory buffers that are too large to fit into memory. However, when exceptions are disabled, LLVM installs a custom new handler (https://github.com/llvm/llvm-project/blob/90109d444839683b09f0aafdc50b749cb4b3203b/llvm/lib/Support/InitLLVM.cpp#L61) that explicitly crashes when we run out of memory (https://github.com/llvm/llvm-project/blob/de14b749fee41d4ded711e771e43043ae3100cb3/llvm/lib/Support/ErrorHandling.cpp#L188) and that means this particular out-of-memory situation cannot be gracefully handled. This was discovered while working on #embed (https://github.com/llvm/llvm-project/pull/68620) on Windows and resulted in a crash rather than the preprocessor issuing a diagnostic as expected. This patch switches away from the non-throwing new to a call to malloc (and free), which will return a null pointer without calling a custom new handler. It is the only instance in Clang or LLVM that I could find which used a non-throwing new, so I did not think we would need anything more involved than this change. Testing this would be highly platform dependent and so it does not come with test coverage. And because it doesn't change behavior that users are likely to be able to observe, it does not come with a release note. --- llvm/lib/Support/MemoryBuffer.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp index 4cc4fe019b75..50308bd2bf4a 100644 --- a/llvm/lib/Support/MemoryBuffer.cpp +++ b/llvm/lib/Support/MemoryBuffer.cpp @@ -98,7 +98,7 @@ public: /// Disable sized deallocation for MemoryBufferMem, because it has /// tail-allocated data. - void operator delete(void *p) { ::operator delete(p); } + void operator delete(void *p) { std::free(p); } StringRef getBufferIdentifier() const override { // The name is stored after the class itself. @@ -315,7 +315,14 @@ WritableMemoryBuffer::getNewUninitMemBuffer(size_t Size, size_t RealLen = StringLen + Size + 1 + BufAlign.value(); if (RealLen <= Size) // Check for rollover. return nullptr; - char *Mem = static_cast(operator new(RealLen, std::nothrow)); + // We use a call to malloc() rather than a call to a non-throwing operator + // new() because LLVM unconditionally installs an out of memory new handler + // when exceptions are disabled. This new handler intentionally crashes to + // aid with debugging, but that makes non-throwing new calls unhelpful. + // See MemoryBufferMem::operator delete() for the paired call to free(), and + // llvm::install_out_of_memory_new_handler() for the installation of the + // custom new handler. + char *Mem = static_cast(std::malloc(RealLen)); if (!Mem) return nullptr; -- GitLab From 8ab753c121447c1388c4cb1af08ab27b2cd62a82 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 15 May 2024 10:10:49 -0500 Subject: [PATCH 364/578] [flang][OpenMP] Add `REQUIRES: asserts` to test that relies on it This should fix failures in release builds. --- flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 | 1 + 1 file changed, 1 insertion(+) diff --git a/flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 b/flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 index 817c5b731c62..53871276761f 100644 --- a/flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 +++ b/flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 @@ -1,4 +1,5 @@ !Remove the --crash below once we can diagnose the issue more gracefully. +!REQUIRES: asserts !RUN: not --crash %flang_fc1 -fopenmp -emit-hlfir -o - %s ! Check that we reject the "task" reduction modifier on the "simd" directive. -- GitLab From 413aaf11cd74f422f05b990613f822dc10db4391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 15 May 2024 13:03:35 +0200 Subject: [PATCH 365/578] [clang][Interp][NFC] Support IntAP(S) in emitPrimCast --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 1da74ac7c8bd..7cdc1c6d1947 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -3685,12 +3685,22 @@ bool ByteCodeExprGen::emitPrimCast(PrimType FromT, PrimType ToT, return this->emitCastFP(ToSem, getRoundingMode(E), E); } + if (ToT == PT_IntAP) + return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(ToQT), E); + if (ToT == PT_IntAPS) + return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(ToQT), E); + // Float to integral. if (isIntegralType(ToT) || ToT == PT_Bool) return this->emitCastFloatingIntegral(ToT, E); } if (isIntegralType(FromT) || FromT == PT_Bool) { + if (ToT == PT_IntAP) + return this->emitCastAP(FromT, Ctx.getBitWidth(ToQT), E); + if (ToT == PT_IntAPS) + return this->emitCastAPS(FromT, Ctx.getBitWidth(ToQT), E); + // Integral to integral. if (isIntegralType(ToT) || ToT == PT_Bool) return FromT != ToT ? this->emitCast(FromT, ToT, E) : true; -- GitLab From 28d5f7907e8c3adb6f0e2e16c9673a99f5e07522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 15 May 2024 15:15:07 +0200 Subject: [PATCH 366/578] [clang][Interp][NFC] Use a smaller default size for IntegralAP Since we later possibly initialize the value by using operator-new, we need the default value to _not_ allocate memory. --- clang/lib/AST/Interp/IntegralAP.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h index fb7ee1451571..7464f15cdb03 100644 --- a/clang/lib/AST/Interp/IntegralAP.h +++ b/clang/lib/AST/Interp/IntegralAP.h @@ -61,7 +61,7 @@ public: IntegralAP(APInt V) : V(V) {} /// Arbitrary value for uninitialized variables. - IntegralAP() : IntegralAP(-1, 1024) {} + IntegralAP() : IntegralAP(-1, 3) {} IntegralAP operator-() const { return IntegralAP(-V); } IntegralAP operator-(const IntegralAP &Other) const { -- GitLab From 4527adc500ea0dc4b942a51dc7209da4ea26d9a2 Mon Sep 17 00:00:00 2001 From: Daniel Kuts Date: Wed, 15 May 2024 18:15:13 +0300 Subject: [PATCH 367/578] Fix null pointer dereference in logging in mlir TransformOps (#92237) A variable `typeConverterOp` may be nullptr after dynamic cast. There is a security guard for this, but during logging error message the variable getting dereferenced. Found with static analysis. --- mlir/lib/Dialect/Transform/IR/TransformOps.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp index eb09f007fbca..247759e21efb 100644 --- a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp +++ b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp @@ -648,13 +648,14 @@ LogicalResult transform::ApplyConversionPatternsOp::verify() { if (!llvm::hasSingleElement(typeConverterRegion.front())) return emitOpError() << "expected exactly one op in default type converter region"; + Operation *maybeTypeConverter = &typeConverterRegion.front().front(); auto typeConverterOp = dyn_cast( - &typeConverterRegion.front().front()); + maybeTypeConverter); if (!typeConverterOp) { InFlightDiagnostic diag = emitOpError() << "expected default converter child op to " "implement TypeConverterBuilderOpInterface"; - diag.attachNote(typeConverterOp->getLoc()) << "op without interface"; + diag.attachNote(maybeTypeConverter->getLoc()) << "op without interface"; return diag; } // Check default type converter type. -- GitLab From b576a6b0452b9bfb634feaa215506d8a1afe857d Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Wed, 15 May 2024 23:15:48 +0800 Subject: [PATCH 368/578] [X86][AMX] Fix a bug after #83628 (#91207) We need to check if `GR64Cand` a valid register before using it. Test is not needed since it's covered in llvm-test-suite. Fixes #90954 --- llvm/lib/Target/X86/X86LowerTileCopy.cpp | 4 +- llvm/test/CodeGen/X86/AMX/amx-tile-basic.ll | 153 ++++++++++++++++++++ 2 files changed, 155 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/X86/X86LowerTileCopy.cpp b/llvm/lib/Target/X86/X86LowerTileCopy.cpp index fd05e16ac1ce..60c024556ff1 100644 --- a/llvm/lib/Target/X86/X86LowerTileCopy.cpp +++ b/llvm/lib/Target/X86/X86LowerTileCopy.cpp @@ -146,7 +146,7 @@ bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) { addFrameReference(BuildMI(MBB, MI, DL, TII->get(Opc)), TileSS) .addReg(SrcReg, getKillRegState(SrcMO.isKill())); MachineOperand &MO = NewMI->getOperand(2); - MO.setReg(GR64Cand); + MO.setReg(GR64Cand ? GR64Cand : X86::RAX); MO.setIsKill(true); // tileloadd (%sp, %idx), %tmm Opc = GET_EGPR_IF_ENABLED(X86::TILELOADD); @@ -157,7 +157,7 @@ bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) { // restore %rax // mov (%sp) %rax addFrameReference( - BuildMI(MBB, MI, DL, TII->get(X86::MOV64rm), GR64Cand), StrideSS); + BuildMI(MBB, MI, DL, TII->get(X86::MOV64rm), X86::RAX), StrideSS); } MI.eraseFromParent(); Changed = true; diff --git a/llvm/test/CodeGen/X86/AMX/amx-tile-basic.ll b/llvm/test/CodeGen/X86/AMX/amx-tile-basic.ll index 4a9f9d3bf77a..7511e5953dac 100644 --- a/llvm/test/CodeGen/X86/AMX/amx-tile-basic.ll +++ b/llvm/test/CodeGen/X86/AMX/amx-tile-basic.ll @@ -51,3 +51,156 @@ declare x86_amx @llvm.x86.tdpbusd.internal(i16, i16, i16, x86_amx, x86_amx, x86_ declare x86_amx @llvm.x86.tdpbuud.internal(i16, i16, i16, x86_amx, x86_amx, x86_amx) declare x86_amx @llvm.x86.tdpbf16ps.internal(i16, i16, i16, x86_amx, x86_amx, x86_amx) declare void @llvm.x86.tilestored64.internal(i16, i16, ptr, i64, x86_amx) + +define void @PR90954(ptr %0, ptr %1, i32 %2) { +; CHECK-LABEL: PR90954: +; CHECK: # %bb.0: +; CHECK-NEXT: pushq %rbp +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset %rbp, -16 +; CHECK-NEXT: movq %rsp, %rbp +; CHECK-NEXT: .cfi_def_cfa_register %rbp +; CHECK-NEXT: pushq %r15 +; CHECK-NEXT: pushq %r14 +; CHECK-NEXT: pushq %r13 +; CHECK-NEXT: pushq %r12 +; CHECK-NEXT: pushq %rbx +; CHECK-NEXT: andq $-1024, %rsp # imm = 0xFC00 +; CHECK-NEXT: subq $5120, %rsp # imm = 0x1400 +; CHECK-NEXT: .cfi_offset %rbx, -56 +; CHECK-NEXT: .cfi_offset %r12, -48 +; CHECK-NEXT: .cfi_offset %r13, -40 +; CHECK-NEXT: .cfi_offset %r14, -32 +; CHECK-NEXT: .cfi_offset %r15, -24 +; CHECK-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; CHECK-NEXT: vmovups %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: movb $1, {{[0-9]+}}(%rsp) +; CHECK-NEXT: movb $16, {{[0-9]+}}(%rsp) +; CHECK-NEXT: movw $64, {{[0-9]+}}(%rsp) +; CHECK-NEXT: movb $16, {{[0-9]+}}(%rsp) +; CHECK-NEXT: movw $64, {{[0-9]+}}(%rsp) +; CHECK-NEXT: movb $16, {{[0-9]+}}(%rsp) +; CHECK-NEXT: movw $64, {{[0-9]+}}(%rsp) +; CHECK-NEXT: ldtilecfg {{[0-9]+}}(%rsp) +; CHECK-NEXT: shll $4, %edx +; CHECK-NEXT: xorl %eax, %eax +; CHECK-NEXT: movw $64, %cx +; CHECK-NEXT: movw $16, %di +; CHECK-NEXT: movb $1, %r8b +; CHECK-NEXT: movl $64, %r9d +; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %r10 +; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %r11 +; CHECK-NEXT: xorl %ebx, %ebx +; CHECK-NEXT: xorl %r14d, %r14d +; CHECK-NEXT: jmp .LBB1_1 +; CHECK-NEXT: .p2align 4, 0x90 +; CHECK-NEXT: .LBB1_5: # in Loop: Header=BB1_1 Depth=1 +; CHECK-NEXT: incq %r14 +; CHECK-NEXT: addl %edx, %ebx +; CHECK-NEXT: .LBB1_1: # =>This Loop Header: Depth=1 +; CHECK-NEXT: # Child Loop BB1_2 Depth 2 +; CHECK-NEXT: movslq %ebx, %r15 +; CHECK-NEXT: leaq (%rsi,%r15,4), %r15 +; CHECK-NEXT: xorl %r12d, %r12d +; CHECK-NEXT: xorl %r13d, %r13d +; CHECK-NEXT: jmp .LBB1_2 +; CHECK-NEXT: .p2align 4, 0x90 +; CHECK-NEXT: .LBB1_4: # in Loop: Header=BB1_2 Depth=2 +; CHECK-NEXT: tilestored %tmm1, (%r15,%rax) +; CHECK-NEXT: incq %r13 +; CHECK-NEXT: addq $64, %r15 +; CHECK-NEXT: decq %r12 +; CHECK-NEXT: je .LBB1_5 +; CHECK-NEXT: .LBB1_2: # Parent Loop BB1_1 Depth=1 +; CHECK-NEXT: # => This Inner Loop Header: Depth=2 +; CHECK-NEXT: tilezero %tmm0 +; CHECK-NEXT: tilezero %tmm1 +; CHECK-NEXT: testb %r8b, %r8b +; CHECK-NEXT: jne .LBB1_4 +; CHECK-NEXT: # %bb.3: # in Loop: Header=BB1_2 Depth=2 +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: tileloadd (%r10,%r9), %tmm1 +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: vmovaps %zmm0, {{[0-9]+}}(%rsp) +; CHECK-NEXT: tileloadd (%r11,%r9), %tmm2 +; CHECK-NEXT: tdpbf16ps %tmm2, %tmm1, %tmm0 +; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; CHECK-NEXT: movabsq $64, %rax +; CHECK-NEXT: tilestored %tmm0, 3072(%rsp,%rax) # 1024-byte Folded Spill +; CHECK-NEXT: tileloadd {{[-0-9]+}}(%r{{[sb]}}p), %tmm1 # 1024-byte Folded Reload +; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; CHECK-NEXT: jmp .LBB1_4 + %4 = shl i32 %2, 4 + %5 = icmp eq i64 0, 0 + br label %6 + +6: ; preds = %31, %3 + %7 = phi i64 [ 0, %3 ], [ %32, %31 ] + %8 = trunc nuw nsw i64 %7 to i32 + %9 = mul i32 %4, %8 + %10 = mul i32 0, %8 + %11 = sext i32 %9 to i64 + %12 = getelementptr inbounds i32, ptr %1, i64 %11 + br label %13 + +13: ; preds = %25, %6 + %14 = phi i64 [ %29, %25 ], [ 0, %6 ] + %15 = tail call x86_amx @llvm.x86.tilezero.internal(i16 16, i16 64) + %16 = tail call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx %15) + %17 = shl nsw i64 %14, 4 + %18 = getelementptr i32, ptr %0, i64 %17 + br i1 %5, label %25, label %19 + +19: ; preds = %13 + %20 = tail call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> %16) + %21 = tail call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> zeroinitializer) + %22 = tail call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> zeroinitializer) + %23 = tail call x86_amx @llvm.x86.tdpbf16ps.internal(i16 16, i16 64, i16 64, x86_amx %20, x86_amx %21, x86_amx %22) + %24 = tail call noundef <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx %23) + br label %25 + +25: ; preds = %19, %13 + %26 = phi <256 x i32> [ undef, %13 ], [ %24, %19 ] + %27 = getelementptr inbounds i32, ptr %12, i64 %17 + %28 = tail call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> %26) + tail call void @llvm.x86.tilestored64.internal(i16 16, i16 64, ptr %27, i64 0, x86_amx %28) + %29 = add nuw nsw i64 %14, 1 + %30 = icmp eq i64 %29, 0 + br i1 %30, label %31, label %13 + +31: ; preds = %25 + %32 = add nuw nsw i64 %7, 1 + br label %6 +} + +declare x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32>) +declare <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx) -- GitLab From bed5546bb53bdb231b62f569b67f449019426ce8 Mon Sep 17 00:00:00 2001 From: Rajveer Singh Bharadwaj Date: Wed, 15 May 2024 20:46:15 +0530 Subject: [PATCH 369/578] [DebugInfo] Get rid of redundant conditional checks in `/DebugInfo` (#92111) Resolves #90326 --- llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h index 3f7f8c7838fd..efc8db12a697 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h @@ -246,20 +246,17 @@ public: virtual void setName(StringRef ObjectName) {} LVElement *getParent() const { - assert((!Parent.Element || - (Parent.Element && static_cast(Parent.Element))) && + assert((!Parent.Element || static_cast(Parent.Element)) && "Invalid element"); return Parent.Element; } LVScope *getParentScope() const { - assert((!Parent.Scope || - (Parent.Scope && static_cast(Parent.Scope))) && + assert((!Parent.Scope || static_cast(Parent.Scope)) && "Invalid scope"); return Parent.Scope; } LVSymbol *getParentSymbol() const { - assert((!Parent.Symbol || - (Parent.Symbol && static_cast(Parent.Symbol))) && + assert((!Parent.Symbol || static_cast(Parent.Symbol)) && "Invalid symbol"); return Parent.Symbol; } -- GitLab From dcf3102be8458fe7588f9d11315beddfca4323b0 Mon Sep 17 00:00:00 2001 From: Elvina Yakubova Date: Wed, 15 May 2024 16:16:39 +0100 Subject: [PATCH 370/578] [BOLT][NFC] Add documentation on BOLT options (#92117) Add .md file documentation with all BOLT options to display it more conveniently. --- bolt/docs/CommandLineArgumentReference.md | 1213 +++++++++++++++++++++ 1 file changed, 1213 insertions(+) create mode 100644 bolt/docs/CommandLineArgumentReference.md diff --git a/bolt/docs/CommandLineArgumentReference.md b/bolt/docs/CommandLineArgumentReference.md new file mode 100644 index 000000000000..1951ad5a2dc5 --- /dev/null +++ b/bolt/docs/CommandLineArgumentReference.md @@ -0,0 +1,1213 @@ +# BOLT - a post-link optimizer developed to speed up large applications + +## SYNOPSIS + +`llvm-bolt [-o outputfile] .bolt [-data=perf.fdata] [options]` + +## OPTIONS + +### Generic options + +- `-h` + + Alias for `--help` + +- `--help` + + Display available options (`--help-hidden` for more). + +- `--help-hidden` + + Display all available options. + +- `--help-list` + + Display list of available options (`--help-list-hidden` for more). + +- `--help-list-hidden` + + Display list of all available options. + +- `--print-all-options` + + Print all option values after command line parsing. + +- `--print-options` + + Print non-default options after command line parsing. + +- `--version` + + Display the version of this program. + +### Output options + +- `-o ` + + output file + +- `-w ` + + Save recorded profile to a file + +### BOLT generic options + +- `--align-text=` + + Alignment of .text section + +- `--allow-stripped` + + Allow processing of stripped binaries + +- `--asm-dump[=]` + + Dump function into assembly + +- `-b` + + Alias for -data + +- `--bolt-id=` + + Add any string to tag this execution in the output binary via bolt info section + +- `--break-funcs=` + + List of functions to core dump on (debugging) + +- `--check-encoding` + + Perform verification of LLVM instruction encoding/decoding. Every instruction + in the input is decoded and re-encoded. If the resulting bytes do not match + the input, a warning message is printed. + +- `--cu-processing-batch-size=` + + Specifies the size of batches for processing CUs. Higher number has better + performance, but more memory usage. Default value is 1. + +- `--data=` + + + +- `--debug-skeleton-cu` + + Prints out offsets for abbrev and debug_info of Skeleton CUs that get patched. + +- `--deterministic-debuginfo` + + Disables parallel execution of tasks that may produce nondeterministic debug info + +- `--dot-tooltip-code` + + Add basic block instructions as tool tips on nodes + +- `--dump-cg=` + + Dump callgraph to the given file + +- `--dump-data` + + Dump parsed bolt data for debugging + +- `--dump-dot-all` + + Dump function CFGs to graphviz format after each stage; enable '-print-loops' + for color-coded blocks + +- `--dump-orc` + + Dump raw ORC unwind information (sorted) + +- `--dwarf-output-path=` + + Path to where .dwo files or dwp file will be written out to. + +- `--dwp=` + + Path and name to DWP file. + +- `--dyno-stats` + + Print execution info based on profile + +- `--dyno-stats-all` + + Print dyno stats after each stage + +- `--dyno-stats-scale=` + + Scale to be applied while reporting dyno stats + +- `--enable-bat` + + Write BOLT Address Translation tables + +- `--force-data-relocations` + + Force relocations to data sections to always be processed + +- `--force-patch` + + Force patching of original entry points + +- `--funcs=` + + Limit optimizations to functions from the list + +- `--funcs-file=` + + File with list of functions to optimize + +- `--funcs-file-no-regex=` + + File with list of functions to optimize (non-regex) + +- `--funcs-no-regex=` + + Limit optimizations to functions from the list (non-regex) + +- `--hot-data` + + Hot data symbols support (relocation mode) + +- `--hot-functions-at-end` + + If reorder-functions is used, order functions putting hottest last + +- `--hot-text` + + Generate hot text symbols. Apply this option to a precompiled binary that + manually calls into hugify, such that at runtime hugify call will put hot + code into 2M pages. This requires relocation. + +- `--hot-text-move-sections=` + + List of sections containing functions used for hugifying hot text. BOLT makes + sure these functions are not placed on the same page as the hot text. + (default='.stub,.mover'). + +- `--insert-retpolines` + + Run retpoline insertion pass + +- `--keep-aranges` + + Keep or generate .debug_aranges section if .gdb_index is written + +- `--keep-tmp` + + Preserve intermediate .o file + +- `--lite` + + Skip processing of cold functions + +- `--max-data-relocations=` + + Maximum number of data relocations to process + +- `--max-funcs=` + + Maximum number of functions to process + +- `--no-huge-pages` + + Use regular size pages for code alignment + +- `--no-threads` + + Disable multithreading + +- `--pad-funcs=` + + List of functions to pad with amount of bytes + +- `--profile-format=` + + Format to dump profile output in aggregation mode, default is fdata + - `=fdata`: offset-based plaintext format + - `=yaml`: dense YAML representation + +- `--r11-availability=` + + Determine the availability of r11 before indirect branches + - `=never`: r11 not available + - `=always`: r11 available before calls and jumps + - `=abi`r11 available before calls but not before jumps + +- `--relocs` + + Use relocations in the binary (default=autodetect) + +- `--remove-symtab` + + Remove .symtab section + +- `--reorder-skip-symbols=` + + List of symbol names that cannot be reordered + +- `--reorder-symbols=` + + List of symbol names that can be reordered + +- `--retpoline-lfence` + + Determine if lfence instruction should exist in the retpoline + +- `--skip-funcs=` + + List of functions to skip + +- `--skip-funcs-file=` + + File with list of functions to skip + +- `--strict` + + Trust the input to be from a well-formed source + +- `--tasks-per-thread=` + + Number of tasks to be created per thread + +- `--thread-count=` + + Number of threads + +- `--top-called-limit=` + + Maximum number of functions to print in top called functions section + +- `--trap-avx512` + + In relocation mode trap upon entry to any function that uses AVX-512 instructions + +- `--trap-old-code` + + Insert traps in old function bodies (relocation mode) + +- `--update-debug-sections` + + Update DWARF debug sections of the executable + +- `--use-gnu-stack` + + Use GNU_STACK program header for new segment (workaround for issues with + strip/objcopy) + +- `--use-old-text` + + Re-use space in old .text if possible (relocation mode) + +- `-v ` + + Set verbosity level for diagnostic output + +- `--write-dwp` + + Output a single dwarf package file (dwp) instead of multiple non-relocatable + dwarf object files (dwo). + +### BOLT optimization options + +- `--align-blocks` + + Align basic blocks + +- `--align-blocks-min-size=` + + Minimal size of the basic block that should be aligned + +- `--align-blocks-threshold=` + + Align only blocks with frequency larger than containing function execution + frequency specified in percent. E.g. 1000 means aligning blocks that are 10 + times more frequently executed than the containing function. + +- `--align-functions=` + + Align functions at a given value (relocation mode) + +- `--align-functions-max-bytes=` + + Maximum number of bytes to use to align functions + +- `--assume-abi` + + Assume the ABI is never violated + +- `--block-alignment=` + + Boundary to use for alignment of basic blocks + +- `--bolt-seed=` + + Seed for randomization + +- `--cg-from-perf-data` + + Use perf data directly when constructing the call graph for stale functions + +- `--cg-ignore-recursive-calls` + + Ignore recursive calls when constructing the call graph + +- `--cg-use-split-hot-size` + + Use hot/cold data on basic blocks to determine hot sizes for call graph functions + +- `--cold-threshold=` + + Tenths of percents of main entry frequency to use as a threshold when + evaluating whether a basic block is cold (0 means it is only considered + cold if the block has zero samples). Default: 0 + +- `--elim-link-veneers` + + Run veneer elimination pass + +- `--eliminate-unreachable` + + Eliminate unreachable code + +- `--equalize-bb-counts` + + Use same count for BBs that should have equivalent count (used in non-LBR + and shrink wrapping) + +- `--execution-count-threshold=` + + Perform profiling accuracy-sensitive optimizations only if function execution + count >= the threshold (default: 0) + +- `--fix-block-counts` + + Adjust block counts based on outgoing branch counts + +- `--fix-func-counts` + + Adjust function counts based on basic blocks execution count + +- `--force-inline=` + + List of functions to always consider for inlining + +- `--frame-opt=` + + Optimize stack frame accesses + - `none`: do not perform frame optimization + - `hot`: perform FOP on hot functions + - `all`: perform FOP on all functions + +- `--frame-opt-rm-stores` + + Apply additional analysis to remove stores (experimental) + +- `--function-order=` + + File containing an ordered list of functions to use for function reordering + +- `--generate-function-order=` + + File to dump the ordered list of functions to use for function reordering + +- `--generate-link-sections=` + + Generate a list of function sections in a format suitable for inclusion in a + linker script + +- `--group-stubs` + + Share stubs across functions + +- `--hugify` + + Automatically put hot code on 2MB page(s) (hugify) at runtime. No manual call + to hugify is needed in the binary (which is what --hot-text relies on). + +- `--icf` + + Fold functions with identical code + +- `--icp` + + Alias for --indirect-call-promotion + +- `--icp-calls-remaining-percent-threshold=` + + The percentage threshold against remaining unpromoted indirect call count + for the promotion for calls + +- `--icp-calls-topn` + + Alias for --indirect-call-promotion-calls-topn + +- `--icp-calls-total-percent-threshold=` + + The percentage threshold against total count for the promotion for calls + +- `--icp-eliminate-loads` + + Enable load elimination using memory profiling data when performing ICP + +- `--icp-funcs=` + + List of functions to enable ICP for + +- `--icp-inline` + + Only promote call targets eligible for inlining + +- `--icp-jt-remaining-percent-threshold=` + + The percentage threshold against remaining unpromoted indirect call count for + the promotion for jump tables + +- `--icp-jt-targets` + + Alias for --icp-jump-tables-targets + +- `--icp-jt-topn` + + Alias for --indirect-call-promotion-jump-tables-topn + +- `--icp-jt-total-percent-threshold=` + + The percentage threshold against total count for the promotion for jump tables + +- `--icp-jump-tables-targets` + + For jump tables, optimize indirect jmp targets instead of indices + +- `--icp-mp-threshold` + + Alias for --indirect-call-promotion-mispredict-threshold + +- `--icp-old-code-sequence` + + Use old code sequence for promoted calls + +- `--icp-top-callsites=` + + Optimize hottest calls until at least this percentage of all indirect calls + frequency is covered. 0 = all callsites + +- `--icp-topn` + + Alias for --indirect-call-promotion-topn + +- `--icp-use-mp` + + Alias for --indirect-call-promotion-use-mispredicts + +- `--indirect-call-promotion=` + + Indirect call promotion + - `none`: do not perform indirect call promotion + - `calls`: perform ICP on indirect calls + - `jump-tables`: perform ICP on jump tables + - `all`: perform ICP on calls and jump tables + +- `--indirect-call-promotion-calls-topn=` + + Limit number of targets to consider when doing indirect call promotion on + calls. 0 = no limit + +- `--indirect-call-promotion-jump-tables-topn=` + + Limit number of targets to consider when doing indirect call promotion on + jump tables. 0 = no limit + +- `--indirect-call-promotion-mispredict-threshold=` + + Misprediction threshold for skipping ICP on an indirect call + +- `--indirect-call-promotion-topn=` + + Limit number of targets to consider when doing indirect call promotion. + 0 = no limit + +- `--indirect-call-promotion-use-mispredicts` + + Use misprediction frequency for determining whether or not ICP should be + applied at a callsite. The `-indirect-call-promotion-mispredict-threshold` + value will be used by this heuristic + +- `--infer-fall-throughs` + + Infer execution count for fall-through blocks + +- `--infer-stale-profile` + + Infer counts from stale profile data. + +- `--inline-all` + + Inline all functions + +- `--inline-ap` + + Adjust function profile after inlining + +- `--inline-limit=` + + Maximum number of call sites to inline + +- `--inline-max-iters=` + + Maximum number of inline iterations + +- `--inline-memcpy` + + Inline memcpy using 'rep movsb' instruction (X86-only) + +- `--inline-small-functions` + + Inline functions if increase in size is less than defined by `-inline-small-functions-bytes` + +- `--inline-small-functions-bytes=` + + Max number of bytes for the function to be considered small for inlining purposes + +- `--instrument` + + Instrument code to generate accurate profile data + +- `--iterative-guess` + + In non-LBR mode, guess edge counts using iterative technique + +- `--jt-footprint-optimize-for-icache` + + With jt-footprint-reduction, only process PIC jumptables and turn off other + transformations that increase code size + +- `--jt-footprint-reduction` + + Make jump tables size smaller at the cost of using more instructions at jump + sites + +- `-jump-tables=` + + Jump tables support (default=basic) + - `none`: do not optimize functions with jump tables + - `basic`: optimize functions with jump tables + - `move`: move jump tables to a separate section + - `split`: split jump tables section into hot and cold based on function + execution frequency + - `aggressive`: aggressively split jump tables section based on usage of the + tables + +- `--keep-nops` + + Keep no-op instructions. By default they are removed. + +- `--lite-threshold-count=` + + Similar to '-lite-threshold-pct' but specify threshold using absolute function + call count. I.e. limit processing to functions executed at least the specified + number of times. + +- `--lite-threshold-pct=` + + Threshold (in percent) for selecting functions to process in lite mode. Higher + threshold means fewer functions to process. E.g threshold of 90 means only top + 10 percent of functions with profile will be processed. + +- `--mcf-use-rarcs` + + In MCF, consider the possibility of cancelling flow to balance edges + +- `--memcpy1-spec=` + + List of functions with call sites for which to specialize memcpy() for size 1 + +- `--min-branch-clusters` + + Use a modified clustering algorithm geared towards minimizing branches + +- `--no-inline` + + Disable all inlining (overrides other inlining options) + +- `--no-scan` + + Do not scan cold functions for external references (may result in slower binary) + +- `--peepholes=` + + Enable peephole optimizations + - `none`: disable peepholes + - `double-jumps`: remove double jumps when able + - `tailcall-traps`: insert tail call traps + - `useless-branches`: remove useless conditional branches + - `all`: enable all peephole optimizations + +- `--plt=` + + Optimize PLT calls (requires linking with -znow) + - `none`: do not optimize PLT calls + - `hot`: optimize executed (hot) PLT calls + - `all`: optimize all PLT calls + +- `--preserve-blocks-alignment` + + Try to preserve basic block alignment + +- `--profile-ignore-hash` + + Ignore hash while reading function profile + +- `--profile-use-dfs` + + Use DFS order for YAML profile + +- `--reg-reassign` + + Reassign registers so as to avoid using REX prefixes in hot code + +- `--reorder-blocks=` + + Change layout of basic blocks in a function + - `none`: do not reorder basic blocks + - `reverse`: layout blocks in reverse order + - `normal`: perform optimal layout based on profile + - `branch-predictor`: perform optimal layout prioritizing branch predictions + - `cache`: perform optimal layout prioritizing I-cache behavior + - `cache+`: perform layout optimizing I-cache behavior + - `ext-tsp`: perform layout optimizing I-cache behavior + - `cluster-shuffle`: perform random layout of clusters + +- `--reorder-data=` + + List of sections to reorder + +- `--reorder-data-algo=` + + Algorithm used to reorder data sections + - `count`: sort hot data by read counts + - `funcs`: sort hot data by hot function usage and count + +- `--reorder-data-inplace` + + Reorder data sections in place + +- `--reorder-data-max-bytes=` + + Maximum number of bytes to reorder + +- `--reorder-data-max-symbols=` + + Maximum number of symbols to reorder + +- `--reorder-functions=` + + Reorder and cluster functions (works only with relocations) + - `none`: do not reorder functions + - `exec-count`: order by execution count + - `hfsort`: use hfsort algorithm + - `hfsort+`: use hfsort+ algorithm + - `cdsort`: use cache-directed sort + - `pettis-hansen`: use Pettis-Hansen algorithm + - `random`: reorder functions randomly + - `user`: use function order specified by -function-order + +- `--reorder-functions-use-hot-size` + + Use a function's hot size when doing clustering + +- `--report-bad-layout=` + + Print top functions with suboptimal code layout on input + +- `--report-stale` + + Print the list of functions with stale profile + +- `--runtime-hugify-lib=` + + Specify file name of the runtime hugify library + +- `--runtime-instrumentation-lib=` + + Specify file name of the runtime instrumentation library + +- `--sctc-mode=` + + Mode for simplify conditional tail calls + - `always`: always perform sctc + - `preserve`: only perform sctc when branch direction is preserved + - `heuristic`: use branch prediction data to control sctc + +- `--sequential-disassembly` + + Performs disassembly sequentially + +- `--shrink-wrapping-threshold=` + + Percentage of prologue execution count to use as threshold when evaluating + whether a block is cold enough to be profitable to move eligible spills there + +- `--simplify-conditional-tail-calls` + + Simplify conditional tail calls by removing unnecessary jumps + +- `--simplify-rodata-loads` + + Simplify loads from read-only sections by replacing the memory operand with + the constant found in the corresponding section + +- `--split-align-threshold=` + + When deciding to split a function, apply this alignment while doing the size + comparison (see -split-threshold). Default value: 2. + +- `--split-all-cold` + + Outline as many cold basic blocks as possible + +- `--split-eh` + + Split C++ exception handling code + +- `--split-functions` + + Split functions into fragments + +- `--split-strategy=` + + Strategy used to partition blocks into fragments + + - `profile2`: split each function into a hot and cold fragment using + profiling information + - `cdsplit`: split each function into a hot, warm, and cold fragment using + profiling information + - `random2`: split each function into a hot and cold fragment at a randomly + chosen split point (ignoring any available profiling information) + - `randomN`: split each function into N fragments at randomly chosen split + points (ignoring any available profiling information) + - `all`: split all basic blocks of each function into fragments such that + each fragment contains exactly a single basic block + +- `--split-threshold=` + + Split function only if its main size is reduced by more than given amount of + bytes. Default value: 0, i.e. split iff the size is reduced. Note that on + some architectures the size can increase after splitting. + +- `--stale-matching-max-func-size=` + + The maximum size of a function to consider for inference. + +- `--stale-threshold=` + + Maximum percentage of stale functions to tolerate (default: 100) + +- `--stoke` + + Turn on the stoke analysis + +- `--strip-rep-ret` + + Strip 'repz' prefix from 'repz retq' sequence (on by default) + +- `--tail-duplication=` + + Duplicate unconditional branches that cross a cache line + + - `none` do not apply + - `aggressive` aggressive strategy + - `moderate` moderate strategy + - `cache` cache-aware duplication strategy + +- `--tsp-threshold=` + + Maximum number of hot basic blocks in a function for which to use a precise TSP solution while re-ordering basic blocks + +- `--use-aggr-reg-reassign` + + Use register liveness analysis to try to find more opportunities for -reg-reassign optimization + +- `--use-compact-aligner` + + Use compact approach for aligning functions + +- `--use-edge-counts` + + Use edge count data when doing clustering + +- `--verify-cfg` + + Verify the CFG after every pass + +- `--x86-align-branch-boundary-hot-only` + + Only apply branch boundary alignment in hot code + +- `--x86-strip-redundant-address-size` + + Remove redundant Address-Size override prefix + +### BOLT options in relocation mode + +- `-align-macro-fusion=` + + Fix instruction alignment for macro-fusion (x86 relocation mode) + + - `none`: do not insert alignment no-ops for macro-fusion + - `hot`: only insert alignment no-ops on hot execution paths (default) + - `all`: always align instructions to allow macro-fusion + +### BOLT instrumentation options + +`llvm-bolt -instrument [-o outputfile] ` + +- `--conservative-instrumentation` + + Disable instrumentation optimizations that sacrifice profile accuracy (for + debugging, default: false) + +- `--instrument-calls` + + Record profile for inter-function control flow activity (default: true) + +- `--instrument-hot-only` + + Only insert instrumentation on hot functions (needs profile, default: false) + +- `--instrumentation-binpath=` + + Path to instrumented binary in case if /proc/self/map_files is not accessible + due to access restriction issues + +- `--instrumentation-file=` + + File name where instrumented profile will be saved (default: /tmp/prof.fdata) + +- `--instrumentation-file-append-pid` + + Append PID to saved profile file name (default: false) + +- `--instrumentation-no-counters-clear` + + Don't clear counters across dumps (use with `instrumentation-sleep-time` option) + +- `--instrumentation-sleep-time=` + + Interval between profile writes (default: 0 = write only at program end). + This is useful for service workloads when you want to dump profile every X + minutes or if you are killing the program and the profile is not being + dumped at the end. + +- `--instrumentation-wait-forks` + + Wait until all forks of instrumented process will finish (use with + `instrumentation-sleep-time` option) + +### Data aggregation options (perf2bolt) + +`perf2bolt -p perf.data [-o outputfile] perf.fdata ` + +- `--autofdo` + + Generate autofdo textual data instead of bolt data + +- `--filter-mem-profile` + + If processing a memory profile, filter out stack or heap accesses that won't + be useful for BOLT to reduce profile file size + +- `--ignore-build-id` + + Continue even if build-ids in input binary and perf.data mismatch + +- `--ignore-interrupt-lbr` + + Ignore kernel interrupt LBR that happens asynchronously + +- `--itrace=` + + Generate LBR info with perf itrace argument + +- `--nl` + + Aggregate basic samples (without LBR info) + +- `--pa` + + Skip perf and read data from a pre-aggregated file format + +- `--perfdata=` + + Data file + +- `--pid=` + + Only use samples from process with specified PID + +- `--time-aggr` + + Time BOLT aggregator + +- `--use-event-pc` + + Use event PC in combination with LBR sampling + +### BOLT printing options + +#### Generic options + +- `--print-aliases` + + Print aliases when printing objects + +- `--print-all` + + Print functions after each stage + +- `--print-cfg` + + Print functions after CFG construction + +- `--print-debug-info` + + Print debug info when printing functions + +- `--print-disasm` + + Print function after disassembly + +- `--print-dyno-opcode-stats=` + + Print per instruction opcode dyno stats and the functionnames:BB offsets of + the nth highest execution counts + +- `--print-dyno-stats-only` + + While printing functions output dyno-stats and skip instructions + +- `--print-exceptions` + + Print exception handling data + +- `--print-globals` + + Print global symbols after disassembly + +- `--print-jump-tables` + + Print jump tables + +- `--print-loops` + + Print loop related information + +- `--print-mem-data` + + Print memory data annotations when printing functions + +- `--print-normalized` + + Print functions after CFG is normalized + +- `--print-only=` + + List of functions to print + +- `--print-orc` + + Print ORC unwind information for instructions + +- `--print-profile` + + Print functions after attaching profile + +- `--print-profile-stats` + + Print profile quality/bias analysis + +- `--print-pseudo-probes=` + + Print pseudo probe info + - `=decode`: decode probes section from binary + - `=address_conversion`: update address2ProbesMap with output block address + - `=encoded_probes`: display the encoded probes in binary section + - `=all`: enable all debugging printout + +- `--print-relocations` + + Print relocations when printing functions/objects + +- `--print-reordered-data` + + Print section contents after reordering + +- `--print-retpoline-insertion` + + Print functions after retpoline insertion pass + +- `--print-sdt` + + Print all SDT markers + +- `--print-sections` + + Print all registered sections + +- `--print-unknown` + + Print names of functions with unknown control flow + +- `--time-opts` + + Print time spent in each optimization + +#### Optimization options + +- `--print-after-branch-fixup` + + Print function after fixing local branches + +- `--print-after-jt-footprint-reduction` + + Print function after jt-footprint-reduction pass + +- `--print-after-lowering` + + Print function after instruction lowering + +- `--print-cache-metrics` + + Calculate and print various metrics for instruction cache + +- `--print-clusters` + + Print clusters + +- `--print-finalized` + + Print function after CFG is finalized + +- `--print-fix-relaxations` + + Print functions after fix relaxations pass + +- `--print-fix-riscv-calls` + + Print functions after fix RISCV calls pass + +- `--print-fop` + + Print functions after frame optimizer pass + +- `--print-function-statistics=` + + Print statistics about basic block ordering + +- `--print-icf` + + Print functions after ICF optimization + +- `--print-icp` + + Print functions after indirect call promotion + +- `--print-inline` + + Print functions after inlining optimization + +- `--print-longjmp` + + Print functions after longjmp pass + +- `--print-optimize-bodyless` + + Print functions after bodyless optimization + +- `--print-output-address-range` + + Print output address range for each basic block in the function + whenBinaryFunction::print is called + +- `--print-peepholes` + + Print functions after peephole optimization + +- `--print-plt` + + Print functions after PLT optimization + +- `--print-regreassign` + + Print functions after regreassign pass + +- `--print-reordered` + + Print functions after layout optimization + +- `--print-reordered-functions` + + Print functions after clustering + +- `--print-sctc` + + Print functions after conditional tail call simplification + +- `--print-simplify-rodata-loads` + + Print functions after simplification of RO data loads + +- `--print-sorted-by=` + + Print functions sorted by order of dyno stats + - `executed-forward-branches`: executed forward branches + - `taken-forward-branches`: taken forward branches + - `executed-backward-branches`: executed backward branches + - `taken-backward-branches`: taken backward branches + - `executed-unconditional-branches`: executed unconditional branches + - `all-function-calls`: all function calls + - `indirect-calls`: indirect calls + - `PLT-calls`: PLT calls + - `executed-instructions`: executed instructions + - `executed-load-instructions`: executed load instructions + - `executed-store-instructions`: executed store instructions + - `taken-jump-table-branches`: taken jump table branches + - `taken-unknown-indirect-branches`: taken unknown indirect branches + - `total-branches`: total branches + - `taken-branches`: taken branches + - `non-taken-conditional-branches`: non-taken conditional branches + - `taken-conditional-branches`: taken conditional branches + - `all-conditional-branches`: all conditional branches + - `linker-inserted-veneer-calls`: linker-inserted veneer calls + - `all`: sorted by all names + +- `--print-sorted-by-order=` + + Use ascending or descending order when printing functions ordered by dyno stats + +- `--print-split` + + Print functions after code splitting + +- `--print-stoke` + + Print functions after stoke analysis + +- `--print-uce` + + Print functions after unreachable code elimination + +- `--print-veneer-elimination` + + Print functions after veneer elimination pass + +- `--time-build` + + Print time spent constructing binary functions + +- `--time-rewrite` + + Print time spent in rewriting passes -- GitLab From 8e00703be9ceb41d9b80c2bc8f024a9610b9aaa1 Mon Sep 17 00:00:00 2001 From: jyu2-git Date: Wed, 15 May 2024 08:20:25 -0700 Subject: [PATCH 371/578] [Clang][OpenMP] Fix runtime problem when explicit map both pointer and pointee (#92210) ponter int *p for following map, test currently crash. map(p, p[:100]) or map(p, p[1]) Currly IR looks like // &p, &p, sizeof(int), TARGET_PARAM | TO | FROM // &p, p[0], 100sizeof(float) TO | FROM Worrking IR is // map(p, p[0:100]) to map(p[0:100]) // &p, &p[0], 100*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ The change is add new argument AreBothBasePtrAndPteeMapped in generateInfoForComponentList Use that to skip map for map(p), when processing map(p[:100]) generate map with right flag. --- clang/lib/CodeGen/CGOpenMPRuntime.cpp | 37 +++-- ...arget_map_both_pointer_pointee_codegen.cpp | 150 ++++++++++++++++++ .../test/mapping/map_both_pointer_pointee.c | 42 +++++ 3 files changed, 220 insertions(+), 9 deletions(-) create mode 100644 clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp create mode 100644 offload/test/mapping/map_both_pointer_pointee.c diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index e39c7c58d278..f56af318ff6a 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -6830,7 +6830,8 @@ private: const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false, const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr, ArrayRef - OverlappedElements = std::nullopt) const { + OverlappedElements = std::nullopt, + bool AreBothBasePtrAndPteeMapped = false) const { // The following summarizes what has to be generated for each map and the // types below. The generated information is expressed in this order: // base pointer, section pointer, size, flags @@ -7006,6 +7007,10 @@ private: // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO // (*) the struct this entry pertains to is the 4th element in the list // of arguments, hence MEMBER_OF(4) + // + // map(p, p[:100]) + // ===> map(p[:100]) + // &p, &p[0], 100*sizeof(float), TARGET_PARAM | PTR_AND_OBJ | TO | FROM // Track if the map information being generated is the first for a capture. bool IsCaptureFirstInfo = IsFirstComponentList; @@ -7029,6 +7034,8 @@ private: const auto *OASE = dyn_cast(AssocExpr); const auto *OAShE = dyn_cast(AssocExpr); + if (AreBothBasePtrAndPteeMapped && std::next(I) == CE) + return; if (isa(AssocExpr)) { // The base is the 'this' pointer. The content of the pointer is going // to be the base of the field being mapped. @@ -7071,8 +7078,9 @@ private: // can be associated with the combined storage if shared memory mode is // active or the base declaration is not global variable. const auto *VD = dyn_cast(I->getAssociatedDeclaration()); - if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || - !VD || VD->hasLocalStorage()) + if (!AreBothBasePtrAndPteeMapped && + (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || + !VD || VD->hasLocalStorage())) BP = CGF.EmitLoadOfPointer(BP, Ty->castAs()); else FirstPointerInComplexData = true; @@ -7394,11 +7402,13 @@ private: // same expression except for the first one. We also need to signal // this map is the first one that relates with the current capture // (there is a set of entries for each capture). - OpenMPOffloadMappingFlags Flags = getMapTypeBits( - MapType, MapModifiers, MotionModifiers, IsImplicit, - !IsExpressionFirstInfo || RequiresReference || - FirstPointerInComplexData || IsMemberReference, - IsCaptureFirstInfo && !RequiresReference, IsNonContiguous); + OpenMPOffloadMappingFlags Flags = + getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit, + !IsExpressionFirstInfo || RequiresReference || + FirstPointerInComplexData || IsMemberReference, + AreBothBasePtrAndPteeMapped || + (IsCaptureFirstInfo && !RequiresReference), + IsNonContiguous); if (!IsExpressionFirstInfo || IsMemberReference) { // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, @@ -8492,6 +8502,8 @@ public: assert(CurDir.is() && "Expect a executable directive"); const auto *CurExecDir = CurDir.get(); + bool HasMapBasePtr = false; + bool HasMapArraySec = false; for (const auto *C : CurExecDir->getClausesOfKind()) { const auto *EI = C->getVarRefs().begin(); for (const auto L : C->decl_component_lists(VD)) { @@ -8503,6 +8515,11 @@ public: assert(VDecl == VD && "We got information for the wrong declaration??"); assert(!Components.empty() && "Not expecting declaration with no component lists."); + if (VD && E && VD->getType()->isAnyPointerType() && isa(E)) + HasMapBasePtr = true; + if (VD && E && VD->getType()->isAnyPointerType() && + (isa(E) || isa(E))) + HasMapArraySec = true; DeclComponentLists.emplace_back(Components, C->getMapType(), C->getMapTypeModifiers(), C->isImplicit(), Mapper, E); @@ -8685,7 +8702,9 @@ public: MapType, MapModifiers, std::nullopt, Components, CombinedInfo, StructBaseCombinedInfo, PartialStruct, IsFirstComponentList, IsImplicit, /*GenerateAllInfoForClauses*/ false, Mapper, - /*ForDeviceAddr=*/false, VD, VarRef); + /*ForDeviceAddr=*/false, VD, VarRef, + /*OverlappedElements*/ std::nullopt, + HasMapBasePtr && HasMapArraySec); IsFirstComponentList = false; } } diff --git a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp new file mode 100644 index 000000000000..e2c27f37f5b9 --- /dev/null +++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp @@ -0,0 +1,150 @@ +// 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 _ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s + +// expected-no-diagnostics +#ifndef HEADER +#define HEADER + +extern void *malloc (int __size) throw () __attribute__ ((__malloc__)); + +void foo() { + int *ptr = (int *) malloc(3 * sizeof(int)); + + #pragma omp target map(ptr, ptr[0:2]) + { + ptr[1] = 6; + } + #pragma omp target map(ptr, ptr[2]) + { + ptr[2] = 8; + } +} +#endif +// CHECK-LABEL: define {{[^@]+}}@_Z3foov +// CHECK-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[PTR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [1 x ptr], align 8 +// CHECK-NEXT: [[DOTOFFLOAD_PTRS:%.*]] = alloca [1 x ptr], align 8 +// CHECK-NEXT: [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [1 x ptr], align 8 +// CHECK-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 +// CHECK-NEXT: [[DOTOFFLOAD_BASEPTRS2:%.*]] = alloca [1 x ptr], align 8 +// CHECK-NEXT: [[DOTOFFLOAD_PTRS3:%.*]] = alloca [1 x ptr], align 8 +// CHECK-NEXT: [[DOTOFFLOAD_MAPPERS4:%.*]] = alloca [1 x ptr], align 8 +// CHECK-NEXT: [[KERNEL_ARGS5:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 +// CHECK-NEXT: [[CALL:%.*]] = call noalias noundef ptr @_Z6malloci(i32 noundef signext 12) #[[ATTR3:[0-9]+]] +// CHECK-NEXT: store ptr [[CALL]], ptr [[PTR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[PTR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 0 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[PTR]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0 +// CHECK-NEXT: store ptr null, ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 +// CHECK-NEXT: store i32 3, ptr [[TMP7]], align 4 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 +// CHECK-NEXT: store i32 1, ptr [[TMP8]], align 4 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP5]], ptr [[TMP9]], align 8 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3 +// CHECK-NEXT: store ptr [[TMP6]], ptr [[TMP10]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4 +// CHECK-NEXT: store ptr @.offload_sizes, ptr [[TMP11]], align 8 +// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5 +// CHECK-NEXT: store ptr @.offload_maptypes, ptr [[TMP12]], align 8 +// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6 +// CHECK-NEXT: store ptr null, ptr [[TMP13]], align 8 +// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7 +// CHECK-NEXT: store ptr null, ptr [[TMP14]], align 8 +// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8 +// CHECK-NEXT: store i64 0, ptr [[TMP15]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9 +// CHECK-NEXT: store i64 0, ptr [[TMP16]], align 8 +// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10 +// CHECK-NEXT: store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP17]], align 4 +// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11 +// CHECK-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP18]], align 4 +// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12 +// CHECK-NEXT: store i32 0, ptr [[TMP19]], align 4 +// CHECK-NEXT: [[TMP20:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l15.region_id, ptr [[KERNEL_ARGS]]) +// CHECK-NEXT: [[TMP21:%.*]] = icmp ne i32 [[TMP20]], 0 +// CHECK-NEXT: br i1 [[TMP21]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]] +// CHECK: omp_offload.failed: +// CHECK-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l15(ptr [[TMP0]]) #[[ATTR3]] +// CHECK-NEXT: br label [[OMP_OFFLOAD_CONT]] +// CHECK: omp_offload.cont: +// CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[PTR]], align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load ptr, ptr [[PTR]], align 8 +// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP23]], i64 2 +// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[PTR]], ptr [[TMP24]], align 8 +// CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 +// CHECK-NEXT: store ptr [[ARRAYIDX1]], ptr [[TMP25]], align 8 +// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS4]], i64 0, i64 0 +// CHECK-NEXT: store ptr null, ptr [[TMP26]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0 +// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 +// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 +// CHECK-NEXT: store i32 3, ptr [[TMP29]], align 4 +// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 +// CHECK-NEXT: store i32 1, ptr [[TMP30]], align 4 +// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 +// CHECK-NEXT: store ptr [[TMP27]], ptr [[TMP31]], align 8 +// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 3 +// CHECK-NEXT: store ptr [[TMP28]], ptr [[TMP32]], align 8 +// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 4 +// CHECK-NEXT: store ptr @.offload_sizes.1, ptr [[TMP33]], align 8 +// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 5 +// CHECK-NEXT: store ptr @.offload_maptypes.2, ptr [[TMP34]], align 8 +// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 6 +// CHECK-NEXT: store ptr null, ptr [[TMP35]], align 8 +// CHECK-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 7 +// CHECK-NEXT: store ptr null, ptr [[TMP36]], align 8 +// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 8 +// CHECK-NEXT: store i64 0, ptr [[TMP37]], align 8 +// CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 9 +// CHECK-NEXT: store i64 0, ptr [[TMP38]], align 8 +// CHECK-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 10 +// CHECK-NEXT: store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP39]], align 4 +// CHECK-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 11 +// CHECK-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP40]], align 4 +// CHECK-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 12 +// CHECK-NEXT: store i32 0, ptr [[TMP41]], align 4 +// CHECK-NEXT: [[TMP42:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l19.region_id, ptr [[KERNEL_ARGS5]]) +// CHECK-NEXT: [[TMP43:%.*]] = icmp ne i32 [[TMP42]], 0 +// CHECK-NEXT: br i1 [[TMP43]], label [[OMP_OFFLOAD_FAILED6:%.*]], label [[OMP_OFFLOAD_CONT7:%.*]] +// CHECK: omp_offload.failed6: +// CHECK-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l19(ptr [[TMP22]]) #[[ATTR3]] +// CHECK-NEXT: br label [[OMP_OFFLOAD_CONT7]] +// CHECK: omp_offload.cont7: +// CHECK-NEXT: ret void +// +// +// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l15 +// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR2:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[PTR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1 +// CHECK-NEXT: store i32 6, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret void +// +// +// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l19 +// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR2]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[PTR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2 +// CHECK-NEXT: store i32 8, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret void +// diff --git a/offload/test/mapping/map_both_pointer_pointee.c b/offload/test/mapping/map_both_pointer_pointee.c new file mode 100644 index 000000000000..4b724823e7a4 --- /dev/null +++ b/offload/test/mapping/map_both_pointer_pointee.c @@ -0,0 +1,42 @@ +// RUN: %libomptarget-compilexx-run-and-check-aarch64-unknown-linux-gnu +// RUN: %libomptarget-compilexx-run-and-check-powerpc64-ibm-linux-gnu +// RUN: %libomptarget-compilexx-run-and-check-powerpc64le-ibm-linux-gnu +// RUN: %libomptarget-compilexx-run-and-check-x86_64-pc-linux-gnu +// RUN: %libomptarget-compilexx-run-and-check-nvptx64-nvidia-cuda + +// REQUIRES: unified_shared_memory +// UNSUPPORTED: amdgcn-amd-amdhsa + +#pragma omp declare target +int *ptr1; +#pragma omp end declare target + +#include +#include +int main() { + ptr1 = (int *)malloc(sizeof(int) * 100); + int *ptr2; + ptr2 = (int *)malloc(sizeof(int) * 100); +#pragma omp target map(ptr1, ptr1[ : 100]) + { ptr1[1] = 6; } + // CHECK: 6 + printf(" %d \n", ptr1[1]); +#pragma omp target data map(ptr1[ : 5]) + { +#pragma omp target map(ptr1[2], ptr1, ptr1[3]) map(ptr2, ptr2[2]) + { + ptr1[2] = 7; + ptr1[3] = 9; + ptr2[2] = 7; + } + } + // CHECK: 7 7 9 + printf(" %d %d %d \n", ptr2[2], ptr1[2], ptr1[3]); + free(ptr1); +#pragma omp target map(ptr2, ptr2[ : 100]) + { ptr2[1] = 6; } + // CHECK: 6 + printf(" %d \n", ptr2[1]); + free(ptr2); + return 0; +} -- GitLab From ff313ee70a4f27e3555ee4baef53b9b51c5aa27e Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Wed, 15 May 2024 23:37:31 +0800 Subject: [PATCH 372/578] [RISCV] Remove hasSideEffects=1 for vsetvli pseudos (#91319) In a similar vein to #90049, we currently model all of the effects of a vsetvli pseudo: * VL and VTYPE are marked as defs * VL preserving x0,x0 vsetvlis doesn't get emitted until RISCVInsertVSETVLI, and when they are they have implicit uses on VL * Regular vector pseudos are fully modelled too: Before RISCVInsertVSETVLI they can be moved between vsetvli pseudos because we will eventually insert vsetvlis to correct VL and VTYPE. Afterwards, they will have implicit uses on VL and VTYPE. Since we model everything we can remove hasSideEffects=1. This gives us some improvements like sinking in vsetvli-insert-crossbb.ll. We need to update RISCVDeadRegisterDefinitions to keep handling vsetvli pseudos since it only operates on instructions with unmodelled side effects. --- .../RISCV/RISCVDeadRegisterDefinitions.cpp | 4 +- .../Target/RISCV/RISCVInstrInfoVPseudos.td | 2 +- .../CodeGen/RISCV/rvv/calling-conv-fastcc.ll | 38 +- llvm/test/CodeGen/RISCV/rvv/calling-conv.ll | 8 +- ...d-vectors-fnearbyint-constrained-sdnode.ll | 24 +- .../RISCV/rvv/fixed-vectors-fp2i-sat.ll | 24 +- .../CodeGen/RISCV/rvv/fixed-vectors-i2fp.ll | 80 ++-- .../RISCV/rvv/fixed-vectors-int-buildvec.ll | 154 ++++---- ...fixed-vectors-interleaved-access-zve32x.ll | 38 +- .../CodeGen/RISCV/rvv/fixed-vectors-lrint.ll | 20 +- .../RISCV/rvv/fixed-vectors-masked-gather.ll | 372 +++++++++--------- .../RISCV/rvv/fixed-vectors-masked-scatter.ll | 69 ++-- .../RISCV/rvv/fixed-vectors-nearbyint-vp.ll | 56 +-- .../RISCV/rvv/fixed-vectors-vselect.ll | 24 +- .../CodeGen/RISCV/rvv/fixed-vectors-vwadd.ll | 8 +- .../CodeGen/RISCV/rvv/fixed-vectors-vwaddu.ll | 8 +- .../CodeGen/RISCV/rvv/fixed-vectors-vwmul.ll | 2 +- .../RISCV/rvv/fixed-vectors-vwmulsu.ll | 6 +- .../CodeGen/RISCV/rvv/fixed-vectors-vwsub.ll | 8 +- .../CodeGen/RISCV/rvv/fixed-vectors-vwsubu.ll | 8 +- llvm/test/CodeGen/RISCV/rvv/fmaximum-vp.ll | 154 +++++--- llvm/test/CodeGen/RISCV/rvv/fminimum-vp.ll | 154 +++++--- .../rvv/fnearbyint-constrained-sdnode.ll | 30 +- .../CodeGen/RISCV/rvv/fnearbyint-sdnode.ll | 30 +- llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll | 294 ++++++-------- llvm/test/CodeGen/RISCV/rvv/mgather-sdnode.ll | 19 +- .../test/CodeGen/RISCV/rvv/mscatter-sdnode.ll | 2 +- llvm/test/CodeGen/RISCV/rvv/nearbyint-vp.ll | 197 +++++----- llvm/test/CodeGen/RISCV/rvv/setcc-fp-vp.ll | 268 ++++++------- llvm/test/CodeGen/RISCV/rvv/setcc-int-vp.ll | 40 +- llvm/test/CodeGen/RISCV/rvv/vfma-vp.ll | 34 +- llvm/test/CodeGen/RISCV/rvv/vfmuladd-vp.ll | 34 +- llvm/test/CodeGen/RISCV/rvv/vpmerge-sdnode.ll | 14 +- llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll | 6 +- .../RISCV/rvv/vsetvli-insert-crossbb.ll | 39 +- .../CodeGen/RISCV/rvv/vsetvli-regression.ll | 5 +- 36 files changed, 1107 insertions(+), 1166 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVDeadRegisterDefinitions.cpp b/llvm/lib/Target/RISCV/RISCVDeadRegisterDefinitions.cpp index 5e6b7891449f..7de48d8218f0 100644 --- a/llvm/lib/Target/RISCV/RISCVDeadRegisterDefinitions.cpp +++ b/llvm/lib/Target/RISCV/RISCVDeadRegisterDefinitions.cpp @@ -72,7 +72,9 @@ bool RISCVDeadRegisterDefinitions::runOnMachineFunction(MachineFunction &MF) { // are reserved for HINT instructions. const MCInstrDesc &Desc = MI.getDesc(); if (!Desc.mayLoad() && !Desc.mayStore() && - !Desc.hasUnmodeledSideEffects()) + !Desc.hasUnmodeledSideEffects() && + MI.getOpcode() != RISCV::PseudoVSETVLI && + MI.getOpcode() != RISCV::PseudoVSETIVLI) continue; // For PseudoVSETVLIX0, Rd = X0 has special meaning. if (MI.getOpcode() == RISCV::PseudoVSETVLIX0) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td index 4adc26f62891..317a6d7d4c52 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -6181,7 +6181,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 0, //===----------------------------------------------------------------------===// // Pseudos. -let hasSideEffects = 1, mayLoad = 0, mayStore = 0, Defs = [VL, VTYPE] in { +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Defs = [VL, VTYPE] in { // Due to rs1=X0 having special meaning, we need a GPRNoX0 register class for // the when we aren't using one of the special X0 encodings. Otherwise it could // be accidentally be made X0 by MachineIR optimizations. To satisfy the diff --git a/llvm/test/CodeGen/RISCV/rvv/calling-conv-fastcc.ll b/llvm/test/CodeGen/RISCV/rvv/calling-conv-fastcc.ll index 187f758b7802..0a7fa38b0c8a 100644 --- a/llvm/test/CodeGen/RISCV/rvv/calling-conv-fastcc.ll +++ b/llvm/test/CodeGen/RISCV/rvv/calling-conv-fastcc.ll @@ -236,11 +236,12 @@ define fastcc @ret_nxv32i32_param_nxv32i32_nxv32i32_nxv32i32 ; CHECK-NEXT: addi sp, sp, -16 ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: csrr a1, vlenb -; CHECK-NEXT: slli a1, a1, 4 +; CHECK-NEXT: li a3, 24 +; CHECK-NEXT: mul a1, a1, a3 ; CHECK-NEXT: sub sp, sp, a1 -; CHECK-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x10, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 16 * vlenb +; CHECK-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 24 * vlenb ; CHECK-NEXT: csrr a1, vlenb -; CHECK-NEXT: slli a1, a1, 3 +; CHECK-NEXT: slli a1, a1, 4 ; CHECK-NEXT: add a1, sp, a1 ; CHECK-NEXT: addi a1, a1, 16 ; CHECK-NEXT: vs8r.v v16, (a1) # Unknown-size Folded Spill @@ -248,29 +249,40 @@ define fastcc @ret_nxv32i32_param_nxv32i32_nxv32i32_nxv32i32 ; CHECK-NEXT: csrr a1, vlenb ; CHECK-NEXT: slli a1, a1, 3 ; CHECK-NEXT: add a3, a2, a1 -; CHECK-NEXT: vl8re32.v v8, (a3) -; CHECK-NEXT: addi a3, sp, 16 -; CHECK-NEXT: vs8r.v v8, (a3) # Unknown-size Folded Spill ; CHECK-NEXT: add a1, a0, a1 -; CHECK-NEXT: vl8re32.v v0, (a0) ; CHECK-NEXT: vl8re32.v v8, (a1) -; CHECK-NEXT: vl8re32.v v16, (a2) +; CHECK-NEXT: csrr a1, vlenb +; CHECK-NEXT: slli a1, a1, 3 +; CHECK-NEXT: add a1, sp, a1 +; CHECK-NEXT: addi a1, a1, 16 +; CHECK-NEXT: vs8r.v v8, (a1) # Unknown-size Folded Spill +; CHECK-NEXT: vl8re32.v v0, (a0) ; CHECK-NEXT: vsetvli a0, zero, e32, m8, ta, ma +; CHECK-NEXT: vl8re32.v v8, (a3) +; CHECK-NEXT: addi a0, sp, 16 +; CHECK-NEXT: vs8r.v v8, (a0) # Unknown-size Folded Spill +; CHECK-NEXT: vl8re32.v v16, (a2) ; CHECK-NEXT: vadd.vv v0, v24, v0 ; CHECK-NEXT: csrr a0, vlenb -; CHECK-NEXT: slli a0, a0, 3 +; CHECK-NEXT: slli a0, a0, 4 ; CHECK-NEXT: add a0, sp, a0 ; CHECK-NEXT: addi a0, a0, 16 ; CHECK-NEXT: vl8r.v v24, (a0) # Unknown-size Folded Reload -; CHECK-NEXT: vadd.vv v8, v24, v8 +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: slli a0, a0, 3 +; CHECK-NEXT: add a0, sp, a0 +; CHECK-NEXT: addi a0, a0, 16 +; CHECK-NEXT: vl8r.v v8, (a0) # Unknown-size Folded Reload +; CHECK-NEXT: vadd.vv v24, v24, v8 ; CHECK-NEXT: addi a0, sp, 16 -; CHECK-NEXT: vl8r.v v24, (a0) # Unknown-size Folded Reload -; CHECK-NEXT: vadd.vv v8, v8, v24 +; CHECK-NEXT: vl8r.v v8, (a0) # Unknown-size Folded Reload +; CHECK-NEXT: vadd.vv v8, v24, v8 ; CHECK-NEXT: vadd.vv v24, v0, v16 ; CHECK-NEXT: vadd.vx v16, v8, a4 ; CHECK-NEXT: vadd.vx v8, v24, a4 ; CHECK-NEXT: csrr a0, vlenb -; CHECK-NEXT: slli a0, a0, 4 +; CHECK-NEXT: li a1, 24 +; CHECK-NEXT: mul a0, a0, a1 ; CHECK-NEXT: add sp, sp, a0 ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll b/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll index 647d3158b616..fa62143546df 100644 --- a/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll +++ b/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll @@ -39,11 +39,11 @@ define @caller_scalable_vector_split_indirect( @caller_scalable_vector_split_indirect( @nearbyint_v2f16(<2 x half> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, mf4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <2 x half> @llvm.experimental.constrained.nearbyint.v2f16(<2 x half> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <2 x half> %r @@ -42,9 +42,9 @@ define <4 x half> @nearbyint_v4f16(<4 x half> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <4 x half> @llvm.experimental.constrained.nearbyint.v4f16(<4 x half> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <4 x half> %r @@ -65,9 +65,9 @@ define <8 x half> @nearbyint_v8f16(<8 x half> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <8 x half> @llvm.experimental.constrained.nearbyint.v8f16(<8 x half> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <8 x half> %r @@ -88,9 +88,9 @@ define <16 x half> @nearbyint_v16f16(<16 x half> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <16 x half> @llvm.experimental.constrained.nearbyint.v16f16(<16 x half> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <16 x half> %r @@ -112,9 +112,9 @@ define <32 x half> @nearbyint_v32f16(<32 x half> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <32 x half> @llvm.experimental.constrained.nearbyint.v32f16(<32 x half> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <32 x half> %r @@ -135,9 +135,9 @@ define <2 x float> @nearbyint_v2f32(<2 x float> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <2 x float> @llvm.experimental.constrained.nearbyint.v2f32(<2 x float> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <2 x float> %r @@ -158,9 +158,9 @@ define <4 x float> @nearbyint_v4f32(<4 x float> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <4 x float> @llvm.experimental.constrained.nearbyint.v4f32(<4 x float> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <4 x float> %r @@ -181,9 +181,9 @@ define <8 x float> @nearbyint_v8f32(<8 x float> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <8 x float> @llvm.experimental.constrained.nearbyint.v8f32(<8 x float> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <8 x float> %r @@ -204,9 +204,9 @@ define <16 x float> @nearbyint_v16f32(<16 x float> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <16 x float> @llvm.experimental.constrained.nearbyint.v16f32(<16 x float> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <16 x float> %r @@ -227,9 +227,9 @@ define <2 x double> @nearbyint_v2f64(<2 x double> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <2 x double> @llvm.experimental.constrained.nearbyint.v2f64(<2 x double> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <2 x double> %r @@ -250,9 +250,9 @@ define <4 x double> @nearbyint_v4f64(<4 x double> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <4 x double> @llvm.experimental.constrained.nearbyint.v4f64(<4 x double> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <4 x double> %r @@ -273,9 +273,9 @@ define <8 x double> @nearbyint_v8f64(<8 x double> %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call <8 x double> @llvm.experimental.constrained.nearbyint.v8f64(<8 x double> %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret <8 x double> %r diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp2i-sat.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp2i-sat.ll index a8e4af2d7368..6320b07125bb 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp2i-sat.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp2i-sat.ll @@ -359,13 +359,13 @@ define void @fp2si_v8f64_v8i8(ptr %x, ptr %y) { ; RV32-NEXT: feq.d a0, fa3, fa3 ; RV32-NEXT: fmax.d fa3, fa3, fa5 ; RV32-NEXT: fmin.d fa3, fa3, fa4 -; RV32-NEXT: vsetivli zero, 8, e8, mf2, ta, mu -; RV32-NEXT: fld fa2, 40(sp) ; RV32-NEXT: fcvt.w.d a2, fa3, rtz +; RV32-NEXT: fld fa3, 40(sp) ; RV32-NEXT: neg a0, a0 ; RV32-NEXT: and a0, a0, a2 -; RV32-NEXT: feq.d a2, fa2, fa2 -; RV32-NEXT: fmax.d fa3, fa2, fa5 +; RV32-NEXT: vsetivli zero, 8, e8, mf2, ta, mu +; RV32-NEXT: feq.d a2, fa3, fa3 +; RV32-NEXT: fmax.d fa3, fa3, fa5 ; RV32-NEXT: fmin.d fa3, fa3, fa4 ; RV32-NEXT: fcvt.w.d a3, fa3, rtz ; RV32-NEXT: fld fa3, 32(sp) @@ -460,13 +460,13 @@ define void @fp2si_v8f64_v8i8(ptr %x, ptr %y) { ; RV64-NEXT: feq.d a0, fa3, fa3 ; RV64-NEXT: fmax.d fa3, fa3, fa5 ; RV64-NEXT: fmin.d fa3, fa3, fa4 -; RV64-NEXT: vsetivli zero, 8, e8, mf2, ta, mu -; RV64-NEXT: fld fa2, 40(sp) ; RV64-NEXT: fcvt.l.d a2, fa3, rtz +; RV64-NEXT: fld fa3, 40(sp) ; RV64-NEXT: neg a0, a0 ; RV64-NEXT: and a0, a0, a2 -; RV64-NEXT: feq.d a2, fa2, fa2 -; RV64-NEXT: fmax.d fa3, fa2, fa5 +; RV64-NEXT: vsetivli zero, 8, e8, mf2, ta, mu +; RV64-NEXT: feq.d a2, fa3, fa3 +; RV64-NEXT: fmax.d fa3, fa3, fa5 ; RV64-NEXT: fmin.d fa3, fa3, fa4 ; RV64-NEXT: fcvt.l.d a3, fa3, rtz ; RV64-NEXT: fld fa3, 32(sp) @@ -557,7 +557,6 @@ define void @fp2ui_v8f64_v8i8(ptr %x, ptr %y) { ; RV32-NEXT: vslidedown.vi v8, v8, 3 ; RV32-NEXT: vfmv.f.s fa4, v8 ; RV32-NEXT: fmax.d fa4, fa4, fa3 -; RV32-NEXT: vsetivli zero, 8, e8, mf2, ta, mu ; RV32-NEXT: fld fa2, 40(sp) ; RV32-NEXT: fmin.d fa4, fa4, fa5 ; RV32-NEXT: fcvt.wu.d a0, fa4, rtz @@ -566,9 +565,10 @@ define void @fp2ui_v8f64_v8i8(ptr %x, ptr %y) { ; RV32-NEXT: fmin.d fa2, fa2, fa5 ; RV32-NEXT: fcvt.wu.d a2, fa2, rtz ; RV32-NEXT: fmax.d fa4, fa4, fa3 -; RV32-NEXT: fld fa2, 48(sp) ; RV32-NEXT: fmin.d fa4, fa4, fa5 +; RV32-NEXT: fld fa2, 48(sp) ; RV32-NEXT: fcvt.wu.d a3, fa4, rtz +; RV32-NEXT: vsetivli zero, 8, e8, mf2, ta, mu ; RV32-NEXT: vslide1down.vx v8, v10, a0 ; RV32-NEXT: fmax.d fa4, fa2, fa3 ; RV32-NEXT: fmin.d fa4, fa4, fa5 @@ -633,7 +633,6 @@ define void @fp2ui_v8f64_v8i8(ptr %x, ptr %y) { ; RV64-NEXT: vslidedown.vi v8, v8, 3 ; RV64-NEXT: vfmv.f.s fa4, v8 ; RV64-NEXT: fmax.d fa4, fa4, fa3 -; RV64-NEXT: vsetivli zero, 8, e8, mf2, ta, mu ; RV64-NEXT: fld fa2, 40(sp) ; RV64-NEXT: fmin.d fa4, fa4, fa5 ; RV64-NEXT: fcvt.lu.d a0, fa4, rtz @@ -642,9 +641,10 @@ define void @fp2ui_v8f64_v8i8(ptr %x, ptr %y) { ; RV64-NEXT: fmin.d fa2, fa2, fa5 ; RV64-NEXT: fcvt.lu.d a2, fa2, rtz ; RV64-NEXT: fmax.d fa4, fa4, fa3 -; RV64-NEXT: fld fa2, 48(sp) ; RV64-NEXT: fmin.d fa4, fa4, fa5 +; RV64-NEXT: fld fa2, 48(sp) ; RV64-NEXT: fcvt.lu.d a3, fa4, rtz +; RV64-NEXT: vsetivli zero, 8, e8, mf2, ta, mu ; RV64-NEXT: vslide1down.vx v8, v10, a0 ; RV64-NEXT: fmax.d fa4, fa2, fa3 ; RV64-NEXT: fmin.d fa4, fa4, fa5 diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-i2fp.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-i2fp.ll index 6ffa6ac250ed..9c76b83d0974 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-i2fp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-i2fp.ll @@ -132,12 +132,12 @@ define <3 x float> @si2fp_v3i1_v3f32(<3 x i1> %x) { define <3 x float> @si2fp_v3i7_v3f32(<3 x i7> %x) { ; ZVFH32-LABEL: si2fp_v3i7_v3f32: ; ZVFH32: # %bb.0: -; ZVFH32-NEXT: lw a1, 4(a0) -; ZVFH32-NEXT: lw a2, 0(a0) -; ZVFH32-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFH32-NEXT: lw a1, 0(a0) +; ZVFH32-NEXT: lw a2, 4(a0) ; ZVFH32-NEXT: lw a0, 8(a0) -; ZVFH32-NEXT: vmv.v.x v8, a2 -; ZVFH32-NEXT: vslide1down.vx v8, v8, a1 +; ZVFH32-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFH32-NEXT: vmv.v.x v8, a1 +; ZVFH32-NEXT: vslide1down.vx v8, v8, a2 ; ZVFH32-NEXT: vslide1down.vx v8, v8, a0 ; ZVFH32-NEXT: vslidedown.vi v8, v8, 1 ; ZVFH32-NEXT: vadd.vv v8, v8, v8 @@ -149,12 +149,12 @@ define <3 x float> @si2fp_v3i7_v3f32(<3 x i7> %x) { ; ; ZVFH64-LABEL: si2fp_v3i7_v3f32: ; ZVFH64: # %bb.0: -; ZVFH64-NEXT: ld a1, 8(a0) -; ZVFH64-NEXT: ld a2, 0(a0) -; ZVFH64-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFH64-NEXT: ld a1, 0(a0) +; ZVFH64-NEXT: ld a2, 8(a0) ; ZVFH64-NEXT: ld a0, 16(a0) -; ZVFH64-NEXT: vmv.v.x v8, a2 -; ZVFH64-NEXT: vslide1down.vx v8, v8, a1 +; ZVFH64-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFH64-NEXT: vmv.v.x v8, a1 +; ZVFH64-NEXT: vslide1down.vx v8, v8, a2 ; ZVFH64-NEXT: vslide1down.vx v8, v8, a0 ; ZVFH64-NEXT: vslidedown.vi v8, v8, 1 ; ZVFH64-NEXT: vadd.vv v8, v8, v8 @@ -166,12 +166,12 @@ define <3 x float> @si2fp_v3i7_v3f32(<3 x i7> %x) { ; ; ZVFHMIN32-LABEL: si2fp_v3i7_v3f32: ; ZVFHMIN32: # %bb.0: -; ZVFHMIN32-NEXT: lw a1, 4(a0) -; ZVFHMIN32-NEXT: lw a2, 0(a0) -; ZVFHMIN32-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFHMIN32-NEXT: lw a1, 0(a0) +; ZVFHMIN32-NEXT: lw a2, 4(a0) ; ZVFHMIN32-NEXT: lw a0, 8(a0) -; ZVFHMIN32-NEXT: vmv.v.x v8, a2 -; ZVFHMIN32-NEXT: vslide1down.vx v8, v8, a1 +; ZVFHMIN32-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFHMIN32-NEXT: vmv.v.x v8, a1 +; ZVFHMIN32-NEXT: vslide1down.vx v8, v8, a2 ; ZVFHMIN32-NEXT: vslide1down.vx v8, v8, a0 ; ZVFHMIN32-NEXT: vslidedown.vi v8, v8, 1 ; ZVFHMIN32-NEXT: vadd.vv v8, v8, v8 @@ -183,12 +183,12 @@ define <3 x float> @si2fp_v3i7_v3f32(<3 x i7> %x) { ; ; ZVFHMIN64-LABEL: si2fp_v3i7_v3f32: ; ZVFHMIN64: # %bb.0: -; ZVFHMIN64-NEXT: ld a1, 8(a0) -; ZVFHMIN64-NEXT: ld a2, 0(a0) -; ZVFHMIN64-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFHMIN64-NEXT: ld a1, 0(a0) +; ZVFHMIN64-NEXT: ld a2, 8(a0) ; ZVFHMIN64-NEXT: ld a0, 16(a0) -; ZVFHMIN64-NEXT: vmv.v.x v8, a2 -; ZVFHMIN64-NEXT: vslide1down.vx v8, v8, a1 +; ZVFHMIN64-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFHMIN64-NEXT: vmv.v.x v8, a1 +; ZVFHMIN64-NEXT: vslide1down.vx v8, v8, a2 ; ZVFHMIN64-NEXT: vslide1down.vx v8, v8, a0 ; ZVFHMIN64-NEXT: vslidedown.vi v8, v8, 1 ; ZVFHMIN64-NEXT: vadd.vv v8, v8, v8 @@ -205,12 +205,12 @@ define <3 x float> @si2fp_v3i7_v3f32(<3 x i7> %x) { define <3 x float> @ui2fp_v3i7_v3f32(<3 x i7> %x) { ; ZVFH32-LABEL: ui2fp_v3i7_v3f32: ; ZVFH32: # %bb.0: -; ZVFH32-NEXT: lw a1, 4(a0) -; ZVFH32-NEXT: lw a2, 0(a0) -; ZVFH32-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFH32-NEXT: lw a1, 0(a0) +; ZVFH32-NEXT: lw a2, 4(a0) ; ZVFH32-NEXT: lw a0, 8(a0) -; ZVFH32-NEXT: vmv.v.x v8, a2 -; ZVFH32-NEXT: vslide1down.vx v8, v8, a1 +; ZVFH32-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFH32-NEXT: vmv.v.x v8, a1 +; ZVFH32-NEXT: vslide1down.vx v8, v8, a2 ; ZVFH32-NEXT: vslide1down.vx v8, v8, a0 ; ZVFH32-NEXT: vslidedown.vi v8, v8, 1 ; ZVFH32-NEXT: li a0, 127 @@ -222,12 +222,12 @@ define <3 x float> @ui2fp_v3i7_v3f32(<3 x i7> %x) { ; ; ZVFH64-LABEL: ui2fp_v3i7_v3f32: ; ZVFH64: # %bb.0: -; ZVFH64-NEXT: ld a1, 8(a0) -; ZVFH64-NEXT: ld a2, 0(a0) -; ZVFH64-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFH64-NEXT: ld a1, 0(a0) +; ZVFH64-NEXT: ld a2, 8(a0) ; ZVFH64-NEXT: ld a0, 16(a0) -; ZVFH64-NEXT: vmv.v.x v8, a2 -; ZVFH64-NEXT: vslide1down.vx v8, v8, a1 +; ZVFH64-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFH64-NEXT: vmv.v.x v8, a1 +; ZVFH64-NEXT: vslide1down.vx v8, v8, a2 ; ZVFH64-NEXT: vslide1down.vx v8, v8, a0 ; ZVFH64-NEXT: vslidedown.vi v8, v8, 1 ; ZVFH64-NEXT: li a0, 127 @@ -239,12 +239,12 @@ define <3 x float> @ui2fp_v3i7_v3f32(<3 x i7> %x) { ; ; ZVFHMIN32-LABEL: ui2fp_v3i7_v3f32: ; ZVFHMIN32: # %bb.0: -; ZVFHMIN32-NEXT: lw a1, 4(a0) -; ZVFHMIN32-NEXT: lw a2, 0(a0) -; ZVFHMIN32-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFHMIN32-NEXT: lw a1, 0(a0) +; ZVFHMIN32-NEXT: lw a2, 4(a0) ; ZVFHMIN32-NEXT: lw a0, 8(a0) -; ZVFHMIN32-NEXT: vmv.v.x v8, a2 -; ZVFHMIN32-NEXT: vslide1down.vx v8, v8, a1 +; ZVFHMIN32-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFHMIN32-NEXT: vmv.v.x v8, a1 +; ZVFHMIN32-NEXT: vslide1down.vx v8, v8, a2 ; ZVFHMIN32-NEXT: vslide1down.vx v8, v8, a0 ; ZVFHMIN32-NEXT: vslidedown.vi v8, v8, 1 ; ZVFHMIN32-NEXT: li a0, 127 @@ -256,12 +256,12 @@ define <3 x float> @ui2fp_v3i7_v3f32(<3 x i7> %x) { ; ; ZVFHMIN64-LABEL: ui2fp_v3i7_v3f32: ; ZVFHMIN64: # %bb.0: -; ZVFHMIN64-NEXT: ld a1, 8(a0) -; ZVFHMIN64-NEXT: ld a2, 0(a0) -; ZVFHMIN64-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFHMIN64-NEXT: ld a1, 0(a0) +; ZVFHMIN64-NEXT: ld a2, 8(a0) ; ZVFHMIN64-NEXT: ld a0, 16(a0) -; ZVFHMIN64-NEXT: vmv.v.x v8, a2 -; ZVFHMIN64-NEXT: vslide1down.vx v8, v8, a1 +; ZVFHMIN64-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; ZVFHMIN64-NEXT: vmv.v.x v8, a1 +; ZVFHMIN64-NEXT: vslide1down.vx v8, v8, a2 ; ZVFHMIN64-NEXT: vslide1down.vx v8, v8, a0 ; ZVFHMIN64-NEXT: vslidedown.vi v8, v8, 1 ; ZVFHMIN64-NEXT: li a0, 127 diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll index 592ce6fc5be0..4f4f0a09de74 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll @@ -1183,38 +1183,38 @@ define <8 x i64> @v8xi64_exact_undef_prefix(i64 %a, i64 %b, i64 %c, i64 %d) vsca define <16 x i8> @buildvec_v16i8_loads_contigous(ptr %p) { ; CHECK-LABEL: buildvec_v16i8_loads_contigous: ; CHECK: # %bb.0: -; CHECK-NEXT: lbu a1, 1(a0) -; CHECK-NEXT: lbu a2, 2(a0) -; CHECK-NEXT: lbu a3, 3(a0) -; CHECK-NEXT: lbu a4, 4(a0) -; CHECK-NEXT: lbu a5, 5(a0) -; CHECK-NEXT: lbu a6, 6(a0) -; CHECK-NEXT: lbu a7, 7(a0) -; CHECK-NEXT: lbu t0, 9(a0) -; CHECK-NEXT: lbu t1, 10(a0) -; CHECK-NEXT: lbu t2, 11(a0) -; CHECK-NEXT: lbu t3, 12(a0) -; CHECK-NEXT: lbu t4, 13(a0) -; CHECK-NEXT: lbu t5, 14(a0) -; CHECK-NEXT: lbu t6, 15(a0) +; CHECK-NEXT: addi a1, a0, 8 +; CHECK-NEXT: lbu a2, 1(a0) +; CHECK-NEXT: lbu a3, 2(a0) +; CHECK-NEXT: lbu a4, 3(a0) +; CHECK-NEXT: lbu a5, 4(a0) +; CHECK-NEXT: lbu a6, 5(a0) +; CHECK-NEXT: lbu a7, 6(a0) +; CHECK-NEXT: lbu t0, 7(a0) +; CHECK-NEXT: lbu t1, 9(a0) +; CHECK-NEXT: lbu t2, 10(a0) +; CHECK-NEXT: lbu t3, 11(a0) +; CHECK-NEXT: lbu t4, 12(a0) ; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma ; CHECK-NEXT: vlse8.v v8, (a0), zero -; CHECK-NEXT: addi a0, a0, 8 -; CHECK-NEXT: vslide1down.vx v8, v8, a1 +; CHECK-NEXT: lbu t5, 13(a0) +; CHECK-NEXT: lbu t6, 14(a0) +; CHECK-NEXT: lbu a0, 15(a0) ; CHECK-NEXT: vslide1down.vx v8, v8, a2 ; CHECK-NEXT: vslide1down.vx v8, v8, a3 ; CHECK-NEXT: vslide1down.vx v8, v8, a4 -; CHECK-NEXT: vlse8.v v9, (a0), zero ; CHECK-NEXT: vslide1down.vx v8, v8, a5 +; CHECK-NEXT: vlse8.v v9, (a1), zero ; CHECK-NEXT: vslide1down.vx v8, v8, a6 -; CHECK-NEXT: vslide1down.vx v10, v8, a7 -; CHECK-NEXT: vslide1down.vx v8, v9, t0 -; CHECK-NEXT: vslide1down.vx v8, v8, t1 +; CHECK-NEXT: vslide1down.vx v8, v8, a7 +; CHECK-NEXT: vslide1down.vx v10, v8, t0 +; CHECK-NEXT: vslide1down.vx v8, v9, t1 ; CHECK-NEXT: vslide1down.vx v8, v8, t2 ; CHECK-NEXT: vslide1down.vx v8, v8, t3 ; CHECK-NEXT: vslide1down.vx v8, v8, t4 ; CHECK-NEXT: vslide1down.vx v8, v8, t5 ; CHECK-NEXT: vslide1down.vx v8, v8, t6 +; CHECK-NEXT: vslide1down.vx v8, v8, a0 ; CHECK-NEXT: li a0, 255 ; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma ; CHECK-NEXT: vmv.s.x v0, a0 @@ -1277,38 +1277,38 @@ define <16 x i8> @buildvec_v16i8_loads_contigous(ptr %p) { define <16 x i8> @buildvec_v16i8_loads_gather(ptr %p) { ; CHECK-LABEL: buildvec_v16i8_loads_gather: ; CHECK: # %bb.0: -; CHECK-NEXT: lbu a1, 1(a0) -; CHECK-NEXT: lbu a2, 22(a0) -; CHECK-NEXT: lbu a3, 31(a0) -; CHECK-NEXT: lbu a4, 44(a0) -; CHECK-NEXT: lbu a5, 55(a0) -; CHECK-NEXT: lbu a6, 623(a0) -; CHECK-NEXT: lbu a7, 75(a0) -; CHECK-NEXT: lbu t0, 93(a0) -; CHECK-NEXT: lbu t1, 105(a0) -; CHECK-NEXT: lbu t2, 161(a0) -; CHECK-NEXT: lbu t3, 124(a0) -; CHECK-NEXT: lbu t4, 163(a0) -; CHECK-NEXT: lbu t5, 144(a0) -; CHECK-NEXT: lbu t6, 154(a0) +; CHECK-NEXT: addi a1, a0, 82 +; CHECK-NEXT: lbu a2, 1(a0) +; CHECK-NEXT: lbu a3, 22(a0) +; CHECK-NEXT: lbu a4, 31(a0) +; CHECK-NEXT: lbu a5, 44(a0) +; CHECK-NEXT: lbu a6, 55(a0) +; CHECK-NEXT: lbu a7, 623(a0) +; CHECK-NEXT: lbu t0, 75(a0) +; CHECK-NEXT: lbu t1, 93(a0) +; CHECK-NEXT: lbu t2, 105(a0) +; CHECK-NEXT: lbu t3, 161(a0) +; CHECK-NEXT: lbu t4, 124(a0) ; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma ; CHECK-NEXT: vlse8.v v8, (a0), zero -; CHECK-NEXT: addi a0, a0, 82 -; CHECK-NEXT: vslide1down.vx v8, v8, a1 +; CHECK-NEXT: lbu t5, 163(a0) +; CHECK-NEXT: lbu t6, 144(a0) +; CHECK-NEXT: lbu a0, 154(a0) ; CHECK-NEXT: vslide1down.vx v8, v8, a2 ; CHECK-NEXT: vslide1down.vx v8, v8, a3 ; CHECK-NEXT: vslide1down.vx v8, v8, a4 -; CHECK-NEXT: vlse8.v v9, (a0), zero ; CHECK-NEXT: vslide1down.vx v8, v8, a5 +; CHECK-NEXT: vlse8.v v9, (a1), zero ; CHECK-NEXT: vslide1down.vx v8, v8, a6 -; CHECK-NEXT: vslide1down.vx v10, v8, a7 -; CHECK-NEXT: vslide1down.vx v8, v9, t0 -; CHECK-NEXT: vslide1down.vx v8, v8, t1 +; CHECK-NEXT: vslide1down.vx v8, v8, a7 +; CHECK-NEXT: vslide1down.vx v10, v8, t0 +; CHECK-NEXT: vslide1down.vx v8, v9, t1 ; CHECK-NEXT: vslide1down.vx v8, v8, t2 ; CHECK-NEXT: vslide1down.vx v8, v8, t3 ; CHECK-NEXT: vslide1down.vx v8, v8, t4 ; CHECK-NEXT: vslide1down.vx v8, v8, t5 ; CHECK-NEXT: vslide1down.vx v8, v8, t6 +; CHECK-NEXT: vslide1down.vx v8, v8, a0 ; CHECK-NEXT: li a0, 255 ; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma ; CHECK-NEXT: vmv.s.x v0, a0 @@ -1375,17 +1375,17 @@ define <16 x i8> @buildvec_v16i8_undef_low_half(ptr %p) { ; CHECK-NEXT: lbu a3, 105(a0) ; CHECK-NEXT: lbu a4, 161(a0) ; CHECK-NEXT: lbu a5, 124(a0) -; CHECK-NEXT: lbu a6, 163(a0) -; CHECK-NEXT: lbu a7, 144(a0) -; CHECK-NEXT: lbu a0, 154(a0) ; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma ; CHECK-NEXT: vlse8.v v8, (a1), zero +; CHECK-NEXT: lbu a1, 163(a0) +; CHECK-NEXT: lbu a6, 144(a0) +; CHECK-NEXT: lbu a0, 154(a0) ; CHECK-NEXT: vslide1down.vx v8, v8, a2 ; CHECK-NEXT: vslide1down.vx v8, v8, a3 ; CHECK-NEXT: vslide1down.vx v8, v8, a4 ; CHECK-NEXT: vslide1down.vx v8, v8, a5 +; CHECK-NEXT: vslide1down.vx v8, v8, a1 ; CHECK-NEXT: vslide1down.vx v8, v8, a6 -; CHECK-NEXT: vslide1down.vx v8, v8, a7 ; CHECK-NEXT: vslide1down.vx v8, v8, a0 ; CHECK-NEXT: ret %p9 = getelementptr i8, ptr %p, i32 82 @@ -1424,18 +1424,18 @@ define <16 x i8> @buildvec_v16i8_undef_high_half(ptr %p) { ; CHECK-NEXT: lbu a2, 22(a0) ; CHECK-NEXT: lbu a3, 31(a0) ; CHECK-NEXT: lbu a4, 44(a0) -; CHECK-NEXT: lbu a5, 55(a0) -; CHECK-NEXT: lbu a6, 623(a0) -; CHECK-NEXT: lbu a7, 75(a0) ; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma ; CHECK-NEXT: vlse8.v v8, (a0), zero +; CHECK-NEXT: lbu a5, 55(a0) +; CHECK-NEXT: lbu a6, 623(a0) +; CHECK-NEXT: lbu a0, 75(a0) ; CHECK-NEXT: vslide1down.vx v8, v8, a1 ; CHECK-NEXT: vslide1down.vx v8, v8, a2 ; CHECK-NEXT: vslide1down.vx v8, v8, a3 ; CHECK-NEXT: vslide1down.vx v8, v8, a4 ; CHECK-NEXT: vslide1down.vx v8, v8, a5 ; CHECK-NEXT: vslide1down.vx v8, v8, a6 -; CHECK-NEXT: vslide1down.vx v8, v8, a7 +; CHECK-NEXT: vslide1down.vx v8, v8, a0 ; CHECK-NEXT: vslidedown.vi v8, v8, 8 ; CHECK-NEXT: ret %p2 = getelementptr i8, ptr %p, i32 1 @@ -1470,24 +1470,24 @@ define <16 x i8> @buildvec_v16i8_undef_edges(ptr %p) { ; CHECK-LABEL: buildvec_v16i8_undef_edges: ; CHECK: # %bb.0: ; CHECK-NEXT: addi a1, a0, 31 -; CHECK-NEXT: lbu a2, 44(a0) -; CHECK-NEXT: lbu a3, 55(a0) -; CHECK-NEXT: lbu a4, 623(a0) -; CHECK-NEXT: lbu a5, 75(a0) -; CHECK-NEXT: lbu a6, 93(a0) -; CHECK-NEXT: lbu a7, 105(a0) -; CHECK-NEXT: lbu t0, 161(a0) +; CHECK-NEXT: addi a2, a0, 82 +; CHECK-NEXT: lbu a3, 44(a0) +; CHECK-NEXT: lbu a4, 55(a0) +; CHECK-NEXT: lbu a5, 623(a0) +; CHECK-NEXT: lbu a6, 75(a0) ; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma ; CHECK-NEXT: vlse8.v v8, (a1), zero -; CHECK-NEXT: addi a0, a0, 82 -; CHECK-NEXT: vslide1down.vx v8, v8, a2 -; CHECK-NEXT: vlse8.v v9, (a0), zero +; CHECK-NEXT: lbu a1, 93(a0) +; CHECK-NEXT: lbu a7, 105(a0) +; CHECK-NEXT: lbu a0, 161(a0) ; CHECK-NEXT: vslide1down.vx v8, v8, a3 +; CHECK-NEXT: vlse8.v v9, (a2), zero ; CHECK-NEXT: vslide1down.vx v8, v8, a4 -; CHECK-NEXT: vslide1down.vx v10, v8, a5 -; CHECK-NEXT: vslide1down.vx v8, v9, a6 +; CHECK-NEXT: vslide1down.vx v8, v8, a5 +; CHECK-NEXT: vslide1down.vx v10, v8, a6 +; CHECK-NEXT: vslide1down.vx v8, v9, a1 ; CHECK-NEXT: vslide1down.vx v8, v8, a7 -; CHECK-NEXT: vslide1down.vx v8, v8, t0 +; CHECK-NEXT: vslide1down.vx v8, v8, a0 ; CHECK-NEXT: vslidedown.vi v8, v8, 4 ; CHECK-NEXT: li a0, 255 ; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma @@ -1530,30 +1530,30 @@ define <16 x i8> @buildvec_v16i8_undef_edges(ptr %p) { define <16 x i8> @buildvec_v16i8_loads_undef_scattered(ptr %p) { ; CHECK-LABEL: buildvec_v16i8_loads_undef_scattered: ; CHECK: # %bb.0: -; CHECK-NEXT: lbu a1, 1(a0) -; CHECK-NEXT: lbu a2, 44(a0) -; CHECK-NEXT: lbu a3, 55(a0) -; CHECK-NEXT: lbu a4, 75(a0) -; CHECK-NEXT: lbu a5, 93(a0) -; CHECK-NEXT: lbu a6, 124(a0) -; CHECK-NEXT: lbu a7, 144(a0) -; CHECK-NEXT: lbu t0, 154(a0) +; CHECK-NEXT: addi a1, a0, 82 +; CHECK-NEXT: lbu a2, 1(a0) +; CHECK-NEXT: lbu a3, 44(a0) +; CHECK-NEXT: lbu a4, 55(a0) +; CHECK-NEXT: lbu a5, 75(a0) +; CHECK-NEXT: lbu a6, 93(a0) ; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma ; CHECK-NEXT: vlse8.v v8, (a0), zero -; CHECK-NEXT: addi a0, a0, 82 -; CHECK-NEXT: vslide1down.vx v8, v8, a1 -; CHECK-NEXT: vslidedown.vi v8, v8, 2 +; CHECK-NEXT: lbu a7, 124(a0) +; CHECK-NEXT: lbu t0, 144(a0) +; CHECK-NEXT: lbu a0, 154(a0) ; CHECK-NEXT: vslide1down.vx v8, v8, a2 -; CHECK-NEXT: vlse8.v v9, (a0), zero +; CHECK-NEXT: vslidedown.vi v8, v8, 2 ; CHECK-NEXT: vslide1down.vx v8, v8, a3 +; CHECK-NEXT: vlse8.v v9, (a1), zero +; CHECK-NEXT: vslide1down.vx v8, v8, a4 ; CHECK-NEXT: vslidedown.vi v8, v8, 1 -; CHECK-NEXT: vslide1down.vx v10, v8, a4 -; CHECK-NEXT: vslide1down.vx v8, v9, a5 +; CHECK-NEXT: vslide1down.vx v10, v8, a5 +; CHECK-NEXT: vslide1down.vx v8, v9, a6 ; CHECK-NEXT: vslidedown.vi v8, v8, 2 -; CHECK-NEXT: vslide1down.vx v8, v8, a6 -; CHECK-NEXT: vslidedown.vi v8, v8, 1 ; CHECK-NEXT: vslide1down.vx v8, v8, a7 +; CHECK-NEXT: vslidedown.vi v8, v8, 1 ; CHECK-NEXT: vslide1down.vx v8, v8, t0 +; CHECK-NEXT: vslide1down.vx v8, v8, a0 ; CHECK-NEXT: li a0, 255 ; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma ; CHECK-NEXT: vmv.s.x v0, a0 diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-interleaved-access-zve32x.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-interleaved-access-zve32x.ll index 8acc70faaa1f..eb95d86e3404 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-interleaved-access-zve32x.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-interleaved-access-zve32x.ll @@ -7,25 +7,23 @@ define <4 x i1> @load_large_vector(ptr %p) { ; ZVE32X-LABEL: load_large_vector: ; ZVE32X: # %bb.0: -; ZVE32X-NEXT: ld a1, 80(a0) -; ZVE32X-NEXT: ld a2, 72(a0) -; ZVE32X-NEXT: ld a3, 56(a0) -; ZVE32X-NEXT: ld a4, 32(a0) -; ZVE32X-NEXT: ld a5, 24(a0) -; ZVE32X-NEXT: ld a6, 48(a0) -; ZVE32X-NEXT: ld a7, 8(a0) -; ZVE32X-NEXT: ld a0, 0(a0) -; ZVE32X-NEXT: xor a4, a5, a4 -; ZVE32X-NEXT: snez a4, a4 +; ZVE32X-NEXT: ld a1, 56(a0) +; ZVE32X-NEXT: ld a2, 32(a0) +; ZVE32X-NEXT: ld a3, 24(a0) +; ZVE32X-NEXT: ld a4, 48(a0) +; ZVE32X-NEXT: ld a5, 8(a0) +; ZVE32X-NEXT: ld a6, 0(a0) +; ZVE32X-NEXT: xor a2, a3, a2 +; ZVE32X-NEXT: snez a2, a2 ; ZVE32X-NEXT: vsetivli zero, 1, e8, mf4, ta, ma -; ZVE32X-NEXT: vmv.s.x v8, a4 +; ZVE32X-NEXT: vmv.s.x v8, a2 ; ZVE32X-NEXT: vand.vi v8, v8, 1 ; ZVE32X-NEXT: vmsne.vi v0, v8, 0 ; ZVE32X-NEXT: vmv.s.x v8, zero ; ZVE32X-NEXT: vmerge.vim v9, v8, 1, v0 -; ZVE32X-NEXT: xor a0, a0, a7 -; ZVE32X-NEXT: snez a0, a0 -; ZVE32X-NEXT: vmv.s.x v10, a0 +; ZVE32X-NEXT: xor a2, a6, a5 +; ZVE32X-NEXT: snez a2, a2 +; ZVE32X-NEXT: vmv.s.x v10, a2 ; ZVE32X-NEXT: vand.vi v10, v10, 1 ; ZVE32X-NEXT: vmsne.vi v0, v10, 0 ; ZVE32X-NEXT: vsetivli zero, 4, e8, mf4, ta, ma @@ -35,21 +33,23 @@ define <4 x i1> @load_large_vector(ptr %p) { ; ZVE32X-NEXT: vslideup.vi v11, v9, 1 ; ZVE32X-NEXT: vsetivli zero, 4, e8, mf4, ta, ma ; ZVE32X-NEXT: vmsne.vi v0, v11, 0 +; ZVE32X-NEXT: ld a2, 80(a0) ; ZVE32X-NEXT: vmerge.vim v9, v10, 1, v0 -; ZVE32X-NEXT: xor a0, a6, a3 -; ZVE32X-NEXT: snez a0, a0 -; ZVE32X-NEXT: vmv.s.x v11, a0 +; ZVE32X-NEXT: xor a1, a4, a1 +; ZVE32X-NEXT: snez a1, a1 +; ZVE32X-NEXT: vmv.s.x v11, a1 ; ZVE32X-NEXT: vsetivli zero, 1, e8, mf4, ta, ma ; ZVE32X-NEXT: vand.vi v11, v11, 1 ; ZVE32X-NEXT: vmsne.vi v0, v11, 0 +; ZVE32X-NEXT: ld a0, 72(a0) ; ZVE32X-NEXT: vmerge.vim v11, v8, 1, v0 ; ZVE32X-NEXT: vsetivli zero, 3, e8, mf4, tu, ma ; ZVE32X-NEXT: vslideup.vi v9, v11, 2 ; ZVE32X-NEXT: vsetivli zero, 4, e8, mf4, ta, ma ; ZVE32X-NEXT: vmsne.vi v0, v9, 0 ; ZVE32X-NEXT: vmerge.vim v9, v10, 1, v0 -; ZVE32X-NEXT: xor a1, a2, a1 -; ZVE32X-NEXT: snez a0, a1 +; ZVE32X-NEXT: xor a0, a0, a2 +; ZVE32X-NEXT: snez a0, a0 ; ZVE32X-NEXT: vmv.s.x v10, a0 ; ZVE32X-NEXT: vsetivli zero, 1, e8, mf4, ta, ma ; ZVE32X-NEXT: vand.vi v10, v10, 1 diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-lrint.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-lrint.ll index 35baa6808db6..e2075e074179 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-lrint.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-lrint.ll @@ -812,14 +812,14 @@ define <8 x iXLen> @lrint_v8f64(<8 x double> %x) { ; RV32-NEXT: vslide1down.vx v10, v10, a0 ; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma ; RV32-NEXT: vslidedown.vi v8, v8, 3 -; RV32-NEXT: vfmv.f.s fa5, v8 -; RV32-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; RV32-NEXT: fld fa4, 32(sp) +; RV32-NEXT: fld fa5, 32(sp) +; RV32-NEXT: vfmv.f.s fa4, v8 ; RV32-NEXT: fld fa3, 40(sp) -; RV32-NEXT: fcvt.w.d a0, fa5 +; RV32-NEXT: fcvt.w.d a0, fa4 +; RV32-NEXT: fcvt.w.d a1, fa5 ; RV32-NEXT: fld fa5, 48(sp) -; RV32-NEXT: fcvt.w.d a1, fa4 ; RV32-NEXT: fcvt.w.d a2, fa3 +; RV32-NEXT: vsetivli zero, 8, e32, m2, ta, ma ; RV32-NEXT: vslide1down.vx v8, v10, a0 ; RV32-NEXT: fcvt.w.d a0, fa5 ; RV32-NEXT: fld fa5, 56(sp) @@ -865,14 +865,14 @@ define <8 x iXLen> @lrint_v8f64(<8 x double> %x) { ; RV64-i32-NEXT: vslide1down.vx v10, v10, a0 ; RV64-i32-NEXT: vsetivli zero, 1, e64, m2, ta, ma ; RV64-i32-NEXT: vslidedown.vi v8, v8, 3 -; RV64-i32-NEXT: vfmv.f.s fa5, v8 -; RV64-i32-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; RV64-i32-NEXT: fld fa4, 32(sp) +; RV64-i32-NEXT: fld fa5, 32(sp) +; RV64-i32-NEXT: vfmv.f.s fa4, v8 ; RV64-i32-NEXT: fld fa3, 40(sp) -; RV64-i32-NEXT: fcvt.l.d a0, fa5 +; RV64-i32-NEXT: fcvt.l.d a0, fa4 +; RV64-i32-NEXT: fcvt.l.d a1, fa5 ; RV64-i32-NEXT: fld fa5, 48(sp) -; RV64-i32-NEXT: fcvt.l.d a1, fa4 ; RV64-i32-NEXT: fcvt.l.d a2, fa3 +; RV64-i32-NEXT: vsetivli zero, 8, e32, m2, ta, ma ; RV64-i32-NEXT: vslide1down.vx v8, v10, a0 ; RV64-i32-NEXT: fcvt.l.d a0, fa5 ; RV64-i32-NEXT: fld fa5, 56(sp) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll index f42f32e24658..08cad29ab1b8 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll @@ -519,17 +519,17 @@ define <4 x i8> @mgather_truemask_v4i8(<4 x ptr> %ptrs, <4 x i8> %passthru) { ; RV64ZVE32F-LABEL: mgather_truemask_v4i8: ; RV64ZVE32F: # %bb.0: ; RV64ZVE32F-NEXT: ld a1, 8(a0) -; RV64ZVE32F-NEXT: ld a2, 16(a0) +; RV64ZVE32F-NEXT: ld a2, 0(a0) ; RV64ZVE32F-NEXT: ld a3, 24(a0) -; RV64ZVE32F-NEXT: ld a0, 0(a0) +; RV64ZVE32F-NEXT: ld a0, 16(a0) ; RV64ZVE32F-NEXT: lbu a1, 0(a1) -; RV64ZVE32F-NEXT: lbu a2, 0(a2) -; RV64ZVE32F-NEXT: lbu a3, 0(a3) ; RV64ZVE32F-NEXT: vsetivli zero, 4, e8, mf4, ta, ma -; RV64ZVE32F-NEXT: vlse8.v v8, (a0), zero +; RV64ZVE32F-NEXT: vlse8.v v8, (a2), zero +; RV64ZVE32F-NEXT: lbu a0, 0(a0) +; RV64ZVE32F-NEXT: lbu a2, 0(a3) ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a1 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 ; RV64ZVE32F-NEXT: ret %v = call <4 x i8> @llvm.masked.gather.v4i8.v4p0(<4 x ptr> %ptrs, i32 1, <4 x i1> splat (i1 1), <4 x i8> %passthru) ret <4 x i8> %v @@ -1208,17 +1208,17 @@ define <4 x i16> @mgather_truemask_v4i16(<4 x ptr> %ptrs, <4 x i16> %passthru) { ; RV64ZVE32F-LABEL: mgather_truemask_v4i16: ; RV64ZVE32F: # %bb.0: ; RV64ZVE32F-NEXT: ld a1, 8(a0) -; RV64ZVE32F-NEXT: ld a2, 16(a0) +; RV64ZVE32F-NEXT: ld a2, 0(a0) ; RV64ZVE32F-NEXT: ld a3, 24(a0) -; RV64ZVE32F-NEXT: ld a0, 0(a0) +; RV64ZVE32F-NEXT: ld a0, 16(a0) ; RV64ZVE32F-NEXT: lh a1, 0(a1) -; RV64ZVE32F-NEXT: lh a2, 0(a2) -; RV64ZVE32F-NEXT: lh a3, 0(a3) ; RV64ZVE32F-NEXT: vsetivli zero, 4, e16, mf2, ta, ma -; RV64ZVE32F-NEXT: vlse16.v v8, (a0), zero +; RV64ZVE32F-NEXT: vlse16.v v8, (a2), zero +; RV64ZVE32F-NEXT: lh a0, 0(a0) +; RV64ZVE32F-NEXT: lh a2, 0(a3) ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a1 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 ; RV64ZVE32F-NEXT: ret %v = call <4 x i16> @llvm.masked.gather.v4i16.v4p0(<4 x ptr> %ptrs, i32 2, <4 x i1> splat (i1 1), <4 x i16> %passthru) ret <4 x i16> %v @@ -2257,17 +2257,17 @@ define <4 x i32> @mgather_truemask_v4i32(<4 x ptr> %ptrs, <4 x i32> %passthru) { ; RV64ZVE32F-LABEL: mgather_truemask_v4i32: ; RV64ZVE32F: # %bb.0: ; RV64ZVE32F-NEXT: ld a1, 8(a0) -; RV64ZVE32F-NEXT: ld a2, 16(a0) +; RV64ZVE32F-NEXT: ld a2, 0(a0) ; RV64ZVE32F-NEXT: ld a3, 24(a0) -; RV64ZVE32F-NEXT: ld a0, 0(a0) +; RV64ZVE32F-NEXT: ld a0, 16(a0) ; RV64ZVE32F-NEXT: lw a1, 0(a1) -; RV64ZVE32F-NEXT: lw a2, 0(a2) -; RV64ZVE32F-NEXT: lw a3, 0(a3) ; RV64ZVE32F-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; RV64ZVE32F-NEXT: vlse32.v v8, (a0), zero +; RV64ZVE32F-NEXT: vlse32.v v8, (a2), zero +; RV64ZVE32F-NEXT: lw a0, 0(a0) +; RV64ZVE32F-NEXT: lw a2, 0(a3) ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a1 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 ; RV64ZVE32F-NEXT: ret %v = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %ptrs, i32 4, <4 x i1> splat (i1 1), <4 x i32> %passthru) ret <4 x i32> %v @@ -6589,16 +6589,16 @@ define <8 x i64> @mgather_baseidx_v8i64(ptr %base, <8 x i64> %idxs, <8 x i1> %m, ; RV32ZVE32F-NEXT: lw a4, 56(a2) ; RV32ZVE32F-NEXT: lw a5, 48(a2) ; RV32ZVE32F-NEXT: lw a6, 40(a2) -; RV32ZVE32F-NEXT: lw a7, 32(a2) -; RV32ZVE32F-NEXT: lw t0, 24(a2) -; RV32ZVE32F-NEXT: lw t1, 16(a2) -; RV32ZVE32F-NEXT: lw t2, 8(a2) +; RV32ZVE32F-NEXT: lw a7, 8(a2) ; RV32ZVE32F-NEXT: vsetivli zero, 8, e32, m2, ta, ma ; RV32ZVE32F-NEXT: vlse32.v v8, (a2), zero -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, t2 -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, t1 -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, t0 +; RV32ZVE32F-NEXT: lw t0, 16(a2) +; RV32ZVE32F-NEXT: lw t1, 24(a2) +; RV32ZVE32F-NEXT: lw a2, 32(a2) ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a7 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, t0 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, t1 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a2 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a6 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a5 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a4 @@ -7017,14 +7017,14 @@ define <4 x half> @mgather_truemask_v4f16(<4 x ptr> %ptrs, <4 x half> %passthru) ; RV64ZVE32F-LABEL: mgather_truemask_v4f16: ; RV64ZVE32F: # %bb.0: ; RV64ZVE32F-NEXT: ld a1, 8(a0) -; RV64ZVE32F-NEXT: ld a2, 16(a0) +; RV64ZVE32F-NEXT: ld a2, 0(a0) ; RV64ZVE32F-NEXT: ld a3, 24(a0) -; RV64ZVE32F-NEXT: ld a0, 0(a0) +; RV64ZVE32F-NEXT: ld a0, 16(a0) ; RV64ZVE32F-NEXT: flh fa5, 0(a1) -; RV64ZVE32F-NEXT: flh fa4, 0(a2) -; RV64ZVE32F-NEXT: flh fa3, 0(a3) ; RV64ZVE32F-NEXT: vsetivli zero, 4, e16, mf2, ta, ma -; RV64ZVE32F-NEXT: vlse16.v v8, (a0), zero +; RV64ZVE32F-NEXT: vlse16.v v8, (a2), zero +; RV64ZVE32F-NEXT: flh fa4, 0(a0) +; RV64ZVE32F-NEXT: flh fa3, 0(a3) ; RV64ZVE32F-NEXT: vfslide1down.vf v8, v8, fa5 ; RV64ZVE32F-NEXT: vfslide1down.vf v8, v8, fa4 ; RV64ZVE32F-NEXT: vfslide1down.vf v8, v8, fa3 @@ -7940,14 +7940,14 @@ define <4 x float> @mgather_truemask_v4f32(<4 x ptr> %ptrs, <4 x float> %passthr ; RV64ZVE32F-LABEL: mgather_truemask_v4f32: ; RV64ZVE32F: # %bb.0: ; RV64ZVE32F-NEXT: ld a1, 8(a0) -; RV64ZVE32F-NEXT: ld a2, 16(a0) +; RV64ZVE32F-NEXT: ld a2, 0(a0) ; RV64ZVE32F-NEXT: ld a3, 24(a0) -; RV64ZVE32F-NEXT: ld a0, 0(a0) +; RV64ZVE32F-NEXT: ld a0, 16(a0) ; RV64ZVE32F-NEXT: flw fa5, 0(a1) -; RV64ZVE32F-NEXT: flw fa4, 0(a2) -; RV64ZVE32F-NEXT: flw fa3, 0(a3) ; RV64ZVE32F-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; RV64ZVE32F-NEXT: vlse32.v v8, (a0), zero +; RV64ZVE32F-NEXT: vlse32.v v8, (a2), zero +; RV64ZVE32F-NEXT: flw fa4, 0(a0) +; RV64ZVE32F-NEXT: flw fa3, 0(a3) ; RV64ZVE32F-NEXT: vfslide1down.vf v8, v8, fa5 ; RV64ZVE32F-NEXT: vfslide1down.vf v8, v8, fa4 ; RV64ZVE32F-NEXT: vfslide1down.vf v8, v8, fa3 @@ -11632,16 +11632,16 @@ define <8 x double> @mgather_baseidx_v8f64(ptr %base, <8 x i64> %idxs, <8 x i1> ; RV32ZVE32F-NEXT: lw a3, 56(a2) ; RV32ZVE32F-NEXT: lw a4, 48(a2) ; RV32ZVE32F-NEXT: lw a5, 40(a2) -; RV32ZVE32F-NEXT: lw a6, 32(a2) -; RV32ZVE32F-NEXT: lw a7, 24(a2) -; RV32ZVE32F-NEXT: lw t0, 16(a2) -; RV32ZVE32F-NEXT: lw t1, 8(a2) +; RV32ZVE32F-NEXT: lw a6, 8(a2) ; RV32ZVE32F-NEXT: vsetivli zero, 8, e32, m2, ta, ma ; RV32ZVE32F-NEXT: vlse32.v v8, (a2), zero -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, t1 -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, t0 -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a7 +; RV32ZVE32F-NEXT: lw a7, 16(a2) +; RV32ZVE32F-NEXT: lw t0, 24(a2) +; RV32ZVE32F-NEXT: lw a2, 32(a2) ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a6 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a7 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, t0 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a2 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a5 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a4 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a3 @@ -12881,22 +12881,22 @@ define <8 x i16> @mgather_strided_2xSEW(ptr %base) { ; ; RV64ZVE32F-LABEL: mgather_strided_2xSEW: ; RV64ZVE32F: # %bb.0: -; RV64ZVE32F-NEXT: lh a1, 2(a0) -; RV64ZVE32F-NEXT: lh a2, 8(a0) -; RV64ZVE32F-NEXT: lh a3, 10(a0) -; RV64ZVE32F-NEXT: lh a4, 18(a0) -; RV64ZVE32F-NEXT: lh a5, 24(a0) -; RV64ZVE32F-NEXT: lh a6, 26(a0) +; RV64ZVE32F-NEXT: addi a1, a0, 16 +; RV64ZVE32F-NEXT: lh a2, 2(a0) +; RV64ZVE32F-NEXT: lh a3, 8(a0) +; RV64ZVE32F-NEXT: lh a4, 10(a0) +; RV64ZVE32F-NEXT: lh a5, 18(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 8, e16, m1, ta, mu ; RV64ZVE32F-NEXT: vlse16.v v8, (a0), zero -; RV64ZVE32F-NEXT: addi a0, a0, 16 -; RV64ZVE32F-NEXT: vlse16.v v9, (a0), zero -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a1 +; RV64ZVE32F-NEXT: lh a6, 24(a0) +; RV64ZVE32F-NEXT: lh a0, 26(a0) +; RV64ZVE32F-NEXT: vlse16.v v9, (a1), zero ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 -; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a3 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a4 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a5 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 +; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a4 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a5 ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a6 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vmv.v.i v0, 15 ; RV64ZVE32F-NEXT: vslidedown.vi v8, v10, 4, v0.t ; RV64ZVE32F-NEXT: ret @@ -12925,23 +12925,23 @@ define <8 x i16> @mgather_strided_2xSEW_with_offset(ptr %base) { ; ; RV64ZVE32F-LABEL: mgather_strided_2xSEW_with_offset: ; RV64ZVE32F: # %bb.0: -; RV64ZVE32F-NEXT: addi a1, a0, 4 -; RV64ZVE32F-NEXT: lh a2, 6(a0) -; RV64ZVE32F-NEXT: lh a3, 12(a0) -; RV64ZVE32F-NEXT: lh a4, 14(a0) -; RV64ZVE32F-NEXT: lh a5, 22(a0) -; RV64ZVE32F-NEXT: lh a6, 28(a0) -; RV64ZVE32F-NEXT: lh a7, 30(a0) +; RV64ZVE32F-NEXT: addi a1, a0, 20 +; RV64ZVE32F-NEXT: addi a2, a0, 4 +; RV64ZVE32F-NEXT: lh a3, 6(a0) +; RV64ZVE32F-NEXT: lh a4, 12(a0) +; RV64ZVE32F-NEXT: lh a5, 14(a0) +; RV64ZVE32F-NEXT: lh a6, 22(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 8, e16, m1, ta, mu -; RV64ZVE32F-NEXT: vlse16.v v8, (a1), zero -; RV64ZVE32F-NEXT: addi a0, a0, 20 -; RV64ZVE32F-NEXT: vlse16.v v9, (a0), zero -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 +; RV64ZVE32F-NEXT: vlse16.v v8, (a2), zero +; RV64ZVE32F-NEXT: lh a2, 28(a0) +; RV64ZVE32F-NEXT: lh a0, 30(a0) +; RV64ZVE32F-NEXT: vlse16.v v9, (a1), zero ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 -; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a4 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a5 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a6 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a7 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a4 +; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a5 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a6 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vmv.v.i v0, 15 ; RV64ZVE32F-NEXT: vslidedown.vi v8, v10, 4, v0.t ; RV64ZVE32F-NEXT: ret @@ -12970,23 +12970,23 @@ define <8 x i16> @mgather_reverse_unit_strided_2xSEW(ptr %base) { ; ; RV64ZVE32F-LABEL: mgather_reverse_unit_strided_2xSEW: ; RV64ZVE32F: # %bb.0: -; RV64ZVE32F-NEXT: addi a1, a0, 28 -; RV64ZVE32F-NEXT: lh a2, 30(a0) -; RV64ZVE32F-NEXT: lh a3, 24(a0) -; RV64ZVE32F-NEXT: lh a4, 26(a0) -; RV64ZVE32F-NEXT: lh a5, 22(a0) -; RV64ZVE32F-NEXT: lh a6, 16(a0) -; RV64ZVE32F-NEXT: lh a7, 18(a0) +; RV64ZVE32F-NEXT: addi a1, a0, 20 +; RV64ZVE32F-NEXT: addi a2, a0, 28 +; RV64ZVE32F-NEXT: lh a3, 30(a0) +; RV64ZVE32F-NEXT: lh a4, 24(a0) +; RV64ZVE32F-NEXT: lh a5, 26(a0) +; RV64ZVE32F-NEXT: lh a6, 22(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 8, e16, m1, ta, mu -; RV64ZVE32F-NEXT: vlse16.v v8, (a1), zero -; RV64ZVE32F-NEXT: addi a0, a0, 20 -; RV64ZVE32F-NEXT: vlse16.v v9, (a0), zero -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 +; RV64ZVE32F-NEXT: vlse16.v v8, (a2), zero +; RV64ZVE32F-NEXT: lh a2, 16(a0) +; RV64ZVE32F-NEXT: lh a0, 18(a0) +; RV64ZVE32F-NEXT: vlse16.v v9, (a1), zero ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 -; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a4 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a5 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a6 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a7 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a4 +; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a5 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a6 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vmv.v.i v0, 15 ; RV64ZVE32F-NEXT: vslidedown.vi v8, v10, 4, v0.t ; RV64ZVE32F-NEXT: ret @@ -13015,23 +13015,23 @@ define <8 x i16> @mgather_reverse_strided_2xSEW(ptr %base) { ; ; RV64ZVE32F-LABEL: mgather_reverse_strided_2xSEW: ; RV64ZVE32F: # %bb.0: -; RV64ZVE32F-NEXT: addi a1, a0, 28 -; RV64ZVE32F-NEXT: lh a2, 30(a0) -; RV64ZVE32F-NEXT: lh a3, 20(a0) -; RV64ZVE32F-NEXT: lh a4, 22(a0) -; RV64ZVE32F-NEXT: lh a5, 14(a0) -; RV64ZVE32F-NEXT: lh a6, 4(a0) -; RV64ZVE32F-NEXT: lh a7, 6(a0) +; RV64ZVE32F-NEXT: addi a1, a0, 12 +; RV64ZVE32F-NEXT: addi a2, a0, 28 +; RV64ZVE32F-NEXT: lh a3, 30(a0) +; RV64ZVE32F-NEXT: lh a4, 20(a0) +; RV64ZVE32F-NEXT: lh a5, 22(a0) +; RV64ZVE32F-NEXT: lh a6, 14(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 8, e16, m1, ta, mu -; RV64ZVE32F-NEXT: vlse16.v v8, (a1), zero -; RV64ZVE32F-NEXT: addi a0, a0, 12 -; RV64ZVE32F-NEXT: vlse16.v v9, (a0), zero -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 +; RV64ZVE32F-NEXT: vlse16.v v8, (a2), zero +; RV64ZVE32F-NEXT: lh a2, 4(a0) +; RV64ZVE32F-NEXT: lh a0, 6(a0) +; RV64ZVE32F-NEXT: vlse16.v v9, (a1), zero ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 -; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a4 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a5 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a6 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a7 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a4 +; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a5 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a6 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vmv.v.i v0, 15 ; RV64ZVE32F-NEXT: vslidedown.vi v8, v10, 4, v0.t ; RV64ZVE32F-NEXT: ret @@ -13059,22 +13059,22 @@ define <8 x i16> @mgather_gather_2xSEW(ptr %base) { ; ; RV64ZVE32F-LABEL: mgather_gather_2xSEW: ; RV64ZVE32F: # %bb.0: -; RV64ZVE32F-NEXT: lh a1, 2(a0) -; RV64ZVE32F-NEXT: lh a2, 16(a0) -; RV64ZVE32F-NEXT: lh a3, 18(a0) -; RV64ZVE32F-NEXT: lh a4, 10(a0) -; RV64ZVE32F-NEXT: lh a5, 4(a0) -; RV64ZVE32F-NEXT: lh a6, 6(a0) +; RV64ZVE32F-NEXT: addi a1, a0, 8 +; RV64ZVE32F-NEXT: lh a2, 2(a0) +; RV64ZVE32F-NEXT: lh a3, 16(a0) +; RV64ZVE32F-NEXT: lh a4, 18(a0) +; RV64ZVE32F-NEXT: lh a5, 10(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 8, e16, m1, ta, mu ; RV64ZVE32F-NEXT: vlse16.v v8, (a0), zero -; RV64ZVE32F-NEXT: addi a0, a0, 8 -; RV64ZVE32F-NEXT: vlse16.v v9, (a0), zero -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a1 +; RV64ZVE32F-NEXT: lh a6, 4(a0) +; RV64ZVE32F-NEXT: lh a0, 6(a0) +; RV64ZVE32F-NEXT: vlse16.v v9, (a1), zero ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 -; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a3 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a4 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a5 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 +; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a4 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a5 ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a6 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vmv.v.i v0, 15 ; RV64ZVE32F-NEXT: vslidedown.vi v8, v10, 4, v0.t ; RV64ZVE32F-NEXT: ret @@ -13105,22 +13105,22 @@ define <8 x i16> @mgather_gather_2xSEW_unaligned(ptr %base) { ; ; RV64ZVE32F-LABEL: mgather_gather_2xSEW_unaligned: ; RV64ZVE32F: # %bb.0: -; RV64ZVE32F-NEXT: lh a1, 2(a0) -; RV64ZVE32F-NEXT: lh a2, 18(a0) -; RV64ZVE32F-NEXT: lh a3, 20(a0) -; RV64ZVE32F-NEXT: lh a4, 10(a0) -; RV64ZVE32F-NEXT: lh a5, 4(a0) -; RV64ZVE32F-NEXT: lh a6, 6(a0) +; RV64ZVE32F-NEXT: addi a1, a0, 8 +; RV64ZVE32F-NEXT: lh a2, 2(a0) +; RV64ZVE32F-NEXT: lh a3, 18(a0) +; RV64ZVE32F-NEXT: lh a4, 20(a0) +; RV64ZVE32F-NEXT: lh a5, 10(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 8, e16, m1, ta, mu ; RV64ZVE32F-NEXT: vlse16.v v8, (a0), zero -; RV64ZVE32F-NEXT: addi a0, a0, 8 -; RV64ZVE32F-NEXT: vlse16.v v9, (a0), zero -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a1 +; RV64ZVE32F-NEXT: lh a6, 4(a0) +; RV64ZVE32F-NEXT: lh a0, 6(a0) +; RV64ZVE32F-NEXT: vlse16.v v9, (a1), zero ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 -; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a3 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a4 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a5 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 +; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a4 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a5 ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a6 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vmv.v.i v0, 15 ; RV64ZVE32F-NEXT: vslidedown.vi v8, v10, 4, v0.t ; RV64ZVE32F-NEXT: ret @@ -13152,22 +13152,22 @@ define <8 x i16> @mgather_gather_2xSEW_unaligned2(ptr %base) { ; ; RV64ZVE32F-LABEL: mgather_gather_2xSEW_unaligned2: ; RV64ZVE32F: # %bb.0: -; RV64ZVE32F-NEXT: addi a1, a0, 2 -; RV64ZVE32F-NEXT: lh a2, 4(a0) -; RV64ZVE32F-NEXT: lh a3, 18(a0) -; RV64ZVE32F-NEXT: lh a4, 20(a0) -; RV64ZVE32F-NEXT: lh a5, 10(a0) -; RV64ZVE32F-NEXT: lh a6, 6(a0) +; RV64ZVE32F-NEXT: addi a1, a0, 8 +; RV64ZVE32F-NEXT: addi a2, a0, 2 +; RV64ZVE32F-NEXT: lh a3, 4(a0) +; RV64ZVE32F-NEXT: lh a4, 18(a0) +; RV64ZVE32F-NEXT: lh a5, 20(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 8, e16, m1, ta, mu -; RV64ZVE32F-NEXT: vlse16.v v8, (a1), zero -; RV64ZVE32F-NEXT: addi a0, a0, 8 -; RV64ZVE32F-NEXT: vlse16.v v9, (a0), zero -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 +; RV64ZVE32F-NEXT: vlse16.v v8, (a2), zero +; RV64ZVE32F-NEXT: lh a2, 10(a0) +; RV64ZVE32F-NEXT: lh a0, 6(a0) +; RV64ZVE32F-NEXT: vlse16.v v9, (a1), zero ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 -; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a4 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a5 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a6 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a4 +; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a5 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a2 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vmv.v.i v0, 15 ; RV64ZVE32F-NEXT: vslidedown.vi v8, v10, 4, v0.t ; RV64ZVE32F-NEXT: ret @@ -13202,22 +13202,22 @@ define <8 x i16> @mgather_gather_4xSEW(ptr %base) { ; ; RV64ZVE32F-LABEL: mgather_gather_4xSEW: ; RV64ZVE32F: # %bb.0: -; RV64ZVE32F-NEXT: lh a1, 2(a0) -; RV64ZVE32F-NEXT: lh a2, 4(a0) -; RV64ZVE32F-NEXT: lh a3, 6(a0) -; RV64ZVE32F-NEXT: lh a4, 18(a0) -; RV64ZVE32F-NEXT: lh a5, 20(a0) -; RV64ZVE32F-NEXT: lh a6, 22(a0) +; RV64ZVE32F-NEXT: addi a1, a0, 16 +; RV64ZVE32F-NEXT: lh a2, 2(a0) +; RV64ZVE32F-NEXT: lh a3, 4(a0) +; RV64ZVE32F-NEXT: lh a4, 6(a0) +; RV64ZVE32F-NEXT: lh a5, 18(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 8, e16, m1, ta, mu ; RV64ZVE32F-NEXT: vlse16.v v8, (a0), zero -; RV64ZVE32F-NEXT: addi a0, a0, 16 -; RV64ZVE32F-NEXT: vlse16.v v9, (a0), zero -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a1 +; RV64ZVE32F-NEXT: lh a6, 20(a0) +; RV64ZVE32F-NEXT: lh a0, 22(a0) +; RV64ZVE32F-NEXT: vlse16.v v9, (a1), zero ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 -; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a3 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a4 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a5 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 +; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a4 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a5 ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a6 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vmv.v.i v0, 15 ; RV64ZVE32F-NEXT: vslidedown.vi v8, v10, 4, v0.t ; RV64ZVE32F-NEXT: ret @@ -13249,22 +13249,22 @@ define <8 x i16> @mgather_gather_4xSEW_partial_align(ptr %base) { ; ; RV64ZVE32F-LABEL: mgather_gather_4xSEW_partial_align: ; RV64ZVE32F: # %bb.0: -; RV64ZVE32F-NEXT: lh a1, 2(a0) -; RV64ZVE32F-NEXT: lh a2, 4(a0) -; RV64ZVE32F-NEXT: lh a3, 6(a0) -; RV64ZVE32F-NEXT: lh a4, 18(a0) -; RV64ZVE32F-NEXT: lh a5, 20(a0) -; RV64ZVE32F-NEXT: lh a6, 22(a0) +; RV64ZVE32F-NEXT: addi a1, a0, 16 +; RV64ZVE32F-NEXT: lh a2, 2(a0) +; RV64ZVE32F-NEXT: lh a3, 4(a0) +; RV64ZVE32F-NEXT: lh a4, 6(a0) +; RV64ZVE32F-NEXT: lh a5, 18(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 8, e16, m1, ta, mu ; RV64ZVE32F-NEXT: vlse16.v v8, (a0), zero -; RV64ZVE32F-NEXT: addi a0, a0, 16 -; RV64ZVE32F-NEXT: vlse16.v v9, (a0), zero -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a1 +; RV64ZVE32F-NEXT: lh a6, 20(a0) +; RV64ZVE32F-NEXT: lh a0, 22(a0) +; RV64ZVE32F-NEXT: vlse16.v v9, (a1), zero ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 -; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a3 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a4 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a5 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 +; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a4 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a5 ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a6 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vmv.v.i v0, 15 ; RV64ZVE32F-NEXT: vslidedown.vi v8, v10, 4, v0.t ; RV64ZVE32F-NEXT: ret @@ -13305,22 +13305,22 @@ define <8 x i16> @mgather_shuffle_rotate(ptr %base) { ; ; RV64ZVE32F-LABEL: mgather_shuffle_rotate: ; RV64ZVE32F: # %bb.0: -; RV64ZVE32F-NEXT: lh a1, 10(a0) -; RV64ZVE32F-NEXT: lh a2, 12(a0) -; RV64ZVE32F-NEXT: lh a3, 14(a0) -; RV64ZVE32F-NEXT: lh a4, 2(a0) -; RV64ZVE32F-NEXT: lh a5, 4(a0) -; RV64ZVE32F-NEXT: lh a6, 6(a0) +; RV64ZVE32F-NEXT: addi a1, a0, 8 +; RV64ZVE32F-NEXT: lh a2, 10(a0) +; RV64ZVE32F-NEXT: lh a3, 12(a0) +; RV64ZVE32F-NEXT: lh a4, 14(a0) +; RV64ZVE32F-NEXT: lh a5, 2(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 8, e16, m1, ta, mu ; RV64ZVE32F-NEXT: vlse16.v v8, (a0), zero -; RV64ZVE32F-NEXT: addi a0, a0, 8 -; RV64ZVE32F-NEXT: vlse16.v v9, (a0), zero -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a4 +; RV64ZVE32F-NEXT: lh a6, 4(a0) +; RV64ZVE32F-NEXT: lh a0, 6(a0) +; RV64ZVE32F-NEXT: vlse16.v v9, (a1), zero ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a5 ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a6 -; RV64ZVE32F-NEXT: vslide1down.vx v9, v9, a1 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vslide1down.vx v9, v9, a2 ; RV64ZVE32F-NEXT: vslide1down.vx v9, v9, a3 +; RV64ZVE32F-NEXT: vslide1down.vx v9, v9, a4 ; RV64ZVE32F-NEXT: vmv.v.i v0, 15 ; RV64ZVE32F-NEXT: vslidedown.vi v8, v9, 4, v0.t ; RV64ZVE32F-NEXT: ret @@ -13352,22 +13352,22 @@ define <8 x i16> @mgather_shuffle_vrgather(ptr %base) { ; ; RV64ZVE32F-LABEL: mgather_shuffle_vrgather: ; RV64ZVE32F: # %bb.0: -; RV64ZVE32F-NEXT: lh a1, 4(a0) -; RV64ZVE32F-NEXT: lh a2, 6(a0) -; RV64ZVE32F-NEXT: lh a3, 2(a0) -; RV64ZVE32F-NEXT: lh a4, 10(a0) -; RV64ZVE32F-NEXT: lh a5, 12(a0) -; RV64ZVE32F-NEXT: lh a6, 14(a0) +; RV64ZVE32F-NEXT: addi a1, a0, 8 +; RV64ZVE32F-NEXT: lh a2, 4(a0) +; RV64ZVE32F-NEXT: lh a3, 6(a0) +; RV64ZVE32F-NEXT: lh a4, 2(a0) +; RV64ZVE32F-NEXT: lh a5, 10(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 8, e16, m1, ta, mu ; RV64ZVE32F-NEXT: vlse16.v v8, (a0), zero -; RV64ZVE32F-NEXT: addi a0, a0, 8 -; RV64ZVE32F-NEXT: vlse16.v v9, (a0), zero -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a1 +; RV64ZVE32F-NEXT: lh a6, 12(a0) +; RV64ZVE32F-NEXT: lh a0, 14(a0) +; RV64ZVE32F-NEXT: vlse16.v v9, (a1), zero ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 -; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a3 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a4 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a5 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 +; RV64ZVE32F-NEXT: vslide1down.vx v10, v8, a4 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v9, a5 ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a6 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: vmv.v.i v0, 15 ; RV64ZVE32F-NEXT: vslidedown.vi v8, v10, 4, v0.t ; RV64ZVE32F-NEXT: ret @@ -13853,12 +13853,12 @@ define <4 x i32> @masked_gather_widen_sew_negative_stride(ptr %base) { ; RV64ZVE32F: # %bb.0: ; RV64ZVE32F-NEXT: addi a1, a0, 136 ; RV64ZVE32F-NEXT: lw a2, 140(a0) -; RV64ZVE32F-NEXT: lw a3, 0(a0) -; RV64ZVE32F-NEXT: lw a0, 4(a0) ; RV64ZVE32F-NEXT: vsetivli zero, 4, e32, m1, ta, ma ; RV64ZVE32F-NEXT: vlse32.v v8, (a1), zero +; RV64ZVE32F-NEXT: lw a1, 0(a0) +; RV64ZVE32F-NEXT: lw a0, 4(a0) ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a2 -; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a3 +; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a1 ; RV64ZVE32F-NEXT: vslide1down.vx v8, v8, a0 ; RV64ZVE32F-NEXT: ret %ptrs = getelementptr i32, ptr %base, <4 x i64> diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-scatter.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-scatter.ll index aa815e18ac10..42e52436a7da 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-scatter.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-scatter.ll @@ -5598,17 +5598,16 @@ define void @mscatter_baseidx_v8i64(<8 x i64> %val, ptr %base, <8 x i64> %idxs, ; ; RV32ZVE32F-LABEL: mscatter_baseidx_v8i64: ; RV32ZVE32F: # %bb.0: -; RV32ZVE32F-NEXT: addi sp, sp, -48 -; RV32ZVE32F-NEXT: .cfi_def_cfa_offset 48 -; RV32ZVE32F-NEXT: sw s0, 44(sp) # 4-byte Folded Spill -; RV32ZVE32F-NEXT: sw s1, 40(sp) # 4-byte Folded Spill -; RV32ZVE32F-NEXT: sw s2, 36(sp) # 4-byte Folded Spill -; RV32ZVE32F-NEXT: sw s3, 32(sp) # 4-byte Folded Spill -; RV32ZVE32F-NEXT: sw s4, 28(sp) # 4-byte Folded Spill -; RV32ZVE32F-NEXT: sw s5, 24(sp) # 4-byte Folded Spill -; RV32ZVE32F-NEXT: sw s6, 20(sp) # 4-byte Folded Spill -; RV32ZVE32F-NEXT: sw s7, 16(sp) # 4-byte Folded Spill -; RV32ZVE32F-NEXT: sw s8, 12(sp) # 4-byte Folded Spill +; RV32ZVE32F-NEXT: addi sp, sp, -32 +; RV32ZVE32F-NEXT: .cfi_def_cfa_offset 32 +; RV32ZVE32F-NEXT: sw s0, 28(sp) # 4-byte Folded Spill +; RV32ZVE32F-NEXT: sw s1, 24(sp) # 4-byte Folded Spill +; RV32ZVE32F-NEXT: sw s2, 20(sp) # 4-byte Folded Spill +; RV32ZVE32F-NEXT: sw s3, 16(sp) # 4-byte Folded Spill +; RV32ZVE32F-NEXT: sw s4, 12(sp) # 4-byte Folded Spill +; RV32ZVE32F-NEXT: sw s5, 8(sp) # 4-byte Folded Spill +; RV32ZVE32F-NEXT: sw s6, 4(sp) # 4-byte Folded Spill +; RV32ZVE32F-NEXT: sw s7, 0(sp) # 4-byte Folded Spill ; RV32ZVE32F-NEXT: .cfi_offset s0, -4 ; RV32ZVE32F-NEXT: .cfi_offset s1, -8 ; RV32ZVE32F-NEXT: .cfi_offset s2, -12 @@ -5617,7 +5616,6 @@ define void @mscatter_baseidx_v8i64(<8 x i64> %val, ptr %base, <8 x i64> %idxs, ; RV32ZVE32F-NEXT: .cfi_offset s5, -24 ; RV32ZVE32F-NEXT: .cfi_offset s6, -28 ; RV32ZVE32F-NEXT: .cfi_offset s7, -32 -; RV32ZVE32F-NEXT: .cfi_offset s8, -36 ; RV32ZVE32F-NEXT: lw a3, 60(a0) ; RV32ZVE32F-NEXT: lw a4, 56(a0) ; RV32ZVE32F-NEXT: lw a5, 52(a0) @@ -5635,16 +5633,16 @@ define void @mscatter_baseidx_v8i64(<8 x i64> %val, ptr %base, <8 x i64> %idxs, ; RV32ZVE32F-NEXT: lw s2, 56(a2) ; RV32ZVE32F-NEXT: lw s3, 48(a2) ; RV32ZVE32F-NEXT: lw s4, 40(a2) -; RV32ZVE32F-NEXT: lw s5, 32(a2) -; RV32ZVE32F-NEXT: lw s6, 24(a2) -; RV32ZVE32F-NEXT: lw s7, 16(a2) -; RV32ZVE32F-NEXT: lw s8, 8(a2) +; RV32ZVE32F-NEXT: lw s5, 8(a2) ; RV32ZVE32F-NEXT: vsetivli zero, 8, e32, m2, ta, ma ; RV32ZVE32F-NEXT: vlse32.v v8, (a2), zero -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, s8 -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, s7 -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, s6 +; RV32ZVE32F-NEXT: lw s6, 16(a2) +; RV32ZVE32F-NEXT: lw s7, 24(a2) +; RV32ZVE32F-NEXT: lw a2, 32(a2) ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, s5 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, s6 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, s7 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a2 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, s4 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, s3 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, s2 @@ -5682,16 +5680,15 @@ define void @mscatter_baseidx_v8i64(<8 x i64> %val, ptr %base, <8 x i64> %idxs, ; RV32ZVE32F-NEXT: sw a4, 0(a0) ; RV32ZVE32F-NEXT: sw a3, 4(a0) ; RV32ZVE32F-NEXT: .LBB51_9: # %else14 -; RV32ZVE32F-NEXT: lw s0, 44(sp) # 4-byte Folded Reload -; RV32ZVE32F-NEXT: lw s1, 40(sp) # 4-byte Folded Reload -; RV32ZVE32F-NEXT: lw s2, 36(sp) # 4-byte Folded Reload -; RV32ZVE32F-NEXT: lw s3, 32(sp) # 4-byte Folded Reload -; RV32ZVE32F-NEXT: lw s4, 28(sp) # 4-byte Folded Reload -; RV32ZVE32F-NEXT: lw s5, 24(sp) # 4-byte Folded Reload -; RV32ZVE32F-NEXT: lw s6, 20(sp) # 4-byte Folded Reload -; RV32ZVE32F-NEXT: lw s7, 16(sp) # 4-byte Folded Reload -; RV32ZVE32F-NEXT: lw s8, 12(sp) # 4-byte Folded Reload -; RV32ZVE32F-NEXT: addi sp, sp, 48 +; RV32ZVE32F-NEXT: lw s0, 28(sp) # 4-byte Folded Reload +; RV32ZVE32F-NEXT: lw s1, 24(sp) # 4-byte Folded Reload +; RV32ZVE32F-NEXT: lw s2, 20(sp) # 4-byte Folded Reload +; RV32ZVE32F-NEXT: lw s3, 16(sp) # 4-byte Folded Reload +; RV32ZVE32F-NEXT: lw s4, 12(sp) # 4-byte Folded Reload +; RV32ZVE32F-NEXT: lw s5, 8(sp) # 4-byte Folded Reload +; RV32ZVE32F-NEXT: lw s6, 4(sp) # 4-byte Folded Reload +; RV32ZVE32F-NEXT: lw s7, 0(sp) # 4-byte Folded Reload +; RV32ZVE32F-NEXT: addi sp, sp, 32 ; RV32ZVE32F-NEXT: ret ; RV32ZVE32F-NEXT: .LBB51_10: # %cond.store ; RV32ZVE32F-NEXT: lw a2, 4(a0) @@ -10227,16 +10224,16 @@ define void @mscatter_baseidx_v8f64(<8 x double> %val, ptr %base, <8 x i64> %idx ; RV32ZVE32F-NEXT: lw a2, 56(a1) ; RV32ZVE32F-NEXT: lw a3, 48(a1) ; RV32ZVE32F-NEXT: lw a4, 40(a1) -; RV32ZVE32F-NEXT: lw a5, 32(a1) -; RV32ZVE32F-NEXT: lw a6, 24(a1) -; RV32ZVE32F-NEXT: lw a7, 16(a1) -; RV32ZVE32F-NEXT: lw t0, 8(a1) +; RV32ZVE32F-NEXT: lw a5, 8(a1) ; RV32ZVE32F-NEXT: vsetivli zero, 8, e32, m2, ta, ma ; RV32ZVE32F-NEXT: vlse32.v v8, (a1), zero -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, t0 -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a7 -; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a6 +; RV32ZVE32F-NEXT: lw a6, 16(a1) +; RV32ZVE32F-NEXT: lw a7, 24(a1) +; RV32ZVE32F-NEXT: lw a1, 32(a1) ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a5 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a6 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a7 +; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a1 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a4 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a3 ; RV32ZVE32F-NEXT: vslide1down.vx v8, v8, a2 diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-nearbyint-vp.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-nearbyint-vp.ll index 19f3d3ce19fa..7be015e26b09 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-nearbyint-vp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-nearbyint-vp.ll @@ -19,9 +19,9 @@ define <2 x half> @vp_nearbyint_v2f16(<2 x half> %va, <2 x i1> %m, i32 zeroext % ; CHECK-NEXT: vsetvli zero, zero, e16, mf4, ta, ma ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, mf4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <2 x half> @llvm.vp.nearbyint.v2f16(<2 x half> %va, <2 x i1> %m, i32 %evl) ret <2 x half> %v @@ -38,9 +38,9 @@ define <2 x half> @vp_nearbyint_v2f16_unmasked(<2 x half> %va, i32 zeroext %evl) ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, mf4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <2 x half> @llvm.vp.nearbyint.v2f16(<2 x half> %va, <2 x i1> splat (i1 true), i32 %evl) ret <2 x half> %v @@ -61,9 +61,9 @@ define <4 x half> @vp_nearbyint_v4f16(<4 x half> %va, <4 x i1> %m, i32 zeroext % ; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, ma ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <4 x half> @llvm.vp.nearbyint.v4f16(<4 x half> %va, <4 x i1> %m, i32 %evl) ret <4 x half> %v @@ -80,9 +80,9 @@ define <4 x half> @vp_nearbyint_v4f16_unmasked(<4 x half> %va, i32 zeroext %evl) ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <4 x half> @llvm.vp.nearbyint.v4f16(<4 x half> %va, <4 x i1> splat (i1 true), i32 %evl) ret <4 x half> %v @@ -103,9 +103,9 @@ define <8 x half> @vp_nearbyint_v8f16(<8 x half> %va, <8 x i1> %m, i32 zeroext % ; CHECK-NEXT: vsetvli zero, zero, e16, m1, ta, ma ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <8 x half> @llvm.vp.nearbyint.v8f16(<8 x half> %va, <8 x i1> %m, i32 %evl) ret <8 x half> %v @@ -122,9 +122,9 @@ define <8 x half> @vp_nearbyint_v8f16_unmasked(<8 x half> %va, i32 zeroext %evl) ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <8 x half> @llvm.vp.nearbyint.v8f16(<8 x half> %va, <8 x i1> splat (i1 true), i32 %evl) ret <8 x half> %v @@ -147,9 +147,9 @@ define <16 x half> @vp_nearbyint_v16f16(<16 x half> %va, <16 x i1> %m, i32 zeroe ; CHECK-NEXT: vmv1r.v v0, v10 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <16 x half> @llvm.vp.nearbyint.v16f16(<16 x half> %va, <16 x i1> %m, i32 %evl) ret <16 x half> %v @@ -166,9 +166,9 @@ define <16 x half> @vp_nearbyint_v16f16_unmasked(<16 x half> %va, i32 zeroext %e ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <16 x half> @llvm.vp.nearbyint.v16f16(<16 x half> %va, <16 x i1> splat (i1 true), i32 %evl) ret <16 x half> %v @@ -189,9 +189,9 @@ define <2 x float> @vp_nearbyint_v2f32(<2 x float> %va, <2 x i1> %m, i32 zeroext ; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <2 x float> @llvm.vp.nearbyint.v2f32(<2 x float> %va, <2 x i1> %m, i32 %evl) ret <2 x float> %v @@ -208,9 +208,9 @@ define <2 x float> @vp_nearbyint_v2f32_unmasked(<2 x float> %va, i32 zeroext %ev ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <2 x float> @llvm.vp.nearbyint.v2f32(<2 x float> %va, <2 x i1> splat (i1 true), i32 %evl) ret <2 x float> %v @@ -231,9 +231,9 @@ define <4 x float> @vp_nearbyint_v4f32(<4 x float> %va, <4 x i1> %m, i32 zeroext ; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <4 x float> @llvm.vp.nearbyint.v4f32(<4 x float> %va, <4 x i1> %m, i32 %evl) ret <4 x float> %v @@ -250,9 +250,9 @@ define <4 x float> @vp_nearbyint_v4f32_unmasked(<4 x float> %va, i32 zeroext %ev ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <4 x float> @llvm.vp.nearbyint.v4f32(<4 x float> %va, <4 x i1> splat (i1 true), i32 %evl) ret <4 x float> %v @@ -275,9 +275,9 @@ define <8 x float> @vp_nearbyint_v8f32(<8 x float> %va, <8 x i1> %m, i32 zeroext ; CHECK-NEXT: vmv1r.v v0, v10 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <8 x float> @llvm.vp.nearbyint.v8f32(<8 x float> %va, <8 x i1> %m, i32 %evl) ret <8 x float> %v @@ -294,9 +294,9 @@ define <8 x float> @vp_nearbyint_v8f32_unmasked(<8 x float> %va, i32 zeroext %ev ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <8 x float> @llvm.vp.nearbyint.v8f32(<8 x float> %va, <8 x i1> splat (i1 true), i32 %evl) ret <8 x float> %v @@ -319,9 +319,9 @@ define <16 x float> @vp_nearbyint_v16f32(<16 x float> %va, <16 x i1> %m, i32 zer ; CHECK-NEXT: vmv1r.v v0, v12 ; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v16, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <16 x float> @llvm.vp.nearbyint.v16f32(<16 x float> %va, <16 x i1> %m, i32 %evl) ret <16 x float> %v @@ -338,9 +338,9 @@ define <16 x float> @vp_nearbyint_v16f32_unmasked(<16 x float> %va, i32 zeroext ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <16 x float> @llvm.vp.nearbyint.v16f32(<16 x float> %va, <16 x i1> splat (i1 true), i32 %evl) ret <16 x float> %v @@ -361,9 +361,9 @@ define <2 x double> @vp_nearbyint_v2f64(<2 x double> %va, <2 x i1> %m, i32 zeroe ; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <2 x double> @llvm.vp.nearbyint.v2f64(<2 x double> %va, <2 x i1> %m, i32 %evl) ret <2 x double> %v @@ -380,9 +380,9 @@ define <2 x double> @vp_nearbyint_v2f64_unmasked(<2 x double> %va, i32 zeroext % ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <2 x double> @llvm.vp.nearbyint.v2f64(<2 x double> %va, <2 x i1> splat (i1 true), i32 %evl) ret <2 x double> %v @@ -405,9 +405,9 @@ define <4 x double> @vp_nearbyint_v4f64(<4 x double> %va, <4 x i1> %m, i32 zeroe ; CHECK-NEXT: vmv1r.v v0, v10 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <4 x double> @llvm.vp.nearbyint.v4f64(<4 x double> %va, <4 x i1> %m, i32 %evl) ret <4 x double> %v @@ -424,9 +424,9 @@ define <4 x double> @vp_nearbyint_v4f64_unmasked(<4 x double> %va, i32 zeroext % ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <4 x double> @llvm.vp.nearbyint.v4f64(<4 x double> %va, <4 x i1> splat (i1 true), i32 %evl) ret <4 x double> %v @@ -449,9 +449,9 @@ define <8 x double> @vp_nearbyint_v8f64(<8 x double> %va, <8 x i1> %m, i32 zeroe ; CHECK-NEXT: vmv1r.v v0, v12 ; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v16, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <8 x double> @llvm.vp.nearbyint.v8f64(<8 x double> %va, <8 x i1> %m, i32 %evl) ret <8 x double> %v @@ -468,9 +468,9 @@ define <8 x double> @vp_nearbyint_v8f64_unmasked(<8 x double> %va, i32 zeroext % ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <8 x double> @llvm.vp.nearbyint.v8f64(<8 x double> %va, <8 x i1> splat (i1 true), i32 %evl) ret <8 x double> %v @@ -493,9 +493,9 @@ define <15 x double> @vp_nearbyint_v15f64(<15 x double> %va, <15 x i1> %m, i32 z ; CHECK-NEXT: vmv1r.v v0, v16 ; CHECK-NEXT: vfcvt.x.f.v v24, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v24, v24, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v24, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <15 x double> @llvm.vp.nearbyint.v15f64(<15 x double> %va, <15 x i1> %m, i32 %evl) ret <15 x double> %v @@ -512,9 +512,9 @@ define <15 x double> @vp_nearbyint_v15f64_unmasked(<15 x double> %va, i32 zeroex ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v16, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <15 x double> @llvm.vp.nearbyint.v15f64(<15 x double> %va, <15 x i1> splat (i1 true), i32 %evl) ret <15 x double> %v @@ -537,9 +537,9 @@ define <16 x double> @vp_nearbyint_v16f64(<16 x double> %va, <16 x i1> %m, i32 z ; CHECK-NEXT: vmv1r.v v0, v16 ; CHECK-NEXT: vfcvt.x.f.v v24, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v24, v24, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v24, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <16 x double> @llvm.vp.nearbyint.v16f64(<16 x double> %va, <16 x i1> %m, i32 %evl) ret <16 x double> %v @@ -556,9 +556,9 @@ define <16 x double> @vp_nearbyint_v16f64_unmasked(<16 x double> %va, i32 zeroex ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v16, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <16 x double> @llvm.vp.nearbyint.v16f64(<16 x double> %va, <16 x i1> splat (i1 true), i32 %evl) ret <16 x double> %v @@ -617,9 +617,9 @@ define <32 x double> @vp_nearbyint_v32f64(<32 x double> %va, <32 x i1> %m, i32 z ; CHECK-NEXT: vmv1r.v v0, v7 ; CHECK-NEXT: vfcvt.x.f.v v16, v24, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v24, v16, v24, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vmv.v.v v16, v24 ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 @@ -660,9 +660,9 @@ define <32 x double> @vp_nearbyint_v32f64_unmasked(<32 x double> %va, i32 zeroex ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v24, v16, v0.t ; CHECK-NEXT: vfcvt.f.x.v v24, v24, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v16, v24, v16, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call <32 x double> @llvm.vp.nearbyint.v32f64(<32 x double> %va, <32 x i1> splat (i1 true), i32 %evl) ret <32 x double> %v diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vselect.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vselect.ll index 7dcd4c419982..ed2ed2a2ebfa 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vselect.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vselect.ll @@ -5,8 +5,8 @@ define void @vselect_vv_v6i32(ptr %a, ptr %b, ptr %cc, ptr %z) { ; RV32-LABEL: vselect_vv_v6i32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: lbu a2, 0(a2) +; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: vle32.v v8, (a1) ; RV32-NEXT: slli a1, a2, 30 ; RV32-NEXT: srli a1, a1, 31 @@ -35,8 +35,8 @@ define void @vselect_vv_v6i32(ptr %a, ptr %b, ptr %cc, ptr %z) { ; ; RV64-LABEL: vselect_vv_v6i32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: lbu a2, 0(a2) +; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: vle32.v v8, (a1) ; RV64-NEXT: slli a1, a2, 62 ; RV64-NEXT: srli a1, a1, 63 @@ -73,8 +73,8 @@ define void @vselect_vv_v6i32(ptr %a, ptr %b, ptr %cc, ptr %z) { define void @vselect_vx_v6i32(i32 %a, ptr %b, ptr %cc, ptr %z) { ; RV32-LABEL: vselect_vx_v6i32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: lbu a2, 0(a2) +; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: vle32.v v8, (a1) ; RV32-NEXT: slli a1, a2, 30 ; RV32-NEXT: srli a1, a1, 31 @@ -104,8 +104,8 @@ define void @vselect_vx_v6i32(i32 %a, ptr %b, ptr %cc, ptr %z) { ; ; RV64-LABEL: vselect_vx_v6i32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: lbu a2, 0(a2) +; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: vle32.v v8, (a1) ; RV64-NEXT: slli a1, a2, 62 ; RV64-NEXT: srli a1, a1, 63 @@ -144,8 +144,8 @@ define void @vselect_vx_v6i32(i32 %a, ptr %b, ptr %cc, ptr %z) { define void @vselect_vi_v6i32(ptr %b, ptr %cc, ptr %z) { ; RV32-LABEL: vselect_vi_v6i32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: lbu a1, 0(a1) +; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: vle32.v v8, (a0) ; RV32-NEXT: slli a0, a1, 30 ; RV32-NEXT: srli a0, a0, 31 @@ -175,8 +175,8 @@ define void @vselect_vi_v6i32(ptr %b, ptr %cc, ptr %z) { ; ; RV64-LABEL: vselect_vi_v6i32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: lbu a1, 0(a1) +; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: vle32.v v8, (a0) ; RV64-NEXT: slli a0, a1, 62 ; RV64-NEXT: srli a0, a0, 63 @@ -214,8 +214,8 @@ define void @vselect_vi_v6i32(ptr %b, ptr %cc, ptr %z) { define void @vselect_vv_v6f32(ptr %a, ptr %b, ptr %cc, ptr %z) { ; RV32-LABEL: vselect_vv_v6f32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: lbu a2, 0(a2) +; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: vle32.v v8, (a1) ; RV32-NEXT: slli a1, a2, 30 ; RV32-NEXT: srli a1, a1, 31 @@ -244,8 +244,8 @@ define void @vselect_vv_v6f32(ptr %a, ptr %b, ptr %cc, ptr %z) { ; ; RV64-LABEL: vselect_vv_v6f32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: lbu a2, 0(a2) +; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: vle32.v v8, (a1) ; RV64-NEXT: slli a1, a2, 62 ; RV64-NEXT: srli a1, a1, 63 @@ -282,8 +282,8 @@ define void @vselect_vv_v6f32(ptr %a, ptr %b, ptr %cc, ptr %z) { define void @vselect_vx_v6f32(float %a, ptr %b, ptr %cc, ptr %z) { ; RV32-LABEL: vselect_vx_v6f32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: lbu a1, 0(a1) +; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: vle32.v v8, (a0) ; RV32-NEXT: slli a0, a1, 30 ; RV32-NEXT: srli a0, a0, 31 @@ -313,8 +313,8 @@ define void @vselect_vx_v6f32(float %a, ptr %b, ptr %cc, ptr %z) { ; ; RV64-LABEL: vselect_vx_v6f32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: lbu a1, 0(a1) +; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: vle32.v v8, (a0) ; RV64-NEXT: slli a0, a1, 62 ; RV64-NEXT: srli a0, a0, 63 @@ -353,8 +353,8 @@ define void @vselect_vx_v6f32(float %a, ptr %b, ptr %cc, ptr %z) { define void @vselect_vfpzero_v6f32(ptr %b, ptr %cc, ptr %z) { ; RV32-LABEL: vselect_vfpzero_v6f32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: lbu a1, 0(a1) +; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV32-NEXT: vle32.v v8, (a0) ; RV32-NEXT: slli a0, a1, 30 ; RV32-NEXT: srli a0, a0, 31 @@ -384,8 +384,8 @@ define void @vselect_vfpzero_v6f32(ptr %b, ptr %cc, ptr %z) { ; ; RV64-LABEL: vselect_vfpzero_v6f32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: lbu a1, 0(a1) +; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma ; RV64-NEXT: vle32.v v8, (a0) ; RV64-NEXT: slli a0, a1, 62 ; RV64-NEXT: srli a0, a0, 63 diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwadd.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwadd.ll index a4a5917fd4f9..b1726be941e3 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwadd.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwadd.ll @@ -768,8 +768,8 @@ define <4 x i32> @vwadd_vx_v4i32_i32(ptr %x, ptr %y) { define <2 x i64> @vwadd_vx_v2i64_i8(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwadd_vx_v2i64_i8: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: lb a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: vmv.v.x v8, a1 ; RV32-NEXT: vsetvli zero, zero, e32, mf2, ta, ma @@ -796,8 +796,8 @@ define <2 x i64> @vwadd_vx_v2i64_i8(ptr %x, ptr %y) nounwind { define <2 x i64> @vwadd_vx_v2i64_i16(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwadd_vx_v2i64_i16: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: lh a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: vmv.v.x v8, a1 ; RV32-NEXT: vsetvli zero, zero, e32, mf2, ta, ma @@ -824,8 +824,8 @@ define <2 x i64> @vwadd_vx_v2i64_i16(ptr %x, ptr %y) nounwind { define <2 x i64> @vwadd_vx_v2i64_i32(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwadd_vx_v2i64_i32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: lw a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: vmv.v.x v8, a1 ; RV32-NEXT: vsetvli zero, zero, e32, mf2, ta, ma @@ -853,9 +853,9 @@ define <2 x i64> @vwadd_vx_v2i64_i64(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwadd_vx_v2i64_i64: ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 -; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: lw a2, 4(a1) ; RV32-NEXT: lw a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: sw a2, 12(sp) ; RV32-NEXT: sw a1, 8(sp) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwaddu.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwaddu.ll index bc0bf5dd76ad..f6d9695c5149 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwaddu.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwaddu.ll @@ -769,8 +769,8 @@ define <2 x i64> @vwaddu_vx_v2i64_i8(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwaddu_vx_v2i64_i8: ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 -; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: lbu a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: sw zero, 12(sp) ; RV32-NEXT: sw a1, 8(sp) @@ -801,8 +801,8 @@ define <2 x i64> @vwaddu_vx_v2i64_i16(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwaddu_vx_v2i64_i16: ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 -; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: lhu a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: sw zero, 12(sp) ; RV32-NEXT: sw a1, 8(sp) @@ -833,8 +833,8 @@ define <2 x i64> @vwaddu_vx_v2i64_i32(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwaddu_vx_v2i64_i32: ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 -; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: lw a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: sw zero, 12(sp) ; RV32-NEXT: sw a1, 8(sp) @@ -865,9 +865,9 @@ define <2 x i64> @vwaddu_vx_v2i64_i64(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwaddu_vx_v2i64_i64: ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 -; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: lw a2, 4(a1) ; RV32-NEXT: lw a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: sw a2, 12(sp) ; RV32-NEXT: sw a1, 8(sp) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmul.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmul.ll index 2abd34f01c14..c87584ab6351 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmul.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmul.ll @@ -883,9 +883,9 @@ define <2 x i64> @vwmul_vx_v2i64_i64(ptr %x, ptr %y) { ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 ; RV32-NEXT: .cfi_def_cfa_offset 16 -; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: lw a2, 4(a1) ; RV32-NEXT: lw a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: vle32.v v8, (a0) ; RV32-NEXT: sw a2, 12(sp) ; RV32-NEXT: sw a1, 8(sp) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulsu.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulsu.ll index 921037db2ea9..a56984577ea7 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulsu.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulsu.ll @@ -793,8 +793,8 @@ define <2 x i64> @vwmulsu_vx_v2i64_i8(ptr %x, ptr %y) { ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 ; RV32-NEXT: .cfi_def_cfa_offset 16 -; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: lbu a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: vle32.v v8, (a0) ; RV32-NEXT: sw zero, 12(sp) ; RV32-NEXT: sw a1, 8(sp) @@ -827,8 +827,8 @@ define <2 x i64> @vwmulsu_vx_v2i64_i16(ptr %x, ptr %y) { ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 ; RV32-NEXT: .cfi_def_cfa_offset 16 -; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: lhu a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: vle32.v v8, (a0) ; RV32-NEXT: sw zero, 12(sp) ; RV32-NEXT: sw a1, 8(sp) @@ -861,8 +861,8 @@ define <2 x i64> @vwmulsu_vx_v2i64_i32(ptr %x, ptr %y) { ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 ; RV32-NEXT: .cfi_def_cfa_offset 16 -; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: lw a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: vle32.v v8, (a0) ; RV32-NEXT: sw zero, 12(sp) ; RV32-NEXT: sw a1, 8(sp) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwsub.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwsub.ll index 154093d759d6..2782a5fbb1ea 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwsub.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwsub.ll @@ -769,8 +769,8 @@ define <4 x i32> @vwsub_vx_v4i32_i32(ptr %x, ptr %y) { define <2 x i64> @vwsub_vx_v2i64_i8(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwsub_vx_v2i64_i8: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: lb a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: vmv.v.x v8, a1 ; RV32-NEXT: vsetvli zero, zero, e32, mf2, ta, ma @@ -798,8 +798,8 @@ define <2 x i64> @vwsub_vx_v2i64_i8(ptr %x, ptr %y) nounwind { define <2 x i64> @vwsub_vx_v2i64_i16(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwsub_vx_v2i64_i16: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: lh a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: vmv.v.x v8, a1 ; RV32-NEXT: vsetvli zero, zero, e32, mf2, ta, ma @@ -827,8 +827,8 @@ define <2 x i64> @vwsub_vx_v2i64_i16(ptr %x, ptr %y) nounwind { define <2 x i64> @vwsub_vx_v2i64_i32(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwsub_vx_v2i64_i32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: lw a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: vmv.v.x v8, a1 ; RV32-NEXT: vsetvli zero, zero, e32, mf2, ta, ma @@ -856,9 +856,9 @@ define <2 x i64> @vwsub_vx_v2i64_i64(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwsub_vx_v2i64_i64: ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 -; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: lw a2, 4(a1) ; RV32-NEXT: lw a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: sw a2, 12(sp) ; RV32-NEXT: sw a1, 8(sp) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwsubu.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwsubu.ll index a084b5383b40..ccbc26c84d80 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwsubu.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwsubu.ll @@ -770,8 +770,8 @@ define <2 x i64> @vwsubu_vx_v2i64_i8(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwsubu_vx_v2i64_i8: ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 -; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: lbu a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: sw zero, 12(sp) ; RV32-NEXT: sw a1, 8(sp) @@ -803,8 +803,8 @@ define <2 x i64> @vwsubu_vx_v2i64_i16(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwsubu_vx_v2i64_i16: ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 -; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: lhu a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: sw zero, 12(sp) ; RV32-NEXT: sw a1, 8(sp) @@ -836,8 +836,8 @@ define <2 x i64> @vwsubu_vx_v2i64_i32(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwsubu_vx_v2i64_i32: ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 -; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: lw a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: sw zero, 12(sp) ; RV32-NEXT: sw a1, 8(sp) @@ -868,9 +868,9 @@ define <2 x i64> @vwsubu_vx_v2i64_i64(ptr %x, ptr %y) nounwind { ; RV32-LABEL: vwsubu_vx_v2i64_i64: ; RV32: # %bb.0: ; RV32-NEXT: addi sp, sp, -16 -; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: lw a2, 4(a1) ; RV32-NEXT: lw a1, 0(a1) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; RV32-NEXT: vle32.v v9, (a0) ; RV32-NEXT: sw a2, 12(sp) ; RV32-NEXT: sw a1, 8(sp) diff --git a/llvm/test/CodeGen/RISCV/rvv/fmaximum-vp.ll b/llvm/test/CodeGen/RISCV/rvv/fmaximum-vp.ll index b78b8663eac9..02cfd3de6b4d 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fmaximum-vp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fmaximum-vp.ll @@ -1012,77 +1012,99 @@ define @vfmax_vv_nxv16f64( %va, @vfmax_vv_nxv16f64( %va, @vfmax_vv_nxv16f64_unmasked( ; CHECK-NEXT: slli a3, a1, 3 ; CHECK-NEXT: add a3, a0, a3 ; CHECK-NEXT: vl8re64.v v24, (a3) +; CHECK-NEXT: sub a3, a2, a1 +; CHECK-NEXT: sltu a4, a2, a3 +; CHECK-NEXT: addi a4, a4, -1 +; CHECK-NEXT: and a3, a4, a3 +; CHECK-NEXT: vsetvli zero, a3, e64, m8, ta, ma +; CHECK-NEXT: vmfeq.vv v0, v16, v16 +; CHECK-NEXT: vmfeq.vv v7, v24, v24 ; CHECK-NEXT: vl8re64.v v8, (a0) ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: add a0, sp, a0 ; CHECK-NEXT: addi a0, a0, 16 ; CHECK-NEXT: vs8r.v v8, (a0) # Unknown-size Folded Spill -; CHECK-NEXT: sub a0, a2, a1 -; CHECK-NEXT: sltu a3, a2, a0 -; CHECK-NEXT: addi a3, a3, -1 -; CHECK-NEXT: and a0, a3, a0 -; CHECK-NEXT: vsetvli zero, a0, e64, m8, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v7, v24, v24 ; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 ; CHECK-NEXT: vmv1r.v v0, v7 ; CHECK-NEXT: vmerge.vvm v16, v24, v16, v0 diff --git a/llvm/test/CodeGen/RISCV/rvv/fminimum-vp.ll b/llvm/test/CodeGen/RISCV/rvv/fminimum-vp.ll index 69c76152910e..72a47ca2a605 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fminimum-vp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fminimum-vp.ll @@ -1012,77 +1012,99 @@ define @vfmin_vv_nxv16f64( %va, @vfmin_vv_nxv16f64( %va, @vfmin_vv_nxv16f64_unmasked( ; CHECK-NEXT: slli a3, a1, 3 ; CHECK-NEXT: add a3, a0, a3 ; CHECK-NEXT: vl8re64.v v24, (a3) +; CHECK-NEXT: sub a3, a2, a1 +; CHECK-NEXT: sltu a4, a2, a3 +; CHECK-NEXT: addi a4, a4, -1 +; CHECK-NEXT: and a3, a4, a3 +; CHECK-NEXT: vsetvli zero, a3, e64, m8, ta, ma +; CHECK-NEXT: vmfeq.vv v0, v16, v16 +; CHECK-NEXT: vmfeq.vv v7, v24, v24 ; CHECK-NEXT: vl8re64.v v8, (a0) ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: add a0, sp, a0 ; CHECK-NEXT: addi a0, a0, 16 ; CHECK-NEXT: vs8r.v v8, (a0) # Unknown-size Folded Spill -; CHECK-NEXT: sub a0, a2, a1 -; CHECK-NEXT: sltu a3, a2, a0 -; CHECK-NEXT: addi a3, a3, -1 -; CHECK-NEXT: and a0, a3, a0 -; CHECK-NEXT: vsetvli zero, a0, e64, m8, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v7, v24, v24 ; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 ; CHECK-NEXT: vmv1r.v v0, v7 ; CHECK-NEXT: vmerge.vvm v16, v24, v16, v0 diff --git a/llvm/test/CodeGen/RISCV/rvv/fnearbyint-constrained-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/fnearbyint-constrained-sdnode.ll index f90237b8d7e9..f88a9b3081a1 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fnearbyint-constrained-sdnode.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fnearbyint-constrained-sdnode.ll @@ -19,9 +19,9 @@ define @nearbyint_nxv1f16( %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, mf4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv1f16( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -42,9 +42,9 @@ define @nearbyint_nxv2f16( %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv2f16( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -65,9 +65,9 @@ define @nearbyint_nxv4f16( %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv4f16( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -88,9 +88,9 @@ define @nearbyint_nxv8f16( %v) strictfp { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv8f16( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -111,9 +111,9 @@ define @nearbyint_nxv16f16( %v) strictf ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv16f16( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -134,9 +134,9 @@ define @nearbyint_nxv32f16( %v) strictf ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v16, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv32f16( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -157,9 +157,9 @@ define @nearbyint_nxv1f32( %v) strictfp ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv1f32( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -180,9 +180,9 @@ define @nearbyint_nxv2f32( %v) strictfp ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv2f32( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -203,9 +203,9 @@ define @nearbyint_nxv4f32( %v) strictfp ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv4f32( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -226,9 +226,9 @@ define @nearbyint_nxv8f32( %v) strictfp ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv8f32( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -249,9 +249,9 @@ define @nearbyint_nxv16f32( %v) stric ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v16, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv16f32( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -272,9 +272,9 @@ define @nearbyint_nxv1f64( %v) strict ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv1f64( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -295,9 +295,9 @@ define @nearbyint_nxv2f64( %v) strict ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv2f64( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -318,9 +318,9 @@ define @nearbyint_nxv4f64( %v) strict ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv4f64( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r @@ -341,9 +341,9 @@ define @nearbyint_nxv8f64( %v) strict ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v16, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %r = call @llvm.experimental.constrained.nearbyint.nxv8f64( %v, metadata !"round.dynamic", metadata !"fpexcept.strict") ret %r diff --git a/llvm/test/CodeGen/RISCV/rvv/fnearbyint-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/fnearbyint-sdnode.ll index 9aa356b9b65e..9e14852305ca 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fnearbyint-sdnode.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fnearbyint-sdnode.ll @@ -15,9 +15,9 @@ define @nearbyint_nxv1f16( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, mf4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv1f16( %x) ret %a @@ -35,9 +35,9 @@ define @nearbyint_nxv2f16( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv2f16( %x) ret %a @@ -55,9 +55,9 @@ define @nearbyint_nxv4f16( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv4f16( %x) ret %a @@ -75,9 +75,9 @@ define @nearbyint_nxv8f16( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv8f16( %x) ret %a @@ -95,9 +95,9 @@ define @nearbyint_nxv16f16( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv16f16( %x) ret %a @@ -115,9 +115,9 @@ define @nearbyint_nxv32f16( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e16, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v16, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv32f16( %x) ret %a @@ -135,9 +135,9 @@ define @nearbyint_nxv1f32( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv1f32( %x) ret %a @@ -155,9 +155,9 @@ define @nearbyint_nxv2f32( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv2f32( %x) ret %a @@ -175,9 +175,9 @@ define @nearbyint_nxv4f32( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv4f32( %x) ret %a @@ -195,9 +195,9 @@ define @nearbyint_nxv8f32( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv8f32( %x) ret %a @@ -215,9 +215,9 @@ define @nearbyint_nxv16f32( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v16, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv16f32( %x) ret %a @@ -235,9 +235,9 @@ define @nearbyint_nxv1f64( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv1f64( %x) ret %a @@ -255,9 +255,9 @@ define @nearbyint_nxv2f64( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv2f64( %x) ret %a @@ -275,9 +275,9 @@ define @nearbyint_nxv4f64( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv4f64( %x) ret %a @@ -295,9 +295,9 @@ define @nearbyint_nxv8f64( %x) { ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v16, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %a = call @llvm.nearbyint.nxv8f64( %x) ret %a diff --git a/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll b/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll index 277cd7dcdabc..249f765971b0 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll @@ -960,108 +960,87 @@ define @fshr_v16i64( %a, @fshr_v16i64( %a, @fshl_v16i64( %a, @fshl_v16i64( %a, %ptrs0, %ptr ; ; RV64-LABEL: mgather_nxv16i64: ; RV64: # %bb.0: -; RV64-NEXT: addi sp, sp, -16 -; RV64-NEXT: .cfi_def_cfa_offset 16 -; RV64-NEXT: csrr a3, vlenb -; RV64-NEXT: slli a3, a3, 3 -; RV64-NEXT: sub sp, sp, a3 -; RV64-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 8 * vlenb ; RV64-NEXT: vl8re64.v v24, (a0) -; RV64-NEXT: addi a0, sp, 16 -; RV64-NEXT: vs8r.v v16, (a0) # Unknown-size Folded Spill -; RV64-NEXT: vmv8r.v v16, v8 -; RV64-NEXT: vl8re64.v v8, (a1) ; RV64-NEXT: vsetvli a0, zero, e64, m8, ta, mu -; RV64-NEXT: vluxei64.v v24, (zero), v16, v0.t +; RV64-NEXT: vluxei64.v v24, (zero), v8, v0.t +; RV64-NEXT: vl8re64.v v8, (a1) ; RV64-NEXT: csrr a0, vlenb ; RV64-NEXT: srli a1, a0, 3 ; RV64-NEXT: vsetvli a3, zero, e8, mf4, ta, ma ; RV64-NEXT: vslidedown.vx v0, v0, a1 ; RV64-NEXT: vsetvli a1, zero, e64, m8, ta, mu -; RV64-NEXT: addi a1, sp, 16 -; RV64-NEXT: vl8r.v v16, (a1) # Unknown-size Folded Reload ; RV64-NEXT: vluxei64.v v8, (zero), v16, v0.t ; RV64-NEXT: slli a0, a0, 3 ; RV64-NEXT: add a0, a2, a0 ; RV64-NEXT: vs8r.v v8, (a0) ; RV64-NEXT: vs8r.v v24, (a2) -; RV64-NEXT: csrr a0, vlenb -; RV64-NEXT: slli a0, a0, 3 -; RV64-NEXT: add sp, sp, a0 -; RV64-NEXT: addi sp, sp, 16 ; RV64-NEXT: ret %p0 = call @llvm.vector.insert.nxv8p0.nxv16p0( undef, %ptrs0, i64 0) %p1 = call @llvm.vector.insert.nxv8p0.nxv16p0( %p0, %ptrs1, i64 8) diff --git a/llvm/test/CodeGen/RISCV/rvv/mscatter-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/mscatter-sdnode.ll index 0e09f59b6a20..fc8fdf4aaafe 100644 --- a/llvm/test/CodeGen/RISCV/rvv/mscatter-sdnode.ll +++ b/llvm/test/CodeGen/RISCV/rvv/mscatter-sdnode.ll @@ -1714,8 +1714,8 @@ define void @mscatter_nxv16f64( %val0, @vp_nearbyint_nxv1f16( %va, @vp_nearbyint_nxv1f16( %va, @llvm.vp.nearbyint.nxv1f16( %va, %m, i32 %evl) ret %v @@ -63,9 +63,9 @@ define @vp_nearbyint_nxv1f16_unmasked( %v ; ZVFH-NEXT: frflags a0 ; ZVFH-NEXT: vfcvt.x.f.v v9, v8, v0.t ; ZVFH-NEXT: vfcvt.f.x.v v9, v9, v0.t -; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: vsetvli zero, zero, e16, mf4, ta, mu ; ZVFH-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: ret ; ; ZVFHMIN-LABEL: vp_nearbyint_nxv1f16_unmasked: @@ -80,11 +80,11 @@ define @vp_nearbyint_nxv1f16_unmasked( %v ; ZVFHMIN-NEXT: frflags a0 ; ZVFHMIN-NEXT: vfcvt.x.f.v v8, v9, v0.t ; ZVFHMIN-NEXT: vfcvt.f.x.v v8, v8, v0.t -; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: vsetvli zero, zero, e32, mf2, ta, mu ; ZVFHMIN-NEXT: vfsgnj.vv v9, v8, v9, v0.t -; ZVFHMIN-NEXT: vsetvli a0, zero, e16, mf4, ta, ma +; ZVFHMIN-NEXT: vsetvli a1, zero, e16, mf4, ta, ma ; ZVFHMIN-NEXT: vfncvt.f.f.w v8, v9 +; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: ret %v = call @llvm.vp.nearbyint.nxv1f16( %va, splat (i1 true), i32 %evl) ret %v @@ -105,9 +105,9 @@ define @vp_nearbyint_nxv2f16( %va, @vp_nearbyint_nxv2f16( %va, @llvm.vp.nearbyint.nxv2f16( %va, %m, i32 %evl) ret %v @@ -145,9 +145,9 @@ define @vp_nearbyint_nxv2f16_unmasked( %v ; ZVFH-NEXT: frflags a0 ; ZVFH-NEXT: vfcvt.x.f.v v9, v8, v0.t ; ZVFH-NEXT: vfcvt.f.x.v v9, v9, v0.t -; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: vsetvli zero, zero, e16, mf2, ta, mu ; ZVFH-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: ret ; ; ZVFHMIN-LABEL: vp_nearbyint_nxv2f16_unmasked: @@ -162,11 +162,11 @@ define @vp_nearbyint_nxv2f16_unmasked( %v ; ZVFHMIN-NEXT: frflags a0 ; ZVFHMIN-NEXT: vfcvt.x.f.v v8, v9, v0.t ; ZVFHMIN-NEXT: vfcvt.f.x.v v8, v8, v0.t -; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: vsetvli zero, zero, e32, m1, ta, mu ; ZVFHMIN-NEXT: vfsgnj.vv v9, v8, v9, v0.t -; ZVFHMIN-NEXT: vsetvli a0, zero, e16, mf2, ta, ma +; ZVFHMIN-NEXT: vsetvli a1, zero, e16, mf2, ta, ma ; ZVFHMIN-NEXT: vfncvt.f.f.w v8, v9 +; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: ret %v = call @llvm.vp.nearbyint.nxv2f16( %va, splat (i1 true), i32 %evl) ret %v @@ -187,9 +187,9 @@ define @vp_nearbyint_nxv4f16( %va, @vp_nearbyint_nxv4f16( %va, @llvm.vp.nearbyint.nxv4f16( %va, %m, i32 %evl) ret %v @@ -229,9 +229,9 @@ define @vp_nearbyint_nxv4f16_unmasked( %v ; ZVFH-NEXT: frflags a0 ; ZVFH-NEXT: vfcvt.x.f.v v9, v8, v0.t ; ZVFH-NEXT: vfcvt.f.x.v v9, v9, v0.t -; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: vsetvli zero, zero, e16, m1, ta, mu ; ZVFH-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: ret ; ; ZVFHMIN-LABEL: vp_nearbyint_nxv4f16_unmasked: @@ -246,11 +246,11 @@ define @vp_nearbyint_nxv4f16_unmasked( %v ; ZVFHMIN-NEXT: frflags a0 ; ZVFHMIN-NEXT: vfcvt.x.f.v v8, v10, v0.t ; ZVFHMIN-NEXT: vfcvt.f.x.v v8, v8, v0.t -; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: vsetvli zero, zero, e32, m2, ta, mu ; ZVFHMIN-NEXT: vfsgnj.vv v10, v8, v10, v0.t -; ZVFHMIN-NEXT: vsetvli a0, zero, e16, m1, ta, ma +; ZVFHMIN-NEXT: vsetvli a1, zero, e16, m1, ta, ma ; ZVFHMIN-NEXT: vfncvt.f.f.w v8, v10 +; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: ret %v = call @llvm.vp.nearbyint.nxv4f16( %va, splat (i1 true), i32 %evl) ret %v @@ -273,9 +273,9 @@ define @vp_nearbyint_nxv8f16( %va, @vp_nearbyint_nxv8f16( %va, @llvm.vp.nearbyint.nxv8f16( %va, %m, i32 %evl) ret %v @@ -315,9 +315,9 @@ define @vp_nearbyint_nxv8f16_unmasked( %v ; ZVFH-NEXT: frflags a0 ; ZVFH-NEXT: vfcvt.x.f.v v10, v8, v0.t ; ZVFH-NEXT: vfcvt.f.x.v v10, v10, v0.t -; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: vsetvli zero, zero, e16, m2, ta, mu ; ZVFH-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: ret ; ; ZVFHMIN-LABEL: vp_nearbyint_nxv8f16_unmasked: @@ -332,11 +332,11 @@ define @vp_nearbyint_nxv8f16_unmasked( %v ; ZVFHMIN-NEXT: frflags a0 ; ZVFHMIN-NEXT: vfcvt.x.f.v v8, v12, v0.t ; ZVFHMIN-NEXT: vfcvt.f.x.v v8, v8, v0.t -; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: vsetvli zero, zero, e32, m4, ta, mu ; ZVFHMIN-NEXT: vfsgnj.vv v12, v8, v12, v0.t -; ZVFHMIN-NEXT: vsetvli a0, zero, e16, m2, ta, ma +; ZVFHMIN-NEXT: vsetvli a1, zero, e16, m2, ta, ma ; ZVFHMIN-NEXT: vfncvt.f.f.w v8, v12 +; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: ret %v = call @llvm.vp.nearbyint.nxv8f16( %va, splat (i1 true), i32 %evl) ret %v @@ -359,9 +359,9 @@ define @vp_nearbyint_nxv16f16( %va, @vp_nearbyint_nxv16f16( %va, @llvm.vp.nearbyint.nxv16f16( %va, %m, i32 %evl) ret %v @@ -401,9 +401,9 @@ define @vp_nearbyint_nxv16f16_unmasked( ; ZVFH-NEXT: frflags a0 ; ZVFH-NEXT: vfcvt.x.f.v v12, v8, v0.t ; ZVFH-NEXT: vfcvt.f.x.v v12, v12, v0.t -; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: vsetvli zero, zero, e16, m4, ta, mu ; ZVFH-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: ret ; ; ZVFHMIN-LABEL: vp_nearbyint_nxv16f16_unmasked: @@ -418,11 +418,11 @@ define @vp_nearbyint_nxv16f16_unmasked( ; ZVFHMIN-NEXT: frflags a0 ; ZVFHMIN-NEXT: vfcvt.x.f.v v8, v16, v0.t ; ZVFHMIN-NEXT: vfcvt.f.x.v v8, v8, v0.t -; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: vsetvli zero, zero, e32, m8, ta, mu ; ZVFHMIN-NEXT: vfsgnj.vv v16, v8, v16, v0.t -; ZVFHMIN-NEXT: vsetvli a0, zero, e16, m4, ta, ma +; ZVFHMIN-NEXT: vsetvli a1, zero, e16, m4, ta, ma ; ZVFHMIN-NEXT: vfncvt.f.f.w v8, v16 +; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: ret %v = call @llvm.vp.nearbyint.nxv16f16( %va, splat (i1 true), i32 %evl) ret %v @@ -445,9 +445,9 @@ define @vp_nearbyint_nxv32f16( %va, @vp_nearbyint_nxv32f16( %va, @vp_nearbyint_nxv32f16( %va, @vp_nearbyint_nxv32f16_unmasked( ; ZVFH-NEXT: frflags a0 ; ZVFH-NEXT: vfcvt.x.f.v v16, v8, v0.t ; ZVFH-NEXT: vfcvt.f.x.v v16, v16, v0.t -; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: vsetvli zero, zero, e16, m8, ta, mu ; ZVFH-NEXT: vfsgnj.vv v8, v16, v8, v0.t +; ZVFH-NEXT: fsflags a0 ; ZVFH-NEXT: ret ; ; ZVFHMIN-LABEL: vp_nearbyint_nxv32f16_unmasked: @@ -589,11 +590,11 @@ define @vp_nearbyint_nxv32f16_unmasked( ; ZVFHMIN-NEXT: frflags a0 ; ZVFHMIN-NEXT: vfcvt.x.f.v v24, v16, v0.t ; ZVFHMIN-NEXT: vfcvt.f.x.v v24, v24, v0.t -; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: vsetvli zero, zero, e32, m8, ta, mu ; ZVFHMIN-NEXT: vfsgnj.vv v16, v24, v16, v0.t -; ZVFHMIN-NEXT: vsetvli a0, zero, e16, m4, ta, ma +; ZVFHMIN-NEXT: vsetvli a1, zero, e16, m4, ta, ma ; ZVFHMIN-NEXT: vfncvt.f.f.w v8, v16 +; ZVFHMIN-NEXT: fsflags a0 ; ZVFHMIN-NEXT: csrr a0, vlenb ; ZVFHMIN-NEXT: slli a0, a0, 3 ; ZVFHMIN-NEXT: add sp, sp, a0 @@ -618,9 +619,9 @@ define @vp_nearbyint_nxv1f32( %va, @llvm.vp.nearbyint.nxv1f32( %va, %m, i32 %evl) ret %v @@ -637,9 +638,9 @@ define @vp_nearbyint_nxv1f32_unmasked( ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call @llvm.vp.nearbyint.nxv1f32( %va, splat (i1 true), i32 %evl) ret %v @@ -660,9 +661,9 @@ define @vp_nearbyint_nxv2f32( %va, @llvm.vp.nearbyint.nxv2f32( %va, %m, i32 %evl) ret %v @@ -679,9 +680,9 @@ define @vp_nearbyint_nxv2f32_unmasked( ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v9, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v9, v9, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v9, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call @llvm.vp.nearbyint.nxv2f32( %va, splat (i1 true), i32 %evl) ret %v @@ -704,9 +705,9 @@ define @vp_nearbyint_nxv4f32( %va, @llvm.vp.nearbyint.nxv4f32( %va, %m, i32 %evl) ret %v @@ -723,9 +724,9 @@ define @vp_nearbyint_nxv4f32_unmasked( ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v10, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v10, v10, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v10, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call @llvm.vp.nearbyint.nxv4f32( %va, splat (i1 true), i32 %evl) ret %v @@ -748,9 +749,9 @@ define @vp_nearbyint_nxv8f32( %va, @llvm.vp.nearbyint.nxv8f32( %va, %m, i32 %evl) ret %v @@ -767,9 +768,9 @@ define @vp_nearbyint_nxv8f32_unmasked( ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vfcvt.x.f.v v12, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v12, v12, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v12, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call @llvm.vp.nearbyint.nxv8f32( %va, splat (i1 true), i32 %evl) ret %v @@ -792,9 +793,9 @@ define @vp_nearbyint_nxv16f32( %va, < ; CHECK-NEXT: vmv1r.v v0, v16 ; CHECK-NEXT: vfcvt.x.f.v v24, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v24, v24, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e32, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v24, v8, v0.t +; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: ret %v = call @llvm.vp.nearbyint.nxv16f32( %va, %m, i32 %evl) ret %v @@ -811,9 +812,9 @@ define @vp_nearbyint_nxv16f32_unmasked( @llvm.vp.nearbyint.nxv16f32( %va, splat (i1 true), i32 %evl) ret %v @@ -834,9 +835,9 @@ define @vp_nearbyint_nxv1f64( %va, @llvm.vp.nearbyint.nxv1f64( %va, %m, i32 %evl) ret %v @@ -853,9 +854,9 @@ define @vp_nearbyint_nxv1f64_unmasked( @llvm.vp.nearbyint.nxv1f64( %va, splat (i1 true), i32 %evl) ret %v @@ -878,9 +879,9 @@ define @vp_nearbyint_nxv2f64( %va, @llvm.vp.nearbyint.nxv2f64( %va, %m, i32 %evl) ret %v @@ -897,9 +898,9 @@ define @vp_nearbyint_nxv2f64_unmasked( @llvm.vp.nearbyint.nxv2f64( %va, splat (i1 true), i32 %evl) ret %v @@ -922,9 +923,9 @@ define @vp_nearbyint_nxv4f64( %va, @llvm.vp.nearbyint.nxv4f64( %va, %m, i32 %evl) ret %v @@ -941,9 +942,9 @@ define @vp_nearbyint_nxv4f64_unmasked( @llvm.vp.nearbyint.nxv4f64( %va, splat (i1 true), i32 %evl) ret %v @@ -966,9 +967,9 @@ define @vp_nearbyint_nxv7f64( %va, @llvm.vp.nearbyint.nxv7f64( %va, %m, i32 %evl) ret %v @@ -985,9 +986,9 @@ define @vp_nearbyint_nxv7f64_unmasked( @llvm.vp.nearbyint.nxv7f64( %va, splat (i1 true), i32 %evl) ret %v @@ -1010,9 +1011,9 @@ define @vp_nearbyint_nxv8f64( %va, @llvm.vp.nearbyint.nxv8f64( %va, %m, i32 %evl) ret %v @@ -1029,9 +1030,9 @@ define @vp_nearbyint_nxv8f64_unmasked( @llvm.vp.nearbyint.nxv8f64( %va, splat (i1 true), i32 %evl) ret %v @@ -1046,16 +1047,15 @@ define @vp_nearbyint_nxv16f64( %va, ; CHECK-NEXT: addi sp, sp, -16 ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: csrr a1, vlenb -; CHECK-NEXT: slli a1, a1, 4 +; CHECK-NEXT: slli a1, a1, 3 ; CHECK-NEXT: sub sp, sp, a1 -; CHECK-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x10, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 16 * vlenb -; CHECK-NEXT: vmv1r.v v24, v0 -; CHECK-NEXT: addi a1, sp, 16 -; CHECK-NEXT: vs8r.v v8, (a1) # Unknown-size Folded Spill +; CHECK-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 8 * vlenb +; CHECK-NEXT: vmv1r.v v7, v0 +; CHECK-NEXT: vmv8r.v v24, v16 ; CHECK-NEXT: csrr a1, vlenb ; CHECK-NEXT: srli a2, a1, 3 ; CHECK-NEXT: vsetvli a3, zero, e8, mf4, ta, ma -; CHECK-NEXT: vslidedown.vx v25, v0, a2 +; CHECK-NEXT: vslidedown.vx v6, v0, a2 ; CHECK-NEXT: sub a2, a0, a1 ; CHECK-NEXT: sltu a3, a0, a2 ; CHECK-NEXT: addi a3, a3, -1 @@ -1063,60 +1063,41 @@ define @vp_nearbyint_nxv16f64( %va, ; CHECK-NEXT: lui a3, %hi(.LCPI32_0) ; CHECK-NEXT: fld fa5, %lo(.LCPI32_0)(a3) ; CHECK-NEXT: vsetvli zero, a2, e64, m8, ta, ma -; CHECK-NEXT: vmv1r.v v0, v25 -; CHECK-NEXT: vmv8r.v v8, v16 -; CHECK-NEXT: csrr a2, vlenb -; CHECK-NEXT: slli a2, a2, 3 -; CHECK-NEXT: add a2, sp, a2 -; CHECK-NEXT: addi a2, a2, 16 -; CHECK-NEXT: vs8r.v v16, (a2) # Unknown-size Folded Spill +; CHECK-NEXT: vmv1r.v v0, v6 ; CHECK-NEXT: vfabs.v v16, v16, v0.t ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu -; CHECK-NEXT: vmflt.vf v25, v16, fa5, v0.t +; CHECK-NEXT: vmflt.vf v6, v16, fa5, v0.t ; CHECK-NEXT: frflags a2 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vmv1r.v v0, v25 -; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t -; CHECK-NEXT: vfcvt.f.x.v v8, v16, v0.t +; CHECK-NEXT: vmv1r.v v0, v6 +; CHECK-NEXT: vfcvt.x.f.v v16, v24, v0.t +; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t ; CHECK-NEXT: fsflags a2 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu -; CHECK-NEXT: csrr a2, vlenb -; CHECK-NEXT: slli a2, a2, 3 -; CHECK-NEXT: add a2, sp, a2 -; CHECK-NEXT: addi a2, a2, 16 -; CHECK-NEXT: vl8r.v v16, (a2) # Unknown-size Folded Reload -; CHECK-NEXT: vfsgnj.vv v16, v8, v16, v0.t -; CHECK-NEXT: csrr a2, vlenb -; CHECK-NEXT: slli a2, a2, 3 -; CHECK-NEXT: add a2, sp, a2 -; CHECK-NEXT: addi a2, a2, 16 -; CHECK-NEXT: vs8r.v v16, (a2) # Unknown-size Folded Spill +; CHECK-NEXT: vfsgnj.vv v24, v16, v24, v0.t +; CHECK-NEXT: addi a2, sp, 16 +; CHECK-NEXT: vs8r.v v24, (a2) # Unknown-size Folded Spill ; CHECK-NEXT: bltu a0, a1, .LBB32_2 ; CHECK-NEXT: # %bb.1: ; CHECK-NEXT: mv a0, a1 ; CHECK-NEXT: .LBB32_2: ; CHECK-NEXT: vsetvli zero, a0, e64, m8, ta, ma -; CHECK-NEXT: vmv1r.v v0, v24 -; CHECK-NEXT: addi a0, sp, 16 -; CHECK-NEXT: vl8r.v v8, (a0) # Unknown-size Folded Reload +; CHECK-NEXT: vmv1r.v v0, v7 ; CHECK-NEXT: vfabs.v v16, v8, v0.t ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu -; CHECK-NEXT: vmflt.vf v24, v16, fa5, v0.t +; CHECK-NEXT: vmflt.vf v7, v16, fa5, v0.t ; CHECK-NEXT: frflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vmv1r.v v0, v24 +; CHECK-NEXT: vmv1r.v v0, v7 ; CHECK-NEXT: vfcvt.x.f.v v16, v8, v0.t ; CHECK-NEXT: vfcvt.f.x.v v16, v16, v0.t -; CHECK-NEXT: fsflags a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, mu ; CHECK-NEXT: vfsgnj.vv v8, v16, v8, v0.t -; CHECK-NEXT: csrr a0, vlenb -; CHECK-NEXT: slli a0, a0, 3 -; CHECK-NEXT: add a0, sp, a0 -; CHECK-NEXT: addi a0, a0, 16 +; CHECK-NEXT: fsflags a0 +; CHECK-NEXT: addi a0, sp, 16 ; CHECK-NEXT: vl8r.v v16, (a0) # Unknown-size Folded Reload ; CHECK-NEXT: csrr a0, vlenb -; CHECK-NEXT: slli a0, a0, 4 +; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: add sp, sp, a0 ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret @@ -1153,9 +1134,9 @@ define @vp_nearbyint_nxv16f64_unmasked( @llvm.vp.nearbyint.nxv16f64( %va, splat (i1 true), i32 %evl) ret %v diff --git a/llvm/test/CodeGen/RISCV/rvv/setcc-fp-vp.ll b/llvm/test/CodeGen/RISCV/rvv/setcc-fp-vp.ll index 897bfdea69f1..cc967396153b 100644 --- a/llvm/test/CodeGen/RISCV/rvv/setcc-fp-vp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/setcc-fp-vp.ll @@ -2203,17 +2203,17 @@ define @fcmp_oeq_vv_nxv64f16( %va, @fcmp_oeq_vv_nxv64f16( %va, @fcmp_oeq_vv_nxv64f16( %va, @fcmp_oeq_vv_nxv32f64( %va, @fcmp_oeq_vv_nxv32f64( %va, @fcmp_oeq_vv_nxv32f64( %va, @fcmp_oeq_vv_nxv32f64( %va, @icmp_eq_vv_nxv128i8( %va, @icmp_eq_vv_nxv128i8( %va, @icmp_eq_vv_nxv128i8( %va, @icmp_eq_vv_nxv32i32( %va, @vfma_vv_nxv16f64( %va, @vfma_vv_nxv16f64( %va, @vfma_vv_nxv16f64( %va, @vfma_vv_nxv16f64( %va, @vpmerge_vv_nxv128i8( %va, @select_nxv32i32( %a, @select_evl_nxv32i32( %a, @select_nxv16f64( %a, @test6(i64 %avl, i8 zeroext %cond, @llvm.riscv.vwadd.w.nxv2i32.nxv2i16(This Inner Loop Header: Depth=1 ; CHECK-NEXT: vle64.v v8, (a2) ; CHECK-NEXT: vle64.v v9, (a3) ; CHECK-NEXT: vfadd.vv v8, v8, v9 ; CHECK-NEXT: vse64.v v8, (a1) -; CHECK-NEXT: add a5, a5, a6 -; CHECK-NEXT: add a1, a1, a4 -; CHECK-NEXT: add a3, a3, a4 -; CHECK-NEXT: add a2, a2, a4 -; CHECK-NEXT: blt a5, a0, .LBB12_2 +; CHECK-NEXT: add a4, a4, a6 +; CHECK-NEXT: add a1, a1, a5 +; CHECK-NEXT: add a3, a3, a5 +; CHECK-NEXT: add a2, a2, a5 +; CHECK-NEXT: blt a4, a0, .LBB12_2 ; CHECK-NEXT: .LBB12_3: # %for.end ; CHECK-NEXT: ret entry: @@ -678,18 +677,18 @@ for.end: ; preds = %for.body, %entry define void @vector_init_vlmax(i64 %N, ptr %c) { ; CHECK-LABEL: vector_init_vlmax: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: vsetvli a2, zero, e64, m1, ta, ma ; CHECK-NEXT: blez a0, .LBB13_3 ; CHECK-NEXT: # %bb.1: # %for.body.preheader -; CHECK-NEXT: li a3, 0 -; CHECK-NEXT: slli a4, a2, 3 +; CHECK-NEXT: li a2, 0 +; CHECK-NEXT: vsetvli a3, zero, e64, m1, ta, ma +; CHECK-NEXT: slli a4, a3, 3 ; CHECK-NEXT: vmv.v.i v8, 0 ; CHECK-NEXT: .LBB13_2: # %for.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vse64.v v8, (a1) -; CHECK-NEXT: add a3, a3, a2 +; CHECK-NEXT: add a2, a2, a3 ; CHECK-NEXT: add a1, a1, a4 -; CHECK-NEXT: blt a3, a0, .LBB13_2 +; CHECK-NEXT: blt a2, a0, .LBB13_2 ; CHECK-NEXT: .LBB13_3: # %for.end ; CHECK-NEXT: ret entry: @@ -714,20 +713,20 @@ for.end: ; preds = %for.body, %entry define void @vector_init_vsetvli_N(i64 %N, ptr %c) { ; CHECK-LABEL: vector_init_vsetvli_N: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: vsetvli a2, a0, e64, m1, ta, ma ; CHECK-NEXT: blez a0, .LBB14_3 ; CHECK-NEXT: # %bb.1: # %for.body.preheader -; CHECK-NEXT: li a3, 0 -; CHECK-NEXT: slli a4, a2, 3 +; CHECK-NEXT: li a2, 0 +; CHECK-NEXT: vsetvli a3, a0, e64, m1, ta, ma +; CHECK-NEXT: slli a4, a3, 3 ; CHECK-NEXT: vsetvli a5, zero, e64, m1, ta, ma ; CHECK-NEXT: vmv.v.i v8, 0 ; CHECK-NEXT: .LBB14_2: # %for.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: vsetvli zero, a2, e64, m1, ta, ma +; CHECK-NEXT: vsetvli zero, a3, e64, m1, ta, ma ; CHECK-NEXT: vse64.v v8, (a1) -; CHECK-NEXT: add a3, a3, a2 +; CHECK-NEXT: add a2, a2, a3 ; CHECK-NEXT: add a1, a1, a4 -; CHECK-NEXT: blt a3, a0, .LBB14_2 +; CHECK-NEXT: blt a2, a0, .LBB14_2 ; CHECK-NEXT: .LBB14_3: # %for.end ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-regression.ll b/llvm/test/CodeGen/RISCV/rvv/vsetvli-regression.ll index f658a2c6b24a..c3b19b59ec3d 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vsetvli-regression.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-regression.ll @@ -11,9 +11,10 @@ define i32 @illegal_preserve_vl( %a, %x, pt ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e64, m4, ta, ma ; CHECK-NEXT: vadd.vv v12, v12, v12 -; CHECK-NEXT: vs4r.v v12, (a0) ; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma -; CHECK-NEXT: vmv.x.s a0, v8 +; CHECK-NEXT: vmv.x.s a1, v8 +; CHECK-NEXT: vs4r.v v12, (a0) +; CHECK-NEXT: mv a0, a1 ; CHECK-NEXT: ret %index = add %x, %x store %index, ptr %y -- GitLab From 74218a9c8fc4b0bdb4b2a4839455cf2f211a2a30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 15 May 2024 15:43:28 +0200 Subject: [PATCH 373/578] [clang][Interp] Implement __builtin_convertvector --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 33 +++ clang/lib/AST/Interp/ByteCodeExprGen.h | 1 + clang/test/AST/Interp/builtin-functions.cpp | 235 ++++++++++++++++++++ 3 files changed, 269 insertions(+) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 7cdc1c6d1947..205e53f02b1a 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2498,6 +2498,39 @@ bool ByteCodeExprGen::VisitAddrLabelExpr(const AddrLabelExpr *E) { return this->emitGetLocal(PT_Ptr, Offset, E); } +template +bool ByteCodeExprGen::VisitConvertVectorExpr( + const ConvertVectorExpr *E) { + assert(Initializing); + const auto *VT = E->getType()->castAs(); + QualType ElemType = VT->getElementType(); + PrimType ElemT = classifyPrim(ElemType); + const Expr *Src = E->getSrcExpr(); + PrimType SrcElemT = + classifyPrim(Src->getType()->castAs()->getElementType()); + + unsigned SrcOffset = this->allocateLocalPrimitive(Src, PT_Ptr, true, false); + if (!this->visit(Src)) + return false; + if (!this->emitSetLocal(PT_Ptr, SrcOffset, E)) + return false; + + for (unsigned I = 0; I != VT->getNumElements(); ++I) { + if (!this->emitGetLocal(PT_Ptr, SrcOffset, E)) + return false; + if (!this->emitArrayElemPop(SrcElemT, I, E)) + return false; + if (SrcElemT != ElemT) { + if (!this->emitPrimCast(SrcElemT, ElemT, ElemType, E)) + return false; + } + if (!this->emitInitElem(ElemT, I, E)) + return false; + } + + return true; +} + template bool ByteCodeExprGen::discard(const Expr *E) { OptionScope Scope(this, /*NewDiscardResult=*/true, /*NewInitializing=*/false); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 6039a54d32a5..fba4e45b9aa2 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -123,6 +123,7 @@ public: bool VisitPackIndexingExpr(const PackIndexingExpr *E); bool VisitRecoveryExpr(const RecoveryExpr *E); bool VisitAddrLabelExpr(const AddrLabelExpr *E); + bool VisitConvertVectorExpr(const ConvertVectorExpr *E); protected: bool visitExpr(const Expr *E) override; diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index 0cbab1fcd91d..afdfd25527e4 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -639,3 +639,238 @@ void test7(void) { /// the actual implementation uses analyze_os_log::computeOSLogBufferLayout(), which /// is tested elsewhere. static_assert(__builtin_os_log_format_buffer_size("%{mask.xyz}s", "abc") != 0, ""); + +/// Copied from test/Sema/constant_builtins_vector.cpp. +/// Some tests are missing since we run this for multiple targets, +/// some of which do not support _BitInt. +#ifndef __AVR__ +namespace convertvector { + typedef _BitInt(128) BitInt128; + + typedef double vector4double __attribute__((__vector_size__(32))); + typedef float vector4float __attribute__((__vector_size__(16))); + typedef long long vector4long __attribute__((__vector_size__(32))); + typedef int vector4int __attribute__((__vector_size__(16))); + typedef short vector4short __attribute__((__vector_size__(8))); + typedef char vector4char __attribute__((__vector_size__(4))); + typedef BitInt128 vector4BitInt128 __attribute__((__vector_size__(64))); + typedef double vector8double __attribute__((__vector_size__(64))); + typedef float vector8float __attribute__((__vector_size__(32))); + typedef long long vector8long __attribute__((__vector_size__(64))); + typedef int vector8int __attribute__((__vector_size__(32))); + typedef short vector8short __attribute__((__vector_size__(16))); + typedef char vector8char __attribute__((__vector_size__(8))); + typedef BitInt128 vector8BitInt128 __attribute__((__vector_size__(128))); + + constexpr vector4double from_vector4double_to_vector4double_var = + __builtin_convertvector((vector4double){0, 1, 2, 3}, vector4double); + constexpr vector4float from_vector4double_to_vector4float_var = + __builtin_convertvector((vector4double){0, 1, 2, 3}, vector4float); + constexpr vector4long from_vector4double_to_vector4long_var = + __builtin_convertvector((vector4double){0, 1, 2, 3}, vector4long); + constexpr vector4int from_vector4double_to_vector4int_var = + __builtin_convertvector((vector4double){0, 1, 2, 3}, vector4int); + constexpr vector4short from_vector4double_to_vector4short_var = + __builtin_convertvector((vector4double){0, 1, 2, 3}, vector4short); + constexpr vector4char from_vector4double_to_vector4char_var = + __builtin_convertvector((vector4double){0, 1, 2, 3}, vector4char); + constexpr vector4BitInt128 from_vector4double_to_vector4BitInt128_var = + __builtin_convertvector((vector4double){0, 1, 2, 3}, vector4BitInt128); + constexpr vector4double from_vector4float_to_vector4double_var = + __builtin_convertvector((vector4float){0, 1, 2, 3}, vector4double); + constexpr vector4float from_vector4float_to_vector4float_var = + __builtin_convertvector((vector4float){0, 1, 2, 3}, vector4float); + constexpr vector4long from_vector4float_to_vector4long_var = + __builtin_convertvector((vector4float){0, 1, 2, 3}, vector4long); + constexpr vector4int from_vector4float_to_vector4int_var = + __builtin_convertvector((vector4float){0, 1, 2, 3}, vector4int); + constexpr vector4short from_vector4float_to_vector4short_var = + __builtin_convertvector((vector4float){0, 1, 2, 3}, vector4short); + constexpr vector4char from_vector4float_to_vector4char_var = + __builtin_convertvector((vector4float){0, 1, 2, 3}, vector4char); + constexpr vector4BitInt128 from_vector4float_to_vector4BitInt128_var = + __builtin_convertvector((vector4float){0, 1, 2, 3}, vector4BitInt128); + constexpr vector4double from_vector4long_to_vector4double_var = + __builtin_convertvector((vector4long){0, 1, 2, 3}, vector4double); + constexpr vector4float from_vector4long_to_vector4float_var = + __builtin_convertvector((vector4long){0, 1, 2, 3}, vector4float); + constexpr vector4long from_vector4long_to_vector4long_var = + __builtin_convertvector((vector4long){0, 1, 2, 3}, vector4long); + constexpr vector4int from_vector4long_to_vector4int_var = + __builtin_convertvector((vector4long){0, 1, 2, 3}, vector4int); + constexpr vector4short from_vector4long_to_vector4short_var = + __builtin_convertvector((vector4long){0, 1, 2, 3}, vector4short); + constexpr vector4char from_vector4long_to_vector4char_var = + __builtin_convertvector((vector4long){0, 1, 2, 3}, vector4char); + constexpr vector4BitInt128 from_vector4long_to_vector4BitInt128_var = + __builtin_convertvector((vector4long){0, 1, 2, 3}, vector4BitInt128); + constexpr vector4double from_vector4int_to_vector4double_var = + __builtin_convertvector((vector4int){0, 1, 2, 3}, vector4double); + constexpr vector4float from_vector4int_to_vector4float_var = + __builtin_convertvector((vector4int){0, 1, 2, 3}, vector4float); + constexpr vector4long from_vector4int_to_vector4long_var = + __builtin_convertvector((vector4int){0, 1, 2, 3}, vector4long); + constexpr vector4int from_vector4int_to_vector4int_var = + __builtin_convertvector((vector4int){0, 1, 2, 3}, vector4int); + constexpr vector4short from_vector4int_to_vector4short_var = + __builtin_convertvector((vector4int){0, 1, 2, 3}, vector4short); + constexpr vector4char from_vector4int_to_vector4char_var = + __builtin_convertvector((vector4int){0, 1, 2, 3}, vector4char); + constexpr vector4BitInt128 from_vector4int_to_vector4BitInt128_var = + __builtin_convertvector((vector4int){0, 1, 2, 3}, vector4BitInt128); + constexpr vector4double from_vector4short_to_vector4double_var = + __builtin_convertvector((vector4short){0, 1, 2, 3}, vector4double); + constexpr vector4float from_vector4short_to_vector4float_var = + __builtin_convertvector((vector4short){0, 1, 2, 3}, vector4float); + constexpr vector4long from_vector4short_to_vector4long_var = + __builtin_convertvector((vector4short){0, 1, 2, 3}, vector4long); + constexpr vector4int from_vector4short_to_vector4int_var = + __builtin_convertvector((vector4short){0, 1, 2, 3}, vector4int); + constexpr vector4short from_vector4short_to_vector4short_var = + __builtin_convertvector((vector4short){0, 1, 2, 3}, vector4short); + constexpr vector4char from_vector4short_to_vector4char_var = + __builtin_convertvector((vector4short){0, 1, 2, 3}, vector4char); + constexpr vector4BitInt128 from_vector4short_to_vector4BitInt128_var = + __builtin_convertvector((vector4short){0, 1, 2, 3}, vector4BitInt128); + constexpr vector4double from_vector4char_to_vector4double_var = + __builtin_convertvector((vector4char){0, 1, 2, 3}, vector4double); + constexpr vector4float from_vector4char_to_vector4float_var = + __builtin_convertvector((vector4char){0, 1, 2, 3}, vector4float); + constexpr vector4long from_vector4char_to_vector4long_var = + __builtin_convertvector((vector4char){0, 1, 2, 3}, vector4long); + constexpr vector4int from_vector4char_to_vector4int_var = + __builtin_convertvector((vector4char){0, 1, 2, 3}, vector4int); + constexpr vector4short from_vector4char_to_vector4short_var = + __builtin_convertvector((vector4char){0, 1, 2, 3}, vector4short); + constexpr vector4char from_vector4char_to_vector4char_var = + __builtin_convertvector((vector4char){0, 1, 2, 3}, vector4char); + constexpr vector8double from_vector8double_to_vector8double_var = + __builtin_convertvector((vector8double){0, 1, 2, 3, 4, 5, 6, 7}, + vector8double); + constexpr vector8float from_vector8double_to_vector8float_var = + __builtin_convertvector((vector8double){0, 1, 2, 3, 4, 5, 6, 7}, + vector8float); + constexpr vector8long from_vector8double_to_vector8long_var = + __builtin_convertvector((vector8double){0, 1, 2, 3, 4, 5, 6, 7}, + vector8long); + constexpr vector8int from_vector8double_to_vector8int_var = + __builtin_convertvector((vector8double){0, 1, 2, 3, 4, 5, 6, 7}, + vector8int); + constexpr vector8short from_vector8double_to_vector8short_var = + __builtin_convertvector((vector8double){0, 1, 2, 3, 4, 5, 6, 7}, + vector8short); + constexpr vector8char from_vector8double_to_vector8char_var = + __builtin_convertvector((vector8double){0, 1, 2, 3, 4, 5, 6, 7}, + vector8char); + constexpr vector8BitInt128 from_vector8double_to_vector8BitInt128_var = + __builtin_convertvector((vector8double){0, 1, 2, 3, 4, 5, 6, 7}, + vector8BitInt128); + constexpr vector8double from_vector8float_to_vector8double_var = + __builtin_convertvector((vector8float){0, 1, 2, 3, 4, 5, 6, 7}, + vector8double); + constexpr vector8float from_vector8float_to_vector8float_var = + __builtin_convertvector((vector8float){0, 1, 2, 3, 4, 5, 6, 7}, + vector8float); + constexpr vector8long from_vector8float_to_vector8long_var = + __builtin_convertvector((vector8float){0, 1, 2, 3, 4, 5, 6, 7}, + vector8long); + constexpr vector8int from_vector8float_to_vector8int_var = + __builtin_convertvector((vector8float){0, 1, 2, 3, 4, 5, 6, 7}, vector8int); + constexpr vector8short from_vector8float_to_vector8short_var = + __builtin_convertvector((vector8float){0, 1, 2, 3, 4, 5, 6, 7}, + vector8short); + constexpr vector8char from_vector8float_to_vector8char_var = + __builtin_convertvector((vector8float){0, 1, 2, 3, 4, 5, 6, 7}, + vector8char); + constexpr vector8BitInt128 from_vector8float_to_vector8BitInt128_var = + __builtin_convertvector((vector8float){0, 1, 2, 3, 4, 5, 6, 7}, + vector8BitInt128); + constexpr vector8double from_vector8long_to_vector8double_var = + __builtin_convertvector((vector8long){0, 1, 2, 3, 4, 5, 6, 7}, + vector8double); + constexpr vector8float from_vector8long_to_vector8float_var = + __builtin_convertvector((vector8long){0, 1, 2, 3, 4, 5, 6, 7}, + vector8float); + constexpr vector8long from_vector8long_to_vector8long_var = + __builtin_convertvector((vector8long){0, 1, 2, 3, 4, 5, 6, 7}, vector8long); + constexpr vector8int from_vector8long_to_vector8int_var = + __builtin_convertvector((vector8long){0, 1, 2, 3, 4, 5, 6, 7}, vector8int); + constexpr vector8short from_vector8long_to_vector8short_var = + __builtin_convertvector((vector8long){0, 1, 2, 3, 4, 5, 6, 7}, + vector8short); + constexpr vector8char from_vector8long_to_vector8char_var = + __builtin_convertvector((vector8long){0, 1, 2, 3, 4, 5, 6, 7}, vector8char); + constexpr vector8double from_vector8int_to_vector8double_var = + __builtin_convertvector((vector8int){0, 1, 2, 3, 4, 5, 6, 7}, + vector8double); + constexpr vector8float from_vector8int_to_vector8float_var = + __builtin_convertvector((vector8int){0, 1, 2, 3, 4, 5, 6, 7}, vector8float); + constexpr vector8long from_vector8int_to_vector8long_var = + __builtin_convertvector((vector8int){0, 1, 2, 3, 4, 5, 6, 7}, vector8long); + constexpr vector8int from_vector8int_to_vector8int_var = + __builtin_convertvector((vector8int){0, 1, 2, 3, 4, 5, 6, 7}, vector8int); + constexpr vector8short from_vector8int_to_vector8short_var = + __builtin_convertvector((vector8int){0, 1, 2, 3, 4, 5, 6, 7}, vector8short); + constexpr vector8char from_vector8int_to_vector8char_var = + __builtin_convertvector((vector8int){0, 1, 2, 3, 4, 5, 6, 7}, vector8char); + constexpr vector8double from_vector8short_to_vector8double_var = + __builtin_convertvector((vector8short){0, 1, 2, 3, 4, 5, 6, 7}, + vector8double); + constexpr vector8float from_vector8short_to_vector8float_var = + __builtin_convertvector((vector8short){0, 1, 2, 3, 4, 5, 6, 7}, + vector8float); + constexpr vector8long from_vector8short_to_vector8long_var = + __builtin_convertvector((vector8short){0, 1, 2, 3, 4, 5, 6, 7}, + vector8long); + constexpr vector8int from_vector8short_to_vector8int_var = + __builtin_convertvector((vector8short){0, 1, 2, 3, 4, 5, 6, 7}, vector8int); + constexpr vector8short from_vector8short_to_vector8short_var = + __builtin_convertvector((vector8short){0, 1, 2, 3, 4, 5, 6, 7}, + vector8short); + constexpr vector8char from_vector8short_to_vector8char_var = + __builtin_convertvector((vector8short){0, 1, 2, 3, 4, 5, 6, 7}, + vector8char); + + constexpr vector8double from_vector8char_to_vector8double_var = + __builtin_convertvector((vector8char){0, 1, 2, 3, 4, 5, 6, 7}, + vector8double); + constexpr vector8float from_vector8char_to_vector8float_var = + __builtin_convertvector((vector8char){0, 1, 2, 3, 4, 5, 6, 7}, + vector8float); + constexpr vector8long from_vector8char_to_vector8long_var = + __builtin_convertvector((vector8char){0, 1, 2, 3, 4, 5, 6, 7}, vector8long); + constexpr vector8int from_vector8char_to_vector8int_var = + __builtin_convertvector((vector8char){0, 1, 2, 3, 4, 5, 6, 7}, vector8int); + constexpr vector8short from_vector8char_to_vector8short_var = + __builtin_convertvector((vector8char){0, 1, 2, 3, 4, 5, 6, 7}, + vector8short); + constexpr vector8char from_vector8char_to_vector8char_var = + __builtin_convertvector((vector8char){0, 1, 2, 3, 4, 5, 6, 7}, vector8char); + constexpr vector8double from_vector8BitInt128_to_vector8double_var = + __builtin_convertvector((vector8BitInt128){0, 1, 2, 3, 4, 5, 6, 7}, + vector8double); + constexpr vector8float from_vector8BitInt128_to_vector8float_var = + __builtin_convertvector((vector8BitInt128){0, 1, 2, 3, 4, 5, 6, 7}, + vector8float); + constexpr vector8long from_vector8BitInt128_to_vector8long_var = + __builtin_convertvector((vector8BitInt128){0, 1, 2, 3, 4, 5, 6, 7}, + vector8long); + constexpr vector8int from_vector8BitInt128_to_vector8int_var = + __builtin_convertvector((vector8BitInt128){0, 1, 2, 3, 4, 5, 6, 7}, + vector8int); + constexpr vector8short from_vector8BitInt128_to_vector8short_var = + __builtin_convertvector((vector8BitInt128){0, 1, 2, 3, 4, 5, 6, 7}, + vector8short); + constexpr vector8char from_vector8BitInt128_to_vector8char_var = + __builtin_convertvector((vector8BitInt128){0, 1, 2, 3, 4, 5, 6, 7}, + vector8char); + constexpr vector8BitInt128 from_vector8BitInt128_to_vector8BitInt128_var = + __builtin_convertvector((vector8BitInt128){0, 1, 2, 3, 4, 5, 6, 7}, + vector8BitInt128); + static_assert(from_vector8BitInt128_to_vector8BitInt128_var[0] == 0, ""); // ref-error {{not an integral constant expression}} + static_assert(from_vector8BitInt128_to_vector8BitInt128_var[1] == 1, ""); // ref-error {{not an integral constant expression}} + static_assert(from_vector8BitInt128_to_vector8BitInt128_var[2] == 2, ""); // ref-error {{not an integral constant expression}} + static_assert(from_vector8BitInt128_to_vector8BitInt128_var[3] == 3, ""); // ref-error {{not an integral constant expression}} + static_assert(from_vector8BitInt128_to_vector8BitInt128_var[4] == 4, ""); // ref-error {{not an integral constant expression}} +} +#endif -- GitLab From 3a8d176af519e4385652e762c615ace9b80ef045 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Wed, 15 May 2024 16:50:52 +0100 Subject: [PATCH 374/578] [utils][filecheck-lint] Add shebang (#92243) --- llvm/utils/filecheck_lint/filecheck_lint.py | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 llvm/utils/filecheck_lint/filecheck_lint.py diff --git a/llvm/utils/filecheck_lint/filecheck_lint.py b/llvm/utils/filecheck_lint/filecheck_lint.py old mode 100644 new mode 100755 index dc054ab76a09..837846db8332 --- a/llvm/utils/filecheck_lint/filecheck_lint.py +++ b/llvm/utils/filecheck_lint/filecheck_lint.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 # ===----------------------------------------------------------------------===## # # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -- GitLab From ba3447601c435bb2b24ad9e3c8d146c578f00568 Mon Sep 17 00:00:00 2001 From: Piotr Zegar Date: Wed, 15 May 2024 17:52:46 +0200 Subject: [PATCH 375/578] [clang-tidy] Fix crash in modernize-use-constraints (#92019) Improved modernize-use-constraints check by fixing a crash that occurred in some scenarios and excluded system headers from analysis. Problem were with DependentNameTypeLoc having null type location as getQualifierLoc().getTypeLoc(). Fixes #91872 --- .../modernize/UseConstraintsCheck.cpp | 4 +++ clang-tools-extra/docs/ReleaseNotes.rst | 4 +++ .../checks/modernize/use-constraints.rst | 4 +++ .../checkers/modernize/use-constraints.cpp | 32 +++++++++++++++++++ 4 files changed, 44 insertions(+) diff --git a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp index 1585925ee996..7a021fe14436 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp @@ -41,6 +41,8 @@ AST_MATCHER(FunctionDecl, hasOtherDeclarations) { void UseConstraintsCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( functionTemplateDecl( + // Skip external libraries included as system headers + unless(isExpansionInSystemHeader()), has(functionDecl(unless(hasOtherDeclarations()), isDefinition(), hasReturnTypeLoc(typeLoc().bind("return"))) .bind("function"))) @@ -57,6 +59,8 @@ matchEnableIfSpecializationImplTypename(TypeLoc TheType) { return std::nullopt; } TheType = Dep.getQualifierLoc().getTypeLoc(); + if (TheType.isNull()) + return std::nullopt; } if (const auto SpecializationLoc = diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 19f830741295..b7ef5a860e8b 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -322,6 +322,10 @@ Changes in existing checks don't remove parentheses used in ``sizeof`` calls when they have array index accesses as arguments. +- Improved :doc:`modernize-use-constraints + ` check by fixing a crash that + occurred in some scenarios and excluding system headers from analysis. + - Improved :doc:`modernize-use-nullptr ` check to include support for C23, which also has introduced the ``nullptr`` keyword. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-constraints.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-constraints.rst index be62dd5823d5..a8b31b80e580 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-constraints.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-constraints.rst @@ -68,3 +68,7 @@ The tool will replace the above code with, // The tool will not emit a diagnostic or attempt to replace the code. template = 0> struct my_class {}; + +.. note:: + + System headers are not analyzed by this check. diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp index 3ec44be8a1c8..3bcd5cd74024 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp @@ -724,3 +724,35 @@ void not_last_param() { } } // namespace enable_if_trailing_type_parameter + + +// Issue fixes: + +namespace PR91872 { + +enum expression_template_option { value1, value2 }; + +template struct number_category { + static const int value = 0; +}; + +constexpr int number_kind_complex = 1; + +template +struct number { + using type = T; +}; + +template struct component_type { + using type = T; +}; + +template +inline typename std::enable_if< + number_category::value == number_kind_complex, + component_type>>::type::type +abs(const number &v) { + return {}; +} + +} -- GitLab From 54c6ee922abbaea7d2f138a209f320c414c1657b Mon Sep 17 00:00:00 2001 From: Piotr Zegar Date: Wed, 15 May 2024 17:53:03 +0200 Subject: [PATCH 376/578] [clang-tidy] Add AllowImplicitlyDeletedCopyOrMove option to cppcoreguidelines-special-member-functions (#71683) Improved cppcoreguidelines-special-member-functions check with a new option AllowImplicitlyDeletedCopyOrMove, which removes the requirement for explicit copy or move special member functions when they are already implicitly deleted. Closes #62392 --- .../SpecialMemberFunctionsCheck.cpp | 70 ++++++++++++++----- .../SpecialMemberFunctionsCheck.h | 7 +- clang-tools-extra/docs/ReleaseNotes.rst | 6 ++ .../special-member-functions.rst | 28 ++++++-- .../special-member-functions-relaxed.cpp | 26 ++++++- 5 files changed, 107 insertions(+), 30 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp index d2117c67a76d..ed76ac665049 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp @@ -25,7 +25,9 @@ SpecialMemberFunctionsCheck::SpecialMemberFunctionsCheck( "AllowMissingMoveFunctions", false)), AllowSoleDefaultDtor(Options.get("AllowSoleDefaultDtor", false)), AllowMissingMoveFunctionsWhenCopyIsDeleted( - Options.get("AllowMissingMoveFunctionsWhenCopyIsDeleted", false)) {} + Options.get("AllowMissingMoveFunctionsWhenCopyIsDeleted", false)), + AllowImplicitlyDeletedCopyOrMove( + Options.get("AllowImplicitlyDeletedCopyOrMove", false)) {} void SpecialMemberFunctionsCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { @@ -33,17 +35,34 @@ void SpecialMemberFunctionsCheck::storeOptions( Options.store(Opts, "AllowSoleDefaultDtor", AllowSoleDefaultDtor); Options.store(Opts, "AllowMissingMoveFunctionsWhenCopyIsDeleted", AllowMissingMoveFunctionsWhenCopyIsDeleted); + Options.store(Opts, "AllowImplicitlyDeletedCopyOrMove", + AllowImplicitlyDeletedCopyOrMove); +} + +std::optional +SpecialMemberFunctionsCheck::getCheckTraversalKind() const { + return AllowImplicitlyDeletedCopyOrMove ? TK_AsIs + : TK_IgnoreUnlessSpelledInSource; } void SpecialMemberFunctionsCheck::registerMatchers(MatchFinder *Finder) { + auto IsNotImplicitOrDeleted = anyOf(unless(isImplicit()), isDeleted()); + Finder->addMatcher( cxxRecordDecl( - eachOf(has(cxxDestructorDecl().bind("dtor")), - has(cxxConstructorDecl(isCopyConstructor()).bind("copy-ctor")), - has(cxxMethodDecl(isCopyAssignmentOperator()) + unless(isImplicit()), + eachOf(has(cxxDestructorDecl(unless(isImplicit())).bind("dtor")), + has(cxxConstructorDecl(isCopyConstructor(), + IsNotImplicitOrDeleted) + .bind("copy-ctor")), + has(cxxMethodDecl(isCopyAssignmentOperator(), + IsNotImplicitOrDeleted) .bind("copy-assign")), - has(cxxConstructorDecl(isMoveConstructor()).bind("move-ctor")), - has(cxxMethodDecl(isMoveAssignmentOperator()) + has(cxxConstructorDecl(isMoveConstructor(), + IsNotImplicitOrDeleted) + .bind("move-ctor")), + has(cxxMethodDecl(isMoveAssignmentOperator(), + IsNotImplicitOrDeleted) .bind("move-assign")))) .bind("class-def"), this); @@ -127,7 +146,8 @@ void SpecialMemberFunctionsCheck::check( for (const auto &KV : Matchers) if (const auto *MethodDecl = Result.Nodes.getNodeAs(KV.first)) { - StoreMember({KV.second, MethodDecl->isDeleted()}); + StoreMember( + {KV.second, MethodDecl->isDeleted(), MethodDecl->isImplicit()}); } } @@ -144,7 +164,13 @@ void SpecialMemberFunctionsCheck::checkForMissingMembers( auto HasMember = [&](SpecialMemberFunctionKind Kind) { return llvm::any_of(DefinedMembers, [Kind](const auto &Data) { - return Data.FunctionKind == Kind; + return Data.FunctionKind == Kind && !Data.IsImplicit; + }); + }; + + auto HasImplicitDeletedMember = [&](SpecialMemberFunctionKind Kind) { + return llvm::any_of(DefinedMembers, [Kind](const auto &Data) { + return Data.FunctionKind == Kind && Data.IsImplicit && Data.IsDeleted; }); }; @@ -154,9 +180,17 @@ void SpecialMemberFunctionsCheck::checkForMissingMembers( }); }; - auto RequireMember = [&](SpecialMemberFunctionKind Kind) { - if (!HasMember(Kind)) - MissingMembers.push_back(Kind); + auto RequireMembers = [&](SpecialMemberFunctionKind Kind1, + SpecialMemberFunctionKind Kind2) { + if (AllowImplicitlyDeletedCopyOrMove && HasImplicitDeletedMember(Kind1) && + HasImplicitDeletedMember(Kind2)) + return; + + if (!HasMember(Kind1)) + MissingMembers.push_back(Kind1); + + if (!HasMember(Kind2)) + MissingMembers.push_back(Kind2); }; bool RequireThree = @@ -180,8 +214,8 @@ void SpecialMemberFunctionsCheck::checkForMissingMembers( !HasMember(SpecialMemberFunctionKind::NonDefaultDestructor)) MissingMembers.push_back(SpecialMemberFunctionKind::Destructor); - RequireMember(SpecialMemberFunctionKind::CopyConstructor); - RequireMember(SpecialMemberFunctionKind::CopyAssignment); + RequireMembers(SpecialMemberFunctionKind::CopyConstructor, + SpecialMemberFunctionKind::CopyAssignment); } if (RequireFive && @@ -189,14 +223,16 @@ void SpecialMemberFunctionsCheck::checkForMissingMembers( (IsDeleted(SpecialMemberFunctionKind::CopyConstructor) && IsDeleted(SpecialMemberFunctionKind::CopyAssignment)))) { assert(RequireThree); - RequireMember(SpecialMemberFunctionKind::MoveConstructor); - RequireMember(SpecialMemberFunctionKind::MoveAssignment); + RequireMembers(SpecialMemberFunctionKind::MoveConstructor, + SpecialMemberFunctionKind::MoveAssignment); } if (!MissingMembers.empty()) { llvm::SmallVector DefinedMemberKinds; - llvm::transform(DefinedMembers, std::back_inserter(DefinedMemberKinds), - [](const auto &Data) { return Data.FunctionKind; }); + for (const auto &Data : DefinedMembers) { + if (!Data.IsImplicit) + DefinedMemberKinds.push_back(Data.FunctionKind); + } diag(ID.first, "class '%0' defines %1 but does not define %2") << ID.second << cppcoreguidelines::join(DefinedMemberKinds, " and ") << cppcoreguidelines::join(MissingMembers, " or "); diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h index 6042f0fd6cb0..9ebc03ed2fa1 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h @@ -30,9 +30,8 @@ public: void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; void onEndOfTranslationUnit() override; - std::optional getCheckTraversalKind() const override { - return TK_IgnoreUnlessSpelledInSource; - } + std::optional getCheckTraversalKind() const override; + enum class SpecialMemberFunctionKind : uint8_t { Destructor, DefaultDestructor, @@ -46,6 +45,7 @@ public: struct SpecialMemberFunctionData { SpecialMemberFunctionKind FunctionKind; bool IsDeleted; + bool IsImplicit = false; bool operator==(const SpecialMemberFunctionData &Other) const { return (Other.FunctionKind == FunctionKind) && @@ -67,6 +67,7 @@ private: const bool AllowMissingMoveFunctions; const bool AllowSoleDefaultDtor; const bool AllowMissingMoveFunctionsWhenCopyIsDeleted; + const bool AllowImplicitlyDeletedCopyOrMove; ClassDefiningSpecialMembersMap ClassWithSpecialMembers; }; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index b7ef5a860e8b..71734617bf7a 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -262,6 +262,12 @@ Changes in existing checks `. Fixed incorrect hints when using list-initialization. +- Improved :doc:`cppcoreguidelines-special-member-functions + ` check with a + new option `AllowImplicitlyDeletedCopyOrMove`, which removes the requirement + for explicit copy or move special member functions when they are already + implicitly deleted. + - Improved :doc:`google-build-namespaces ` check by replacing the local option `HeaderFileExtensions` by the global option of the same name. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst index 176956d6cb2b..20f898fdab93 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst @@ -45,9 +45,10 @@ Options .. option:: AllowMissingMoveFunctions - When set to `true` (default is `false`), this check doesn't flag classes which define no move - operations at all. It still flags classes which define only one of either - move constructor or move assignment operator. With this option enabled, the following class won't be flagged: + When set to `true` (default is `false`), this check doesn't flag classes + which define no move operations at all. It still flags classes which define + only one of either move constructor or move assignment operator. With this + option enabled, the following class won't be flagged: .. code-block:: c++ @@ -59,10 +60,11 @@ Options .. option:: AllowMissingMoveFunctionsWhenCopyIsDeleted - When set to `true` (default is `false`), this check doesn't flag classes which define deleted copy - operations but don't define move operations. This flag is related to Google C++ Style Guide - https://google.github.io/styleguide/cppguide.html#Copyable_Movable_Types. With this option enabled, the - following class won't be flagged: + When set to `true` (default is `false`), this check doesn't flag classes + which define deleted copy operations but don't define move operations. This + flag is related to Google C++ Style Guide `Copyable and Movable Types + `_. + With this option enabled, the following class won't be flagged: .. code-block:: c++ @@ -71,3 +73,15 @@ Options A& operator=(const A&) = delete; ~A(); }; + +.. option:: AllowImplicitlyDeletedCopyOrMove + + When set to `true` (default is `false`), this check doesn't flag classes + which implicitly delete copy or move operations. + With this option enabled, the following class won't be flagged: + + .. code-block:: c++ + + struct A : boost::noncopyable { + ~A() { std::cout << "dtor\n"; } + }; diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-relaxed.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-relaxed.cpp index 0c17f57968a9..26142ccc835f 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-relaxed.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/special-member-functions-relaxed.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-special-member-functions %t -- -config="{CheckOptions: {cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions: true, cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor: true}}" -- +// RUN: %check_clang_tidy %s cppcoreguidelines-special-member-functions %t -- -config="{CheckOptions: {cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions: true, cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor: true, cppcoreguidelines-special-member-functions.AllowImplicitlyDeletedCopyOrMove: true}}" -- // Don't warn on destructors without definitions, they might be defaulted in another TU. class DeclaresDestructor { @@ -34,12 +34,13 @@ class DefinesCopyAssignment { class DefinesMoveConstructor { DefinesMoveConstructor(DefinesMoveConstructor &&); }; -// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveConstructor' defines a move constructor but does not define a destructor, a copy constructor, a copy assignment operator or a move assignment operator [cppcoreguidelines-special-member-functions] +// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveConstructor' defines a move constructor but does not define a destructor or a move assignment operator [cppcoreguidelines-special-member-functions] class DefinesMoveAssignment { DefinesMoveAssignment &operator=(DefinesMoveAssignment &&); }; -// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveAssignment' defines a move assignment operator but does not define a destructor, a copy constructor, a copy assignment operator or a move constructor [cppcoreguidelines-special-member-functions] +// CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveAssignment' defines a move assignment operator but does not define a destructor or a move constructor [cppcoreguidelines-special-member-functions] + class DefinesNothing { }; @@ -81,3 +82,22 @@ struct TemplateClass { // This should not cause problems. TemplateClass InstantiationWithInt; TemplateClass InstantiationWithDouble; + +struct NoCopy +{ + NoCopy() = default; + ~NoCopy() = default; + + NoCopy(const NoCopy&) = delete; + NoCopy(NoCopy&&) = delete; + + NoCopy& operator=(const NoCopy&) = delete; + NoCopy& operator=(NoCopy&&) = delete; +}; + +// CHECK-MESSAGES: [[@LINE+1]]:8: warning: class 'NonCopyable' defines a copy constructor but does not define a destructor or a copy assignment operator [cppcoreguidelines-special-member-functions] +struct NonCopyable : NoCopy +{ + NonCopyable() = default; + NonCopyable(const NonCopyable&) = delete; +}; -- GitLab From 9bbefb7f600019c9d7025281132dd160729bfff2 Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Wed, 15 May 2024 23:12:57 +0700 Subject: [PATCH 377/578] [clang] Store FPOptions earlier when parsing function (#92146) After https://github.com/llvm/llvm-project/pull/85605 ([clang] Set correct FPOptions if attribute 'optnone' presents) the current FP options in Sema are saved during parsing function because Sema can modify them if optnone is present. However they were saved too late, it caused fails in some cases when precompiled headers are used. This patch moves the storing earlier. --- clang/lib/Parse/Parser.cpp | 4 ++-- clang/test/PCH/optnone.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 clang/test/PCH/optnone.cpp diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index adcbe5858bc7..869b9c6669c2 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1439,6 +1439,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, } } + Sema::FPFeaturesStateRAII SaveFPFeatures(Actions); + // Tell the actions module that we have entered a function definition with the // specified Declarator for the function. SkipBodyInfo SkipBody; @@ -1497,8 +1499,6 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, return Actions.ActOnFinishFunctionBody(Res, nullptr, false); } - Sema::FPFeaturesStateRAII SaveFPFeatures(Actions); - if (Tok.is(tok::kw_try)) return ParseFunctionTryBlock(Res, BodyScope); diff --git a/clang/test/PCH/optnone.cpp b/clang/test/PCH/optnone.cpp new file mode 100644 index 000000000000..8351bd9de70d --- /dev/null +++ b/clang/test/PCH/optnone.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -emit-pch -x c++-header %s -o %t.pch +// RUN: %clang_cc1 -emit-llvm -DMAIN -include-pch %t.pch %s -o /dev/null + +#ifndef MAIN +__attribute__((optnone)) void foo() {} +#endif -- GitLab From 03c53c69a367008da689f0d2940e2197eb4a955c Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 15 May 2024 09:18:39 -0700 Subject: [PATCH 378/578] [MC] Remove UseAssemblerInfoForParsing Commit 6c0665e22174d474050e85ca367424f6e02476be (https://reviews.llvm.org/D45164) enabled certain constant expression evaluation for `MCObjectStreamer` at parse time (e.g. `.if` directives, see llvm/test/MC/AsmParser/assembler-expressions.s). `getUseAssemblerInfoForParsing` was added to make `clang -c` handling inline assembly similar to `MCAsmStreamer` (e.g. `llvm-mc -filetype=asm`), where such expression folding (related to `AttemptToFoldSymbolOffsetDifference`) is unavailable. I believe this is overly conservative. We can make some parse-time expression folding work for `clang -c` even if `clang -S` would still report an error, a MCAsmStreamer issue (we cannot print `.if` directives) that should not restrict the functionality of MCObjectStreamer. ``` % cat b.cc asm(R"( .pushsection .text,"ax" .globl _start; _start: ret .if . -_start == 1 ret .endif .popsection )"); % gcc -S b.cc && gcc -c b.cc % clang -S -fno-integrated-as b.cc # succeeded % clang -c b.cc # succeeded with this patch % clang -S b.cc # still failed :4:5: error: expected absolute expression 4 | .if . -_start == 1 | ^ 1 error generated. ``` Close #62520 Link: https://discourse.llvm.org/t/rfc-clang-assembly-object-equivalence-for-files-with-inline-assembly/78841 Pull Request: https://github.com/llvm/llvm-project/pull/91082 --- clang/tools/driver/cc1as_main.cpp | 3 --- llvm/include/llvm/MC/MCStreamer.h | 7 ++----- .../CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp | 3 --- llvm/lib/MC/MCObjectStreamer.cpp | 9 +-------- llvm/lib/MC/MCStreamer.cpp | 2 +- llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp | 7 ++----- llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp | 3 --- .../AsmParser/assembler-expressions-inlineasm.ll | 16 ++++++++++------ llvm/tools/llvm-mc/llvm-mc.cpp | 3 --- llvm/tools/llvm-ml/llvm-ml.cpp | 3 --- 10 files changed, 16 insertions(+), 40 deletions(-) diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 86afe22fac24..4eb753a7297a 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -576,9 +576,6 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, Str.get()->emitZeros(1); } - // Assembly to object compilation should leverage assembly info. - Str->setUseAssemblerInfoForParsing(true); - bool Failed = false; std::unique_ptr Parser( diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 69867620e1bf..50986e6bde88 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -245,8 +245,6 @@ class MCStreamer { /// requires. unsigned NextWinCFIID = 0; - bool UseAssemblerInfoForParsing; - /// Is the assembler allowed to insert padding automatically? For /// correctness reasons, we sometimes need to ensure instructions aren't /// separated in unexpected ways. At the moment, this feature is only @@ -296,11 +294,10 @@ public: MCContext &getContext() const { return Context; } + // MCObjectStreamer has an MCAssembler and allows more expression folding at + // parse time. virtual MCAssembler *getAssemblerPtr() { return nullptr; } - void setUseAssemblerInfoForParsing(bool v) { UseAssemblerInfoForParsing = v; } - bool getUseAssemblerInfoForParsing() { return UseAssemblerInfoForParsing; } - MCTargetStreamer *getTargetStreamer() { return TargetStreamer.get(); } diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index d0ef3e5a1939..08e3c208ba4d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -102,9 +102,6 @@ void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, std::unique_ptr Parser( createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); - // Do not use assembler-level information for parsing inline assembly. - OutStreamer->setUseAssemblerInfoForParsing(false); - // We create a new MCInstrInfo here since we might be at the module level // and not have a MachineFunction to initialize the TargetInstrInfo from and // we only need MCInstrInfo for asm parsing. We create one unconditionally diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index d2da5d0d3f90..a9003a164b30 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -40,14 +40,7 @@ MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCObjectStreamer::~MCObjectStreamer() = default; -// AssemblerPtr is used for evaluation of expressions and causes -// difference between asm and object outputs. Return nullptr to in -// inline asm mode to limit divergence to assembly inputs. -MCAssembler *MCObjectStreamer::getAssemblerPtr() { - if (getUseAssemblerInfoForParsing()) - return Assembler.get(); - return nullptr; -} +MCAssembler *MCObjectStreamer::getAssemblerPtr() { return Assembler.get(); } void MCObjectStreamer::addPendingLabel(MCSymbol* S) { MCSection *CurSection = getCurrentSectionOnly(); diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 176d55aa890b..199d865ea349 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -93,7 +93,7 @@ void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), CurrentWinFrameInfo(nullptr), - CurrentProcWinFrameInfoStartIndex(0), UseAssemblerInfoForParsing(false) { + CurrentProcWinFrameInfoStartIndex(0) { SectionStack.push_back(std::pair()); } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp index b7388ed9e85a..bd48a5f80c82 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -517,12 +517,9 @@ bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) { DumpCodeInstEmitter = nullptr; if (STM.dumpCode()) { - // For -dumpcode, get the assembler out of the streamer, even if it does - // not really want to let us have it. This only works with -filetype=obj. - bool SaveFlag = OutStreamer->getUseAssemblerInfoForParsing(); - OutStreamer->setUseAssemblerInfoForParsing(true); + // For -dumpcode, get the assembler out of the streamer. This only works + // with -filetype=obj. MCAssembler *Assembler = OutStreamer->getAssemblerPtr(); - OutStreamer->setUseAssemblerInfoForParsing(SaveFlag); if (Assembler) DumpCodeInstEmitter = Assembler->getEmitterPtr(); } diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp index 2ebe5bdc4771..ad0158086044 100644 --- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp @@ -114,12 +114,9 @@ void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) { // Bound is an approximation that accounts for the maximum used register // number and number of generated OpLabels unsigned Bound = 2 * (ST->getBound() + 1) + NLabels; - bool FlagToRestore = OutStreamer->getUseAssemblerInfoForParsing(); - OutStreamer->setUseAssemblerInfoForParsing(true); if (MCAssembler *Asm = OutStreamer->getAssemblerPtr()) Asm->setBuildVersion(static_cast(0), Major, Minor, Bound, VersionTuple(Major, Minor, 0, Bound)); - OutStreamer->setUseAssemblerInfoForParsing(FlagToRestore); } void SPIRVAsmPrinter::emitFunctionHeader() { diff --git a/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll b/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll index 35f110f37e2f..9d9a38f5b5a5 100644 --- a/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll +++ b/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll @@ -1,13 +1,17 @@ -; RUN: not llc -mtriple x86_64-unknown-linux-gnu -o %t.s -filetype=asm %s 2>&1 | FileCheck %s -; RUN: not llc -mtriple x86_64-unknown-linux-gnu -o %t.o -filetype=obj %s 2>&1 | FileCheck %s - -; Assembler-aware expression evaluation should be disabled in inline -; assembly to prevent differences in behavior between object and -; assembly output. +; RUN: not llc -mtriple=x86_64 %s -o /dev/null 2>&1 | FileCheck %s +; RUN: llc -mtriple=x86_64 -no-integrated-as < %s | FileCheck %s --check-prefix=GAS +; RUN: llc -mtriple=x86_64 -filetype=obj %s -o - | llvm-objdump -d - | FileCheck %s --check-prefix=DISASM +; GAS: nop; .if . - foo==1; nop;.endif ; CHECK: :1:17: error: expected absolute expression +; DISASM:

: +; DISASM-NEXT: nop +; DISASM-NEXT: nop +; DISASM-NEXT: xorl %eax, %eax +; DISASM-NEXT: retq + define i32 @main() local_unnamed_addr { tail call void asm sideeffect "foo: nop; .if . - foo==1; nop;.endif", "~{dirflag},~{fpsr},~{flags}"() ret i32 0 diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp index 807071a7b9a1..506e4f22ef8f 100644 --- a/llvm/tools/llvm-mc/llvm-mc.cpp +++ b/llvm/tools/llvm-mc/llvm-mc.cpp @@ -569,9 +569,6 @@ int main(int argc, char **argv) { Str->initSections(true, *STI); } - // Use Assembler information for parsing. - Str->setUseAssemblerInfoForParsing(true); - int Res = 1; bool disassemble = false; switch (Action) { diff --git a/llvm/tools/llvm-ml/llvm-ml.cpp b/llvm/tools/llvm-ml/llvm-ml.cpp index 1cac576f54e7..f1f39af059aa 100644 --- a/llvm/tools/llvm-ml/llvm-ml.cpp +++ b/llvm/tools/llvm-ml/llvm-ml.cpp @@ -428,9 +428,6 @@ int llvm_ml_main(int Argc, char **Argv, const llvm::ToolContext &) { Str->emitAssignment(Feat00Sym, MCConstantExpr::create(Feat00Flags, Ctx)); } - // Use Assembler information for parsing. - Str->setUseAssemblerInfoForParsing(true); - int Res = 1; if (InputArgs.hasArg(OPT_as_lex)) { // -as-lex; Lex only, and output a stream of tokens -- GitLab From 141391ad2f22885342935442642c6c892f43e1ed Mon Sep 17 00:00:00 2001 From: Nuri Amari Date: Wed, 15 May 2024 09:21:02 -0700 Subject: [PATCH 379/578] [lld] Fix -ObjC load behavior with LTO (#92162) When -ObjC is passed, the linker must force load any object files that contain special sections that store Objective-C / Swift information that is used at runtime. This should work regadless if input files are bitcode or native, but it was not working with bitcode. This is because the sections that identify an object file that should be loaded were inconsistent when dealing with a native file vs bitcode file. In particular, bitcode files were not searched for `__TEXT,__swift` prefixed sections, while native files were. This means LLD wasn't loading certain bitcode files and forcing the user to introduce --force-load to their linker invocation for that archive. Co-authored-by: Nuri Amari --- lld/test/MachO/objc.s | 23 ++++++++++++++++++++--- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 3 ++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lld/test/MachO/objc.s b/lld/test/MachO/objc.s index e7074141f011..dbb9f1df2757 100644 --- a/lld/test/MachO/objc.s +++ b/lld/test/MachO/objc.s @@ -5,12 +5,14 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/has-objc-category.s -o %t/has-objc-category.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/has-objc-symbol-and-category.s -o %t/has-objc-symbol-and-category.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/has-swift.s -o %t/has-swift.o +# RUN: llvm-as %t/has-swift-ir-loaded.ll -o %t/has-swift-ir-loaded.o +# RUN: llvm-as %t/has-swift-ir-not-loaded.ll -o %t/has-swift-ir-not-loaded.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/has-swift-proto.s -o %t/has-swift-proto.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/no-objc.s -o %t/no-objc.o ## Make sure we don't mis-parse a 32-bit file as 64-bit # RUN: llvm-mc -filetype=obj -triple=armv7-apple-watchos %t/no-objc.s -o %t/wrong-arch.o -# RUN: llvm-ar rcs %t/libHasSomeObjC.a %t/no-objc.o %t/has-objc-symbol.o %t/has-objc-category.o %t/has-swift.o %t/has-swift-proto.o %t/wrong-arch.o -# RUN: llvm-ar rcs %t/libHasSomeObjC2.a %t/no-objc.o %t/has-objc-symbol-and-category.o %t/has-swift.o %t/has-swift-proto.o %t/wrong-arch.o +# RUN: llvm-ar rcs %t/libHasSomeObjC.a %t/no-objc.o %t/has-objc-symbol.o %t/has-objc-category.o %t/has-swift.o %t/has-swift-proto.o %t/has-swift-ir-loaded.o %t/has-swift-ir-not-loaded.o %t/wrong-arch.o +# RUN: llvm-ar rcs %t/libHasSomeObjC2.a %t/no-objc.o %t/has-objc-symbol-and-category.o %t/has-swift.o %t/has-swift-proto.o %t/has-swift-ir-loaded.o %t/has-swift-ir-not-loaded.o %t/wrong-arch.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o @@ -20,7 +22,7 @@ # RUN: %lld -lSystem %t/test.o -o %t/test -L%t -lHasSomeObjC2 -ObjC # RUN: llvm-objdump --section-headers --syms %t/test | FileCheck %s --check-prefix=OBJC -# RUN: %no-fatal-warnings-lld -lSystem %t/test.o -o %t/test --start-lib %t/no-objc.o %t/has-objc-symbol.o %t/has-objc-category.o %t/has-swift.o %t/has-swift-proto.o %t/wrong-arch.o --end-lib -ObjC 2>&1 \ +# RUN: %no-fatal-warnings-lld -lSystem %t/test.o -o %t/test --start-lib %t/no-objc.o %t/has-objc-symbol.o %t/has-objc-category.o %t/has-swift.o %t/has-swift-proto.o %t/has-swift-ir-loaded.o %t/has-swift-ir-not-loaded.o %t/wrong-arch.o --end-lib -ObjC 2>&1 \ # RUN: | FileCheck -check-prefix=WARNING %s # RUN: llvm-objdump --section-headers --syms %t/test | FileCheck %s --check-prefix=OBJC @@ -36,6 +38,7 @@ # OBJC-NEXT: 4 has_objc_symbol {{.*}} DATA # OBJC-EMPTY: # OBJC-NEXT: SYMBOL TABLE: +# OBJC-DAG: g O __TEXT,__swift _foo # OBJC-DAG: g F __TEXT,__text _main # OBJC-DAG: g F __TEXT,__text _OBJC_CLASS_$_MyObject # OBJC-DAG: g O __TEXT,__swift5_fieldmd $s7somelib4Blah_pMF @@ -100,6 +103,20 @@ _has_dup: .section __TEXT,__swift .quad 0x1234 +#--- has-swift-ir-loaded.ll +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "x86_64-apple-darwin" + +@foo = global i64 1234, section "__TEXT,__swift" +@llvm.used = appending global [1 x ptr] [ptr @foo] + +#--- has-swift-ir-not-loaded.ll +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "x86_64-apple-darwin" + +@bar = global i64 1234 +@llvm.used = appending global [1 x ptr] [ptr @bar] + #--- has-swift-proto.s .section __TEXT,__swift5_fieldmd .globl $s7somelib4Blah_pMF diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 19a15209f8b6..e64051cf5386 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -306,7 +306,8 @@ static Expected hasObjCCategoryInModule(BitstreamCursor &Stream) { return error("Invalid section name record"); // Check for the i386 and other (x86_64, ARM) conventions if (S.find("__DATA,__objc_catlist") != std::string::npos || - S.find("__OBJC,__category") != std::string::npos) + S.find("__OBJC,__category") != std::string::npos || + S.find("__TEXT,__swift") != std::string::npos) return true; break; } -- GitLab From f0e79db215ada7316b4d4046490ab715194a519a Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 15 May 2024 08:58:07 -0700 Subject: [PATCH 380/578] [RISCV] Fix 80 columns in RISCVMatInt.cpp. NFC --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp index 0a304d4cb7d9..0a857eb96935 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp @@ -114,11 +114,13 @@ static void generateInstSeqImpl(int64_t Val, const MCSubtargetInfo &STI, ShiftAmount = llvm::countr_zero((uint64_t)Val); Val >>= ShiftAmount; - // If the remaining bits don't fit in 12 bits, we might be able to reduce the - // shift amount in order to use LUI which will zero the lower 12 bits. + // If the remaining bits don't fit in 12 bits, we might be able to reduce + // the // shift amount in order to use LUI which will zero the lower 12 + // bits. if (ShiftAmount > 12 && !isInt<12>(Val)) { if (isInt<32>((uint64_t)Val << 12)) { - // Reduce the shift amount and add zeros to the LSBs so it will match LUI. + // Reduce the shift amount and add zeros to the LSBs so it will match + // LUI. ShiftAmount -= 12; Val = (uint64_t)Val << 12; } else if (isUInt<32>((uint64_t)Val << 12) && -- GitLab From 29c2475f215110d9e6b3955d5eb2832b3f719c2f Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Wed, 15 May 2024 18:34:59 +0200 Subject: [PATCH 381/578] [mlir] Fix the build after 03c53c69a367008da689f0d2940e2197eb4a955c --- mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp | 1 - mlir/lib/Target/LLVM/ROCDL/Target.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp b/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp index b07addc77b56..a4f19981eec3 100644 --- a/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp +++ b/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp @@ -363,7 +363,6 @@ LogicalResult SerializeToHsacoPass::assembleIsa(const std::string &isa, mab->createObjectWriter(os), std::unique_ptr(ce), *sti, mcOptions.MCRelaxAll, mcOptions.MCIncrementalLinkerCompatible, /*DWARFMustBeAtTheEnd*/ false)); - mcStreamer->setUseAssemblerInfoForParsing(true); std::unique_ptr parser( createMCAsmParser(srcMgr, ctx, *mcStreamer, *mai)); diff --git a/mlir/lib/Target/LLVM/ROCDL/Target.cpp b/mlir/lib/Target/LLVM/ROCDL/Target.cpp index 66593fd8a55f..cc13e5b7436e 100644 --- a/mlir/lib/Target/LLVM/ROCDL/Target.cpp +++ b/mlir/lib/Target/LLVM/ROCDL/Target.cpp @@ -299,7 +299,6 @@ SerializeGPUModuleBase::assembleIsa(StringRef isa) { mab->createObjectWriter(os), std::unique_ptr(ce), *sti, mcOptions.MCRelaxAll, mcOptions.MCIncrementalLinkerCompatible, /*DWARFMustBeAtTheEnd*/ false)); - mcStreamer->setUseAssemblerInfoForParsing(true); std::unique_ptr parser( createMCAsmParser(srcMgr, ctx, *mcStreamer, *mai)); -- GitLab From 3f954f575156bce8ac81d6b4d94de443786befed Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Wed, 15 May 2024 12:33:54 -0400 Subject: [PATCH 382/578] Correct mismatched allocation/deallocation calls This amends dceaa0f4491ebe30c0b0f1bc7fa5ec365b60ced6 because ASAN caught an issue where the allocation and deallocation were not properly paired: https://lab.llvm.org/buildbot/#/builders/239/builds/7001 Use malloc and free throughout this file to ensure that all kinds of memory buffers use the proper pairing. --- llvm/lib/Support/MemoryBuffer.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp index 50308bd2bf4a..fb7e804fd7e8 100644 --- a/llvm/lib/Support/MemoryBuffer.cpp +++ b/llvm/lib/Support/MemoryBuffer.cpp @@ -79,8 +79,16 @@ void *operator new(size_t N, const NamedBufferAlloc &Alloc) { SmallString<256> NameBuf; StringRef NameRef = Alloc.Name.toStringRef(NameBuf); - char *Mem = static_cast(operator new(N + sizeof(size_t) + - NameRef.size() + 1)); + // We use malloc() and manually handle it returning null instead of calling + // operator new because we need all uses of NamedBufferAlloc to be + // deallocated with a call to free() due to needing to use malloc() in + // WritableMemoryBuffer::getNewUninitMemBuffer() to work around the out-of- + // memory handler installed by default in LLVM. See operator delete() member + // functions within this file for the paired call to free(). + char *Mem = + static_cast(std::malloc(N + sizeof(size_t) + NameRef.size() + 1)); + if (!Mem) + llvm::report_bad_alloc_error("Allocation failed"); *reinterpret_cast(Mem + N) = NameRef.size(); CopyStringRef(Mem + N + sizeof(size_t), NameRef); return Mem; @@ -225,7 +233,7 @@ public: /// Disable sized deallocation for MemoryBufferMMapFile, because it has /// tail-allocated data. - void operator delete(void *p) { ::operator delete(p); } + void operator delete(void *p) { std::free(p); } StringRef getBufferIdentifier() const override { // The name is stored after the class itself. -- GitLab From 332de4b2677ce7a95cc2df30d761fbb55376fe07 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 15 May 2024 11:38:41 -0500 Subject: [PATCH 383/578] [Offload] Correctly reject building on unsupported architectures (#92276) Summary: Previously we had this `LIBOMPTARGET_ENABLED` variable which controlled including `libomptarget`. This is now redundant since it's controlled by `LLVM_ENABLE_RUNTIMES`. However, this had the extra effect of not building it when given unsupported targets. THis was lost during the move to `offload`. This patch moves this logic back and makes the `offload` target just quit without doing anything if used on an unsupported architecture. https://github.com/llvm/llvm-project/issues/91881 https://github.com/llvm/llvm-project/issues/91819 --------- Co-authored-by: Sylvestre Ledru --- offload/CMakeLists.txt | 30 ++++++++++-------------------- openmp/CMakeLists.txt | 12 ------------ 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/offload/CMakeLists.txt b/offload/CMakeLists.txt index 626df8125063..1d8cab240924 100644 --- a/offload/CMakeLists.txt +++ b/offload/CMakeLists.txt @@ -17,26 +17,16 @@ if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") project(offload C CXX ASM) endif() -set(ENABLE_LIBOMPTARGET ON) -# Currently libomptarget cannot be compiled on Windows or MacOS X. -# Since the device plugins are only supported on Linux anyway, -# there is no point in trying to compile libomptarget on other OSes. -# 32-bit systems are not supported either. -if (APPLE OR WIN32 OR NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8) - set(ENABLE_LIBOMPTARGET OFF) -endif() - -option(OPENMP_ENABLE_LIBOMPTARGET "Enable building libomptarget for offloading." - ${ENABLE_LIBOMPTARGET}) -if (OPENMP_ENABLE_LIBOMPTARGET) - # Check that the library can actually be built. - if (APPLE OR WIN32) - message(FATAL_ERROR "libomptarget cannot be built on Windows and MacOS X!") - elseif (NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES) - message(FATAL_ERROR "Host compiler must support C++17 to build libomptarget!") - elseif (NOT CMAKE_SIZEOF_VOID_P EQUAL 8) - message(FATAL_ERROR "libomptarget on 32-bit systems are not supported!") - endif() +# Check that the library can actually be built. +if(APPLE OR WIN32 OR WASM) + message(WARNING "libomptarget cannot be built on Windows and MacOS X!") + return() +elseif(NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES) + message(WARNING "Host compiler must support C++17 to build libomptarget!") + return() +elseif(NOT CMAKE_SIZEOF_VOID_P EQUAL 8) + message(WARNING "libomptarget on 32-bit systems is not supported!") + return() endif() if(OPENMP_STANDALONE_BUILD) diff --git a/openmp/CMakeLists.txt b/openmp/CMakeLists.txt index 9097ca562300..33bfdc8630ef 100644 --- a/openmp/CMakeLists.txt +++ b/openmp/CMakeLists.txt @@ -97,18 +97,6 @@ set(OPENMP_TEST_FLAGS "" CACHE STRING set(OPENMP_TEST_OPENMP_FLAGS ${OPENMP_TEST_COMPILER_OPENMP_FLAGS} CACHE STRING "OpenMP compiler flag to use for testing OpenMP runtime libraries.") -set(ENABLE_LIBOMPTARGET ON) -# Currently libomptarget cannot be compiled on Windows or MacOS X. -# Since the device plugins are only supported on Linux anyway, -# there is no point in trying to compile libomptarget on other OSes. -# 32-bit systems are not supported either. -if (APPLE OR WIN32 OR WASM OR NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES - OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8 OR ${CMAKE_SYSTEM_NAME} MATCHES "AIX") - set(ENABLE_LIBOMPTARGET OFF) -endif() - -option(OPENMP_ENABLE_LIBOMPTARGET "Enable building libomptarget for offloading." - ${ENABLE_LIBOMPTARGET}) option(OPENMP_ENABLE_LIBOMP_PROFILING "Enable time profiling for libomp." OFF) # Header install location -- GitLab From be10746f3a4381456eb5082a968766201c17ab5d Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 15 May 2024 12:43:55 -0400 Subject: [PATCH 384/578] [clang] Don't assume location of compiler-rt for OpenBSD (#92183) If the `/usr/lib/...` path where compiler-rt is conventionally installed on OpenBSD does not exist, fall back to the regular logic to find it. This is a minimal change to allow OpenBSD cross compilation from a toolchain that doesn't adopt all of OpenBSD's monorepo's conventions. --- clang/lib/Driver/ToolChains/OpenBSD.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp index e20d9fb1cfc4..3770471bae7c 100644 --- a/clang/lib/Driver/ToolChains/OpenBSD.cpp +++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -375,7 +375,8 @@ std::string OpenBSD::getCompilerRT(const ArgList &Args, StringRef Component, if (Component == "builtins") { SmallString<128> Path(getDriver().SysRoot); llvm::sys::path::append(Path, "/usr/lib/libcompiler_rt.a"); - return std::string(Path); + if (getVFS().exists(Path)) + return std::string(Path); } SmallString<128> P(getDriver().ResourceDir); std::string CRTBasename = -- GitLab From e2d74a25eb562b117974add098ba2b9dd4cfc7f5 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 15 May 2024 17:46:49 +0100 Subject: [PATCH 385/578] [X86] EmitCmp - always use cmpw with foldable loads (#92251) By default, EmitCmp avoids cmpw with i16 immediates due to 66/67h length-changing prefixes causing stalls, instead extending the value to i32 and using a cmpl with a i32 immediate, unless it has the TuningFastImm16 flag or we're building for optsize/minsize. However, if we're loading the value for comparison, the performance costs of the decode stalls are likely to be exceeded by the impact of the load latency of the folded load, the shorter encoding and not needing an extra register to store the ext-load. This matches the behaviour of gcc and msvc. Fixes #90355 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 9 +- llvm/test/CodeGen/X86/cmp16.ll | 196 ++++-------------- .../CodeGen/X86/memcmp-more-load-pairs-x32.ll | 3 +- .../CodeGen/X86/memcmp-more-load-pairs.ll | 3 +- llvm/test/CodeGen/X86/memcmp-optsize-x32.ll | 3 +- llvm/test/CodeGen/X86/memcmp-optsize.ll | 3 +- llvm/test/CodeGen/X86/memcmp-pgso-x32.ll | 3 +- llvm/test/CodeGen/X86/memcmp-pgso.ll | 3 +- llvm/test/CodeGen/X86/memcmp-x32.ll | 3 +- llvm/test/CodeGen/X86/memcmp.ll | 3 +- 10 files changed, 60 insertions(+), 169 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index a57c10e784d9..e7c70e3872ad 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -22692,11 +22692,14 @@ static SDValue EmitCmp(SDValue Op0, SDValue Op1, unsigned X86CC, CmpVT == MVT::i32 || CmpVT == MVT::i64) && "Unexpected VT!"); // Only promote the compare up to I32 if it is a 16 bit operation - // with an immediate. 16 bit immediates are to be avoided. + // with an immediate. 16 bit immediates are to be avoided unless the target + // isn't slowed down by length changing prefixes, we're optimizing for + // codesize or the comparison is with a folded load. if (CmpVT == MVT::i16 && !Subtarget.hasFastImm16() && + !X86::mayFoldLoad(Op0, Subtarget) && !X86::mayFoldLoad(Op1, Subtarget) && !DAG.getMachineFunction().getFunction().hasMinSize()) { - ConstantSDNode *COp0 = dyn_cast(Op0); - ConstantSDNode *COp1 = dyn_cast(Op1); + auto *COp0 = dyn_cast(Op0); + auto *COp1 = dyn_cast(Op1); // Don't do this if the immediate can fit in 8-bits. if ((COp0 && !COp0->getAPIntValue().isSignedIntN(8)) || (COp1 && !COp1->getAPIntValue().isSignedIntN(8))) { diff --git a/llvm/test/CodeGen/X86/cmp16.ll b/llvm/test/CodeGen/X86/cmp16.ll index 699ea3e4dd47..fa9e75ff16a5 100644 --- a/llvm/test/CodeGen/X86/cmp16.ll +++ b/llvm/test/CodeGen/X86/cmp16.ll @@ -113,8 +113,7 @@ define i1 @cmp16_reg_eq_imm8(i16 %a0) { define i1 @cmp16_reg_eq_imm16(i16 %a0) { ; X86-GENERIC-LABEL: cmp16_reg_eq_imm16: ; X86-GENERIC: # %bb.0: -; X86-GENERIC-NEXT: movzwl {{[0-9]+}}(%esp), %eax -; X86-GENERIC-NEXT: cmpl $1024, %eax # imm = 0x400 +; X86-GENERIC-NEXT: cmpw $1024, {{[0-9]+}}(%esp) # imm = 0x400 ; X86-GENERIC-NEXT: sete %al ; X86-GENERIC-NEXT: retl ; @@ -177,12 +176,11 @@ define i1 @cmp16_reg_eq_imm16_minsize(i16 %a0) minsize { } define i1 @cmp16_reg_eq_imm16_optsize(i16 %a0) optsize { -; X86-GENERIC-LABEL: cmp16_reg_eq_imm16_optsize: -; X86-GENERIC: # %bb.0: -; X86-GENERIC-NEXT: movzwl {{[0-9]+}}(%esp), %eax -; X86-GENERIC-NEXT: cmpl $1024, %eax # imm = 0x400 -; X86-GENERIC-NEXT: sete %al -; X86-GENERIC-NEXT: retl +; X86-LABEL: cmp16_reg_eq_imm16_optsize: +; X86: # %bb.0: +; X86-NEXT: cmpw $1024, {{[0-9]+}}(%esp) # imm = 0x400 +; X86-NEXT: sete %al +; X86-NEXT: retl ; ; X64-GENERIC-LABEL: cmp16_reg_eq_imm16_optsize: ; X64-GENERIC: # %bb.0: @@ -191,24 +189,12 @@ define i1 @cmp16_reg_eq_imm16_optsize(i16 %a0) optsize { ; X64-GENERIC-NEXT: sete %al ; X64-GENERIC-NEXT: retq ; -; X86-FAST-LABEL: cmp16_reg_eq_imm16_optsize: -; X86-FAST: # %bb.0: -; X86-FAST-NEXT: cmpw $1024, {{[0-9]+}}(%esp) # imm = 0x400 -; X86-FAST-NEXT: sete %al -; X86-FAST-NEXT: retl -; ; X64-FAST-LABEL: cmp16_reg_eq_imm16_optsize: ; X64-FAST: # %bb.0: ; X64-FAST-NEXT: cmpw $1024, %di # imm = 0x400 ; X64-FAST-NEXT: sete %al ; X64-FAST-NEXT: retq ; -; X86-ATOM-LABEL: cmp16_reg_eq_imm16_optsize: -; X86-ATOM: # %bb.0: -; X86-ATOM-NEXT: cmpw $1024, {{[0-9]+}}(%esp) # imm = 0x400 -; X86-ATOM-NEXT: sete %al -; X86-ATOM-NEXT: retl -; ; X64-ATOM-LABEL: cmp16_reg_eq_imm16_optsize: ; X64-ATOM: # %bb.0: ; X64-ATOM-NEXT: cmpw $1024, %di # imm = 0x400 @@ -269,8 +255,7 @@ define i1 @cmp16_reg_sgt_imm8(i16 %a0) { define i1 @cmp16_reg_sgt_imm16(i16 %a0) { ; X86-GENERIC-LABEL: cmp16_reg_sgt_imm16: ; X86-GENERIC: # %bb.0: -; X86-GENERIC-NEXT: movswl {{[0-9]+}}(%esp), %eax -; X86-GENERIC-NEXT: cmpl $-1023, %eax # imm = 0xFC01 +; X86-GENERIC-NEXT: cmpw $-1023, {{[0-9]+}}(%esp) # imm = 0xFC01 ; X86-GENERIC-NEXT: setge %al ; X86-GENERIC-NEXT: retl ; @@ -333,12 +318,11 @@ define i1 @cmp16_reg_sgt_imm16_minsize(i16 %a0) minsize { } define i1 @cmp16_reg_sgt_imm16_optsize(i16 %a0) optsize { -; X86-GENERIC-LABEL: cmp16_reg_sgt_imm16_optsize: -; X86-GENERIC: # %bb.0: -; X86-GENERIC-NEXT: movswl {{[0-9]+}}(%esp), %eax -; X86-GENERIC-NEXT: cmpl $-1023, %eax # imm = 0xFC01 -; X86-GENERIC-NEXT: setge %al -; X86-GENERIC-NEXT: retl +; X86-LABEL: cmp16_reg_sgt_imm16_optsize: +; X86: # %bb.0: +; X86-NEXT: cmpw $-1023, {{[0-9]+}}(%esp) # imm = 0xFC01 +; X86-NEXT: setge %al +; X86-NEXT: retl ; ; X64-GENERIC-LABEL: cmp16_reg_sgt_imm16_optsize: ; X64-GENERIC: # %bb.0: @@ -347,24 +331,12 @@ define i1 @cmp16_reg_sgt_imm16_optsize(i16 %a0) optsize { ; X64-GENERIC-NEXT: setge %al ; X64-GENERIC-NEXT: retq ; -; X86-FAST-LABEL: cmp16_reg_sgt_imm16_optsize: -; X86-FAST: # %bb.0: -; X86-FAST-NEXT: cmpw $-1023, {{[0-9]+}}(%esp) # imm = 0xFC01 -; X86-FAST-NEXT: setge %al -; X86-FAST-NEXT: retl -; ; X64-FAST-LABEL: cmp16_reg_sgt_imm16_optsize: ; X64-FAST: # %bb.0: ; X64-FAST-NEXT: cmpw $-1023, %di # imm = 0xFC01 ; X64-FAST-NEXT: setge %al ; X64-FAST-NEXT: retq ; -; X86-ATOM-LABEL: cmp16_reg_sgt_imm16_optsize: -; X86-ATOM: # %bb.0: -; X86-ATOM-NEXT: cmpw $-1023, {{[0-9]+}}(%esp) # imm = 0xFC01 -; X86-ATOM-NEXT: setge %al -; X86-ATOM-NEXT: retl -; ; X64-ATOM-LABEL: cmp16_reg_sgt_imm16_optsize: ; X64-ATOM: # %bb.0: ; X64-ATOM-NEXT: cmpw $-1023, %di # imm = 0xFC01 @@ -377,8 +349,7 @@ define i1 @cmp16_reg_sgt_imm16_optsize(i16 %a0) optsize { define i1 @cmp16_reg_uge_imm16(i16 %a0) { ; X86-GENERIC-LABEL: cmp16_reg_uge_imm16: ; X86-GENERIC: # %bb.0: -; X86-GENERIC-NEXT: movzwl {{[0-9]+}}(%esp), %eax -; X86-GENERIC-NEXT: cmpl $64512, %eax # imm = 0xFC00 +; X86-GENERIC-NEXT: cmpw $-1024, {{[0-9]+}}(%esp) # imm = 0xFC00 ; X86-GENERIC-NEXT: setae %al ; X86-GENERIC-NEXT: retl ; @@ -441,12 +412,11 @@ define i1 @cmp16_reg_uge_imm16_minsize(i16 %a0) minsize { } define i1 @cmp16_reg_uge_imm16_optsize(i16 %a0) optsize { -; X86-GENERIC-LABEL: cmp16_reg_uge_imm16_optsize: -; X86-GENERIC: # %bb.0: -; X86-GENERIC-NEXT: movzwl {{[0-9]+}}(%esp), %eax -; X86-GENERIC-NEXT: cmpl $64512, %eax # imm = 0xFC00 -; X86-GENERIC-NEXT: setae %al -; X86-GENERIC-NEXT: retl +; X86-LABEL: cmp16_reg_uge_imm16_optsize: +; X86: # %bb.0: +; X86-NEXT: cmpw $-1024, {{[0-9]+}}(%esp) # imm = 0xFC00 +; X86-NEXT: setae %al +; X86-NEXT: retl ; ; X64-GENERIC-LABEL: cmp16_reg_uge_imm16_optsize: ; X64-GENERIC: # %bb.0: @@ -455,24 +425,12 @@ define i1 @cmp16_reg_uge_imm16_optsize(i16 %a0) optsize { ; X64-GENERIC-NEXT: setae %al ; X64-GENERIC-NEXT: retq ; -; X86-FAST-LABEL: cmp16_reg_uge_imm16_optsize: -; X86-FAST: # %bb.0: -; X86-FAST-NEXT: cmpw $-1024, {{[0-9]+}}(%esp) # imm = 0xFC00 -; X86-FAST-NEXT: setae %al -; X86-FAST-NEXT: retl -; ; X64-FAST-LABEL: cmp16_reg_uge_imm16_optsize: ; X64-FAST: # %bb.0: ; X64-FAST-NEXT: cmpw $-1024, %di # imm = 0xFC00 ; X64-FAST-NEXT: setae %al ; X64-FAST-NEXT: retq ; -; X86-ATOM-LABEL: cmp16_reg_uge_imm16_optsize: -; X86-ATOM: # %bb.0: -; X86-ATOM-NEXT: cmpw $-1024, {{[0-9]+}}(%esp) # imm = 0xFC00 -; X86-ATOM-NEXT: setae %al -; X86-ATOM-NEXT: retl -; ; X64-ATOM-LABEL: cmp16_reg_uge_imm16_optsize: ; X64-ATOM: # %bb.0: ; X64-ATOM-NEXT: cmpw $-1024, %di # imm = 0xFC00 @@ -592,15 +550,13 @@ define i1 @cmp16_load_ne_imm16(ptr %p0) { ; X86-GENERIC-LABEL: cmp16_load_ne_imm16: ; X86-GENERIC: # %bb.0: ; X86-GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-GENERIC-NEXT: movzwl (%eax), %eax -; X86-GENERIC-NEXT: cmpl $512, %eax # imm = 0x200 +; X86-GENERIC-NEXT: cmpw $512, (%eax) # imm = 0x200 ; X86-GENERIC-NEXT: setne %al ; X86-GENERIC-NEXT: retl ; ; X64-GENERIC-LABEL: cmp16_load_ne_imm16: ; X64-GENERIC: # %bb.0: -; X64-GENERIC-NEXT: movzwl (%rdi), %eax -; X64-GENERIC-NEXT: cmpl $512, %eax # imm = 0x200 +; X64-GENERIC-NEXT: cmpw $512, (%rdi) # imm = 0x200 ; X64-GENERIC-NEXT: setne %al ; X64-GENERIC-NEXT: retq ; @@ -694,15 +650,13 @@ define i1 @cmp16_load_slt_imm16(ptr %p0) { ; X86-GENERIC-LABEL: cmp16_load_slt_imm16: ; X86-GENERIC: # %bb.0: ; X86-GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-GENERIC-NEXT: movswl (%eax), %eax -; X86-GENERIC-NEXT: cmpl $512, %eax # imm = 0x200 +; X86-GENERIC-NEXT: cmpw $512, (%eax) # imm = 0x200 ; X86-GENERIC-NEXT: setl %al ; X86-GENERIC-NEXT: retl ; ; X64-GENERIC-LABEL: cmp16_load_slt_imm16: ; X64-GENERIC: # %bb.0: -; X64-GENERIC-NEXT: movswl (%rdi), %eax -; X64-GENERIC-NEXT: cmpl $512, %eax # imm = 0x200 +; X64-GENERIC-NEXT: cmpw $512, (%rdi) # imm = 0x200 ; X64-GENERIC-NEXT: setl %al ; X64-GENERIC-NEXT: retq ; @@ -761,46 +715,18 @@ define i1 @cmp16_load_slt_imm16_minsize(ptr %p0) minsize { } define i1 @cmp16_load_slt_imm16_optsize(ptr %p0) optsize { -; X86-GENERIC-LABEL: cmp16_load_slt_imm16_optsize: -; X86-GENERIC: # %bb.0: -; X86-GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-GENERIC-NEXT: movswl (%eax), %eax -; X86-GENERIC-NEXT: cmpl $512, %eax # imm = 0x200 -; X86-GENERIC-NEXT: setl %al -; X86-GENERIC-NEXT: retl -; -; X64-GENERIC-LABEL: cmp16_load_slt_imm16_optsize: -; X64-GENERIC: # %bb.0: -; X64-GENERIC-NEXT: movswl (%rdi), %eax -; X64-GENERIC-NEXT: cmpl $512, %eax # imm = 0x200 -; X64-GENERIC-NEXT: setl %al -; X64-GENERIC-NEXT: retq -; -; X86-FAST-LABEL: cmp16_load_slt_imm16_optsize: -; X86-FAST: # %bb.0: -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-FAST-NEXT: cmpw $512, (%eax) # imm = 0x200 -; X86-FAST-NEXT: setl %al -; X86-FAST-NEXT: retl -; -; X64-FAST-LABEL: cmp16_load_slt_imm16_optsize: -; X64-FAST: # %bb.0: -; X64-FAST-NEXT: cmpw $512, (%rdi) # imm = 0x200 -; X64-FAST-NEXT: setl %al -; X64-FAST-NEXT: retq -; -; X86-ATOM-LABEL: cmp16_load_slt_imm16_optsize: -; X86-ATOM: # %bb.0: -; X86-ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-ATOM-NEXT: cmpw $512, (%eax) # imm = 0x200 -; X86-ATOM-NEXT: setl %al -; X86-ATOM-NEXT: retl +; X86-LABEL: cmp16_load_slt_imm16_optsize: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: cmpw $512, (%eax) # imm = 0x200 +; X86-NEXT: setl %al +; X86-NEXT: retl ; -; X64-ATOM-LABEL: cmp16_load_slt_imm16_optsize: -; X64-ATOM: # %bb.0: -; X64-ATOM-NEXT: cmpw $512, (%rdi) # imm = 0x200 -; X64-ATOM-NEXT: setl %al -; X64-ATOM-NEXT: retq +; X64-LABEL: cmp16_load_slt_imm16_optsize: +; X64: # %bb.0: +; X64-NEXT: cmpw $512, (%rdi) # imm = 0x200 +; X64-NEXT: setl %al +; X64-NEXT: retq %ld = load i16, ptr %p0 %cmp = icmp slt i16 %ld, 512 ret i1 %cmp @@ -860,15 +786,13 @@ define i1 @cmp16_load_ule_imm16(ptr %p0) { ; X86-GENERIC-LABEL: cmp16_load_ule_imm16: ; X86-GENERIC: # %bb.0: ; X86-GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-GENERIC-NEXT: movzwl (%eax), %eax -; X86-GENERIC-NEXT: cmpl $513, %eax # imm = 0x201 +; X86-GENERIC-NEXT: cmpw $513, (%eax) # imm = 0x201 ; X86-GENERIC-NEXT: setb %al ; X86-GENERIC-NEXT: retl ; ; X64-GENERIC-LABEL: cmp16_load_ule_imm16: ; X64-GENERIC: # %bb.0: -; X64-GENERIC-NEXT: movzwl (%rdi), %eax -; X64-GENERIC-NEXT: cmpl $513, %eax # imm = 0x201 +; X64-GENERIC-NEXT: cmpw $513, (%rdi) # imm = 0x201 ; X64-GENERIC-NEXT: setb %al ; X64-GENERIC-NEXT: retq ; @@ -927,46 +851,18 @@ define i1 @cmp16_load_ule_imm16_minsize(ptr %p0) minsize { } define i1 @cmp16_load_ule_imm16_optsize(ptr %p0) optsize { -; X86-GENERIC-LABEL: cmp16_load_ule_imm16_optsize: -; X86-GENERIC: # %bb.0: -; X86-GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-GENERIC-NEXT: movzwl (%eax), %eax -; X86-GENERIC-NEXT: cmpl $513, %eax # imm = 0x201 -; X86-GENERIC-NEXT: setb %al -; X86-GENERIC-NEXT: retl -; -; X64-GENERIC-LABEL: cmp16_load_ule_imm16_optsize: -; X64-GENERIC: # %bb.0: -; X64-GENERIC-NEXT: movzwl (%rdi), %eax -; X64-GENERIC-NEXT: cmpl $513, %eax # imm = 0x201 -; X64-GENERIC-NEXT: setb %al -; X64-GENERIC-NEXT: retq -; -; X86-FAST-LABEL: cmp16_load_ule_imm16_optsize: -; X86-FAST: # %bb.0: -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-FAST-NEXT: cmpw $513, (%eax) # imm = 0x201 -; X86-FAST-NEXT: setb %al -; X86-FAST-NEXT: retl -; -; X64-FAST-LABEL: cmp16_load_ule_imm16_optsize: -; X64-FAST: # %bb.0: -; X64-FAST-NEXT: cmpw $513, (%rdi) # imm = 0x201 -; X64-FAST-NEXT: setb %al -; X64-FAST-NEXT: retq -; -; X86-ATOM-LABEL: cmp16_load_ule_imm16_optsize: -; X86-ATOM: # %bb.0: -; X86-ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-ATOM-NEXT: cmpw $513, (%eax) # imm = 0x201 -; X86-ATOM-NEXT: setb %al -; X86-ATOM-NEXT: retl +; X86-LABEL: cmp16_load_ule_imm16_optsize: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: cmpw $513, (%eax) # imm = 0x201 +; X86-NEXT: setb %al +; X86-NEXT: retl ; -; X64-ATOM-LABEL: cmp16_load_ule_imm16_optsize: -; X64-ATOM: # %bb.0: -; X64-ATOM-NEXT: cmpw $513, (%rdi) # imm = 0x201 -; X64-ATOM-NEXT: setb %al -; X64-ATOM-NEXT: retq +; X64-LABEL: cmp16_load_ule_imm16_optsize: +; X64: # %bb.0: +; X64-NEXT: cmpw $513, (%rdi) # imm = 0x201 +; X64-NEXT: setb %al +; X64-NEXT: retq %ld = load i16, ptr %p0 %cmp = icmp ule i16 %ld, 512 ret i1 %cmp diff --git a/llvm/test/CodeGen/X86/memcmp-more-load-pairs-x32.ll b/llvm/test/CodeGen/X86/memcmp-more-load-pairs-x32.ll index 0253d1312260..ee5fd78c6437 100644 --- a/llvm/test/CodeGen/X86/memcmp-more-load-pairs-x32.ll +++ b/llvm/test/CodeGen/X86/memcmp-more-load-pairs-x32.ll @@ -116,8 +116,7 @@ define i1 @length2_eq_const(ptr %X) nounwind { ; X86-LABEL: length2_eq_const: ; X86: # %bb.0: ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movzwl (%eax), %eax -; X86-NEXT: cmpl $12849, %eax # imm = 0x3231 +; X86-NEXT: cmpw $12849, (%eax) # imm = 0x3231 ; X86-NEXT: setne %al ; X86-NEXT: retl %m = tail call i32 @memcmp(ptr %X, ptr getelementptr inbounds ([513 x i8], ptr @.str, i32 0, i32 1), i32 2) nounwind diff --git a/llvm/test/CodeGen/X86/memcmp-more-load-pairs.ll b/llvm/test/CodeGen/X86/memcmp-more-load-pairs.ll index da46ea406557..a46f9ed3d379 100644 --- a/llvm/test/CodeGen/X86/memcmp-more-load-pairs.ll +++ b/llvm/test/CodeGen/X86/memcmp-more-load-pairs.ll @@ -113,8 +113,7 @@ define i1 @length2_gt(ptr %X, ptr %Y) nounwind { define i1 @length2_eq_const(ptr %X) nounwind { ; X64-LABEL: length2_eq_const: ; X64: # %bb.0: -; X64-NEXT: movzwl (%rdi), %eax -; X64-NEXT: cmpl $12849, %eax # imm = 0x3231 +; X64-NEXT: cmpw $12849, (%rdi) # imm = 0x3231 ; X64-NEXT: setne %al ; X64-NEXT: retq %m = tail call i32 @memcmp(ptr %X, ptr getelementptr inbounds ([513 x i8], ptr @.str, i32 0, i32 1), i64 2) nounwind diff --git a/llvm/test/CodeGen/X86/memcmp-optsize-x32.ll b/llvm/test/CodeGen/X86/memcmp-optsize-x32.ll index 3db6ae8b76b2..4a9643c0f4fc 100644 --- a/llvm/test/CodeGen/X86/memcmp-optsize-x32.ll +++ b/llvm/test/CodeGen/X86/memcmp-optsize-x32.ll @@ -45,8 +45,7 @@ define i1 @length2_eq_const(ptr %X) nounwind optsize { ; X86-LABEL: length2_eq_const: ; X86: # %bb.0: ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movzwl (%eax), %eax -; X86-NEXT: cmpl $12849, %eax # imm = 0x3231 +; X86-NEXT: cmpw $12849, (%eax) # imm = 0x3231 ; X86-NEXT: setne %al ; X86-NEXT: retl %m = tail call i32 @memcmp(ptr %X, ptr getelementptr inbounds ([65 x i8], ptr @.str, i32 0, i32 1), i32 2) nounwind diff --git a/llvm/test/CodeGen/X86/memcmp-optsize.ll b/llvm/test/CodeGen/X86/memcmp-optsize.ll index edd61641ad2a..4e27301436c3 100644 --- a/llvm/test/CodeGen/X86/memcmp-optsize.ll +++ b/llvm/test/CodeGen/X86/memcmp-optsize.ll @@ -41,8 +41,7 @@ define i1 @length2_eq(ptr %X, ptr %Y) nounwind optsize { define i1 @length2_eq_const(ptr %X) nounwind optsize { ; X64-LABEL: length2_eq_const: ; X64: # %bb.0: -; X64-NEXT: movzwl (%rdi), %eax -; X64-NEXT: cmpl $12849, %eax # imm = 0x3231 +; X64-NEXT: cmpw $12849, (%rdi) # imm = 0x3231 ; X64-NEXT: setne %al ; X64-NEXT: retq %m = tail call i32 @memcmp(ptr %X, ptr getelementptr inbounds ([65 x i8], ptr @.str, i32 0, i32 1), i64 2) nounwind diff --git a/llvm/test/CodeGen/X86/memcmp-pgso-x32.ll b/llvm/test/CodeGen/X86/memcmp-pgso-x32.ll index 1c301da26bea..bdb50f5b60c4 100644 --- a/llvm/test/CodeGen/X86/memcmp-pgso-x32.ll +++ b/llvm/test/CodeGen/X86/memcmp-pgso-x32.ll @@ -45,8 +45,7 @@ define i1 @length2_eq_const(ptr %X) nounwind !prof !14 { ; X86-LABEL: length2_eq_const: ; X86: # %bb.0: ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movzwl (%eax), %eax -; X86-NEXT: cmpl $12849, %eax # imm = 0x3231 +; X86-NEXT: cmpw $12849, (%eax) # imm = 0x3231 ; X86-NEXT: setne %al ; X86-NEXT: retl %m = tail call i32 @memcmp(ptr %X, ptr getelementptr inbounds ([65 x i8], ptr @.str, i32 0, i32 1), i32 2) nounwind diff --git a/llvm/test/CodeGen/X86/memcmp-pgso.ll b/llvm/test/CodeGen/X86/memcmp-pgso.ll index 1ee3317b9c96..9347e5422022 100644 --- a/llvm/test/CodeGen/X86/memcmp-pgso.ll +++ b/llvm/test/CodeGen/X86/memcmp-pgso.ll @@ -41,8 +41,7 @@ define i1 @length2_eq(ptr %X, ptr %Y) nounwind !prof !14 { define i1 @length2_eq_const(ptr %X) nounwind !prof !14 { ; X64-LABEL: length2_eq_const: ; X64: # %bb.0: -; X64-NEXT: movzwl (%rdi), %eax -; X64-NEXT: cmpl $12849, %eax # imm = 0x3231 +; X64-NEXT: cmpw $12849, (%rdi) # imm = 0x3231 ; X64-NEXT: setne %al ; X64-NEXT: retq %m = tail call i32 @memcmp(ptr %X, ptr getelementptr inbounds ([65 x i8], ptr @.str, i32 0, i32 1), i64 2) nounwind diff --git a/llvm/test/CodeGen/X86/memcmp-x32.ll b/llvm/test/CodeGen/X86/memcmp-x32.ll index a63402cea209..ad9f2a30d75b 100644 --- a/llvm/test/CodeGen/X86/memcmp-x32.ll +++ b/llvm/test/CodeGen/X86/memcmp-x32.ll @@ -144,8 +144,7 @@ define i1 @length2_eq_const(ptr %X) nounwind { ; X86-LABEL: length2_eq_const: ; X86: # %bb.0: ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movzwl (%eax), %eax -; X86-NEXT: cmpl $12849, %eax # imm = 0x3231 +; X86-NEXT: cmpw $12849, (%eax) # imm = 0x3231 ; X86-NEXT: setne %al ; X86-NEXT: retl %m = tail call i32 @memcmp(ptr %X, ptr getelementptr inbounds ([513 x i8], ptr @.str, i32 0, i32 1), i32 2) nounwind diff --git a/llvm/test/CodeGen/X86/memcmp.ll b/llvm/test/CodeGen/X86/memcmp.ll index 83cb0d6f973b..8fe1a581cd9c 100644 --- a/llvm/test/CodeGen/X86/memcmp.ll +++ b/llvm/test/CodeGen/X86/memcmp.ll @@ -139,8 +139,7 @@ define i1 @length2_gt(ptr %X, ptr %Y) nounwind { define i1 @length2_eq_const(ptr %X) nounwind { ; X64-LABEL: length2_eq_const: ; X64: # %bb.0: -; X64-NEXT: movzwl (%rdi), %eax -; X64-NEXT: cmpl $12849, %eax # imm = 0x3231 +; X64-NEXT: cmpw $12849, (%rdi) # imm = 0x3231 ; X64-NEXT: setne %al ; X64-NEXT: retq %m = tail call i32 @memcmp(ptr %X, ptr getelementptr inbounds ([513 x i8], ptr @.str, i32 0, i32 1), i64 2) nounwind -- GitLab From 34f33babc28d240d4ceee69f9afe7d6f5e8ac29b Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Wed, 15 May 2024 20:48:16 +0400 Subject: [PATCH 386/578] [lldb] Fixed the TestGdbRemoteCompletion test (#92268) Do not try to run lldb-server on localhost in case of the remote target. --- lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py index 04d6abe9d88c..58373d2f85bb 100644 --- a/lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py +++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py @@ -26,6 +26,7 @@ class GdbRemoteCompletionTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): def generate_hex_path(self, target): return str(os.path.join(self.getBuildDir(), target)).encode().hex() + @skipIfRemote @add_test_categories(["llgs"]) def test_autocomplete_path(self): self.build() -- GitLab From fc1df55bcf9b6cc2dec157bcd188b471bc91b945 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Wed, 15 May 2024 20:50:58 +0400 Subject: [PATCH 387/578] [lldb][Windows] Fixed the test gdb_remote_client/TestGDBRemotePlatformFile (#92088) The tests `test_file_permissions` and `test_file_permissions_fallback` are disabled for Windows target. These tests use MockGDBServerResponder and do not depend on the real target. These tests failed in case of Windows host and Linux target. Disable them for Windows host too. --- .../gdb_remote_client/TestGDBRemotePlatformFile.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py index 2be5ae313203..c902722a2f74 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py @@ -147,7 +147,9 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): log=server2.responder.packetLog, ) - @skipIfWindows + @expectedFailureAll( + hostoslist=["windows"], bugnumber="github.com/llvm/llvm-project/issues/92255" + ) def test_file_permissions(self): """Test 'platform get-permissions'""" @@ -167,7 +169,9 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): ] ) - @skipIfWindows + @expectedFailureAll( + hostoslist=["windows"], bugnumber="github.com/llvm/llvm-project/issues/92255" + ) def test_file_permissions_fallback(self): """Test 'platform get-permissions' fallback to fstat""" -- GitLab From 2ec85713bd910c5b22ce090798ca00f742d5eb14 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 15 May 2024 11:57:48 -0500 Subject: [PATCH 388/578] [OpenMP] Add back in `ENABLE_LIBOMPTARGET' definition Summary: Even though we moved `libomptarget` this is still present in `omp.h` and can't be removed. --- openmp/CMakeLists.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openmp/CMakeLists.txt b/openmp/CMakeLists.txt index 33bfdc8630ef..9097ca562300 100644 --- a/openmp/CMakeLists.txt +++ b/openmp/CMakeLists.txt @@ -97,6 +97,18 @@ set(OPENMP_TEST_FLAGS "" CACHE STRING set(OPENMP_TEST_OPENMP_FLAGS ${OPENMP_TEST_COMPILER_OPENMP_FLAGS} CACHE STRING "OpenMP compiler flag to use for testing OpenMP runtime libraries.") +set(ENABLE_LIBOMPTARGET ON) +# Currently libomptarget cannot be compiled on Windows or MacOS X. +# Since the device plugins are only supported on Linux anyway, +# there is no point in trying to compile libomptarget on other OSes. +# 32-bit systems are not supported either. +if (APPLE OR WIN32 OR WASM OR NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES + OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8 OR ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + set(ENABLE_LIBOMPTARGET OFF) +endif() + +option(OPENMP_ENABLE_LIBOMPTARGET "Enable building libomptarget for offloading." + ${ENABLE_LIBOMPTARGET}) option(OPENMP_ENABLE_LIBOMP_PROFILING "Enable time profiling for libomp." OFF) # Header install location -- GitLab From 4525f442fadb7cc44cc2eaede2c8ac6ba15bdf78 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 15 May 2024 12:01:16 -0500 Subject: [PATCH 389/578] [flang][OpenMP] Don't pass clauses to op-generating functions anymore (#90108) Remove parameter `const List &clauses` from functions that take construct queue. The clauses should now be accessed from the construct queue. --- flang/lib/Lower/OpenMP/OpenMP.cpp | 232 +++++++++++++----------------- 1 file changed, 103 insertions(+), 129 deletions(-) diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index f21acdd64d7c..f05cf1f5120f 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -1233,8 +1233,7 @@ genCriticalOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item, + const ConstructQueue &queue, ConstructQueue::iterator item, const std::optional &name) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::FlatSymbolRefAttr nameAttr; @@ -1245,8 +1244,8 @@ genCriticalOp(Fortran::lower::AbstractConverter &converter, auto global = mod.lookupSymbol(nameStr); if (!global) { mlir::omp::CriticalClauseOps clauseOps; - genCriticalDeclareClauses(converter, semaCtx, clauses, loc, clauseOps, - nameStr); + genCriticalDeclareClauses(converter, semaCtx, item->clauses, loc, + clauseOps, nameStr); mlir::OpBuilder modBuilder(mod.getBodyRegion()); global = modBuilder.create(loc, clauseOps); @@ -1266,8 +1265,7 @@ genDistributeOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { TODO(loc, "Distribute construct"); return nullptr; } @@ -1277,10 +1275,11 @@ genFlushOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ObjectList &objects, const List &clauses, - const ConstructQueue &queue, ConstructQueue::iterator item) { + const ObjectList &objects, const ConstructQueue &queue, + ConstructQueue::iterator item) { llvm::SmallVector operandRange; - genFlushClauses(converter, semaCtx, objects, clauses, loc, operandRange); + genFlushClauses(converter, semaCtx, objects, item->clauses, loc, + operandRange); return converter.getFirOpBuilder().create( converter.getCurrentLocation(), operandRange); @@ -1291,8 +1290,7 @@ genMasterOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_master), @@ -1304,8 +1302,7 @@ genOrderedOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { TODO(loc, "OMPD_ordered"); return nullptr; } @@ -1315,10 +1312,9 @@ genOrderedRegionOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { mlir::omp::OrderedRegionClauseOps clauseOps; - genOrderedRegionClauses(converter, semaCtx, clauses, loc, clauseOps); + genOrderedRegionClauses(converter, semaCtx, item->clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, @@ -1331,15 +1327,15 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item, bool outerCombined = false) { + const ConstructQueue &queue, ConstructQueue::iterator item, + bool outerCombined = false) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; mlir::omp::ParallelClauseOps clauseOps; llvm::SmallVector privateSyms; llvm::SmallVector reductionTypes; llvm::SmallVector reductionSyms; - genParallelClauses(converter, semaCtx, stmtCtx, clauses, loc, + genParallelClauses(converter, semaCtx, stmtCtx, item->clauses, loc, /*processReduction=*/!outerCombined, clauseOps, reductionTypes, reductionSyms); @@ -1352,7 +1348,7 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_parallel) .setOuterCombined(outerCombined) - .setClauses(&clauses) + .setClauses(&item->clauses) .setReductions(&reductionSyms, &reductionTypes) .setGenRegionEntryCb(reductionCallback); @@ -1361,7 +1357,7 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, clauseOps); bool privatize = !outerCombined; - DataSharingProcessor dsp(converter, semaCtx, clauses, eval, + DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval, /*useDelayedPrivatization=*/true, &symTable); if (privatize) @@ -1414,14 +1410,13 @@ genSectionOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { // Currently only private/firstprivate clause is handled, and // all privatization is done within `omp.section` operations. return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_section) - .setClauses(&clauses), + .setClauses(&item->clauses), queue, item); } @@ -1430,22 +1425,21 @@ genSectionsOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { mlir::omp::SectionsClauseOps clauseOps; - genSectionsClauses(converter, semaCtx, clauses, loc, clauseOps); + genSectionsClauses(converter, semaCtx, item->clauses, loc, clauseOps); auto &builder = converter.getFirOpBuilder(); // Insert privatizations before SECTIONS symTable.pushScope(); - DataSharingProcessor dsp(converter, semaCtx, clauses, eval); + DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval); dsp.processStep1(); List nonDsaClauses; List lastprivates; - for (const Clause &clause : clauses) { + for (const Clause &clause : item->clauses) { if (clause.id == llvm::omp::Clause::OMPC_lastprivate) { lastprivates.push_back(&std::get(clause.u)); } else { @@ -1508,18 +1502,18 @@ genSimdOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - DataSharingProcessor dsp(converter, semaCtx, clauses, eval); + DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval); dsp.processStep1(); Fortran::lower::StatementContext stmtCtx; mlir::omp::LoopNestClauseOps loopClauseOps; mlir::omp::SimdClauseOps simdClauseOps; llvm::SmallVector iv; - genLoopNestClauses(converter, semaCtx, eval, clauses, loc, loopClauseOps, iv); - genSimdClauses(converter, semaCtx, clauses, loc, simdClauseOps); + genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc, + loopClauseOps, iv); + genSimdClauses(converter, semaCtx, item->clauses, loc, simdClauseOps); // Create omp.simd wrapper. auto simdOp = firOpBuilder.create(loc, simdClauseOps); @@ -1532,7 +1526,8 @@ genSimdOp(Fortran::lower::AbstractConverter &converter, // Create nested omp.loop_nest and fill body with loop contents. auto loopOp = firOpBuilder.create(loc, loopClauseOps); - auto *nestedEval = getCollapsedLoopEval(eval, getCollapseValue(clauses)); + auto *nestedEval = + getCollapsedLoopEval(eval, getCollapseValue(item->clauses)); auto ivCallback = [&](mlir::Operation *op) { genLoopVars(op, converter, loc, iv); @@ -1542,7 +1537,7 @@ genSimdOp(Fortran::lower::AbstractConverter &converter, createBodyOfOp(*loopOp, OpWithBodyGenInfo(converter, symTable, semaCtx, loc, *nestedEval, llvm::omp::Directive::OMPD_simd) - .setClauses(&clauses) + .setClauses(&item->clauses) .setDataSharingProcessor(&dsp) .setGenRegionEntryCb(ivCallback), queue, item); @@ -1555,15 +1550,14 @@ genSingleOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { mlir::omp::SingleClauseOps clauseOps; - genSingleClauses(converter, semaCtx, clauses, loc, clauseOps); + genSingleClauses(converter, semaCtx, item->clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_single) - .setClauses(&clauses), + .setClauses(&item->clauses), queue, item, clauseOps); } @@ -1572,8 +1566,8 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item, bool outerCombined = false) { + const ConstructQueue &queue, ConstructQueue::iterator item, + bool outerCombined = false) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; @@ -1586,7 +1580,7 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, deviceAddrSyms; llvm::SmallVector mapLocs, devicePtrLocs, deviceAddrLocs; llvm::SmallVector mapTypes, devicePtrTypes, deviceAddrTypes; - genTargetClauses(converter, semaCtx, stmtCtx, clauses, loc, + genTargetClauses(converter, semaCtx, stmtCtx, item->clauses, loc, processHostOnlyClauses, /*processReduction=*/outerCombined, clauseOps, mapSyms, mapLocs, mapTypes, deviceAddrSyms, deviceAddrLocs, deviceAddrTypes, devicePtrSyms, @@ -1690,15 +1684,14 @@ genTargetDataOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TargetDataClauseOps clauseOps; llvm::SmallVector useDeviceTypes; llvm::SmallVector useDeviceLocs; llvm::SmallVector useDeviceSyms; - genTargetDataClauses(converter, semaCtx, stmtCtx, clauses, loc, clauseOps, - useDeviceTypes, useDeviceLocs, useDeviceSyms); + genTargetDataClauses(converter, semaCtx, stmtCtx, item->clauses, loc, + clauseOps, useDeviceTypes, useDeviceLocs, useDeviceSyms); auto targetDataOp = converter.getFirOpBuilder().create(loc, @@ -1714,8 +1707,7 @@ static OpTy genTargetEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, - mlir::Location loc, const List &clauses, - const ConstructQueue &queue, + mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; @@ -1733,8 +1725,8 @@ genTargetEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, } mlir::omp::TargetEnterExitUpdateDataClauseOps clauseOps; - genTargetEnterExitUpdateDataClauses(converter, semaCtx, stmtCtx, clauses, loc, - directive, clauseOps); + genTargetEnterExitUpdateDataClauses(converter, semaCtx, stmtCtx, + item->clauses, loc, directive, clauseOps); return firOpBuilder.create(loc, clauseOps); } @@ -1744,16 +1736,15 @@ genTaskOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TaskClauseOps clauseOps; - genTaskClauses(converter, semaCtx, stmtCtx, clauses, loc, clauseOps); + genTaskClauses(converter, semaCtx, stmtCtx, item->clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_task) - .setClauses(&clauses), + .setClauses(&item->clauses), queue, item, clauseOps); } @@ -1762,15 +1753,14 @@ genTaskgroupOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { mlir::omp::TaskgroupClauseOps clauseOps; - genTaskgroupClauses(converter, semaCtx, clauses, loc, clauseOps); + genTaskgroupClauses(converter, semaCtx, item->clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_taskgroup) - .setClauses(&clauses), + .setClauses(&item->clauses), queue, item, clauseOps); } @@ -1779,8 +1769,7 @@ genTaskloopOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { TODO(loc, "Taskloop construct"); } @@ -1789,10 +1778,9 @@ genTaskwaitOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { mlir::omp::TaskwaitClauseOps clauseOps; - genTaskwaitClauses(converter, semaCtx, clauses, loc, clauseOps); + genTaskwaitClauses(converter, semaCtx, item->clauses, loc, clauseOps); return converter.getFirOpBuilder().create(loc, clauseOps); } @@ -1811,17 +1799,17 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item, bool outerCombined = false) { + const ConstructQueue &queue, ConstructQueue::iterator item, + bool outerCombined = false) { Fortran::lower::StatementContext stmtCtx; mlir::omp::TeamsClauseOps clauseOps; - genTeamsClauses(converter, semaCtx, stmtCtx, clauses, loc, clauseOps); + genTeamsClauses(converter, semaCtx, stmtCtx, item->clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_teams) .setOuterCombined(outerCombined) - .setClauses(&clauses), + .setClauses(&item->clauses), queue, item, clauseOps); } @@ -1830,10 +1818,9 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - DataSharingProcessor dsp(converter, semaCtx, clauses, eval); + DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval); dsp.processStep1(); Fortran::lower::StatementContext stmtCtx; @@ -1842,8 +1829,9 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, llvm::SmallVector iv; llvm::SmallVector reductionTypes; llvm::SmallVector reductionSyms; - genLoopNestClauses(converter, semaCtx, eval, clauses, loc, loopClauseOps, iv); - genWsloopClauses(converter, semaCtx, stmtCtx, clauses, loc, wsClauseOps, + genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc, + loopClauseOps, iv); + genWsloopClauses(converter, semaCtx, stmtCtx, item->clauses, loc, wsClauseOps, reductionTypes, reductionSyms); // Create omp.wsloop wrapper and populate entry block arguments with reduction @@ -1858,7 +1846,8 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, // Create nested omp.loop_nest and fill body with loop contents. auto loopOp = firOpBuilder.create(loc, loopClauseOps); - auto *nestedEval = getCollapsedLoopEval(eval, getCollapseValue(clauses)); + auto *nestedEval = + getCollapsedLoopEval(eval, getCollapseValue(item->clauses)); auto ivCallback = [&](mlir::Operation *op) { genLoopVars(op, converter, loc, iv, reductionSyms, @@ -1869,7 +1858,7 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, createBodyOfOp(*loopOp, OpWithBodyGenInfo(converter, symTable, semaCtx, loc, *nestedEval, llvm::omp::Directive::OMPD_do) - .setClauses(&clauses) + .setClauses(&item->clauses) .setDataSharingProcessor(&dsp) .setReductions(&reductionSyms, &reductionTypes) .setGenRegionEntryCb(ivCallback), @@ -1886,8 +1875,7 @@ static void genCompositeDistributeParallelDo( Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO"); } @@ -1896,8 +1884,7 @@ static void genCompositeDistributeParallelDoSimd( Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &clauses, const ConstructQueue &queue, - ConstructQueue::iterator item) { + const ConstructQueue &queue, ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO SIMD"); } @@ -1906,8 +1893,7 @@ genCompositeDistributeSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - mlir::Location loc, const List &clauses, - const ConstructQueue &queue, + mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE SIMD"); } @@ -1916,10 +1902,9 @@ static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - mlir::Location loc, const List &clauses, - const ConstructQueue &queue, + mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { - ClauseProcessor cp(converter, semaCtx, clauses); + ClauseProcessor cp(converter, semaCtx, item->clauses); cp.processTODO( loc, llvm::omp::OMPD_do_simd); @@ -1931,7 +1916,7 @@ static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, // When support for vectorization is enabled, then we need to add handling of // if clause. Currently if clause can be skipped because we always assume // SIMD length = 1. - genWsloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + genWsloopOp(converter, symTable, semaCtx, eval, loc, queue, item); } static void @@ -1939,8 +1924,7 @@ genCompositeTaskloopSimd(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - mlir::Location loc, const List &clauses, - const ConstructQueue &queue, + mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { TODO(loc, "Composite TASKLOOP SIMD"); } @@ -1956,18 +1940,16 @@ static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { assert(item != queue.end()); - const List &clauses = item->clauses; switch (llvm::omp::Directive dir = item->id) { case llvm::omp::Directive::OMPD_barrier: genBarrierOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_distribute: - genDistributeOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); + genDistributeOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_do: - genWsloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + genWsloopOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_loop: case llvm::omp::Directive::OMPD_masked: @@ -1975,71 +1957,64 @@ static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, llvm::omp::getOpenMPDirectiveName(dir) + ")"); break; case llvm::omp::Directive::OMPD_master: - genMasterOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + genMasterOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_ordered: // Block-associated "ordered" construct. - genOrderedRegionOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); + genOrderedRegionOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_parallel: - genParallelOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item, + genParallelOp(converter, symTable, semaCtx, eval, loc, queue, item, /*outerCombined=*/false); break; case llvm::omp::Directive::OMPD_section: - genSectionOp(converter, symTable, semaCtx, eval, loc, /*clauses=*/{}, queue, - item); + genSectionOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_sections: - genSectionsOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); + genSectionsOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_simd: - genSimdOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + genSimdOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_single: - genSingleOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + genSingleOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_target: - genTargetOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item, + genTargetOp(converter, symTable, semaCtx, eval, loc, queue, item, /*outerCombined=*/false); break; case llvm::omp::Directive::OMPD_target_data: - genTargetDataOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); + genTargetDataOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_target_enter_data: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, loc, clauses, queue, item); + converter, symTable, semaCtx, loc, queue, item); break; case llvm::omp::Directive::OMPD_target_exit_data: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, loc, clauses, queue, item); + converter, symTable, semaCtx, loc, queue, item); break; case llvm::omp::Directive::OMPD_target_update: genTargetEnterExitUpdateDataOp( - converter, symTable, semaCtx, loc, clauses, queue, item); + converter, symTable, semaCtx, loc, queue, item); break; case llvm::omp::Directive::OMPD_task: - genTaskOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + genTaskOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_taskgroup: - genTaskgroupOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); + genTaskgroupOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_taskloop: - genTaskloopOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); + genTaskloopOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_taskwait: - genTaskwaitOp(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); + genTaskwaitOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_taskyield: genTaskyieldOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_teams: - genTeamsOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + genTeamsOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_tile: case llvm::omp::Directive::OMPD_unroll: @@ -2050,29 +2025,28 @@ static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, // FIXME: Workshare is not a commonly used OpenMP construct, an // implementation for this feature will come later. For the codes // that use this construct, add a single construct for now. - genSingleOp(converter, symTable, semaCtx, eval, loc, clauses, queue, item); + genSingleOp(converter, symTable, semaCtx, eval, loc, queue, item); break; // Composite constructs case llvm::omp::Directive::OMPD_distribute_parallel_do: genCompositeDistributeParallelDo(converter, symTable, semaCtx, eval, loc, - clauses, queue, item); + queue, item); break; case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: genCompositeDistributeParallelDoSimd(converter, symTable, semaCtx, eval, - loc, clauses, queue, item); + loc, queue, item); break; case llvm::omp::Directive::OMPD_distribute_simd: - genCompositeDistributeSimd(converter, symTable, semaCtx, eval, loc, clauses, - queue, item); + genCompositeDistributeSimd(converter, symTable, semaCtx, eval, loc, queue, + item); break; case llvm::omp::Directive::OMPD_do_simd: - genCompositeDoSimd(converter, symTable, semaCtx, eval, loc, clauses, queue, - item); + genCompositeDoSimd(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_taskloop_simd: - genCompositeTaskloopSimd(converter, symTable, semaCtx, eval, loc, clauses, - queue, item); + genCompositeTaskloopSimd(converter, symTable, semaCtx, eval, loc, queue, + item); break; default: break; @@ -2194,8 +2168,8 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, eval, directive.source, directive.v, clauses)}; if (directive.v == llvm::omp::Directive::OMPD_ordered) { // Standalone "ordered" directive. - genOrderedOp(converter, symTable, semaCtx, eval, currentLocation, clauses, - queue, queue.begin()); + genOrderedOp(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin()); } else { // Dispatch handles the "block-associated" variant of "ordered". genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue, @@ -2227,7 +2201,7 @@ genOMP(Fortran::lower::AbstractConverter &converter, converter.getFirOpBuilder().getModule(), semaCtx, eval, verbatim.source, llvm::omp::Directive::OMPD_flush, clauses)}; genFlushOp(converter, symTable, semaCtx, eval, currentLocation, objects, - clauses, queue, queue.begin()); + queue, queue.begin()); } static void @@ -2399,8 +2373,8 @@ genOMP(Fortran::lower::AbstractConverter &converter, const auto &name = std::get>(cd.t); mlir::Location currentLocation = converter.getCurrentLocation(); - genCriticalOp(converter, symTable, semaCtx, eval, currentLocation, clauses, - queue, queue.begin(), name); + genCriticalOp(converter, symTable, semaCtx, eval, currentLocation, queue, + queue.begin(), name); } static void -- GitLab From eb822dc25853299ea81166f9bb8a43436ab8b0c8 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Wed, 15 May 2024 21:03:15 +0400 Subject: [PATCH 390/578] [lldb] Fixed the TestCompletion test running on a remote target (#92281) Install the image to the remote target if necessary. --- .../functionalities/completion/TestCompletion.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lldb/test/API/functionalities/completion/TestCompletion.py b/lldb/test/API/functionalities/completion/TestCompletion.py index 0d6907e0c3d2..63842487fc33 100644 --- a/lldb/test/API/functionalities/completion/TestCompletion.py +++ b/lldb/test/API/functionalities/completion/TestCompletion.py @@ -107,9 +107,16 @@ class CommandLineCompletionTestCase(TestBase): self, "// Break here", lldb.SBFileSpec("main.cpp") ) err = lldb.SBError() - self.process().LoadImage( - lldb.SBFileSpec(self.getBuildArtifact("libshared.so")), err + local_spec = lldb.SBFileSpec(self.getBuildArtifact("libshared.so")) + remote_spec = ( + lldb.SBFileSpec( + lldbutil.append_to_process_working_directory(self, "libshared.so"), + False, + ) + if lldb.remote_platform + else lldb.SBFileSpec() ) + self.process().LoadImage(local_spec, remote_spec, err) self.assertSuccess(err) self.complete_from_to("process unload ", "process unload 0") @@ -473,7 +480,7 @@ class CommandLineCompletionTestCase(TestBase): self.complete_from_to("my_test_cmd main.cp", ["main.cpp"]) self.expect("my_test_cmd main.cpp", substrs=["main.cpp"]) - @skipIfWindows + @skipIf(hostoslist=["windows"]) def test_completion_target_create_from_root_dir(self): """Tests source file completion by completing .""" root_dir = os.path.abspath(os.sep) -- GitLab From 7645269710493c188d1d270b9e4e085b3e92b9b0 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Wed, 15 May 2024 21:06:30 +0400 Subject: [PATCH 391/578] [lldb] Fixed the TestNetBSDCore test (#92285) TestNetBSDCore.py contains 3 classes with the same test names test_aarch64 and test_amd64. It causes conflicts because the same build dir. Add suffixes to avoid conflicts. --- .../postmortem/netbsd-core/TestNetBSDCore.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lldb/test/API/functionalities/postmortem/netbsd-core/TestNetBSDCore.py b/lldb/test/API/functionalities/postmortem/netbsd-core/TestNetBSDCore.py index 756f4d1e81ca..ff1ef21e02e3 100644 --- a/lldb/test/API/functionalities/postmortem/netbsd-core/TestNetBSDCore.py +++ b/lldb/test/API/functionalities/postmortem/netbsd-core/TestNetBSDCore.py @@ -147,12 +147,12 @@ class NetBSD1LWPCoreTestCase(NetBSDCoreCommonTestCase): self.check_backtrace(thread, filename, backtrace) @skipIfLLVMTargetMissing("AArch64") - def test_aarch64(self): + def test_aarch64_single_threaded(self): """Test single-threaded aarch64 core dump.""" self.do_test("1lwp_SIGSEGV.aarch64", pid=8339, region_count=32) @skipIfLLVMTargetMissing("X86") - def test_amd64(self): + def test_amd64_single_threaded(self): """Test single-threaded amd64 core dump.""" self.do_test("1lwp_SIGSEGV.amd64", pid=693, region_count=21) @@ -177,12 +177,12 @@ class NetBSD2LWPT2CoreTestCase(NetBSDCoreCommonTestCase): self.assertEqual(thread.GetStopReasonDataAtIndex(0), 0) @skipIfLLVMTargetMissing("AArch64") - def test_aarch64(self): + def test_aarch64_thread_signaled(self): """Test double-threaded aarch64 core dump where thread 2 is signalled.""" self.do_test("2lwp_t2_SIGSEGV.aarch64", pid=14142, region_count=31) @skipIfLLVMTargetMissing("X86") - def test_amd64(self): + def test_amd64_thread_signaled(self): """Test double-threaded amd64 core dump where thread 2 is signalled.""" self.do_test("2lwp_t2_SIGSEGV.amd64", pid=622, region_count=24) @@ -207,11 +207,11 @@ class NetBSD2LWPProcessSigCoreTestCase(NetBSDCoreCommonTestCase): self.assertEqual(thread.GetStopReasonDataAtIndex(0), signal.SIGSEGV) @skipIfLLVMTargetMissing("AArch64") - def test_aarch64(self): + def test_aarch64_process_signaled(self): """Test double-threaded aarch64 core dump where process is signalled.""" self.do_test("2lwp_process_SIGSEGV.aarch64", pid=1403, region_count=30) @skipIfLLVMTargetMissing("X86") - def test_amd64(self): + def test_amd64_process_signaled(self): """Test double-threaded amd64 core dump where process is signalled.""" self.do_test("2lwp_process_SIGSEGV.amd64", pid=665, region_count=24) -- GitLab From d92c67784f21063d6334a009dbf4f9e0f8217b41 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Wed, 15 May 2024 21:08:35 +0400 Subject: [PATCH 392/578] [lldb][Windows] Fixed the TestIOHandlerResizeNoEditline test (#92286) This test caused python crash on Windows x86_64 host with the exit code 0xC0000409 (STATUS_STACK_BUFFER_OVERRUN). Close the input stream before exit to avoid this crash. --- lldb/test/API/iohandler/resize/TestIOHandlerResizeNoEditline.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/test/API/iohandler/resize/TestIOHandlerResizeNoEditline.py b/lldb/test/API/iohandler/resize/TestIOHandlerResizeNoEditline.py index 3c07554f6caf..bbc2dcbe4e30 100644 --- a/lldb/test/API/iohandler/resize/TestIOHandlerResizeNoEditline.py +++ b/lldb/test/API/iohandler/resize/TestIOHandlerResizeNoEditline.py @@ -18,3 +18,4 @@ class TestCase(TestBase): dbg.RunCommandInterpreter(True, True, opts, 0, False, False) # Try resizing the terminal which shouldn't crash. dbg.SetTerminalWidth(47) + dbg.GetInputFile().Close() -- GitLab From 217668f641e82f901645f428ae0d07a3c01e9a8a Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Wed, 15 May 2024 10:34:47 -0700 Subject: [PATCH 393/578] [nfc] Allow forwarding `Error` returns from `Expected` callers (#92208) On a few compilers (clang 11/12 for example [1]), the following does not result in a copy elision, and since `Error`'s copy dtor is elided, results in a compile error: ``` Expect foobar() { ... if (Error E = aCallReturningError()) return E; ... } ``` Moving `E` would, conversely, result in the pessimizing-move warning on more recent clangs ("moving a local object in a return statement prevents copy elision") We just need to make the `Expected` ctor taking an `Error` take it as a r-value reference. [1] https://lab.llvm.org/buildbot/#/builders/54/builds/10505 --- llvm/include/llvm/Support/Error.h | 2 +- llvm/lib/Bitstream/Reader/BitstreamReader.cpp | 12 ++++++------ llvm/lib/Object/COFFObjectFile.cpp | 6 +++--- llvm/lib/Object/WindowsResource.cpp | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/llvm/include/llvm/Support/Error.h b/llvm/include/llvm/Support/Error.h index 894b6484336a..217130ce293a 100644 --- a/llvm/include/llvm/Support/Error.h +++ b/llvm/include/llvm/Support/Error.h @@ -493,7 +493,7 @@ private: public: /// Create an Expected error value from the given Error. - Expected(Error Err) + Expected(Error &&Err) : HasError(true) #if LLVM_ENABLE_ABI_BREAKING_CHECKS // Expected is unchecked upon construction in Debug builds. diff --git a/llvm/lib/Bitstream/Reader/BitstreamReader.cpp b/llvm/lib/Bitstream/Reader/BitstreamReader.cpp index 3cc9dfdf7b85..5b2c76350029 100644 --- a/llvm/lib/Bitstream/Reader/BitstreamReader.cpp +++ b/llvm/lib/Bitstream/Reader/BitstreamReader.cpp @@ -167,7 +167,7 @@ Expected BitstreamCursor::skipRecord(unsigned AbbrevID) { if (Error Err = JumpToBit(GetCurrentBitNo() + static_cast(NumElts) * EltEnc.getEncodingData())) - return std::move(Err); + return Err; break; case BitCodeAbbrevOp::VBR: assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize); @@ -180,7 +180,7 @@ Expected BitstreamCursor::skipRecord(unsigned AbbrevID) { break; case BitCodeAbbrevOp::Char6: if (Error Err = JumpToBit(GetCurrentBitNo() + NumElts * 6)) - return std::move(Err); + return Err; break; } continue; @@ -206,7 +206,7 @@ Expected BitstreamCursor::skipRecord(unsigned AbbrevID) { // Skip over the blob. if (Error Err = JumpToBit(NewEnd)) - return std::move(Err); + return Err; } return Code; } @@ -344,7 +344,7 @@ Expected BitstreamCursor::readRecord(unsigned AbbrevID, // over tail padding first, in case jumping to NewEnd invalidates the Blob // pointer. if (Error Err = JumpToBit(NewEnd)) - return std::move(Err); + return Err; const char *Ptr = (const char *)getPointerToBit(CurBitPos, NumElts); // If we can return a reference to the data, do so to avoid copying it. @@ -421,7 +421,7 @@ Error BitstreamCursor::ReadAbbrevRecord() { Expected> BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) { if (llvm::Error Err = EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) - return std::move(Err); + return Err; BitstreamBlockInfo NewBlockInfo; @@ -452,7 +452,7 @@ BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) { if (!CurBlockInfo) return std::nullopt; if (Error Err = ReadAbbrevRecord()) - return std::move(Err); + return Err; // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the // appropriate BlockInfo. diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp index 18506f39f6b5..5a85b8e00c63 100644 --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/lib/Object/COFFObjectFile.cpp @@ -294,7 +294,7 @@ COFFObjectFile::getSectionContents(DataRefImpl Ref) const { const coff_section *Sec = toSec(Ref); ArrayRef Res; if (Error E = getSectionContents(Sec, Res)) - return std::move(E); + return E; return Res; } @@ -807,7 +807,7 @@ Expected> COFFObjectFile::create(MemoryBufferRef Object) { std::unique_ptr Obj(new COFFObjectFile(std::move(Object))); if (Error E = Obj->initialize()) - return std::move(E); + return E; return std::move(Obj); } @@ -1959,7 +1959,7 @@ ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) { uint64_t Offset = Entry.DataRVA + Sym->getValue(); ArrayRef Contents; if (Error E = Obj->getSectionContents(*Section, Contents)) - return std::move(E); + return E; if (Offset + Entry.DataSize > Contents.size()) return createStringError(object_error::parse_failed, "data outside of section"); diff --git a/llvm/lib/Object/WindowsResource.cpp b/llvm/lib/Object/WindowsResource.cpp index 983c8e30a942..306e8ec54206 100644 --- a/llvm/lib/Object/WindowsResource.cpp +++ b/llvm/lib/Object/WindowsResource.cpp @@ -80,7 +80,7 @@ Expected ResourceEntryRef::create(BinaryStreamRef BSR, const WindowsResource *Owner) { auto Ref = ResourceEntryRef(BSR, Owner); if (auto E = Ref.loadNext()) - return std::move(E); + return E; return Ref; } @@ -1006,7 +1006,7 @@ writeWindowsResourceCOFF(COFF::MachineTypes MachineType, Error E = Error::success(); WindowsResourceCOFFWriter Writer(MachineType, Parser, E); if (E) - return std::move(E); + return E; return Writer.write(TimeDateStamp); } -- GitLab From 0647d1035cb208195e002b38089b82004b6f7b92 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 15 May 2024 10:15:35 -0700 Subject: [PATCH 394/578] [RISCV] Remove unneeded casts from int64_t to uint64_t in RISCVMatInt.cpp. NFC Most of these were to avoid undefined behavior if a shift left changed the sign of the result. I don't think its possible to change the sign of the result here. We're shifting left by 12 after an arithmetic right shift by more than 12. The bits we are shifting out with the left shift are guaranteed to be sign bits. Also use SignExtend64<32> to force upper bits to all 1s instead of an Or. We know the value isUInt<32> && !isInt<32> which means bit 31 is set. --- .../Target/RISCV/MCTargetDesc/RISCVMatInt.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp index 0a857eb96935..fca3362f9a8b 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp @@ -115,30 +115,29 @@ static void generateInstSeqImpl(int64_t Val, const MCSubtargetInfo &STI, Val >>= ShiftAmount; // If the remaining bits don't fit in 12 bits, we might be able to reduce - // the // shift amount in order to use LUI which will zero the lower 12 - // bits. + // the shift amount in order to use LUI which will zero the lower 12 bits. if (ShiftAmount > 12 && !isInt<12>(Val)) { - if (isInt<32>((uint64_t)Val << 12)) { + if (isInt<32>(Val << 12)) { // Reduce the shift amount and add zeros to the LSBs so it will match // LUI. ShiftAmount -= 12; - Val = (uint64_t)Val << 12; - } else if (isUInt<32>((uint64_t)Val << 12) && + Val = Val << 12; + } else if (isUInt<32>(Val << 12) && STI.hasFeature(RISCV::FeatureStdExtZba)) { // Reduce the shift amount and add zeros to the LSBs so it will match // LUI, then shift left with SLLI.UW to clear the upper 32 set bits. ShiftAmount -= 12; - Val = ((uint64_t)Val << 12) | (0xffffffffull << 32); + Val = SignExtend64<32>(Val << 12); Unsigned = true; } } // Try to use SLLI_UW for Val when it is uint32 but not int32. - if (isUInt<32>((uint64_t)Val) && !isInt<32>((uint64_t)Val) && + if (isUInt<32>(Val) && !isInt<32>(Val) && STI.hasFeature(RISCV::FeatureStdExtZba)) { - // Use LUI+ADDI or LUI to compose, then clear the upper 32 bits with + // Use LUI+ADDI(W) or LUI to compose, then clear the upper 32 bits with // SLLI_UW. - Val = ((uint64_t)Val) | (0xffffffffull << 32); + Val = SignExtend64<32>(Val); Unsigned = true; } } -- GitLab From ec36145f58d2cf93d86bc4e3be617ad7d7d8ace7 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 15 May 2024 18:54:23 +0100 Subject: [PATCH 395/578] [LAA] Add tests with invariant dependences before strided ones. Add extra test coverage for loops with strided and invariant accesses to the same object. --- .../invariant-dependence-before.ll | 756 ++++++++++++++++++ 1 file changed, 756 insertions(+) create mode 100644 llvm/test/Analysis/LoopAccessAnalysis/invariant-dependence-before.ll diff --git a/llvm/test/Analysis/LoopAccessAnalysis/invariant-dependence-before.ll b/llvm/test/Analysis/LoopAccessAnalysis/invariant-dependence-before.ll new file mode 100644 index 000000000000..2a210a5a445b --- /dev/null +++ b/llvm/test/Analysis/LoopAccessAnalysis/invariant-dependence-before.ll @@ -0,0 +1,756 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 3 +; RUN: opt -passes='print' -disable-output %s 2>&1 | FileCheck %s + +define void @test_invar_dependence_before_positive_strided_access_1(ptr %a) { +; CHECK-LABEL: 'test_invar_dependence_before_positive_strided_access_1' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %a, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %gep, 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: + %gep.off = getelementptr i8, ptr %a, i32 4 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %a + store i32 %l, ptr %gep + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_before_positive_strided_access_2(ptr %a) { +; CHECK-LABEL: 'test_invar_dependence_before_positive_strided_access_2' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %gep, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %a, 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: + %gep.off = getelementptr i8, ptr %a, i32 4 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %gep + store i32 %l, ptr %a + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_not_before_positive_strided_access_1(ptr %a) { +; CHECK-LABEL: 'test_invar_dependence_not_before_positive_strided_access_1' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %a, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %gep, 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: + %gep.off = getelementptr i8, ptr %a, i32 3 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %a + store i32 %l, ptr %gep + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_not_before_positive_strided_access_2(ptr %a) { +; CHECK-LABEL: 'test_invar_dependence_not_before_positive_strided_access_2' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %gep, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %a, 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: + %gep.off = getelementptr i8, ptr %a, i32 3 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %gep + store i32 %l, ptr %a + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_before_positive_strided_access_1_different_access_sizes(ptr %a) { +; CHECK-LABEL: 'test_invar_dependence_before_positive_strided_access_1_different_access_sizes' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %a, align 4 -> +; CHECK-NEXT: store i8 %t, ptr %gep, align 1 +; 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: + %gep.off = getelementptr i8, ptr %a, i32 4 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %a + %t = trunc i32 %l to i8 + store i8 %t, ptr %gep + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_not_before_positive_strided_access_1_different_access_sizes(ptr %a) { +; CHECK-LABEL: 'test_invar_dependence_not_before_positive_strided_access_1_different_access_sizes' +; CHECK-NEXT: loop: +; 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: %l = load i64, ptr %a, align 4 -> +; CHECK-NEXT: store i32 %t, ptr %gep, 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: + %gep.off = getelementptr i8, ptr %a, i32 4 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i64, ptr %a + %t = trunc i64 %l to i32 + store i32 %t, ptr %gep + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_before_negative_strided_access_1(ptr %a) { +; CHECK-LABEL: 'test_invar_dependence_before_negative_strided_access_1' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %a, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %gep, 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: + %gep.off = getelementptr i32, ptr %a, i32 100 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %a + store i32 %l, ptr %gep + %iv.next = sub i32 %iv, 1 + %ec = icmp eq i32 %iv.next, -100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_before_negative_strided_access_2(ptr %a) { +; CHECK-LABEL: 'test_invar_dependence_before_negative_strided_access_2' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %gep, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %a, 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: + %gep.off = getelementptr i32, ptr %a, i32 100 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %gep + store i32 %l, ptr %a + %iv.next = sub i32 %iv, 1 + %ec = icmp eq i32 %iv.next, -100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + + +define void @test_invar_dependence_not_before_negative_strided_access_1(ptr %a) { +; CHECK-LABEL: 'test_invar_dependence_not_before_negative_strided_access_1' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %a, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %gep, 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: + %gep.off = getelementptr i32, ptr %a, i32 99 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %a + store i32 %l, ptr %gep + %iv.next = sub i32 %iv, 1 + %ec = icmp eq i32 %iv.next, -100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_not_before_negative_strided_access_2(ptr %a) { +; CHECK-LABEL: 'test_invar_dependence_not_before_negative_strided_access_2' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %gep, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %a, 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: + %gep.off = getelementptr i32, ptr %a, i32 99 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %gep + store i32 %l, ptr %a + %iv.next = sub i32 %iv, 1 + %ec = icmp eq i32 %iv.next, -100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_both_invar_before_1(ptr %a) { +; CHECK-LABEL: 'test_both_invar_before_1' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %a, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %gep.off, 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: + %gep.off = getelementptr i8, ptr %a, i32 4 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %l = load i32, ptr %a + store i32 %l, ptr %gep.off + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_both_invar_before_2(ptr %a) { +; CHECK-LABEL: 'test_both_invar_before_2' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %gep.off, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %a, 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: + %gep.off = getelementptr i8, ptr %a, i32 4 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %l = load i32, ptr %gep.off + store i32 %l, ptr %a + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_both_invar_not_before_1(ptr %a) { +; CHECK-LABEL: 'test_both_invar_not_before_1' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %a, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %gep.off, 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: + %gep.off = getelementptr i8, ptr %a, i32 3 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %l = load i32, ptr %a + store i32 %l, ptr %gep.off + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_both_invar_not_before_2(ptr %a) { +; CHECK-LABEL: 'test_both_invar_not_before_2' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %gep.off, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %a, 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: + %gep.off = getelementptr i8, ptr %a, i32 3 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %l = load i32, ptr %gep.off + store i32 %l, ptr %a + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_before_via_loop_guard_positive_strided_access_1(ptr %a, i32 %off) { +; CHECK-LABEL: 'test_invar_dependence_before_via_loop_guard_positive_strided_access_1' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %a, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %gep, 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: + %gep.off = getelementptr i8, ptr %a, i32 %off + %c = icmp sge i32 %off, 4 + br i1 %c, label %loop, label %exit + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %a + store i32 %l, ptr %gep + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_before_via_loop_guard_positive_strided_access_2(ptr %a, i32 %off) { +; CHECK-LABEL: 'test_invar_dependence_before_via_loop_guard_positive_strided_access_2' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %gep, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %a, 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: + %gep.off = getelementptr i8, ptr %a, i32 %off + %c = icmp sge i32 %off, 4 + br i1 %c, label %loop, label %exit + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %gep + store i32 %l, ptr %a + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} +define void @test_invar_dependence_not_before_via_loop_guard_positive_strided_access_1(ptr %a, i32 %off) { +; CHECK-LABEL: 'test_invar_dependence_not_before_via_loop_guard_positive_strided_access_1' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %a, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %gep, 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: + %gep.off = getelementptr i8, ptr %a, i32 %off + %c = icmp sge i32 %off, 3 + br i1 %c, label %loop, label %exit + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %a + store i32 %l, ptr %gep + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_not_before_via_loop_guard_positive_strided_access_2(ptr %a, i32 %off) { +; CHECK-LABEL: 'test_invar_dependence_not_before_via_loop_guard_positive_strided_access_2' +; CHECK-NEXT: loop: +; 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: %l = load i32, ptr %gep, align 4 -> +; CHECK-NEXT: store i32 %l, ptr %a, 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: + %gep.off = getelementptr i8, ptr %a, i32 %off + %c = icmp sge i32 %off, 3 + br i1 %c, label %loop, label %exit + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %gep + store i32 %l, ptr %a + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_before_positive_strided_access_via_loop_guard_1(ptr %a, i32 %off) { +; CHECK-LABEL: 'test_invar_dependence_before_positive_strided_access_via_loop_guard_1' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: could not determine number of loop iterations +; 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: + %gep.off = getelementptr i8, ptr %a, i32 4 + %c = icmp sge i32 %off, 0 + br i1 %c, label %loop, label %exit + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %gep + store i32 %l, ptr %a + %iv.next = add i32 %iv, %off + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_before_positive_strided_access_via_loop_guard_2(ptr %a, i32 %off) { +; CHECK-LABEL: 'test_invar_dependence_before_positive_strided_access_via_loop_guard_2' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: could not determine number of loop iterations +; 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: + %gep.off = getelementptr i8, ptr %a, i32 4 + %c = icmp sge i32 %off, 0 + br i1 %c, label %loop, label %exit + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %a + store i32 %l, ptr %gep + %iv.next = add i32 %iv, %off + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_not_known_beforepositive_strided_access_not_known_via_loop_guard_1(ptr %a, i32 %off) { +; CHECK-LABEL: 'test_invar_dependence_not_known_beforepositive_strided_access_not_known_via_loop_guard_1' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: could not determine number of loop iterations +; 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: + %gep.off = getelementptr i8, ptr %a, i32 4 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %a + store i32 %l, ptr %gep + %iv.next = add i32 %iv, %off + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_dependence_not_known_beforepositive_strided_access_not_known_via_loop_guard_2(ptr %a, i32 %off) { +; CHECK-LABEL: 'test_invar_dependence_not_known_beforepositive_strided_access_not_known_via_loop_guard_2' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: could not determine number of loop iterations +; 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: + %gep.off = getelementptr i8, ptr %a, i32 4 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load i32, ptr %gep + store i32 %l, ptr %a + %iv.next = add i32 %iv, %off + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} -- GitLab From c19f2c773b0e23fd623502888894add822079f63 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Tue, 14 May 2024 18:11:53 -0700 Subject: [PATCH 396/578] Reapply "[ctx_profile] Profile reader and writer" (#92199) This reverts commit 03c7458a3603396d2d0e1dee43399d3d1664a264. One of the problems was addressed in #92208 The other problem: needed to add `BitstreamReader` to the list of link deps of `LLVMProfileData` --- .../llvm/ProfileData/PGOCtxProfReader.h | 92 +++++++ .../llvm/ProfileData/PGOCtxProfWriter.h | 91 +++++++ llvm/lib/ProfileData/CMakeLists.txt | 3 + llvm/lib/ProfileData/PGOCtxProfReader.cpp | 173 ++++++++++++ llvm/lib/ProfileData/PGOCtxProfWriter.cpp | 49 ++++ llvm/unittests/ProfileData/CMakeLists.txt | 1 + .../PGOCtxProfReaderWriterTest.cpp | 255 ++++++++++++++++++ 7 files changed, 664 insertions(+) create mode 100644 llvm/include/llvm/ProfileData/PGOCtxProfReader.h create mode 100644 llvm/include/llvm/ProfileData/PGOCtxProfWriter.h create mode 100644 llvm/lib/ProfileData/PGOCtxProfReader.cpp create mode 100644 llvm/lib/ProfileData/PGOCtxProfWriter.cpp create mode 100644 llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp diff --git a/llvm/include/llvm/ProfileData/PGOCtxProfReader.h b/llvm/include/llvm/ProfileData/PGOCtxProfReader.h new file mode 100644 index 000000000000..a19b3f51d642 --- /dev/null +++ b/llvm/include/llvm/ProfileData/PGOCtxProfReader.h @@ -0,0 +1,92 @@ +//===--- PGOCtxProfReader.h - Contextual profile reader ---------*- 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 +/// +/// Reader for contextual iFDO profile, which comes in bitstream format. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H +#define LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Bitstream/BitstreamReader.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Support/Error.h" +#include +#include + +namespace llvm { +/// The loaded contextual profile, suitable for mutation during IPO passes. We +/// generally expect a fraction of counters and of callsites to be populated. +/// We continue to model counters as vectors, but callsites are modeled as a map +/// of a map. The expectation is that, typically, there is a small number of +/// indirect targets (usually, 1 for direct calls); but potentially a large +/// number of callsites, and, as inlining progresses, the callsite count of a +/// caller will grow. +class PGOContextualProfile final { +public: + using CallTargetMapTy = std::map; + using CallsiteMapTy = DenseMap; + +private: + friend class PGOCtxProfileReader; + GlobalValue::GUID GUID = 0; + SmallVector Counters; + CallsiteMapTy Callsites; + + PGOContextualProfile(GlobalValue::GUID G, + SmallVectorImpl &&Counters) + : GUID(G), Counters(std::move(Counters)) {} + + Expected + getOrEmplace(uint32_t Index, GlobalValue::GUID G, + SmallVectorImpl &&Counters); + +public: + PGOContextualProfile(const PGOContextualProfile &) = delete; + PGOContextualProfile &operator=(const PGOContextualProfile &) = delete; + PGOContextualProfile(PGOContextualProfile &&) = default; + PGOContextualProfile &operator=(PGOContextualProfile &&) = default; + + GlobalValue::GUID guid() const { return GUID; } + const SmallVectorImpl &counters() const { return Counters; } + const CallsiteMapTy &callsites() const { return Callsites; } + CallsiteMapTy &callsites() { return Callsites; } + + bool hasCallsite(uint32_t I) const { + return Callsites.find(I) != Callsites.end(); + } + + const CallTargetMapTy &callsite(uint32_t I) const { + assert(hasCallsite(I) && "Callsite not found"); + return Callsites.find(I)->second; + } + void getContainedGuids(DenseSet &Guids) const; +}; + +class PGOCtxProfileReader final { + BitstreamCursor &Cursor; + Expected advance(); + Error readMetadata(); + Error wrongValue(const Twine &); + Error unsupported(const Twine &); + + Expected, PGOContextualProfile>> + readContext(bool ExpectIndex); + bool canReadContext(); + +public: + PGOCtxProfileReader(BitstreamCursor &Cursor) : Cursor(Cursor) {} + + Expected> loadContexts(); +}; +} // namespace llvm +#endif diff --git a/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h b/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h new file mode 100644 index 000000000000..15578c51a495 --- /dev/null +++ b/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h @@ -0,0 +1,91 @@ +//===- PGOCtxProfWriter.h - Contextual Profile Writer -----------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares a utility for writing a contextual profile to bitstream. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ +#define LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ + +#include "llvm/Bitstream/BitstreamWriter.h" +#include "llvm/ProfileData/CtxInstrContextNode.h" + +namespace llvm { +enum PGOCtxProfileRecords { Invalid = 0, Version, Guid, CalleeIndex, Counters }; + +enum PGOCtxProfileBlockIDs { + ProfileMetadataBlockID = 100, + ContextNodeBlockID = ProfileMetadataBlockID + 1 +}; + +/// Write one or more ContextNodes to the provided raw_fd_stream. +/// The caller must destroy the PGOCtxProfileWriter object before closing the +/// stream. +/// The design allows serializing a bunch of contexts embedded in some other +/// file. The overall format is: +/// +/// [... other data written to the stream...] +/// SubBlock(ProfileMetadataBlockID) +/// Version +/// SubBlock(ContextNodeBlockID) +/// [RECORDS] +/// SubBlock(ContextNodeBlockID) +/// [RECORDS] +/// [... more SubBlocks] +/// EndBlock +/// EndBlock +/// +/// The "RECORDS" are bitsream records. The IDs are in CtxProfileCodes (except) +/// for Version, which is just for metadata). All contexts will have Guid and +/// Counters, and all but the roots have CalleeIndex. The order in which the +/// records appear does not matter, but they must precede any subcontexts, +/// because that helps keep the reader code simpler. +/// +/// Subblock containment captures the context->subcontext relationship. The +/// "next()" relationship in the raw profile, between call targets of indirect +/// calls, are just modeled as peer subblocks where the callee index is the +/// same. +/// +/// Versioning: the writer may produce additional records not known by the +/// reader. The version number indicates a more structural change. +/// The current version, in particular, is set up to expect optional extensions +/// like value profiling - which would appear as additional records. For +/// example, value profiling would produce a new record with a new record ID, +/// containing the profiled values (much like the counters) +class PGOCtxProfileWriter final { + SmallVector Buff; + BitstreamWriter Writer; + + void writeCounters(const ctx_profile::ContextNode &Node); + void writeImpl(std::optional CallerIndex, + const ctx_profile::ContextNode &Node); + +public: + PGOCtxProfileWriter(raw_fd_stream &Out, + std::optional VersionOverride = std::nullopt) + : Writer(Buff, &Out, 0) { + Writer.EnterSubblock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID, + CodeLen); + const auto Version = VersionOverride ? *VersionOverride : CurrentVersion; + Writer.EmitRecord(PGOCtxProfileRecords::Version, + SmallVector({Version})); + } + + ~PGOCtxProfileWriter() { Writer.ExitBlock(); } + + void write(const ctx_profile::ContextNode &); + + // constants used in writing which a reader may find useful. + static constexpr unsigned CodeLen = 2; + static constexpr uint32_t CurrentVersion = 1; + static constexpr unsigned VBREncodingBits = 6; +}; + +} // namespace llvm +#endif diff --git a/llvm/lib/ProfileData/CMakeLists.txt b/llvm/lib/ProfileData/CMakeLists.txt index 408f9ff01ec8..4fa1b76f0a06 100644 --- a/llvm/lib/ProfileData/CMakeLists.txt +++ b/llvm/lib/ProfileData/CMakeLists.txt @@ -7,6 +7,8 @@ add_llvm_component_library(LLVMProfileData ItaniumManglingCanonicalizer.cpp MemProf.cpp MemProfReader.cpp + PGOCtxProfReader.cpp + PGOCtxProfWriter.cpp ProfileSummaryBuilder.cpp SampleProf.cpp SampleProfReader.cpp @@ -20,6 +22,7 @@ add_llvm_component_library(LLVMProfileData intrinsics_gen LINK_COMPONENTS + BitstreamReader Core Object Support diff --git a/llvm/lib/ProfileData/PGOCtxProfReader.cpp b/llvm/lib/ProfileData/PGOCtxProfReader.cpp new file mode 100644 index 000000000000..3710f2e4b818 --- /dev/null +++ b/llvm/lib/ProfileData/PGOCtxProfReader.cpp @@ -0,0 +1,173 @@ +//===- PGOCtxProfReader.cpp - Contextual Instrumentation profile reader ---===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Read a contextual profile into a datastructure suitable for maintenance +// throughout IPO +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/PGOCtxProfReader.h" +#include "llvm/Bitstream/BitCodeEnums.h" +#include "llvm/Bitstream/BitstreamReader.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" + +using namespace llvm; + +// FIXME(#92054) - these Error handling macros are (re-)invented in a few +// places. +#define EXPECT_OR_RET(LHS, RHS) \ + auto LHS = RHS; \ + if (!LHS) \ + return LHS.takeError(); + +#define RET_ON_ERR(EXPR) \ + if (auto Err = (EXPR)) \ + return Err; + +Expected +PGOContextualProfile::getOrEmplace(uint32_t Index, GlobalValue::GUID G, + SmallVectorImpl &&Counters) { + auto [Iter, Inserted] = Callsites[Index].insert( + {G, PGOContextualProfile(G, std::move(Counters))}); + if (!Inserted) + return make_error(instrprof_error::invalid_prof, + "Duplicate GUID for same callsite."); + return Iter->second; +} + +void PGOContextualProfile::getContainedGuids( + DenseSet &Guids) const { + Guids.insert(GUID); + for (const auto &[_, Callsite] : Callsites) + for (const auto &[_, Callee] : Callsite) + Callee.getContainedGuids(Guids); +} + +Expected PGOCtxProfileReader::advance() { + return Cursor.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); +} + +Error PGOCtxProfileReader::wrongValue(const Twine &Msg) { + return make_error(instrprof_error::invalid_prof, Msg); +} + +Error PGOCtxProfileReader::unsupported(const Twine &Msg) { + return make_error(instrprof_error::unsupported_version, Msg); +} + +bool PGOCtxProfileReader::canReadContext() { + auto Blk = advance(); + if (!Blk) { + consumeError(Blk.takeError()); + return false; + } + return Blk->Kind == BitstreamEntry::SubBlock && + Blk->ID == PGOCtxProfileBlockIDs::ContextNodeBlockID; +} + +Expected, PGOContextualProfile>> +PGOCtxProfileReader::readContext(bool ExpectIndex) { + RET_ON_ERR(Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ContextNodeBlockID)); + + std::optional Guid; + std::optional> Counters; + std::optional CallsiteIndex; + + SmallVector RecordValues; + + // We don't prescribe the order in which the records come in, and we are ok + // if other unsupported records appear. We seek in the current subblock until + // we get all we know. + auto GotAllWeNeed = [&]() { + return Guid.has_value() && Counters.has_value() && + (!ExpectIndex || CallsiteIndex.has_value()); + }; + while (!GotAllWeNeed()) { + RecordValues.clear(); + EXPECT_OR_RET(Entry, advance()); + if (Entry->Kind != BitstreamEntry::Record) + return wrongValue( + "Expected records before encountering more subcontexts"); + EXPECT_OR_RET(ReadRecord, + Cursor.readRecord(bitc::UNABBREV_RECORD, RecordValues)); + switch (*ReadRecord) { + case PGOCtxProfileRecords::Guid: + if (RecordValues.size() != 1) + return wrongValue("The GUID record should have exactly one value"); + Guid = RecordValues[0]; + break; + case PGOCtxProfileRecords::Counters: + Counters = std::move(RecordValues); + if (Counters->empty()) + return wrongValue("Empty counters. At least the entry counter (one " + "value) was expected"); + break; + case PGOCtxProfileRecords::CalleeIndex: + if (!ExpectIndex) + return wrongValue("The root context should not have a callee index"); + if (RecordValues.size() != 1) + return wrongValue("The callee index should have exactly one value"); + CallsiteIndex = RecordValues[0]; + break; + default: + // OK if we see records we do not understand, like records (profile + // components) introduced later. + break; + } + } + + PGOContextualProfile Ret(*Guid, std::move(*Counters)); + + while (canReadContext()) { + EXPECT_OR_RET(SC, readContext(true)); + auto &Targets = Ret.callsites()[*SC->first]; + auto [_, Inserted] = + Targets.insert({SC->second.guid(), std::move(SC->second)}); + if (!Inserted) + return wrongValue( + "Unexpected duplicate target (callee) at the same callsite."); + } + return std::make_pair(CallsiteIndex, std::move(Ret)); +} + +Error PGOCtxProfileReader::readMetadata() { + EXPECT_OR_RET(Blk, advance()); + if (Blk->Kind != BitstreamEntry::SubBlock) + return unsupported("Expected Version record"); + RET_ON_ERR( + Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID)); + EXPECT_OR_RET(MData, advance()); + if (MData->Kind != BitstreamEntry::Record) + return unsupported("Expected Version record"); + + SmallVector Ver; + EXPECT_OR_RET(Code, Cursor.readRecord(bitc::UNABBREV_RECORD, Ver)); + if (*Code != PGOCtxProfileRecords::Version) + return unsupported("Expected Version record"); + if (Ver.size() != 1 || Ver[0] > PGOCtxProfileWriter::CurrentVersion) + return unsupported("Version " + Twine(*Code) + + " is higher than supported version " + + Twine(PGOCtxProfileWriter::CurrentVersion)); + return Error::success(); +} + +Expected> +PGOCtxProfileReader::loadContexts() { + std::map Ret; + RET_ON_ERR(readMetadata()); + while (canReadContext()) { + EXPECT_OR_RET(E, readContext(false)); + auto Key = E->second.guid(); + if (!Ret.insert({Key, std::move(E->second)}).second) + return wrongValue("Duplicate roots"); + } + return Ret; +} diff --git a/llvm/lib/ProfileData/PGOCtxProfWriter.cpp b/llvm/lib/ProfileData/PGOCtxProfWriter.cpp new file mode 100644 index 000000000000..508179756446 --- /dev/null +++ b/llvm/lib/ProfileData/PGOCtxProfWriter.cpp @@ -0,0 +1,49 @@ +//===- PGOCtxProfWriter.cpp - Contextual Instrumentation profile writer ---===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Write a contextual profile to bitstream. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Bitstream/BitCodeEnums.h" + +using namespace llvm; +using namespace llvm::ctx_profile; + +void PGOCtxProfileWriter::writeCounters(const ContextNode &Node) { + Writer.EmitCode(bitc::UNABBREV_RECORD); + Writer.EmitVBR(PGOCtxProfileRecords::Counters, VBREncodingBits); + Writer.EmitVBR(Node.counters_size(), VBREncodingBits); + for (uint32_t I = 0U; I < Node.counters_size(); ++I) + Writer.EmitVBR64(Node.counters()[I], VBREncodingBits); +} + +// recursively write all the subcontexts. We do need to traverse depth first to +// model the context->subcontext implicitly, and since this captures call +// stacks, we don't really need to be worried about stack overflow and we can +// keep the implementation simple. +void PGOCtxProfileWriter::writeImpl(std::optional CallerIndex, + const ContextNode &Node) { + Writer.EnterSubblock(PGOCtxProfileBlockIDs::ContextNodeBlockID, CodeLen); + Writer.EmitRecord(PGOCtxProfileRecords::Guid, + SmallVector{Node.guid()}); + if (CallerIndex) + Writer.EmitRecord(PGOCtxProfileRecords::CalleeIndex, + SmallVector{*CallerIndex}); + writeCounters(Node); + for (uint32_t I = 0U; I < Node.callsites_size(); ++I) + for (const auto *Subcontext = Node.subContexts()[I]; Subcontext; + Subcontext = Subcontext->next()) + writeImpl(I, *Subcontext); + Writer.ExitBlock(); +} + +void PGOCtxProfileWriter::write(const ContextNode &RootNode) { + writeImpl(std::nullopt, RootNode); +} diff --git a/llvm/unittests/ProfileData/CMakeLists.txt b/llvm/unittests/ProfileData/CMakeLists.txt index ce3a0a45ccf1..c92642ded828 100644 --- a/llvm/unittests/ProfileData/CMakeLists.txt +++ b/llvm/unittests/ProfileData/CMakeLists.txt @@ -13,6 +13,7 @@ add_llvm_unittest(ProfileDataTests InstrProfTest.cpp ItaniumManglingCanonicalizerTest.cpp MemProfTest.cpp + PGOCtxProfReaderWriterTest.cpp SampleProfTest.cpp SymbolRemappingReaderTest.cpp ) diff --git a/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp b/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp new file mode 100644 index 000000000000..d2cdbb28e2fc --- /dev/null +++ b/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp @@ -0,0 +1,255 @@ +//===-------------- PGOCtxProfReadWriteTest.cpp ---------------------------===// +// +// 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 "llvm/Bitstream/BitstreamReader.h" +#include "llvm/ProfileData/CtxInstrContextNode.h" +#include "llvm/ProfileData/PGOCtxProfReader.h" +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Testing/Support/SupportHelpers.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::ctx_profile; + +class PGOCtxProfRWTest : public ::testing::Test { + std::vector> Nodes; + std::map Roots; + +public: + ContextNode *createNode(GUID Guid, uint32_t NrCounters, uint32_t NrCallsites, + ContextNode *Next = nullptr) { + auto AllocSize = ContextNode::getAllocSize(NrCounters, NrCallsites); + auto *Mem = Nodes.emplace_back(std::make_unique(AllocSize)).get(); + std::memset(Mem, 0, AllocSize); + auto *Ret = new (Mem) ContextNode(Guid, NrCounters, NrCallsites, Next); + return Ret; + } + + void SetUp() override { + // Root (guid 1) has 2 callsites, one used for an indirect call to either + // guid 2 or 4. + // guid 2 calls guid 5 + // guid 5 calls guid 2 + // there's also a second root, guid3. + auto *Root1 = createNode(1, 2, 2); + Root1->counters()[0] = 10; + Root1->counters()[1] = 11; + Roots.insert({1, Root1}); + auto *L1 = createNode(2, 1, 1); + L1->counters()[0] = 12; + Root1->subContexts()[1] = createNode(4, 3, 1, L1); + Root1->subContexts()[1]->counters()[0] = 13; + Root1->subContexts()[1]->counters()[1] = 14; + Root1->subContexts()[1]->counters()[2] = 15; + + auto *L3 = createNode(5, 6, 3); + for (auto I = 0; I < 6; ++I) + L3->counters()[I] = 16 + I; + L1->subContexts()[0] = L3; + L3->subContexts()[2] = createNode(2, 1, 1); + L3->subContexts()[2]->counters()[0] = 30; + auto *Root2 = createNode(3, 1, 0); + Root2->counters()[0] = 40; + Roots.insert({3, Root2}); + } + + const std::map &roots() const { return Roots; } +}; + +void checkSame(const ContextNode &Raw, const PGOContextualProfile &Profile) { + EXPECT_EQ(Raw.guid(), Profile.guid()); + ASSERT_EQ(Raw.counters_size(), Profile.counters().size()); + for (auto I = 0U; I < Raw.counters_size(); ++I) + EXPECT_EQ(Raw.counters()[I], Profile.counters()[I]); + + for (auto I = 0U; I < Raw.callsites_size(); ++I) { + if (Raw.subContexts()[I] == nullptr) + continue; + EXPECT_TRUE(Profile.hasCallsite(I)); + const auto &ProfileTargets = Profile.callsite(I); + + std::map Targets; + for (const auto *N = Raw.subContexts()[I]; N; N = N->next()) + EXPECT_TRUE(Targets.insert({N->guid(), N}).second); + + EXPECT_EQ(Targets.size(), ProfileTargets.size()); + for (auto It : Targets) { + auto PIt = ProfileTargets.find(It.second->guid()); + EXPECT_NE(PIt, ProfileTargets.end()); + checkSame(*It.second, PIt->second); + } + } +} + +TEST_F(PGOCtxProfRWTest, RoundTrip) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + for (auto &[_, R] : roots()) + Writer.write(*R); + } + } + { + ErrorOr> MB = + MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + ASSERT_TRUE(!!Expected); + auto &Ctxes = *Expected; + EXPECT_EQ(Ctxes.size(), roots().size()); + EXPECT_EQ(Ctxes.size(), 2U); + for (auto &[G, R] : roots()) + checkSame(*R, Ctxes.find(G)->second); + } +} + +TEST_F(PGOCtxProfRWTest, InvalidCounters) { + auto *R = createNode(1, 0, 1); + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + Writer.write(*R); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} + +TEST_F(PGOCtxProfRWTest, Empty) { + BitstreamCursor Cursor(""); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); +} + +TEST_F(PGOCtxProfRWTest, Invalid) { + BitstreamCursor Cursor("Surely this is not valid"); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); +} + +TEST_F(PGOCtxProfRWTest, ValidButEmpty) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + // don't write anything - this will just produce the metadata subblock. + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_TRUE(!!Expected); + EXPECT_TRUE(Expected->empty()); + } +} + +TEST_F(PGOCtxProfRWTest, WrongVersion) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out, PGOCtxProfileWriter::CurrentVersion + 1); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} + +TEST_F(PGOCtxProfRWTest, DuplicateRoots) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + Writer.write(*createNode(1, 1, 1)); + Writer.write(*createNode(1, 1, 1)); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} + +TEST_F(PGOCtxProfRWTest, DuplicateTargets) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + auto *R = createNode(1, 1, 1); + auto *L1 = createNode(2, 1, 0); + auto *L2 = createNode(2, 1, 0, L1); + R->subContexts()[0] = L2; + PGOCtxProfileWriter Writer(Out); + Writer.write(*R); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} -- GitLab From df5804aec48f99704ef26c740e19deaa4072fe27 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Wed, 15 May 2024 18:08:23 +0000 Subject: [PATCH 397/578] [gn build] Port c19f2c773b0e --- llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn | 2 ++ llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn | 1 + 2 files changed, 3 insertions(+) diff --git a/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn index 9dbfe0f94c1d..c6fa142b3766 100644 --- a/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn @@ -17,6 +17,8 @@ static_library("ProfileData") { "ItaniumManglingCanonicalizer.cpp", "MemProf.cpp", "MemProfReader.cpp", + "PGOCtxProfReader.cpp", + "PGOCtxProfWriter.cpp", "ProfileSummaryBuilder.cpp", "SampleProf.cpp", "SampleProfReader.cpp", diff --git a/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn index 4919a8089209..f45542519173 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn @@ -14,6 +14,7 @@ unittest("ProfileDataTests") { "InstrProfTest.cpp", "ItaniumManglingCanonicalizerTest.cpp", "MemProfTest.cpp", + "PGOCtxProfReaderWriterTest.cpp", "SampleProfTest.cpp", "SymbolRemappingReaderTest.cpp", ] -- GitLab From 468357114c64633651ebcc5ef17161990da25a78 Mon Sep 17 00:00:00 2001 From: Pete Steinfeld <47540744+psteinfeld@users.noreply.github.com> Date: Wed, 15 May 2024 11:30:30 -0700 Subject: [PATCH 398/578] =?UTF-8?q?Revert=20"[flang]=20Initial=20debug=20i?= =?UTF-8?q?nfo=20support=20for=20local=20variables.=20(#909=E2=80=A6=20(#9?= =?UTF-8?q?2302)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …05)" This reverts commit 61da6366d043792d7db280ce9edd2db62516e0e8. Update #90905 was causing many tests to fail. See comments in #90905. --- .../include/flang/Optimizer/CodeGen/CGOps.td | 34 ------- .../flang/Optimizer/CodeGen/CGPasses.td | 4 - .../include/flang/Optimizer/CodeGen/CodeGen.h | 6 +- flang/include/flang/Tools/CLOptions.inc | 11 +-- flang/lib/Optimizer/CodeGen/CGOps.cpp | 2 +- .../flang => lib}/Optimizer/CodeGen/CGOps.h | 1 - flang/lib/Optimizer/CodeGen/CodeGen.cpp | 50 +++------- flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp | 49 ++-------- .../lib/Optimizer/Transforms/AddDebugInfo.cpp | 56 +----------- .../Transforms/DebugTypeGenerator.cpp | 10 +- flang/test/Fir/declare-codegen.fir | 22 ++--- flang/test/Fir/dummy-scope-codegen.fir | 11 +-- flang/test/Transforms/debug-local-var-2.f90 | 91 ------------------- flang/test/Transforms/debug-local-var.f90 | 54 ----------- 14 files changed, 47 insertions(+), 354 deletions(-) rename flang/{include/flang => lib}/Optimizer/CodeGen/CGOps.h (94%) delete mode 100644 flang/test/Transforms/debug-local-var-2.f90 delete mode 100644 flang/test/Transforms/debug-local-var.f90 diff --git a/flang/include/flang/Optimizer/CodeGen/CGOps.td b/flang/include/flang/Optimizer/CodeGen/CGOps.td index c375edee1fa7..35e70fa2ffa3 100644 --- a/flang/include/flang/Optimizer/CodeGen/CGOps.td +++ b/flang/include/flang/Optimizer/CodeGen/CGOps.td @@ -16,8 +16,6 @@ include "mlir/IR/SymbolInterfaces.td" include "flang/Optimizer/Dialect/FIRTypes.td" -include "flang/Optimizer/Dialect/FIRAttr.td" -include "mlir/IR/BuiltinAttributes.td" def fircg_Dialect : Dialect { let name = "fircg"; @@ -204,36 +202,4 @@ def fircg_XArrayCoorOp : fircg_Op<"ext_array_coor", [AttrSizedOperandSegments]> }]; } -// Extended Declare operation. -def fircg_XDeclareOp : fircg_Op<"ext_declare", [AttrSizedOperandSegments]> { - let summary = "for internal conversion only"; - - let description = [{ - Prior to lowering to LLVM IR dialect, a DeclareOp will - be converted to an extended DeclareOp. - }]; - - let arguments = (ins - AnyRefOrBox:$memref, - Variadic:$shape, - Variadic:$shift, - Variadic:$typeparams, - Optional:$dummy_scope, - Builtin_StringAttr:$uniq_name - ); - let results = (outs AnyRefOrBox); - - let assemblyFormat = [{ - $memref (`(` $shape^ `)`)? (`origin` $shift^)? (`typeparams` $typeparams^)? - (`dummy_scope` $dummy_scope^)? - attr-dict `:` functional-type(operands, results) - }]; - - let extraClassDeclaration = [{ - // Shape is optional, but if it exists, it will be at offset 1. - unsigned shapeOffset() { return 1; } - unsigned shiftOffset() { return shapeOffset() + getShape().size(); } - }]; -} - #endif diff --git a/flang/include/flang/Optimizer/CodeGen/CGPasses.td b/flang/include/flang/Optimizer/CodeGen/CGPasses.td index 565920e55e6a..f524fb423734 100644 --- a/flang/include/flang/Optimizer/CodeGen/CGPasses.td +++ b/flang/include/flang/Optimizer/CodeGen/CGPasses.td @@ -47,10 +47,6 @@ def CodeGenRewrite : Pass<"cg-rewrite", "mlir::ModuleOp"> { let dependentDialects = [ "fir::FIROpsDialect", "fir::FIRCodeGenDialect" ]; - let options = [ - Option<"preserveDeclare", "preserve-declare", "bool", /*default=*/"false", - "Preserve DeclareOp during pre codegen re-write."> - ]; let statistics = [ Statistic<"numDCE", "num-dce'd", "Number of operations eliminated"> ]; diff --git a/flang/include/flang/Optimizer/CodeGen/CodeGen.h b/flang/include/flang/Optimizer/CodeGen/CodeGen.h index 4d2b191b46d0..26097dabf56c 100644 --- a/flang/include/flang/Optimizer/CodeGen/CodeGen.h +++ b/flang/include/flang/Optimizer/CodeGen/CodeGen.h @@ -30,8 +30,7 @@ struct NameUniquer; /// Prerequiste pass for code gen. Perform intermediate rewrites to perform /// the code gen (to LLVM-IR dialect) conversion. -std::unique_ptr createFirCodeGenRewritePass( - CodeGenRewriteOptions Options = CodeGenRewriteOptions{}); +std::unique_ptr createFirCodeGenRewritePass(); /// FirTargetRewritePass options. struct TargetRewriteOptions { @@ -89,8 +88,7 @@ void populateFIRToLLVMConversionPatterns(fir::LLVMTypeConverter &converter, fir::FIRToLLVMPassOptions &options); /// Populate the pattern set with the PreCGRewrite patterns. -void populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns, - bool preserveDeclare); +void populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns); // declarative passes #define GEN_PASS_REGISTRATION diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc index 761315e0abc8..cc3431d5b71d 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -169,11 +169,9 @@ inline void addMemoryAllocationOpt(mlir::PassManager &pm) { } #if !defined(FLANG_EXCLUDE_CODEGEN) -inline void addCodeGenRewritePass(mlir::PassManager &pm, bool preserveDeclare) { - fir::CodeGenRewriteOptions options; - options.preserveDeclare = preserveDeclare; - addPassConditionally(pm, disableCodeGenRewrite, - [&]() { return fir::createFirCodeGenRewritePass(options); }); +inline void addCodeGenRewritePass(mlir::PassManager &pm) { + addPassConditionally( + pm, disableCodeGenRewrite, fir::createFirCodeGenRewritePass); } inline void addTargetRewritePass(mlir::PassManager &pm) { @@ -355,8 +353,7 @@ inline void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig config, llvm::StringRef inputFilename = {}) { fir::addBoxedProcedurePass(pm); addNestedPassToAllTopLevelOperations(pm, fir::createAbstractResultOpt); - fir::addCodeGenRewritePass( - pm, (config.DebugInfo != llvm::codegenoptions::NoDebugInfo)); + fir::addCodeGenRewritePass(pm); fir::addTargetRewritePass(pm); fir::addExternalNameConversionPass(pm, config.Underscoring); fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename); diff --git a/flang/lib/Optimizer/CodeGen/CGOps.cpp b/flang/lib/Optimizer/CodeGen/CGOps.cpp index 6b8ba7452555..44d07d26dd2b 100644 --- a/flang/lib/Optimizer/CodeGen/CGOps.cpp +++ b/flang/lib/Optimizer/CodeGen/CGOps.cpp @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -#include "flang/Optimizer/CodeGen/CGOps.h" +#include "CGOps.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" diff --git a/flang/include/flang/Optimizer/CodeGen/CGOps.h b/flang/lib/Optimizer/CodeGen/CGOps.h similarity index 94% rename from flang/include/flang/Optimizer/CodeGen/CGOps.h rename to flang/lib/Optimizer/CodeGen/CGOps.h index df909d9ee81c..b5a6d5bb9a9e 100644 --- a/flang/include/flang/Optimizer/CodeGen/CGOps.h +++ b/flang/lib/Optimizer/CodeGen/CGOps.h @@ -13,7 +13,6 @@ #ifndef OPTIMIZER_CODEGEN_CGOPS_H #define OPTIMIZER_CODEGEN_CGOPS_H -#include "flang/Optimizer/Dialect/FIRAttr.h" #include "flang/Optimizer/Dialect/FIRType.h" #include "mlir/Dialect/Func/IR/FuncOps.h" diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 72172f63888e..21154902d23f 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -12,7 +12,7 @@ #include "flang/Optimizer/CodeGen/CodeGen.h" -#include "flang/Optimizer/CodeGen/CGOps.h" +#include "CGOps.h" #include "flang/Optimizer/CodeGen/CodeGenOpenMP.h" #include "flang/Optimizer/CodeGen/FIROpPatterns.h" #include "flang/Optimizer/CodeGen/TypeConverter.h" @@ -170,28 +170,6 @@ genAllocationScaleSize(OP op, mlir::Type ity, return nullptr; } -namespace { -struct DeclareOpConversion : public fir::FIROpConversion { -public: - using FIROpConversion::FIROpConversion; - mlir::LogicalResult - matchAndRewrite(fir::cg::XDeclareOp declareOp, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const override { - auto memRef = adaptor.getOperands()[0]; - if (auto fusedLoc = mlir::dyn_cast(declareOp.getLoc())) { - if (auto varAttr = - mlir::dyn_cast_or_null( - fusedLoc.getMetadata())) { - rewriter.create(memRef.getLoc(), memRef, - varAttr, nullptr); - } - } - rewriter.replaceOp(declareOp, memRef); - return mlir::success(); - } -}; -} // namespace - namespace { /// convert to LLVM IR dialect `alloca` struct AllocaOpConversion : public fir::FIROpConversion { @@ -3736,19 +3714,19 @@ void fir::populateFIRToLLVMConversionPatterns( BoxOffsetOpConversion, BoxProcHostOpConversion, BoxRankOpConversion, BoxTypeCodeOpConversion, BoxTypeDescOpConversion, CallOpConversion, CmpcOpConversion, ConstcOpConversion, ConvertOpConversion, - CoordinateOpConversion, DTEntryOpConversion, DeclareOpConversion, - DivcOpConversion, EmboxOpConversion, EmboxCharOpConversion, - EmboxProcOpConversion, ExtractValueOpConversion, FieldIndexOpConversion, - FirEndOpConversion, FreeMemOpConversion, GlobalLenOpConversion, - GlobalOpConversion, HasValueOpConversion, InsertOnRangeOpConversion, - InsertValueOpConversion, IsPresentOpConversion, LenParamIndexOpConversion, - LoadOpConversion, MulcOpConversion, NegcOpConversion, - NoReassocOpConversion, SelectCaseOpConversion, SelectOpConversion, - SelectRankOpConversion, SelectTypeOpConversion, ShapeOpConversion, - ShapeShiftOpConversion, ShiftOpConversion, SliceOpConversion, - StoreOpConversion, StringLitOpConversion, SubcOpConversion, - TypeDescOpConversion, TypeInfoOpConversion, UnboxCharOpConversion, - UnboxProcOpConversion, UndefOpConversion, UnreachableOpConversion, + CoordinateOpConversion, DTEntryOpConversion, DivcOpConversion, + EmboxOpConversion, EmboxCharOpConversion, EmboxProcOpConversion, + ExtractValueOpConversion, FieldIndexOpConversion, FirEndOpConversion, + FreeMemOpConversion, GlobalLenOpConversion, GlobalOpConversion, + HasValueOpConversion, InsertOnRangeOpConversion, InsertValueOpConversion, + IsPresentOpConversion, LenParamIndexOpConversion, LoadOpConversion, + MulcOpConversion, NegcOpConversion, NoReassocOpConversion, + SelectCaseOpConversion, SelectOpConversion, SelectRankOpConversion, + SelectTypeOpConversion, ShapeOpConversion, ShapeShiftOpConversion, + ShiftOpConversion, SliceOpConversion, StoreOpConversion, + StringLitOpConversion, SubcOpConversion, TypeDescOpConversion, + TypeInfoOpConversion, UnboxCharOpConversion, UnboxProcOpConversion, + UndefOpConversion, UnreachableOpConversion, UnrealizedConversionCastOpConversion, XArrayCoorOpConversion, XEmboxOpConversion, XReboxOpConversion, ZeroOpConversion>(converter, options); diff --git a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp index c54a7457db76..5bd3ec8d1845 100644 --- a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp +++ b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp @@ -12,8 +12,8 @@ #include "flang/Optimizer/CodeGen/CodeGen.h" +#include "CGOps.h" #include "flang/Optimizer/Builder/Todo.h" // remove when TODO's are done -#include "flang/Optimizer/CodeGen/CGOps.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" @@ -270,43 +270,13 @@ public: }; class DeclareOpConversion : public mlir::OpRewritePattern { - bool preserveDeclare; - public: using OpRewritePattern::OpRewritePattern; - DeclareOpConversion(mlir::MLIRContext *ctx, bool preserveDecl) - : OpRewritePattern(ctx), preserveDeclare(preserveDecl) {} mlir::LogicalResult matchAndRewrite(fir::DeclareOp declareOp, mlir::PatternRewriter &rewriter) const override { - if (!preserveDeclare) { - rewriter.replaceOp(declareOp, declareOp.getMemref()); - return mlir::success(); - } - auto loc = declareOp.getLoc(); - llvm::SmallVector shapeOpers; - llvm::SmallVector shiftOpers; - if (auto shapeVal = declareOp.getShape()) { - if (auto shapeOp = mlir::dyn_cast(shapeVal.getDefiningOp())) - populateShape(shapeOpers, shapeOp); - else if (auto shiftOp = - mlir::dyn_cast(shapeVal.getDefiningOp())) - populateShapeAndShift(shapeOpers, shiftOpers, shiftOp); - else if (auto shiftOp = - mlir::dyn_cast(shapeVal.getDefiningOp())) - populateShift(shiftOpers, shiftOp); - else - return mlir::failure(); - } - // FIXME: Add FortranAttrs and CudaAttrs - auto xDeclOp = rewriter.create( - loc, declareOp.getType(), declareOp.getMemref(), shapeOpers, shiftOpers, - declareOp.getTypeparams(), declareOp.getDummyScope(), - declareOp.getUniqName()); - LLVM_DEBUG(llvm::dbgs() - << "rewriting " << declareOp << " to " << xDeclOp << '\n'); - rewriter.replaceOp(declareOp, xDeclOp.getOperation()->getResults()); + rewriter.replaceOp(declareOp, declareOp.getMemref()); return mlir::success(); } }; @@ -327,7 +297,6 @@ public: class CodeGenRewrite : public fir::impl::CodeGenRewriteBase { public: - CodeGenRewrite(fir::CodeGenRewriteOptions opts) : Base(opts) {} void runOnOperation() override final { mlir::ModuleOp mod = getOperation(); @@ -345,7 +314,7 @@ public: mlir::cast(embox.getType()).getEleTy())); }); mlir::RewritePatternSet patterns(&context); - fir::populatePreCGRewritePatterns(patterns, preserveDeclare); + fir::populatePreCGRewritePatterns(patterns); if (mlir::failed( mlir::applyPartialConversion(mod, target, std::move(patterns)))) { mlir::emitError(mlir::UnknownLoc::get(&context), @@ -361,14 +330,12 @@ public: } // namespace -std::unique_ptr -fir::createFirCodeGenRewritePass(fir::CodeGenRewriteOptions Options) { - return std::make_unique(Options); +std::unique_ptr fir::createFirCodeGenRewritePass() { + return std::make_unique(); } -void fir::populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns, - bool preserveDeclare) { +void fir::populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns) { patterns.insert(patterns.getContext()); - patterns.add(patterns.getContext(), preserveDeclare); + DeclareOpConversion, DummyScopeOpConversion>( + patterns.getContext()); } diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index cfad366cb5cb..908c8fc96f63 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -15,7 +15,6 @@ #include "flang/Common/Version.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Todo.h" -#include "flang/Optimizer/CodeGen/CGOps.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" @@ -46,59 +45,13 @@ namespace fir { namespace { class AddDebugInfoPass : public fir::impl::AddDebugInfoBase { - void handleDeclareOp(fir::cg::XDeclareOp declOp, - mlir::LLVM::DIFileAttr fileAttr, - mlir::LLVM::DIScopeAttr scopeAttr, - fir::DebugTypeGenerator &typeGen); - public: AddDebugInfoPass(fir::AddDebugInfoOptions options) : Base(options) {} void runOnOperation() override; }; -static uint32_t getLineFromLoc(mlir::Location loc) { - uint32_t line = 1; - if (auto fileLoc = mlir::dyn_cast(loc)) - line = fileLoc.getLine(); - return line; -} - } // namespace -void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp, - mlir::LLVM::DIFileAttr fileAttr, - mlir::LLVM::DIScopeAttr scopeAttr, - fir::DebugTypeGenerator &typeGen) { - mlir::MLIRContext *context = &getContext(); - mlir::OpBuilder builder(context); - auto result = fir::NameUniquer::deconstruct(declOp.getUniqName()); - - if (result.first != fir::NameUniquer::NameKind::VARIABLE) - return; - - // Only accept local variables. - if (result.second.procs.empty()) - return; - - // FIXME: There may be cases where an argument is processed a bit before - // DeclareOp is generated. In that case, DeclareOp may point to an - // intermediate op and not to BlockArgument. We need to find those cases and - // walk the chain to get to the actual argument. - - unsigned argNo = 0; - if (auto Arg = llvm::dyn_cast(declOp.getMemref())) - argNo = Arg.getArgNumber() + 1; - - auto tyAttr = typeGen.convertType(fir::unwrapRefType(declOp.getType()), - fileAttr, scopeAttr, declOp.getLoc()); - - auto localVarAttr = mlir::LLVM::DILocalVariableAttr::get( - context, scopeAttr, mlir::StringAttr::get(context, result.second.name), - fileAttr, getLineFromLoc(declOp.getLoc()), argNo, /* alignInBits*/ 0, - tyAttr); - declOp->setLoc(builder.getFusedLoc({declOp->getLoc()}, localVarAttr)); -} - void AddDebugInfoPass::runOnOperation() { mlir::ModuleOp module = getOperation(); mlir::MLIRContext *context = &getContext(); @@ -191,15 +144,14 @@ void AddDebugInfoPass::runOnOperation() { subprogramFlags = subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition; } - unsigned line = getLineFromLoc(l); + unsigned line = 1; + if (auto funcLoc = mlir::dyn_cast(l)) + line = funcLoc.getLine(); + auto spAttr = mlir::LLVM::DISubprogramAttr::get( context, id, compilationUnit, fileAttr, funcName, fullName, funcFileAttr, line, line, subprogramFlags, subTypeAttr); funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr)); - - funcOp.walk([&](fir::cg::XDeclareOp declOp) { - handleDeclareOp(declOp, fileAttr, spAttr, typeGen); - }); }); } diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp index 64c6547e06e0..e5b4050dfb24 100644 --- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp @@ -24,6 +24,11 @@ DebugTypeGenerator::DebugTypeGenerator(mlir::ModuleOp m) LLVM_DEBUG(llvm::dbgs() << "DITypeAttr generator\n"); } +static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) { + return mlir::LLVM::DIBasicTypeAttr::get( + context, llvm::dwarf::DW_TAG_base_type, "void", 32, 1); +} + static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context, mlir::StringAttr name, unsigned bitSize, @@ -32,11 +37,6 @@ static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context, context, llvm::dwarf::DW_TAG_base_type, name, bitSize, decoding); } -static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) { - return genBasicType(context, mlir::StringAttr::get(context, "integer"), 32, - llvm::dwarf::DW_ATE_signed); -} - mlir::LLVM::DITypeAttr DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scope, diff --git a/flang/test/Fir/declare-codegen.fir b/flang/test/Fir/declare-codegen.fir index c5879facb157..9d68d3b2f9d4 100644 --- a/flang/test/Fir/declare-codegen.fir +++ b/flang/test/Fir/declare-codegen.fir @@ -1,7 +1,5 @@ // Test rewrite of fir.declare. The result is replaced by the memref operand. -// RUN: fir-opt --cg-rewrite="preserve-declare=true" %s -o - | FileCheck %s --check-prefixes DECL -// RUN: fir-opt --cg-rewrite="preserve-declare=false" %s -o - | FileCheck %s --check-prefixes NODECL -// RUN: fir-opt --cg-rewrite %s -o - | FileCheck %s --check-prefixes NODECL +// RUN: fir-opt --cg-rewrite %s -o - | FileCheck %s func.func @test(%arg0: !fir.ref>) { @@ -17,14 +15,9 @@ func.func @test(%arg0: !fir.ref>) { func.func private @bar(%arg0: !fir.ref>) -// NODECL-LABEL: func.func @test( -// NODECL-SAME: %[[arg0:.*]]: !fir.ref>) { -// NODECL-NEXT: fir.call @bar(%[[arg0]]) : (!fir.ref>) -> () - -// DECL-LABEL: func.func @test( -// DECL-SAME: %[[arg0:.*]]: !fir.ref>) { -// DECL: fircg.ext_declare - +// CHECK-LABEL: func.func @test( +// CHECK-SAME: %[[arg0:.*]]: !fir.ref>) { +// CHECK-NEXT: fir.call @bar(%[[arg0]]) : (!fir.ref>) -> () func.func @useless_shape_with_duplicate_extent_operand(%arg0: !fir.ref>) { %c3 = arith.constant 3 : index @@ -33,8 +26,5 @@ func.func @useless_shape_with_duplicate_extent_operand(%arg0: !fir.ref) { %scope = fir.dummy_scope : !fir.dscope %0 = fir.declare %arg0 dummy_scope %scope {uniq_name = "x"} : (!fir.ref, !fir.dscope) -> !fir.ref return } -// DECL-LABEL: func.func @dummy_scope( -// DECL: fircg.ext_declare - -// NODECL-LABEL: func.func @dummy_scope( -// NODECL-NEXT: return \ No newline at end of file +// CHECK-LABEL: func.func @dummy_scope( +// CHECK-NEXT: return diff --git a/flang/test/Transforms/debug-local-var-2.f90 b/flang/test/Transforms/debug-local-var-2.f90 deleted file mode 100644 index 15b9b148492e..000000000000 --- a/flang/test/Transforms/debug-local-var-2.f90 +++ /dev/null @@ -1,91 +0,0 @@ -! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s - -! This tests checks the debug information for local variables in llvm IR. - -! CHECK-LABEL: define void @_QQmain -! CHECK-DAG: %[[AL11:.*]] = alloca i32 -! CHECK-DAG: %[[AL12:.*]] = alloca i64 -! CHECK-DAG: %[[AL13:.*]] = alloca i8 -! CHECK-DAG: %[[AL14:.*]] = alloca i32 -! CHECK-DAG: %[[AL15:.*]] = alloca float -! CHECK-DAG: %[[AL16:.*]] = alloca double -! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL11]], metadata ![[I4:.*]], metadata !DIExpression()) -! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL12]], metadata ![[I8:.*]], metadata !DIExpression()) -! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL13]], metadata ![[L1:.*]], metadata !DIExpression()) -! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL14]], metadata ![[L4:.*]], metadata !DIExpression()) -! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL15]], metadata ![[R4:.*]], metadata !DIExpression()) -! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL16]], metadata ![[R8:.*]], metadata !DIExpression()) -! CHECK-LABEL: } - -! CHECK-LABEL: define {{.*}}i64 @_QFPfn1 -! CHECK-SAME: (ptr %[[ARG1:.*]], ptr %[[ARG2:.*]], ptr %[[ARG3:.*]]) -! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[ARG1]], metadata ![[A1:.*]], metadata !DIExpression()) -! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[ARG2]], metadata ![[B1:.*]], metadata !DIExpression()) -! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[ARG3]], metadata ![[C1:.*]], metadata !DIExpression()) -! CHECK-DAG: %[[AL2:.*]] = alloca i64 -! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[AL2]], metadata ![[RES1:.*]], metadata !DIExpression()) -! CHECK-LABEL: } - -! CHECK-LABEL: define {{.*}}i32 @_QFPfn2 -! CHECK-SAME: (ptr %[[FN2ARG1:.*]], ptr %[[FN2ARG2:.*]], ptr %[[FN2ARG3:.*]]) -! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[FN2ARG1]], metadata ![[A2:.*]], metadata !DIExpression()) -! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[FN2ARG2]], metadata ![[B2:.*]], metadata !DIExpression()) -! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[FN2ARG3]], metadata ![[C2:.*]], metadata !DIExpression()) -! CHECK-DAG: %[[AL3:.*]] = alloca i32 -! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[AL3]], metadata ![[RES2:.*]], metadata !DIExpression()) -! CHECK-LABEL: } - -program mn -! CHECK-DAG: ![[MAIN:.*]] = distinct !DISubprogram(name: "_QQmain", {{.*}}) - -! CHECK-DAG: ![[TYI32:.*]] = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed) -! CHECK-DAG: ![[TYI64:.*]] = !DIBasicType(name: "integer", size: 64, encoding: DW_ATE_signed) -! CHECK-DAG: ![[TYL8:.*]] = !DIBasicType(name: "logical", size: 8, encoding: DW_ATE_boolean) -! CHECK-DAG: ![[TYL32:.*]] = !DIBasicType(name: "logical", size: 32, encoding: DW_ATE_boolean) -! CHECK-DAG: ![[TYR32:.*]] = !DIBasicType(name: "real", size: 32, encoding: DW_ATE_float) -! CHECK-DAG: ![[TYR64:.*]] = !DIBasicType(name: "real", size: 64, encoding: DW_ATE_float) - -! CHECK-DAG: ![[I4]] = !DILocalVariable(name: "i4", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYI32]]) -! CHECK-DAG: ![[I8]] = !DILocalVariable(name: "i8", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYI64]]) -! CHECK-DAG: ![[R4]] = !DILocalVariable(name: "r4", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYR32]]) -! CHECK-DAG: ![[R8]] = !DILocalVariable(name: "r8", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYR64]]) -! CHECK-DAG: ![[L1]] = !DILocalVariable(name: "l1", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYL8]]) -! CHECK-DAG: ![[L4]] = !DILocalVariable(name: "l4", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYL32]]) - integer(kind=4) :: i4 - integer(kind=8) :: i8 - real(kind=4) :: r4 - real(kind=8) :: r8 - logical(kind=1) :: l1 - logical(kind=4) :: l4 - - i8 = fn1(i4, r8, l1) - i4 = fn2(i8, r4, l4) -contains -! CHECK-DAG: ![[FN1:.*]] = distinct !DISubprogram(name: "fn1", {{.*}}) -! CHECK-DAG: ![[A1]] = !DILocalVariable(name: "a1", arg: 1, scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI32]]) -! CHECK-DAG: ![[B1]] = !DILocalVariable(name: "b1", arg: 2, scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYR64]]) -! CHECK-DAG: ![[C1]] = !DILocalVariable(name: "c1", arg: 3, scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYL8]]) -! CHECK-DAG: ![[RES1]] = !DILocalVariable(name: "res1", scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI64]]) - function fn1(a1, b1, c1) result (res1) - integer(kind=4), intent(in) :: a1 - real(kind=8), intent(in) :: b1 - logical(kind=1), intent(in) :: c1 - integer(kind=8) :: res1 - - res1 = a1 + b1 - end function - -! CHECK-DAG: ![[FN2:.*]] = distinct !DISubprogram(name: "fn2", {{.*}}) -! CHECK-DAG: ![[A2]] = !DILocalVariable(name: "a2", arg: 1, scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI64]]) -! CHECK-DAG: ![[B2]] = !DILocalVariable(name: "b2", arg: 2, scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYR32]]) -! CHECK-DAG: ![[C2]] = !DILocalVariable(name: "c2", arg: 3, scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYL32]]) -! CHECK-DAG: ![[RES2]] = !DILocalVariable(name: "res2", scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI32]]) - function fn2(a2, b2, c2) result (res2) - integer(kind=8), intent(in) :: a2 - real(kind=4), intent(in) :: b2 - logical(kind=4), intent(in) :: c2 - integer(kind=4) :: res2 - - res2 = a2 + b2 - end function -end program diff --git a/flang/test/Transforms/debug-local-var.f90 b/flang/test/Transforms/debug-local-var.f90 deleted file mode 100644 index 96dc111ad308..000000000000 --- a/flang/test/Transforms/debug-local-var.f90 +++ /dev/null @@ -1,54 +0,0 @@ -! RUN: %flang_fc1 -emit-fir -debug-info-kind=standalone -mmlir --mlir-print-debuginfo %s -o - | \ -! RUN: fir-opt --cg-rewrite="preserve-declare=true" --mlir-print-debuginfo | fir-opt --add-debug-info --mlir-print-debuginfo | FileCheck %s - -! CHECK-DAG: #[[INT8:.*]] = #llvm.di_basic_type -! CHECK-DAG: #[[INT4:.*]] = #llvm.di_basic_type -! CHECK-DAG: #[[REAL8:.*]] = #llvm.di_basic_type -! CHECK-DAG: #[[LOG1:.*]] = #llvm.di_basic_type -! CHECK-DAG: #[[REAL4:.*]] = #llvm.di_basic_type -! CHECK-DAG: #[[LOG4:.*]] = #llvm.di_basic_type -! CHECK-DAG: #[[MAIN:.*]] = #llvm.di_subprogram<{{.*}}name = "_QQmain"{{.*}}> -! CHECK-DAG: #[[FN1:.*]] = #llvm.di_subprogram<{{.*}}name = "fn1"{{.*}}> -! CHECK-DAG: #[[FN2:.*]] = #llvm.di_subprogram<{{.*}}name = "fn2"{{.*}}> - -program mn -! CHECK-DAG: #[[I4:.*]] = #llvm.di_local_variable -! CHECK-DAG: #[[I8:.*]] = #llvm.di_local_variable -! CHECK-DAG: #[[R4:.*]] = #llvm.di_local_variable -! CHECK-DAG: #[[R8:.*]] = #llvm.di_local_variable -! CHECK-DAG: #[[L1:.*]] = #llvm.di_local_variable -! CHECK-DAG: #[[L4:.*]] = #llvm.di_local_variable - integer(kind=4) :: i4 - integer(kind=8) :: i8 - real(kind=4) :: r4 - real(kind=8) :: r8 - logical(kind=1) :: l1 - logical(kind=4) :: l4 - i8 = fn1(i4, r8, l1) - i4 = fn2(i8, r4, l4) -contains - function fn1(a1, b1, c1) result (res1) -! CHECK-DAG: #[[A1:.*]] = #llvm.di_local_variable -! CHECK-DAG: #[[B1:.*]] = #llvm.di_local_variable -! CHECK-DAG: #[[C1:.*]] = #llvm.di_local_variable -! CHECK-DAG: #[[RES1:.*]] = #llvm.di_local_variable - integer(kind=4), intent(in) :: a1 - real(kind=8), intent(in) :: b1 - logical(kind=1), intent(in) :: c1 - integer(kind=8) :: res1 - res1 = a1 + b1 - end function - - function fn2(a2, b2, c2) result (res2) - implicit none -! CHECK-DAG: #[[A2:.*]] = #llvm.di_local_variable -! CHECK-DAG: #[[B2:.*]] = #llvm.di_local_variable -! CHECK-DAG: #[[C2:.*]] = #llvm.di_local_variable -! CHECK-DAG: #[[RES2:.*]] = #llvm.di_local_variable - integer(kind=8), intent(in) :: a2 - real(kind=4), intent(in) :: b2 - logical(kind=4), intent(in) :: c2 - integer(kind=4) :: res2 - res2 = a2 + b2 - end function -end program -- GitLab From 411bf385ba27f15145c635c7d8ff2701fe8de5b9 Mon Sep 17 00:00:00 2001 From: Walter Erquinigo Date: Wed, 15 May 2024 20:44:12 +0200 Subject: [PATCH 399/578] [lldb-dap] Include npm install in the extension installation steps (#92028) Otherwise the build step fails due to missing dependencies. --- lldb/tools/lldb-dap/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lldb/tools/lldb-dap/README.md b/lldb/tools/lldb-dap/README.md index 274b1519208a..16ce4672be71 100644 --- a/lldb/tools/lldb-dap/README.md +++ b/lldb/tools/lldb-dap/README.md @@ -46,6 +46,7 @@ Installing the plug-in is very straightforward and involves just a few steps. ```bash cd /path/to/lldb/tools/lldb-dap +npm install npm run package # This also compiles the extension. npm run vscode-install ``` @@ -69,6 +70,7 @@ no effect. ```bash # Bump version in package.json cd /path/to/lldb/tools/lldb-dap +npm install npm run package npm run vscode-install ``` -- GitLab From 2c54bf497f7d7aecd24f4b849ee08e37a3519611 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Wed, 15 May 2024 11:44:26 -0700 Subject: [PATCH 400/578] Revert "Reapply "[ctx_profile] Profile reader and writer" (#92199)" This reverts commit c19f2c773b0e23fd623502888894add822079f63. Broke the gcc-7 bot. --- .../llvm/ProfileData/PGOCtxProfReader.h | 92 ------- .../llvm/ProfileData/PGOCtxProfWriter.h | 91 ------- llvm/lib/ProfileData/CMakeLists.txt | 3 - llvm/lib/ProfileData/PGOCtxProfReader.cpp | 173 ------------ llvm/lib/ProfileData/PGOCtxProfWriter.cpp | 49 ---- llvm/unittests/ProfileData/CMakeLists.txt | 1 - .../PGOCtxProfReaderWriterTest.cpp | 255 ------------------ 7 files changed, 664 deletions(-) delete mode 100644 llvm/include/llvm/ProfileData/PGOCtxProfReader.h delete mode 100644 llvm/include/llvm/ProfileData/PGOCtxProfWriter.h delete mode 100644 llvm/lib/ProfileData/PGOCtxProfReader.cpp delete mode 100644 llvm/lib/ProfileData/PGOCtxProfWriter.cpp delete mode 100644 llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp diff --git a/llvm/include/llvm/ProfileData/PGOCtxProfReader.h b/llvm/include/llvm/ProfileData/PGOCtxProfReader.h deleted file mode 100644 index a19b3f51d642..000000000000 --- a/llvm/include/llvm/ProfileData/PGOCtxProfReader.h +++ /dev/null @@ -1,92 +0,0 @@ -//===--- PGOCtxProfReader.h - Contextual profile reader ---------*- 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 -/// -/// Reader for contextual iFDO profile, which comes in bitstream format. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H -#define LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/Bitstream/BitstreamReader.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/ProfileData/PGOCtxProfWriter.h" -#include "llvm/Support/Error.h" -#include -#include - -namespace llvm { -/// The loaded contextual profile, suitable for mutation during IPO passes. We -/// generally expect a fraction of counters and of callsites to be populated. -/// We continue to model counters as vectors, but callsites are modeled as a map -/// of a map. The expectation is that, typically, there is a small number of -/// indirect targets (usually, 1 for direct calls); but potentially a large -/// number of callsites, and, as inlining progresses, the callsite count of a -/// caller will grow. -class PGOContextualProfile final { -public: - using CallTargetMapTy = std::map; - using CallsiteMapTy = DenseMap; - -private: - friend class PGOCtxProfileReader; - GlobalValue::GUID GUID = 0; - SmallVector Counters; - CallsiteMapTy Callsites; - - PGOContextualProfile(GlobalValue::GUID G, - SmallVectorImpl &&Counters) - : GUID(G), Counters(std::move(Counters)) {} - - Expected - getOrEmplace(uint32_t Index, GlobalValue::GUID G, - SmallVectorImpl &&Counters); - -public: - PGOContextualProfile(const PGOContextualProfile &) = delete; - PGOContextualProfile &operator=(const PGOContextualProfile &) = delete; - PGOContextualProfile(PGOContextualProfile &&) = default; - PGOContextualProfile &operator=(PGOContextualProfile &&) = default; - - GlobalValue::GUID guid() const { return GUID; } - const SmallVectorImpl &counters() const { return Counters; } - const CallsiteMapTy &callsites() const { return Callsites; } - CallsiteMapTy &callsites() { return Callsites; } - - bool hasCallsite(uint32_t I) const { - return Callsites.find(I) != Callsites.end(); - } - - const CallTargetMapTy &callsite(uint32_t I) const { - assert(hasCallsite(I) && "Callsite not found"); - return Callsites.find(I)->second; - } - void getContainedGuids(DenseSet &Guids) const; -}; - -class PGOCtxProfileReader final { - BitstreamCursor &Cursor; - Expected advance(); - Error readMetadata(); - Error wrongValue(const Twine &); - Error unsupported(const Twine &); - - Expected, PGOContextualProfile>> - readContext(bool ExpectIndex); - bool canReadContext(); - -public: - PGOCtxProfileReader(BitstreamCursor &Cursor) : Cursor(Cursor) {} - - Expected> loadContexts(); -}; -} // namespace llvm -#endif diff --git a/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h b/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h deleted file mode 100644 index 15578c51a495..000000000000 --- a/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h +++ /dev/null @@ -1,91 +0,0 @@ -//===- PGOCtxProfWriter.h - Contextual Profile Writer -----------*- 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 -// -//===----------------------------------------------------------------------===// -// -// This file declares a utility for writing a contextual profile to bitstream. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ -#define LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ - -#include "llvm/Bitstream/BitstreamWriter.h" -#include "llvm/ProfileData/CtxInstrContextNode.h" - -namespace llvm { -enum PGOCtxProfileRecords { Invalid = 0, Version, Guid, CalleeIndex, Counters }; - -enum PGOCtxProfileBlockIDs { - ProfileMetadataBlockID = 100, - ContextNodeBlockID = ProfileMetadataBlockID + 1 -}; - -/// Write one or more ContextNodes to the provided raw_fd_stream. -/// The caller must destroy the PGOCtxProfileWriter object before closing the -/// stream. -/// The design allows serializing a bunch of contexts embedded in some other -/// file. The overall format is: -/// -/// [... other data written to the stream...] -/// SubBlock(ProfileMetadataBlockID) -/// Version -/// SubBlock(ContextNodeBlockID) -/// [RECORDS] -/// SubBlock(ContextNodeBlockID) -/// [RECORDS] -/// [... more SubBlocks] -/// EndBlock -/// EndBlock -/// -/// The "RECORDS" are bitsream records. The IDs are in CtxProfileCodes (except) -/// for Version, which is just for metadata). All contexts will have Guid and -/// Counters, and all but the roots have CalleeIndex. The order in which the -/// records appear does not matter, but they must precede any subcontexts, -/// because that helps keep the reader code simpler. -/// -/// Subblock containment captures the context->subcontext relationship. The -/// "next()" relationship in the raw profile, between call targets of indirect -/// calls, are just modeled as peer subblocks where the callee index is the -/// same. -/// -/// Versioning: the writer may produce additional records not known by the -/// reader. The version number indicates a more structural change. -/// The current version, in particular, is set up to expect optional extensions -/// like value profiling - which would appear as additional records. For -/// example, value profiling would produce a new record with a new record ID, -/// containing the profiled values (much like the counters) -class PGOCtxProfileWriter final { - SmallVector Buff; - BitstreamWriter Writer; - - void writeCounters(const ctx_profile::ContextNode &Node); - void writeImpl(std::optional CallerIndex, - const ctx_profile::ContextNode &Node); - -public: - PGOCtxProfileWriter(raw_fd_stream &Out, - std::optional VersionOverride = std::nullopt) - : Writer(Buff, &Out, 0) { - Writer.EnterSubblock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID, - CodeLen); - const auto Version = VersionOverride ? *VersionOverride : CurrentVersion; - Writer.EmitRecord(PGOCtxProfileRecords::Version, - SmallVector({Version})); - } - - ~PGOCtxProfileWriter() { Writer.ExitBlock(); } - - void write(const ctx_profile::ContextNode &); - - // constants used in writing which a reader may find useful. - static constexpr unsigned CodeLen = 2; - static constexpr uint32_t CurrentVersion = 1; - static constexpr unsigned VBREncodingBits = 6; -}; - -} // namespace llvm -#endif diff --git a/llvm/lib/ProfileData/CMakeLists.txt b/llvm/lib/ProfileData/CMakeLists.txt index 4fa1b76f0a06..408f9ff01ec8 100644 --- a/llvm/lib/ProfileData/CMakeLists.txt +++ b/llvm/lib/ProfileData/CMakeLists.txt @@ -7,8 +7,6 @@ add_llvm_component_library(LLVMProfileData ItaniumManglingCanonicalizer.cpp MemProf.cpp MemProfReader.cpp - PGOCtxProfReader.cpp - PGOCtxProfWriter.cpp ProfileSummaryBuilder.cpp SampleProf.cpp SampleProfReader.cpp @@ -22,7 +20,6 @@ add_llvm_component_library(LLVMProfileData intrinsics_gen LINK_COMPONENTS - BitstreamReader Core Object Support diff --git a/llvm/lib/ProfileData/PGOCtxProfReader.cpp b/llvm/lib/ProfileData/PGOCtxProfReader.cpp deleted file mode 100644 index 3710f2e4b818..000000000000 --- a/llvm/lib/ProfileData/PGOCtxProfReader.cpp +++ /dev/null @@ -1,173 +0,0 @@ -//===- PGOCtxProfReader.cpp - Contextual Instrumentation profile reader ---===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Read a contextual profile into a datastructure suitable for maintenance -// throughout IPO -// -//===----------------------------------------------------------------------===// - -#include "llvm/ProfileData/PGOCtxProfReader.h" -#include "llvm/Bitstream/BitCodeEnums.h" -#include "llvm/Bitstream/BitstreamReader.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/ProfileData/PGOCtxProfWriter.h" -#include "llvm/Support/Errc.h" -#include "llvm/Support/Error.h" - -using namespace llvm; - -// FIXME(#92054) - these Error handling macros are (re-)invented in a few -// places. -#define EXPECT_OR_RET(LHS, RHS) \ - auto LHS = RHS; \ - if (!LHS) \ - return LHS.takeError(); - -#define RET_ON_ERR(EXPR) \ - if (auto Err = (EXPR)) \ - return Err; - -Expected -PGOContextualProfile::getOrEmplace(uint32_t Index, GlobalValue::GUID G, - SmallVectorImpl &&Counters) { - auto [Iter, Inserted] = Callsites[Index].insert( - {G, PGOContextualProfile(G, std::move(Counters))}); - if (!Inserted) - return make_error(instrprof_error::invalid_prof, - "Duplicate GUID for same callsite."); - return Iter->second; -} - -void PGOContextualProfile::getContainedGuids( - DenseSet &Guids) const { - Guids.insert(GUID); - for (const auto &[_, Callsite] : Callsites) - for (const auto &[_, Callee] : Callsite) - Callee.getContainedGuids(Guids); -} - -Expected PGOCtxProfileReader::advance() { - return Cursor.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); -} - -Error PGOCtxProfileReader::wrongValue(const Twine &Msg) { - return make_error(instrprof_error::invalid_prof, Msg); -} - -Error PGOCtxProfileReader::unsupported(const Twine &Msg) { - return make_error(instrprof_error::unsupported_version, Msg); -} - -bool PGOCtxProfileReader::canReadContext() { - auto Blk = advance(); - if (!Blk) { - consumeError(Blk.takeError()); - return false; - } - return Blk->Kind == BitstreamEntry::SubBlock && - Blk->ID == PGOCtxProfileBlockIDs::ContextNodeBlockID; -} - -Expected, PGOContextualProfile>> -PGOCtxProfileReader::readContext(bool ExpectIndex) { - RET_ON_ERR(Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ContextNodeBlockID)); - - std::optional Guid; - std::optional> Counters; - std::optional CallsiteIndex; - - SmallVector RecordValues; - - // We don't prescribe the order in which the records come in, and we are ok - // if other unsupported records appear. We seek in the current subblock until - // we get all we know. - auto GotAllWeNeed = [&]() { - return Guid.has_value() && Counters.has_value() && - (!ExpectIndex || CallsiteIndex.has_value()); - }; - while (!GotAllWeNeed()) { - RecordValues.clear(); - EXPECT_OR_RET(Entry, advance()); - if (Entry->Kind != BitstreamEntry::Record) - return wrongValue( - "Expected records before encountering more subcontexts"); - EXPECT_OR_RET(ReadRecord, - Cursor.readRecord(bitc::UNABBREV_RECORD, RecordValues)); - switch (*ReadRecord) { - case PGOCtxProfileRecords::Guid: - if (RecordValues.size() != 1) - return wrongValue("The GUID record should have exactly one value"); - Guid = RecordValues[0]; - break; - case PGOCtxProfileRecords::Counters: - Counters = std::move(RecordValues); - if (Counters->empty()) - return wrongValue("Empty counters. At least the entry counter (one " - "value) was expected"); - break; - case PGOCtxProfileRecords::CalleeIndex: - if (!ExpectIndex) - return wrongValue("The root context should not have a callee index"); - if (RecordValues.size() != 1) - return wrongValue("The callee index should have exactly one value"); - CallsiteIndex = RecordValues[0]; - break; - default: - // OK if we see records we do not understand, like records (profile - // components) introduced later. - break; - } - } - - PGOContextualProfile Ret(*Guid, std::move(*Counters)); - - while (canReadContext()) { - EXPECT_OR_RET(SC, readContext(true)); - auto &Targets = Ret.callsites()[*SC->first]; - auto [_, Inserted] = - Targets.insert({SC->second.guid(), std::move(SC->second)}); - if (!Inserted) - return wrongValue( - "Unexpected duplicate target (callee) at the same callsite."); - } - return std::make_pair(CallsiteIndex, std::move(Ret)); -} - -Error PGOCtxProfileReader::readMetadata() { - EXPECT_OR_RET(Blk, advance()); - if (Blk->Kind != BitstreamEntry::SubBlock) - return unsupported("Expected Version record"); - RET_ON_ERR( - Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID)); - EXPECT_OR_RET(MData, advance()); - if (MData->Kind != BitstreamEntry::Record) - return unsupported("Expected Version record"); - - SmallVector Ver; - EXPECT_OR_RET(Code, Cursor.readRecord(bitc::UNABBREV_RECORD, Ver)); - if (*Code != PGOCtxProfileRecords::Version) - return unsupported("Expected Version record"); - if (Ver.size() != 1 || Ver[0] > PGOCtxProfileWriter::CurrentVersion) - return unsupported("Version " + Twine(*Code) + - " is higher than supported version " + - Twine(PGOCtxProfileWriter::CurrentVersion)); - return Error::success(); -} - -Expected> -PGOCtxProfileReader::loadContexts() { - std::map Ret; - RET_ON_ERR(readMetadata()); - while (canReadContext()) { - EXPECT_OR_RET(E, readContext(false)); - auto Key = E->second.guid(); - if (!Ret.insert({Key, std::move(E->second)}).second) - return wrongValue("Duplicate roots"); - } - return Ret; -} diff --git a/llvm/lib/ProfileData/PGOCtxProfWriter.cpp b/llvm/lib/ProfileData/PGOCtxProfWriter.cpp deleted file mode 100644 index 508179756446..000000000000 --- a/llvm/lib/ProfileData/PGOCtxProfWriter.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===- PGOCtxProfWriter.cpp - Contextual Instrumentation profile writer ---===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Write a contextual profile to bitstream. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ProfileData/PGOCtxProfWriter.h" -#include "llvm/Bitstream/BitCodeEnums.h" - -using namespace llvm; -using namespace llvm::ctx_profile; - -void PGOCtxProfileWriter::writeCounters(const ContextNode &Node) { - Writer.EmitCode(bitc::UNABBREV_RECORD); - Writer.EmitVBR(PGOCtxProfileRecords::Counters, VBREncodingBits); - Writer.EmitVBR(Node.counters_size(), VBREncodingBits); - for (uint32_t I = 0U; I < Node.counters_size(); ++I) - Writer.EmitVBR64(Node.counters()[I], VBREncodingBits); -} - -// recursively write all the subcontexts. We do need to traverse depth first to -// model the context->subcontext implicitly, and since this captures call -// stacks, we don't really need to be worried about stack overflow and we can -// keep the implementation simple. -void PGOCtxProfileWriter::writeImpl(std::optional CallerIndex, - const ContextNode &Node) { - Writer.EnterSubblock(PGOCtxProfileBlockIDs::ContextNodeBlockID, CodeLen); - Writer.EmitRecord(PGOCtxProfileRecords::Guid, - SmallVector{Node.guid()}); - if (CallerIndex) - Writer.EmitRecord(PGOCtxProfileRecords::CalleeIndex, - SmallVector{*CallerIndex}); - writeCounters(Node); - for (uint32_t I = 0U; I < Node.callsites_size(); ++I) - for (const auto *Subcontext = Node.subContexts()[I]; Subcontext; - Subcontext = Subcontext->next()) - writeImpl(I, *Subcontext); - Writer.ExitBlock(); -} - -void PGOCtxProfileWriter::write(const ContextNode &RootNode) { - writeImpl(std::nullopt, RootNode); -} diff --git a/llvm/unittests/ProfileData/CMakeLists.txt b/llvm/unittests/ProfileData/CMakeLists.txt index c92642ded828..ce3a0a45ccf1 100644 --- a/llvm/unittests/ProfileData/CMakeLists.txt +++ b/llvm/unittests/ProfileData/CMakeLists.txt @@ -13,7 +13,6 @@ add_llvm_unittest(ProfileDataTests InstrProfTest.cpp ItaniumManglingCanonicalizerTest.cpp MemProfTest.cpp - PGOCtxProfReaderWriterTest.cpp SampleProfTest.cpp SymbolRemappingReaderTest.cpp ) diff --git a/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp b/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp deleted file mode 100644 index d2cdbb28e2fc..000000000000 --- a/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp +++ /dev/null @@ -1,255 +0,0 @@ -//===-------------- PGOCtxProfReadWriteTest.cpp ---------------------------===// -// -// 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 "llvm/Bitstream/BitstreamReader.h" -#include "llvm/ProfileData/CtxInstrContextNode.h" -#include "llvm/ProfileData/PGOCtxProfReader.h" -#include "llvm/ProfileData/PGOCtxProfWriter.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Testing/Support/SupportHelpers.h" -#include "gtest/gtest.h" - -using namespace llvm; -using namespace llvm::ctx_profile; - -class PGOCtxProfRWTest : public ::testing::Test { - std::vector> Nodes; - std::map Roots; - -public: - ContextNode *createNode(GUID Guid, uint32_t NrCounters, uint32_t NrCallsites, - ContextNode *Next = nullptr) { - auto AllocSize = ContextNode::getAllocSize(NrCounters, NrCallsites); - auto *Mem = Nodes.emplace_back(std::make_unique(AllocSize)).get(); - std::memset(Mem, 0, AllocSize); - auto *Ret = new (Mem) ContextNode(Guid, NrCounters, NrCallsites, Next); - return Ret; - } - - void SetUp() override { - // Root (guid 1) has 2 callsites, one used for an indirect call to either - // guid 2 or 4. - // guid 2 calls guid 5 - // guid 5 calls guid 2 - // there's also a second root, guid3. - auto *Root1 = createNode(1, 2, 2); - Root1->counters()[0] = 10; - Root1->counters()[1] = 11; - Roots.insert({1, Root1}); - auto *L1 = createNode(2, 1, 1); - L1->counters()[0] = 12; - Root1->subContexts()[1] = createNode(4, 3, 1, L1); - Root1->subContexts()[1]->counters()[0] = 13; - Root1->subContexts()[1]->counters()[1] = 14; - Root1->subContexts()[1]->counters()[2] = 15; - - auto *L3 = createNode(5, 6, 3); - for (auto I = 0; I < 6; ++I) - L3->counters()[I] = 16 + I; - L1->subContexts()[0] = L3; - L3->subContexts()[2] = createNode(2, 1, 1); - L3->subContexts()[2]->counters()[0] = 30; - auto *Root2 = createNode(3, 1, 0); - Root2->counters()[0] = 40; - Roots.insert({3, Root2}); - } - - const std::map &roots() const { return Roots; } -}; - -void checkSame(const ContextNode &Raw, const PGOContextualProfile &Profile) { - EXPECT_EQ(Raw.guid(), Profile.guid()); - ASSERT_EQ(Raw.counters_size(), Profile.counters().size()); - for (auto I = 0U; I < Raw.counters_size(); ++I) - EXPECT_EQ(Raw.counters()[I], Profile.counters()[I]); - - for (auto I = 0U; I < Raw.callsites_size(); ++I) { - if (Raw.subContexts()[I] == nullptr) - continue; - EXPECT_TRUE(Profile.hasCallsite(I)); - const auto &ProfileTargets = Profile.callsite(I); - - std::map Targets; - for (const auto *N = Raw.subContexts()[I]; N; N = N->next()) - EXPECT_TRUE(Targets.insert({N->guid(), N}).second); - - EXPECT_EQ(Targets.size(), ProfileTargets.size()); - for (auto It : Targets) { - auto PIt = ProfileTargets.find(It.second->guid()); - EXPECT_NE(PIt, ProfileTargets.end()); - checkSame(*It.second, PIt->second); - } - } -} - -TEST_F(PGOCtxProfRWTest, RoundTrip) { - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - PGOCtxProfileWriter Writer(Out); - for (auto &[_, R] : roots()) - Writer.write(*R); - } - } - { - ErrorOr> MB = - MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - ASSERT_TRUE(!!Expected); - auto &Ctxes = *Expected; - EXPECT_EQ(Ctxes.size(), roots().size()); - EXPECT_EQ(Ctxes.size(), 2U); - for (auto &[G, R] : roots()) - checkSame(*R, Ctxes.find(G)->second); - } -} - -TEST_F(PGOCtxProfRWTest, InvalidCounters) { - auto *R = createNode(1, 0, 1); - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - PGOCtxProfileWriter Writer(Out); - Writer.write(*R); - } - } - { - auto MB = MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); - } -} - -TEST_F(PGOCtxProfRWTest, Empty) { - BitstreamCursor Cursor(""); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); -} - -TEST_F(PGOCtxProfRWTest, Invalid) { - BitstreamCursor Cursor("Surely this is not valid"); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); -} - -TEST_F(PGOCtxProfRWTest, ValidButEmpty) { - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - PGOCtxProfileWriter Writer(Out); - // don't write anything - this will just produce the metadata subblock. - } - } - { - auto MB = MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_TRUE(!!Expected); - EXPECT_TRUE(Expected->empty()); - } -} - -TEST_F(PGOCtxProfRWTest, WrongVersion) { - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - PGOCtxProfileWriter Writer(Out, PGOCtxProfileWriter::CurrentVersion + 1); - } - } - { - auto MB = MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); - } -} - -TEST_F(PGOCtxProfRWTest, DuplicateRoots) { - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - PGOCtxProfileWriter Writer(Out); - Writer.write(*createNode(1, 1, 1)); - Writer.write(*createNode(1, 1, 1)); - } - } - { - auto MB = MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); - } -} - -TEST_F(PGOCtxProfRWTest, DuplicateTargets) { - llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); - { - std::error_code EC; - raw_fd_stream Out(ProfileFile.path(), EC); - ASSERT_FALSE(EC); - { - auto *R = createNode(1, 1, 1); - auto *L1 = createNode(2, 1, 0); - auto *L2 = createNode(2, 1, 0, L1); - R->subContexts()[0] = L2; - PGOCtxProfileWriter Writer(Out); - Writer.write(*R); - } - } - { - auto MB = MemoryBuffer::getFile(ProfileFile.path()); - ASSERT_TRUE(!!MB); - ASSERT_NE(*MB, nullptr); - BitstreamCursor Cursor((*MB)->getBuffer()); - PGOCtxProfileReader Reader(Cursor); - auto Expected = Reader.loadContexts(); - EXPECT_FALSE(Expected); - consumeError(Expected.takeError()); - } -} -- GitLab From 9ae2177843f681c70ad89506155a2cb83eeebfd4 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Thu, 16 May 2024 02:41:48 +0800 Subject: [PATCH 401/578] [RISCV] Handle undef AVLs in RISCVInsertVSETVLI Before #91440 a VSETVLIInfo would have had an IMPLICIT_DEF defining instruction, but now we look up a VNInfo which doesn't exist, which triggers an assertion failure. Mark these undef AVLs as AVLIsIgnored. --- llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp | 20 +++++++++------- llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll | 24 +++++++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp index 1c815424bdfa..363007d7b68b 100644 --- a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp +++ b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp @@ -48,15 +48,13 @@ static cl::opt DisableInsertVSETVLPHIOpt( namespace { /// Given a virtual register \p Reg, return the corresponding VNInfo for it. -/// This should never return nullptr. +/// This will return nullptr if the virtual register is an implicit_def. static VNInfo *getVNInfoFromReg(Register Reg, const MachineInstr &MI, const LiveIntervals *LIS) { assert(Reg.isVirtual()); auto &LI = LIS->getInterval(Reg); SlotIndex SI = LIS->getSlotIndexes()->getInstructionIndex(MI); - VNInfo *VNI = LI.getVNInfoBefore(SI); - assert(VNI); - return VNI; + return LI.getVNInfoBefore(SI); } static unsigned getVLOpNum(const MachineInstr &MI) { @@ -894,8 +892,12 @@ static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI, "Can't handle X0, X0 vsetvli yet"); if (AVLReg == RISCV::X0) NewInfo.setAVLVLMAX(); - else - NewInfo.setAVLRegDef(getVNInfoFromReg(AVLReg, MI, LIS), AVLReg); + else if (VNInfo *VNI = getVNInfoFromReg(AVLReg, MI, LIS)) + NewInfo.setAVLRegDef(VNI, AVLReg); + else { + assert(MI.getOperand(1).isUndef()); + NewInfo.setAVLIgnored(); + } } NewInfo.setVTYPE(MI.getOperand(2).getImm()); @@ -966,9 +968,11 @@ static VSETVLIInfo computeInfoForInstr(const MachineInstr &MI, uint64_t TSFlags, } else InstrInfo.setAVLImm(Imm); + } else if (VNInfo *VNI = getVNInfoFromReg(VLOp.getReg(), MI, LIS)) { + InstrInfo.setAVLRegDef(VNI, VLOp.getReg()); } else { - InstrInfo.setAVLRegDef(getVNInfoFromReg(VLOp.getReg(), MI, LIS), - VLOp.getReg()); + assert(VLOp.isUndef()); + InstrInfo.setAVLIgnored(); } } else { assert(isScalarExtractInstr(MI)); diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll index 12bb4d27b0f9..da0c1cfb5009 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll @@ -699,3 +699,27 @@ declare @llvm.riscv.vmsgt.nxv2i32.i32.i64(, declare @llvm.riscv.vmor.nxv2i1.i64(, , i64) declare void @llvm.riscv.vse.mask.nxv2i32.i64(, ptr nocapture, , i64) declare void @llvm.riscv.vse.nxv2i32.i64(, ptr nocapture, i64) + +define @avl_undef1(, , ) { +; CHECK-LABEL: avl_undef1: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e32, m1, tu, ma +; CHECK-NEXT: vadd.vv v8, v9, v10 +; CHECK-NEXT: ret + %a = call @llvm.riscv.vadd.nxv2i32.nxv2i32( + %0, + %1, + %2, + i64 undef + ) + ret %a +} + +define i64 @avl_undef2() { +; CHECK-LABEL: avl_undef2: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, a0, e32, mf2, ta, ma +; CHECK-NEXT: ret + %1 = tail call i64 @llvm.riscv.vsetvli(i64 poison, i64 2, i64 7) + ret i64 %1 +} -- GitLab From 378c9e952a3d198873677fb2d2afb33695185b72 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Wed, 15 May 2024 18:51:56 +0000 Subject: [PATCH 402/578] [gn build] Port 2c54bf497f7d --- llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn | 2 -- llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn | 1 - 2 files changed, 3 deletions(-) diff --git a/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn index c6fa142b3766..9dbfe0f94c1d 100644 --- a/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn @@ -17,8 +17,6 @@ static_library("ProfileData") { "ItaniumManglingCanonicalizer.cpp", "MemProf.cpp", "MemProfReader.cpp", - "PGOCtxProfReader.cpp", - "PGOCtxProfWriter.cpp", "ProfileSummaryBuilder.cpp", "SampleProf.cpp", "SampleProfReader.cpp", diff --git a/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn index f45542519173..4919a8089209 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn @@ -14,7 +14,6 @@ unittest("ProfileDataTests") { "InstrProfTest.cpp", "ItaniumManglingCanonicalizerTest.cpp", "MemProfTest.cpp", - "PGOCtxProfReaderWriterTest.cpp", "SampleProfTest.cpp", "SymbolRemappingReaderTest.cpp", ] -- GitLab From d542eb7aa830e94490b943a3ea0937506fece15b Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Wed, 15 May 2024 23:12:02 +0400 Subject: [PATCH 403/578] [clang] Add tests for CWG issues regarding completeness of types (#92113) This patch covers the following Core issues: [CWG930](https://cplusplus.github.io/CWG/issues/930.html) "`alignof` with incomplete array type" [CWG1110](https://cplusplus.github.io/CWG/issues/1110.html) "Incomplete return type should be allowed in `decltype` operand" [CWG1340](https://cplusplus.github.io/CWG/issues/1340.html) "Complete type in member pointer expressions" [CWG1352](https://cplusplus.github.io/CWG/issues/1352.html) "Inconsistent class scope and completeness rules" [CWG1458](https://cplusplus.github.io/CWG/issues/1458.html) "Address of incomplete type vs `operator&()`" [CWG1824](https://cplusplus.github.io/CWG/issues/1824.html) "Completeness of return type vs point of instantiation" [CWG1832](https://cplusplus.github.io/CWG/issues/1832.html) "Casting to incomplete enumeration" [CWG2304](https://cplusplus.github.io/CWG/issues/2304.html) "Incomplete type vs overload resolution" [CWG2310](https://cplusplus.github.io/CWG/issues/2310.html) "Type completeness and derived-to-base pointer conversions" [CWG2430](https://cplusplus.github.io/CWG/issues/2430.html) "Completeness of return and parameter types of member functions" [CWG2512](https://cplusplus.github.io/CWG/issues/2512.html) "`typeid` and incomplete class types" [CWG2630](https://cplusplus.github.io/CWG/issues/2630.html) "Syntactic specification of class completeness" [CWG2718](https://cplusplus.github.io/CWG/issues/2718.html) "Type completeness for derived-to-base conversions" [CWG2857](https://cplusplus.github.io/CWG/issues/2857.html) "Argument-dependent lookup with incomplete class types" Current wording for CWG1110 came from [P0135R1](https://wg21.link/p0135R1) "Wording for guaranteed copy elision through simplified value categories". As a drive-by fix, I fixed incorrect status of CWG1815, test for which was added in #87933. CC @yronglin --- clang/test/CXX/drs/cwg11xx.cpp | 15 +++++++++++ clang/test/CXX/drs/cwg13xx.cpp | 31 ++++++++++++++++++++++ clang/test/CXX/drs/cwg14xx.cpp | 17 ++++++++++++ clang/test/CXX/drs/cwg18xx.cpp | 28 +++++++++++++++++++- clang/test/CXX/drs/cwg23xx.cpp | 48 ++++++++++++++++++++++++++++++++-- clang/test/CXX/drs/cwg24xx.cpp | 6 +++++ clang/test/CXX/drs/cwg25xx.cpp | 15 ++++++++--- clang/test/CXX/drs/cwg2630.cpp | 23 ++++++++++++++++ clang/test/CXX/drs/cwg26xx.cpp | 2 ++ clang/test/CXX/drs/cwg27xx.cpp | 14 +++++++--- clang/test/CXX/drs/cwg28xx.cpp | 28 +++++++++++++++++--- clang/test/CXX/drs/cwg9xx.cpp | 7 +++++ clang/www/cxx_dr_status.html | 46 ++++++++++++++++++++------------ 13 files changed, 250 insertions(+), 30 deletions(-) create mode 100644 clang/test/CXX/drs/cwg2630.cpp diff --git a/clang/test/CXX/drs/cwg11xx.cpp b/clang/test/CXX/drs/cwg11xx.cpp index 46a0e526be39..8d187041400a 100644 --- a/clang/test/CXX/drs/cwg11xx.cpp +++ b/clang/test/CXX/drs/cwg11xx.cpp @@ -4,6 +4,21 @@ // RUN: %clang_cc1 -std=c++17 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2a %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +namespace cwg1110 { // cwg1110: 3.1 +#if __cplusplus >= 201103L +template +T return_T(); + +struct A; + +template +struct B; + +decltype(return_T())* a; +decltype(return_T>())* b; +#endif +} // namespace cwg1110 + namespace cwg1111 { // cwg1111: 3.2 namespace example1 { template struct set; // #cwg1111-struct-set diff --git a/clang/test/CXX/drs/cwg13xx.cpp b/clang/test/CXX/drs/cwg13xx.cpp index a334b6d01acf..416de7c536b1 100644 --- a/clang/test/CXX/drs/cwg13xx.cpp +++ b/clang/test/CXX/drs/cwg13xx.cpp @@ -306,6 +306,18 @@ namespace cwg1330 { // cwg1330: 4 c++11 // cwg1334: sup 1719 +namespace cwg1340 { // cwg1340: 2.9 +struct A; +struct B; + +void f(B* a, A B::* p) { + (*a).*p; + // expected-warning@-1 {{expression result unused}} + a->*p; + // expected-warning@-1 {{expression result unused}} +} +} // namespace cwg1340 + namespace cwg1341 { // cwg1341: sup P0683R1 #if __cplusplus >= 202002L int a; @@ -451,6 +463,25 @@ static_assert(!__is_nothrow_constructible(D4, int), ""); #endif } // namespace cwg1350 +namespace cwg1352 { // cwg1352: 3.0 +struct A { +#if __cplusplus >= 201103L + int a = sizeof(A); +#endif + void f(int b = sizeof(A)); +}; + +template +struct B { +#if __cplusplus >= 201103L + int a = sizeof(B) + sizeof(T); +#endif + void f(int b = sizeof(B) + sizeof(T)); +}; + +template class B; +} // namespace cwg1352 + namespace cwg1358 { // cwg1358: 3.1 #if __cplusplus >= 201103L struct Lit { constexpr operator int() const { return 0; } }; diff --git a/clang/test/CXX/drs/cwg14xx.cpp b/clang/test/CXX/drs/cwg14xx.cpp index 9ff9a68dc13c..f01d96ad47f3 100644 --- a/clang/test/CXX/drs/cwg14xx.cpp +++ b/clang/test/CXX/drs/cwg14xx.cpp @@ -86,6 +86,23 @@ struct A { }; } +namespace cwg1458 { // cwg1458: 3.1 +#if __cplusplus >= 201103L +struct A; + +void f() { + constexpr A* a = nullptr; + constexpr int p = &*a; + // expected-error@-1 {{cannot initialize a variable of type 'const int' with an rvalue of type 'A *'}} + constexpr A *p2 = &*a; +} + +struct A { + int operator&(); +}; +#endif +} // namespace cwg1458 + namespace cwg1460 { // cwg1460: 3.5 #if __cplusplus >= 201103L namespace DRExample { diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp index 9eb749153e57..89adc2838490 100644 --- a/clang/test/CXX/drs/cwg18xx.cpp +++ b/clang/test/CXX/drs/cwg18xx.cpp @@ -206,7 +206,7 @@ namespace cwg1814 { // cwg1814: yes #endif } -namespace cwg1815 { // cwg1815: yes +namespace cwg1815 { // cwg1815: 19 #if __cplusplus >= 201402L struct A { int &&r = 0; }; A a = {}; @@ -303,6 +303,32 @@ namespace cwg1822 { // cwg1822: yes #endif } +namespace cwg1824 { // cwg1824: 2.7 +template +struct A { + T t; +}; + +struct S { + A f() { return A(); } +}; +} // namespace cwg1824 + +namespace cwg1832 { // cwg1832: 3.0 +enum E { // #cwg1832-E + a = static_cast(static_cast(0)) + // expected-error@-1 {{'E' is an incomplete type}} + // expected-note@#cwg1832-E {{definition of 'cwg1832::E' is not complete until the closing '}'}} +}; + +#if __cplusplus >= 201103L +enum E2: decltype(static_cast(0), 0) {}; +// expected-error@-1 {{unknown type name 'E2'}} +enum class E3: decltype(static_cast(0), 0) {}; +// expected-error@-1 {{unknown type name 'E3'}} +#endif +} // namespace cwg1832 + namespace cwg1837 { // cwg1837: 3.3 #if __cplusplus >= 201103L template diff --git a/clang/test/CXX/drs/cwg23xx.cpp b/clang/test/CXX/drs/cwg23xx.cpp index db5b7c3cd3c9..ae5ec3b878f5 100644 --- a/clang/test/CXX/drs/cwg23xx.cpp +++ b/clang/test/CXX/drs/cwg23xx.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++11 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-14,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s // RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s // RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s @@ -47,6 +47,50 @@ void g() { } // namespace cwg2303 #endif +namespace cwg2304 { // cwg2304: 2.8 +template void foo(T, int); +template void foo(T&, ...); +struct Q; // #cwg2304-Q +void fn1(Q &data_vectors) { + foo(data_vectors, 0); + // expected-error@-1 {{argument type 'cwg2304::Q' is incomplete}} + // expected-note@#cwg2304-Q {{forward declaration of 'cwg2304::Q'}} +} +} // namespace cwg2304 + +namespace cwg2310 { // cwg2310: partial +#if __cplusplus >= 201103L +template +struct check_derived_from { + static A a; + // FIXME: all 3 examples should be rejected in all language modes. + // FIXME: we should test this in 98 mode. + // FIXME: we accept this when MSVC triple is used + static constexpr B *p = &a; +#if !defined(_WIN32) || defined(__MINGW32__) + // cxx11-14-error@-2 {{cannot initialize a variable of type 'cwg2310::X *const' with an rvalue of type 'cwg2310::Z *'}} + // cxx11-14-note@#cwg2310-X {{in instantiation of template class 'cwg2310::check_derived_from' requested here}} + // cxx11-14-error@-4 {{cannot initialize a variable of type 'cwg2310::Y *const' with an rvalue of type 'cwg2310::Z *'}} + // cxx11-14-note@#cwg2310-Y {{in instantiation of template class 'cwg2310::check_derived_from' requested here}} +#endif +}; + +struct W {}; +struct X {}; +struct Y {}; +struct Z : W, + X, check_derived_from, // #cwg2310-X + check_derived_from, Y // #cwg2310-Y +{ + // FIXME: It was properly rejected before, but we're crashing since Clang 11 in C++11 and C++14 modes. + // See https://github.com/llvm/llvm-project/issues/59920 +#if __cplusplus >= 201703L + check_derived_from cdf; +#endif +}; +#endif +} // namespace cwg2310 + // cwg2331: na // cwg2335 is in cwg2335.cxx diff --git a/clang/test/CXX/drs/cwg24xx.cpp b/clang/test/CXX/drs/cwg24xx.cpp index 9f876cd87083..75e1a614765c 100644 --- a/clang/test/CXX/drs/cwg24xx.cpp +++ b/clang/test/CXX/drs/cwg24xx.cpp @@ -45,6 +45,12 @@ void fallthrough(int n) { #endif } +namespace cwg2430 { // cwg2430: 2.7 +struct S { + S f(S s) { return s; } +}; +} // namespace cwg2430 + namespace cwg2450 { // cwg2450: 18 #if __cplusplus >= 202302L struct S {int a;}; diff --git a/clang/test/CXX/drs/cwg25xx.cpp b/clang/test/CXX/drs/cwg25xx.cpp index 8bca58f44944..0934f0cc19c6 100644 --- a/clang/test/CXX/drs/cwg25xx.cpp +++ b/clang/test/CXX/drs/cwg25xx.cpp @@ -6,12 +6,21 @@ // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors -#if __cplusplus == 199711L -// expected-no-diagnostics -#endif +namespace std { +struct type_info{}; +} // namespace std // cwg2504 is in cwg2504.cpp +namespace cwg2512 { // cwg2512: 2.7 +struct A; // #cwg2512-A +void foo(A* p) { + typeid(*p); + // expected-error@-1 {{'typeid' of incomplete type 'A'}} + // expected-note@#cwg2512-A {{forward declaration of 'cwg2512::A'}} +} +} // namespace cwg2512 + namespace cwg2516 { // cwg2516: 3.0 // NB: reusing 1482 test #if __cplusplus >= 201103L diff --git a/clang/test/CXX/drs/cwg2630.cpp b/clang/test/CXX/drs/cwg2630.cpp new file mode 100644 index 000000000000..0f50dc4f7458 --- /dev/null +++ b/clang/test/CXX/drs/cwg2630.cpp @@ -0,0 +1,23 @@ +// RUN: split-file --leading-lines %s %t +// RUN: %clang_cc1 -std=c++20 -verify -emit-module-interface %t/module.cppm -o %t/module.pcm +// RUN: %clang_cc1 -std=c++20 -verify -fmodule-file=A=%t/module.pcm %t/main.cpp +// RUN: %clang_cc1 -std=c++23 -verify -emit-module-interface %t/module.cppm -o %t/module.pcm +// RUN: %clang_cc1 -std=c++23 -verify -fmodule-file=A=%t/module.pcm %t/main.cpp +// RUN: %clang_cc1 -std=c++2c -verify -emit-module-interface %t/module.cppm -o %t/module.pcm +// RUN: %clang_cc1 -std=c++2c -verify -fmodule-file=A=%t/module.pcm %t/main.cpp + +//--- module.cppm +// expected-no-diagnostics +export module A; + +namespace cwg2630 { +export class X {}; +} // namespace cwg2630 + +//--- main.cpp +// expected-no-diagnostics +import A; + +namespace cwg2630 { // cwg2630: 9 +X x; +} // namespace cwg2630 diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp index f7a05b9827a2..d3c5b5bb7b6b 100644 --- a/clang/test/CXX/drs/cwg26xx.cpp +++ b/clang/test/CXX/drs/cwg26xx.cpp @@ -49,6 +49,8 @@ void f() { #endif } +// cwg2630 is in cwg2630.cpp + namespace cwg2631 { // cwg2631: 16 #if __cplusplus >= 202002L constexpr int g(); diff --git a/clang/test/CXX/drs/cwg27xx.cpp b/clang/test/CXX/drs/cwg27xx.cpp index 0434427d6c92..53ddd566b7db 100644 --- a/clang/test/CXX/drs/cwg27xx.cpp +++ b/clang/test/CXX/drs/cwg27xx.cpp @@ -6,9 +6,17 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -verify=expected,since-cxx23 %s // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++2c -verify=expected,since-cxx23,since-cxx26 %s -#if __cplusplus <= 202002L -// expected-no-diagnostics -#endif +namespace cwg2718 { // cwg2718: 2.7 +struct B {}; +struct D; + +void f(B b) { + static_cast(b); + // expected-error@-1 {{non-const lvalue reference to type 'D' cannot bind to a value of unrelated type 'B'}} +} + +struct D : B {}; +} // namespace cwg2718 namespace cwg2759 { // cwg2759: 19 #if __cplusplus >= 201103L diff --git a/clang/test/CXX/drs/cwg28xx.cpp b/clang/test/CXX/drs/cwg28xx.cpp index be35d366bdd6..696cd1b9c84e 100644 --- a/clang/test/CXX/drs/cwg28xx.cpp +++ b/clang/test/CXX/drs/cwg28xx.cpp @@ -6,10 +6,6 @@ // RUN: %clang_cc1 -std=c++23 -verify=expected,since-cxx20,since-cxx23 %s // RUN: %clang_cc1 -std=c++2c -verify=expected,since-cxx20,since-cxx23,since-cxx26 %s -#if __cplusplus < 202002L -// expected-no-diagnostics -#endif - namespace cwg2819 { // cwg2819: 19 tentatively ready 2023-12-01 #if __cpp_constexpr >= 202306L constexpr void* p = nullptr; @@ -67,6 +63,30 @@ void B::g() requires true; } // namespace cwg2847 +namespace cwg2857 { // cwg2857: no +struct A {}; +template +struct D; +namespace N { + struct B {}; + void adl_only(A*, D*); // #cwg2857-adl_only +} + +void f(A* a, D* d) { + adl_only(a, d); + // expected-error@-1 {{use of undeclared identifier 'adl_only'; did you mean 'N::adl_only'?}} + // expected-note@#cwg2857-adl_only {{'N::adl_only' declared here}} +} + +#if __cplusplus >= 201103L +template +struct D : N::B { + // FIXME: ADL shouldn't associate it's base B and N since D is not complete here + decltype(adl_only((A*) nullptr, (D*) nullptr)) f; +}; +#endif +} // namespace cwg2857 + namespace cwg2858 { // cwg2858: 19 tentatively ready 2024-04-05 #if __cplusplus > 202302L diff --git a/clang/test/CXX/drs/cwg9xx.cpp b/clang/test/CXX/drs/cwg9xx.cpp index 8ecb149c355f..2700b0f5662a 100644 --- a/clang/test/CXX/drs/cwg9xx.cpp +++ b/clang/test/CXX/drs/cwg9xx.cpp @@ -14,6 +14,13 @@ namespace std { }; } +namespace cwg930 { // cwg930: 2.7 +#if __cplusplus >= 201103L +static_assert(alignof(int[]) == alignof(int), ""); +static_assert(alignof(int[][2]) == alignof(int[2]), ""); +#endif +} // namespace cwg930 + namespace cwg948 { // cwg948: 3.7 #if __cplusplus >= 201103L class A { diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 92fdcf5556ed..abf5d4ae4676 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -5388,7 +5388,7 @@ and POD class 930 CD2 alignof with incomplete array type - Unknown + Clang 2.7 931 @@ -6468,7 +6468,7 @@ and POD class 1110 NAD Incomplete return type should be allowed in decltype operand - Unknown + Clang 3.1 1111 @@ -7848,7 +7848,7 @@ and POD class 1340 CD3 Complete type in member pointer expressions - Unknown + Clang 2.9 1341 @@ -7920,7 +7920,7 @@ and POD class 1352 CD3 Inconsistent class scope and completeness rules - Unknown + Clang 3.0 1353 @@ -8556,7 +8556,7 @@ and POD class 1458 CD3 Address of incomplete type vs operator&() - Unknown + Clang 3.1 1459 @@ -10752,7 +10752,7 @@ and POD class 1824 CD4 Completeness of return type vs point of instantiation - Unknown + Clang 2.7 1825 @@ -10800,7 +10800,7 @@ and POD class 1832 CD4 Casting to incomplete enumeration - Unknown + Clang 3.0 1833 @@ -13632,7 +13632,7 @@ and POD class 2304 NAD Incomplete type vs overload resolution - Unknown + Clang 2.8 2305 @@ -13668,7 +13668,7 @@ and POD class 2310 CD5 Type completeness and derived-to-base pointer conversions - Unknown + Partial 2311 @@ -14388,7 +14388,7 @@ and POD class 2430 C++20 Completeness of return and parameter types of member functions - Unknown + Clang 2.7 2431 @@ -14880,7 +14880,7 @@ and POD class 2512 NAD typeid and incomplete class types - Unknown + Clang 2.7 2513 @@ -15588,7 +15588,7 @@ and POD class 2630 C++23 Syntactic specification of class completeness - Unknown + Clang 9 2631 @@ -16116,7 +16116,7 @@ and POD class 2718 DRWP Type completeness for derived-to-base conversions - Unknown + Clang 2.7 2719 @@ -16951,7 +16951,7 @@ objects 2857 DR Argument-dependent lookup with incomplete class types - Unknown + No 2858 @@ -16985,7 +16985,7 @@ objects 2863 - tentatively ready + drafting Unclear synchronization requirements for object lifetime rules Not resolved @@ -17021,13 +17021,13 @@ objects 2869 - open + review this in local classes Not resolved 2870 - open + review Combining absent encoding-prefixes Not resolved @@ -17138,6 +17138,18 @@ objects open Missing cases for reference and array types for argument-dependent lookup Not resolved + + + 2889 + open + Requiring an accessible destructor for destroying operator delete + Not resolved + + + 2890 + open + Defining members of local classes + Not resolved -- GitLab From 64b3cdc0220174c1af236a42b227a5226f0f12c5 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 15 May 2024 14:13:50 -0500 Subject: [PATCH 404/578] [libc] Fix GPU handling for unsupported backends (#92271) Summary: If the user does not have the selected backend enabled, we should still be able to build the LLVM-IR an ddistribute it. This patch makes logic to suppress tests if the backend can't build it, as well as removing a flag for the building that's only present int he NVPTX backend. --- libc/cmake/modules/LLVMLibCCompileOptionRules.cmake | 1 - libc/cmake/modules/prepare_libc_gpu_build.cmake | 10 +++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake index 5b3a10d55fed..3bf429381d4a 100644 --- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake +++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake @@ -101,7 +101,6 @@ function(_get_common_compile_options output_var flags) if(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) list(APPEND compile_options "-Wno-unknown-cuda-version") - list(APPEND compile_options "SHELL:-mllvm -nvptx-emit-init-fini-kernel=false") list(APPEND compile_options "--cuda-feature=+ptx63") if(LIBC_CUDA_ROOT) list(APPEND compile_options "--cuda-path=${LIBC_CUDA_ROOT}") diff --git a/libc/cmake/modules/prepare_libc_gpu_build.cmake b/libc/cmake/modules/prepare_libc_gpu_build.cmake index 20aca16990fc..88538caaa3bc 100644 --- a/libc/cmake/modules/prepare_libc_gpu_build.cmake +++ b/libc/cmake/modules/prepare_libc_gpu_build.cmake @@ -76,7 +76,15 @@ elseif(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) endif() set(gpu_test_architecture "") -if(LIBC_GPU_TEST_ARCHITECTURE) +if(DEFINED LLVM_TARGETS_TO_BUILD AND LIBC_TARGET_ARCHITECTURE_IS_AMDGPU + AND NOT "AMDGPU" IN_LIST LLVM_TARGETS_TO_BUILD) + set(LIBC_GPU_TESTS_DISABLED TRUE) + message(STATUS "AMDGPU backend is not available, tests will not be built") +elseif(DEFINED LLVM_TARGETS_TO_BUILD AND LIBC_TARGET_ARCHITECTURE_IS_AMDGPU + AND NOT "NVPTX" IN_LIST LLVM_TARGETS_TO_BUILD) + set(LIBC_GPU_TESTS_DISABLED TRUE) + message(STATUS "NVPTX backend is not available, tests will not be built") +elseif(LIBC_GPU_TEST_ARCHITECTURE) set(LIBC_GPU_TESTS_DISABLED FALSE) set(gpu_test_architecture ${LIBC_GPU_TEST_ARCHITECTURE}) message(STATUS "Using user-specified GPU architecture for testing: " -- GitLab From 4ab2ac22d0a481460536f673377b644702cb3372 Mon Sep 17 00:00:00 2001 From: Patrick O'Neill Date: Wed, 15 May 2024 12:39:28 -0700 Subject: [PATCH 405/578] [DAGCombiner] Mark vectors as not AllAddOne/AllSubOne on type mismatch (#92195) Fixes #92193. --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 7 +++++-- llvm/test/CodeGen/RISCV/pr92193.ll | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/RISCV/pr92193.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index a044b6dc4838..2b181cd3ab1d 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -12142,8 +12142,11 @@ SDValue DAGCombiner::foldVSelectOfConstants(SDNode *N) { SDValue N2Elt = N2.getOperand(i); if (N1Elt.isUndef() || N2Elt.isUndef()) continue; - if (N1Elt.getValueType() != N2Elt.getValueType()) - continue; + if (N1Elt.getValueType() != N2Elt.getValueType()) { + AllAddOne = false; + AllSubOne = false; + break; + } const APInt &C1 = N1Elt->getAsAPIntVal(); const APInt &C2 = N2Elt->getAsAPIntVal(); diff --git a/llvm/test/CodeGen/RISCV/pr92193.ll b/llvm/test/CodeGen/RISCV/pr92193.ll new file mode 100644 index 000000000000..8c8398c4b45f --- /dev/null +++ b/llvm/test/CodeGen/RISCV/pr92193.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=riscv64-unknown-linux-gnu < %s | FileCheck %s +; RUN: llc -mtriple=riscv32-unknown-linux-gnu < %s | FileCheck %s + +; Dag-combine used to improperly combine a vector vselect of 0 and 2 into +; 2 + condition(0/1) because one of the two args was transformed from an i32->i64. + +define i16 @foo() { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: li a0, 0 +; CHECK-NEXT: ret +entry: + %insert.0 = insertelement <4 x i16> zeroinitializer, i16 2, i64 0 + %all.two = shufflevector <4 x i16> %insert.0, <4 x i16> zeroinitializer, <4 x i32> zeroinitializer + %sel.0 = select <4 x i1> , <4 x i16> zeroinitializer, <4 x i16> %all.two + %mul.0 = call i16 @llvm.vector.reduce.mul.v4i16(<4 x i16> %sel.0) + ret i16 %mul.0 +} + +declare i16 @llvm.vector.reduce.mul.v4i32(<4 x i16>) -- GitLab From fc8775e2142c6bd7876831c27c3fbef0d64860bc Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Wed, 15 May 2024 12:45:50 -0700 Subject: [PATCH 406/578] "Reapply "[ctx_profile] Profile reader and writer" (#92199)" This reverts commit 2c54bf497f7d7aecd24f4b849ee08e37a3519611. Fixed gcc-7 issue. --- .../llvm/ProfileData/PGOCtxProfReader.h | 92 +++++++ .../llvm/ProfileData/PGOCtxProfWriter.h | 91 +++++++ llvm/lib/ProfileData/CMakeLists.txt | 3 + llvm/lib/ProfileData/PGOCtxProfReader.cpp | 173 ++++++++++++ llvm/lib/ProfileData/PGOCtxProfWriter.cpp | 49 ++++ llvm/unittests/ProfileData/CMakeLists.txt | 1 + .../PGOCtxProfReaderWriterTest.cpp | 255 ++++++++++++++++++ 7 files changed, 664 insertions(+) create mode 100644 llvm/include/llvm/ProfileData/PGOCtxProfReader.h create mode 100644 llvm/include/llvm/ProfileData/PGOCtxProfWriter.h create mode 100644 llvm/lib/ProfileData/PGOCtxProfReader.cpp create mode 100644 llvm/lib/ProfileData/PGOCtxProfWriter.cpp create mode 100644 llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp diff --git a/llvm/include/llvm/ProfileData/PGOCtxProfReader.h b/llvm/include/llvm/ProfileData/PGOCtxProfReader.h new file mode 100644 index 000000000000..a19b3f51d642 --- /dev/null +++ b/llvm/include/llvm/ProfileData/PGOCtxProfReader.h @@ -0,0 +1,92 @@ +//===--- PGOCtxProfReader.h - Contextual profile reader ---------*- 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 +/// +/// Reader for contextual iFDO profile, which comes in bitstream format. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H +#define LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Bitstream/BitstreamReader.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Support/Error.h" +#include +#include + +namespace llvm { +/// The loaded contextual profile, suitable for mutation during IPO passes. We +/// generally expect a fraction of counters and of callsites to be populated. +/// We continue to model counters as vectors, but callsites are modeled as a map +/// of a map. The expectation is that, typically, there is a small number of +/// indirect targets (usually, 1 for direct calls); but potentially a large +/// number of callsites, and, as inlining progresses, the callsite count of a +/// caller will grow. +class PGOContextualProfile final { +public: + using CallTargetMapTy = std::map; + using CallsiteMapTy = DenseMap; + +private: + friend class PGOCtxProfileReader; + GlobalValue::GUID GUID = 0; + SmallVector Counters; + CallsiteMapTy Callsites; + + PGOContextualProfile(GlobalValue::GUID G, + SmallVectorImpl &&Counters) + : GUID(G), Counters(std::move(Counters)) {} + + Expected + getOrEmplace(uint32_t Index, GlobalValue::GUID G, + SmallVectorImpl &&Counters); + +public: + PGOContextualProfile(const PGOContextualProfile &) = delete; + PGOContextualProfile &operator=(const PGOContextualProfile &) = delete; + PGOContextualProfile(PGOContextualProfile &&) = default; + PGOContextualProfile &operator=(PGOContextualProfile &&) = default; + + GlobalValue::GUID guid() const { return GUID; } + const SmallVectorImpl &counters() const { return Counters; } + const CallsiteMapTy &callsites() const { return Callsites; } + CallsiteMapTy &callsites() { return Callsites; } + + bool hasCallsite(uint32_t I) const { + return Callsites.find(I) != Callsites.end(); + } + + const CallTargetMapTy &callsite(uint32_t I) const { + assert(hasCallsite(I) && "Callsite not found"); + return Callsites.find(I)->second; + } + void getContainedGuids(DenseSet &Guids) const; +}; + +class PGOCtxProfileReader final { + BitstreamCursor &Cursor; + Expected advance(); + Error readMetadata(); + Error wrongValue(const Twine &); + Error unsupported(const Twine &); + + Expected, PGOContextualProfile>> + readContext(bool ExpectIndex); + bool canReadContext(); + +public: + PGOCtxProfileReader(BitstreamCursor &Cursor) : Cursor(Cursor) {} + + Expected> loadContexts(); +}; +} // namespace llvm +#endif diff --git a/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h b/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h new file mode 100644 index 000000000000..15578c51a495 --- /dev/null +++ b/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h @@ -0,0 +1,91 @@ +//===- PGOCtxProfWriter.h - Contextual Profile Writer -----------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares a utility for writing a contextual profile to bitstream. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ +#define LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ + +#include "llvm/Bitstream/BitstreamWriter.h" +#include "llvm/ProfileData/CtxInstrContextNode.h" + +namespace llvm { +enum PGOCtxProfileRecords { Invalid = 0, Version, Guid, CalleeIndex, Counters }; + +enum PGOCtxProfileBlockIDs { + ProfileMetadataBlockID = 100, + ContextNodeBlockID = ProfileMetadataBlockID + 1 +}; + +/// Write one or more ContextNodes to the provided raw_fd_stream. +/// The caller must destroy the PGOCtxProfileWriter object before closing the +/// stream. +/// The design allows serializing a bunch of contexts embedded in some other +/// file. The overall format is: +/// +/// [... other data written to the stream...] +/// SubBlock(ProfileMetadataBlockID) +/// Version +/// SubBlock(ContextNodeBlockID) +/// [RECORDS] +/// SubBlock(ContextNodeBlockID) +/// [RECORDS] +/// [... more SubBlocks] +/// EndBlock +/// EndBlock +/// +/// The "RECORDS" are bitsream records. The IDs are in CtxProfileCodes (except) +/// for Version, which is just for metadata). All contexts will have Guid and +/// Counters, and all but the roots have CalleeIndex. The order in which the +/// records appear does not matter, but they must precede any subcontexts, +/// because that helps keep the reader code simpler. +/// +/// Subblock containment captures the context->subcontext relationship. The +/// "next()" relationship in the raw profile, between call targets of indirect +/// calls, are just modeled as peer subblocks where the callee index is the +/// same. +/// +/// Versioning: the writer may produce additional records not known by the +/// reader. The version number indicates a more structural change. +/// The current version, in particular, is set up to expect optional extensions +/// like value profiling - which would appear as additional records. For +/// example, value profiling would produce a new record with a new record ID, +/// containing the profiled values (much like the counters) +class PGOCtxProfileWriter final { + SmallVector Buff; + BitstreamWriter Writer; + + void writeCounters(const ctx_profile::ContextNode &Node); + void writeImpl(std::optional CallerIndex, + const ctx_profile::ContextNode &Node); + +public: + PGOCtxProfileWriter(raw_fd_stream &Out, + std::optional VersionOverride = std::nullopt) + : Writer(Buff, &Out, 0) { + Writer.EnterSubblock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID, + CodeLen); + const auto Version = VersionOverride ? *VersionOverride : CurrentVersion; + Writer.EmitRecord(PGOCtxProfileRecords::Version, + SmallVector({Version})); + } + + ~PGOCtxProfileWriter() { Writer.ExitBlock(); } + + void write(const ctx_profile::ContextNode &); + + // constants used in writing which a reader may find useful. + static constexpr unsigned CodeLen = 2; + static constexpr uint32_t CurrentVersion = 1; + static constexpr unsigned VBREncodingBits = 6; +}; + +} // namespace llvm +#endif diff --git a/llvm/lib/ProfileData/CMakeLists.txt b/llvm/lib/ProfileData/CMakeLists.txt index 408f9ff01ec8..4fa1b76f0a06 100644 --- a/llvm/lib/ProfileData/CMakeLists.txt +++ b/llvm/lib/ProfileData/CMakeLists.txt @@ -7,6 +7,8 @@ add_llvm_component_library(LLVMProfileData ItaniumManglingCanonicalizer.cpp MemProf.cpp MemProfReader.cpp + PGOCtxProfReader.cpp + PGOCtxProfWriter.cpp ProfileSummaryBuilder.cpp SampleProf.cpp SampleProfReader.cpp @@ -20,6 +22,7 @@ add_llvm_component_library(LLVMProfileData intrinsics_gen LINK_COMPONENTS + BitstreamReader Core Object Support diff --git a/llvm/lib/ProfileData/PGOCtxProfReader.cpp b/llvm/lib/ProfileData/PGOCtxProfReader.cpp new file mode 100644 index 000000000000..1b42d8c765f2 --- /dev/null +++ b/llvm/lib/ProfileData/PGOCtxProfReader.cpp @@ -0,0 +1,173 @@ +//===- PGOCtxProfReader.cpp - Contextual Instrumentation profile reader ---===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Read a contextual profile into a datastructure suitable for maintenance +// throughout IPO +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/PGOCtxProfReader.h" +#include "llvm/Bitstream/BitCodeEnums.h" +#include "llvm/Bitstream/BitstreamReader.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" + +using namespace llvm; + +// FIXME(#92054) - these Error handling macros are (re-)invented in a few +// places. +#define EXPECT_OR_RET(LHS, RHS) \ + auto LHS = RHS; \ + if (!LHS) \ + return LHS.takeError(); + +#define RET_ON_ERR(EXPR) \ + if (auto Err = (EXPR)) \ + return Err; + +Expected +PGOContextualProfile::getOrEmplace(uint32_t Index, GlobalValue::GUID G, + SmallVectorImpl &&Counters) { + auto [Iter, Inserted] = Callsites[Index].insert( + {G, PGOContextualProfile(G, std::move(Counters))}); + if (!Inserted) + return make_error(instrprof_error::invalid_prof, + "Duplicate GUID for same callsite."); + return Iter->second; +} + +void PGOContextualProfile::getContainedGuids( + DenseSet &Guids) const { + Guids.insert(GUID); + for (const auto &[_, Callsite] : Callsites) + for (const auto &[_, Callee] : Callsite) + Callee.getContainedGuids(Guids); +} + +Expected PGOCtxProfileReader::advance() { + return Cursor.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); +} + +Error PGOCtxProfileReader::wrongValue(const Twine &Msg) { + return make_error(instrprof_error::invalid_prof, Msg); +} + +Error PGOCtxProfileReader::unsupported(const Twine &Msg) { + return make_error(instrprof_error::unsupported_version, Msg); +} + +bool PGOCtxProfileReader::canReadContext() { + auto Blk = advance(); + if (!Blk) { + consumeError(Blk.takeError()); + return false; + } + return Blk->Kind == BitstreamEntry::SubBlock && + Blk->ID == PGOCtxProfileBlockIDs::ContextNodeBlockID; +} + +Expected, PGOContextualProfile>> +PGOCtxProfileReader::readContext(bool ExpectIndex) { + RET_ON_ERR(Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ContextNodeBlockID)); + + std::optional Guid; + std::optional> Counters; + std::optional CallsiteIndex; + + SmallVector RecordValues; + + // We don't prescribe the order in which the records come in, and we are ok + // if other unsupported records appear. We seek in the current subblock until + // we get all we know. + auto GotAllWeNeed = [&]() { + return Guid.has_value() && Counters.has_value() && + (!ExpectIndex || CallsiteIndex.has_value()); + }; + while (!GotAllWeNeed()) { + RecordValues.clear(); + EXPECT_OR_RET(Entry, advance()); + if (Entry->Kind != BitstreamEntry::Record) + return wrongValue( + "Expected records before encountering more subcontexts"); + EXPECT_OR_RET(ReadRecord, + Cursor.readRecord(bitc::UNABBREV_RECORD, RecordValues)); + switch (*ReadRecord) { + case PGOCtxProfileRecords::Guid: + if (RecordValues.size() != 1) + return wrongValue("The GUID record should have exactly one value"); + Guid = RecordValues[0]; + break; + case PGOCtxProfileRecords::Counters: + Counters = std::move(RecordValues); + if (Counters->empty()) + return wrongValue("Empty counters. At least the entry counter (one " + "value) was expected"); + break; + case PGOCtxProfileRecords::CalleeIndex: + if (!ExpectIndex) + return wrongValue("The root context should not have a callee index"); + if (RecordValues.size() != 1) + return wrongValue("The callee index should have exactly one value"); + CallsiteIndex = RecordValues[0]; + break; + default: + // OK if we see records we do not understand, like records (profile + // components) introduced later. + break; + } + } + + PGOContextualProfile Ret(*Guid, std::move(*Counters)); + + while (canReadContext()) { + EXPECT_OR_RET(SC, readContext(true)); + auto &Targets = Ret.callsites()[*SC->first]; + auto [_, Inserted] = + Targets.insert({SC->second.guid(), std::move(SC->second)}); + if (!Inserted) + return wrongValue( + "Unexpected duplicate target (callee) at the same callsite."); + } + return std::make_pair(CallsiteIndex, std::move(Ret)); +} + +Error PGOCtxProfileReader::readMetadata() { + EXPECT_OR_RET(Blk, advance()); + if (Blk->Kind != BitstreamEntry::SubBlock) + return unsupported("Expected Version record"); + RET_ON_ERR( + Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID)); + EXPECT_OR_RET(MData, advance()); + if (MData->Kind != BitstreamEntry::Record) + return unsupported("Expected Version record"); + + SmallVector Ver; + EXPECT_OR_RET(Code, Cursor.readRecord(bitc::UNABBREV_RECORD, Ver)); + if (*Code != PGOCtxProfileRecords::Version) + return unsupported("Expected Version record"); + if (Ver.size() != 1 || Ver[0] > PGOCtxProfileWriter::CurrentVersion) + return unsupported("Version " + Twine(*Code) + + " is higher than supported version " + + Twine(PGOCtxProfileWriter::CurrentVersion)); + return Error::success(); +} + +Expected> +PGOCtxProfileReader::loadContexts() { + std::map Ret; + RET_ON_ERR(readMetadata()); + while (canReadContext()) { + EXPECT_OR_RET(E, readContext(false)); + auto Key = E->second.guid(); + if (!Ret.insert({Key, std::move(E->second)}).second) + return wrongValue("Duplicate roots"); + } + return std::move(Ret); +} diff --git a/llvm/lib/ProfileData/PGOCtxProfWriter.cpp b/llvm/lib/ProfileData/PGOCtxProfWriter.cpp new file mode 100644 index 000000000000..508179756446 --- /dev/null +++ b/llvm/lib/ProfileData/PGOCtxProfWriter.cpp @@ -0,0 +1,49 @@ +//===- PGOCtxProfWriter.cpp - Contextual Instrumentation profile writer ---===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Write a contextual profile to bitstream. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Bitstream/BitCodeEnums.h" + +using namespace llvm; +using namespace llvm::ctx_profile; + +void PGOCtxProfileWriter::writeCounters(const ContextNode &Node) { + Writer.EmitCode(bitc::UNABBREV_RECORD); + Writer.EmitVBR(PGOCtxProfileRecords::Counters, VBREncodingBits); + Writer.EmitVBR(Node.counters_size(), VBREncodingBits); + for (uint32_t I = 0U; I < Node.counters_size(); ++I) + Writer.EmitVBR64(Node.counters()[I], VBREncodingBits); +} + +// recursively write all the subcontexts. We do need to traverse depth first to +// model the context->subcontext implicitly, and since this captures call +// stacks, we don't really need to be worried about stack overflow and we can +// keep the implementation simple. +void PGOCtxProfileWriter::writeImpl(std::optional CallerIndex, + const ContextNode &Node) { + Writer.EnterSubblock(PGOCtxProfileBlockIDs::ContextNodeBlockID, CodeLen); + Writer.EmitRecord(PGOCtxProfileRecords::Guid, + SmallVector{Node.guid()}); + if (CallerIndex) + Writer.EmitRecord(PGOCtxProfileRecords::CalleeIndex, + SmallVector{*CallerIndex}); + writeCounters(Node); + for (uint32_t I = 0U; I < Node.callsites_size(); ++I) + for (const auto *Subcontext = Node.subContexts()[I]; Subcontext; + Subcontext = Subcontext->next()) + writeImpl(I, *Subcontext); + Writer.ExitBlock(); +} + +void PGOCtxProfileWriter::write(const ContextNode &RootNode) { + writeImpl(std::nullopt, RootNode); +} diff --git a/llvm/unittests/ProfileData/CMakeLists.txt b/llvm/unittests/ProfileData/CMakeLists.txt index ce3a0a45ccf1..c92642ded828 100644 --- a/llvm/unittests/ProfileData/CMakeLists.txt +++ b/llvm/unittests/ProfileData/CMakeLists.txt @@ -13,6 +13,7 @@ add_llvm_unittest(ProfileDataTests InstrProfTest.cpp ItaniumManglingCanonicalizerTest.cpp MemProfTest.cpp + PGOCtxProfReaderWriterTest.cpp SampleProfTest.cpp SymbolRemappingReaderTest.cpp ) diff --git a/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp b/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp new file mode 100644 index 000000000000..d2cdbb28e2fc --- /dev/null +++ b/llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp @@ -0,0 +1,255 @@ +//===-------------- PGOCtxProfReadWriteTest.cpp ---------------------------===// +// +// 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 "llvm/Bitstream/BitstreamReader.h" +#include "llvm/ProfileData/CtxInstrContextNode.h" +#include "llvm/ProfileData/PGOCtxProfReader.h" +#include "llvm/ProfileData/PGOCtxProfWriter.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Testing/Support/SupportHelpers.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::ctx_profile; + +class PGOCtxProfRWTest : public ::testing::Test { + std::vector> Nodes; + std::map Roots; + +public: + ContextNode *createNode(GUID Guid, uint32_t NrCounters, uint32_t NrCallsites, + ContextNode *Next = nullptr) { + auto AllocSize = ContextNode::getAllocSize(NrCounters, NrCallsites); + auto *Mem = Nodes.emplace_back(std::make_unique(AllocSize)).get(); + std::memset(Mem, 0, AllocSize); + auto *Ret = new (Mem) ContextNode(Guid, NrCounters, NrCallsites, Next); + return Ret; + } + + void SetUp() override { + // Root (guid 1) has 2 callsites, one used for an indirect call to either + // guid 2 or 4. + // guid 2 calls guid 5 + // guid 5 calls guid 2 + // there's also a second root, guid3. + auto *Root1 = createNode(1, 2, 2); + Root1->counters()[0] = 10; + Root1->counters()[1] = 11; + Roots.insert({1, Root1}); + auto *L1 = createNode(2, 1, 1); + L1->counters()[0] = 12; + Root1->subContexts()[1] = createNode(4, 3, 1, L1); + Root1->subContexts()[1]->counters()[0] = 13; + Root1->subContexts()[1]->counters()[1] = 14; + Root1->subContexts()[1]->counters()[2] = 15; + + auto *L3 = createNode(5, 6, 3); + for (auto I = 0; I < 6; ++I) + L3->counters()[I] = 16 + I; + L1->subContexts()[0] = L3; + L3->subContexts()[2] = createNode(2, 1, 1); + L3->subContexts()[2]->counters()[0] = 30; + auto *Root2 = createNode(3, 1, 0); + Root2->counters()[0] = 40; + Roots.insert({3, Root2}); + } + + const std::map &roots() const { return Roots; } +}; + +void checkSame(const ContextNode &Raw, const PGOContextualProfile &Profile) { + EXPECT_EQ(Raw.guid(), Profile.guid()); + ASSERT_EQ(Raw.counters_size(), Profile.counters().size()); + for (auto I = 0U; I < Raw.counters_size(); ++I) + EXPECT_EQ(Raw.counters()[I], Profile.counters()[I]); + + for (auto I = 0U; I < Raw.callsites_size(); ++I) { + if (Raw.subContexts()[I] == nullptr) + continue; + EXPECT_TRUE(Profile.hasCallsite(I)); + const auto &ProfileTargets = Profile.callsite(I); + + std::map Targets; + for (const auto *N = Raw.subContexts()[I]; N; N = N->next()) + EXPECT_TRUE(Targets.insert({N->guid(), N}).second); + + EXPECT_EQ(Targets.size(), ProfileTargets.size()); + for (auto It : Targets) { + auto PIt = ProfileTargets.find(It.second->guid()); + EXPECT_NE(PIt, ProfileTargets.end()); + checkSame(*It.second, PIt->second); + } + } +} + +TEST_F(PGOCtxProfRWTest, RoundTrip) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + for (auto &[_, R] : roots()) + Writer.write(*R); + } + } + { + ErrorOr> MB = + MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + ASSERT_TRUE(!!Expected); + auto &Ctxes = *Expected; + EXPECT_EQ(Ctxes.size(), roots().size()); + EXPECT_EQ(Ctxes.size(), 2U); + for (auto &[G, R] : roots()) + checkSame(*R, Ctxes.find(G)->second); + } +} + +TEST_F(PGOCtxProfRWTest, InvalidCounters) { + auto *R = createNode(1, 0, 1); + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + Writer.write(*R); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} + +TEST_F(PGOCtxProfRWTest, Empty) { + BitstreamCursor Cursor(""); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); +} + +TEST_F(PGOCtxProfRWTest, Invalid) { + BitstreamCursor Cursor("Surely this is not valid"); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); +} + +TEST_F(PGOCtxProfRWTest, ValidButEmpty) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + // don't write anything - this will just produce the metadata subblock. + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_TRUE(!!Expected); + EXPECT_TRUE(Expected->empty()); + } +} + +TEST_F(PGOCtxProfRWTest, WrongVersion) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out, PGOCtxProfileWriter::CurrentVersion + 1); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} + +TEST_F(PGOCtxProfRWTest, DuplicateRoots) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + PGOCtxProfileWriter Writer(Out); + Writer.write(*createNode(1, 1, 1)); + Writer.write(*createNode(1, 1, 1)); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} + +TEST_F(PGOCtxProfRWTest, DuplicateTargets) { + llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true); + { + std::error_code EC; + raw_fd_stream Out(ProfileFile.path(), EC); + ASSERT_FALSE(EC); + { + auto *R = createNode(1, 1, 1); + auto *L1 = createNode(2, 1, 0); + auto *L2 = createNode(2, 1, 0, L1); + R->subContexts()[0] = L2; + PGOCtxProfileWriter Writer(Out); + Writer.write(*R); + } + } + { + auto MB = MemoryBuffer::getFile(ProfileFile.path()); + ASSERT_TRUE(!!MB); + ASSERT_NE(*MB, nullptr); + BitstreamCursor Cursor((*MB)->getBuffer()); + PGOCtxProfileReader Reader(Cursor); + auto Expected = Reader.loadContexts(); + EXPECT_FALSE(Expected); + consumeError(Expected.takeError()); + } +} -- GitLab From 2fb92520cba15afff6f25a1f0b959ef39912fa0a Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Wed, 15 May 2024 19:54:54 +0000 Subject: [PATCH 407/578] [gn build] Port fc8775e2142c --- llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn | 2 ++ llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn | 1 + 2 files changed, 3 insertions(+) diff --git a/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn index 9dbfe0f94c1d..c6fa142b3766 100644 --- a/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/ProfileData/BUILD.gn @@ -17,6 +17,8 @@ static_library("ProfileData") { "ItaniumManglingCanonicalizer.cpp", "MemProf.cpp", "MemProfReader.cpp", + "PGOCtxProfReader.cpp", + "PGOCtxProfWriter.cpp", "ProfileSummaryBuilder.cpp", "SampleProf.cpp", "SampleProfReader.cpp", diff --git a/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn index 4919a8089209..f45542519173 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/ProfileData/BUILD.gn @@ -14,6 +14,7 @@ unittest("ProfileDataTests") { "InstrProfTest.cpp", "ItaniumManglingCanonicalizerTest.cpp", "MemProfTest.cpp", + "PGOCtxProfReaderWriterTest.cpp", "SampleProfTest.cpp", "SymbolRemappingReaderTest.cpp", ] -- GitLab From 24c39261e62d9f99bab91edf67bb9607a681b038 Mon Sep 17 00:00:00 2001 From: Alex Bradbury Date: Wed, 15 May 2024 21:04:20 +0100 Subject: [PATCH 408/578] [RISCV][test] Add tests for parsing profiles using RISCVISAInfo::parseArchString --- .../TargetParser/RISCVISAInfoTest.cpp | 63 ++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp index 7f2d1eb8c017..d04f21fa2006 100644 --- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp +++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp @@ -21,8 +21,8 @@ bool operator==(const RISCVISAUtils::ExtensionVersion &A, } TEST(ParseNormalizedArchString, RejectsInvalidChars) { - for (StringRef Input : - {"RV32", "rV64", "rv32i2P0", "rv64i2p0_A2p0", "rv32e2.0"}) { + for (StringRef Input : {"RV32", "rV64", "rv32i2P0", "rv64i2p0_A2p0", + "rv32e2.0", "rva20u64+zbc"}) { EXPECT_EQ( toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()), "string may only contain [a-z0-9_]"); @@ -667,6 +667,65 @@ TEST(ParseArchString, RejectsConflictingExtensions) { } } +TEST(ParseArchString, RejectsUnrecognizedProfileNames) { + for (StringRef Input : {"rvi23u99", "rvz23u64", "rva99u32"}) { + EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), + "string must begin with rv32{i,e,g}, rv64{i,e,g}, or a supported " + "profile name"); + } +} + +TEST(ParseArchString, RejectsProfilesWithUnseparatedExtraExtensions) { + for (StringRef Input : {"rvi20u32m", "rvi20u64c"}) { + EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), + "additional extensions must be after separator '_'"); + } +} + +TEST(ParseArchString, AcceptsBareProfileNames) { + auto MaybeRVA20U64 = RISCVISAInfo::parseArchString("rva20u64", true); + ASSERT_THAT_EXPECTED(MaybeRVA20U64, Succeeded()); + const auto &Exts = (*MaybeRVA20U64)->getExtensions(); + EXPECT_EQ(Exts.size(), 13UL); + EXPECT_EQ(Exts.count("i"), 1U); + EXPECT_EQ(Exts.count("m"), 1U); + EXPECT_EQ(Exts.count("f"), 1U); + EXPECT_EQ(Exts.count("a"), 1U); + EXPECT_EQ(Exts.count("d"), 1U); + EXPECT_EQ(Exts.count("c"), 1U); + EXPECT_EQ(Exts.count("za128rs"), 1U); + EXPECT_EQ(Exts.count("zicntr"), 1U); + EXPECT_EQ(Exts.count("ziccif"), 1U); + EXPECT_EQ(Exts.count("zicsr"), 1U); + EXPECT_EQ(Exts.count("ziccrse"), 1U); + EXPECT_EQ(Exts.count("ziccamoa"), 1U); + EXPECT_EQ(Exts.count("zicclsm"), 1U); + + auto MaybeRVA23U64 = RISCVISAInfo::parseArchString("rva23u64", true); + ASSERT_THAT_EXPECTED(MaybeRVA23U64, Succeeded()); + EXPECT_GT((*MaybeRVA23U64)->getExtensions().size(), 13UL); +} + +TEST(ParseArchSTring, AcceptsProfileNamesWithSeparatedAdditionalExtensions) { + auto MaybeRVI20U64 = RISCVISAInfo::parseArchString("rvi20u64_m_zba", true); + ASSERT_THAT_EXPECTED(MaybeRVI20U64, Succeeded()); + const auto &Exts = (*MaybeRVI20U64)->getExtensions(); + EXPECT_EQ(Exts.size(), 3UL); + EXPECT_EQ(Exts.count("i"), 1U); + EXPECT_EQ(Exts.count("m"), 1U); + EXPECT_EQ(Exts.count("zba"), 1U); +} + +TEST(ParseArchString, + RejectsProfilesWithAdditionalExtensionsGivenAlreadyInProfile) { + // This test was added to document the current behaviour. Discussion isn't + // believed to have taken place about if this is desirable or not. + EXPECT_EQ( + toString( + RISCVISAInfo::parseArchString("rva20u64_zicntr", true).takeError()), + "duplicated standard user-level extension 'zicntr'"); +} + TEST(ToFeatures, IIsDroppedAndExperimentalExtensionsArePrefixed) { auto MaybeISAInfo1 = RISCVISAInfo::parseArchString("rv64im_ztso", true, false); -- GitLab From 891d687137ad9bb3b4efae116f9539addb5be0ea Mon Sep 17 00:00:00 2001 From: Alex Bradbury Date: Wed, 15 May 2024 21:09:43 +0100 Subject: [PATCH 409/578] [RISCV] Gate unratified profiles behind -menable-experimental-extensions (#92167) As discussed in the last sync-up call, because these profiles are not yet finalised they shouldn't be exposed to users unless they opt-in to them (much like experimental extensions). We may later want to add a more specific flag, but reusing `-menable-experimental-extensions` solves the immediate problem. This is implemented using the new support for marking profiles s experimental added in #91993 to move the unratified profiles to RISCVExperimentalProfile and making the necessary changes to logic in RISCVISAInfo to handle this. --- clang/test/Driver/riscv-profiles.c | 10 +++++-- llvm/lib/Target/RISCV/RISCVProfiles.td | 14 +++++---- llvm/lib/TargetParser/RISCVISAInfo.cpp | 29 +++++++++++++++---- llvm/test/CodeGen/RISCV/attributes.ll | 10 +++---- .../TargetParser/RISCVISAInfoTest.cpp | 13 +++++++-- 5 files changed, 55 insertions(+), 21 deletions(-) diff --git a/clang/test/Driver/riscv-profiles.c b/clang/test/Driver/riscv-profiles.c index 298f301de3fe..55aa5b398cee 100644 --- a/clang/test/Driver/riscv-profiles.c +++ b/clang/test/Driver/riscv-profiles.c @@ -111,7 +111,7 @@ // RVA22S64: "-target-feature" "+svinval" // RVA22S64: "-target-feature" "+svpbmt" -// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva23u64 \ +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva23u64 -menable-experimental-extensions \ // RUN: | FileCheck -check-prefix=RVA23U64 %s // RVA23U64: "-target-feature" "+m" // RVA23U64: "-target-feature" "+a" @@ -207,7 +207,7 @@ // RVA23S64: "-target-feature" "+svnapot" // RVA23S64: "-target-feature" "+svpbmt" -// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rvb23u64 \ +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rvb23u64 -menable-experimental-extensions \ // RUN: | FileCheck -check-prefix=RVB23U64 %s // RVB23U64: "-target-feature" "+m" // RVB23U64: "-target-feature" "+a" @@ -284,7 +284,7 @@ // RVB23S64: "-target-feature" "+svnapot" // RVB23S64: "-target-feature" "+svpbmt" -// RUN: %clang --target=riscv32 -### -c %s 2>&1 -march=rvm23u32 \ +// RUN: %clang --target=riscv32 -### -c %s 2>&1 -march=rvm23u32 -menable-experimental-extensions \ // RUN: | FileCheck -check-prefix=RVM23U32 %s // RVM23U32: "-target-feature" "+m" // RVM23U32: "-target-feature" "+zicbop" @@ -322,3 +322,7 @@ // RUN: not %clang --target=riscv64 -### -c %s 2>&1 -march=rva22u64zfa | FileCheck -check-prefix=INVALID-ADDITIONAL %s // INVALID-ADDITIONAL: error: invalid arch name 'rva22u64zfa', additional extensions must be after separator '_' + +// RUN: not %clang --target=riscv64 -### -c %s 2>&1 -march=rva23u64 | FileCheck -check-prefix=EXPERIMENTAL-NOFLAG %s +// EXPERIMENTAL-NOFLAG: error: invalid arch name 'rva23u64' +// EXPERIMENTAL-NOFLAG: requires '-menable-experimental-extensions' for profile 'rva23u64' diff --git a/llvm/lib/Target/RISCV/RISCVProfiles.td b/llvm/lib/Target/RISCV/RISCVProfiles.td index e56df33bd8cb..c4a64681f5f1 100644 --- a/llvm/lib/Target/RISCV/RISCVProfiles.td +++ b/llvm/lib/Target/RISCV/RISCVProfiles.td @@ -13,6 +13,10 @@ class RISCVProfile features> // experimental. bit Experimental = false; } +class RISCVExperimentalProfile features> + : RISCVProfile<"experimental-"#name, features> { + let Experimental = true; +} defvar RVI20U32Features = [Feature32Bit, FeatureStdExtI]; defvar RVI20U64Features = [Feature64Bit, FeatureStdExtI]; @@ -201,8 +205,8 @@ def RVA20U64 : RISCVProfile<"rva20u64", RVA20U64Features>; def RVA20S64 : RISCVProfile<"rva20s64", RVA20S64Features>; def RVA22U64 : RISCVProfile<"rva22u64", RVA22U64Features>; def RVA22S64 : RISCVProfile<"rva22s64", RVA22S64Features>; -def RVA23U64 : RISCVProfile<"rva23u64", RVA23U64Features>; -def RVA23S64 : RISCVProfile<"rva23s64", RVA23S64Features>; -def RVB23U64 : RISCVProfile<"rvb23u64", RVB23U64Features>; -def RVB23S64 : RISCVProfile<"rvb23s64", RVB23S64Features>; -def RVM23U32 : RISCVProfile<"rvm23u32", RVM23U32Features>; +def RVA23U64 : RISCVExperimentalProfile<"rva23u64", RVA23U64Features>; +def RVA23S64 : RISCVExperimentalProfile<"rva23s64", RVA23S64Features>; +def RVB23U64 : RISCVExperimentalProfile<"rvb23u64", RVB23U64Features>; +def RVB23S64 : RISCVExperimentalProfile<"rvb23s64", RVB23S64Features>; +def RVM23U32 : RISCVExperimentalProfile<"rvm23u32", RVM23U32Features>; diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp index 575c9dbad515..706b2853cd2c 100644 --- a/llvm/lib/TargetParser/RISCVISAInfo.cpp +++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp @@ -102,6 +102,10 @@ void llvm::riscvExtensionsHelp(StringMap DescMap) { for (const auto &P : SupportedProfiles) outs().indent(4) << P.Name << "\n"; + outs() << "\nExperimental Profiles\n"; + for (const auto &P : SupportedExperimentalProfiles) + outs().indent(4) << P.Name << "\n"; + outs() << "\nUse -march to specify the target's extension.\n" "For example, clang -march=rv32i_v1p0\n"; } @@ -608,12 +612,25 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension, XLen = 64; } else { // Try parsing as a profile. - auto I = llvm::upper_bound(SupportedProfiles, Arch, - [](StringRef Arch, const RISCVProfile &Profile) { - return Arch < Profile.Name; - }); - - if (I != std::begin(SupportedProfiles) && Arch.starts_with((--I)->Name)) { + auto ProfileCmp = [](StringRef Arch, const RISCVProfile &Profile) { + return Arch < Profile.Name; + }; + auto I = llvm::upper_bound(SupportedProfiles, Arch, ProfileCmp); + bool FoundProfile = I != std::begin(SupportedProfiles) && + Arch.starts_with(std::prev(I)->Name); + if (!FoundProfile) { + I = llvm::upper_bound(SupportedExperimentalProfiles, Arch, ProfileCmp); + FoundProfile = (I != std::begin(SupportedExperimentalProfiles) && + Arch.starts_with(std::prev(I)->Name)); + if (FoundProfile && !EnableExperimentalExtension) { + return createStringError(errc::invalid_argument, + "requires '-menable-experimental-extensions' " + "for profile '" + + std::prev(I)->Name + "'"); + } + } + if (FoundProfile) { + --I; std::string NewArch = I->MArch.str(); StringRef ArchWithoutProfile = Arch.drop_front(I->Name.size()); if (!ArchWithoutProfile.empty()) { diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll index 8f49f6648ad2..953ed5ee3795 100644 --- a/llvm/test/CodeGen/RISCV/attributes.ll +++ b/llvm/test/CodeGen/RISCV/attributes.ll @@ -265,11 +265,11 @@ ; RUN: llc -mtriple=riscv64 -mattr=+rva20s64 %s -o - | FileCheck --check-prefix=RVA20S64 %s ; RUN: llc -mtriple=riscv64 -mattr=+rva22u64 %s -o - | FileCheck --check-prefix=RVA22U64 %s ; RUN: llc -mtriple=riscv64 -mattr=+rva22s64 %s -o - | FileCheck --check-prefix=RVA22S64 %s -; RUN: llc -mtriple=riscv64 -mattr=+rva23u64 %s -o - | FileCheck --check-prefix=RVA23U64 %s -; RUN: llc -mtriple=riscv64 -mattr=+rva23s64 %s -o - | FileCheck --check-prefix=RVA23S64 %s -; RUN: llc -mtriple=riscv64 -mattr=+rvb23u64 %s -o - | FileCheck --check-prefix=RVB23U64 %s -; RUN: llc -mtriple=riscv64 -mattr=+rvb23s64 %s -o - | FileCheck --check-prefix=RVB23S64 %s -; RUN: llc -mtriple=riscv32 -mattr=+rvm23u32 %s -o - | FileCheck --check-prefix=RVM23U32 %s +; RUN: llc -mtriple=riscv64 -mattr=+experimental-rva23u64 %s -o - | FileCheck --check-prefix=RVA23U64 %s +; RUN: llc -mtriple=riscv64 -mattr=+experimental-rva23s64 %s -o - | FileCheck --check-prefix=RVA23S64 %s +; RUN: llc -mtriple=riscv64 -mattr=+experimental-rvb23u64 %s -o - | FileCheck --check-prefix=RVB23U64 %s +; RUN: llc -mtriple=riscv64 -mattr=+experimental-rvb23s64 %s -o - | FileCheck --check-prefix=RVB23S64 %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-rvm23u32 %s -o - | FileCheck --check-prefix=RVM23U32 %s ; CHECK: .attribute 4, 16 diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp index d04f21fa2006..22fe31809319 100644 --- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp +++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp @@ -726,6 +726,13 @@ TEST(ParseArchString, "duplicated standard user-level extension 'zicntr'"); } +TEST(ParseArchString, + RejectsExperimentalProfilesIfEnableExperimentalExtensionsNotSet) { + EXPECT_EQ( + toString(RISCVISAInfo::parseArchString("rva23u64", false).takeError()), + "requires '-menable-experimental-extensions' for profile 'rva23u64'"); +} + TEST(ToFeatures, IIsDroppedAndExperimentalExtensionsArePrefixed) { auto MaybeISAInfo1 = RISCVISAInfo::parseArchString("rv64im_ztso", true, false); @@ -1073,12 +1080,14 @@ Supported Profiles rva20u64 rva22s64 rva22u64 + rvi20u32 + rvi20u64 + +Experimental Profiles rva23s64 rva23u64 rvb23s64 rvb23u64 - rvi20u32 - rvi20u64 rvm23u32 Use -march to specify the target's extension. -- GitLab From 80d9ae9cbf692a73404995a88665af7166c7e8ad Mon Sep 17 00:00:00 2001 From: Samira Bazuzi Date: Wed, 15 May 2024 16:11:11 -0400 Subject: [PATCH 410/578] [clang][dataflow] Fully support Environment construction for Stmt analysis. (#91616) Assume in fewer places that the analysis is of a `FunctionDecl`, and initialize the `Environment` properly for `Stmt`s. Moves constructors for `Environment` to header to make it more obvious that there are only minor differences between them and very little initialization in the constructors. Tested with check-clang-tooling. --- .../FlowSensitive/DataflowEnvironment.h | 118 +++++++++++------- .../FlowSensitive/DataflowEnvironment.cpp | 107 ++++++++-------- .../TypeErasedDataflowAnalysis.cpp | 2 +- .../FlowSensitive/DataflowEnvironmentTest.cpp | 33 +++++ .../Analysis/FlowSensitive/TestingSupport.h | 4 +- .../TypeErasedDataflowAnalysisTest.cpp | 32 +++++ 6 files changed, 198 insertions(+), 98 deletions(-) diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index cdf89c7def2c..097ff2bdfe7a 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -19,6 +19,7 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" +#include "clang/Analysis/FlowSensitive/ASTOps.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowLattice.h" #include "clang/Analysis/FlowSensitive/Formula.h" @@ -30,9 +31,11 @@ #include "llvm/ADT/MapVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include #include #include #include +#include namespace clang { namespace dataflow { @@ -155,7 +158,28 @@ public: /// Creates an environment that uses `DACtx` to store objects that encompass /// the state of a program. - explicit Environment(DataflowAnalysisContext &DACtx); + explicit Environment(DataflowAnalysisContext &DACtx) + : DACtx(&DACtx), + FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {} + + /// Creates an environment that uses `DACtx` to store objects that encompass + /// the state of a program, with `S` as the statement to analyze. + Environment(DataflowAnalysisContext &DACtx, Stmt &S) : Environment(DACtx) { + InitialTargetStmt = &S; + } + + /// Creates an environment that uses `DACtx` to store objects that encompass + /// the state of a program, with `FD` as the function to analyze. + /// + /// Requirements: + /// + /// The function must have a body, i.e. + /// `FunctionDecl::doesThisDecalarationHaveABody()` must be true. + Environment(DataflowAnalysisContext &DACtx, const FunctionDecl &FD) + : Environment(DACtx, *FD.getBody()) { + assert(FD.doesThisDeclarationHaveABody()); + InitialTargetFunc = &FD; + } // Copy-constructor is private, Environments should not be copied. See fork(). Environment &operator=(const Environment &Other) = delete; @@ -163,24 +187,11 @@ public: Environment(Environment &&Other) = default; Environment &operator=(Environment &&Other) = default; - /// Creates an environment that uses `DACtx` to store objects that encompass - /// the state of a program. - /// - /// If `DeclCtx` is a function, initializes the environment with symbolic - /// representations of the function parameters. - /// - /// If `DeclCtx` is a non-static member function, initializes the environment - /// with a symbolic representation of the `this` pointee. - Environment(DataflowAnalysisContext &DACtx, const DeclContext &DeclCtx); - /// Assigns storage locations and values to all parameters, captures, global - /// variables, fields and functions referenced in the function currently being - /// analyzed. - /// - /// Requirements: + /// variables, fields and functions referenced in the `Stmt` or `FunctionDecl` + /// passed to the constructor. /// - /// The function must have a body, i.e. - /// `FunctionDecl::doesThisDecalarationHaveABody()` must be true. + /// If no `Stmt` or `FunctionDecl` was supplied, this function does nothing. void initialize(); /// Returns a new environment that is a copy of this one. @@ -193,7 +204,7 @@ public: /// forked flow condition references the original). Environment fork() const; - /// Creates and returns an environment to use for an inline analysis of the + /// Creates and returns an environment to use for an inline analysis of the /// callee. Uses the storage location from each argument in the `Call` as the /// storage location for the corresponding parameter in the callee. /// @@ -365,46 +376,51 @@ public: RecordStorageLocation & getResultObjectLocation(const Expr &RecordPRValue) const; - /// Returns the return value of the current function. This can be null if: + /// Returns the return value of the function currently being analyzed. + /// This can be null if: /// - The function has a void return type /// - No return value could be determined for the function, for example /// because it calls a function without a body. /// /// Requirements: - /// The current function must have a non-reference return type. + /// The current analysis target must be a function and must have a + /// non-reference return type. Value *getReturnValue() const { assert(getCurrentFunc() != nullptr && !getCurrentFunc()->getReturnType()->isReferenceType()); return ReturnVal; } - /// Returns the storage location for the reference returned by the current - /// function. This can be null if function doesn't return a single consistent - /// reference. + /// Returns the storage location for the reference returned by the function + /// currently being analyzed. This can be null if the function doesn't return + /// a single consistent reference. /// /// Requirements: - /// The current function must have a reference return type. + /// The current analysis target must be a function and must have a reference + /// return type. StorageLocation *getReturnStorageLocation() const { assert(getCurrentFunc() != nullptr && getCurrentFunc()->getReturnType()->isReferenceType()); return ReturnLoc; } - /// Sets the return value of the current function. + /// Sets the return value of the function currently being analyzed. /// /// Requirements: - /// The current function must have a non-reference return type. + /// The current analysis target must be a function and must have a + /// non-reference return type. void setReturnValue(Value *Val) { assert(getCurrentFunc() != nullptr && !getCurrentFunc()->getReturnType()->isReferenceType()); ReturnVal = Val; } - /// Sets the storage location for the reference returned by the current - /// function. + /// Sets the storage location for the reference returned by the function + /// currently being analyzed. /// /// Requirements: - /// The current function must have a reference return type. + /// The current analysis target must be a function and must have a reference + /// return type. void setReturnStorageLocation(StorageLocation *Loc) { assert(getCurrentFunc() != nullptr && getCurrentFunc()->getReturnType()->isReferenceType()); @@ -641,23 +657,21 @@ public: /// (or the flow condition is overly constraining) or if the solver times out. bool allows(const Formula &) const; - /// Returns the `DeclContext` of the block being analysed, if any. Otherwise, - /// returns null. - const DeclContext *getDeclCtx() const { return CallStack.back(); } - /// Returns the function currently being analyzed, or null if the code being /// analyzed isn't part of a function. const FunctionDecl *getCurrentFunc() const { - return dyn_cast(getDeclCtx()); + return CallStack.empty() ? InitialTargetFunc : CallStack.back(); } - /// Returns the size of the call stack. + /// Returns the size of the call stack, not counting the initial analysis + /// target. size_t callStackSize() const { return CallStack.size(); } /// Returns whether this `Environment` can be extended to analyze the given - /// `Callee` (i.e. if `pushCall` can be used), with recursion disallowed and a - /// given `MaxDepth`. - bool canDescend(unsigned MaxDepth, const DeclContext *Callee) const; + /// `Callee` (i.e. if `pushCall` can be used). + /// Recursion is not allowed. `MaxDepth` is the maximum size of the call stack + /// (i.e. the maximum value that `callStackSize()` may assume after the call). + bool canDescend(unsigned MaxDepth, const FunctionDecl *Callee) const; /// Returns the `DataflowAnalysisContext` used by the environment. DataflowAnalysisContext &getDataflowAnalysisContext() const { return *DACtx; } @@ -719,8 +733,8 @@ private: ArrayRef Args); /// Assigns storage locations and values to all global variables, fields - /// and functions referenced in `FuncDecl`. `FuncDecl` must have a body. - void initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl); + /// and functions in `Referenced`. + void initFieldsGlobalsAndFuncs(const ReferencedDecls &Referenced); static PrValueToResultObject buildResultObjectMap(DataflowAnalysisContext *DACtx, @@ -728,6 +742,11 @@ private: RecordStorageLocation *ThisPointeeLoc, RecordStorageLocation *LocForRecordReturnVal); + static PrValueToResultObject + buildResultObjectMap(DataflowAnalysisContext *DACtx, Stmt *S, + RecordStorageLocation *ThisPointeeLoc, + RecordStorageLocation *LocForRecordReturnVal); + // `DACtx` is not null and not owned by this object. DataflowAnalysisContext *DACtx; @@ -736,11 +755,20 @@ private: // shared between environments in the same call. // https://github.com/llvm/llvm-project/issues/59005 - // `DeclContext` of the block being analysed if provided. - std::vector CallStack; + // The stack of functions called from the initial analysis target. + std::vector CallStack; + + // Initial function to analyze, if a function was passed to the constructor. + // Null otherwise. + const FunctionDecl *InitialTargetFunc = nullptr; + // Top-level statement of the initial analysis target. + // If a function was passed to the constructor, this is its body. + // If a statement was passed to the constructor, this is that statement. + // Null if no analysis target was passed to the constructor. + Stmt *InitialTargetStmt = nullptr; // Maps from prvalues of record type to their result objects. Shared between - // all environments for the same function. + // all environments for the same analysis target. // FIXME: It's somewhat unsatisfactory that we have to use a `shared_ptr` // here, though the cost is acceptable: The overhead of a `shared_ptr` is // incurred when it is copied, and this happens only relatively rarely (when @@ -749,7 +777,7 @@ private: std::shared_ptr ResultObjectMap; // The following three member variables handle various different types of - // return values. + // return values when the current analysis target is a function. // - If the return type is not a reference and not a record: Value returned // by the function. Value *ReturnVal = nullptr; @@ -762,7 +790,7 @@ private: RecordStorageLocation *LocForRecordReturnVal = nullptr; // The storage location of the `this` pointee. Should only be null if the - // function being analyzed is only a function and not a method. + // analysis target is not a method. RecordStorageLocation *ThisPointeeLoc = nullptr; // Maps from declarations and glvalue expression to storage locations that are diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index cb6c8b2ef107..338a85525b38 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -16,17 +16,22 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/Stmt.h" #include "clang/AST/Type.h" #include "clang/Analysis/FlowSensitive/ASTOps.h" +#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowLattice.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/ErrorHandling.h" +#include #include +#include #include #define DEBUG_TYPE "dataflow" @@ -290,15 +295,14 @@ widenKeyToValueMap(const llvm::MapVector &CurMap, namespace { // Visitor that builds a map from record prvalues to result objects. -// This traverses the body of the function to be analyzed; for each result -// object that it encounters, it propagates the storage location of the result -// object to all record prvalues that can initialize it. +// For each result object that it encounters, it propagates the storage location +// of the result object to all record prvalues that can initialize it. class ResultObjectVisitor : public RecursiveASTVisitor { public: // `ResultObjectMap` will be filled with a map from record prvalues to result - // object. If the function being analyzed returns a record by value, - // `LocForRecordReturnVal` is the location to which this record should be - // written; otherwise, it is null. + // object. If this visitor will traverse a function that returns a record by + // value, `LocForRecordReturnVal` is the location to which this record should + // be written; otherwise, it is null. explicit ResultObjectVisitor( llvm::DenseMap &ResultObjectMap, RecordStorageLocation *LocForRecordReturnVal, @@ -514,39 +518,31 @@ private: } // namespace -Environment::Environment(DataflowAnalysisContext &DACtx) - : DACtx(&DACtx), - FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {} - -Environment::Environment(DataflowAnalysisContext &DACtx, - const DeclContext &DeclCtx) - : Environment(DACtx) { - CallStack.push_back(&DeclCtx); -} - void Environment::initialize() { - const DeclContext *DeclCtx = getDeclCtx(); - if (DeclCtx == nullptr) + if (InitialTargetStmt == nullptr) return; - const auto *FuncDecl = dyn_cast(DeclCtx); - if (FuncDecl == nullptr) + if (InitialTargetFunc == nullptr) { + initFieldsGlobalsAndFuncs(getReferencedDecls(*InitialTargetStmt)); + ResultObjectMap = + std::make_shared(buildResultObjectMap( + DACtx, InitialTargetStmt, getThisPointeeStorageLocation(), + /*LocForRecordReturnValue=*/nullptr)); return; + } - assert(FuncDecl->doesThisDeclarationHaveABody()); - - initFieldsGlobalsAndFuncs(FuncDecl); + initFieldsGlobalsAndFuncs(getReferencedDecls(*InitialTargetFunc)); - for (const auto *ParamDecl : FuncDecl->parameters()) { + for (const auto *ParamDecl : InitialTargetFunc->parameters()) { assert(ParamDecl != nullptr); setStorageLocation(*ParamDecl, createObject(*ParamDecl, nullptr)); } - if (FuncDecl->getReturnType()->isRecordType()) + if (InitialTargetFunc->getReturnType()->isRecordType()) LocForRecordReturnVal = &cast( - createStorageLocation(FuncDecl->getReturnType())); + createStorageLocation(InitialTargetFunc->getReturnType())); - if (const auto *MethodDecl = dyn_cast(DeclCtx)) { + if (const auto *MethodDecl = dyn_cast(InitialTargetFunc)) { auto *Parent = MethodDecl->getParent(); assert(Parent != nullptr); @@ -558,7 +554,7 @@ void Environment::initialize() { setStorageLocation(*VarDecl, createObject(*VarDecl, nullptr)); } else if (Capture.capturesThis()) { const auto *SurroundingMethodDecl = - cast(DeclCtx->getNonClosureAncestor()); + cast(InitialTargetFunc->getNonClosureAncestor()); QualType ThisPointeeType = SurroundingMethodDecl->getFunctionObjectParameterType(); setThisPointeeStorageLocation( @@ -580,18 +576,16 @@ void Environment::initialize() { // We do this below the handling of `CXXMethodDecl` above so that we can // be sure that the storage location for `this` has been set. - ResultObjectMap = std::make_shared( - buildResultObjectMap(DACtx, FuncDecl, getThisPointeeStorageLocation(), - LocForRecordReturnVal)); + ResultObjectMap = + std::make_shared(buildResultObjectMap( + DACtx, InitialTargetFunc, getThisPointeeStorageLocation(), + LocForRecordReturnVal)); } -// FIXME: Add support for resetting globals after function calls to enable -// the implementation of sound analyses. -void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl) { - assert(FuncDecl->doesThisDeclarationHaveABody()); - - ReferencedDecls Referenced = getReferencedDecls(*FuncDecl); +// FIXME: Add support for resetting globals after function calls to enable the +// implementation of sound analyses. +void Environment::initFieldsGlobalsAndFuncs(const ReferencedDecls &Referenced) { // These have to be added before the lines that follow to ensure that // `create*` work correctly for structs. DACtx->addModeledFields(Referenced.Fields); @@ -602,9 +596,9 @@ void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl) { // We don't run transfer functions on the initializers of global variables, // so they won't be associated with a value or storage location. We - // therefore intentionally don't pass an initializer to `createObject()`; - // in particular, this ensures that `createObject()` will initialize the - // fields of record-type variables with values. + // therefore intentionally don't pass an initializer to `createObject()`; in + // particular, this ensures that `createObject()` will initialize the fields + // of record-type variables with values. setStorageLocation(*D, createObject(*D, nullptr)); } @@ -623,8 +617,8 @@ Environment Environment::fork() const { } bool Environment::canDescend(unsigned MaxDepth, - const DeclContext *Callee) const { - return CallStack.size() <= MaxDepth && !llvm::is_contained(CallStack, Callee); + const FunctionDecl *Callee) const { + return CallStack.size() < MaxDepth && !llvm::is_contained(CallStack, Callee); } Environment Environment::pushCall(const CallExpr *Call) const { @@ -671,7 +665,7 @@ void Environment::pushCallInternal(const FunctionDecl *FuncDecl, CallStack.push_back(FuncDecl); - initFieldsGlobalsAndFuncs(FuncDecl); + initFieldsGlobalsAndFuncs(getReferencedDecls(*FuncDecl)); const auto *ParamIt = FuncDecl->param_begin(); @@ -755,6 +749,8 @@ LatticeEffect Environment::widen(const Environment &PrevEnv, assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc); assert(CallStack == PrevEnv.CallStack); assert(ResultObjectMap == PrevEnv.ResultObjectMap); + assert(InitialTargetFunc == PrevEnv.InitialTargetFunc); + assert(InitialTargetStmt == PrevEnv.InitialTargetStmt); auto Effect = LatticeEffect::Unchanged; @@ -790,6 +786,8 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB, assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc); assert(EnvA.CallStack == EnvB.CallStack); assert(EnvA.ResultObjectMap == EnvB.ResultObjectMap); + assert(EnvA.InitialTargetFunc == EnvB.InitialTargetFunc); + assert(EnvA.InitialTargetStmt == EnvB.InitialTargetStmt); Environment JoinedEnv(*EnvA.DACtx); @@ -797,14 +795,13 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB, JoinedEnv.ResultObjectMap = EnvA.ResultObjectMap; JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal; JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc; + JoinedEnv.InitialTargetFunc = EnvA.InitialTargetFunc; + JoinedEnv.InitialTargetStmt = EnvA.InitialTargetStmt; - if (EnvA.CallStack.empty()) { + const FunctionDecl *Func = EnvA.getCurrentFunc(); + if (!Func) { JoinedEnv.ReturnVal = nullptr; } else { - // FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this - // cast. - auto *Func = dyn_cast(EnvA.CallStack.back()); - assert(Func != nullptr); JoinedEnv.ReturnVal = joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal, EnvB, JoinedEnv, Model); @@ -1229,16 +1226,26 @@ Environment::PrValueToResultObject Environment::buildResultObjectMap( RecordStorageLocation *LocForRecordReturnVal) { assert(FuncDecl->doesThisDeclarationHaveABody()); - PrValueToResultObject Map; + PrValueToResultObject Map = buildResultObjectMap( + DACtx, FuncDecl->getBody(), ThisPointeeLoc, LocForRecordReturnVal); ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx); if (const auto *Ctor = dyn_cast(FuncDecl)) Visitor.TraverseConstructorInits(Ctor, ThisPointeeLoc); - Visitor.TraverseStmt(FuncDecl->getBody()); return Map; } +Environment::PrValueToResultObject Environment::buildResultObjectMap( + DataflowAnalysisContext *DACtx, Stmt *S, + RecordStorageLocation *ThisPointeeLoc, + RecordStorageLocation *LocForRecordReturnVal) { + PrValueToResultObject Map; + ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx); + Visitor.TraverseStmt(S); + return Map; +} + RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE, const Environment &Env) { Expr *ImplicitObject = MCE.getImplicitObjectArgument(); diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 12eff4dd4b78..675b42550f17 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -476,7 +476,7 @@ runTypeErasedDataflowAnalysis( PrettyStackTraceAnalysis CrashInfo(ACFG, "runTypeErasedDataflowAnalysis"); std::optional MaybeStartingEnv; - if (InitEnv.callStackSize() == 1) { + if (InitEnv.callStackSize() == 0) { MaybeStartingEnv = InitEnv.fork(); MaybeStartingEnv->initialize(); } diff --git a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp index 419564816124..bd710a00c47c 100644 --- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp @@ -9,6 +9,8 @@ #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "TestingSupport.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/Stmt.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" @@ -403,4 +405,35 @@ TEST_F(EnvironmentTest, Contains(Member)); } +TEST_F(EnvironmentTest, Stmt) { + using namespace ast_matchers; + + std::string Code = R"cc( + struct S { int i; }; + void foo() { + S AnS = S{1}; + } + )cc"; + auto Unit = + tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++11"}); + auto &Context = Unit->getASTContext(); + + ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U); + + auto *DeclStatement = const_cast(selectFirst( + "d", match(declStmt(hasSingleDecl(varDecl(hasName("AnS")))).bind("d"), + Context))); + ASSERT_THAT(DeclStatement, NotNull()); + auto *Init = (cast(*DeclStatement->decl_begin()))->getInit(); + ASSERT_THAT(Init, NotNull()); + + // Verify that we can retrieve the result object location for the initializer + // expression when we analyze the DeclStmt for `AnS`. + Environment Env(DAContext, *DeclStatement); + // Don't crash when initializing. + Env.initialize(); + // And don't crash when retrieving the result object location. + Env.getResultObjectLocation(*Init); +} + } // namespace diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h index 3b0e05ed7222..7348f8b1740d 100644 --- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h +++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h @@ -355,8 +355,8 @@ checkDataflow(AnalysisInputs AI, auto SetupTest = [&StmtToAnnotations, PrevSetupTest = std::move(AI.SetupTest)]( AnalysisOutputs &AO) -> llvm::Error { - auto MaybeStmtToAnnotations = buildStatementToAnnotationMapping( - cast(AO.InitEnv.getDeclCtx()), AO.Code); + auto MaybeStmtToAnnotations = + buildStatementToAnnotationMapping(AO.InitEnv.getCurrentFunc(), AO.Code); if (!MaybeStmtToAnnotations) { return MaybeStmtToAnnotations.takeError(); } diff --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp index b0b579d2bc19..1a52b82d6566 100644 --- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp @@ -146,6 +146,38 @@ TEST_F(DataflowAnalysisTest, DiagnoseFunctionDiagnoserCalledOnEachElement) { " (Lifetime ends)\n"))); } +TEST_F(DataflowAnalysisTest, CanAnalyzeStmt) { + std::string Code = R"cc( + struct S { bool b; }; + void foo() { + S AnS = S{true}; + } + )cc"; + AST = tooling::buildASTFromCodeWithArgs(Code, {"-std=c++11"}); + const auto &DeclStatement = + matchNode(declStmt(hasSingleDecl(varDecl(hasName("AnS"))))); + const auto &Func = matchNode(functionDecl(hasName("foo"))); + + ACFG = std::make_unique(llvm::cantFail(AdornedCFG::build( + Func, const_cast(DeclStatement), AST->getASTContext()))); + + NoopAnalysis Analysis = NoopAnalysis(AST->getASTContext()); + DACtx = std::make_unique( + std::make_unique()); + Environment Env(*DACtx, const_cast(DeclStatement)); + + llvm::Expected>>> + Results = runDataflowAnalysis(*ACFG, Analysis, Env); + + ASSERT_THAT_ERROR(Results.takeError(), llvm::Succeeded()); + const Environment &ExitBlockEnv = Results->front()->Env; + BoolValue *BoolFieldValue = cast( + getFieldValue(ExitBlockEnv.get( + *cast((*DeclStatement.decl_begin()))), + "b", AST->getASTContext(), ExitBlockEnv)); + EXPECT_TRUE(Env.proves(BoolFieldValue->formula())); +} + // Tests for the statement-to-block map. using StmtToBlockTest = DataflowAnalysisTest; -- GitLab From ee765b0c94df7e636d9739216b1646d3a2d3b5db Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Wed, 15 May 2024 22:17:29 +0200 Subject: [PATCH 411/578] [NewPM] Add pass options for `InternalizePass` to preserve GVs. (#91334) This PR adds a string interface to `InternalizePass`' `MustPreserveGV` option, which is a callback function to indicate if a GV is not to be internalized. This is for use in LLVM.jl, the Julia wrapper for LLVM, which uses the C API and is thus required to use the PassBuilder string API for building NewPM pipelines. --- llvm/lib/Passes/PassBuilder.cpp | 18 ++++++++++++++++++ llvm/lib/Passes/PassRegistry.def | 15 ++++++++++++++- llvm/test/Transforms/Internalize/lists.ll | 5 +++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index e4131706aba0..91c5b65c0351 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -1142,6 +1142,24 @@ Expected parseGlobalMergeOptions(StringRef Params) { return Result; } +Expected> parseInternalizeGVs(StringRef Params) { + SmallVector PreservedGVs; + while (!Params.empty()) { + StringRef ParamName; + std::tie(ParamName, Params) = Params.split(';'); + + if (ParamName.consume_front("preserve-gv=")) { + PreservedGVs.push_back(ParamName.str()); + } else { + return make_error( + formatv("invalid Internalize pass parameter '{0}' ", ParamName).str(), + inconvertibleErrorCode()); + } + } + + return PreservedGVs; +} + } // namespace /// Tests whether a pass name starts with a valid prefix for a default pipeline diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index e5ce6cb7da64..50682ca4970f 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -78,7 +78,6 @@ MODULE_PASS("insert-gcov-profiling", GCOVProfilerPass()) MODULE_PASS("instrorderfile", InstrOrderFilePass()) MODULE_PASS("instrprof", InstrProfilingLoweringPass()) MODULE_PASS("ctx-instr-lower", PGOCtxProfLoweringPass()) -MODULE_PASS("internalize", InternalizePass()) MODULE_PASS("invalidate", InvalidateAllAnalysesPass()) MODULE_PASS("iroutliner", IROutlinerPass()) MODULE_PASS("jmc-instrumenter", JMCInstrumenterPass()) @@ -175,6 +174,20 @@ MODULE_PASS_WITH_PARAMS( "hwasan", "HWAddressSanitizerPass", [](HWAddressSanitizerOptions Opts) { return HWAddressSanitizerPass(Opts); }, parseHWASanPassOptions, "kernel;recover") +MODULE_PASS_WITH_PARAMS( + "internalize", "InternalizePass", + [](SmallVector PreservedGVs) { + if (PreservedGVs.empty()) + return InternalizePass(); + auto MustPreserveGV = [=](const GlobalValue &GV) { + for (auto &PreservedGV : PreservedGVs) + if (GV.getName() == PreservedGV) + return true; + return false; + }; + return InternalizePass(MustPreserveGV); + }, + parseInternalizeGVs, "preserve-gv=GV") MODULE_PASS_WITH_PARAMS( "ipsccp", "IPSCCPPass", [](IPSCCPOptions Opts) { return IPSCCPPass(Opts); }, parseIPSCCPOptions, "no-func-spec;func-spec") diff --git a/llvm/test/Transforms/Internalize/lists.ll b/llvm/test/Transforms/Internalize/lists.ll index df408f906b78..83dad03d75ea 100644 --- a/llvm/test/Transforms/Internalize/lists.ll +++ b/llvm/test/Transforms/Internalize/lists.ll @@ -13,6 +13,11 @@ ; -file and -list options should be merged, the apifile contains foo and j ; RUN: opt < %s -passes=internalize -internalize-public-api-list bar -internalize-public-api-file %S/apifile -S | FileCheck --check-prefix=FOO_J_AND_BAR %s +; specifying through pass builder option +; RUN: opt < %s -passes='internalize' -S | FileCheck --check-prefix=FOO_AND_J %s +; RUN: opt < %s -passes='internalize' -S | FileCheck --check-prefix=FOO_AND_BAR %s +; RUN: opt < %s -passes='internalize' -S | FileCheck --check-prefix=FOO_J_AND_BAR %s + ; ALL: @i = internal global ; FOO_AND_J: @i = internal global ; FOO_AND_BAR: @i = internal global -- GitLab From ec1f28dc97ce22ba5b3e6f95ff84414dfbda46b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= Date: Wed, 15 May 2024 22:23:18 +0200 Subject: [PATCH 412/578] AMDGPU/gfx12: avoid crashing on legacy waitcnt intrinsics (#92306) They *are* still accepted by the HW but have a conservative effect. Leave them untouched since handling them would complicate the logic a bit, and developers who code to such a low level really need to revisit what they're doing anyway. --- llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp | 5 + .../CodeGen/AMDGPU/waitcnt-preexisting.mir | 175 ++++++++++++++++++ 2 files changed, 180 insertions(+) diff --git a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp index 839ac927a0ee..5577ce9eb128 100644 --- a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp +++ b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp @@ -1364,6 +1364,11 @@ bool WaitcntGeneratorGFX12Plus::applyPreexistingWaitcnt( unsigned Opcode = SIInstrInfo::getNonSoftWaitcntOpcode(II.getOpcode()); bool TrySimplify = Opcode != II.getOpcode() && !OptNone; + // Don't crash if the programmer used legacy waitcnt intrinsics, but don't + // attempt to do more than that either. + if (Opcode == AMDGPU::S_WAITCNT) + continue; + if (Opcode == AMDGPU::S_WAIT_LOADCNT_DSCNT) { unsigned OldEnc = TII->getNamedOperand(II, AMDGPU::OpName::simm16)->getImm(); diff --git a/llvm/test/CodeGen/AMDGPU/waitcnt-preexisting.mir b/llvm/test/CodeGen/AMDGPU/waitcnt-preexisting.mir index 4c01786e45f5..e15814210dfd 100644 --- a/llvm/test/CodeGen/AMDGPU/waitcnt-preexisting.mir +++ b/llvm/test/CodeGen/AMDGPU/waitcnt-preexisting.mir @@ -1,5 +1,12 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=amdgcn -mcpu=gfx908 -verify-machineinstrs -run-pass si-insert-waitcnts -o - %s | FileCheck -check-prefixes=GFX9 %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs -run-pass si-insert-waitcnts -o - %s | FileCheck -check-prefixes=GFX12 %s + +# For gfx12+, this test simply ensures that we don't crash in the face of manually +# inserted waitcnt intrinsics. They are still allowed for compatibility, but +# their effect in the HW is very conservative and code generation does not attempt +# to do anything with them. Developers who write code at such a low level should +# revisit their code for gfx12+ anyway. --- name: test_waitcnt_preexisting_lgkmcnt_unmodified @@ -17,6 +24,22 @@ body: | ; GFX9-NEXT: S_WAITCNT 112 ; GFX9-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr ; GFX9-NEXT: S_ENDPGM 0 + ; + ; GFX12-LABEL: name: test_waitcnt_preexisting_lgkmcnt_unmodified + ; GFX12: liveins: $vgpr0 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: S_WAIT_EXPCNT 0 + ; GFX12-NEXT: S_WAIT_SAMPLECNT 0 + ; GFX12-NEXT: S_WAIT_BVHCNT 0 + ; GFX12-NEXT: S_WAIT_KMCNT 0 + ; GFX12-NEXT: $vgpr0_vgpr1 = DS_READ2_B32 $vgpr0, 0, 1, 0, implicit $m0, implicit $exec + ; GFX12-NEXT: S_WAITCNT 49279 + ; GFX12-NEXT: S_WAIT_DSCNT 0 + ; GFX12-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_ENDPGM 0 $vgpr0_vgpr1 = DS_READ2_B32 $vgpr0, 0, 1, 0, implicit $m0, implicit $exec S_WAITCNT 49279 $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr @@ -40,6 +63,22 @@ body: | ; GFX9-NEXT: S_WAITCNT 112 ; GFX9-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr ; GFX9-NEXT: S_ENDPGM 0 + ; + ; GFX12-LABEL: name: test_waitcnt_preexisting_vmcnt_unmodified + ; GFX12: liveins: $vgpr0_vgpr1 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: S_WAIT_EXPCNT 0 + ; GFX12-NEXT: S_WAIT_SAMPLECNT 0 + ; GFX12-NEXT: S_WAIT_BVHCNT 0 + ; GFX12-NEXT: S_WAIT_KMCNT 0 + ; GFX12-NEXT: $vgpr0_vgpr1 = GLOBAL_LOAD_DWORDX2 $vgpr0_vgpr1, 0, 0, implicit $exec + ; GFX12-NEXT: S_WAITCNT 3952 + ; GFX12-NEXT: S_WAIT_LOADCNT 0 + ; GFX12-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_ENDPGM 0 $vgpr0_vgpr1 = GLOBAL_LOAD_DWORDX2 $vgpr0_vgpr1, 0, 0, implicit $exec S_WAITCNT 3952 $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr @@ -65,6 +104,22 @@ body: | ; GFX9-NEXT: S_WAITCNT 112 ; GFX9-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr ; GFX9-NEXT: S_ENDPGM 0 + ; + ; GFX12-LABEL: name: test_waitcnt_preexisting_vmcnt_needs_lgkmcnt + ; GFX12: liveins: $vgpr0 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: S_WAIT_EXPCNT 0 + ; GFX12-NEXT: S_WAIT_SAMPLECNT 0 + ; GFX12-NEXT: S_WAIT_BVHCNT 0 + ; GFX12-NEXT: S_WAIT_KMCNT 0 + ; GFX12-NEXT: $vgpr0_vgpr1 = DS_READ2_B32 $vgpr0, 0, 1, 0, implicit $m0, implicit $exec + ; GFX12-NEXT: S_WAITCNT 3952 + ; GFX12-NEXT: S_WAIT_DSCNT 0 + ; GFX12-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_ENDPGM 0 $vgpr0_vgpr1 = DS_READ2_B32 $vgpr0, 0, 1, 0, implicit $m0, implicit $exec S_WAITCNT 3952 $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr @@ -88,6 +143,22 @@ body: | ; GFX9-NEXT: S_WAITCNT 112 ; GFX9-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr ; GFX9-NEXT: S_ENDPGM 0 + ; + ; GFX12-LABEL: name: test_waitcnt_preexisting_lgkmcnt_needs_vmcnt + ; GFX12: liveins: $vgpr0_vgpr1 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: S_WAIT_EXPCNT 0 + ; GFX12-NEXT: S_WAIT_SAMPLECNT 0 + ; GFX12-NEXT: S_WAIT_BVHCNT 0 + ; GFX12-NEXT: S_WAIT_KMCNT 0 + ; GFX12-NEXT: $vgpr0_vgpr1 = GLOBAL_LOAD_DWORDX2 $vgpr0_vgpr1, 0, 0, implicit $exec + ; GFX12-NEXT: S_WAITCNT 49279 + ; GFX12-NEXT: S_WAIT_LOADCNT 0 + ; GFX12-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_ENDPGM 0 $vgpr0_vgpr1 = GLOBAL_LOAD_DWORDX2 $vgpr0_vgpr1, 0, 0, implicit $exec S_WAITCNT 49279 $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr @@ -115,6 +186,24 @@ body: | ; GFX9-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr4_vgpr5, 0, 0, implicit $exec, implicit $flat_scr ; GFX9-NEXT: S_WAITCNT 112 ; GFX9-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr + ; + ; GFX12-LABEL: name: test_waitcnt_preexisting_apply_all_counters + ; GFX12: liveins: $vgpr0_vgpr1, $vgpr2 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: S_WAIT_EXPCNT 0 + ; GFX12-NEXT: S_WAIT_SAMPLECNT 0 + ; GFX12-NEXT: S_WAIT_BVHCNT 0 + ; GFX12-NEXT: S_WAIT_KMCNT 0 + ; GFX12-NEXT: $vgpr4_vgpr5 = GLOBAL_LOAD_DWORDX2 $vgpr0_vgpr1, 0, 0, implicit $exec + ; GFX12-NEXT: $vgpr6_vgpr7 = DS_READ2_B32 $vgpr2, 0, 1, 0, implicit $m0, implicit $exec + ; GFX12-NEXT: S_WAITCNT 0 + ; GFX12-NEXT: S_WAIT_DSCNT 0 + ; GFX12-NEXT: $vgpr6 = V_OR_B32_e32 1, killed $vgpr6, implicit $exec + ; GFX12-NEXT: S_WAIT_LOADCNT 0 + ; GFX12-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr4_vgpr5, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr $vgpr4_vgpr5 = GLOBAL_LOAD_DWORDX2 $vgpr0_vgpr1, 0, 0, implicit $exec $vgpr6_vgpr7 = DS_READ2_B32 $vgpr2, 0, 1, 0, implicit $m0, implicit $exec S_WAITCNT 0 @@ -136,6 +225,24 @@ body: | ; GFX9-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr ; GFX9-NEXT: S_WAITCNT 0 ; GFX9-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr + ; + ; GFX12-LABEL: name: test_waitcnt_preexisting_combine_waitcnt + ; GFX12: liveins: $vgpr0_vgpr1 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: S_WAIT_EXPCNT 0 + ; GFX12-NEXT: S_WAIT_SAMPLECNT 0 + ; GFX12-NEXT: S_WAIT_BVHCNT 0 + ; GFX12-NEXT: S_WAIT_KMCNT 0 + ; GFX12-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_WAITCNT 0 + ; GFX12-NEXT: S_WAITCNT 0 + ; GFX12-NEXT: S_WAITCNT 0 + ; GFX12-NEXT: S_WAITCNT 0 + ; GFX12-NEXT: S_WAITCNT 0 + ; GFX12-NEXT: S_WAITCNT 0 + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr S_WAITCNT 0 S_WAITCNT 0 @@ -159,6 +266,20 @@ body: | ; GFX9-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr ; GFX9-NEXT: S_WAITCNT 112 ; GFX9-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr + ; + ; GFX12-LABEL: name: test_waitcnt_preexisting_combine_waitcnt_diff_counters + ; GFX12: liveins: $vgpr0_vgpr1 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: S_WAIT_EXPCNT 0 + ; GFX12-NEXT: S_WAIT_SAMPLECNT 0 + ; GFX12-NEXT: S_WAIT_BVHCNT 0 + ; GFX12-NEXT: S_WAIT_KMCNT 0 + ; GFX12-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_WAITCNT 49279 + ; GFX12-NEXT: S_WAITCNT 3952 + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr S_WAITCNT 49279 S_WAITCNT 3952 @@ -185,6 +306,23 @@ body: | ; GFX9-NEXT: S_NOP 0 ; GFX9-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr ; GFX9-NEXT: S_ENDPGM 0 + ; + ; GFX12-LABEL: name: test_waitcnt_preexisting_early_wait + ; GFX12: liveins: $vgpr0_vgpr1 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: S_WAIT_EXPCNT 0 + ; GFX12-NEXT: S_WAIT_SAMPLECNT 0 + ; GFX12-NEXT: S_WAIT_BVHCNT 0 + ; GFX12-NEXT: S_WAIT_KMCNT 0 + ; GFX12-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_WAITCNT 0 + ; GFX12-NEXT: S_NOP 0 + ; GFX12-NEXT: S_NOP 0 + ; GFX12-NEXT: S_NOP 0 + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_ENDPGM 0 $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr S_WAITCNT 0 S_NOP 0 @@ -207,6 +345,18 @@ body: | ; GFX9-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr ; GFX9-NEXT: S_WAITCNT 3952 ; GFX9-NEXT: KILL $vgpr0 + ; + ; GFX12-LABEL: name: test_waitcnt_preexisting_ignore_kill + ; GFX12: liveins: $vgpr0_vgpr1 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: S_WAIT_EXPCNT 0 + ; GFX12-NEXT: S_WAIT_SAMPLECNT 0 + ; GFX12-NEXT: S_WAIT_BVHCNT 0 + ; GFX12-NEXT: S_WAIT_KMCNT 0 + ; GFX12-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_WAITCNT 3952 + ; GFX12-NEXT: KILL $vgpr0 $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr S_WAITCNT 3952 KILL $vgpr0 @@ -221,6 +371,15 @@ body: | ; GFX9-LABEL: name: test_waitcnt_preexisting_func_start ; GFX9: S_WAITCNT 0 ; GFX9-NEXT: S_ENDPGM 0 + ; + ; GFX12-LABEL: name: test_waitcnt_preexisting_func_start + ; GFX12: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: S_WAIT_EXPCNT 0 + ; GFX12-NEXT: S_WAIT_SAMPLECNT 0 + ; GFX12-NEXT: S_WAIT_BVHCNT 0 + ; GFX12-NEXT: S_WAIT_KMCNT 0 + ; GFX12-NEXT: S_WAITCNT 0 + ; GFX12-NEXT: S_ENDPGM 0 S_WAITCNT 0 S_ENDPGM 0 ... @@ -241,6 +400,22 @@ body: | ; GFX9-NEXT: S_WAITCNT 112 ; GFX9-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr ; GFX9-NEXT: S_ENDPGM 0 + ; + ; GFX12-LABEL: name: test_waitcnt_preexisting_buffer_inv + ; GFX12: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: S_WAIT_EXPCNT 0 + ; GFX12-NEXT: S_WAIT_SAMPLECNT 0 + ; GFX12-NEXT: S_WAIT_BVHCNT 0 + ; GFX12-NEXT: S_WAIT_KMCNT 0 + ; GFX12-NEXT: $vgpr0_vgpr1 = GLOBAL_LOAD_DWORDX2 $vgpr0_vgpr1, 0, 0, implicit $exec + ; GFX12-NEXT: S_WAITCNT 3952 + ; GFX12-NEXT: BUFFER_INVL2 implicit $exec + ; GFX12-NEXT: S_WAIT_LOADCNT 0 + ; GFX12-NEXT: BUFFER_WBINVL1_VOL implicit $exec + ; GFX12-NEXT: $vgpr0 = FLAT_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_WAIT_LOADCNT_DSCNT 0 + ; GFX12-NEXT: FLAT_STORE_DWORD $vgpr0_vgpr1, $vgpr0, 0, 0, implicit $exec, implicit $flat_scr + ; GFX12-NEXT: S_ENDPGM 0 $vgpr0_vgpr1 = GLOBAL_LOAD_DWORDX2 $vgpr0_vgpr1, 0, 0, implicit $exec S_WAITCNT 3952 BUFFER_INVL2 implicit $exec -- GitLab From 81d20d861e48f5202c9f79b47dee244674fb9121 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 15 May 2024 15:30:05 -0500 Subject: [PATCH 413/578] [Offload][NFC] Fix warning messages in runtime Summary: These are lots of random warnings due to inconsistent initialization or signedness. --- offload/plugins-nextgen/amdgpu/src/rtl.cpp | 11 ++++------- .../plugins-nextgen/common/src/PluginInterface.cpp | 2 +- offload/src/LegacyAPI.cpp | 6 ++++-- offload/src/OpenMP/API.cpp | 2 +- offload/src/OpenMP/Mapping.cpp | 12 +++--------- offload/src/omptarget.cpp | 2 +- 6 files changed, 14 insertions(+), 21 deletions(-) diff --git a/offload/plugins-nextgen/amdgpu/src/rtl.cpp b/offload/plugins-nextgen/amdgpu/src/rtl.cpp index 295685fceaa4..2a9503333c19 100644 --- a/offload/plugins-nextgen/amdgpu/src/rtl.cpp +++ b/offload/plugins-nextgen/amdgpu/src/rtl.cpp @@ -1670,10 +1670,10 @@ private: hsa_agent_t Agent; /// The maximum number of queues. - int MaxNumQueues; + uint32_t MaxNumQueues; /// The size of created queues. - int QueueSize; + uint32_t QueueSize; }; /// Abstract class that holds the common members of the actual kernel devices @@ -1847,8 +1847,7 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy { // Create an AMDGPU device with a device id and default AMDGPU grid values. AMDGPUDeviceTy(GenericPluginTy &Plugin, int32_t DeviceId, int32_t NumDevices, AMDHostDeviceTy &HostDevice, hsa_agent_t Agent) - : GenericDeviceTy(Plugin, DeviceId, NumDevices, {0}), - AMDGenericDeviceTy(), + : GenericDeviceTy(Plugin, DeviceId, NumDevices, {}), AMDGenericDeviceTy(), OMPX_NumQueues("LIBOMPTARGET_AMDGPU_NUM_HSA_QUEUES", 4), OMPX_QueueSize("LIBOMPTARGET_AMDGPU_HSA_QUEUE_SIZE", 512), OMPX_DefaultTeamsPerCU("LIBOMPTARGET_AMDGPU_TEAMS_PER_CU", 4), @@ -2015,9 +2014,7 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy { return Plugin::success(); } - const uint64_t getStreamBusyWaitMicroseconds() const { - return OMPX_StreamBusyWait; - } + uint64_t getStreamBusyWaitMicroseconds() const { return OMPX_StreamBusyWait; } Expected> doJITPostProcessing(std::unique_ptr MB) const override { diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp index a5c8cce63fac..737a8b2a4064 100644 --- a/offload/plugins-nextgen/common/src/PluginInterface.cpp +++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp @@ -593,7 +593,7 @@ void *GenericKernelTy::prepareArgs( Args[0] = &Ptrs[0]; } - for (int I = KLEOffset; I < NumArgs; ++I) { + for (uint32_t I = KLEOffset; I < NumArgs; ++I) { Ptrs[I] = (void *)((intptr_t)ArgPtrs[I - KLEOffset] + ArgOffsets[I - KLEOffset]); Args[I] = &Ptrs[I]; diff --git a/offload/src/LegacyAPI.cpp b/offload/src/LegacyAPI.cpp index 91d5642e8112..033d7a3ef712 100644 --- a/offload/src/LegacyAPI.cpp +++ b/offload/src/LegacyAPI.cpp @@ -88,7 +88,8 @@ EXTERN int __tgt_target_mapper(ident_t *Loc, int64_t DeviceId, void *HostPtr, TIMESCOPE_WITH_IDENT(Loc); OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); KernelArgsTy KernelArgs{1, ArgNum, ArgsBase, Args, ArgSizes, - ArgTypes, ArgNames, ArgMappers, 0}; + ArgTypes, ArgNames, ArgMappers, 0, {}, + {}, {}, 0}; return __tgt_target_kernel(Loc, DeviceId, -1, -1, HostPtr, &KernelArgs); } @@ -132,7 +133,8 @@ EXTERN int __tgt_target_teams_mapper(ident_t *Loc, int64_t DeviceId, TIMESCOPE_WITH_IDENT(Loc); OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); KernelArgsTy KernelArgs{1, ArgNum, ArgsBase, Args, ArgSizes, - ArgTypes, ArgNames, ArgMappers, 0}; + ArgTypes, ArgNames, ArgMappers, 0, {}, + {}, {}, 0}; return __tgt_target_kernel(Loc, DeviceId, NumTeams, ThreadLimit, HostPtr, &KernelArgs); } diff --git a/offload/src/OpenMP/API.cpp b/offload/src/OpenMP/API.cpp index c85f9868e37c..374c54163d6a 100644 --- a/offload/src/OpenMP/API.cpp +++ b/offload/src/OpenMP/API.cpp @@ -642,7 +642,7 @@ EXTERN void *omp_get_mapped_ptr(const void *Ptr, int DeviceNum) { return nullptr; } - size_t NumDevices = omp_get_initial_device(); + int NumDevices = omp_get_initial_device(); if (DeviceNum == NumDevices) { DP("Device %d is initial device, returning Ptr " DPxMOD ".\n", DeviceNum, DPxPTR(Ptr)); diff --git a/offload/src/OpenMP/Mapping.cpp b/offload/src/OpenMP/Mapping.cpp index c6ff3aa54dd6..595e3456ab54 100644 --- a/offload/src/OpenMP/Mapping.cpp +++ b/offload/src/OpenMP/Mapping.cpp @@ -314,9 +314,7 @@ TargetPointerResultTy MappingInfoTy::getTargetPointer( // Notify the plugin about the new mapping. if (Device.notifyDataMapped(HstPtrBegin, Size)) - return {{false /*IsNewEntry=*/, false /*IsHostPointer=*/}, - nullptr /*Entry=*/, - nullptr /*TargetPointer=*/}; + return TargetPointerResultTy{}; } else { // This entry is not present and we did not create a new entry for it. LR.TPR.Flags.IsPresent = false; @@ -344,9 +342,7 @@ TargetPointerResultTy MappingInfoTy::getTargetPointer( LR.TPR.TargetPointer = nullptr; } else if (LR.TPR.getEntry()->addEventIfNecessary(Device, AsyncInfo) != OFFLOAD_SUCCESS) - return {{false /*IsNewEntry=*/, false /*IsHostPointer=*/}, - nullptr /*Entry=*/, - nullptr /*TargetPointer=*/}; + return TargetPointerResultTy{}; } else { // If not a host pointer and no present modifier, we need to wait for the // event if it exists. @@ -360,9 +356,7 @@ TargetPointerResultTy MappingInfoTy::getTargetPointer( // If it fails to wait for the event, we need to return nullptr in // case of any data race. REPORT("Failed to wait for event " DPxMOD ".\n", DPxPTR(Event)); - return {{false /*IsNewEntry=*/, false /*IsHostPointer=*/}, - nullptr /*Entry=*/, - nullptr /*TargetPointer=*/}; + return TargetPointerResultTy{}; } } } diff --git a/offload/src/omptarget.cpp b/offload/src/omptarget.cpp index 5d5c6b05051b..91e1213f175e 100644 --- a/offload/src/omptarget.cpp +++ b/offload/src/omptarget.cpp @@ -1750,7 +1750,7 @@ int target_replay(ident_t *Loc, DeviceTy &Device, void *HostPtr, TARGET_ALLOC_DEFAULT); Device.submitData(TgtPtr, DeviceMemory, DeviceMemorySize, AsyncInfo); - KernelArgsTy KernelArgs = {0}; + KernelArgsTy KernelArgs{}; KernelArgs.Version = OMP_KERNEL_ARG_VERSION; KernelArgs.NumArgs = NumArgs; KernelArgs.Tripcount = LoopTripCount; -- GitLab From 83f065d582977aca5c037c27a7290f30850bdd35 Mon Sep 17 00:00:00 2001 From: Alex Bradbury Date: Wed, 15 May 2024 21:33:10 +0100 Subject: [PATCH 414/578] [RISCV] static_assert SupportedProfiles and SupportedExperimentalProfiles are sorted Just as we do for the arrays of extension names. --- llvm/lib/TargetParser/RISCVISAInfo.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp index 706b2853cd2c..827bc5b44387 100644 --- a/llvm/lib/TargetParser/RISCVISAInfo.cpp +++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp @@ -39,6 +39,10 @@ struct RISCVSupportedExtension { struct RISCVProfile { StringLiteral Name; StringLiteral MArch; + + bool operator<(const RISCVProfile &RHS) const { + return StringRef(Name) < StringRef(RHS.Name); + } }; } // end anonymous namespace @@ -61,6 +65,10 @@ static void verifyTables() { "Extensions are not sorted by name"); assert(llvm::is_sorted(SupportedExperimentalExtensions) && "Experimental extensions are not sorted by name"); + assert(llvm::is_sorted(SupportedProfiles) && + "Profiles are not sorted by name"); + assert(llvm::is_sorted(SupportedExperimentalProfiles) && + "Experimental profiles are not sorted by name"); TableChecked.store(true, std::memory_order_relaxed); } #endif -- GitLab From e1ed138a67a92ef1ff0214ca198094be13045090 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 15 May 2024 14:38:45 -0700 Subject: [PATCH 415/578] [bazel] Port #92199 --- utils/bazel/llvm-project-overlay/llvm/BUILD.bazel | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel index df5cd276b12f..c469da74fc56 100644 --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -1125,6 +1125,8 @@ cc_library( ]), copts = llvm_copts, deps = [ + ":BitstreamReader", + ":BitstreamWriter", ":Core", ":DebugInfo", ":DebugInfoDWARF", -- GitLab From 8530b1c464ae9af4a5c8be145a8db043798634f6 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Wed, 15 May 2024 14:44:42 -0700 Subject: [PATCH 416/578] [lldb] Support custom LLVM formatting for variables (#91868) Re-apply https://github.com/llvm/llvm-project/pull/81196, with a fix that handles the absence of llvm formatting: https://github.com/llvm/llvm-project/pull/91868/commits/3ba650e91eded3543764f37921dcce3b b47d425f --- lldb/docs/use/variable.rst | 9 +++ lldb/source/Core/FormatEntity.cpp | 72 ++++++++++++++++--- .../custom-printf-summary/Makefile | 2 + .../TestCustomSummaryLLVMFormat.py | 20 ++++++ .../custom-printf-summary/main.c | 13 ++++ 5 files changed, 106 insertions(+), 10 deletions(-) create mode 100644 lldb/test/API/functionalities/data-formatter/custom-printf-summary/Makefile create mode 100644 lldb/test/API/functionalities/data-formatter/custom-printf-summary/TestCustomSummaryLLVMFormat.py create mode 100644 lldb/test/API/functionalities/data-formatter/custom-printf-summary/main.c diff --git a/lldb/docs/use/variable.rst b/lldb/docs/use/variable.rst index 8eaed6405315..e9175b25336b 100644 --- a/lldb/docs/use/variable.rst +++ b/lldb/docs/use/variable.rst @@ -460,6 +460,15 @@ summary strings, regardless of the format they have applied to their types. To do that, you can use %format inside an expression path, as in ${var.x->x%u}, which would display the value of x as an unsigned integer. +Additionally, custom output can be achieved by using an LLVM format string, +commencing with the ``:`` marker. To illustrate, compare ``${var.byte%x}`` and +``${var.byte:x-}``. The former uses lldb's builtin hex formatting (``x``), +which unconditionally inserts a ``0x`` prefix, and also zero pads the value to +match the size of the type. The latter uses ``llvm::formatv`` formatting +(``:x-``), and will print only the hex value, with no ``0x`` prefix, and no +padding. This raw control is useful when composing multiple pieces into a +larger whole. + You can also use some other special format markers, not available for formats themselves, but which carry a special meaning when used in this context: diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp index ba62e2625259..07978d388296 100644 --- a/lldb/source/Core/FormatEntity.cpp +++ b/lldb/source/Core/FormatEntity.cpp @@ -57,6 +57,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Regex.h" #include "llvm/TargetParser/Triple.h" #include @@ -658,6 +659,37 @@ static char ConvertValueObjectStyleToChar( return '\0'; } +/// Options supported by format_provider for integral arithmetic types. +/// See table in FormatProviders.h. +static llvm::Regex LLVMFormatPattern{"x[-+]?\\d*|n|d", llvm::Regex::IgnoreCase}; + +static bool DumpValueWithLLVMFormat(Stream &s, llvm::StringRef options, + ValueObject &valobj) { + std::string formatted; + std::string llvm_format = ("{0:" + options + "}").str(); + + auto type_info = valobj.GetTypeInfo(); + if ((type_info & eTypeIsInteger) && LLVMFormatPattern.match(options)) { + if (type_info & eTypeIsSigned) { + bool success = false; + int64_t integer = valobj.GetValueAsSigned(0, &success); + if (success) + formatted = llvm::formatv(llvm_format.data(), integer); + } else { + bool success = false; + uint64_t integer = valobj.GetValueAsUnsigned(0, &success); + if (success) + formatted = llvm::formatv(llvm_format.data(), integer); + } + } + + if (formatted.empty()) + return false; + + s.Write(formatted.data(), formatted.size()); + return true; +} + static bool DumpValue(Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, const FormatEntity::Entry &entry, ValueObject *valobj) { @@ -728,9 +760,12 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str()); } - llvm::StringRef subpath(entry.string); + auto split = llvm::StringRef(entry.string).split(':'); + auto subpath = split.first; + auto llvm_format = split.second; + // simplest case ${var}, just print valobj's value - if (entry.string.empty()) { + if (subpath.empty()) { if (entry.printf_format.empty() && entry.fmt == eFormatDefault && entry.number == ValueObject::eValueObjectRepresentationStyleValue) was_plain_var = true; @@ -739,7 +774,7 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, target = valobj; } else // this is ${var.something} or multiple .something nested { - if (entry.string[0] == '[') + if (subpath[0] == '[') was_var_indexed = true; ScanBracketedRange(subpath, close_bracket_index, var_name_final_if_array_range, index_lower, @@ -747,14 +782,11 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, Status error; - const std::string &expr_path = entry.string; - - LLDB_LOGF(log, "[Debugger::FormatPrompt] symbol to expand: %s", - expr_path.c_str()); + LLDB_LOG(log, "[Debugger::FormatPrompt] symbol to expand: {0}", subpath); target = valobj - ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop, + ->GetValueForExpressionPath(subpath, &reason_to_stop, &final_value_type, options, &what_next) .get(); @@ -883,8 +915,18 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, } if (!is_array_range) { - LLDB_LOGF(log, - "[Debugger::FormatPrompt] dumping ordinary printable output"); + if (!llvm_format.empty()) { + if (DumpValueWithLLVMFormat(s, llvm_format, *target)) { + LLDB_LOGF(log, "dumping using llvm format"); + return true; + } else { + LLDB_LOG( + log, + "empty output using llvm format '{0}' - with type info flags {1}", + entry.printf_format, target->GetTypeInfo()); + } + } + LLDB_LOGF(log, "dumping ordinary printable output"); return target->DumpPrintableRepresentation(s, val_obj_display, custom_format); } else { @@ -2227,6 +2269,16 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry, if (error.Fail()) return error; + llvm::StringRef entry_string(entry.string); + if (entry_string.contains(':')) { + auto [_, llvm_format] = entry_string.split(':'); + if (!llvm_format.empty() && !LLVMFormatPattern.match(llvm_format)) { + error.SetErrorStringWithFormat("invalid llvm format: '%s'", + llvm_format.data()); + return error; + } + } + if (verify_is_thread_id) { if (entry.type != Entry::Type::ThreadID && entry.type != Entry::Type::ThreadProtocolID) { diff --git a/lldb/test/API/functionalities/data-formatter/custom-printf-summary/Makefile b/lldb/test/API/functionalities/data-formatter/custom-printf-summary/Makefile new file mode 100644 index 000000000000..c9319d6e6888 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/custom-printf-summary/Makefile @@ -0,0 +1,2 @@ +C_SOURCES := main.c +include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/custom-printf-summary/TestCustomSummaryLLVMFormat.py b/lldb/test/API/functionalities/data-formatter/custom-printf-summary/TestCustomSummaryLLVMFormat.py new file mode 100644 index 000000000000..d6906a49463b --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/custom-printf-summary/TestCustomSummaryLLVMFormat.py @@ -0,0 +1,20 @@ +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class TestCase(TestBase): + def test_raw_bytes(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.c")) + self.runCmd("type summary add -s '${var.ubyte:x-2}${var.sbyte:x-2}!' Bytes") + self.expect("v bytes", substrs=[" = 3001!"]) + + def test_bad_format(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.c")) + self.expect( + "type summary add -s '${var.ubyte:y}!' Bytes", + error=True, + substrs=["invalid llvm format"], + ) diff --git a/lldb/test/API/functionalities/data-formatter/custom-printf-summary/main.c b/lldb/test/API/functionalities/data-formatter/custom-printf-summary/main.c new file mode 100644 index 000000000000..4164aff7dbf6 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/custom-printf-summary/main.c @@ -0,0 +1,13 @@ +#include +#include + +struct Bytes { + uint8_t ubyte; + int8_t sbyte; +}; + +int main() { + struct Bytes bytes = {0x30, 0x01}; + (void)bytes; + printf("break here\n"); +} -- GitLab From 1daa7fd3fadd17e61d9dfa56f84228617c5514d9 Mon Sep 17 00:00:00 2001 From: Amara Emerson Date: Wed, 15 May 2024 14:38:18 -0700 Subject: [PATCH 417/578] [AArch64][SME] Remove Darwin compile error for ABI support routine calls. These are allowed for Darwin and use the same ABI. --- llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp | 8 ++------ .../sme-support-routines-calling-convention.ll | 12 ++++++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index 5a5a18edb12e..d82fa3924f83 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -233,13 +233,9 @@ AArch64RegisterInfo::getDarwinCallPreservedMask(const MachineFunction &MF, report_fatal_error( "Calling convention SVE_VectorCall is unsupported on Darwin."); if (CC == CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0) - report_fatal_error( - "Calling convention AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0 is " - "unsupported on Darwin."); + return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask; if (CC == CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2) - report_fatal_error( - "Calling convention AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2 is " - "unsupported on Darwin."); + return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2_RegMask; if (CC == CallingConv::CFGuard_Check) report_fatal_error( "Calling convention CFGuard_Check is unsupported on Darwin."); diff --git a/llvm/test/CodeGen/AArch64/sme-support-routines-calling-convention.ll b/llvm/test/CodeGen/AArch64/sme-support-routines-calling-convention.ll index d88deec40ce7..7535638137ca 100644 --- a/llvm/test/CodeGen/AArch64/sme-support-routines-calling-convention.ll +++ b/llvm/test/CodeGen/AArch64/sme-support-routines-calling-convention.ll @@ -1,5 +1,7 @@ ; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=aarch64-apple-darwin -mattr=+sme -verify-machineinstrs < %s | FileCheck %s --check-prefix=DARWIN ; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme -verify-machineinstrs -stop-after=finalize-isel < %s | FileCheck %s --check-prefix=CHECK-CSRMASK +; RUN: llc -mtriple=aarch64-apple-darwin -mattr=+sme -verify-machineinstrs -stop-after=finalize-isel < %s | FileCheck %s --check-prefix=CHECK-CSRMASK ; Test that the PCS attribute is accepted and uses the correct register mask. ; @@ -11,6 +13,11 @@ define void @test_sme_calling_convention_x0() nounwind { ; CHECK-NEXT: bl __arm_tpidr2_save ; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret +; DARWIN-LABEL: test_sme_calling_convention_x0: +; DARWIN: stp x29, x30, [sp, #-16]! +; DARWIN: bl ___arm_tpidr2_save +; DARWIN: ldp x29, x30, [sp], #16 +; DARWIN: ret ; ; CHECK-CSRMASK-LABEL: name: test_sme_calling_convention_x0 ; CHECK-CSRMASK: BL @__arm_tpidr2_save, csr_aarch64_sme_abi_support_routines_preservemost_from_x0 @@ -25,6 +32,11 @@ define i64 @test_sme_calling_convention_x2() nounwind { ; CHECK-NEXT: bl __arm_sme_state ; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret +; DARWIN-LABEL: test_sme_calling_convention_x2: +; DARWIN: stp x29, x30, [sp, #-16]! +; DARWIN: bl ___arm_sme_state +; DARWIN: ldp x29, x30, [sp], #16 +; DARWIN: ret ; ; CHECK-CSRMASK-LABEL: name: test_sme_calling_convention_x2 ; CHECK-CSRMASK: BL @__arm_sme_state, csr_aarch64_sme_abi_support_routines_preservemost_from_x2 -- GitLab From 537a94b2ef67cd96a4b3a9b5612ea726a91c602b Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Wed, 15 May 2024 15:06:08 -0700 Subject: [PATCH 418/578] Revert "[NewPM] Add pass options for `InternalizePass` to preserve GVs." (#92321) Reverts llvm/llvm-project#91334 This broke the gcc7 build. I suspect the issue is a mismatch on user-defined move constructor on the return: `return PreservedGVs;` does not match the return type of the function. --- llvm/lib/Passes/PassBuilder.cpp | 18 ------------------ llvm/lib/Passes/PassRegistry.def | 15 +-------------- llvm/test/Transforms/Internalize/lists.ll | 5 ----- 3 files changed, 1 insertion(+), 37 deletions(-) diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 91c5b65c0351..e4131706aba0 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -1142,24 +1142,6 @@ Expected parseGlobalMergeOptions(StringRef Params) { return Result; } -Expected> parseInternalizeGVs(StringRef Params) { - SmallVector PreservedGVs; - while (!Params.empty()) { - StringRef ParamName; - std::tie(ParamName, Params) = Params.split(';'); - - if (ParamName.consume_front("preserve-gv=")) { - PreservedGVs.push_back(ParamName.str()); - } else { - return make_error( - formatv("invalid Internalize pass parameter '{0}' ", ParamName).str(), - inconvertibleErrorCode()); - } - } - - return PreservedGVs; -} - } // namespace /// Tests whether a pass name starts with a valid prefix for a default pipeline diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index 50682ca4970f..e5ce6cb7da64 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -78,6 +78,7 @@ MODULE_PASS("insert-gcov-profiling", GCOVProfilerPass()) MODULE_PASS("instrorderfile", InstrOrderFilePass()) MODULE_PASS("instrprof", InstrProfilingLoweringPass()) MODULE_PASS("ctx-instr-lower", PGOCtxProfLoweringPass()) +MODULE_PASS("internalize", InternalizePass()) MODULE_PASS("invalidate", InvalidateAllAnalysesPass()) MODULE_PASS("iroutliner", IROutlinerPass()) MODULE_PASS("jmc-instrumenter", JMCInstrumenterPass()) @@ -174,20 +175,6 @@ MODULE_PASS_WITH_PARAMS( "hwasan", "HWAddressSanitizerPass", [](HWAddressSanitizerOptions Opts) { return HWAddressSanitizerPass(Opts); }, parseHWASanPassOptions, "kernel;recover") -MODULE_PASS_WITH_PARAMS( - "internalize", "InternalizePass", - [](SmallVector PreservedGVs) { - if (PreservedGVs.empty()) - return InternalizePass(); - auto MustPreserveGV = [=](const GlobalValue &GV) { - for (auto &PreservedGV : PreservedGVs) - if (GV.getName() == PreservedGV) - return true; - return false; - }; - return InternalizePass(MustPreserveGV); - }, - parseInternalizeGVs, "preserve-gv=GV") MODULE_PASS_WITH_PARAMS( "ipsccp", "IPSCCPPass", [](IPSCCPOptions Opts) { return IPSCCPPass(Opts); }, parseIPSCCPOptions, "no-func-spec;func-spec") diff --git a/llvm/test/Transforms/Internalize/lists.ll b/llvm/test/Transforms/Internalize/lists.ll index 83dad03d75ea..df408f906b78 100644 --- a/llvm/test/Transforms/Internalize/lists.ll +++ b/llvm/test/Transforms/Internalize/lists.ll @@ -13,11 +13,6 @@ ; -file and -list options should be merged, the apifile contains foo and j ; RUN: opt < %s -passes=internalize -internalize-public-api-list bar -internalize-public-api-file %S/apifile -S | FileCheck --check-prefix=FOO_J_AND_BAR %s -; specifying through pass builder option -; RUN: opt < %s -passes='internalize' -S | FileCheck --check-prefix=FOO_AND_J %s -; RUN: opt < %s -passes='internalize' -S | FileCheck --check-prefix=FOO_AND_BAR %s -; RUN: opt < %s -passes='internalize' -S | FileCheck --check-prefix=FOO_J_AND_BAR %s - ; ALL: @i = internal global ; FOO_AND_J: @i = internal global ; FOO_AND_BAR: @i = internal global -- GitLab From f97f039e0bb7bb60c9cc437f678059c5ee19c8da Mon Sep 17 00:00:00 2001 From: klensy Date: Thu, 16 May 2024 01:11:14 +0300 Subject: [PATCH 419/578] [lld,test] Fix few FileCheck annotation typos (#92238) --- lld/test/MachO/install-name.s | 2 +- lld/test/MachO/objc-methname.s | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lld/test/MachO/install-name.s b/lld/test/MachO/install-name.s index 1cf675e278bf..c419c6ca1f95 100644 --- a/lld/test/MachO/install-name.s +++ b/lld/test/MachO/install-name.s @@ -31,7 +31,7 @@ # ID: cmd LC_ID_DYLIB # ID-NEXT: cmdsize -# LID-NEXT: name foo +# ID-NEXT: name foo .globl _main _main: diff --git a/lld/test/MachO/objc-methname.s b/lld/test/MachO/objc-methname.s index afc137eac8c2..3d06472971c8 100644 --- a/lld/test/MachO/objc-methname.s +++ b/lld/test/MachO/objc-methname.s @@ -16,7 +16,7 @@ # CSTRING: Contents of (__TEXT,__cstring) section # CSTRING-NEXT: existing-cstring -# CSTIRNG-EMPTY: +# CSTRING-EMPTY: # METHNAME: Contents of (__TEXT,__objc_methname) section # METHNAME-NEXT: existing_methname -- GitLab From 00179e92c147e16de1f7c653f88c8805aef820c1 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Wed, 15 May 2024 15:23:29 -0700 Subject: [PATCH 420/578] [bazel] Add new dependencies (#92323) This also fixes building ... on Linux. Seems like target_compatible_with isn't enough but you also need a manual tag. --- utils/bazel/llvm-project-overlay/lldb/BUILD.bazel | 5 ++++- utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/utils/bazel/llvm-project-overlay/lldb/BUILD.bazel b/utils/bazel/llvm-project-overlay/lldb/BUILD.bazel index c6fc4e08aa72..ddcaea5184d4 100644 --- a/utils/bazel/llvm-project-overlay/lldb/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/lldb/BUILD.bazel @@ -916,7 +916,10 @@ apple_genrule( srcs = [":debugserver_unsigned"], outs = ["debugserver"], cmd = "cp $(SRCS) $(OUTS) && xcrun codesign -f -s - --entitlements $(location tools/debugserver/resources/debugserver-macosx-entitlements.plist) $(OUTS)", - tags = ["nobuildkite"], + tags = [ + "manual", + "nobuildkite", + ], target_compatible_with = select({ "@platforms//os:macos": [], "//conditions:default": ["@platforms//:incompatible"], diff --git a/utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel index 21f0c7092f32..b44489e213a4 100644 --- a/utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel @@ -617,6 +617,7 @@ cc_test( allow_empty = False, ), deps = [ + "//llvm:BitstreamReader", "//llvm:Core", "//llvm:Coverage", "//llvm:DebugInfo", -- GitLab From 050593fc4f9a7f2b9450ee093c4638b8539315b7 Mon Sep 17 00:00:00 2001 From: Andrey Ali Khan Bolshakov Date: Thu, 16 May 2024 01:39:12 +0300 Subject: [PATCH 421/578] [Coverage] Handle `CoroutineSuspendExpr` correctly (#88898) This avoids visiting `co_await` or `co_yield` operand 5 times (it is repeated under transformed awaiter subexpression, and under `await_ready`, `await_suspend`, and `await_resume` generated call subexpressions). --- clang/lib/CodeGen/CoverageMappingGen.cpp | 4 ++++ clang/test/CoverageMapping/coroutine.cpp | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index ce2f39aeb082..e46560029ab0 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1439,6 +1439,10 @@ struct CounterCoverageMappingBuilder terminateRegion(S); } + void VisitCoroutineSuspendExpr(const CoroutineSuspendExpr *E) { + Visit(E->getOperand()); + } + void VisitCXXThrowExpr(const CXXThrowExpr *E) { extendRegion(E); if (E->getSubExpr()) diff --git a/clang/test/CoverageMapping/coroutine.cpp b/clang/test/CoverageMapping/coroutine.cpp index 0105005d198a..d322bc351a72 100644 --- a/clang/test/CoverageMapping/coroutine.cpp +++ b/clang/test/CoverageMapping/coroutine.cpp @@ -32,6 +32,7 @@ struct std::coroutine_traits { suspend_always final_suspend() noexcept; void unhandled_exception() noexcept; void return_value(int); + suspend_always yield_value(int); }; }; @@ -45,3 +46,21 @@ int f1(int x) { // CHECK-NEXT: File 0, [[@LINE]]:15 -> [[@LINE+8]]:2 = #0 } // CHECK-NEXT: File 0, [[@LINE-2]]:10 -> [[@LINE]]:4 = (#0 - #1) co_return x; // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = #1 } // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:14 = #1 + +// CHECK-LABEL: _Z2f2i: +// CHECK-NEXT: File 0, [[@LINE+1]]:15 -> [[@LINE+15]]:2 = #0 +int f2(int x) { +// CHECK-NEXT: File 0, [[@LINE+5]]:13 -> [[@LINE+5]]:18 = #0 +// CHECK-NEXT: Branch,File 0, [[@LINE+4]]:13 -> [[@LINE+4]]:18 = #1, (#0 - #1) +// CHECK-NEXT: Gap,File 0, [[@LINE+3]]:20 -> [[@LINE+3]]:21 = #1 +// CHECK-NEXT: File 0, [[@LINE+2]]:21 -> [[@LINE+2]]:37 = #1 +// CHECK-NEXT: File 0, [[@LINE+1]]:40 -> [[@LINE+1]]:56 = (#0 - #1) + co_await (x > 0 ? suspend_always{} : suspend_always{}); +// CHECK-NEXT: File 0, [[@LINE+5]]:12 -> [[@LINE+5]]:17 = #0 +// CHECK-NEXT: Branch,File 0, [[@LINE+4]]:12 -> [[@LINE+4]]:17 = #2, (#0 - #2) +// CHECK-NEXT: Gap,File 0, [[@LINE+3]]:19 -> [[@LINE+3]]:20 = #2 +// CHECK-NEXT: File 0, [[@LINE+2]]:20 -> [[@LINE+2]]:21 = #2 +// CHECK-NEXT: File 0, [[@LINE+1]]:24 -> [[@LINE+1]]:25 = (#0 - #2) + co_yield x > 0 ? 1 : 2; + co_return 0; +} -- GitLab From 5ff6c6542ac451daaed6c417e481e313165d3454 Mon Sep 17 00:00:00 2001 From: Andrey Ali Khan Bolshakov Date: Thu, 16 May 2024 01:40:03 +0300 Subject: [PATCH 422/578] [Coverage] Handle array decomposition correctly (#88881) `ArrayInitLoopExpr` AST node has two occurences of its as-written initializing expression in its subexpressions through a non-unique `OpaqueValueExpr`. It causes double-visiting of the initializing expression if not handled explicitly, as discussed in #85837. --- clang/lib/CodeGen/CoverageMappingGen.cpp | 4 ++++ clang/test/CoverageMapping/decomposition.cpp | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 clang/test/CoverageMapping/decomposition.cpp diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index e46560029ab0..cc8ab7a5b436 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -2177,6 +2177,10 @@ struct CounterCoverageMappingBuilder // propagate counts into them. } + void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *AILE) { + Visit(AILE->getCommonExpr()->getSourceExpr()); + } + void VisitPseudoObjectExpr(const PseudoObjectExpr *POE) { // Just visit syntatic expression as this is what users actually write. VisitStmt(POE->getSyntacticForm()); diff --git a/clang/test/CoverageMapping/decomposition.cpp b/clang/test/CoverageMapping/decomposition.cpp new file mode 100644 index 000000000000..601ea630faee --- /dev/null +++ b/clang/test/CoverageMapping/decomposition.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -triple %itanium_abi_triple -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s | FileCheck %s + +// CHECK-LABEL: _Z19array_decompositioni: +// CHECK-NEXT: File 0, [[@LINE+6]]:32 -> {{[0-9]+}}:2 = #0 +// CHECK-NEXT: File 0, [[@LINE+8]]:20 -> [[@LINE+8]]:25 = #0 +// CHECK-NEXT: Branch,File 0, [[@LINE+7]]:20 -> [[@LINE+7]]:25 = #1, (#0 - #1) +// CHECK-NEXT: Gap,File 0, [[@LINE+6]]:27 -> [[@LINE+6]]:28 = #1 +// CHECK-NEXT: File 0, [[@LINE+5]]:28 -> [[@LINE+5]]:29 = #1 +// CHECK-NEXT: File 0, [[@LINE+4]]:32 -> [[@LINE+4]]:33 = (#0 - #1) +int array_decomposition(int i) { + int a[] = {1, 2, 3}; + int b[] = {4, 5, 6}; + auto [x, y, z] = i > 0 ? a : b; + return x + y + z; +} -- GitLab From aa889d7783af050ce5d19af67c7225ee119d625e Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 15 May 2024 15:41:20 -0700 Subject: [PATCH 423/578] [ELF,test] Fix FileCheck prefixes Most violations are stale and should be removed while a few can be adjusted. Reported at #92238 --- lld/test/ELF/arm-exidx-shared.s | 2 +- lld/test/ELF/mips-tls-hilo.s | 10 ---------- lld/test/ELF/ppc32-reloc-rel.s | 3 ++- lld/test/ELF/ppc64-pcrel-call-to-extern.s | 5 ----- lld/test/ELF/ppc64-toc-relax-ifunc.s | 13 +++++-------- lld/test/ELF/riscv-gp.s | 4 ---- 6 files changed, 8 insertions(+), 29 deletions(-) diff --git a/lld/test/ELF/arm-exidx-shared.s b/lld/test/ELF/arm-exidx-shared.s index fce605d6d96a..2e484e5c065f 100644 --- a/lld/test/ELF/arm-exidx-shared.s +++ b/lld/test/ELF/arm-exidx-shared.s @@ -2,7 +2,7 @@ // RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld --hash-style=sysv %t --shared -o %t2 // RUN: llvm-readobj --relocations %t2 | FileCheck %s -// RUN: llvm-objdump -s --triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=CHECK-EXTAB-NEXT %s +// RUN: llvm-objdump -s --triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=CHECK-EXTAB %s // Check that the relative R_ARM_PREL31 relocation can access a PLT entry // for when the personality routine is referenced from a shared library. diff --git a/lld/test/ELF/mips-tls-hilo.s b/lld/test/ELF/mips-tls-hilo.s index 6fd2033aac41..9c67f9fe14ba 100644 --- a/lld/test/ELF/mips-tls-hilo.s +++ b/lld/test/ELF/mips-tls-hilo.s @@ -28,16 +28,6 @@ # CHECK-NEXT: ] # CHECK-NOT: Primary GOT -# SO: Relocations [ -# SO-NEXT: ] -# SO: Primary GOT { -# SO: Local entries [ -# SO-NEXT: ] -# SO-NEXT: Global entries [ -# SO-NEXT: ] -# SO-NEXT: Number of TLS and multi-GOT entries: 0 -# SO-NEXT: } - .text .globl __start .type __start,@function diff --git a/lld/test/ELF/ppc32-reloc-rel.s b/lld/test/ELF/ppc32-reloc-rel.s index b89e0b43cb78..d13ebdb7997f 100644 --- a/lld/test/ELF/ppc32-reloc-rel.s +++ b/lld/test/ELF/ppc32-reloc-rel.s @@ -6,6 +6,7 @@ # RUN: llvm-mc -filetype=obj -triple=powerpcle %s -o %t.le.o # RUN: ld.lld %t.le.o -o %t # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s +# RUN: llvm-objdump -s %t | FileCheck %s --check-prefix=HEX .section .R_PPC_REL14,"ax",@progbits beq 1f @@ -23,7 +24,7 @@ .long 1f - . 1: # HEX-LABEL: section .R_PPC_REL32: -# HEX-NEXT: 10010008 00000004 +# HEX-NEXT: 04000000 .section .R_PPC_PLTREL24,"ax",@progbits b 1f@PLT+32768 diff --git a/lld/test/ELF/ppc64-pcrel-call-to-extern.s b/lld/test/ELF/ppc64-pcrel-call-to-extern.s index e5846e80ce23..de05b733e175 100644 --- a/lld/test/ELF/ppc64-pcrel-call-to-extern.s +++ b/lld/test/ELF/ppc64-pcrel-call-to-extern.s @@ -73,9 +73,7 @@ ## DT_PLTGOT points to .plt # SEC: .plt NOBITS 0000000010030168 040168 000028 00 WA 0 0 8 -# SEC-OG: .plt NOBITS 0000000010030158 040158 000028 00 WA 0 0 8 # SEC: 0x0000000000000003 (PLTGOT) 0x10030168 -# SEC-OG: 0x0000000000000003 (PLTGOT) 0x10030168 ## DT_PLTGOT points to .plt # SEC-NOP10: .plt NOBITS 0000000010030168 040168 000028 00 WA 0 0 8 @@ -86,11 +84,8 @@ ## Check that we emit 3 R_PPC64_JMP_SLOT in .rela.plt. # REL: .rela.plt { # REL-NEXT: 0x10030178 R_PPC64_JMP_SLOT callee_global_stother0 0x0 -# REL-NEXT-OG: 0x10030168 R_PPC64_JMP_SLOT callee_global_stother0 0x0 # REL-NEXT: 0x10030180 R_PPC64_JMP_SLOT callee_global_stother1 0x0 -# REL-NEXT-OG: 0x10030170 R_PPC64_JMP_SLOT callee_global_stother1 0x0 # REL-NEXT: 0x10030188 R_PPC64_JMP_SLOT callee_global_TOC 0x0 -# REL-NEXT-OG: 0x10030178 R_PPC64_JMP_SLOT callee_global_TOC 0x0 # REL-NEXT: } # REL-NOP10: .rela.plt { diff --git a/lld/test/ELF/ppc64-toc-relax-ifunc.s b/lld/test/ELF/ppc64-toc-relax-ifunc.s index 9fb1bf0023b6..00a63c7e5b67 100644 --- a/lld/test/ELF/ppc64-toc-relax-ifunc.s +++ b/lld/test/ELF/ppc64-toc-relax-ifunc.s @@ -4,7 +4,7 @@ # RUN: echo '.globl ifunc; .type ifunc, %gnu_indirect_function; ifunc:' | \ # RUN: llvm-mc -filetype=obj -triple=powerpc64le - -o %t1.o # RUN: ld.lld %t.o %t1.o -o %t -# RUN: llvm-readelf -S -s %t | FileCheck --check-prefix=SEC %s +# RUN: llvm-readelf -Ssr %t | FileCheck --check-prefix=SEC %s # RUN: llvm-readelf -x .toc %t | FileCheck --check-prefix=HEX %s # RUN: llvm-objdump -d %t | FileCheck --check-prefix=DIS %s @@ -13,18 +13,15 @@ ## still perform toc-indirect to toc-relative relaxation because the distance ## to the address of the canonical PLT is fixed. -# SEC: .text PROGBITS 00000000100101e0 -# SEC: .plt NOBITS 0000000010030200 -# SEC: 00000000100101e8 0 FUNC GLOBAL DEFAULT 3 ifunc +# SEC: .text PROGBITS [[#%x,TEXT:]] +# SEC: .plt NOBITS [[#%x,PLT:]] +# SEC: {{0*}}[[#PLT]] {{.+}} R_PPC64_IRELATIVE [[#TEXT+8]] +# SEC: {{0*}}[[#TEXT+8]] 0 FUNC GLOBAL DEFAULT 3 ifunc ## .toc[0] stores the address of the canonical PLT. # HEX: section '.toc': # HEX-NEXT: 0x100201f8 e8010110 00000000 -# REL: .rela.dyn { -# REL-NEXT: 0x100301f8 R_PPC64_IRELATIVE - 0x100101e8 -# REL-NEXT: } - # DIS: addi 3, 3, addis 3, 2, .toc@toc@ha diff --git a/lld/test/ELF/riscv-gp.s b/lld/test/ELF/riscv-gp.s index 29411d19b019..e82e36ee9a7a 100644 --- a/lld/test/ELF/riscv-gp.s +++ b/lld/test/ELF/riscv-gp.s @@ -16,10 +16,6 @@ # SEC64: [ [[#SDATA:]]] .sdata PROGBITS {{0*}}000032e0 # SEC64: {{0*}}00003ae0 0 NOTYPE GLOBAL DEFAULT [[#SDATA]] __global_pointer$ -## __global_pointer$ - 0x1000 = 4096*3-2048 -# DIS: 1000: auipc gp, 3 -# DIS-NEXT: addi gp, gp, -2048 - # ERR: error: relocation R_RISCV_PCREL_HI20 cannot be used against symbol '__global_pointer$'; recompile with -fPIC ## -r mode does not define __global_pointer$. -- GitLab From 0585eed9409c1362f7deaabc42c1d3c3f55c4b6c Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Wed, 15 May 2024 15:44:05 -0700 Subject: [PATCH 424/578] [lldb-dap] Support publishing to the VSCode market place (#92320) Update the publisher and add a publish script that we can use from Github actions. --- lldb/tools/lldb-dap/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index 2e8ad074256b..aeb24445551c 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -2,7 +2,7 @@ "name": "lldb-dap", "displayName": "LLDB DAP", "version": "0.2.0", - "publisher": "llvm", + "publisher": "llvm-vs-code-extensions", "homepage": "https://lldb.llvm.org", "description": "LLDB debugging from VSCode", "license": "Apache 2.0 License with LLVM exceptions", @@ -42,6 +42,7 @@ "watch": "tsc -watch -p ./", "format": "npx prettier './src-ts/' --write", "package": "vsce package --out ./out/lldb-dap.vsix", + "publish": "vsce publish", "vscode-uninstall": "code --uninstall-extension llvm.lldb-dap", "vscode-install": "code --install-extension ./out/lldb-dap.vsix" }, -- GitLab From e00a3ccf43563209b71c5b68f56d83f4052dca63 Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 15 May 2024 15:44:37 -0700 Subject: [PATCH 425/578] [flang] New -fdebug-unparse-with-modules option (#91660) This option is a compilation action that parses a source file and performs semantic analysis on it, like the existing -fdebug-unparse option does. Its output, however, is preceded by the effective contents of all of the non-intrinsic modules on which it depends but does not define, transitively preceded by the closure of all of those modules' dependencies. The output from this option is therefore the analyzed parse tree for a source file encapsulated with all of its non-intrinsic module dependencies. This output may be useful for extracting code from large applications for use as an attachment to a bug report, or as input to a test case reduction tool for problem isolation. --- clang/include/clang/Driver/Options.td | 4 +- .../include/flang/Frontend/FrontendActions.h | 4 ++ .../include/flang/Frontend/FrontendOptions.h | 4 ++ .../flang/Semantics/unparse-with-symbols.h | 4 ++ flang/lib/Frontend/CompilerInvocation.cpp | 3 ++ flang/lib/Frontend/FrontendActions.cpp | 9 +++++ .../ExecuteCompilerInvocation.cpp | 2 + flang/lib/Semantics/mod-file.cpp | 20 +++++++++- flang/lib/Semantics/mod-file.h | 3 ++ flang/lib/Semantics/unparse-with-symbols.cpp | 38 +++++++++++++++++++ flang/test/Driver/unparse-with-modules.f90 | 34 +++++++++++++++++ 11 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 flang/test/Driver/unparse-with-modules.f90 diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index c54eb543d658..e579f1a0a366 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6647,7 +6647,9 @@ def fdebug_unparse : Flag<["-"], "fdebug-unparse">, Group, DocBrief<[{Run the parser and the semantic checks. Then unparse the parse-tree and output the generated Fortran source file.}]>; def fdebug_unparse_with_symbols : Flag<["-"], "fdebug-unparse-with-symbols">, Group, - HelpText<"Unparse and stop.">; + HelpText<"Unparse with symbols and stop.">; +def fdebug_unparse_with_modules : Flag<["-"], "fdebug-unparse-with-modules">, Group, + HelpText<"Unparse with dependent modules and stop.">; def fdebug_dump_symbols : Flag<["-"], "fdebug-dump-symbols">, Group, HelpText<"Dump symbols after the semantic analysis">; def fdebug_dump_parse_tree : Flag<["-"], "fdebug-dump-parse-tree">, Group, diff --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h index e2e859f3a81b..7823565eb815 100644 --- a/flang/include/flang/Frontend/FrontendActions.h +++ b/flang/include/flang/Frontend/FrontendActions.h @@ -108,6 +108,10 @@ class DebugUnparseWithSymbolsAction : public PrescanAndSemaAction { void executeAction() override; }; +class DebugUnparseWithModulesAction : public PrescanAndSemaAction { + void executeAction() override; +}; + class DebugUnparseAction : public PrescanAndSemaAction { void executeAction() override; }; diff --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h index 06b1318f243b..82ca99672ec6 100644 --- a/flang/include/flang/Frontend/FrontendOptions.h +++ b/flang/include/flang/Frontend/FrontendOptions.h @@ -63,6 +63,10 @@ enum ActionKind { /// Fortran source file DebugUnparseWithSymbols, + /// Parse, run semantics, and output a Fortran source file preceded + /// by all the necessary modules (transitively) + DebugUnparseWithModules, + /// Parse, run semantics and then output symbols from semantics DebugDumpSymbols, diff --git a/flang/include/flang/Semantics/unparse-with-symbols.h b/flang/include/flang/Semantics/unparse-with-symbols.h index d70110245e2b..5e18b3fc3063 100644 --- a/flang/include/flang/Semantics/unparse-with-symbols.h +++ b/flang/include/flang/Semantics/unparse-with-symbols.h @@ -21,8 +21,12 @@ struct Program; } namespace Fortran::semantics { +class SemanticsContext; void UnparseWithSymbols(llvm::raw_ostream &, const parser::Program &, parser::Encoding encoding = parser::Encoding::UTF_8); +void UnparseWithModules(llvm::raw_ostream &, SemanticsContext &, + const parser::Program &, + parser::Encoding encoding = parser::Encoding::UTF_8); } #endif // FORTRAN_SEMANTICS_UNPARSE_WITH_SYMBOLS_H_ diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index db7fd3cccc7a..e8a8c90045d9 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -488,6 +488,9 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, case clang::driver::options::OPT_fdebug_unparse_with_symbols: opts.programAction = DebugUnparseWithSymbols; break; + case clang::driver::options::OPT_fdebug_unparse_with_modules: + opts.programAction = DebugUnparseWithModules; + break; case clang::driver::options::OPT_fdebug_dump_symbols: opts.programAction = DebugDumpSymbols; break; diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 2f65ab6102f4..4341c104a69d 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -477,6 +477,15 @@ void DebugUnparseWithSymbolsAction::executeAction() { reportFatalSemanticErrors(); } +void DebugUnparseWithModulesAction::executeAction() { + auto &parseTree{*getInstance().getParsing().parseTree()}; + CompilerInstance &ci{getInstance()}; + Fortran::semantics::UnparseWithModules( + llvm::outs(), ci.getSemantics().context(), parseTree, + /*encoding=*/Fortran::parser::Encoding::UTF_8); + reportFatalSemanticErrors(); +} + void DebugDumpSymbolsAction::executeAction() { CompilerInstance &ci = this->getInstance(); diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 4cad640562c6..e2cbd5112d6e 100644 --- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -59,6 +59,8 @@ createFrontendAction(CompilerInstance &ci) { return std::make_unique(); case DebugUnparseWithSymbols: return std::make_unique(); + case DebugUnparseWithModules: + return std::make_unique(); case DebugDumpSymbols: return std::make_unique(); case DebugDumpParseTree: diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index e9aebe5b08f2..bb8c6c7567b8 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -132,11 +132,11 @@ static std::string ModFileName(const SourceName &name, // Write the module file for symbol, which must be a module or submodule. void ModFileWriter::Write(const Symbol &symbol) { - auto &module{symbol.get()}; + const auto &module{symbol.get()}; if (module.moduleFileHash()) { return; // already written } - auto *ancestor{module.ancestor()}; + const auto *ancestor{module.ancestor()}; isSubmodule_ = ancestor != nullptr; auto ancestorName{ancestor ? ancestor->GetName().value().ToString() : ""s}; auto path{context_.moduleDirectory() + '/' + @@ -151,6 +151,21 @@ void ModFileWriter::Write(const Symbol &symbol) { const_cast(module).set_moduleFileHash(checkSum); } +void ModFileWriter::WriteClosure(llvm::raw_ostream &out, const Symbol &symbol, + UnorderedSymbolSet &nonIntrinsicModulesWritten) { + if (!symbol.has() || symbol.owner().IsIntrinsicModules() || + !nonIntrinsicModulesWritten.insert(symbol).second) { + return; + } + PutSymbols(DEREF(symbol.scope())); + needsBuf_.clear(); // omit module checksums + auto str{GetAsString(symbol)}; + for (auto depRef : std::move(usedNonIntrinsicModules_)) { + WriteClosure(out, *depRef, nonIntrinsicModulesWritten); + } + out << std::move(str); +} + // Return the entire body of the module file // and clear saved uses, decls, and contains. std::string ModFileWriter::GetAsString(const Symbol &symbol) { @@ -710,6 +725,7 @@ void ModFileWriter::PutUse(const Symbol &symbol) { uses_ << "use,intrinsic::"; } else { uses_ << "use "; + usedNonIntrinsicModules_.insert(module); } uses_ << module.name() << ",only:"; PutGenericName(uses_, symbol); diff --git a/flang/lib/Semantics/mod-file.h b/flang/lib/Semantics/mod-file.h index b4ece4018c05..739add32c2e0 100644 --- a/flang/lib/Semantics/mod-file.h +++ b/flang/lib/Semantics/mod-file.h @@ -35,6 +35,8 @@ class ModFileWriter { public: explicit ModFileWriter(SemanticsContext &context) : context_{context} {} bool WriteAll(); + void WriteClosure(llvm::raw_ostream &, const Symbol &, + UnorderedSymbolSet &nonIntrinsicModulesWritten); private: SemanticsContext &context_; @@ -46,6 +48,7 @@ private: std::string containsBuf_; // Tracks nested DEC structures and fields of that type UnorderedSymbolSet emittedDECStructures_, emittedDECFields_; + UnorderedSymbolSet usedNonIntrinsicModules_; llvm::raw_string_ostream needs_{needsBuf_}; llvm::raw_string_ostream uses_{usesBuf_}; diff --git a/flang/lib/Semantics/unparse-with-symbols.cpp b/flang/lib/Semantics/unparse-with-symbols.cpp index 67016e85777c..c451f885c062 100644 --- a/flang/lib/Semantics/unparse-with-symbols.cpp +++ b/flang/lib/Semantics/unparse-with-symbols.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "flang/Semantics/unparse-with-symbols.h" +#include "mod-file.h" #include "flang/Parser/parse-tree-visitor.h" #include "flang/Parser/parse-tree.h" #include "flang/Parser/unparse.h" @@ -98,4 +99,41 @@ void UnparseWithSymbols(llvm::raw_ostream &out, const parser::Program &program, int indent) { visitor.PrintSymbols(location, out, indent); }}; parser::Unparse(out, program, encoding, false, true, &preStatement); } + +// UnparseWithModules() + +class UsedModuleVisitor { +public: + UnorderedSymbolSet &modulesUsed() { return modulesUsed_; } + UnorderedSymbolSet &modulesDefined() { return modulesDefined_; } + template bool Pre(const T &) { return true; } + template void Post(const T &) {} + void Post(const parser::ModuleStmt &module) { + if (module.v.symbol) { + modulesDefined_.insert(*module.v.symbol); + } + } + void Post(const parser::UseStmt &use) { + if (use.moduleName.symbol) { + modulesUsed_.insert(*use.moduleName.symbol); + } + } + +private: + UnorderedSymbolSet modulesUsed_; + UnorderedSymbolSet modulesDefined_; +}; + +void UnparseWithModules(llvm::raw_ostream &out, SemanticsContext &context, + const parser::Program &program, parser::Encoding encoding) { + UsedModuleVisitor visitor; + parser::Walk(program, visitor); + UnorderedSymbolSet nonIntrinsicModulesWritten{ + std::move(visitor.modulesDefined())}; + ModFileWriter writer{context}; + for (SymbolRef moduleRef : visitor.modulesUsed()) { + writer.WriteClosure(out, *moduleRef, nonIntrinsicModulesWritten); + } + parser::Unparse(out, program, encoding, false, true); +} } // namespace Fortran::semantics diff --git a/flang/test/Driver/unparse-with-modules.f90 b/flang/test/Driver/unparse-with-modules.f90 new file mode 100644 index 000000000000..53997f7804ef --- /dev/null +++ b/flang/test/Driver/unparse-with-modules.f90 @@ -0,0 +1,34 @@ +! RUN: %flang_fc1 -I %S/Inputs/module-dir -fdebug-unparse-with-modules %s | FileCheck %s +module m1 + use iso_fortran_env + use BasicTestModuleTwo + implicit none + type(t2) y + real(real32) x +end + +program test + use m1 + use BasicTestModuleTwo + implicit none + x = 123. + y = t2() +end + +!CHECK-NOT: module iso_fortran_env +!CHECK: module basictestmoduletwo +!CHECK: type::t2 +!CHECK: end type +!CHECK: end +!CHECK: module m1 +!CHECK: use :: iso_fortran_env +!CHECK: implicit none +!CHECK: real(kind=real32) x +!CHECK: end module +!CHECK: program test +!CHECK: use :: m1 +!CHECK: use :: basictestmoduletwo +!CHECK: implicit none +!CHECK: x = 123. +!CHECK: y = t2() +!CHECK: end program -- GitLab From 667d12f86e626173726e87e101626a9060b8d967 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 15 May 2024 18:55:53 -0400 Subject: [PATCH 426/578] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (#91534) We do not deduce template arguments from the exception specification when determining the primary template of a function template specialization or when taking the address of a function template. Therefore, this patch changes `isAtLeastAsSpecializedAs` such that we do not mark template parameters in the exception specification as 'used' during partial ordering (per [temp.deduct.partial] p12) to prevent the following from being ambiguous: ``` template void f(U) noexcept(noexcept(T())); // #1 template void f(T*) noexcept; // #2 template<> void f(int*) noexcept; // currently ambiguous, selects #2 with this patch applied ``` Although there is no corresponding wording in the standard (see core issue filed here https://github.com/cplusplus/CWG/issues/537), this seems to be the intended behavior given the definition of _deduction substitution loci_ in [temp.deduct.general] p7 (and EDG does the same thing). --- clang/docs/ReleaseNotes.rst | 3 + clang/lib/Sema/SemaTemplateDeduction.cpp | 36 +++++++--- .../temp.deduct/temp.deduct.partial/p3.cpp | 72 +++++++++++++++++++ 3 files changed, 103 insertions(+), 8 deletions(-) create mode 100644 clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ae699ebfc603..6f7e54252150 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -713,6 +713,9 @@ Bug Fixes to C++ Support - Correctly treat the compound statement of an ``if consteval`` as an immediate context. Fixes (#GH91509). - When partial ordering alias templates against template template parameters, allow pack expansions when the alias has a fixed-size parameter list. Fixes (#GH62529). +- Clang now ignores template parameters only used within the exception specification of candidate function + templates during partial ordering when deducing template arguments from a function declaration or when + taking the address of a function template. Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 853c0e1b5061..b5d405111fe4 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -5453,7 +5453,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc, // is used. if (DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced, - TDF_None, + TDF_AllowCompatibleFunctionType, /*PartialOrdering=*/true) != TemplateDeductionResult::Success) return false; break; @@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc, switch (TPOC) { case TPOC_Call: for (unsigned I = 0, N = Args2.size(); I != N; ++I) - ::MarkUsedTemplateParameters(S.Context, Args2[I], false, - TemplateParams->getDepth(), - UsedParameters); + ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false, + TemplateParams->getDepth(), UsedParameters); break; case TPOC_Conversion: - ::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false, + ::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), + /*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters); break; case TPOC_Other: - ::MarkUsedTemplateParameters(S.Context, FD2->getType(), false, - TemplateParams->getDepth(), - UsedParameters); + // We do not deduce template arguments from the exception specification + // when determining the primary template of a function template + // specialization or when taking the address of a function template. + // Therefore, we do not mark template parameters in the exception + // specification as used during partial ordering to prevent the following + // from being ambiguous: + // + // template + // void f(U) noexcept(noexcept(T())); // #1 + // + // template + // void f(T*) noexcept; // #2 + // + // template<> + // void f(int*) noexcept; // explicit specialization of #2 + // + // Although there is no corresponding wording in the standard, this seems + // to be the intended behavior given the definition of + // 'deduction substitution loci' in [temp.deduct]. + ::MarkUsedTemplateParameters( + S.Context, + S.Context.getFunctionTypeWithExceptionSpec(FD2->getType(), EST_None), + /*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters); break; } diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp new file mode 100644 index 000000000000..cc1d4ecda2ec --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +template +struct A { }; + +constexpr A a; +constexpr A b; + +constexpr int* x = nullptr; +constexpr short* y = nullptr; + +namespace ExplicitArgs { + template + constexpr int f(U) noexcept(noexcept(T())) { + return 0; + } + + template + constexpr int f(T*) noexcept { + return 1; + } + + template<> + constexpr int f(int*) noexcept { + return 2; + } + + static_assert(f(1) == 0); + static_assert(f(y) == 1); + static_assert(f(x) == 2); + + template + constexpr int g(U*) noexcept(noexcept(T())) { + return 3; + } + + template + constexpr int g(T) noexcept { + return 4; + } + + template<> + constexpr int g(int*) noexcept { + return 5; + } + + static_assert(g(y) == 3); + static_assert(g(1) == 4); + static_assert(g(x) == 5); +} // namespace ExplicitArgs + +namespace DeducedArgs { + template + constexpr int f(T, A) noexcept(B) { + return 0; + } + + template + constexpr int f(T*, A) noexcept(B && B) { + return 1; + } + + template<> + constexpr int f(int*, A) { + return 2; + } + + static_assert(f(x, a) == 0); + static_assert(f(y, a) == 1); + static_assert(f(x, a) == 2); +} // namespace DeducedArgs -- GitLab From 325d1d0b73aa6bff0ce4174b45a7601f6b32a793 Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 15 May 2024 15:58:20 -0700 Subject: [PATCH 427/578] [flang] Fix purity checking for internal subprograms (#91759) ELEMENTAL internal subprograms are pure unless explicitly IMPURE. --- flang/lib/Semantics/check-purity.cpp | 10 +++-- flang/test/Semantics/pure02.f90 | 59 ++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 flang/test/Semantics/pure02.f90 diff --git a/flang/lib/Semantics/check-purity.cpp b/flang/lib/Semantics/check-purity.cpp index 5176390f366b..55a9a2f10738 100644 --- a/flang/lib/Semantics/check-purity.cpp +++ b/flang/lib/Semantics/check-purity.cpp @@ -39,12 +39,16 @@ bool PurityChecker::InPureSubprogram() const { bool PurityChecker::HasPurePrefix( const std::list &prefixes) const { + bool result{false}; for (const parser::PrefixSpec &prefix : prefixes) { - if (std::holds_alternative(prefix.u)) { - return true; + if (std::holds_alternative(prefix.u)) { + return false; + } else if (std::holds_alternative(prefix.u) || + std::holds_alternative(prefix.u)) { + result = true; } } - return false; + return result; } void PurityChecker::Entered( diff --git a/flang/test/Semantics/pure02.f90 b/flang/test/Semantics/pure02.f90 new file mode 100644 index 000000000000..11dc0fd26829 --- /dev/null +++ b/flang/test/Semantics/pure02.f90 @@ -0,0 +1,59 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +pure subroutine s1 + contains + !ERROR: An internal subprogram of a pure subprogram must also be pure + subroutine t1 + end + pure subroutine t2 ! ok + end + elemental subroutine t3(k) ! ok + integer, intent(in) :: k + end + !ERROR: An internal subprogram of a pure subprogram must also be pure + impure elemental subroutine t4(k) + integer, intent(in) :: k + end + !ERROR: An internal subprogram of a pure subprogram must also be pure + elemental impure subroutine t5(k) + integer, intent(in) :: k + end +end + +elemental subroutine s2(j) + integer, intent(in) :: j + contains + !ERROR: An internal subprogram of a pure subprogram must also be pure + subroutine t1 + end + pure subroutine t2 ! ok + end + elemental subroutine t3(k) ! ok + integer, intent(in) :: k + end + !ERROR: An internal subprogram of a pure subprogram must also be pure + impure elemental subroutine t4(k) + integer, intent(in) :: k + end + !ERROR: An internal subprogram of a pure subprogram must also be pure + elemental impure subroutine t5(k) + integer, intent(in) :: k + end +end + +impure elemental subroutine s3(j) + integer, intent(in) :: j + contains + subroutine t1 + end + pure subroutine t2 + end + elemental subroutine t3(k) + integer, intent(in) :: k + end + impure elemental subroutine t4(k) + integer, intent(in) :: k + end + elemental impure subroutine t5(k) + integer, intent(in) :: k + end +end -- GitLab From c227bf1b217598066acd32de8c9a75c2e0928f89 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Wed, 15 May 2024 20:01:17 -0300 Subject: [PATCH 428/578] [clang] Create new warning group for deprecation of '-fno-relaxed-template-template-args' (#92324) This allows the warning to be disabled in isolation, as it helps when treating them as errors. --- clang/docs/ReleaseNotes.rst | 3 ++- clang/include/clang/Basic/DiagnosticDriverKinds.td | 3 +++ clang/include/clang/Basic/DiagnosticGroups.td | 2 ++ clang/lib/Driver/ToolChains/Clang.cpp | 10 +++++++--- clang/test/Driver/frelaxed-template-template-args.cpp | 4 +++- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6f7e54252150..089a85c8cb36 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -51,7 +51,8 @@ C++ Specific Potentially Breaking Changes - The behavior controlled by the `-frelaxed-template-template-args` flag is now on by default, and the flag is deprecated. Until the flag is finally removed, it's negative spelling can be used to obtain compatibility with previous - versions of clang. + versions of clang. The deprecation warning for the negative spelling can be + disabled with `-Wno-deprecated-no-relaxed-template-template-args`. - Clang now rejects pointer to member from parenthesized expression in unevaluated context such as ``decltype(&(foo::bar))``. (#GH40906). diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 9781fcaa4ff5..9d97a75f696f 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -436,6 +436,9 @@ def warn_drv_clang_unsupported : Warning< "the clang compiler does not support '%0'">; def warn_drv_deprecated_arg : Warning< "argument '%0' is deprecated%select{|, use '%2' instead}1">, InGroup; +def warn_drv_deprecated_arg_no_relaxed_template_template_args : Warning< + "argument '-fno-relaxed-template-template-args' is deprecated">, + InGroup; def warn_drv_deprecated_custom : Warning< "argument '%0' is deprecated, %1">, InGroup; def warn_drv_assuming_mfloat_abi_is : Warning< diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 2beb1d45124b..4cb4f3d999f7 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -104,6 +104,7 @@ def EnumConversion : DiagGroup<"enum-conversion", [EnumEnumConversion, EnumFloatConversion, EnumCompareConditional]>; +def DeprecatedNoRelaxedTemplateTemplateArgs : DiagGroup<"deprecated-no-relaxed-template-template-args">; def ObjCSignedCharBoolImplicitIntConversion : DiagGroup<"objc-signed-char-bool-implicit-int-conversion">; def Shorten64To32 : DiagGroup<"shorten-64-to-32">; @@ -228,6 +229,7 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAnonEnumEnumConversion, DeprecatedLiteralOperator, DeprecatedPragma, DeprecatedRegister, + DeprecatedNoRelaxedTemplateTemplateArgs, DeprecatedThisCapture, DeprecatedType, DeprecatedVolatile, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 42feb1650574..c3e6d563f3bd 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7253,10 +7253,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_frelaxed_template_template_args, options::OPT_fno_relaxed_template_template_args)) { - D.Diag(diag::warn_drv_deprecated_arg) - << A->getAsString(Args) << /*hasReplacement=*/false; - if (A->getOption().matches(options::OPT_fno_relaxed_template_template_args)) + if (A->getOption().matches( + options::OPT_fno_relaxed_template_template_args)) { + D.Diag(diag::warn_drv_deprecated_arg_no_relaxed_template_template_args); CmdArgs.push_back("-fno-relaxed-template-template-args"); + } else { + D.Diag(diag::warn_drv_deprecated_arg) + << A->getAsString(Args) << /*hasReplacement=*/false; + } } // -fsized-deallocation is off by default, as it is an ABI-breaking change for diff --git a/clang/test/Driver/frelaxed-template-template-args.cpp b/clang/test/Driver/frelaxed-template-template-args.cpp index 57fc4e3da6e5..7a7fd6f0bbc8 100644 --- a/clang/test/Driver/frelaxed-template-template-args.cpp +++ b/clang/test/Driver/frelaxed-template-template-args.cpp @@ -1,7 +1,9 @@ // RUN: %clang -fsyntax-only -### %s 2>&1 | FileCheck --check-prefix=CHECK-DEF %s // RUN: %clang -fsyntax-only -frelaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-ON %s // RUN: %clang -fsyntax-only -fno-relaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-OFF %s +// RUN: %clang -fsyntax-only -fno-relaxed-template-template-args -Wno-deprecated-no-relaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-DIS --allow-empty %s // CHECK-DEF-NOT: "-cc1"{{.*}} "-fno-relaxed-template-template-args" // CHECK-ON: warning: argument '-frelaxed-template-template-args' is deprecated [-Wdeprecated] -// CHECK-OFF: warning: argument '-fno-relaxed-template-template-args' is deprecated [-Wdeprecated] +// CHECK-OFF: warning: argument '-fno-relaxed-template-template-args' is deprecated [-Wdeprecated-no-relaxed-template-template-args] +// CHECK-DIS-NOT: warning: argument '-fno-relaxed-template-template-args' is deprecated -- GitLab From 7605ad8a2f95e3b37de83e7fb3d320efc74e0ccc Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 15 May 2024 16:08:06 -0700 Subject: [PATCH 429/578] [flang] Always check procedure characterizability (#92008) When a procedure is defined with a subprogram but never referenced in a compilation unit, it may not be characterized until lowering, and any errors in characterization then may crash the compiler. So always ensure that procedure definitions are characterizable in declaration checking. Fixes https://github.com/llvm/llvm-project/issues/91845. --- flang/lib/Semantics/check-declarations.cpp | 9 +++++++++ flang/lib/Semantics/resolve-names.cpp | 3 +-- flang/test/Semantics/entry01.f90 | 2 ++ flang/test/Semantics/resolve102.f90 | 23 +++++----------------- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index ce7870b8d54e..8d17989ac279 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -1357,6 +1357,15 @@ bool CheckHelper::IsResultOkToDiffer(const FunctionResult &result) { void CheckHelper::CheckSubprogram( const Symbol &symbol, const SubprogramDetails &details) { + // Evaluate a procedure definition's characteristics to flush out + // any errors that analysis might expose, in case this subprogram hasn't + // had any calls in this compilation unit that would have validated them. + if (!context_.HasError(symbol) && !details.isDummy() && + !details.isInterface() && !details.stmtFunction()) { + if (!Procedure::Characterize(symbol, foldingContext_)) { + context_.SetError(symbol); + } + } if (const Symbol *iface{FindSeparateModuleSubprogramInterface(&symbol)}) { SubprogramMatchHelper{*this}.Check(symbol, *iface); } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index e2875081b732..5626f2a8be97 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -5013,8 +5013,7 @@ bool DeclarationVisitor::HasCycle( if (procsInCycle.count(*interface) > 0) { for (const auto &procInCycle : procsInCycle) { Say(procInCycle->name(), - "The interface for procedure '%s' is recursively " - "defined"_err_en_US, + "The interface for procedure '%s' is recursively defined"_err_en_US, procInCycle->name()); context().SetError(*procInCycle); } diff --git a/flang/test/Semantics/entry01.f90 b/flang/test/Semantics/entry01.f90 index 970cd109921a..765b18c2e81a 100644 --- a/flang/test/Semantics/entry01.f90 +++ b/flang/test/Semantics/entry01.f90 @@ -83,6 +83,7 @@ function ifunc() !ERROR: 'ibad1' is already declared in this scoping unit entry ibad1() result(ibad1res) ! C1570 !ERROR: 'ibad2' is already declared in this scoping unit + !ERROR: Procedure 'ibad2' is referenced before being sufficiently defined in a context where it must be so entry ibad2() !ERROR: ENTRY in a function may not have an alternate return dummy argument entry ibadalt(*) ! C1573 @@ -91,6 +92,7 @@ function ifunc() entry iok() !ERROR: Explicit RESULT('iok') of function 'isameres2' cannot have the same name as a distinct ENTRY into the same scope entry isameres2() result(iok) ! C1574 + !ERROR: Procedure 'iok2' is referenced before being sufficiently defined in a context where it must be so !ERROR: Explicit RESULT('iok2') of function 'isameres3' cannot have the same name as a distinct ENTRY into the same scope entry isameres3() result(iok2) ! C1574 !ERROR: 'iok2' is already declared in this scoping unit diff --git a/flang/test/Semantics/resolve102.f90 b/flang/test/Semantics/resolve102.f90 index 8f6e2246a57e..33cf6fa245ea 100644 --- a/flang/test/Semantics/resolve102.f90 +++ b/flang/test/Semantics/resolve102.f90 @@ -4,17 +4,12 @@ !ERROR: Procedure 'sub' is recursively defined. Procedures in the cycle: 'sub', 'p2' subroutine sub(p2) PROCEDURE(sub) :: p2 - - call sub() end subroutine subroutine circular - !ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: 'p', 'sub', 'p2' procedure(sub) :: p - - call p(sub) - contains + !ERROR: Procedure 'sub' is recursively defined. Procedures in the cycle: 'p', 'sub', 'p2' subroutine sub(p2) procedure(p) :: p2 end subroutine @@ -41,11 +36,10 @@ end subroutine subroutine mutual Procedure(sub1) :: p - - Call p(sub) - contains !ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'p', 'sub1', 'arg' + !ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'sub1', 'arg', 'sub', 'p2' + !ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'sub1', 'arg' Subroutine sub1(arg) procedure(sub1) :: arg End Subroutine @@ -57,15 +51,14 @@ End subroutine subroutine mutual1 Procedure(sub1) :: p - - Call p(sub) - contains !ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'p', 'sub1', 'arg', 'sub', 'p2' + !ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'sub1', 'arg', 'sub', 'p2' Subroutine sub1(arg) procedure(sub) :: arg End Subroutine + !ERROR: Procedure 'sub' is recursively defined. Procedures in the cycle: 'sub1', 'arg', 'sub', 'p2' Subroutine sub(p2) Procedure(sub1) :: p2 End Subroutine @@ -76,8 +69,6 @@ subroutine twoCycle !ERROR: The interface for procedure 'p2' is recursively defined procedure(p1) p2 procedure(p2) p1 - call p1 - call p2 end subroutine subroutine threeCycle @@ -87,9 +78,6 @@ subroutine threeCycle !ERROR: The interface for procedure 'p3' is recursively defined procedure(p2) p3 procedure(p3) p1 - call p1 - call p2 - call p3 end subroutine module mutualSpecExprs @@ -118,4 +106,3 @@ module genericInSpec ifunc = x end end - -- GitLab From 463f58a564a8d136b3e5d56d23bb86b99ab75245 Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 15 May 2024 16:18:47 -0700 Subject: [PATCH 430/578] [flang] Further work on relaxing BIND(C) enforcement (#92029) When a BIND(C) interface or subprogram has a dummy argument whose derived type is not BIND(C) but meets the constraints and requirements of a BIND(C) type, accept it with a warning. --- flang/lib/Semantics/check-declarations.cpp | 16 +++++--- flang/test/Semantics/bind-c15.f90 | 45 ++++++++++++++++++++++ 2 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 flang/test/Semantics/bind-c15.f90 diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 8d17989ac279..527a1a9539aa 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -2891,7 +2891,8 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType( } else { bool interoperableParent{true}; if (parent->symbol()) { - auto bad{WhyNotInteroperableDerivedType(*parent->symbol(), false)}; + auto bad{WhyNotInteroperableDerivedType( + *parent->symbol(), /*isError=*/false)}; if (bad.AnyFatalError()) { auto &msg{msgs.Say(symbol.name(), "The parent of an interoperable type is not interoperable"_err_en_US)}; @@ -2981,6 +2982,9 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType( } } } + if (msgs.AnyFatalError()) { + examinedByWhyNotInteroperableDerivedType_.erase(symbol); + } return msgs; } @@ -3068,8 +3072,8 @@ void CheckHelper::CheckBindC(const Symbol &symbol) { } context_.SetError(symbol); } else if (auto bad{WhyNotInteroperableDerivedType( - derived->typeSymbol(), false)}; - !bad.empty()) { + derived->typeSymbol(), /*isError=*/false)}; + bad.AnyFatalError()) { if (auto *msg{messages_.Say(symbol.name(), "The derived type of an interoperable object must be interoperable, but is not"_err_en_US)}) { msg->Attach( @@ -3077,7 +3081,9 @@ void CheckHelper::CheckBindC(const Symbol &symbol) { bad.AttachTo(*msg, parser::Severity::None); } context_.SetError(symbol); - } else { + } else if (context_.ShouldWarn( + common::LanguageFeature::NonBindCInteroperability) && + !InModuleFile()) { if (auto *msg{messages_.Say(symbol.name(), "The derived type of an interoperable object should be BIND(C)"_warn_en_US)}) { msg->Attach(derived->typeSymbol().name(), "Non-BIND(C) type"_en_US); @@ -3151,7 +3157,7 @@ void CheckHelper::CheckBindC(const Symbol &symbol) { } } } else if (symbol.has()) { - if (auto msgs{WhyNotInteroperableDerivedType(symbol, false)}; + if (auto msgs{WhyNotInteroperableDerivedType(symbol, /*isError=*/false)}; !msgs.empty()) { bool anyFatal{msgs.AnyFatalError()}; if (msgs.AnyFatalError() || diff --git a/flang/test/Semantics/bind-c15.f90 b/flang/test/Semantics/bind-c15.f90 new file mode 100644 index 000000000000..9aaad52cc0e0 --- /dev/null +++ b/flang/test/Semantics/bind-c15.f90 @@ -0,0 +1,45 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic + +module m + type, bind(c) :: explicit_bind_c + real a + end type + type :: interoperable1 + type(explicit_bind_c) a + end type + type, extends(interoperable1) :: interoperable2 + real b + end type + type :: non_interoperable1 + real, allocatable :: a + end type + type :: non_interoperable2 + type(non_interoperable1) b + end type + interface + subroutine sub_bind_c_1(x_bind_c) bind(c) + import explicit_bind_c + type(explicit_bind_c), intent(in) :: x_bind_c + end + subroutine sub_bind_c_2(x_interop1) bind(c) + import interoperable1 + !WARNING: The derived type of an interoperable object should be BIND(C) + type(interoperable1), intent(in) :: x_interop1 + end + subroutine sub_bind_c_3(x_interop2) bind(c) + import interoperable2 + !WARNING: The derived type of an interoperable object should be BIND(C) + type(interoperable2), intent(in) :: x_interop2 + end + subroutine sub_bind_c_4(x_non_interop1) bind(c) + import non_interoperable1 + !ERROR: The derived type of an interoperable object must be interoperable, but is not + type(non_interoperable1), intent(in) :: x_non_interop1 + end + subroutine sub_bind_c_5(x_non_interop2) bind(c) + import non_interoperable2 + !ERROR: The derived type of an interoperable object must be interoperable, but is not + type(non_interoperable2), intent(in) :: x_non_interop2 + end + end interface +end -- GitLab From 5bbb63bd6d6d3929de643fcd88babbda20c97b69 Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 15 May 2024 16:28:58 -0700 Subject: [PATCH 431/578] [flang] Parse REDUCE clauses in !$CUF KERNEL DO (#92154) A !$CUF KERNEL DO directive is allowed to have advisory REDUCE clauses similar to those in OpenACC and DO CONCURRENT. Parse and represent them. Semantic validation will follow. --- flang/include/flang/Parser/dump-parse-tree.h | 1 + flang/include/flang/Parser/parse-tree.h | 18 ++++- flang/lib/Parser/executable-parsers.cpp | 23 +++++-- flang/lib/Parser/openacc-parsers.cpp | 6 +- flang/lib/Parser/unparse.cpp | 36 +++++++++- flang/lib/Semantics/check-cuda.cpp | 44 ++++++++++++ flang/lib/Semantics/resolve-directives.h | 2 +- flang/lib/Semantics/resolve-names.cpp | 2 +- flang/test/Parser/cuf-sanity-common | 7 ++ flang/test/Parser/cuf-sanity-unparse.CUF | 6 ++ flang/test/Semantics/reduce.cuf | 72 ++++++++++++++++++++ 11 files changed, 199 insertions(+), 18 deletions(-) create mode 100644 flang/test/Semantics/reduce.cuf diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 477d391277ee..68ae50c312cd 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -236,6 +236,7 @@ public: NODE(parser, CUFKernelDoConstruct) NODE(CUFKernelDoConstruct, StarOrExpr) NODE(CUFKernelDoConstruct, Directive) + NODE(parser, CUFReduction) NODE(parser, CycleStmt) NODE(parser, DataComponentDefStmt) NODE(parser, DataIDoObject) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index c06354458379..0a40aa8b8f61 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4303,12 +4303,23 @@ struct OpenACCConstruct { }; // CUF-kernel-do-construct -> -// !$CUF KERNEL DO [ (scalar-int-constant-expr) ] <<< grid, block [, stream] -// >>> do-construct +// !$CUF KERNEL DO [ (scalar-int-constant-expr) ] +// <<< grid, block [, stream] >>> +// [ cuf-reduction... ] +// do-construct // star-or-expr -> * | scalar-int-expr // grid -> * | scalar-int-expr | ( star-or-expr-list ) // block -> * | scalar-int-expr | ( star-or-expr-list ) // stream -> 0, scalar-int-expr | STREAM = scalar-int-expr +// cuf-reduction -> [ REDUCE | REDUCTION ] ( +// acc-reduction-op : scalar-variable-list ) + +struct CUFReduction { + TUPLE_CLASS_BOILERPLATE(CUFReduction); + using Operator = AccReductionOperator; + std::tuple>> t; +}; + struct CUFKernelDoConstruct { TUPLE_CLASS_BOILERPLATE(CUFKernelDoConstruct); WRAPPER_CLASS(StarOrExpr, std::optional); @@ -4316,7 +4327,8 @@ struct CUFKernelDoConstruct { TUPLE_CLASS_BOILERPLATE(Directive); CharBlock source; std::tuple, std::list, - std::list, std::optional> + std::list, std::optional, + std::list> t; }; std::tuple> t; diff --git a/flang/lib/Parser/executable-parsers.cpp b/flang/lib/Parser/executable-parsers.cpp index 07a570bd61e9..382a59341687 100644 --- a/flang/lib/Parser/executable-parsers.cpp +++ b/flang/lib/Parser/executable-parsers.cpp @@ -538,25 +538,34 @@ TYPE_CONTEXT_PARSER("UNLOCK statement"_en_US, construct("UNLOCK (" >> lockVariable, defaulted("," >> nonemptyList(statOrErrmsg)) / ")")) -// CUF-kernel-do-construct -> CUF-kernel-do-directive do-construct -// CUF-kernel-do-directive -> -// !$CUF KERNEL DO [ (scalar-int-constant-expr) ] <<< grid, block [, stream] -// >>> do-construct +// CUF-kernel-do-construct -> +// !$CUF KERNEL DO [ (scalar-int-constant-expr) ] +// <<< grid, block [, stream] >>> +// [ cuf-reduction... ] +// do-construct // star-or-expr -> * | scalar-int-expr // grid -> * | scalar-int-expr | ( star-or-expr-list ) // block -> * | scalar-int-expr | ( star-or-expr-list ) -// stream -> ( 0, | STREAM = ) scalar-int-expr +// stream -> 0, scalar-int-expr | STREAM = scalar-int-expr +// cuf-reduction -> [ REDUCTION | REDUCE ] ( +// acc-reduction-op : scalar-variable-list ) + constexpr auto starOrExpr{construct( "*" >> pure>() || applyFunction(presentOptional, scalarIntExpr))}; constexpr auto gridOrBlock{parenthesized(nonemptyList(starOrExpr)) || applyFunction(singletonList, starOrExpr)}; + +TYPE_PARSER(("REDUCTION"_tok || "REDUCE"_tok) >> + parenthesized(construct(Parser{}, + ":" >> nonemptyList(scalar(variable))))) + TYPE_PARSER(sourced(beginDirective >> "$CUF KERNEL DO"_tok >> construct( maybe(parenthesized(scalarIntConstantExpr)), "<<<" >> gridOrBlock, "," >> gridOrBlock, - maybe((", 0 ,"_tok || ", STREAM ="_tok) >> scalarIntExpr) / ">>>" / - endDirective))) + maybe((", 0 ,"_tok || ", STREAM ="_tok) >> scalarIntExpr) / ">>>", + many(Parser{}) / endDirective))) TYPE_CONTEXT_PARSER("!$CUF KERNEL DO construct"_en_US, extension(construct( Parser{}, diff --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp index 946b33d0084a..3d919e29a248 100644 --- a/flang/lib/Parser/openacc-parsers.cpp +++ b/flang/lib/Parser/openacc-parsers.cpp @@ -19,9 +19,9 @@ // OpenACC Directives and Clauses namespace Fortran::parser { -constexpr auto startAccLine = skipStuffBeforeStatement >> - ("!$ACC "_sptok || "C$ACC "_sptok || "*$ACC "_sptok); -constexpr auto endAccLine = space >> endOfLine; +constexpr auto startAccLine{skipStuffBeforeStatement >> + ("!$ACC "_sptok || "C$ACC "_sptok || "*$ACC "_sptok)}; +constexpr auto endAccLine{space >> endOfLine}; // Autogenerated clauses parser. Information is taken from ACC.td and the // parser is generated by tablegen. diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 3398b395f198..1639e900903f 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2705,7 +2705,6 @@ public: void Unparse(const CLASS::ENUM &x) { Word(CLASS::EnumToString(x)); } WALK_NESTED_ENUM(AccDataModifier, Modifier) WALK_NESTED_ENUM(AccessSpec, Kind) // R807 - WALK_NESTED_ENUM(AccReductionOperator, Operator) WALK_NESTED_ENUM(common, TypeParamAttr) // R734 WALK_NESTED_ENUM(common, CUDADataAttr) // CUDA WALK_NESTED_ENUM(common, CUDASubprogramAttrs) // CUDA @@ -2736,6 +2735,31 @@ public: WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type WALK_NESTED_ENUM(OmpOrderModifier, Kind) // OMP order-modifier #undef WALK_NESTED_ENUM + void Unparse(const AccReductionOperator::Operator x) { + switch (x) { + case AccReductionOperator::Operator::Plus: + Word("+"); + break; + case AccReductionOperator::Operator::Multiply: + Word("*"); + break; + case AccReductionOperator::Operator::And: + Word(".AND."); + break; + case AccReductionOperator::Operator::Or: + Word(".OR."); + break; + case AccReductionOperator::Operator::Eqv: + Word(".EQV."); + break; + case AccReductionOperator::Operator::Neqv: + Word(".NEQV."); + break; + default: + Word(AccReductionOperator::EnumToString(x)); + break; + } + } void Unparse(const CUFKernelDoConstruct::StarOrExpr &x) { if (x.v) { @@ -2768,13 +2792,19 @@ public: if (const auto &stream{std::get<3>(x.t)}) { Word(",STREAM="), Walk(*stream); } - Word(">>>\n"); + Word(">>>"); + Walk(" ", std::get>(x.t), " "); + Word("\n"); } - void Unparse(const CUFKernelDoConstruct &x) { Walk(std::get(x.t)); Walk(std::get>(x.t)); } + void Unparse(const CUFReduction &x) { + Word("REDUCE("); + Walk(std::get(x.t)); + Walk(":", std::get>>(x.t), ",", ")"); + } void Done() const { CHECK(indent_ == 0); } diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp index 96ab90239263..45217ed2e3cc 100644 --- a/flang/lib/Semantics/check-cuda.cpp +++ b/flang/lib/Semantics/check-cuda.cpp @@ -463,6 +463,46 @@ static int DoConstructTightNesting( return 1; } +static void CheckReduce( + SemanticsContext &context, const parser::CUFReduction &reduce) { + auto op{std::get(reduce.t).v}; + for (const auto &var : + std::get>>(reduce.t)) { + if (const auto &typedExprPtr{var.thing.typedExpr}; + typedExprPtr && typedExprPtr->v) { + const auto &expr{*typedExprPtr->v}; + if (auto type{expr.GetType()}) { + auto cat{type->category()}; + bool isOk{false}; + switch (op) { + case parser::AccReductionOperator::Operator::Plus: + case parser::AccReductionOperator::Operator::Multiply: + case parser::AccReductionOperator::Operator::Max: + case parser::AccReductionOperator::Operator::Min: + isOk = cat == TypeCategory::Integer || cat == TypeCategory::Real; + break; + case parser::AccReductionOperator::Operator::Iand: + case parser::AccReductionOperator::Operator::Ior: + case parser::AccReductionOperator::Operator::Ieor: + isOk = cat == TypeCategory::Integer; + break; + case parser::AccReductionOperator::Operator::And: + case parser::AccReductionOperator::Operator::Or: + case parser::AccReductionOperator::Operator::Eqv: + case parser::AccReductionOperator::Operator::Neqv: + isOk = cat == TypeCategory::Logical; + break; + } + if (!isOk) { + context.Say(var.thing.GetSource(), + "!$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type %s"_err_en_US, + type->AsFortran()); + } + } + } + } +} + void CUDAChecker::Enter(const parser::CUFKernelDoConstruct &x) { auto source{std::get(x.t).source}; const auto &directive{std::get(x.t)}; @@ -489,6 +529,10 @@ void CUDAChecker::Enter(const parser::CUFKernelDoConstruct &x) { if (innerBlock) { DeviceContextChecker{context_}.Check(*innerBlock); } + for (const auto &reduce : + std::get>(directive.t)) { + CheckReduce(context_, reduce); + } } void CUDAChecker::Enter(const parser::AssignmentStmt &x) { diff --git a/flang/lib/Semantics/resolve-directives.h b/flang/lib/Semantics/resolve-directives.h index 4aef8ad6c400..5a890c26aa33 100644 --- a/flang/lib/Semantics/resolve-directives.h +++ b/flang/lib/Semantics/resolve-directives.h @@ -21,7 +21,7 @@ class SemanticsContext; // Name resolution for OpenACC and OpenMP directives void ResolveAccParts( - SemanticsContext &, const parser::ProgramUnit &, Scope *topScope = {}); + SemanticsContext &, const parser::ProgramUnit &, Scope *topScope); void ResolveOmpParts(SemanticsContext &, const parser::ProgramUnit &); void ResolveOmpTopLevelParts(SemanticsContext &, const parser::Program &); diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 5626f2a8be97..40eee89de131 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -8940,7 +8940,7 @@ bool ResolveNamesVisitor::Pre(const parser::ProgramUnit &x) { FinishSpecificationParts(root); ResolveExecutionParts(root); FinishExecutionParts(root); - ResolveAccParts(context(), x); + ResolveAccParts(context(), x, /*topScope=*/nullptr); ResolveOmpParts(context(), x); return false; } diff --git a/flang/test/Parser/cuf-sanity-common b/flang/test/Parser/cuf-sanity-common index b097a6aa3004..9d73204e3f5f 100644 --- a/flang/test/Parser/cuf-sanity-common +++ b/flang/test/Parser/cuf-sanity-common @@ -23,12 +23,19 @@ module m end subroutine subroutine test logical isPinned + real a(10), x, y, z !$cuf kernel do(1) <<<*, *, stream = 1>>> do j = 1, 10 end do !$cuf kernel do <<<1, (2, 3), stream = 1>>> do j = 1, 10 end do + !$cuf kernel do <<<*, *>>> reduce(+:x,y) reduce(*:z) + do j = 1, 10 + x = x + a(j) + y = y + a(j) + z = z * a(j) + end do call globalsub<<<1, 2>>> call globalsub<<<1, 2, 3>>> call globalsub<<<1, 2, 3, 4>>> diff --git a/flang/test/Parser/cuf-sanity-unparse.CUF b/flang/test/Parser/cuf-sanity-unparse.CUF index b6921e74fc05..d4be347dd044 100644 --- a/flang/test/Parser/cuf-sanity-unparse.CUF +++ b/flang/test/Parser/cuf-sanity-unparse.CUF @@ -34,6 +34,12 @@ include "cuf-sanity-common" !CHECK: !$CUF KERNEL DO <<<1_4,(2_4,3_4),STREAM=1_4>>> !CHECK: DO j=1_4,10_4 !CHECK: END DO +!CHECK: !$CUF KERNEL DO <<<*,*>>> REDUCE(+:x,y) REDUCE(*:z) +!CHECK: DO j=1_4,10_4 +!CHECK: x=x+a(int(j,kind=8)) +!CHECK: y=y+a(int(j,kind=8)) +!CHECK: z=z*a(int(j,kind=8)) +!CHECK: END DO !CHECK: CALL globalsub<<<1_4,2_4>>>() !CHECK: CALL globalsub<<<1_4,2_4,3_4>>>() !CHECK: CALL globalsub<<<1_4,2_4,3_4,4_4>>>() diff --git a/flang/test/Semantics/reduce.cuf b/flang/test/Semantics/reduce.cuf new file mode 100644 index 000000000000..95ff2e87c09b --- /dev/null +++ b/flang/test/Semantics/reduce.cuf @@ -0,0 +1,72 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +subroutine s(n,m,a,l) + integer, intent(in) :: n + integer, intent(in) :: m(n) + real, intent(in) :: a(n) + logical, intent(in) :: l(n) + integer j, mr + real ar + logical lr +!$cuf kernel do <<<*,*>>> reduce (+:mr,ar) + do j=1,n; mr = mr + m(j); ar = ar + a(j); end do +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type LOGICAL(4) +!$cuf kernel do <<<*,*>>> reduce (+:lr) + do j=1,n; end do +!$cuf kernel do <<<*,*>>> reduce (*:mr,ar) + do j=1,n; mr = mr * m(j); ar = ar * a(j); end do +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type LOGICAL(4) +!$cuf kernel do <<<*,*>>> reduce (*:lr) + do j=1,n; end do +!$cuf kernel do <<<*,*>>> reduce (max:mr,ar) + do j=1,n; mr = max(mr,m(j)); ar = max(ar,a(j)); end do +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type LOGICAL(4) +!$cuf kernel do <<<*,*>>> reduce (max:lr) + do j=1,n; end do +!$cuf kernel do <<<*,*>>> reduce (min:mr,ar) + do j=1,n; mr = min(mr,m(j)); ar = min(ar,a(j)); end do +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type LOGICAL(4) +!$cuf kernel do <<<*,*>>> reduce (min:lr) + do j=1,n; end do +!$cuf kernel do <<<*,*>>> reduce (iand:mr) + do j=1,n; mr = iand(mr,m(j)); end do +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type REAL(4) +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type LOGICAL(4) +!$cuf kernel do <<<*,*>>> reduce (iand:ar,lr) + do j=1,n; end do +!$cuf kernel do <<<*,*>>> reduce (ieor:mr) + do j=1,n; mr = ieor(mr,m(j)); end do +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type REAL(4) +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type LOGICAL(4) +!$cuf kernel do <<<*,*>>> reduce (ieor:ar,lr) + do j=1,n; end do +!$cuf kernel do <<<*,*>>> reduce (ior:mr) + do j=1,n; mr = ior(mr,m(j)); end do +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type REAL(4) +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type LOGICAL(4) +!$cuf kernel do <<<*,*>>> reduce (ior:ar,lr) + do j=1,n; end do +!$cuf kernel do <<<*,*>>> reduce (.and.:lr) + do j=1,n; lr = lr .and. l(j); end do +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type INTEGER(4) +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type REAL(4) +!$cuf kernel do <<<*,*>>> reduce (.and.:mr,ar) + do j=1,n; end do +!$cuf kernel do <<<*,*>>> reduce (.eqv.:lr) + do j=1,n; lr = lr .eqv. l(j); end do +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type INTEGER(4) +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type REAL(4) +!$cuf kernel do <<<*,*>>> reduce (.eqv.:mr,ar) + do j=1,n; end do +!$cuf kernel do <<<*,*>>> reduce (.neqv.:lr) + do j=1,n; lr = lr .neqv. l(j); end do +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type INTEGER(4) +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type REAL(4) +!$cuf kernel do <<<*,*>>> reduce (.neqv.:mr,ar) + do j=1,n; end do +!$cuf kernel do <<<*,*>>> reduce (.or.:lr) + do j=1,n; lr = lr .or. l(j); end do +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type INTEGER(4) +!ERROR: !$CUF KERNEL DO REDUCE operation is not acceptable for a variable with type REAL(4) +!$cuf kernel do <<<*,*>>> reduce (.or.:mr,ar) + do j=1,n; end do +end -- GitLab From 3ddfb6807e905868a3a9df71fa5ea87309181270 Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 15 May 2024 16:41:12 -0700 Subject: [PATCH 432/578] [flang] Prevent crash from unfoldable TRANSFER() (#92282) When the MOLD= argument's type is polymorphic, the type of the result cannot be known at compilation time, so the call cannot be folded even when the SOURCE= is constant. Fixes https://github.com/llvm/llvm-project/issues/92264. --- flang/lib/Evaluate/fold.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/flang/lib/Evaluate/fold.cpp b/flang/lib/Evaluate/fold.cpp index ed8829581998..cf6262d9a7c6 100644 --- a/flang/lib/Evaluate/fold.cpp +++ b/flang/lib/Evaluate/fold.cpp @@ -272,6 +272,7 @@ std::optional> FoldTransfer( } } if (sourceBytes && IsActuallyConstant(*source) && moldType && extents && + !moldType->IsPolymorphic() && (moldLength || moldType->category() != TypeCategory::Character)) { std::size_t elements{ extents->empty() ? 1 : static_cast((*extents)[0])}; -- GitLab From c87b1ca4edefe3c267a20f28eaf79f6b83d36c66 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Wed, 15 May 2024 18:41:25 -0500 Subject: [PATCH 433/578] [InstrProf] Fix bug when clearing traces with samples (#92310) The `--temporal-profile-max-trace-length=0` flag in the `llvm-profdata merge` command is used to remove traces from a profile. There was a bug where traces would not be cleared if the profile was already sampled. This patch fixes that. --- llvm/lib/ProfileData/InstrProfWriter.cpp | 11 ++++++----- llvm/test/tools/llvm-profdata/trace-limit.proftext | 6 +++++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index b61c59aacc0f..c941b9d89df3 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -320,11 +320,8 @@ void InstrProfWriter::addBinaryIds(ArrayRef BIs) { } void InstrProfWriter::addTemporalProfileTrace(TemporalProfTraceTy Trace) { - if (Trace.FunctionNameRefs.size() > MaxTemporalProfTraceLength) - Trace.FunctionNameRefs.resize(MaxTemporalProfTraceLength); - if (Trace.FunctionNameRefs.empty()) - return; - + assert(Trace.FunctionNameRefs.size() <= MaxTemporalProfTraceLength); + assert(!Trace.FunctionNameRefs.empty()); if (TemporalProfTraceStreamSize < TemporalProfTraceReservoirSize) { // Simply append the trace if we have not yet hit our reservoir size limit. TemporalProfTraces.push_back(std::move(Trace)); @@ -341,6 +338,10 @@ void InstrProfWriter::addTemporalProfileTrace(TemporalProfTraceTy Trace) { void InstrProfWriter::addTemporalProfileTraces( SmallVectorImpl &SrcTraces, uint64_t SrcStreamSize) { + for (auto &Trace : SrcTraces) + if (Trace.FunctionNameRefs.size() > MaxTemporalProfTraceLength) + Trace.FunctionNameRefs.resize(MaxTemporalProfTraceLength); + llvm::erase_if(SrcTraces, [](auto &T) { return T.FunctionNameRefs.empty(); }); // Assume that the source has the same reservoir size as the destination to // avoid needing to record it in the indexed profile format. bool IsDestSampled = diff --git a/llvm/test/tools/llvm-profdata/trace-limit.proftext b/llvm/test/tools/llvm-profdata/trace-limit.proftext index cf6edd648b23..e246ee890ba3 100644 --- a/llvm/test/tools/llvm-profdata/trace-limit.proftext +++ b/llvm/test/tools/llvm-profdata/trace-limit.proftext @@ -1,13 +1,17 @@ # RUN: llvm-profdata merge --temporal-profile-max-trace-length=0 %s -o %t.profdata # RUN: llvm-profdata show --temporal-profile-traces %t.profdata | FileCheck %s --check-prefix=NONE +# RUN: llvm-profdata merge --temporal-profile-trace-reservoir-size=2 %s %s %s %s -o %t.profdata +# RUN: llvm-profdata merge --temporal-profile-trace-reservoir-size=2 --temporal-profile-max-trace-length=0 %t.profdata -o %t.profdata +# RUN: llvm-profdata show --temporal-profile-traces %t.profdata | FileCheck %s --check-prefix=NONE + # RUN: llvm-profdata merge --temporal-profile-max-trace-length=2 %s -o %t.profdata # RUN: llvm-profdata show --temporal-profile-traces %t.profdata | FileCheck %s --check-prefixes=CHECK,SOME # RUN: llvm-profdata merge --temporal-profile-max-trace-length=1000 %s -o %t.profdata # RUN: llvm-profdata show --temporal-profile-traces %t.profdata | FileCheck %s --check-prefixes=CHECK,ALL -# NONE: Temporal Profile Traces (samples=0 seen=0): +# NONE: Temporal Profile Traces (samples=0 # CHECK: Temporal Profile Traces (samples=1 seen=1): # SOME: Trace 0 (weight=1 count=2): # ALL: Trace 0 (weight=1 count=3): -- GitLab From c00e012bcf5da384a3e7339dc2e046779b339063 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Wed, 15 May 2024 17:03:09 -0700 Subject: [PATCH 434/578] [ctx_profile] Follow the pattern elsewhere for choosing the block IDs This was an oversight in #91859. Using the subblock ID mechanism other places that use the bitstream APIs (e.g. `BitstreamRemarkSerializer`) use. --- llvm/include/llvm/ProfileData/PGOCtxProfWriter.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h b/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h index 15578c51a495..edcf02c09469 100644 --- a/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h +++ b/llvm/include/llvm/ProfileData/PGOCtxProfWriter.h @@ -13,6 +13,7 @@ #ifndef LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ #define LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_ +#include "llvm/Bitstream/BitCodeEnums.h" #include "llvm/Bitstream/BitstreamWriter.h" #include "llvm/ProfileData/CtxInstrContextNode.h" @@ -20,7 +21,7 @@ namespace llvm { enum PGOCtxProfileRecords { Invalid = 0, Version, Guid, CalleeIndex, Counters }; enum PGOCtxProfileBlockIDs { - ProfileMetadataBlockID = 100, + ProfileMetadataBlockID = bitc::FIRST_APPLICATION_BLOCKID, ContextNodeBlockID = ProfileMetadataBlockID + 1 }; -- GitLab From 772b1b0cb26c66804d0a7e416dc7a5742b7f8db2 Mon Sep 17 00:00:00 2001 From: ChiaHungDuan Date: Wed, 15 May 2024 17:13:08 -0700 Subject: [PATCH 435/578] [scudo] Move the chunk update into functions (#83493) The code paths for mte enabled and disabled were interleaving and which increases the difficulty of reading each path in both source level and assembly level. In this change, we move the parts that they have different logic into functions and minor refactors on the code structure. --- compiler-rt/lib/scudo/standalone/combined.h | 371 ++++++++++++-------- 1 file changed, 221 insertions(+), 150 deletions(-) diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h index 927513dea92d..15a199ae0349 100644 --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -410,133 +410,18 @@ public: reportOutOfMemory(NeededSize); } - const uptr BlockUptr = reinterpret_cast(Block); - const uptr UnalignedUserPtr = BlockUptr + Chunk::getHeaderSize(); - const uptr UserPtr = roundUp(UnalignedUserPtr, Alignment); - - void *Ptr = reinterpret_cast(UserPtr); - void *TaggedPtr = Ptr; - if (LIKELY(ClassId)) { - // We only need to zero or tag the contents for Primary backed - // allocations. We only set tags for primary allocations in order to avoid - // faulting potentially large numbers of pages for large secondary - // allocations. We assume that guard pages are enough to protect these - // allocations. - // - // FIXME: When the kernel provides a way to set the background tag of a - // mapping, we should be able to tag secondary allocations as well. - // - // When memory tagging is enabled, zeroing the contents is done as part of - // setting the tag. - if (UNLIKELY(useMemoryTagging(Options))) { - uptr PrevUserPtr; - Chunk::UnpackedHeader Header; - const uptr BlockSize = PrimaryT::getSizeByClassId(ClassId); - const uptr BlockEnd = BlockUptr + BlockSize; - // If possible, try to reuse the UAF tag that was set by deallocate(). - // For simplicity, only reuse tags if we have the same start address as - // the previous allocation. This handles the majority of cases since - // most allocations will not be more aligned than the minimum alignment. - // - // We need to handle situations involving reclaimed chunks, and retag - // the reclaimed portions if necessary. In the case where the chunk is - // fully reclaimed, the chunk's header will be zero, which will trigger - // the code path for new mappings and invalid chunks that prepares the - // chunk from scratch. There are three possibilities for partial - // reclaiming: - // - // (1) Header was reclaimed, data was partially reclaimed. - // (2) Header was not reclaimed, all data was reclaimed (e.g. because - // data started on a page boundary). - // (3) Header was not reclaimed, data was partially reclaimed. - // - // Case (1) will be handled in the same way as for full reclaiming, - // since the header will be zero. - // - // We can detect case (2) by loading the tag from the start - // of the chunk. If it is zero, it means that either all data was - // reclaimed (since we never use zero as the chunk tag), or that the - // previous allocation was of size zero. Either way, we need to prepare - // a new chunk from scratch. - // - // We can detect case (3) by moving to the next page (if covered by the - // chunk) and loading the tag of its first granule. If it is zero, it - // means that all following pages may need to be retagged. On the other - // hand, if it is nonzero, we can assume that all following pages are - // still tagged, according to the logic that if any of the pages - // following the next page were reclaimed, the next page would have been - // reclaimed as well. - uptr TaggedUserPtr; - if (getChunkFromBlock(BlockUptr, &PrevUserPtr, &Header) && - PrevUserPtr == UserPtr && - (TaggedUserPtr = loadTag(UserPtr)) != UserPtr) { - uptr PrevEnd = TaggedUserPtr + Header.SizeOrUnusedBytes; - const uptr NextPage = roundUp(TaggedUserPtr, getPageSizeCached()); - if (NextPage < PrevEnd && loadTag(NextPage) != NextPage) - PrevEnd = NextPage; - TaggedPtr = reinterpret_cast(TaggedUserPtr); - resizeTaggedChunk(PrevEnd, TaggedUserPtr + Size, Size, BlockEnd); - if (UNLIKELY(FillContents != NoFill && !Header.OriginOrWasZeroed)) { - // If an allocation needs to be zeroed (i.e. calloc) we can normally - // avoid zeroing the memory now since we can rely on memory having - // been zeroed on free, as this is normally done while setting the - // UAF tag. But if tagging was disabled per-thread when the memory - // was freed, it would not have been retagged and thus zeroed, and - // therefore it needs to be zeroed now. - memset(TaggedPtr, 0, - Min(Size, roundUp(PrevEnd - TaggedUserPtr, - archMemoryTagGranuleSize()))); - } else if (Size) { - // Clear any stack metadata that may have previously been stored in - // the chunk data. - memset(TaggedPtr, 0, archMemoryTagGranuleSize()); - } - } else { - const uptr OddEvenMask = - computeOddEvenMaskForPointerMaybe(Options, BlockUptr, ClassId); - TaggedPtr = prepareTaggedChunk(Ptr, Size, OddEvenMask, BlockEnd); - } - storePrimaryAllocationStackMaybe(Options, Ptr); - } else { - Block = addHeaderTag(Block); - Ptr = addHeaderTag(Ptr); - if (UNLIKELY(FillContents != NoFill)) { - // This condition is not necessarily unlikely, but since memset is - // costly, we might as well mark it as such. - memset(Block, FillContents == ZeroFill ? 0 : PatternFillByte, - PrimaryT::getSizeByClassId(ClassId)); - } - } - } else { - Block = addHeaderTag(Block); - Ptr = addHeaderTag(Ptr); - if (UNLIKELY(useMemoryTagging(Options))) { - storeTags(reinterpret_cast(Block), reinterpret_cast(Ptr)); - storeSecondaryAllocationStackMaybe(Options, Ptr, Size); - } + const uptr UserPtr = roundUp( + reinterpret_cast(Block) + Chunk::getHeaderSize(), Alignment); + const uptr SizeOrUnusedBytes = + ClassId ? Size : SecondaryBlockEnd - (UserPtr + Size); + + if (LIKELY(!useMemoryTagging(Options))) { + return initChunk(ClassId, Origin, Block, UserPtr, SizeOrUnusedBytes, + FillContents); } - Chunk::UnpackedHeader Header = {}; - if (UNLIKELY(UnalignedUserPtr != UserPtr)) { - const uptr Offset = UserPtr - UnalignedUserPtr; - DCHECK_GE(Offset, 2 * sizeof(u32)); - // The BlockMarker has no security purpose, but is specifically meant for - // the chunk iteration function that can be used in debugging situations. - // It is the only situation where we have to locate the start of a chunk - // based on its block address. - reinterpret_cast(Block)[0] = BlockMarker; - reinterpret_cast(Block)[1] = static_cast(Offset); - Header.Offset = (Offset >> MinAlignmentLog) & Chunk::OffsetMask; - } - Header.ClassId = ClassId & Chunk::ClassIdMask; - Header.State = Chunk::State::Allocated; - Header.OriginOrWasZeroed = Origin & Chunk::OriginMask; - Header.SizeOrUnusedBytes = - (ClassId ? Size : SecondaryBlockEnd - (UserPtr + Size)) & - Chunk::SizeOrUnusedBytesMask; - Chunk::storeHeader(Cookie, Ptr, &Header); - - return TaggedPtr; + return initChunkWithMemoryTagging(ClassId, Origin, Block, UserPtr, Size, + SizeOrUnusedBytes, FillContents); } NOINLINE void deallocate(void *Ptr, Chunk::Origin Origin, uptr DeleteSize = 0, @@ -1163,6 +1048,175 @@ private: reinterpret_cast(Ptr) - SizeOrUnusedBytes; } + ALWAYS_INLINE void *initChunk(const uptr ClassId, const Chunk::Origin Origin, + void *Block, const uptr UserPtr, + const uptr SizeOrUnusedBytes, + const FillContentsMode FillContents) { + Block = addHeaderTag(Block); + // Only do content fill when it's from primary allocator because secondary + // allocator has filled the content. + if (ClassId != 0 && UNLIKELY(FillContents != NoFill)) { + // This condition is not necessarily unlikely, but since memset is + // costly, we might as well mark it as such. + memset(Block, FillContents == ZeroFill ? 0 : PatternFillByte, + PrimaryT::getSizeByClassId(ClassId)); + } + + Chunk::UnpackedHeader Header = {}; + + const uptr DefaultAlignedPtr = + reinterpret_cast(Block) + Chunk::getHeaderSize(); + if (UNLIKELY(DefaultAlignedPtr != UserPtr)) { + const uptr Offset = UserPtr - DefaultAlignedPtr; + DCHECK_GE(Offset, 2 * sizeof(u32)); + // The BlockMarker has no security purpose, but is specifically meant for + // the chunk iteration function that can be used in debugging situations. + // It is the only situation where we have to locate the start of a chunk + // based on its block address. + reinterpret_cast(Block)[0] = BlockMarker; + reinterpret_cast(Block)[1] = static_cast(Offset); + Header.Offset = (Offset >> MinAlignmentLog) & Chunk::OffsetMask; + } + + Header.ClassId = ClassId & Chunk::ClassIdMask; + Header.State = Chunk::State::Allocated; + Header.OriginOrWasZeroed = Origin & Chunk::OriginMask; + Header.SizeOrUnusedBytes = SizeOrUnusedBytes & Chunk::SizeOrUnusedBytesMask; + Chunk::storeHeader(Cookie, reinterpret_cast(addHeaderTag(UserPtr)), + &Header); + + return reinterpret_cast(UserPtr); + } + + NOINLINE void * + initChunkWithMemoryTagging(const uptr ClassId, const Chunk::Origin Origin, + void *Block, const uptr UserPtr, const uptr Size, + const uptr SizeOrUnusedBytes, + const FillContentsMode FillContents) { + const Options Options = Primary.Options.load(); + DCHECK(useMemoryTagging(Options)); + + void *Ptr = reinterpret_cast(UserPtr); + void *TaggedPtr = Ptr; + + if (LIKELY(ClassId)) { + // Init the primary chunk. + // + // We only need to zero or tag the contents for Primary backed + // allocations. We only set tags for primary allocations in order to avoid + // faulting potentially large numbers of pages for large secondary + // allocations. We assume that guard pages are enough to protect these + // allocations. + // + // FIXME: When the kernel provides a way to set the background tag of a + // mapping, we should be able to tag secondary allocations as well. + // + // When memory tagging is enabled, zeroing the contents is done as part of + // setting the tag. + + Chunk::UnpackedHeader Header; + const uptr BlockSize = PrimaryT::getSizeByClassId(ClassId); + const uptr BlockUptr = reinterpret_cast(Block); + const uptr BlockEnd = BlockUptr + BlockSize; + // If possible, try to reuse the UAF tag that was set by deallocate(). + // For simplicity, only reuse tags if we have the same start address as + // the previous allocation. This handles the majority of cases since + // most allocations will not be more aligned than the minimum alignment. + // + // We need to handle situations involving reclaimed chunks, and retag + // the reclaimed portions if necessary. In the case where the chunk is + // fully reclaimed, the chunk's header will be zero, which will trigger + // the code path for new mappings and invalid chunks that prepares the + // chunk from scratch. There are three possibilities for partial + // reclaiming: + // + // (1) Header was reclaimed, data was partially reclaimed. + // (2) Header was not reclaimed, all data was reclaimed (e.g. because + // data started on a page boundary). + // (3) Header was not reclaimed, data was partially reclaimed. + // + // Case (1) will be handled in the same way as for full reclaiming, + // since the header will be zero. + // + // We can detect case (2) by loading the tag from the start + // of the chunk. If it is zero, it means that either all data was + // reclaimed (since we never use zero as the chunk tag), or that the + // previous allocation was of size zero. Either way, we need to prepare + // a new chunk from scratch. + // + // We can detect case (3) by moving to the next page (if covered by the + // chunk) and loading the tag of its first granule. If it is zero, it + // means that all following pages may need to be retagged. On the other + // hand, if it is nonzero, we can assume that all following pages are + // still tagged, according to the logic that if any of the pages + // following the next page were reclaimed, the next page would have been + // reclaimed as well. + uptr TaggedUserPtr; + uptr PrevUserPtr; + if (getChunkFromBlock(BlockUptr, &PrevUserPtr, &Header) && + PrevUserPtr == UserPtr && + (TaggedUserPtr = loadTag(UserPtr)) != UserPtr) { + uptr PrevEnd = TaggedUserPtr + Header.SizeOrUnusedBytes; + const uptr NextPage = roundUp(TaggedUserPtr, getPageSizeCached()); + if (NextPage < PrevEnd && loadTag(NextPage) != NextPage) + PrevEnd = NextPage; + TaggedPtr = reinterpret_cast(TaggedUserPtr); + resizeTaggedChunk(PrevEnd, TaggedUserPtr + Size, Size, BlockEnd); + if (UNLIKELY(FillContents != NoFill && !Header.OriginOrWasZeroed)) { + // If an allocation needs to be zeroed (i.e. calloc) we can normally + // avoid zeroing the memory now since we can rely on memory having + // been zeroed on free, as this is normally done while setting the + // UAF tag. But if tagging was disabled per-thread when the memory + // was freed, it would not have been retagged and thus zeroed, and + // therefore it needs to be zeroed now. + memset(TaggedPtr, 0, + Min(Size, roundUp(PrevEnd - TaggedUserPtr, + archMemoryTagGranuleSize()))); + } else if (Size) { + // Clear any stack metadata that may have previously been stored in + // the chunk data. + memset(TaggedPtr, 0, archMemoryTagGranuleSize()); + } + } else { + const uptr OddEvenMask = + computeOddEvenMaskForPointerMaybe(Options, BlockUptr, ClassId); + TaggedPtr = prepareTaggedChunk(Ptr, Size, OddEvenMask, BlockEnd); + } + storePrimaryAllocationStackMaybe(Options, Ptr); + } else { + // Init the secondary chunk. + + Block = addHeaderTag(Block); + Ptr = addHeaderTag(Ptr); + storeTags(reinterpret_cast(Block), reinterpret_cast(Ptr)); + storeSecondaryAllocationStackMaybe(Options, Ptr, Size); + } + + Chunk::UnpackedHeader Header = {}; + + const uptr DefaultAlignedPtr = + reinterpret_cast(Block) + Chunk::getHeaderSize(); + if (UNLIKELY(DefaultAlignedPtr != UserPtr)) { + const uptr Offset = UserPtr - DefaultAlignedPtr; + DCHECK_GE(Offset, 2 * sizeof(u32)); + // The BlockMarker has no security purpose, but is specifically meant for + // the chunk iteration function that can be used in debugging situations. + // It is the only situation where we have to locate the start of a chunk + // based on its block address. + reinterpret_cast(Block)[0] = BlockMarker; + reinterpret_cast(Block)[1] = static_cast(Offset); + Header.Offset = (Offset >> MinAlignmentLog) & Chunk::OffsetMask; + } + + Header.ClassId = ClassId & Chunk::ClassIdMask; + Header.State = Chunk::State::Allocated; + Header.OriginOrWasZeroed = Origin & Chunk::OriginMask; + Header.SizeOrUnusedBytes = SizeOrUnusedBytes & Chunk::SizeOrUnusedBytesMask; + Chunk::storeHeader(Cookie, Ptr, &Header); + + return TaggedPtr; + } + void quarantineOrDeallocateChunk(const Options &Options, void *TaggedPtr, Chunk::UnpackedHeader *Header, uptr Size) NO_THREAD_SAFETY_ANALYSIS { @@ -1177,31 +1231,23 @@ private: Header->State = Chunk::State::Available; else Header->State = Chunk::State::Quarantined; - Header->OriginOrWasZeroed = useMemoryTagging(Options) && - Header->ClassId && - !TSDRegistry.getDisableMemInit(); - Chunk::storeHeader(Cookie, Ptr, Header); - if (UNLIKELY(useMemoryTagging(Options))) { - u8 PrevTag = extractTag(reinterpret_cast(TaggedPtr)); - storeDeallocationStackMaybe(Options, Ptr, PrevTag, Size); - if (Header->ClassId) { - if (!TSDRegistry.getDisableMemInit()) { - uptr TaggedBegin, TaggedEnd; - const uptr OddEvenMask = computeOddEvenMaskForPointerMaybe( - Options, reinterpret_cast(getBlockBegin(Ptr, Header)), - Header->ClassId); - // Exclude the previous tag so that immediate use after free is - // detected 100% of the time. - setRandomTag(Ptr, Size, OddEvenMask | (1UL << PrevTag), &TaggedBegin, - &TaggedEnd); - } - } + void *BlockBegin; + if (LIKELY(!useMemoryTagging(Options))) { + Header->OriginOrWasZeroed = 0U; + if (BypassQuarantine && allocatorSupportsMemoryTagging()) + Ptr = untagPointer(Ptr); + BlockBegin = getBlockBegin(Ptr, Header); + } else { + Header->OriginOrWasZeroed = + Header->ClassId && !TSDRegistry.getDisableMemInit(); + BlockBegin = + retagBlock(Options, TaggedPtr, Ptr, Header, Size, BypassQuarantine); } + + Chunk::storeHeader(Cookie, Ptr, Header); + if (BypassQuarantine) { - if (allocatorSupportsMemoryTagging()) - Ptr = untagPointer(Ptr); - void *BlockBegin = getBlockBegin(Ptr, Header); const uptr ClassId = Header->ClassId; if (LIKELY(ClassId)) { bool CacheDrained; @@ -1216,9 +1262,6 @@ private: if (CacheDrained) Primary.tryReleaseToOS(ClassId, ReleaseToOS::Normal); } else { - if (UNLIKELY(useMemoryTagging(Options))) - storeTags(reinterpret_cast(BlockBegin), - reinterpret_cast(Ptr)); Secondary.deallocate(Options, BlockBegin); } } else { @@ -1228,6 +1271,34 @@ private: } } + NOINLINE void *retagBlock(const Options &Options, void *TaggedPtr, void *&Ptr, + Chunk::UnpackedHeader *Header, const uptr Size, + bool BypassQuarantine) { + DCHECK(useMemoryTagging(Options)); + + const u8 PrevTag = extractTag(reinterpret_cast(TaggedPtr)); + storeDeallocationStackMaybe(Options, Ptr, PrevTag, Size); + if (Header->ClassId && !TSDRegistry.getDisableMemInit()) { + uptr TaggedBegin, TaggedEnd; + const uptr OddEvenMask = computeOddEvenMaskForPointerMaybe( + Options, reinterpret_cast(getBlockBegin(Ptr, Header)), + Header->ClassId); + // Exclude the previous tag so that immediate use after free is + // detected 100% of the time. + setRandomTag(Ptr, Size, OddEvenMask | (1UL << PrevTag), &TaggedBegin, + &TaggedEnd); + } + + Ptr = untagPointer(Ptr); + void *BlockBegin = getBlockBegin(Ptr, Header); + if (BypassQuarantine && !Header->ClassId) { + storeTags(reinterpret_cast(BlockBegin), + reinterpret_cast(Ptr)); + } + + return BlockBegin; + } + bool getChunkFromBlock(uptr Block, uptr *Chunk, Chunk::UnpackedHeader *Header) { *Chunk = -- GitLab From c6e787f771d1f9d6a846b2d9b8db6adcd87e8dba Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 15 May 2024 17:52:59 -0700 Subject: [PATCH 436/578] [MCAsmParser] .rept/.irp/.irpc: remove excess tail EOL in expansion ``` .irp foo,1 nop .endr nop ``` expands to an excess EOL between two nop lines. Remove the excess EOL. --- llvm/lib/MC/MCParser/AsmParser.cpp | 31 +++++++++++------------------ llvm/test/MC/AsmParser/macro-rept.s | 14 ++++++------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 8d9acd54e879..46c1caa940c5 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -5629,27 +5629,20 @@ MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { return nullptr; } - if (Lexer.is(AsmToken::Identifier) && - (getTok().getIdentifier() == ".rep" || - getTok().getIdentifier() == ".rept" || - getTok().getIdentifier() == ".irp" || - getTok().getIdentifier() == ".irpc")) { - ++NestLevel; - } - - // Otherwise, check whether we have reached the .endr. - if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") { - if (NestLevel == 0) { - EndToken = getTok(); - Lex(); - if (Lexer.isNot(AsmToken::EndOfStatement)) { - printError(getTok().getLoc(), - "unexpected token in '.endr' directive"); - return nullptr; + if (Lexer.is(AsmToken::Identifier)) { + StringRef Ident = getTok().getIdentifier(); + if (Ident == ".rep" || Ident == ".rept" || Ident == ".irp" || + Ident == ".irpc") { + ++NestLevel; + } else if (Ident == ".endr") { + if (NestLevel == 0) { + EndToken = getTok(); + Lex(); + if (!parseEOL()) + break; } - break; + --NestLevel; } - --NestLevel; } // Otherwise, scan till the end of the statement. diff --git a/llvm/test/MC/AsmParser/macro-rept.s b/llvm/test/MC/AsmParser/macro-rept.s index 1dc8060e1d87..2a6a4070bff5 100644 --- a/llvm/test/MC/AsmParser/macro-rept.s +++ b/llvm/test/MC/AsmParser/macro-rept.s @@ -13,10 +13,10 @@ // CHECK: .long 1 // CHECK: .long 1 -// CHECK: .long 0 -// CHECK: .long 0 -// CHECK: .long 0 - -// CHECK: .long 0 -// CHECK: .long 0 -// CHECK: .long 0 +// CHECK: .long 0 +// CHECK-NEXT: .long 0 +// CHECK-NEXT: .long 0 +// CHECK-NEXT: .long 0 +// CHECK-NEXT: .long 0 +// CHECK-NEXT: .long 0 +// CHECK-EMPTY: -- GitLab From 26fabdded34f8cea490060a70188a07ad6b76b8b Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Wed, 15 May 2024 17:53:28 -0700 Subject: [PATCH 437/578] [memprof] Pass FrameIdConverter and CallStackIdConverter by reference (#92327) CallStackIdConverter sets LastUnmappedId when a mapping failure occurs. Now, since toMemProfRecord takes an instance of CallStackIdConverter by value, namely std::function, the caller of toMemProfRecord never receives the mapping failure that occurs inside toMemProfRecord. The same problem applies to FrameIdConverter. The patch fixes the problem by passing FrameIdConverter and CallStackIdConverter by reference, namely llvm::function_ref. While I am it, this patch deletes the copy constructor and copy assignment operator to avoid accidental copies. --- llvm/include/llvm/ProfileData/MemProf.h | 21 +++++-- llvm/lib/ProfileData/MemProf.cpp | 4 +- llvm/unittests/ProfileData/MemProfTest.cpp | 66 ++++++++++++++++++++++ 3 files changed, 85 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h index 3ef6ca8586fb..60bff76d0e46 100644 --- a/llvm/include/llvm/ProfileData/MemProf.h +++ b/llvm/include/llvm/ProfileData/MemProf.h @@ -426,8 +426,8 @@ struct IndexedMemProfRecord { // Convert IndexedMemProfRecord to MemProfRecord. Callback is used to // translate CallStackId to call stacks with frames inline. MemProfRecord toMemProfRecord( - std::function(const CallStackId)> Callback) - const; + llvm::function_ref(const CallStackId)> + Callback) const; // Returns the GUID for the function name after canonicalization. For // memprof, we remove any .llvm suffix added by LTO. MemProfRecords are @@ -784,6 +784,12 @@ template struct FrameIdConverter { FrameIdConverter() = delete; FrameIdConverter(MapTy &Map) : Map(Map) {} + // Delete the copy constructor and copy assignment operator to avoid a + // situation where a copy of FrameIdConverter gets an error in LastUnmappedId + // while the original instance doesn't. + FrameIdConverter(const FrameIdConverter &) = delete; + FrameIdConverter &operator=(const FrameIdConverter &) = delete; + Frame operator()(FrameId Id) { auto Iter = Map.find(Id); if (Iter == Map.end()) { @@ -798,12 +804,19 @@ template struct FrameIdConverter { template struct CallStackIdConverter { std::optional LastUnmappedId; MapTy ⤅ - std::function FrameIdToFrame; + llvm::function_ref FrameIdToFrame; CallStackIdConverter() = delete; - CallStackIdConverter(MapTy &Map, std::function FrameIdToFrame) + CallStackIdConverter(MapTy &Map, + llvm::function_ref FrameIdToFrame) : Map(Map), FrameIdToFrame(FrameIdToFrame) {} + // Delete the copy constructor and copy assignment operator to avoid a + // situation where a copy of CallStackIdConverter gets an error in + // LastUnmappedId while the original instance doesn't. + CallStackIdConverter(const CallStackIdConverter &) = delete; + CallStackIdConverter &operator=(const CallStackIdConverter &) = delete; + llvm::SmallVector operator()(CallStackId CSId) { llvm::SmallVector Frames; auto CSIter = Map.find(CSId); diff --git a/llvm/lib/ProfileData/MemProf.cpp b/llvm/lib/ProfileData/MemProf.cpp index 4667778ca11d..f5789186094c 100644 --- a/llvm/lib/ProfileData/MemProf.cpp +++ b/llvm/lib/ProfileData/MemProf.cpp @@ -243,8 +243,8 @@ IndexedMemProfRecord::deserialize(const MemProfSchema &Schema, } MemProfRecord IndexedMemProfRecord::toMemProfRecord( - std::function(const CallStackId)> Callback) - const { + llvm::function_ref(const CallStackId)> + Callback) const { MemProfRecord Record; for (const memprof::IndexedAllocationInfo &IndexedAI : AllocSites) { diff --git a/llvm/unittests/ProfileData/MemProfTest.cpp b/llvm/unittests/ProfileData/MemProfTest.cpp index 8b97866e403f..a913718d0fe0 100644 --- a/llvm/unittests/ProfileData/MemProfTest.cpp +++ b/llvm/unittests/ProfileData/MemProfTest.cpp @@ -596,4 +596,70 @@ TEST(MemProf, IndexedMemProfRecordToMemProfRecord) { EXPECT_EQ(Record.CallSites[1][0].hash(), F2.hash()); EXPECT_EQ(Record.CallSites[1][1].hash(), F4.hash()); } + +using FrameIdMapTy = + llvm::DenseMap<::llvm::memprof::FrameId, ::llvm::memprof::Frame>; +using CallStackIdMapTy = + llvm::DenseMap<::llvm::memprof::CallStackId, + ::llvm::SmallVector<::llvm::memprof::FrameId>>; + +// Populate those fields returned by getHotColdSchema. +MemInfoBlock makePartialMIB() { + MemInfoBlock MIB; + MIB.AllocCount = 1; + MIB.TotalSize = 5; + MIB.TotalLifetime = 10; + MIB.TotalLifetimeAccessDensity = 23; + return MIB; +} + +TEST(MemProf, MissingCallStackId) { + // Use a non-existent CallStackId to trigger a mapping error in + // toMemProfRecord. + llvm::memprof::IndexedAllocationInfo AI({}, 0xdeadbeefU, makePartialMIB(), + llvm::memprof::getHotColdSchema()); + + IndexedMemProfRecord IndexedMR; + IndexedMR.AllocSites.push_back(AI); + + // Create empty maps. + const FrameIdMapTy IdToFrameMap; + const CallStackIdMapTy CSIdToCallStackMap; + llvm::memprof::FrameIdConverter FrameIdConv( + IdToFrameMap); + llvm::memprof::CallStackIdConverter CSIdConv( + CSIdToCallStackMap, FrameIdConv); + + // We are only interested in errors, not the return value. + (void)IndexedMR.toMemProfRecord(CSIdConv); + + ASSERT_TRUE(CSIdConv.LastUnmappedId.has_value()); + EXPECT_EQ(*CSIdConv.LastUnmappedId, 0xdeadbeefU); + EXPECT_EQ(FrameIdConv.LastUnmappedId, std::nullopt); +} + +TEST(MemProf, MissingFrameId) { + llvm::memprof::IndexedAllocationInfo AI({}, 0x222, makePartialMIB(), + llvm::memprof::getHotColdSchema()); + + IndexedMemProfRecord IndexedMR; + IndexedMR.AllocSites.push_back(AI); + + // An empty map to trigger a mapping error. + const FrameIdMapTy IdToFrameMap; + CallStackIdMapTy CSIdToCallStackMap; + CSIdToCallStackMap.insert({0x222, {2, 3}}); + + llvm::memprof::FrameIdConverter FrameIdConv( + IdToFrameMap); + llvm::memprof::CallStackIdConverter CSIdConv( + CSIdToCallStackMap, FrameIdConv); + + // We are only interested in errors, not the return value. + (void)IndexedMR.toMemProfRecord(CSIdConv); + + EXPECT_EQ(CSIdConv.LastUnmappedId, std::nullopt); + ASSERT_TRUE(FrameIdConv.LastUnmappedId.has_value()); + EXPECT_EQ(*FrameIdConv.LastUnmappedId, 3U); +} } // namespace -- GitLab From fa750f09be6966de7423ddce1af7d1eaf817182c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 16 May 2024 09:49:34 +0900 Subject: [PATCH 438/578] Revert "[MC] Remove UseAssemblerInfoForParsing" This reverts commit 03c53c69a367008da689f0d2940e2197eb4a955c. This causes very large compile-time regressions in some cases, e.g. sqlite3 at O0 regresses by 5%. --- clang/tools/driver/cc1as_main.cpp | 3 +++ llvm/include/llvm/MC/MCStreamer.h | 7 +++++-- .../CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp | 3 +++ llvm/lib/MC/MCObjectStreamer.cpp | 9 ++++++++- llvm/lib/MC/MCStreamer.cpp | 2 +- llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp | 7 +++++-- llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp | 3 +++ .../AsmParser/assembler-expressions-inlineasm.ll | 16 ++++++---------- llvm/tools/llvm-mc/llvm-mc.cpp | 3 +++ llvm/tools/llvm-ml/llvm-ml.cpp | 3 +++ 10 files changed, 40 insertions(+), 16 deletions(-) diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 4eb753a7297a..86afe22fac24 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -576,6 +576,9 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, Str.get()->emitZeros(1); } + // Assembly to object compilation should leverage assembly info. + Str->setUseAssemblerInfoForParsing(true); + bool Failed = false; std::unique_ptr Parser( diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 50986e6bde88..69867620e1bf 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -245,6 +245,8 @@ class MCStreamer { /// requires. unsigned NextWinCFIID = 0; + bool UseAssemblerInfoForParsing; + /// Is the assembler allowed to insert padding automatically? For /// correctness reasons, we sometimes need to ensure instructions aren't /// separated in unexpected ways. At the moment, this feature is only @@ -294,10 +296,11 @@ public: MCContext &getContext() const { return Context; } - // MCObjectStreamer has an MCAssembler and allows more expression folding at - // parse time. virtual MCAssembler *getAssemblerPtr() { return nullptr; } + void setUseAssemblerInfoForParsing(bool v) { UseAssemblerInfoForParsing = v; } + bool getUseAssemblerInfoForParsing() { return UseAssemblerInfoForParsing; } + MCTargetStreamer *getTargetStreamer() { return TargetStreamer.get(); } diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 08e3c208ba4d..d0ef3e5a1939 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -102,6 +102,9 @@ void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, std::unique_ptr Parser( createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); + // Do not use assembler-level information for parsing inline assembly. + OutStreamer->setUseAssemblerInfoForParsing(false); + // We create a new MCInstrInfo here since we might be at the module level // and not have a MachineFunction to initialize the TargetInstrInfo from and // we only need MCInstrInfo for asm parsing. We create one unconditionally diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index a9003a164b30..d2da5d0d3f90 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -40,7 +40,14 @@ MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCObjectStreamer::~MCObjectStreamer() = default; -MCAssembler *MCObjectStreamer::getAssemblerPtr() { return Assembler.get(); } +// AssemblerPtr is used for evaluation of expressions and causes +// difference between asm and object outputs. Return nullptr to in +// inline asm mode to limit divergence to assembly inputs. +MCAssembler *MCObjectStreamer::getAssemblerPtr() { + if (getUseAssemblerInfoForParsing()) + return Assembler.get(); + return nullptr; +} void MCObjectStreamer::addPendingLabel(MCSymbol* S) { MCSection *CurSection = getCurrentSectionOnly(); diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 199d865ea349..176d55aa890b 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -93,7 +93,7 @@ void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), CurrentWinFrameInfo(nullptr), - CurrentProcWinFrameInfoStartIndex(0) { + CurrentProcWinFrameInfoStartIndex(0), UseAssemblerInfoForParsing(false) { SectionStack.push_back(std::pair()); } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp index bd48a5f80c82..b7388ed9e85a 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -517,9 +517,12 @@ bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) { DumpCodeInstEmitter = nullptr; if (STM.dumpCode()) { - // For -dumpcode, get the assembler out of the streamer. This only works - // with -filetype=obj. + // For -dumpcode, get the assembler out of the streamer, even if it does + // not really want to let us have it. This only works with -filetype=obj. + bool SaveFlag = OutStreamer->getUseAssemblerInfoForParsing(); + OutStreamer->setUseAssemblerInfoForParsing(true); MCAssembler *Assembler = OutStreamer->getAssemblerPtr(); + OutStreamer->setUseAssemblerInfoForParsing(SaveFlag); if (Assembler) DumpCodeInstEmitter = Assembler->getEmitterPtr(); } diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp index ad0158086044..2ebe5bdc4771 100644 --- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp @@ -114,9 +114,12 @@ void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) { // Bound is an approximation that accounts for the maximum used register // number and number of generated OpLabels unsigned Bound = 2 * (ST->getBound() + 1) + NLabels; + bool FlagToRestore = OutStreamer->getUseAssemblerInfoForParsing(); + OutStreamer->setUseAssemblerInfoForParsing(true); if (MCAssembler *Asm = OutStreamer->getAssemblerPtr()) Asm->setBuildVersion(static_cast(0), Major, Minor, Bound, VersionTuple(Major, Minor, 0, Bound)); + OutStreamer->setUseAssemblerInfoForParsing(FlagToRestore); } void SPIRVAsmPrinter::emitFunctionHeader() { diff --git a/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll b/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll index 9d9a38f5b5a5..35f110f37e2f 100644 --- a/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll +++ b/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll @@ -1,16 +1,12 @@ -; RUN: not llc -mtriple=x86_64 %s -o /dev/null 2>&1 | FileCheck %s -; RUN: llc -mtriple=x86_64 -no-integrated-as < %s | FileCheck %s --check-prefix=GAS -; RUN: llc -mtriple=x86_64 -filetype=obj %s -o - | llvm-objdump -d - | FileCheck %s --check-prefix=DISASM +; RUN: not llc -mtriple x86_64-unknown-linux-gnu -o %t.s -filetype=asm %s 2>&1 | FileCheck %s +; RUN: not llc -mtriple x86_64-unknown-linux-gnu -o %t.o -filetype=obj %s 2>&1 | FileCheck %s -; GAS: nop; .if . - foo==1; nop;.endif +; Assembler-aware expression evaluation should be disabled in inline +; assembly to prevent differences in behavior between object and +; assembly output. -; CHECK: :1:17: error: expected absolute expression -; DISASM:
: -; DISASM-NEXT: nop -; DISASM-NEXT: nop -; DISASM-NEXT: xorl %eax, %eax -; DISASM-NEXT: retq +; CHECK: :1:17: error: expected absolute expression define i32 @main() local_unnamed_addr { tail call void asm sideeffect "foo: nop; .if . - foo==1; nop;.endif", "~{dirflag},~{fpsr},~{flags}"() diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp index 506e4f22ef8f..807071a7b9a1 100644 --- a/llvm/tools/llvm-mc/llvm-mc.cpp +++ b/llvm/tools/llvm-mc/llvm-mc.cpp @@ -569,6 +569,9 @@ int main(int argc, char **argv) { Str->initSections(true, *STI); } + // Use Assembler information for parsing. + Str->setUseAssemblerInfoForParsing(true); + int Res = 1; bool disassemble = false; switch (Action) { diff --git a/llvm/tools/llvm-ml/llvm-ml.cpp b/llvm/tools/llvm-ml/llvm-ml.cpp index f1f39af059aa..1cac576f54e7 100644 --- a/llvm/tools/llvm-ml/llvm-ml.cpp +++ b/llvm/tools/llvm-ml/llvm-ml.cpp @@ -428,6 +428,9 @@ int llvm_ml_main(int Argc, char **Argv, const llvm::ToolContext &) { Str->emitAssignment(Feat00Sym, MCConstantExpr::create(Feat00Flags, Ctx)); } + // Use Assembler information for parsing. + Str->setUseAssemblerInfoForParsing(true); + int Res = 1; if (InputArgs.hasArg(OPT_as_lex)) { // -as-lex; Lex only, and output a stream of tokens -- GitLab From a9763deb2f3f20d789b947ec69360c258377db6a Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Wed, 15 May 2024 18:15:40 -0700 Subject: [PATCH 439/578] Merge sourcelocation in CSEMIRBuilder::getDominatingInstrForID. (#90922) Make sure to merge the sourcelocation of the Dominating Instruction that is hoisted in a basic block in the CSEMIRBuilder in the legalizer pass. If this is not done, we can have a incorrect line table entry that makes the instruction pointer jump around. For example the line table without this patch looks like: ``` Address Line Column File ISA Discriminator OpIndex Flags ------------------ ------ ------ ------ --- ------------- ------- ------------- 0x0000000000000000 0 0 1 0 0 0 is_stmt 0x0000000000000010 11 14 1 0 0 0 is_stmt prologue_end 0x0000000000000028 12 1 1 0 0 0 is_stmt 0x000000000000002c 12 15 1 0 0 0 0x000000000000004c 12 13 1 0 0 0 0x000000000000005c 13 1 1 0 0 0 is_stmt 0x0000000000000064 12 13 1 0 0 0 is_stmt 0x000000000000007c 13 7 1 0 0 0 is_stmt 0x00000000000000c8 13 1 1 0 0 0 0x00000000000000e8 13 1 1 0 0 0 epilogue_begin 0x00000000000000f8 13 1 1 0 0 0 end_sequence ``` The line table entry for 0x000000000000005c should be 0 After this patch, the line table looks like: ``` Address Line Column File ISA Discriminator OpIndex Flags ------------------ ------ ------ ------ --- ------------- ------- ------------- 0x0000000000000000 0 0 1 0 0 0 is_stmt 0x0000000000000010 11 14 1 0 0 0 is_stmt prologue_end 0x0000000000000028 12 1 1 0 0 0 is_stmt 0x000000000000002c 12 15 1 0 0 0 0x000000000000004c 12 13 1 0 0 0 0x000000000000005c 0 0 1 0 0 0 0x0000000000000064 12 13 1 0 0 0 0x000000000000007c 13 7 1 0 0 0 is_stmt 0x00000000000000c8 13 1 1 0 0 0 0x00000000000000e8 13 1 1 0 0 0 epilogue_begin 0x00000000000000f8 13 1 1 0 0 0 end_sequence ``` --- .../GlobalISel/LegalizationArtifactCombiner.h | 6 ++++ llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp | 5 ++++ .../AArch64/merge-locations-legalizer.mir | 30 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 llvm/test/DebugInfo/AArch64/merge-locations-legalizer.mir diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h index 305bef7dd3ea..2efc48e3be4c 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -26,6 +26,7 @@ #include "llvm/CodeGen/Register.h" #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "legalizer" @@ -99,6 +100,11 @@ public: const LLT DstTy = MRI.getType(DstReg); if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) { auto &CstVal = SrcMI->getOperand(1); + auto *MergedLocation = DILocation::getMergedLocation( + MI.getDebugLoc().get(), SrcMI->getDebugLoc().get()); + // Set the debug location to the merged location of the SrcMI and the MI + // if the aext fold is successful. + Builder.setDebugLoc(MergedLocation); Builder.buildConstant( DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits())); UpdatedDefs.push_back(DstReg); diff --git a/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp index 551ba1e6036c..547529bbe699 100644 --- a/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp @@ -51,6 +51,11 @@ CSEMIRBuilder::getDominatingInstrForID(FoldingSetNodeID &ID, // this builder will have the def ready. setInsertPt(*CurMBB, std::next(MII)); } else if (!dominates(MI, CurrPos)) { + // Update the spliced machineinstr's debug location by merging it with the + // debug location of the instruction at the insertion point. + auto *Loc = DILocation::getMergedLocation(getDebugLoc().get(), + MI->getDebugLoc().get()); + MI->setDebugLoc(Loc); CurMBB->splice(CurrPos, CurMBB, MI); } return MachineInstrBuilder(getMF(), MI); diff --git a/llvm/test/DebugInfo/AArch64/merge-locations-legalizer.mir b/llvm/test/DebugInfo/AArch64/merge-locations-legalizer.mir new file mode 100644 index 000000000000..3bdf87cea0e5 --- /dev/null +++ b/llvm/test/DebugInfo/AArch64/merge-locations-legalizer.mir @@ -0,0 +1,30 @@ +# This test checks to make sure that when an instruction (%3 in the test) is +# moved due to matching a result of a fold of two other instructions +# (%1, and %2 in the test) in the legalizer, the DILocation of the +# instruction that is moved (%3) is updated appropriately. + +# RUN: llc %s -run-pass=legalizer -mtriple=aarch64 -o - | FileCheck %s +# CHECK-NOT: %2:_(s32) = G_CONSTANT i32 0, debug-location !DILocation(line: 13 +# CHECK: %2:_(s32) = G_CONSTANT i32 0, debug-location !DILocation(line: 0, +--- | + + define i32 @main(i32 %0, ptr %1) #0 !dbg !57 { + entry: + ret i32 0, !dbg !71 + } + !3 = !DIFile(filename: "main.swift", directory: "/Volumes/Data/swift") + !23 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, sdk: "blah.sdk") + !57 = distinct !DISubprogram(name: "main", unit: !23) + !64 = distinct !DILexicalBlock(scope: !57, column: 1) + !66 = distinct !DILexicalBlock(scope: !64, column: 1) + !68 = !DILocation(line: 12, scope: !66) + !70 = distinct !DILexicalBlock(scope: !66, column: 1) + !71 = !DILocation(line: 13, scope: !70) +name: main +body: | + bb.0: + %1:_(s8) = G_CONSTANT i8 0, debug-location !68 + %2:_(s32) = G_ANYEXT %1(s8), debug-location !68 + $w2 = COPY %2(s32), debug-location !68 + %3:_(s32) = G_CONSTANT i32 0, debug-location !71 + $w0 = COPY %3(s32), debug-location !71 -- GitLab From 72200fcc346bee1830d9e640e42d717a55acd74c Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Wed, 15 May 2024 18:16:39 -0700 Subject: [PATCH 440/578] [analyzer] Check C++ base or member initializer in WebKit checkers. (#92220) Co-authored-by: Ryosuke Niwa --- .../Checkers/WebKit/PtrTypesSemantics.cpp | 10 ++++++++- .../Checkers/WebKit/uncounted-obj-arg.cpp | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index 950d35a090a3..5c797d523308 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -525,11 +525,19 @@ bool TrivialFunctionAnalysis::isTrivialImpl( if (!IsNew) return It->second; + TrivialFunctionAnalysisVisitor V(Cache); + + if (auto *CtorDecl = dyn_cast(D)) { + for (auto *CtorInit : CtorDecl->inits()) { + if (!V.Visit(CtorInit->getInit())) + return false; + } + } + const Stmt *Body = D->getBody(); if (!Body) return false; - TrivialFunctionAnalysisVisitor V(Cache); bool Result = V.Visit(Body); if (Result) Cache[D] = true; diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp index ed37671df3d3..96986631726f 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp @@ -159,10 +159,13 @@ private: StorageType m_storage { 0 }; }; +int atoi(const char* str); + class Number { public: Number(int v) : v(v) { } Number(double); + Number(const char* str) : v(atoi(str)) { } Number operator+(const Number&); Number& operator++() { ++v; return *this; } Number operator++(int) { Number returnValue(v); ++v; return returnValue; } @@ -173,9 +176,16 @@ private: int v; }; +class DerivedNumber : public Number { +public: + DerivedNumber(char c) : Number(c - '0') { } + DerivedNumber(const char* str) : Number(atoi(str)) { } +}; + class ComplexNumber { public: ComplexNumber() : realPart(0), complexPart(0) { } + ComplexNumber(int real, const char* str) : realPart(real), complexPart(str) { } ComplexNumber(const ComplexNumber&); ComplexNumber& operator++() { realPart.someMethod(); return *this; } ComplexNumber operator++(int); @@ -311,6 +321,7 @@ public: return; } unsigned trivial60() { return ObjectWithNonTrivialDestructor { 5 }.value(); } + unsigned trivial61() { return DerivedNumber('7').value(); } static RefCounted& singleton() { static RefCounted s_RefCounted; @@ -391,6 +402,9 @@ public: ComplexNumber nonTrivial18() { return +complex; } ComplexNumber* nonTrivial19() { return new ComplexNumber(complex); } unsigned nonTrivial20() { return ObjectWithMutatingDestructor { 7 }.value(); } + unsigned nonTrivial21() { return Number("123").value(); } + unsigned nonTrivial22() { return ComplexNumber(123, "456").real().value(); } + unsigned nonTrivial23() { return DerivedNumber("123").value(); } static unsigned s_v; unsigned v { 0 }; @@ -479,6 +493,7 @@ public: getFieldTrivial().trivial58(); // no-warning getFieldTrivial().trivial59(); // no-warning getFieldTrivial().trivial60(); // no-warning + getFieldTrivial().trivial61(); // no-warning RefCounted::singleton().trivial18(); // no-warning RefCounted::singleton().someFunction(); // no-warning @@ -525,6 +540,12 @@ public: // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} getFieldTrivial().nonTrivial20(); // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + getFieldTrivial().nonTrivial21(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + getFieldTrivial().nonTrivial22(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + getFieldTrivial().nonTrivial23(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} } }; -- GitLab From f0b3654701bde1cf7821d60698b42383edaff9f3 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 16 May 2024 10:21:22 +0900 Subject: [PATCH 441/578] [LoopUnroll] Clamp PartialThreshold for large LoopMicroOpBufferSize (#67657) The znver3/znver4 scheduler models are outliers, specifying very large LoopMicroOpBufferSizes at 512, while typical values for other subtargets are on the order of ~50. Even if this information is micro-architecturally correct (*), this does not mean that we want to runtime unroll all loops to a size that completely fills the loop buffer. Unless this is the single hot loop in the entire application, the massive code size increase will bust the micro-op and instruction caches. Protect against this by clamping to the default PartialThreshold of 150, which is the same as the default full-unroll threshold and half the aggressive full-unroll threshold. Allowing more partial unrolling than full unrolling certainly does not make sense. (*) I strongly doubt that this is actually correct -- I believe this may derive from an incorrect reading of Agner Fog's micro-architecture guide. The number 4096 that was originally used here is the size of the general micro-op cache, not that of a loop buffer. A separate loop buffer is not listed for the Zen microarchitecture. Comparing this to the listing for Skylake, it has a 1536 micro-op buffer, but only a 64 micro-op loopback buffer, with a note that it's rarely fully utilized. Our scheduling model specifies LoopMicroOpBufferSize of 50 in that case. --- llvm/include/llvm/CodeGen/BasicTTIImpl.h | 8 +- llvm/test/Transforms/LoopUnroll/X86/znver3.ll | 764 +----------------- 2 files changed, 30 insertions(+), 742 deletions(-) diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h index 2091432d4fe2..8dba6a641285 100644 --- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h +++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h @@ -612,7 +612,13 @@ public: if (PartialUnrollingThreshold.getNumOccurrences() > 0) MaxOps = PartialUnrollingThreshold; else if (ST->getSchedModel().LoopMicroOpBufferSize > 0) - MaxOps = ST->getSchedModel().LoopMicroOpBufferSize; + // Upper bound by the default PartialThreshold, which is the same as + // the default full-unroll Threshold. Even if the loop micro-op buffer + // is very large, this does not mean that we want to unroll all loops + // to that length, as it would increase code size beyond the limits of + // what unrolling normally allows. + MaxOps = std::min(ST->getSchedModel().LoopMicroOpBufferSize, + UP.PartialThreshold); else return; diff --git a/llvm/test/Transforms/LoopUnroll/X86/znver3.ll b/llvm/test/Transforms/LoopUnroll/X86/znver3.ll index 30389062a096..467c57906d88 100644 --- a/llvm/test/Transforms/LoopUnroll/X86/znver3.ll +++ b/llvm/test/Transforms/LoopUnroll/X86/znver3.ll @@ -9,8 +9,8 @@ define i32 @test(ptr %ary) "target-cpu"="znver3" { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT_127:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT_127:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT_31:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT_31:%.*]], [[FOR_BODY]] ] ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV]] ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 ; CHECK-NEXT: [[SUM_NEXT:%.*]] = add nsw i32 [[VAL]], [[SUM]] @@ -137,396 +137,12 @@ define i32 @test(ptr %ary) "target-cpu"="znver3" { ; CHECK-NEXT: [[INDVARS_IV_NEXT_30:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 31 ; CHECK-NEXT: [[ARRAYIDX_31:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_30]] ; CHECK-NEXT: [[VAL_31:%.*]] = load i32, ptr [[ARRAYIDX_31]], align 4 -; CHECK-NEXT: [[SUM_NEXT_31:%.*]] = add nsw i32 [[VAL_31]], [[SUM_NEXT_30]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_31:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 32 -; CHECK-NEXT: [[ARRAYIDX_32:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_31]] -; CHECK-NEXT: [[VAL_32:%.*]] = load i32, ptr [[ARRAYIDX_32]], align 4 -; CHECK-NEXT: [[SUM_NEXT_32:%.*]] = add nsw i32 [[VAL_32]], [[SUM_NEXT_31]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_32:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 33 -; CHECK-NEXT: [[ARRAYIDX_33:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_32]] -; CHECK-NEXT: [[VAL_33:%.*]] = load i32, ptr [[ARRAYIDX_33]], align 4 -; CHECK-NEXT: [[SUM_NEXT_33:%.*]] = add nsw i32 [[VAL_33]], [[SUM_NEXT_32]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_33:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 34 -; CHECK-NEXT: [[ARRAYIDX_34:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_33]] -; CHECK-NEXT: [[VAL_34:%.*]] = load i32, ptr [[ARRAYIDX_34]], align 4 -; CHECK-NEXT: [[SUM_NEXT_34:%.*]] = add nsw i32 [[VAL_34]], [[SUM_NEXT_33]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_34:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 35 -; CHECK-NEXT: [[ARRAYIDX_35:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_34]] -; CHECK-NEXT: [[VAL_35:%.*]] = load i32, ptr [[ARRAYIDX_35]], align 4 -; CHECK-NEXT: [[SUM_NEXT_35:%.*]] = add nsw i32 [[VAL_35]], [[SUM_NEXT_34]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_35:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 36 -; CHECK-NEXT: [[ARRAYIDX_36:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_35]] -; CHECK-NEXT: [[VAL_36:%.*]] = load i32, ptr [[ARRAYIDX_36]], align 4 -; CHECK-NEXT: [[SUM_NEXT_36:%.*]] = add nsw i32 [[VAL_36]], [[SUM_NEXT_35]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_36:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 37 -; CHECK-NEXT: [[ARRAYIDX_37:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_36]] -; CHECK-NEXT: [[VAL_37:%.*]] = load i32, ptr [[ARRAYIDX_37]], align 4 -; CHECK-NEXT: [[SUM_NEXT_37:%.*]] = add nsw i32 [[VAL_37]], [[SUM_NEXT_36]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_37:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 38 -; CHECK-NEXT: [[ARRAYIDX_38:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_37]] -; CHECK-NEXT: [[VAL_38:%.*]] = load i32, ptr [[ARRAYIDX_38]], align 4 -; CHECK-NEXT: [[SUM_NEXT_38:%.*]] = add nsw i32 [[VAL_38]], [[SUM_NEXT_37]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_38:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 39 -; CHECK-NEXT: [[ARRAYIDX_39:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_38]] -; CHECK-NEXT: [[VAL_39:%.*]] = load i32, ptr [[ARRAYIDX_39]], align 4 -; CHECK-NEXT: [[SUM_NEXT_39:%.*]] = add nsw i32 [[VAL_39]], [[SUM_NEXT_38]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_39:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 40 -; CHECK-NEXT: [[ARRAYIDX_40:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_39]] -; CHECK-NEXT: [[VAL_40:%.*]] = load i32, ptr [[ARRAYIDX_40]], align 4 -; CHECK-NEXT: [[SUM_NEXT_40:%.*]] = add nsw i32 [[VAL_40]], [[SUM_NEXT_39]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_40:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 41 -; CHECK-NEXT: [[ARRAYIDX_41:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_40]] -; CHECK-NEXT: [[VAL_41:%.*]] = load i32, ptr [[ARRAYIDX_41]], align 4 -; CHECK-NEXT: [[SUM_NEXT_41:%.*]] = add nsw i32 [[VAL_41]], [[SUM_NEXT_40]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_41:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 42 -; CHECK-NEXT: [[ARRAYIDX_42:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_41]] -; CHECK-NEXT: [[VAL_42:%.*]] = load i32, ptr [[ARRAYIDX_42]], align 4 -; CHECK-NEXT: [[SUM_NEXT_42:%.*]] = add nsw i32 [[VAL_42]], [[SUM_NEXT_41]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_42:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 43 -; CHECK-NEXT: [[ARRAYIDX_43:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_42]] -; CHECK-NEXT: [[VAL_43:%.*]] = load i32, ptr [[ARRAYIDX_43]], align 4 -; CHECK-NEXT: [[SUM_NEXT_43:%.*]] = add nsw i32 [[VAL_43]], [[SUM_NEXT_42]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_43:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 44 -; CHECK-NEXT: [[ARRAYIDX_44:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_43]] -; CHECK-NEXT: [[VAL_44:%.*]] = load i32, ptr [[ARRAYIDX_44]], align 4 -; CHECK-NEXT: [[SUM_NEXT_44:%.*]] = add nsw i32 [[VAL_44]], [[SUM_NEXT_43]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_44:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 45 -; CHECK-NEXT: [[ARRAYIDX_45:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_44]] -; CHECK-NEXT: [[VAL_45:%.*]] = load i32, ptr [[ARRAYIDX_45]], align 4 -; CHECK-NEXT: [[SUM_NEXT_45:%.*]] = add nsw i32 [[VAL_45]], [[SUM_NEXT_44]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_45:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 46 -; CHECK-NEXT: [[ARRAYIDX_46:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_45]] -; CHECK-NEXT: [[VAL_46:%.*]] = load i32, ptr [[ARRAYIDX_46]], align 4 -; CHECK-NEXT: [[SUM_NEXT_46:%.*]] = add nsw i32 [[VAL_46]], [[SUM_NEXT_45]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_46:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 47 -; CHECK-NEXT: [[ARRAYIDX_47:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_46]] -; CHECK-NEXT: [[VAL_47:%.*]] = load i32, ptr [[ARRAYIDX_47]], align 4 -; CHECK-NEXT: [[SUM_NEXT_47:%.*]] = add nsw i32 [[VAL_47]], [[SUM_NEXT_46]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_47:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 48 -; CHECK-NEXT: [[ARRAYIDX_48:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_47]] -; CHECK-NEXT: [[VAL_48:%.*]] = load i32, ptr [[ARRAYIDX_48]], align 4 -; CHECK-NEXT: [[SUM_NEXT_48:%.*]] = add nsw i32 [[VAL_48]], [[SUM_NEXT_47]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_48:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 49 -; CHECK-NEXT: [[ARRAYIDX_49:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_48]] -; CHECK-NEXT: [[VAL_49:%.*]] = load i32, ptr [[ARRAYIDX_49]], align 4 -; CHECK-NEXT: [[SUM_NEXT_49:%.*]] = add nsw i32 [[VAL_49]], [[SUM_NEXT_48]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_49:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 50 -; CHECK-NEXT: [[ARRAYIDX_50:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_49]] -; CHECK-NEXT: [[VAL_50:%.*]] = load i32, ptr [[ARRAYIDX_50]], align 4 -; CHECK-NEXT: [[SUM_NEXT_50:%.*]] = add nsw i32 [[VAL_50]], [[SUM_NEXT_49]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_50:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 51 -; CHECK-NEXT: [[ARRAYIDX_51:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_50]] -; CHECK-NEXT: [[VAL_51:%.*]] = load i32, ptr [[ARRAYIDX_51]], align 4 -; CHECK-NEXT: [[SUM_NEXT_51:%.*]] = add nsw i32 [[VAL_51]], [[SUM_NEXT_50]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_51:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 52 -; CHECK-NEXT: [[ARRAYIDX_52:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_51]] -; CHECK-NEXT: [[VAL_52:%.*]] = load i32, ptr [[ARRAYIDX_52]], align 4 -; CHECK-NEXT: [[SUM_NEXT_52:%.*]] = add nsw i32 [[VAL_52]], [[SUM_NEXT_51]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_52:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 53 -; CHECK-NEXT: [[ARRAYIDX_53:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_52]] -; CHECK-NEXT: [[VAL_53:%.*]] = load i32, ptr [[ARRAYIDX_53]], align 4 -; CHECK-NEXT: [[SUM_NEXT_53:%.*]] = add nsw i32 [[VAL_53]], [[SUM_NEXT_52]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_53:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 54 -; CHECK-NEXT: [[ARRAYIDX_54:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_53]] -; CHECK-NEXT: [[VAL_54:%.*]] = load i32, ptr [[ARRAYIDX_54]], align 4 -; CHECK-NEXT: [[SUM_NEXT_54:%.*]] = add nsw i32 [[VAL_54]], [[SUM_NEXT_53]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_54:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 55 -; CHECK-NEXT: [[ARRAYIDX_55:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_54]] -; CHECK-NEXT: [[VAL_55:%.*]] = load i32, ptr [[ARRAYIDX_55]], align 4 -; CHECK-NEXT: [[SUM_NEXT_55:%.*]] = add nsw i32 [[VAL_55]], [[SUM_NEXT_54]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_55:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 56 -; CHECK-NEXT: [[ARRAYIDX_56:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_55]] -; CHECK-NEXT: [[VAL_56:%.*]] = load i32, ptr [[ARRAYIDX_56]], align 4 -; CHECK-NEXT: [[SUM_NEXT_56:%.*]] = add nsw i32 [[VAL_56]], [[SUM_NEXT_55]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_56:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 57 -; CHECK-NEXT: [[ARRAYIDX_57:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_56]] -; CHECK-NEXT: [[VAL_57:%.*]] = load i32, ptr [[ARRAYIDX_57]], align 4 -; CHECK-NEXT: [[SUM_NEXT_57:%.*]] = add nsw i32 [[VAL_57]], [[SUM_NEXT_56]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_57:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 58 -; CHECK-NEXT: [[ARRAYIDX_58:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_57]] -; CHECK-NEXT: [[VAL_58:%.*]] = load i32, ptr [[ARRAYIDX_58]], align 4 -; CHECK-NEXT: [[SUM_NEXT_58:%.*]] = add nsw i32 [[VAL_58]], [[SUM_NEXT_57]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_58:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 59 -; CHECK-NEXT: [[ARRAYIDX_59:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_58]] -; CHECK-NEXT: [[VAL_59:%.*]] = load i32, ptr [[ARRAYIDX_59]], align 4 -; CHECK-NEXT: [[SUM_NEXT_59:%.*]] = add nsw i32 [[VAL_59]], [[SUM_NEXT_58]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_59:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 60 -; CHECK-NEXT: [[ARRAYIDX_60:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_59]] -; CHECK-NEXT: [[VAL_60:%.*]] = load i32, ptr [[ARRAYIDX_60]], align 4 -; CHECK-NEXT: [[SUM_NEXT_60:%.*]] = add nsw i32 [[VAL_60]], [[SUM_NEXT_59]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_60:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 61 -; CHECK-NEXT: [[ARRAYIDX_61:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_60]] -; CHECK-NEXT: [[VAL_61:%.*]] = load i32, ptr [[ARRAYIDX_61]], align 4 -; CHECK-NEXT: [[SUM_NEXT_61:%.*]] = add nsw i32 [[VAL_61]], [[SUM_NEXT_60]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_61:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 62 -; CHECK-NEXT: [[ARRAYIDX_62:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_61]] -; CHECK-NEXT: [[VAL_62:%.*]] = load i32, ptr [[ARRAYIDX_62]], align 4 -; CHECK-NEXT: [[SUM_NEXT_62:%.*]] = add nsw i32 [[VAL_62]], [[SUM_NEXT_61]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_62:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 63 -; CHECK-NEXT: [[ARRAYIDX_63:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_62]] -; CHECK-NEXT: [[VAL_63:%.*]] = load i32, ptr [[ARRAYIDX_63]], align 4 -; CHECK-NEXT: [[SUM_NEXT_63:%.*]] = add nsw i32 [[VAL_63]], [[SUM_NEXT_62]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_63:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 64 -; CHECK-NEXT: [[ARRAYIDX_64:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_63]] -; CHECK-NEXT: [[VAL_64:%.*]] = load i32, ptr [[ARRAYIDX_64]], align 4 -; CHECK-NEXT: [[SUM_NEXT_64:%.*]] = add nsw i32 [[VAL_64]], [[SUM_NEXT_63]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_64:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 65 -; CHECK-NEXT: [[ARRAYIDX_65:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_64]] -; CHECK-NEXT: [[VAL_65:%.*]] = load i32, ptr [[ARRAYIDX_65]], align 4 -; CHECK-NEXT: [[SUM_NEXT_65:%.*]] = add nsw i32 [[VAL_65]], [[SUM_NEXT_64]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_65:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 66 -; CHECK-NEXT: [[ARRAYIDX_66:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_65]] -; CHECK-NEXT: [[VAL_66:%.*]] = load i32, ptr [[ARRAYIDX_66]], align 4 -; CHECK-NEXT: [[SUM_NEXT_66:%.*]] = add nsw i32 [[VAL_66]], [[SUM_NEXT_65]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_66:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 67 -; CHECK-NEXT: [[ARRAYIDX_67:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_66]] -; CHECK-NEXT: [[VAL_67:%.*]] = load i32, ptr [[ARRAYIDX_67]], align 4 -; CHECK-NEXT: [[SUM_NEXT_67:%.*]] = add nsw i32 [[VAL_67]], [[SUM_NEXT_66]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_67:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 68 -; CHECK-NEXT: [[ARRAYIDX_68:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_67]] -; CHECK-NEXT: [[VAL_68:%.*]] = load i32, ptr [[ARRAYIDX_68]], align 4 -; CHECK-NEXT: [[SUM_NEXT_68:%.*]] = add nsw i32 [[VAL_68]], [[SUM_NEXT_67]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_68:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 69 -; CHECK-NEXT: [[ARRAYIDX_69:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_68]] -; CHECK-NEXT: [[VAL_69:%.*]] = load i32, ptr [[ARRAYIDX_69]], align 4 -; CHECK-NEXT: [[SUM_NEXT_69:%.*]] = add nsw i32 [[VAL_69]], [[SUM_NEXT_68]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_69:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 70 -; CHECK-NEXT: [[ARRAYIDX_70:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_69]] -; CHECK-NEXT: [[VAL_70:%.*]] = load i32, ptr [[ARRAYIDX_70]], align 4 -; CHECK-NEXT: [[SUM_NEXT_70:%.*]] = add nsw i32 [[VAL_70]], [[SUM_NEXT_69]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_70:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 71 -; CHECK-NEXT: [[ARRAYIDX_71:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_70]] -; CHECK-NEXT: [[VAL_71:%.*]] = load i32, ptr [[ARRAYIDX_71]], align 4 -; CHECK-NEXT: [[SUM_NEXT_71:%.*]] = add nsw i32 [[VAL_71]], [[SUM_NEXT_70]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_71:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 72 -; CHECK-NEXT: [[ARRAYIDX_72:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_71]] -; CHECK-NEXT: [[VAL_72:%.*]] = load i32, ptr [[ARRAYIDX_72]], align 4 -; CHECK-NEXT: [[SUM_NEXT_72:%.*]] = add nsw i32 [[VAL_72]], [[SUM_NEXT_71]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_72:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 73 -; CHECK-NEXT: [[ARRAYIDX_73:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_72]] -; CHECK-NEXT: [[VAL_73:%.*]] = load i32, ptr [[ARRAYIDX_73]], align 4 -; CHECK-NEXT: [[SUM_NEXT_73:%.*]] = add nsw i32 [[VAL_73]], [[SUM_NEXT_72]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_73:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 74 -; CHECK-NEXT: [[ARRAYIDX_74:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_73]] -; CHECK-NEXT: [[VAL_74:%.*]] = load i32, ptr [[ARRAYIDX_74]], align 4 -; CHECK-NEXT: [[SUM_NEXT_74:%.*]] = add nsw i32 [[VAL_74]], [[SUM_NEXT_73]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_74:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 75 -; CHECK-NEXT: [[ARRAYIDX_75:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_74]] -; CHECK-NEXT: [[VAL_75:%.*]] = load i32, ptr [[ARRAYIDX_75]], align 4 -; CHECK-NEXT: [[SUM_NEXT_75:%.*]] = add nsw i32 [[VAL_75]], [[SUM_NEXT_74]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_75:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 76 -; CHECK-NEXT: [[ARRAYIDX_76:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_75]] -; CHECK-NEXT: [[VAL_76:%.*]] = load i32, ptr [[ARRAYIDX_76]], align 4 -; CHECK-NEXT: [[SUM_NEXT_76:%.*]] = add nsw i32 [[VAL_76]], [[SUM_NEXT_75]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_76:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 77 -; CHECK-NEXT: [[ARRAYIDX_77:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_76]] -; CHECK-NEXT: [[VAL_77:%.*]] = load i32, ptr [[ARRAYIDX_77]], align 4 -; CHECK-NEXT: [[SUM_NEXT_77:%.*]] = add nsw i32 [[VAL_77]], [[SUM_NEXT_76]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_77:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 78 -; CHECK-NEXT: [[ARRAYIDX_78:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_77]] -; CHECK-NEXT: [[VAL_78:%.*]] = load i32, ptr [[ARRAYIDX_78]], align 4 -; CHECK-NEXT: [[SUM_NEXT_78:%.*]] = add nsw i32 [[VAL_78]], [[SUM_NEXT_77]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_78:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 79 -; CHECK-NEXT: [[ARRAYIDX_79:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_78]] -; CHECK-NEXT: [[VAL_79:%.*]] = load i32, ptr [[ARRAYIDX_79]], align 4 -; CHECK-NEXT: [[SUM_NEXT_79:%.*]] = add nsw i32 [[VAL_79]], [[SUM_NEXT_78]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_79:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 80 -; CHECK-NEXT: [[ARRAYIDX_80:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_79]] -; CHECK-NEXT: [[VAL_80:%.*]] = load i32, ptr [[ARRAYIDX_80]], align 4 -; CHECK-NEXT: [[SUM_NEXT_80:%.*]] = add nsw i32 [[VAL_80]], [[SUM_NEXT_79]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_80:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 81 -; CHECK-NEXT: [[ARRAYIDX_81:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_80]] -; CHECK-NEXT: [[VAL_81:%.*]] = load i32, ptr [[ARRAYIDX_81]], align 4 -; CHECK-NEXT: [[SUM_NEXT_81:%.*]] = add nsw i32 [[VAL_81]], [[SUM_NEXT_80]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_81:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 82 -; CHECK-NEXT: [[ARRAYIDX_82:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_81]] -; CHECK-NEXT: [[VAL_82:%.*]] = load i32, ptr [[ARRAYIDX_82]], align 4 -; CHECK-NEXT: [[SUM_NEXT_82:%.*]] = add nsw i32 [[VAL_82]], [[SUM_NEXT_81]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_82:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 83 -; CHECK-NEXT: [[ARRAYIDX_83:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_82]] -; CHECK-NEXT: [[VAL_83:%.*]] = load i32, ptr [[ARRAYIDX_83]], align 4 -; CHECK-NEXT: [[SUM_NEXT_83:%.*]] = add nsw i32 [[VAL_83]], [[SUM_NEXT_82]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_83:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 84 -; CHECK-NEXT: [[ARRAYIDX_84:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_83]] -; CHECK-NEXT: [[VAL_84:%.*]] = load i32, ptr [[ARRAYIDX_84]], align 4 -; CHECK-NEXT: [[SUM_NEXT_84:%.*]] = add nsw i32 [[VAL_84]], [[SUM_NEXT_83]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_84:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 85 -; CHECK-NEXT: [[ARRAYIDX_85:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_84]] -; CHECK-NEXT: [[VAL_85:%.*]] = load i32, ptr [[ARRAYIDX_85]], align 4 -; CHECK-NEXT: [[SUM_NEXT_85:%.*]] = add nsw i32 [[VAL_85]], [[SUM_NEXT_84]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_85:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 86 -; CHECK-NEXT: [[ARRAYIDX_86:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_85]] -; CHECK-NEXT: [[VAL_86:%.*]] = load i32, ptr [[ARRAYIDX_86]], align 4 -; CHECK-NEXT: [[SUM_NEXT_86:%.*]] = add nsw i32 [[VAL_86]], [[SUM_NEXT_85]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_86:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 87 -; CHECK-NEXT: [[ARRAYIDX_87:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_86]] -; CHECK-NEXT: [[VAL_87:%.*]] = load i32, ptr [[ARRAYIDX_87]], align 4 -; CHECK-NEXT: [[SUM_NEXT_87:%.*]] = add nsw i32 [[VAL_87]], [[SUM_NEXT_86]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_87:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 88 -; CHECK-NEXT: [[ARRAYIDX_88:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_87]] -; CHECK-NEXT: [[VAL_88:%.*]] = load i32, ptr [[ARRAYIDX_88]], align 4 -; CHECK-NEXT: [[SUM_NEXT_88:%.*]] = add nsw i32 [[VAL_88]], [[SUM_NEXT_87]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_88:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 89 -; CHECK-NEXT: [[ARRAYIDX_89:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_88]] -; CHECK-NEXT: [[VAL_89:%.*]] = load i32, ptr [[ARRAYIDX_89]], align 4 -; CHECK-NEXT: [[SUM_NEXT_89:%.*]] = add nsw i32 [[VAL_89]], [[SUM_NEXT_88]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_89:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 90 -; CHECK-NEXT: [[ARRAYIDX_90:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_89]] -; CHECK-NEXT: [[VAL_90:%.*]] = load i32, ptr [[ARRAYIDX_90]], align 4 -; CHECK-NEXT: [[SUM_NEXT_90:%.*]] = add nsw i32 [[VAL_90]], [[SUM_NEXT_89]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_90:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 91 -; CHECK-NEXT: [[ARRAYIDX_91:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_90]] -; CHECK-NEXT: [[VAL_91:%.*]] = load i32, ptr [[ARRAYIDX_91]], align 4 -; CHECK-NEXT: [[SUM_NEXT_91:%.*]] = add nsw i32 [[VAL_91]], [[SUM_NEXT_90]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_91:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 92 -; CHECK-NEXT: [[ARRAYIDX_92:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_91]] -; CHECK-NEXT: [[VAL_92:%.*]] = load i32, ptr [[ARRAYIDX_92]], align 4 -; CHECK-NEXT: [[SUM_NEXT_92:%.*]] = add nsw i32 [[VAL_92]], [[SUM_NEXT_91]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_92:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 93 -; CHECK-NEXT: [[ARRAYIDX_93:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_92]] -; CHECK-NEXT: [[VAL_93:%.*]] = load i32, ptr [[ARRAYIDX_93]], align 4 -; CHECK-NEXT: [[SUM_NEXT_93:%.*]] = add nsw i32 [[VAL_93]], [[SUM_NEXT_92]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_93:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 94 -; CHECK-NEXT: [[ARRAYIDX_94:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_93]] -; CHECK-NEXT: [[VAL_94:%.*]] = load i32, ptr [[ARRAYIDX_94]], align 4 -; CHECK-NEXT: [[SUM_NEXT_94:%.*]] = add nsw i32 [[VAL_94]], [[SUM_NEXT_93]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_94:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 95 -; CHECK-NEXT: [[ARRAYIDX_95:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_94]] -; CHECK-NEXT: [[VAL_95:%.*]] = load i32, ptr [[ARRAYIDX_95]], align 4 -; CHECK-NEXT: [[SUM_NEXT_95:%.*]] = add nsw i32 [[VAL_95]], [[SUM_NEXT_94]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_95:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 96 -; CHECK-NEXT: [[ARRAYIDX_96:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_95]] -; CHECK-NEXT: [[VAL_96:%.*]] = load i32, ptr [[ARRAYIDX_96]], align 4 -; CHECK-NEXT: [[SUM_NEXT_96:%.*]] = add nsw i32 [[VAL_96]], [[SUM_NEXT_95]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_96:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 97 -; CHECK-NEXT: [[ARRAYIDX_97:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_96]] -; CHECK-NEXT: [[VAL_97:%.*]] = load i32, ptr [[ARRAYIDX_97]], align 4 -; CHECK-NEXT: [[SUM_NEXT_97:%.*]] = add nsw i32 [[VAL_97]], [[SUM_NEXT_96]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_97:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 98 -; CHECK-NEXT: [[ARRAYIDX_98:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_97]] -; CHECK-NEXT: [[VAL_98:%.*]] = load i32, ptr [[ARRAYIDX_98]], align 4 -; CHECK-NEXT: [[SUM_NEXT_98:%.*]] = add nsw i32 [[VAL_98]], [[SUM_NEXT_97]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_98:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 99 -; CHECK-NEXT: [[ARRAYIDX_99:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_98]] -; CHECK-NEXT: [[VAL_99:%.*]] = load i32, ptr [[ARRAYIDX_99]], align 4 -; CHECK-NEXT: [[SUM_NEXT_99:%.*]] = add nsw i32 [[VAL_99]], [[SUM_NEXT_98]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_99:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 100 -; CHECK-NEXT: [[ARRAYIDX_100:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_99]] -; CHECK-NEXT: [[VAL_100:%.*]] = load i32, ptr [[ARRAYIDX_100]], align 4 -; CHECK-NEXT: [[SUM_NEXT_100:%.*]] = add nsw i32 [[VAL_100]], [[SUM_NEXT_99]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_100:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 101 -; CHECK-NEXT: [[ARRAYIDX_101:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_100]] -; CHECK-NEXT: [[VAL_101:%.*]] = load i32, ptr [[ARRAYIDX_101]], align 4 -; CHECK-NEXT: [[SUM_NEXT_101:%.*]] = add nsw i32 [[VAL_101]], [[SUM_NEXT_100]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_101:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 102 -; CHECK-NEXT: [[ARRAYIDX_102:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_101]] -; CHECK-NEXT: [[VAL_102:%.*]] = load i32, ptr [[ARRAYIDX_102]], align 4 -; CHECK-NEXT: [[SUM_NEXT_102:%.*]] = add nsw i32 [[VAL_102]], [[SUM_NEXT_101]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_102:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 103 -; CHECK-NEXT: [[ARRAYIDX_103:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_102]] -; CHECK-NEXT: [[VAL_103:%.*]] = load i32, ptr [[ARRAYIDX_103]], align 4 -; CHECK-NEXT: [[SUM_NEXT_103:%.*]] = add nsw i32 [[VAL_103]], [[SUM_NEXT_102]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_103:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 104 -; CHECK-NEXT: [[ARRAYIDX_104:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_103]] -; CHECK-NEXT: [[VAL_104:%.*]] = load i32, ptr [[ARRAYIDX_104]], align 4 -; CHECK-NEXT: [[SUM_NEXT_104:%.*]] = add nsw i32 [[VAL_104]], [[SUM_NEXT_103]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_104:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 105 -; CHECK-NEXT: [[ARRAYIDX_105:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_104]] -; CHECK-NEXT: [[VAL_105:%.*]] = load i32, ptr [[ARRAYIDX_105]], align 4 -; CHECK-NEXT: [[SUM_NEXT_105:%.*]] = add nsw i32 [[VAL_105]], [[SUM_NEXT_104]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_105:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 106 -; CHECK-NEXT: [[ARRAYIDX_106:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_105]] -; CHECK-NEXT: [[VAL_106:%.*]] = load i32, ptr [[ARRAYIDX_106]], align 4 -; CHECK-NEXT: [[SUM_NEXT_106:%.*]] = add nsw i32 [[VAL_106]], [[SUM_NEXT_105]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_106:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 107 -; CHECK-NEXT: [[ARRAYIDX_107:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_106]] -; CHECK-NEXT: [[VAL_107:%.*]] = load i32, ptr [[ARRAYIDX_107]], align 4 -; CHECK-NEXT: [[SUM_NEXT_107:%.*]] = add nsw i32 [[VAL_107]], [[SUM_NEXT_106]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_107:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 108 -; CHECK-NEXT: [[ARRAYIDX_108:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_107]] -; CHECK-NEXT: [[VAL_108:%.*]] = load i32, ptr [[ARRAYIDX_108]], align 4 -; CHECK-NEXT: [[SUM_NEXT_108:%.*]] = add nsw i32 [[VAL_108]], [[SUM_NEXT_107]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_108:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 109 -; CHECK-NEXT: [[ARRAYIDX_109:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_108]] -; CHECK-NEXT: [[VAL_109:%.*]] = load i32, ptr [[ARRAYIDX_109]], align 4 -; CHECK-NEXT: [[SUM_NEXT_109:%.*]] = add nsw i32 [[VAL_109]], [[SUM_NEXT_108]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_109:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 110 -; CHECK-NEXT: [[ARRAYIDX_110:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_109]] -; CHECK-NEXT: [[VAL_110:%.*]] = load i32, ptr [[ARRAYIDX_110]], align 4 -; CHECK-NEXT: [[SUM_NEXT_110:%.*]] = add nsw i32 [[VAL_110]], [[SUM_NEXT_109]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_110:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 111 -; CHECK-NEXT: [[ARRAYIDX_111:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_110]] -; CHECK-NEXT: [[VAL_111:%.*]] = load i32, ptr [[ARRAYIDX_111]], align 4 -; CHECK-NEXT: [[SUM_NEXT_111:%.*]] = add nsw i32 [[VAL_111]], [[SUM_NEXT_110]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_111:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 112 -; CHECK-NEXT: [[ARRAYIDX_112:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_111]] -; CHECK-NEXT: [[VAL_112:%.*]] = load i32, ptr [[ARRAYIDX_112]], align 4 -; CHECK-NEXT: [[SUM_NEXT_112:%.*]] = add nsw i32 [[VAL_112]], [[SUM_NEXT_111]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_112:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 113 -; CHECK-NEXT: [[ARRAYIDX_113:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_112]] -; CHECK-NEXT: [[VAL_113:%.*]] = load i32, ptr [[ARRAYIDX_113]], align 4 -; CHECK-NEXT: [[SUM_NEXT_113:%.*]] = add nsw i32 [[VAL_113]], [[SUM_NEXT_112]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_113:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 114 -; CHECK-NEXT: [[ARRAYIDX_114:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_113]] -; CHECK-NEXT: [[VAL_114:%.*]] = load i32, ptr [[ARRAYIDX_114]], align 4 -; CHECK-NEXT: [[SUM_NEXT_114:%.*]] = add nsw i32 [[VAL_114]], [[SUM_NEXT_113]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_114:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 115 -; CHECK-NEXT: [[ARRAYIDX_115:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_114]] -; CHECK-NEXT: [[VAL_115:%.*]] = load i32, ptr [[ARRAYIDX_115]], align 4 -; CHECK-NEXT: [[SUM_NEXT_115:%.*]] = add nsw i32 [[VAL_115]], [[SUM_NEXT_114]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_115:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 116 -; CHECK-NEXT: [[ARRAYIDX_116:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_115]] -; CHECK-NEXT: [[VAL_116:%.*]] = load i32, ptr [[ARRAYIDX_116]], align 4 -; CHECK-NEXT: [[SUM_NEXT_116:%.*]] = add nsw i32 [[VAL_116]], [[SUM_NEXT_115]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_116:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 117 -; CHECK-NEXT: [[ARRAYIDX_117:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_116]] -; CHECK-NEXT: [[VAL_117:%.*]] = load i32, ptr [[ARRAYIDX_117]], align 4 -; CHECK-NEXT: [[SUM_NEXT_117:%.*]] = add nsw i32 [[VAL_117]], [[SUM_NEXT_116]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_117:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 118 -; CHECK-NEXT: [[ARRAYIDX_118:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_117]] -; CHECK-NEXT: [[VAL_118:%.*]] = load i32, ptr [[ARRAYIDX_118]], align 4 -; CHECK-NEXT: [[SUM_NEXT_118:%.*]] = add nsw i32 [[VAL_118]], [[SUM_NEXT_117]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_118:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 119 -; CHECK-NEXT: [[ARRAYIDX_119:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_118]] -; CHECK-NEXT: [[VAL_119:%.*]] = load i32, ptr [[ARRAYIDX_119]], align 4 -; CHECK-NEXT: [[SUM_NEXT_119:%.*]] = add nsw i32 [[VAL_119]], [[SUM_NEXT_118]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_119:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 120 -; CHECK-NEXT: [[ARRAYIDX_120:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_119]] -; CHECK-NEXT: [[VAL_120:%.*]] = load i32, ptr [[ARRAYIDX_120]], align 4 -; CHECK-NEXT: [[SUM_NEXT_120:%.*]] = add nsw i32 [[VAL_120]], [[SUM_NEXT_119]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_120:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 121 -; CHECK-NEXT: [[ARRAYIDX_121:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_120]] -; CHECK-NEXT: [[VAL_121:%.*]] = load i32, ptr [[ARRAYIDX_121]], align 4 -; CHECK-NEXT: [[SUM_NEXT_121:%.*]] = add nsw i32 [[VAL_121]], [[SUM_NEXT_120]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_121:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 122 -; CHECK-NEXT: [[ARRAYIDX_122:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_121]] -; CHECK-NEXT: [[VAL_122:%.*]] = load i32, ptr [[ARRAYIDX_122]], align 4 -; CHECK-NEXT: [[SUM_NEXT_122:%.*]] = add nsw i32 [[VAL_122]], [[SUM_NEXT_121]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_122:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 123 -; CHECK-NEXT: [[ARRAYIDX_123:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_122]] -; CHECK-NEXT: [[VAL_123:%.*]] = load i32, ptr [[ARRAYIDX_123]], align 4 -; CHECK-NEXT: [[SUM_NEXT_123:%.*]] = add nsw i32 [[VAL_123]], [[SUM_NEXT_122]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_123:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 124 -; CHECK-NEXT: [[ARRAYIDX_124:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_123]] -; CHECK-NEXT: [[VAL_124:%.*]] = load i32, ptr [[ARRAYIDX_124]], align 4 -; CHECK-NEXT: [[SUM_NEXT_124:%.*]] = add nsw i32 [[VAL_124]], [[SUM_NEXT_123]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_124:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 125 -; CHECK-NEXT: [[ARRAYIDX_125:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_124]] -; CHECK-NEXT: [[VAL_125:%.*]] = load i32, ptr [[ARRAYIDX_125]], align 4 -; CHECK-NEXT: [[SUM_NEXT_125:%.*]] = add nsw i32 [[VAL_125]], [[SUM_NEXT_124]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_125:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 126 -; CHECK-NEXT: [[ARRAYIDX_126:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_125]] -; CHECK-NEXT: [[VAL_126:%.*]] = load i32, ptr [[ARRAYIDX_126]], align 4 -; CHECK-NEXT: [[SUM_NEXT_126:%.*]] = add nsw i32 [[VAL_126]], [[SUM_NEXT_125]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_126:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 127 -; CHECK-NEXT: [[ARRAYIDX_127:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_126]] -; CHECK-NEXT: [[VAL_127:%.*]] = load i32, ptr [[ARRAYIDX_127]], align 4 -; CHECK-NEXT: [[SUM_NEXT_127]] = add nsw i32 [[VAL_127]], [[SUM_NEXT_126]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_127]] = add nuw nsw i64 [[INDVARS_IV]], 128 -; CHECK-NEXT: [[EXITCOND_NOT_127:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT_127]], 8192 -; CHECK-NEXT: br i1 [[EXITCOND_NOT_127]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK-NEXT: [[SUM_NEXT_31]] = add nsw i32 [[VAL_31]], [[SUM_NEXT_30]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_31]] = add nuw nsw i64 [[INDVARS_IV]], 32 +; CHECK-NEXT: [[EXITCOND_NOT_31:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT_31]], 8192 +; CHECK-NEXT: br i1 [[EXITCOND_NOT_31]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] ; CHECK: for.cond.cleanup: -; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT_127]], [[FOR_BODY]] ] +; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT_31]], [[FOR_BODY]] ] ; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]] ; entry: @@ -551,16 +167,16 @@ define i32 @test2(ptr %ary, i64 %n) "target-cpu"="znver3" { ; CHECK-SAME: ptr [[ARY:%.*]], i64 [[N:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1 -; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[N]], 7 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 7 +; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[N]], 1 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 1 ; CHECK-NEXT: br i1 [[TMP1]], label [[FOR_COND_CLEANUP_UNR_LCSSA:%.*]], label [[ENTRY_NEW:%.*]] ; CHECK: entry.new: ; CHECK-NEXT: [[UNROLL_ITER:%.*]] = sub i64 [[N]], [[XTRAITER]] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY_NEW]] ], [ [[INDVARS_IV_NEXT_7:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY_NEW]] ], [ [[SUM_NEXT_7:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[NITER:%.*]] = phi i64 [ 0, [[ENTRY_NEW]] ], [ [[NITER_NEXT_7:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY_NEW]] ], [ [[INDVARS_IV_NEXT_1:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY_NEW]] ], [ [[SUM_NEXT_1:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[NITER:%.*]] = phi i64 [ 0, [[ENTRY_NEW]] ], [ [[NITER_NEXT_1:%.*]], [[FOR_BODY]] ] ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV]] ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 ; CHECK-NEXT: [[DUMMY1:%.*]] = mul i32 [[VAL]], [[VAL]] @@ -667,339 +283,15 @@ define i32 @test2(ptr %ary, i64 %n) "target-cpu"="znver3" { ; CHECK-NEXT: [[DUMMY48_1:%.*]] = mul i32 [[DUMMY47_1]], [[DUMMY47_1]] ; CHECK-NEXT: [[DUMMY49_1:%.*]] = mul i32 [[DUMMY48_1]], [[DUMMY48_1]] ; CHECK-NEXT: [[DUMMY50_1:%.*]] = mul i32 [[DUMMY49_1]], [[DUMMY49_1]] -; CHECK-NEXT: [[SUM_NEXT_1:%.*]] = add nsw i32 [[DUMMY50_1]], [[SUM_NEXT]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 2 -; CHECK-NEXT: [[ARRAYIDX_2:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_1]] -; CHECK-NEXT: [[VAL_2:%.*]] = load i32, ptr [[ARRAYIDX_2]], align 4 -; CHECK-NEXT: [[DUMMY1_2:%.*]] = mul i32 [[VAL_2]], [[VAL_2]] -; CHECK-NEXT: [[DUMMY2_2:%.*]] = mul i32 [[DUMMY1_2]], [[DUMMY1_2]] -; CHECK-NEXT: [[DUMMY3_2:%.*]] = mul i32 [[DUMMY2_2]], [[DUMMY2_2]] -; CHECK-NEXT: [[DUMMY4_2:%.*]] = mul i32 [[DUMMY3_2]], [[DUMMY3_2]] -; CHECK-NEXT: [[DUMMY5_2:%.*]] = mul i32 [[DUMMY4_2]], [[DUMMY4_2]] -; CHECK-NEXT: [[DUMMY6_2:%.*]] = mul i32 [[DUMMY5_2]], [[DUMMY5_2]] -; CHECK-NEXT: [[DUMMY7_2:%.*]] = mul i32 [[DUMMY6_2]], [[DUMMY6_2]] -; CHECK-NEXT: [[DUMMY8_2:%.*]] = mul i32 [[DUMMY7_2]], [[DUMMY7_2]] -; CHECK-NEXT: [[DUMMY9_2:%.*]] = mul i32 [[DUMMY8_2]], [[DUMMY8_2]] -; CHECK-NEXT: [[DUMMY10_2:%.*]] = mul i32 [[DUMMY9_2]], [[DUMMY9_2]] -; CHECK-NEXT: [[DUMMY11_2:%.*]] = mul i32 [[DUMMY10_2]], [[DUMMY10_2]] -; CHECK-NEXT: [[DUMMY12_2:%.*]] = mul i32 [[DUMMY11_2]], [[DUMMY11_2]] -; CHECK-NEXT: [[DUMMY13_2:%.*]] = mul i32 [[DUMMY12_2]], [[DUMMY12_2]] -; CHECK-NEXT: [[DUMMY14_2:%.*]] = mul i32 [[DUMMY13_2]], [[DUMMY13_2]] -; CHECK-NEXT: [[DUMMY15_2:%.*]] = mul i32 [[DUMMY14_2]], [[DUMMY14_2]] -; CHECK-NEXT: [[DUMMY16_2:%.*]] = mul i32 [[DUMMY15_2]], [[DUMMY15_2]] -; CHECK-NEXT: [[DUMMY17_2:%.*]] = mul i32 [[DUMMY16_2]], [[DUMMY16_2]] -; CHECK-NEXT: [[DUMMY18_2:%.*]] = mul i32 [[DUMMY17_2]], [[DUMMY17_2]] -; CHECK-NEXT: [[DUMMY19_2:%.*]] = mul i32 [[DUMMY18_2]], [[DUMMY18_2]] -; CHECK-NEXT: [[DUMMY20_2:%.*]] = mul i32 [[DUMMY19_2]], [[DUMMY19_2]] -; CHECK-NEXT: [[DUMMY21_2:%.*]] = mul i32 [[DUMMY20_2]], [[DUMMY20_2]] -; CHECK-NEXT: [[DUMMY22_2:%.*]] = mul i32 [[DUMMY21_2]], [[DUMMY21_2]] -; CHECK-NEXT: [[DUMMY23_2:%.*]] = mul i32 [[DUMMY22_2]], [[DUMMY22_2]] -; CHECK-NEXT: [[DUMMY24_2:%.*]] = mul i32 [[DUMMY23_2]], [[DUMMY23_2]] -; CHECK-NEXT: [[DUMMY25_2:%.*]] = mul i32 [[DUMMY24_2]], [[DUMMY24_2]] -; CHECK-NEXT: [[DUMMY26_2:%.*]] = mul i32 [[DUMMY25_2]], [[DUMMY25_2]] -; CHECK-NEXT: [[DUMMY27_2:%.*]] = mul i32 [[DUMMY26_2]], [[DUMMY26_2]] -; CHECK-NEXT: [[DUMMY28_2:%.*]] = mul i32 [[DUMMY27_2]], [[DUMMY27_2]] -; CHECK-NEXT: [[DUMMY29_2:%.*]] = mul i32 [[DUMMY28_2]], [[DUMMY28_2]] -; CHECK-NEXT: [[DUMMY30_2:%.*]] = mul i32 [[DUMMY29_2]], [[DUMMY29_2]] -; CHECK-NEXT: [[DUMMY31_2:%.*]] = mul i32 [[DUMMY30_2]], [[DUMMY30_2]] -; CHECK-NEXT: [[DUMMY32_2:%.*]] = mul i32 [[DUMMY31_2]], [[DUMMY31_2]] -; CHECK-NEXT: [[DUMMY33_2:%.*]] = mul i32 [[DUMMY32_2]], [[DUMMY32_2]] -; CHECK-NEXT: [[DUMMY34_2:%.*]] = mul i32 [[DUMMY33_2]], [[DUMMY33_2]] -; CHECK-NEXT: [[DUMMY35_2:%.*]] = mul i32 [[DUMMY34_2]], [[DUMMY34_2]] -; CHECK-NEXT: [[DUMMY36_2:%.*]] = mul i32 [[DUMMY35_2]], [[DUMMY35_2]] -; CHECK-NEXT: [[DUMMY37_2:%.*]] = mul i32 [[DUMMY36_2]], [[DUMMY36_2]] -; CHECK-NEXT: [[DUMMY38_2:%.*]] = mul i32 [[DUMMY37_2]], [[DUMMY37_2]] -; CHECK-NEXT: [[DUMMY39_2:%.*]] = mul i32 [[DUMMY38_2]], [[DUMMY38_2]] -; CHECK-NEXT: [[DUMMY40_2:%.*]] = mul i32 [[DUMMY39_2]], [[DUMMY39_2]] -; CHECK-NEXT: [[DUMMY41_2:%.*]] = mul i32 [[DUMMY40_2]], [[DUMMY40_2]] -; CHECK-NEXT: [[DUMMY42_2:%.*]] = mul i32 [[DUMMY41_2]], [[DUMMY41_2]] -; CHECK-NEXT: [[DUMMY43_2:%.*]] = mul i32 [[DUMMY42_2]], [[DUMMY42_2]] -; CHECK-NEXT: [[DUMMY44_2:%.*]] = mul i32 [[DUMMY43_2]], [[DUMMY43_2]] -; CHECK-NEXT: [[DUMMY45_2:%.*]] = mul i32 [[DUMMY44_2]], [[DUMMY44_2]] -; CHECK-NEXT: [[DUMMY46_2:%.*]] = mul i32 [[DUMMY45_2]], [[DUMMY45_2]] -; CHECK-NEXT: [[DUMMY47_2:%.*]] = mul i32 [[DUMMY46_2]], [[DUMMY46_2]] -; CHECK-NEXT: [[DUMMY48_2:%.*]] = mul i32 [[DUMMY47_2]], [[DUMMY47_2]] -; CHECK-NEXT: [[DUMMY49_2:%.*]] = mul i32 [[DUMMY48_2]], [[DUMMY48_2]] -; CHECK-NEXT: [[DUMMY50_2:%.*]] = mul i32 [[DUMMY49_2]], [[DUMMY49_2]] -; CHECK-NEXT: [[SUM_NEXT_2:%.*]] = add nsw i32 [[DUMMY50_2]], [[SUM_NEXT_1]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_2:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 3 -; CHECK-NEXT: [[ARRAYIDX_3:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_2]] -; CHECK-NEXT: [[VAL_3:%.*]] = load i32, ptr [[ARRAYIDX_3]], align 4 -; CHECK-NEXT: [[DUMMY1_3:%.*]] = mul i32 [[VAL_3]], [[VAL_3]] -; CHECK-NEXT: [[DUMMY2_3:%.*]] = mul i32 [[DUMMY1_3]], [[DUMMY1_3]] -; CHECK-NEXT: [[DUMMY3_3:%.*]] = mul i32 [[DUMMY2_3]], [[DUMMY2_3]] -; CHECK-NEXT: [[DUMMY4_3:%.*]] = mul i32 [[DUMMY3_3]], [[DUMMY3_3]] -; CHECK-NEXT: [[DUMMY5_3:%.*]] = mul i32 [[DUMMY4_3]], [[DUMMY4_3]] -; CHECK-NEXT: [[DUMMY6_3:%.*]] = mul i32 [[DUMMY5_3]], [[DUMMY5_3]] -; CHECK-NEXT: [[DUMMY7_3:%.*]] = mul i32 [[DUMMY6_3]], [[DUMMY6_3]] -; CHECK-NEXT: [[DUMMY8_3:%.*]] = mul i32 [[DUMMY7_3]], [[DUMMY7_3]] -; CHECK-NEXT: [[DUMMY9_3:%.*]] = mul i32 [[DUMMY8_3]], [[DUMMY8_3]] -; CHECK-NEXT: [[DUMMY10_3:%.*]] = mul i32 [[DUMMY9_3]], [[DUMMY9_3]] -; CHECK-NEXT: [[DUMMY11_3:%.*]] = mul i32 [[DUMMY10_3]], [[DUMMY10_3]] -; CHECK-NEXT: [[DUMMY12_3:%.*]] = mul i32 [[DUMMY11_3]], [[DUMMY11_3]] -; CHECK-NEXT: [[DUMMY13_3:%.*]] = mul i32 [[DUMMY12_3]], [[DUMMY12_3]] -; CHECK-NEXT: [[DUMMY14_3:%.*]] = mul i32 [[DUMMY13_3]], [[DUMMY13_3]] -; CHECK-NEXT: [[DUMMY15_3:%.*]] = mul i32 [[DUMMY14_3]], [[DUMMY14_3]] -; CHECK-NEXT: [[DUMMY16_3:%.*]] = mul i32 [[DUMMY15_3]], [[DUMMY15_3]] -; CHECK-NEXT: [[DUMMY17_3:%.*]] = mul i32 [[DUMMY16_3]], [[DUMMY16_3]] -; CHECK-NEXT: [[DUMMY18_3:%.*]] = mul i32 [[DUMMY17_3]], [[DUMMY17_3]] -; CHECK-NEXT: [[DUMMY19_3:%.*]] = mul i32 [[DUMMY18_3]], [[DUMMY18_3]] -; CHECK-NEXT: [[DUMMY20_3:%.*]] = mul i32 [[DUMMY19_3]], [[DUMMY19_3]] -; CHECK-NEXT: [[DUMMY21_3:%.*]] = mul i32 [[DUMMY20_3]], [[DUMMY20_3]] -; CHECK-NEXT: [[DUMMY22_3:%.*]] = mul i32 [[DUMMY21_3]], [[DUMMY21_3]] -; CHECK-NEXT: [[DUMMY23_3:%.*]] = mul i32 [[DUMMY22_3]], [[DUMMY22_3]] -; CHECK-NEXT: [[DUMMY24_3:%.*]] = mul i32 [[DUMMY23_3]], [[DUMMY23_3]] -; CHECK-NEXT: [[DUMMY25_3:%.*]] = mul i32 [[DUMMY24_3]], [[DUMMY24_3]] -; CHECK-NEXT: [[DUMMY26_3:%.*]] = mul i32 [[DUMMY25_3]], [[DUMMY25_3]] -; CHECK-NEXT: [[DUMMY27_3:%.*]] = mul i32 [[DUMMY26_3]], [[DUMMY26_3]] -; CHECK-NEXT: [[DUMMY28_3:%.*]] = mul i32 [[DUMMY27_3]], [[DUMMY27_3]] -; CHECK-NEXT: [[DUMMY29_3:%.*]] = mul i32 [[DUMMY28_3]], [[DUMMY28_3]] -; CHECK-NEXT: [[DUMMY30_3:%.*]] = mul i32 [[DUMMY29_3]], [[DUMMY29_3]] -; CHECK-NEXT: [[DUMMY31_3:%.*]] = mul i32 [[DUMMY30_3]], [[DUMMY30_3]] -; CHECK-NEXT: [[DUMMY32_3:%.*]] = mul i32 [[DUMMY31_3]], [[DUMMY31_3]] -; CHECK-NEXT: [[DUMMY33_3:%.*]] = mul i32 [[DUMMY32_3]], [[DUMMY32_3]] -; CHECK-NEXT: [[DUMMY34_3:%.*]] = mul i32 [[DUMMY33_3]], [[DUMMY33_3]] -; CHECK-NEXT: [[DUMMY35_3:%.*]] = mul i32 [[DUMMY34_3]], [[DUMMY34_3]] -; CHECK-NEXT: [[DUMMY36_3:%.*]] = mul i32 [[DUMMY35_3]], [[DUMMY35_3]] -; CHECK-NEXT: [[DUMMY37_3:%.*]] = mul i32 [[DUMMY36_3]], [[DUMMY36_3]] -; CHECK-NEXT: [[DUMMY38_3:%.*]] = mul i32 [[DUMMY37_3]], [[DUMMY37_3]] -; CHECK-NEXT: [[DUMMY39_3:%.*]] = mul i32 [[DUMMY38_3]], [[DUMMY38_3]] -; CHECK-NEXT: [[DUMMY40_3:%.*]] = mul i32 [[DUMMY39_3]], [[DUMMY39_3]] -; CHECK-NEXT: [[DUMMY41_3:%.*]] = mul i32 [[DUMMY40_3]], [[DUMMY40_3]] -; CHECK-NEXT: [[DUMMY42_3:%.*]] = mul i32 [[DUMMY41_3]], [[DUMMY41_3]] -; CHECK-NEXT: [[DUMMY43_3:%.*]] = mul i32 [[DUMMY42_3]], [[DUMMY42_3]] -; CHECK-NEXT: [[DUMMY44_3:%.*]] = mul i32 [[DUMMY43_3]], [[DUMMY43_3]] -; CHECK-NEXT: [[DUMMY45_3:%.*]] = mul i32 [[DUMMY44_3]], [[DUMMY44_3]] -; CHECK-NEXT: [[DUMMY46_3:%.*]] = mul i32 [[DUMMY45_3]], [[DUMMY45_3]] -; CHECK-NEXT: [[DUMMY47_3:%.*]] = mul i32 [[DUMMY46_3]], [[DUMMY46_3]] -; CHECK-NEXT: [[DUMMY48_3:%.*]] = mul i32 [[DUMMY47_3]], [[DUMMY47_3]] -; CHECK-NEXT: [[DUMMY49_3:%.*]] = mul i32 [[DUMMY48_3]], [[DUMMY48_3]] -; CHECK-NEXT: [[DUMMY50_3:%.*]] = mul i32 [[DUMMY49_3]], [[DUMMY49_3]] -; CHECK-NEXT: [[SUM_NEXT_3:%.*]] = add nsw i32 [[DUMMY50_3]], [[SUM_NEXT_2]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_3:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 4 -; CHECK-NEXT: [[ARRAYIDX_4:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_3]] -; CHECK-NEXT: [[VAL_4:%.*]] = load i32, ptr [[ARRAYIDX_4]], align 4 -; CHECK-NEXT: [[DUMMY1_4:%.*]] = mul i32 [[VAL_4]], [[VAL_4]] -; CHECK-NEXT: [[DUMMY2_4:%.*]] = mul i32 [[DUMMY1_4]], [[DUMMY1_4]] -; CHECK-NEXT: [[DUMMY3_4:%.*]] = mul i32 [[DUMMY2_4]], [[DUMMY2_4]] -; CHECK-NEXT: [[DUMMY4_4:%.*]] = mul i32 [[DUMMY3_4]], [[DUMMY3_4]] -; CHECK-NEXT: [[DUMMY5_4:%.*]] = mul i32 [[DUMMY4_4]], [[DUMMY4_4]] -; CHECK-NEXT: [[DUMMY6_4:%.*]] = mul i32 [[DUMMY5_4]], [[DUMMY5_4]] -; CHECK-NEXT: [[DUMMY7_4:%.*]] = mul i32 [[DUMMY6_4]], [[DUMMY6_4]] -; CHECK-NEXT: [[DUMMY8_4:%.*]] = mul i32 [[DUMMY7_4]], [[DUMMY7_4]] -; CHECK-NEXT: [[DUMMY9_4:%.*]] = mul i32 [[DUMMY8_4]], [[DUMMY8_4]] -; CHECK-NEXT: [[DUMMY10_4:%.*]] = mul i32 [[DUMMY9_4]], [[DUMMY9_4]] -; CHECK-NEXT: [[DUMMY11_4:%.*]] = mul i32 [[DUMMY10_4]], [[DUMMY10_4]] -; CHECK-NEXT: [[DUMMY12_4:%.*]] = mul i32 [[DUMMY11_4]], [[DUMMY11_4]] -; CHECK-NEXT: [[DUMMY13_4:%.*]] = mul i32 [[DUMMY12_4]], [[DUMMY12_4]] -; CHECK-NEXT: [[DUMMY14_4:%.*]] = mul i32 [[DUMMY13_4]], [[DUMMY13_4]] -; CHECK-NEXT: [[DUMMY15_4:%.*]] = mul i32 [[DUMMY14_4]], [[DUMMY14_4]] -; CHECK-NEXT: [[DUMMY16_4:%.*]] = mul i32 [[DUMMY15_4]], [[DUMMY15_4]] -; CHECK-NEXT: [[DUMMY17_4:%.*]] = mul i32 [[DUMMY16_4]], [[DUMMY16_4]] -; CHECK-NEXT: [[DUMMY18_4:%.*]] = mul i32 [[DUMMY17_4]], [[DUMMY17_4]] -; CHECK-NEXT: [[DUMMY19_4:%.*]] = mul i32 [[DUMMY18_4]], [[DUMMY18_4]] -; CHECK-NEXT: [[DUMMY20_4:%.*]] = mul i32 [[DUMMY19_4]], [[DUMMY19_4]] -; CHECK-NEXT: [[DUMMY21_4:%.*]] = mul i32 [[DUMMY20_4]], [[DUMMY20_4]] -; CHECK-NEXT: [[DUMMY22_4:%.*]] = mul i32 [[DUMMY21_4]], [[DUMMY21_4]] -; CHECK-NEXT: [[DUMMY23_4:%.*]] = mul i32 [[DUMMY22_4]], [[DUMMY22_4]] -; CHECK-NEXT: [[DUMMY24_4:%.*]] = mul i32 [[DUMMY23_4]], [[DUMMY23_4]] -; CHECK-NEXT: [[DUMMY25_4:%.*]] = mul i32 [[DUMMY24_4]], [[DUMMY24_4]] -; CHECK-NEXT: [[DUMMY26_4:%.*]] = mul i32 [[DUMMY25_4]], [[DUMMY25_4]] -; CHECK-NEXT: [[DUMMY27_4:%.*]] = mul i32 [[DUMMY26_4]], [[DUMMY26_4]] -; CHECK-NEXT: [[DUMMY28_4:%.*]] = mul i32 [[DUMMY27_4]], [[DUMMY27_4]] -; CHECK-NEXT: [[DUMMY29_4:%.*]] = mul i32 [[DUMMY28_4]], [[DUMMY28_4]] -; CHECK-NEXT: [[DUMMY30_4:%.*]] = mul i32 [[DUMMY29_4]], [[DUMMY29_4]] -; CHECK-NEXT: [[DUMMY31_4:%.*]] = mul i32 [[DUMMY30_4]], [[DUMMY30_4]] -; CHECK-NEXT: [[DUMMY32_4:%.*]] = mul i32 [[DUMMY31_4]], [[DUMMY31_4]] -; CHECK-NEXT: [[DUMMY33_4:%.*]] = mul i32 [[DUMMY32_4]], [[DUMMY32_4]] -; CHECK-NEXT: [[DUMMY34_4:%.*]] = mul i32 [[DUMMY33_4]], [[DUMMY33_4]] -; CHECK-NEXT: [[DUMMY35_4:%.*]] = mul i32 [[DUMMY34_4]], [[DUMMY34_4]] -; CHECK-NEXT: [[DUMMY36_4:%.*]] = mul i32 [[DUMMY35_4]], [[DUMMY35_4]] -; CHECK-NEXT: [[DUMMY37_4:%.*]] = mul i32 [[DUMMY36_4]], [[DUMMY36_4]] -; CHECK-NEXT: [[DUMMY38_4:%.*]] = mul i32 [[DUMMY37_4]], [[DUMMY37_4]] -; CHECK-NEXT: [[DUMMY39_4:%.*]] = mul i32 [[DUMMY38_4]], [[DUMMY38_4]] -; CHECK-NEXT: [[DUMMY40_4:%.*]] = mul i32 [[DUMMY39_4]], [[DUMMY39_4]] -; CHECK-NEXT: [[DUMMY41_4:%.*]] = mul i32 [[DUMMY40_4]], [[DUMMY40_4]] -; CHECK-NEXT: [[DUMMY42_4:%.*]] = mul i32 [[DUMMY41_4]], [[DUMMY41_4]] -; CHECK-NEXT: [[DUMMY43_4:%.*]] = mul i32 [[DUMMY42_4]], [[DUMMY42_4]] -; CHECK-NEXT: [[DUMMY44_4:%.*]] = mul i32 [[DUMMY43_4]], [[DUMMY43_4]] -; CHECK-NEXT: [[DUMMY45_4:%.*]] = mul i32 [[DUMMY44_4]], [[DUMMY44_4]] -; CHECK-NEXT: [[DUMMY46_4:%.*]] = mul i32 [[DUMMY45_4]], [[DUMMY45_4]] -; CHECK-NEXT: [[DUMMY47_4:%.*]] = mul i32 [[DUMMY46_4]], [[DUMMY46_4]] -; CHECK-NEXT: [[DUMMY48_4:%.*]] = mul i32 [[DUMMY47_4]], [[DUMMY47_4]] -; CHECK-NEXT: [[DUMMY49_4:%.*]] = mul i32 [[DUMMY48_4]], [[DUMMY48_4]] -; CHECK-NEXT: [[DUMMY50_4:%.*]] = mul i32 [[DUMMY49_4]], [[DUMMY49_4]] -; CHECK-NEXT: [[SUM_NEXT_4:%.*]] = add nsw i32 [[DUMMY50_4]], [[SUM_NEXT_3]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_4:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 5 -; CHECK-NEXT: [[ARRAYIDX_5:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_4]] -; CHECK-NEXT: [[VAL_5:%.*]] = load i32, ptr [[ARRAYIDX_5]], align 4 -; CHECK-NEXT: [[DUMMY1_5:%.*]] = mul i32 [[VAL_5]], [[VAL_5]] -; CHECK-NEXT: [[DUMMY2_5:%.*]] = mul i32 [[DUMMY1_5]], [[DUMMY1_5]] -; CHECK-NEXT: [[DUMMY3_5:%.*]] = mul i32 [[DUMMY2_5]], [[DUMMY2_5]] -; CHECK-NEXT: [[DUMMY4_5:%.*]] = mul i32 [[DUMMY3_5]], [[DUMMY3_5]] -; CHECK-NEXT: [[DUMMY5_5:%.*]] = mul i32 [[DUMMY4_5]], [[DUMMY4_5]] -; CHECK-NEXT: [[DUMMY6_5:%.*]] = mul i32 [[DUMMY5_5]], [[DUMMY5_5]] -; CHECK-NEXT: [[DUMMY7_5:%.*]] = mul i32 [[DUMMY6_5]], [[DUMMY6_5]] -; CHECK-NEXT: [[DUMMY8_5:%.*]] = mul i32 [[DUMMY7_5]], [[DUMMY7_5]] -; CHECK-NEXT: [[DUMMY9_5:%.*]] = mul i32 [[DUMMY8_5]], [[DUMMY8_5]] -; CHECK-NEXT: [[DUMMY10_5:%.*]] = mul i32 [[DUMMY9_5]], [[DUMMY9_5]] -; CHECK-NEXT: [[DUMMY11_5:%.*]] = mul i32 [[DUMMY10_5]], [[DUMMY10_5]] -; CHECK-NEXT: [[DUMMY12_5:%.*]] = mul i32 [[DUMMY11_5]], [[DUMMY11_5]] -; CHECK-NEXT: [[DUMMY13_5:%.*]] = mul i32 [[DUMMY12_5]], [[DUMMY12_5]] -; CHECK-NEXT: [[DUMMY14_5:%.*]] = mul i32 [[DUMMY13_5]], [[DUMMY13_5]] -; CHECK-NEXT: [[DUMMY15_5:%.*]] = mul i32 [[DUMMY14_5]], [[DUMMY14_5]] -; CHECK-NEXT: [[DUMMY16_5:%.*]] = mul i32 [[DUMMY15_5]], [[DUMMY15_5]] -; CHECK-NEXT: [[DUMMY17_5:%.*]] = mul i32 [[DUMMY16_5]], [[DUMMY16_5]] -; CHECK-NEXT: [[DUMMY18_5:%.*]] = mul i32 [[DUMMY17_5]], [[DUMMY17_5]] -; CHECK-NEXT: [[DUMMY19_5:%.*]] = mul i32 [[DUMMY18_5]], [[DUMMY18_5]] -; CHECK-NEXT: [[DUMMY20_5:%.*]] = mul i32 [[DUMMY19_5]], [[DUMMY19_5]] -; CHECK-NEXT: [[DUMMY21_5:%.*]] = mul i32 [[DUMMY20_5]], [[DUMMY20_5]] -; CHECK-NEXT: [[DUMMY22_5:%.*]] = mul i32 [[DUMMY21_5]], [[DUMMY21_5]] -; CHECK-NEXT: [[DUMMY23_5:%.*]] = mul i32 [[DUMMY22_5]], [[DUMMY22_5]] -; CHECK-NEXT: [[DUMMY24_5:%.*]] = mul i32 [[DUMMY23_5]], [[DUMMY23_5]] -; CHECK-NEXT: [[DUMMY25_5:%.*]] = mul i32 [[DUMMY24_5]], [[DUMMY24_5]] -; CHECK-NEXT: [[DUMMY26_5:%.*]] = mul i32 [[DUMMY25_5]], [[DUMMY25_5]] -; CHECK-NEXT: [[DUMMY27_5:%.*]] = mul i32 [[DUMMY26_5]], [[DUMMY26_5]] -; CHECK-NEXT: [[DUMMY28_5:%.*]] = mul i32 [[DUMMY27_5]], [[DUMMY27_5]] -; CHECK-NEXT: [[DUMMY29_5:%.*]] = mul i32 [[DUMMY28_5]], [[DUMMY28_5]] -; CHECK-NEXT: [[DUMMY30_5:%.*]] = mul i32 [[DUMMY29_5]], [[DUMMY29_5]] -; CHECK-NEXT: [[DUMMY31_5:%.*]] = mul i32 [[DUMMY30_5]], [[DUMMY30_5]] -; CHECK-NEXT: [[DUMMY32_5:%.*]] = mul i32 [[DUMMY31_5]], [[DUMMY31_5]] -; CHECK-NEXT: [[DUMMY33_5:%.*]] = mul i32 [[DUMMY32_5]], [[DUMMY32_5]] -; CHECK-NEXT: [[DUMMY34_5:%.*]] = mul i32 [[DUMMY33_5]], [[DUMMY33_5]] -; CHECK-NEXT: [[DUMMY35_5:%.*]] = mul i32 [[DUMMY34_5]], [[DUMMY34_5]] -; CHECK-NEXT: [[DUMMY36_5:%.*]] = mul i32 [[DUMMY35_5]], [[DUMMY35_5]] -; CHECK-NEXT: [[DUMMY37_5:%.*]] = mul i32 [[DUMMY36_5]], [[DUMMY36_5]] -; CHECK-NEXT: [[DUMMY38_5:%.*]] = mul i32 [[DUMMY37_5]], [[DUMMY37_5]] -; CHECK-NEXT: [[DUMMY39_5:%.*]] = mul i32 [[DUMMY38_5]], [[DUMMY38_5]] -; CHECK-NEXT: [[DUMMY40_5:%.*]] = mul i32 [[DUMMY39_5]], [[DUMMY39_5]] -; CHECK-NEXT: [[DUMMY41_5:%.*]] = mul i32 [[DUMMY40_5]], [[DUMMY40_5]] -; CHECK-NEXT: [[DUMMY42_5:%.*]] = mul i32 [[DUMMY41_5]], [[DUMMY41_5]] -; CHECK-NEXT: [[DUMMY43_5:%.*]] = mul i32 [[DUMMY42_5]], [[DUMMY42_5]] -; CHECK-NEXT: [[DUMMY44_5:%.*]] = mul i32 [[DUMMY43_5]], [[DUMMY43_5]] -; CHECK-NEXT: [[DUMMY45_5:%.*]] = mul i32 [[DUMMY44_5]], [[DUMMY44_5]] -; CHECK-NEXT: [[DUMMY46_5:%.*]] = mul i32 [[DUMMY45_5]], [[DUMMY45_5]] -; CHECK-NEXT: [[DUMMY47_5:%.*]] = mul i32 [[DUMMY46_5]], [[DUMMY46_5]] -; CHECK-NEXT: [[DUMMY48_5:%.*]] = mul i32 [[DUMMY47_5]], [[DUMMY47_5]] -; CHECK-NEXT: [[DUMMY49_5:%.*]] = mul i32 [[DUMMY48_5]], [[DUMMY48_5]] -; CHECK-NEXT: [[DUMMY50_5:%.*]] = mul i32 [[DUMMY49_5]], [[DUMMY49_5]] -; CHECK-NEXT: [[SUM_NEXT_5:%.*]] = add nsw i32 [[DUMMY50_5]], [[SUM_NEXT_4]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_5:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 6 -; CHECK-NEXT: [[ARRAYIDX_6:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_5]] -; CHECK-NEXT: [[VAL_6:%.*]] = load i32, ptr [[ARRAYIDX_6]], align 4 -; CHECK-NEXT: [[DUMMY1_6:%.*]] = mul i32 [[VAL_6]], [[VAL_6]] -; CHECK-NEXT: [[DUMMY2_6:%.*]] = mul i32 [[DUMMY1_6]], [[DUMMY1_6]] -; CHECK-NEXT: [[DUMMY3_6:%.*]] = mul i32 [[DUMMY2_6]], [[DUMMY2_6]] -; CHECK-NEXT: [[DUMMY4_6:%.*]] = mul i32 [[DUMMY3_6]], [[DUMMY3_6]] -; CHECK-NEXT: [[DUMMY5_6:%.*]] = mul i32 [[DUMMY4_6]], [[DUMMY4_6]] -; CHECK-NEXT: [[DUMMY6_6:%.*]] = mul i32 [[DUMMY5_6]], [[DUMMY5_6]] -; CHECK-NEXT: [[DUMMY7_6:%.*]] = mul i32 [[DUMMY6_6]], [[DUMMY6_6]] -; CHECK-NEXT: [[DUMMY8_6:%.*]] = mul i32 [[DUMMY7_6]], [[DUMMY7_6]] -; CHECK-NEXT: [[DUMMY9_6:%.*]] = mul i32 [[DUMMY8_6]], [[DUMMY8_6]] -; CHECK-NEXT: [[DUMMY10_6:%.*]] = mul i32 [[DUMMY9_6]], [[DUMMY9_6]] -; CHECK-NEXT: [[DUMMY11_6:%.*]] = mul i32 [[DUMMY10_6]], [[DUMMY10_6]] -; CHECK-NEXT: [[DUMMY12_6:%.*]] = mul i32 [[DUMMY11_6]], [[DUMMY11_6]] -; CHECK-NEXT: [[DUMMY13_6:%.*]] = mul i32 [[DUMMY12_6]], [[DUMMY12_6]] -; CHECK-NEXT: [[DUMMY14_6:%.*]] = mul i32 [[DUMMY13_6]], [[DUMMY13_6]] -; CHECK-NEXT: [[DUMMY15_6:%.*]] = mul i32 [[DUMMY14_6]], [[DUMMY14_6]] -; CHECK-NEXT: [[DUMMY16_6:%.*]] = mul i32 [[DUMMY15_6]], [[DUMMY15_6]] -; CHECK-NEXT: [[DUMMY17_6:%.*]] = mul i32 [[DUMMY16_6]], [[DUMMY16_6]] -; CHECK-NEXT: [[DUMMY18_6:%.*]] = mul i32 [[DUMMY17_6]], [[DUMMY17_6]] -; CHECK-NEXT: [[DUMMY19_6:%.*]] = mul i32 [[DUMMY18_6]], [[DUMMY18_6]] -; CHECK-NEXT: [[DUMMY20_6:%.*]] = mul i32 [[DUMMY19_6]], [[DUMMY19_6]] -; CHECK-NEXT: [[DUMMY21_6:%.*]] = mul i32 [[DUMMY20_6]], [[DUMMY20_6]] -; CHECK-NEXT: [[DUMMY22_6:%.*]] = mul i32 [[DUMMY21_6]], [[DUMMY21_6]] -; CHECK-NEXT: [[DUMMY23_6:%.*]] = mul i32 [[DUMMY22_6]], [[DUMMY22_6]] -; CHECK-NEXT: [[DUMMY24_6:%.*]] = mul i32 [[DUMMY23_6]], [[DUMMY23_6]] -; CHECK-NEXT: [[DUMMY25_6:%.*]] = mul i32 [[DUMMY24_6]], [[DUMMY24_6]] -; CHECK-NEXT: [[DUMMY26_6:%.*]] = mul i32 [[DUMMY25_6]], [[DUMMY25_6]] -; CHECK-NEXT: [[DUMMY27_6:%.*]] = mul i32 [[DUMMY26_6]], [[DUMMY26_6]] -; CHECK-NEXT: [[DUMMY28_6:%.*]] = mul i32 [[DUMMY27_6]], [[DUMMY27_6]] -; CHECK-NEXT: [[DUMMY29_6:%.*]] = mul i32 [[DUMMY28_6]], [[DUMMY28_6]] -; CHECK-NEXT: [[DUMMY30_6:%.*]] = mul i32 [[DUMMY29_6]], [[DUMMY29_6]] -; CHECK-NEXT: [[DUMMY31_6:%.*]] = mul i32 [[DUMMY30_6]], [[DUMMY30_6]] -; CHECK-NEXT: [[DUMMY32_6:%.*]] = mul i32 [[DUMMY31_6]], [[DUMMY31_6]] -; CHECK-NEXT: [[DUMMY33_6:%.*]] = mul i32 [[DUMMY32_6]], [[DUMMY32_6]] -; CHECK-NEXT: [[DUMMY34_6:%.*]] = mul i32 [[DUMMY33_6]], [[DUMMY33_6]] -; CHECK-NEXT: [[DUMMY35_6:%.*]] = mul i32 [[DUMMY34_6]], [[DUMMY34_6]] -; CHECK-NEXT: [[DUMMY36_6:%.*]] = mul i32 [[DUMMY35_6]], [[DUMMY35_6]] -; CHECK-NEXT: [[DUMMY37_6:%.*]] = mul i32 [[DUMMY36_6]], [[DUMMY36_6]] -; CHECK-NEXT: [[DUMMY38_6:%.*]] = mul i32 [[DUMMY37_6]], [[DUMMY37_6]] -; CHECK-NEXT: [[DUMMY39_6:%.*]] = mul i32 [[DUMMY38_6]], [[DUMMY38_6]] -; CHECK-NEXT: [[DUMMY40_6:%.*]] = mul i32 [[DUMMY39_6]], [[DUMMY39_6]] -; CHECK-NEXT: [[DUMMY41_6:%.*]] = mul i32 [[DUMMY40_6]], [[DUMMY40_6]] -; CHECK-NEXT: [[DUMMY42_6:%.*]] = mul i32 [[DUMMY41_6]], [[DUMMY41_6]] -; CHECK-NEXT: [[DUMMY43_6:%.*]] = mul i32 [[DUMMY42_6]], [[DUMMY42_6]] -; CHECK-NEXT: [[DUMMY44_6:%.*]] = mul i32 [[DUMMY43_6]], [[DUMMY43_6]] -; CHECK-NEXT: [[DUMMY45_6:%.*]] = mul i32 [[DUMMY44_6]], [[DUMMY44_6]] -; CHECK-NEXT: [[DUMMY46_6:%.*]] = mul i32 [[DUMMY45_6]], [[DUMMY45_6]] -; CHECK-NEXT: [[DUMMY47_6:%.*]] = mul i32 [[DUMMY46_6]], [[DUMMY46_6]] -; CHECK-NEXT: [[DUMMY48_6:%.*]] = mul i32 [[DUMMY47_6]], [[DUMMY47_6]] -; CHECK-NEXT: [[DUMMY49_6:%.*]] = mul i32 [[DUMMY48_6]], [[DUMMY48_6]] -; CHECK-NEXT: [[DUMMY50_6:%.*]] = mul i32 [[DUMMY49_6]], [[DUMMY49_6]] -; CHECK-NEXT: [[SUM_NEXT_6:%.*]] = add nsw i32 [[DUMMY50_6]], [[SUM_NEXT_5]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_6:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 7 -; CHECK-NEXT: [[ARRAYIDX_7:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_6]] -; CHECK-NEXT: [[VAL_7:%.*]] = load i32, ptr [[ARRAYIDX_7]], align 4 -; CHECK-NEXT: [[DUMMY1_7:%.*]] = mul i32 [[VAL_7]], [[VAL_7]] -; CHECK-NEXT: [[DUMMY2_7:%.*]] = mul i32 [[DUMMY1_7]], [[DUMMY1_7]] -; CHECK-NEXT: [[DUMMY3_7:%.*]] = mul i32 [[DUMMY2_7]], [[DUMMY2_7]] -; CHECK-NEXT: [[DUMMY4_7:%.*]] = mul i32 [[DUMMY3_7]], [[DUMMY3_7]] -; CHECK-NEXT: [[DUMMY5_7:%.*]] = mul i32 [[DUMMY4_7]], [[DUMMY4_7]] -; CHECK-NEXT: [[DUMMY6_7:%.*]] = mul i32 [[DUMMY5_7]], [[DUMMY5_7]] -; CHECK-NEXT: [[DUMMY7_7:%.*]] = mul i32 [[DUMMY6_7]], [[DUMMY6_7]] -; CHECK-NEXT: [[DUMMY8_7:%.*]] = mul i32 [[DUMMY7_7]], [[DUMMY7_7]] -; CHECK-NEXT: [[DUMMY9_7:%.*]] = mul i32 [[DUMMY8_7]], [[DUMMY8_7]] -; CHECK-NEXT: [[DUMMY10_7:%.*]] = mul i32 [[DUMMY9_7]], [[DUMMY9_7]] -; CHECK-NEXT: [[DUMMY11_7:%.*]] = mul i32 [[DUMMY10_7]], [[DUMMY10_7]] -; CHECK-NEXT: [[DUMMY12_7:%.*]] = mul i32 [[DUMMY11_7]], [[DUMMY11_7]] -; CHECK-NEXT: [[DUMMY13_7:%.*]] = mul i32 [[DUMMY12_7]], [[DUMMY12_7]] -; CHECK-NEXT: [[DUMMY14_7:%.*]] = mul i32 [[DUMMY13_7]], [[DUMMY13_7]] -; CHECK-NEXT: [[DUMMY15_7:%.*]] = mul i32 [[DUMMY14_7]], [[DUMMY14_7]] -; CHECK-NEXT: [[DUMMY16_7:%.*]] = mul i32 [[DUMMY15_7]], [[DUMMY15_7]] -; CHECK-NEXT: [[DUMMY17_7:%.*]] = mul i32 [[DUMMY16_7]], [[DUMMY16_7]] -; CHECK-NEXT: [[DUMMY18_7:%.*]] = mul i32 [[DUMMY17_7]], [[DUMMY17_7]] -; CHECK-NEXT: [[DUMMY19_7:%.*]] = mul i32 [[DUMMY18_7]], [[DUMMY18_7]] -; CHECK-NEXT: [[DUMMY20_7:%.*]] = mul i32 [[DUMMY19_7]], [[DUMMY19_7]] -; CHECK-NEXT: [[DUMMY21_7:%.*]] = mul i32 [[DUMMY20_7]], [[DUMMY20_7]] -; CHECK-NEXT: [[DUMMY22_7:%.*]] = mul i32 [[DUMMY21_7]], [[DUMMY21_7]] -; CHECK-NEXT: [[DUMMY23_7:%.*]] = mul i32 [[DUMMY22_7]], [[DUMMY22_7]] -; CHECK-NEXT: [[DUMMY24_7:%.*]] = mul i32 [[DUMMY23_7]], [[DUMMY23_7]] -; CHECK-NEXT: [[DUMMY25_7:%.*]] = mul i32 [[DUMMY24_7]], [[DUMMY24_7]] -; CHECK-NEXT: [[DUMMY26_7:%.*]] = mul i32 [[DUMMY25_7]], [[DUMMY25_7]] -; CHECK-NEXT: [[DUMMY27_7:%.*]] = mul i32 [[DUMMY26_7]], [[DUMMY26_7]] -; CHECK-NEXT: [[DUMMY28_7:%.*]] = mul i32 [[DUMMY27_7]], [[DUMMY27_7]] -; CHECK-NEXT: [[DUMMY29_7:%.*]] = mul i32 [[DUMMY28_7]], [[DUMMY28_7]] -; CHECK-NEXT: [[DUMMY30_7:%.*]] = mul i32 [[DUMMY29_7]], [[DUMMY29_7]] -; CHECK-NEXT: [[DUMMY31_7:%.*]] = mul i32 [[DUMMY30_7]], [[DUMMY30_7]] -; CHECK-NEXT: [[DUMMY32_7:%.*]] = mul i32 [[DUMMY31_7]], [[DUMMY31_7]] -; CHECK-NEXT: [[DUMMY33_7:%.*]] = mul i32 [[DUMMY32_7]], [[DUMMY32_7]] -; CHECK-NEXT: [[DUMMY34_7:%.*]] = mul i32 [[DUMMY33_7]], [[DUMMY33_7]] -; CHECK-NEXT: [[DUMMY35_7:%.*]] = mul i32 [[DUMMY34_7]], [[DUMMY34_7]] -; CHECK-NEXT: [[DUMMY36_7:%.*]] = mul i32 [[DUMMY35_7]], [[DUMMY35_7]] -; CHECK-NEXT: [[DUMMY37_7:%.*]] = mul i32 [[DUMMY36_7]], [[DUMMY36_7]] -; CHECK-NEXT: [[DUMMY38_7:%.*]] = mul i32 [[DUMMY37_7]], [[DUMMY37_7]] -; CHECK-NEXT: [[DUMMY39_7:%.*]] = mul i32 [[DUMMY38_7]], [[DUMMY38_7]] -; CHECK-NEXT: [[DUMMY40_7:%.*]] = mul i32 [[DUMMY39_7]], [[DUMMY39_7]] -; CHECK-NEXT: [[DUMMY41_7:%.*]] = mul i32 [[DUMMY40_7]], [[DUMMY40_7]] -; CHECK-NEXT: [[DUMMY42_7:%.*]] = mul i32 [[DUMMY41_7]], [[DUMMY41_7]] -; CHECK-NEXT: [[DUMMY43_7:%.*]] = mul i32 [[DUMMY42_7]], [[DUMMY42_7]] -; CHECK-NEXT: [[DUMMY44_7:%.*]] = mul i32 [[DUMMY43_7]], [[DUMMY43_7]] -; CHECK-NEXT: [[DUMMY45_7:%.*]] = mul i32 [[DUMMY44_7]], [[DUMMY44_7]] -; CHECK-NEXT: [[DUMMY46_7:%.*]] = mul i32 [[DUMMY45_7]], [[DUMMY45_7]] -; CHECK-NEXT: [[DUMMY47_7:%.*]] = mul i32 [[DUMMY46_7]], [[DUMMY46_7]] -; CHECK-NEXT: [[DUMMY48_7:%.*]] = mul i32 [[DUMMY47_7]], [[DUMMY47_7]] -; CHECK-NEXT: [[DUMMY49_7:%.*]] = mul i32 [[DUMMY48_7]], [[DUMMY48_7]] -; CHECK-NEXT: [[DUMMY50_7:%.*]] = mul i32 [[DUMMY49_7]], [[DUMMY49_7]] -; CHECK-NEXT: [[SUM_NEXT_7]] = add nsw i32 [[DUMMY50_7]], [[SUM_NEXT_6]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_7]] = add nuw nsw i64 [[INDVARS_IV]], 8 -; CHECK-NEXT: [[NITER_NEXT_7]] = add i64 [[NITER]], 8 -; CHECK-NEXT: [[NITER_NCMP_7:%.*]] = icmp eq i64 [[NITER_NEXT_7]], [[UNROLL_ITER]] -; CHECK-NEXT: br i1 [[NITER_NCMP_7]], label [[FOR_COND_CLEANUP_UNR_LCSSA_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK-NEXT: [[SUM_NEXT_1]] = add nsw i32 [[DUMMY50_1]], [[SUM_NEXT]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_1]] = add nuw nsw i64 [[INDVARS_IV]], 2 +; CHECK-NEXT: [[NITER_NEXT_1]] = add i64 [[NITER]], 2 +; CHECK-NEXT: [[NITER_NCMP_1:%.*]] = icmp eq i64 [[NITER_NEXT_1]], [[UNROLL_ITER]] +; CHECK-NEXT: br i1 [[NITER_NCMP_1]], label [[FOR_COND_CLEANUP_UNR_LCSSA_LOOPEXIT:%.*]], label [[FOR_BODY]] ; CHECK: for.cond.cleanup.unr-lcssa.loopexit: -; CHECK-NEXT: [[SUM_NEXT_LCSSA_PH_PH:%.*]] = phi i32 [ [[SUM_NEXT_7]], [[FOR_BODY]] ] -; CHECK-NEXT: [[INDVARS_IV_UNR_PH:%.*]] = phi i64 [ [[INDVARS_IV_NEXT_7]], [[FOR_BODY]] ] -; CHECK-NEXT: [[SUM_UNR_PH:%.*]] = phi i32 [ [[SUM_NEXT_7]], [[FOR_BODY]] ] +; CHECK-NEXT: [[SUM_NEXT_LCSSA_PH_PH:%.*]] = phi i32 [ [[SUM_NEXT_1]], [[FOR_BODY]] ] +; CHECK-NEXT: [[INDVARS_IV_UNR_PH:%.*]] = phi i64 [ [[INDVARS_IV_NEXT_1]], [[FOR_BODY]] ] +; CHECK-NEXT: [[SUM_UNR_PH:%.*]] = phi i32 [ [[SUM_NEXT_1]], [[FOR_BODY]] ] ; CHECK-NEXT: br label [[FOR_COND_CLEANUP_UNR_LCSSA]] ; CHECK: for.cond.cleanup.unr-lcssa: ; CHECK-NEXT: [[SUM_NEXT_LCSSA_PH:%.*]] = phi i32 [ undef, [[ENTRY:%.*]] ], [ [[SUM_NEXT_LCSSA_PH_PH]], [[FOR_COND_CLEANUP_UNR_LCSSA_LOOPEXIT]] ] @@ -1010,10 +302,7 @@ define i32 @test2(ptr %ary, i64 %n) "target-cpu"="znver3" { ; CHECK: for.body.epil.preheader: ; CHECK-NEXT: br label [[FOR_BODY_EPIL:%.*]] ; CHECK: for.body.epil: -; CHECK-NEXT: [[INDVARS_IV_EPIL:%.*]] = phi i64 [ [[INDVARS_IV_UNR]], [[FOR_BODY_EPIL_PREHEADER]] ], [ [[INDVARS_IV_NEXT_EPIL:%.*]], [[FOR_BODY_EPIL]] ] -; CHECK-NEXT: [[SUM_EPIL:%.*]] = phi i32 [ [[SUM_UNR]], [[FOR_BODY_EPIL_PREHEADER]] ], [ [[SUM_NEXT_EPIL:%.*]], [[FOR_BODY_EPIL]] ] -; CHECK-NEXT: [[EPIL_ITER:%.*]] = phi i64 [ 0, [[FOR_BODY_EPIL_PREHEADER]] ], [ [[EPIL_ITER_NEXT:%.*]], [[FOR_BODY_EPIL]] ] -; CHECK-NEXT: [[ARRAYIDX_EPIL:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_EPIL]] +; CHECK-NEXT: [[ARRAYIDX_EPIL:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_UNR]] ; CHECK-NEXT: [[VAL_EPIL:%.*]] = load i32, ptr [[ARRAYIDX_EPIL]], align 4 ; CHECK-NEXT: [[DUMMY1_EPIL:%.*]] = mul i32 [[VAL_EPIL]], [[VAL_EPIL]] ; CHECK-NEXT: [[DUMMY2_EPIL:%.*]] = mul i32 [[DUMMY1_EPIL]], [[DUMMY1_EPIL]] @@ -1065,17 +354,10 @@ define i32 @test2(ptr %ary, i64 %n) "target-cpu"="znver3" { ; CHECK-NEXT: [[DUMMY48_EPIL:%.*]] = mul i32 [[DUMMY47_EPIL]], [[DUMMY47_EPIL]] ; CHECK-NEXT: [[DUMMY49_EPIL:%.*]] = mul i32 [[DUMMY48_EPIL]], [[DUMMY48_EPIL]] ; CHECK-NEXT: [[DUMMY50_EPIL:%.*]] = mul i32 [[DUMMY49_EPIL]], [[DUMMY49_EPIL]] -; CHECK-NEXT: [[SUM_NEXT_EPIL]] = add nsw i32 [[DUMMY50_EPIL]], [[SUM_EPIL]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_EPIL]] = add nuw nsw i64 [[INDVARS_IV_EPIL]], 1 -; CHECK-NEXT: [[EXITCOND_NOT_EPIL:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT_EPIL]], [[N]] -; CHECK-NEXT: [[EPIL_ITER_NEXT]] = add i64 [[EPIL_ITER]], 1 -; CHECK-NEXT: [[EPIL_ITER_CMP:%.*]] = icmp ne i64 [[EPIL_ITER_NEXT]], [[XTRAITER]] -; CHECK-NEXT: br i1 [[EPIL_ITER_CMP]], label [[FOR_BODY_EPIL]], label [[FOR_COND_CLEANUP_EPILOG_LCSSA:%.*]], !llvm.loop [[LOOP0:![0-9]+]] -; CHECK: for.cond.cleanup.epilog-lcssa: -; CHECK-NEXT: [[SUM_NEXT_LCSSA_PH1:%.*]] = phi i32 [ [[SUM_NEXT_EPIL]], [[FOR_BODY_EPIL]] ] +; CHECK-NEXT: [[SUM_NEXT_EPIL:%.*]] = add nsw i32 [[DUMMY50_EPIL]], [[SUM_UNR]] ; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] ; CHECK: for.cond.cleanup: -; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT_LCSSA_PH]], [[FOR_COND_CLEANUP_UNR_LCSSA]] ], [ [[SUM_NEXT_LCSSA_PH1]], [[FOR_COND_CLEANUP_EPILOG_LCSSA]] ] +; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT_LCSSA_PH]], [[FOR_COND_CLEANUP_UNR_LCSSA]] ], [ [[SUM_NEXT_EPIL]], [[FOR_BODY_EPIL]] ] ; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]] ; entry: -- GitLab From f60c699d37c41c46dd0be4ec98e5b4d74e73b2b7 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 15 May 2024 20:44:02 -0500 Subject: [PATCH 442/578] [OpenMP] Fix intermediate header locations for OpenMP Summary: A previous patch moved the code here and accidentally overrwrote the include path that the LSP interface used. This caused incorrect errors when using clangd with the offload project. This patch removes the unnecessary header and makes sure we include the correct folder. --- openmp/runtime/src/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt index a2468d04e60a..94eeea63b804 100644 --- a/openmp/runtime/src/CMakeLists.txt +++ b/openmp/runtime/src/CMakeLists.txt @@ -20,7 +20,7 @@ endif() # Configure omp.h, kmp_config.h and omp-tools.h if necessary configure_file(${LIBOMP_INC_DIR}/omp.h.var ${LIBOMP_HEADERS_INTDIR}/omp.h @ONLY) configure_file(${LIBOMP_INC_DIR}/ompx.h.var ${LIBOMP_HEADERS_INTDIR}/ompx.h @ONLY) -configure_file(kmp_config.h.cmake ${LIBOMP_HEADERS_INTDIR}/kmp_config.h @ONLY) +configure_file(kmp_config.h.cmake kmp_config.h @ONLY) if(${LIBOMP_OMPT_SUPPORT}) configure_file(${LIBOMP_INC_DIR}/omp-tools.h.var ${LIBOMP_HEADERS_INTDIR}/omp-tools.h @ONLY) endif() @@ -55,7 +55,6 @@ include_directories( ${LIBOMP_SRC_DIR}/i18n ${LIBOMP_INC_DIR} ${LIBOMP_SRC_DIR}/thirdparty/ittnotify - ${LIBOMP_HEADERS_INTDIR} ) # Building with time profiling support requires LLVM directory includes. @@ -441,7 +440,7 @@ if(${LIBOMP_OMPT_SUPPORT}) install(FILES ${LIBOMP_HEADERS_INTDIR}/omp-tools.h DESTINATION ${LIBOMP_HEADERS_INSTALL_PATH}) # install under legacy name ompt.h install(FILES ${LIBOMP_HEADERS_INTDIR}/omp-tools.h DESTINATION ${LIBOMP_HEADERS_INSTALL_PATH} RENAME ompt.h) - set(LIBOMP_OMP_TOOLS_INCLUDE_DIR ${LIBOMP_HEADERS_INTDIR} PARENT_SCOPE) + set(LIBOMP_OMP_TOOLS_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE) endif() if(${BUILD_FORTRAN_MODULES}) set (destination ${LIBOMP_HEADERS_INSTALL_PATH}) -- GitLab From 1595988ee6f9732e7ea79928af8a470ad5ef7dbe Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 15 May 2024 21:52:59 -0400 Subject: [PATCH 443/578] Reapply "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" (#92283) This patch reapplies #90500, addressing a bug which caused binary operators with dependent operands to be incorrectly rebuilt by `TreeTransform`. --- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/AST/Type.h | 5 +- clang/lib/Sema/SemaExpr.cpp | 363 +++++++++--------- clang/lib/Sema/TreeTransform.h | 17 +- clang/test/AST/ast-dump-expr-json.cpp | 4 +- clang/test/AST/ast-dump-expr.cpp | 2 +- clang/test/AST/ast-dump-lambda.cpp | 2 +- .../expr/expr.unary/expr.unary.general/p1.cpp | 65 ++++ clang/test/CXX/over/over.built/ast.cpp | 158 ++++++-- clang/test/CXX/over/over.built/p10.cpp | 2 +- clang/test/CXX/over/over.built/p11.cpp | 2 +- .../over/over.oper/over.oper.general/p1.cpp | 173 +++++++++ .../temp.res/temp.dep/temp.dep.type/p4.cpp | 25 +- clang/test/Frontend/noderef_templates.cpp | 4 +- clang/test/SemaCXX/cxx2b-deducing-this.cpp | 6 +- .../test/SemaTemplate/class-template-spec.cpp | 12 +- .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 6 +- 17 files changed, 586 insertions(+), 263 deletions(-) create mode 100644 clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp create mode 100644 clang/test/CXX/over/over.oper/over.oper.general/p1.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 089a85c8cb36..11812c355f8d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -56,6 +56,9 @@ C++ Specific Potentially Breaking Changes - Clang now rejects pointer to member from parenthesized expression in unevaluated context such as ``decltype(&(foo::bar))``. (#GH40906). +- 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. + ABI Changes in This Version --------------------------- - Fixed Microsoft name mangling of implicitly defined variables used for thread diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index e6643469e0b3..da3834f19ca0 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -8044,7 +8044,10 @@ inline bool Type::isUndeducedType() const { /// Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { - return isDependentType() || isRecordType() || isEnumeralType(); + if (!CanonicalType->isDependentType()) + return isRecordType() || isEnumeralType(); + return !isArrayType() && !isFunctionType() && !isAnyPointerType() && + !isMemberPointerType(); } /// Determines whether this type is written as a typedef-name. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ec84798e4ce6..50569c1cd536 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -672,12 +672,12 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // We don't want to throw lvalue-to-rvalue casts on top of // expressions of certain types in C++. - if (getLangOpts().CPlusPlus && - (E->getType() == Context.OverloadTy || - // FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied - // to pointer types even if the pointee type is dependent. - (T->isDependentType() && !T->isPointerType()) || T->isRecordType())) - return E; + if (getLangOpts().CPlusPlus) { + if (T == Context.OverloadTy || T->isRecordType() || + (T->isDependentType() && !T->isAnyPointerType() && + !T->isMemberPointerType())) + return E; + } // The C standard is actually really unclear on this point, and // DR106 tells us what the result should be but not why. It's @@ -10827,7 +10827,7 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc, if (const AtomicType *ResAtomicType = ResType->getAs()) ResType = ResAtomicType->getValueType(); - assert(ResType->isAnyPointerType() && !ResType->isDependentType()); + assert(ResType->isAnyPointerType()); QualType PointeeTy = ResType->getPointeeType(); return S.RequireCompleteSizedType( Loc, PointeeTy, @@ -13957,9 +13957,6 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, ExprObjectKind &OK, SourceLocation OpLoc, bool IsInc, bool IsPrefix) { - if (Op->isTypeDependent()) - return S.Context.DependentTy; - QualType ResType = Op->getType(); // Atomic types can be used for increment / decrement where the non-atomic // versions can, so ignore the _Atomic() specifier for the purpose of @@ -14410,9 +14407,6 @@ static void RecordModifiableNonNullParam(Sema &S, const Expr *Exp) { static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, SourceLocation OpLoc, bool IsAfterAmp = false) { - if (Op->isTypeDependent()) - return S.Context.DependentTy; - ExprResult ConvResult = S.UsualUnaryConversions(Op); if (ConvResult.isInvalid()) return QualType(); @@ -15368,14 +15362,10 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, } if (getLangOpts().CPlusPlus) { - // If either expression is type-dependent, always build an - // overloaded op. - if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) - return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); - - // Otherwise, build an overloaded op if either expression has an - // overloadable type. - if (LHSExpr->getType()->isOverloadableType() || + // Otherwise, build an overloaded op if either expression is type-dependent + // or has an overloadable type. + if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent() || + LHSExpr->getType()->isOverloadableType() || RHSExpr->getType()->isOverloadableType()) return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); } @@ -15466,190 +15456,191 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 1); } - switch (Opc) { - case UO_PreInc: - case UO_PreDec: - case UO_PostInc: - case UO_PostDec: - resultType = - CheckIncrementDecrementOperand(*this, Input.get(), VK, OK, OpLoc, - Opc == UO_PreInc || Opc == UO_PostInc, - Opc == UO_PreInc || Opc == UO_PreDec); - CanOverflow = isOverflowingIntegerType(Context, resultType); - break; - case UO_AddrOf: - resultType = CheckAddressOfOperand(Input, OpLoc); - CheckAddressOfNoDeref(InputExpr); - RecordModifiableNonNullParam(*this, InputExpr); - break; - case UO_Deref: { - Input = DefaultFunctionArrayLvalueConversion(Input.get()); - if (Input.isInvalid()) - return ExprError(); - resultType = - CheckIndirectionOperand(*this, Input.get(), VK, OpLoc, IsAfterAmp); - break; - } - case UO_Plus: - case UO_Minus: - CanOverflow = Opc == UO_Minus && - isOverflowingIntegerType(Context, Input.get()->getType()); - Input = UsualUnaryConversions(Input.get()); - if (Input.isInvalid()) - return ExprError(); - // Unary plus and minus require promoting an operand of half vector to a - // float vector and truncating the result back to a half vector. For now, we - // do this only when HalfArgsAndReturns is set (that is, when the target is - // arm or arm64). - ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get()); - - // If the operand is a half vector, promote it to a float vector. - if (ConvertHalfVec) - Input = convertVector(Input.get(), Context.FloatTy, *this); - resultType = Input.get()->getType(); - if (resultType->isDependentType()) - break; - if (resultType->isArithmeticType()) // C99 6.5.3.3p1 - break; - else if (resultType->isVectorType() && - // The z vector extensions don't allow + or - with bool vectors. - (!Context.getLangOpts().ZVector || - resultType->castAs()->getVectorKind() != - VectorKind::AltiVecBool)) - break; - else if (resultType->isSveVLSBuiltinType()) // SVE vectors allow + and - - break; - else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 - Opc == UO_Plus && resultType->isPointerType()) + if (InputExpr->isTypeDependent() && + InputExpr->getType()->isSpecificBuiltinType(BuiltinType::Dependent)) { + resultType = Context.DependentTy; + } else { + switch (Opc) { + case UO_PreInc: + case UO_PreDec: + case UO_PostInc: + case UO_PostDec: + resultType = + CheckIncrementDecrementOperand(*this, Input.get(), VK, OK, OpLoc, + Opc == UO_PreInc || Opc == UO_PostInc, + Opc == UO_PreInc || Opc == UO_PreDec); + CanOverflow = isOverflowingIntegerType(Context, resultType); break; - - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - - case UO_Not: // bitwise complement - Input = UsualUnaryConversions(Input.get()); - if (Input.isInvalid()) - return ExprError(); - resultType = Input.get()->getType(); - if (resultType->isDependentType()) + case UO_AddrOf: + resultType = CheckAddressOfOperand(Input, OpLoc); + CheckAddressOfNoDeref(InputExpr); + RecordModifiableNonNullParam(*this, InputExpr); break; - // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. - if (resultType->isComplexType() || resultType->isComplexIntegerType()) - // C99 does not support '~' for complex conjugation. - Diag(OpLoc, diag::ext_integer_complement_complex) - << resultType << Input.get()->getSourceRange(); - else if (resultType->hasIntegerRepresentation()) + case UO_Deref: { + Input = DefaultFunctionArrayLvalueConversion(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = + CheckIndirectionOperand(*this, Input.get(), VK, OpLoc, IsAfterAmp); break; - else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { - // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate - // on vector float types. - QualType T = resultType->castAs()->getElementType(); - if (!T->isIntegerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } else { - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - break; - - case UO_LNot: // logical negation - // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). - Input = DefaultFunctionArrayLvalueConversion(Input.get()); - if (Input.isInvalid()) - return ExprError(); - resultType = Input.get()->getType(); - - // Though we still have to promote half FP to float... - if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) { - Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast) - .get(); - resultType = Context.FloatTy; } + case UO_Plus: + case UO_Minus: + CanOverflow = Opc == UO_Minus && + isOverflowingIntegerType(Context, Input.get()->getType()); + Input = UsualUnaryConversions(Input.get()); + if (Input.isInvalid()) + return ExprError(); + // Unary plus and minus require promoting an operand of half vector to a + // float vector and truncating the result back to a half vector. For now, + // we do this only when HalfArgsAndReturns is set (that is, when the + // target is arm or arm64). + ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get()); + + // If the operand is a half vector, promote it to a float vector. + if (ConvertHalfVec) + Input = convertVector(Input.get(), Context.FloatTy, *this); + resultType = Input.get()->getType(); + if (resultType->isArithmeticType()) // C99 6.5.3.3p1 + break; + else if (resultType->isVectorType() && + // The z vector extensions don't allow + or - with bool vectors. + (!Context.getLangOpts().ZVector || + resultType->castAs()->getVectorKind() != + VectorKind::AltiVecBool)) + break; + else if (resultType->isSveVLSBuiltinType()) // SVE vectors allow + and - + break; + else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 + Opc == UO_Plus && resultType->isPointerType()) + break; - // WebAsembly tables can't be used in unary expressions. - if (resultType->isPointerType() && - resultType->getPointeeType().isWebAssemblyReferenceType()) { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); - } - if (resultType->isDependentType()) - break; - if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) { - // C99 6.5.3.3p1: ok, fallthrough; - if (Context.getLangOpts().CPlusPlus) { - // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: - // operand contextually converted to bool. - Input = ImpCastExprToType(Input.get(), Context.BoolTy, - ScalarTypeToBooleanCastKind(resultType)); - } else if (Context.getLangOpts().OpenCL && - Context.getLangOpts().OpenCLVersion < 120) { - // OpenCL v1.1 6.3.h: The logical operator not (!) does not - // operate on scalar float types. - if (!resultType->isIntegerType() && !resultType->isPointerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - } else if (resultType->isExtVectorType()) { - if (Context.getLangOpts().OpenCL && - Context.getLangOpts().getOpenCLCompatibleVersion() < 120) { - // OpenCL v1.1 6.3.h: The logical operator not (!) does not - // operate on vector float types. + case UO_Not: // bitwise complement + Input = UsualUnaryConversions(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = Input.get()->getType(); + // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. + if (resultType->isComplexType() || resultType->isComplexIntegerType()) + // C99 does not support '~' for complex conjugation. + Diag(OpLoc, diag::ext_integer_complement_complex) + << resultType << Input.get()->getSourceRange(); + else if (resultType->hasIntegerRepresentation()) + break; + else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate + // on vector float types. QualType T = resultType->castAs()->getElementType(); if (!T->isIntegerType()) return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); } - // Vector logical not returns the signed variant of the operand type. - resultType = GetSignedVectorType(resultType); break; - } else if (Context.getLangOpts().CPlusPlus && resultType->isVectorType()) { - const VectorType *VTy = resultType->castAs(); - if (VTy->getVectorKind() != VectorKind::Generic) + + case UO_LNot: // logical negation + // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). + Input = DefaultFunctionArrayLvalueConversion(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = Input.get()->getType(); + + // Though we still have to promote half FP to float... + if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) { + Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast) + .get(); + resultType = Context.FloatTy; + } + + // WebAsembly tables can't be used in unary expressions. + if (resultType->isPointerType() && + resultType->getPointeeType().isWebAssemblyReferenceType()) { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); + } - // Vector logical not returns the signed variant of the operand type. - resultType = GetSignedVectorType(resultType); - break; - } else { - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } + if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) { + // C99 6.5.3.3p1: ok, fallthrough; + if (Context.getLangOpts().CPlusPlus) { + // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: + // operand contextually converted to bool. + Input = ImpCastExprToType(Input.get(), Context.BoolTy, + ScalarTypeToBooleanCastKind(resultType)); + } else if (Context.getLangOpts().OpenCL && + Context.getLangOpts().OpenCLVersion < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on scalar float types. + if (!resultType->isIntegerType() && !resultType->isPointerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + } else if (resultType->isExtVectorType()) { + if (Context.getLangOpts().OpenCL && + Context.getLangOpts().getOpenCLCompatibleVersion() < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on vector float types. + QualType T = resultType->castAs()->getElementType(); + if (!T->isIntegerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; + } else if (Context.getLangOpts().CPlusPlus && + resultType->isVectorType()) { + const VectorType *VTy = resultType->castAs(); + if (VTy->getVectorKind() != VectorKind::Generic) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); - // LNot always has type int. C99 6.5.3.3p5. - // In C++, it's bool. C++ 5.3.1p8 - resultType = Context.getLogicalOperationType(); - break; - case UO_Real: - case UO_Imag: - resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); - // _Real maps ordinary l-values into ordinary l-values. _Imag maps ordinary - // complex l-values to ordinary l-values and all other values to r-values. - if (Input.isInvalid()) - return ExprError(); - if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { - if (Input.get()->isGLValue() && - Input.get()->getObjectKind() == OK_Ordinary) - VK = Input.get()->getValueKind(); - } else if (!getLangOpts().CPlusPlus) { - // In C, a volatile scalar is read by __imag. In C++, it is not. - Input = DefaultLvalueConversion(Input.get()); + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + + // LNot always has type int. C99 6.5.3.3p5. + // In C++, it's bool. C++ 5.3.1p8 + resultType = Context.getLogicalOperationType(); + break; + case UO_Real: + case UO_Imag: + resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); + // _Real maps ordinary l-values into ordinary l-values. _Imag maps + // ordinary complex l-values to ordinary l-values and all other values to + // r-values. + if (Input.isInvalid()) + return ExprError(); + if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { + if (Input.get()->isGLValue() && + Input.get()->getObjectKind() == OK_Ordinary) + VK = Input.get()->getValueKind(); + } else if (!getLangOpts().CPlusPlus) { + // In C, a volatile scalar is read by __imag. In C++, it is not. + Input = DefaultLvalueConversion(Input.get()); + } + break; + case UO_Extension: + resultType = Input.get()->getType(); + VK = Input.get()->getValueKind(); + OK = Input.get()->getObjectKind(); + break; + case UO_Coawait: + // It's unnecessary to represent the pass-through operator co_await in the + // AST; just return the input expression instead. + assert(!Input.get()->getType()->isDependentType() && + "the co_await expression must be non-dependant before " + "building operator co_await"); + return Input; } - break; - case UO_Extension: - resultType = Input.get()->getType(); - VK = Input.get()->getValueKind(); - OK = Input.get()->getObjectKind(); - break; - case UO_Coawait: - // It's unnecessary to represent the pass-through operator co_await in the - // AST; just return the input expression instead. - assert(!Input.get()->getType()->isDependentType() && - "the co_await expression must be non-dependant before " - "building operator co_await"); - return Input; } if (resultType.isNull() || Input.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c039b95293af..b10e5ba65eb1 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -16236,10 +16236,11 @@ ExprResult TreeTransform::RebuildCXXOperatorCallExpr( return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, First); } } else { - if (!First->getType()->isOverloadableType() && + if (!First->isTypeDependent() && !Second->isTypeDependent() && + !First->getType()->isOverloadableType() && !Second->getType()->isOverloadableType()) { - // Neither of the arguments is an overloadable type, so try to - // create a built-in binary operation. + // Neither of the arguments is type-dependent or has an overloadable + // type, so try to create a built-in binary operation. BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); ExprResult Result = SemaRef.CreateBuiltinBinOp(OpLoc, Opc, First, Second); @@ -16250,12 +16251,8 @@ ExprResult TreeTransform::RebuildCXXOperatorCallExpr( } } - // Add any functions found via argument-dependent lookup. - Expr *Args[2] = { First, Second }; - unsigned NumArgs = 1 + (Second != nullptr); - // Create the overloaded operator invocation for unary operators. - if (NumArgs == 1 || isPostIncDec) { + if (!Second || isPostIncDec) { UnaryOperatorKind Opc = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec); return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First, @@ -16264,8 +16261,8 @@ ExprResult TreeTransform::RebuildCXXOperatorCallExpr( // Create the overloaded operator invocation for binary operators. BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); - ExprResult Result = SemaRef.CreateOverloadedBinOp( - OpLoc, Opc, Functions, Args[0], Args[1], RequiresADL); + ExprResult Result = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions, + First, Second, RequiresADL); if (Result.isInvalid()) return ExprError(); diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index 0fb07b0b434c..4b7365e554cb 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -4261,9 +4261,9 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "" +// CHECK-NEXT: "qualType": "V" // CHECK-NEXT: }, -// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "valueCategory": "lvalue", // CHECK-NEXT: "isPostfix": false, // CHECK-NEXT: "opcode": "*", // CHECK-NEXT: "canOverflow": false, diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 69e65e22d61d..4df5ba4276ab 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -282,7 +282,7 @@ void PrimaryExpressions(Ts... a) { // CHECK-NEXT: CompoundStmt // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:8 implicit 'V' // CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} 'NULL TYPE' - // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} '' prefix '*' cannot overflow + // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} 'V' lvalue prefix '*' cannot overflow // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} 'V *' this } }; diff --git a/clang/test/AST/ast-dump-lambda.cpp b/clang/test/AST/ast-dump-lambda.cpp index ef8789cd97d3..a4d3fe4fbda5 100644 --- a/clang/test/AST/ast-dump-lambda.cpp +++ b/clang/test/AST/ast-dump-lambda.cpp @@ -81,7 +81,7 @@ template void test(Ts... a) { // CHECK-NEXT: | | | `-CompoundStmt {{.*}} // CHECK-NEXT: | | `-FieldDecl {{.*}} col:8{{( imported)?}} implicit 'V' // CHECK-NEXT: | |-ParenListExpr {{.*}} 'NULL TYPE' -// CHECK-NEXT: | | `-UnaryOperator {{.*}} '' prefix '*' cannot overflow +// CHECK-NEXT: | | `-UnaryOperator {{.*}} 'V' lvalue prefix '*' cannot overflow // CHECK-NEXT: | | `-CXXThisExpr {{.*}} 'V *' this // CHECK-NEXT: | `-CompoundStmt {{.*}} // CHECK-NEXT: |-DeclStmt {{.*}} diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp new file mode 100644 index 000000000000..6744ce1cad17 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -Wno-unused -fsyntax-only %s -verify + +struct A { + void operator*(); + void operator+(); + void operator-(); + void operator!(); + void operator~(); + void operator&(); + void operator++(); + void operator--(); +}; + +struct B { }; + +template +void dependent(T t, T* pt, T U::* mpt, T(&ft)(), T(&at)[4]) { + *t; + +t; + -t; + !t; + ~t; + &t; + ++t; + --t; + + *pt; + +pt; + -pt; // expected-error {{invalid argument type 'T *' to unary expression}} + !pt; + ~pt; // expected-error {{invalid argument type 'T *' to unary expression}} + &pt; + ++pt; + --pt; + + *mpt; // expected-error {{indirection requires pointer operand ('T U::*' invalid)}} + +mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} + -mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} + !mpt; + ~mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} + &mpt; + ++mpt; // expected-error {{cannot increment value of type 'T U::*'}} + --mpt; // expected-error {{cannot decrement value of type 'T U::*'}} + + *ft; + +ft; + -ft; // expected-error {{invalid argument type 'T (*)()' to unary expression}} + !ft; + ~ft; // expected-error {{invalid argument type 'T (*)()' to unary expression}} + &ft; + ++ft; // expected-error {{cannot increment value of type 'T ()'}} + --ft; // expected-error {{cannot decrement value of type 'T ()'}} + + *at; + +at; + -at; // expected-error {{invalid argument type 'T *' to unary expression}} + !at; + ~at; // expected-error {{invalid argument type 'T *' to unary expression}} + &at; + ++at; // expected-error {{cannot increment value of type 'T[4]'}} + --at; // expected-error {{cannot decrement value of type 'T[4]'}} +} + +// Make sure we only emit diagnostics once. +template void dependent(A t, A* pt, A B::* mpt, A(&ft)(), A(&at)[4]); diff --git a/clang/test/CXX/over/over.built/ast.cpp b/clang/test/CXX/over/over.built/ast.cpp index 56a63431269f..78f86edb1e96 100644 --- a/clang/test/CXX/over/over.built/ast.cpp +++ b/clang/test/CXX/over/over.built/ast.cpp @@ -1,41 +1,139 @@ -// RUN: %clang_cc1 -std=c++17 -ast-dump %s -ast-dump-filter Test | FileCheck %s +// RUN: %clang_cc1 -std=c++17 -Wno-unused -ast-dump %s -ast-dump-filter Test | FileCheck %s -struct A{}; +namespace Test { + template + void Unary(T t, T* pt, T U::* mpt, T(&ft)(), T(&at)[4]) { + // CHECK: UnaryOperator {{.*}} '' lvalue prefix '*' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + *t; -template -auto Test(T* pt, U* pu) { - // CHECK: UnaryOperator {{.*}} '' lvalue prefix '*' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)*pt; + // CHECK: UnaryOperator {{.*}} '' prefix '+' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + +t; - // CHECK: UnaryOperator {{.*}} '' lvalue prefix '++' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)(++pt); + // CHECK: UnaryOperator {{.*}} '' prefix '-' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + -t; - // CHECK: UnaryOperator {{.*}} '' prefix '+' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)(+pt); + // CHECK: UnaryOperator {{.*}} '' prefix '!' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + !t; - // CHECK: BinaryOperator {{.*}} '' '+' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3 - (void)(pt + 3); + // CHECK: UnaryOperator {{.*}} '' prefix '~' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + ~t; - // CHECK: BinaryOperator {{.*}} '' '-' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)(pt - pt); + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + &t; - // CHECK: BinaryOperator {{.*}} '' '-' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' - (void)(pt - pu); + // CHECK: UnaryOperator {{.*}} '' lvalue prefix '++' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + ++t; - // CHECK: BinaryOperator {{.*}} '' '==' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' - (void)(pt == pu); + // CHECK: UnaryOperator {{.*}} '' lvalue prefix '--' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + --t; -} + // CHECK: UnaryOperator {{.*}} 'T' lvalue prefix '*' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + *pt; + // CHECK: UnaryOperator {{.*}} 'T *' prefix '+' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + +pt; + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + !pt; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + &pt; + + // CHECK: UnaryOperator {{.*}} 'T *' lvalue prefix '++' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + ++pt; + + // CHECK: UnaryOperator {{.*}} 'T *' lvalue prefix '--' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + --pt; + + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T U::*' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T U::*' lvalue ParmVar {{.*}} 'mpt' 'T U::*' + !mpt; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T U::*' lvalue ParmVar {{.*}} 'mpt' 'T U::*' + &mpt; + + // CHECK: UnaryOperator {{.*}} 'T ()' lvalue prefix '*' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + *ft; + + // CHECK: UnaryOperator {{.*}} 'T (*)()' prefix '+' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + +ft; + + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + !ft; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + &ft; + + // CHECK: UnaryOperator {{.*}} 'T' lvalue prefix '*' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + *at; + + // CHECK: UnaryOperator {{.*}} 'T *' prefix '+' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + +at; + + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + !at; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + &at; + } + + template + void Binary(T* pt, U* pu) { + // CHECK: BinaryOperator {{.*}} '' '+' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3 + pt + 3; + + // CHECK: BinaryOperator {{.*}} '' '-' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + pt - pt; + + // CHECK: BinaryOperator {{.*}} '' '-' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' + pt - pu; + + // CHECK: BinaryOperator {{.*}} '' '==' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' + pt == pu; + } +} // namespace Test diff --git a/clang/test/CXX/over/over.built/p10.cpp b/clang/test/CXX/over/over.built/p10.cpp index 678056da5820..8ff2396d0b6f 100644 --- a/clang/test/CXX/over/over.built/p10.cpp +++ b/clang/test/CXX/over/over.built/p10.cpp @@ -15,6 +15,6 @@ void f(int i, float f, bool b, char c, int* pi, A* pa, T* pt) { (void)-pi; // expected-error {{invalid argument type}} (void)-pa; // expected-error {{invalid argument type}} - (void)-pt; // FIXME: we should be able to give an error here. + (void)-pt; // expected-error {{invalid argument type}} } diff --git a/clang/test/CXX/over/over.built/p11.cpp b/clang/test/CXX/over/over.built/p11.cpp index 7ebf16b95439..f7a741db726d 100644 --- a/clang/test/CXX/over/over.built/p11.cpp +++ b/clang/test/CXX/over/over.built/p11.cpp @@ -7,6 +7,6 @@ void f(int i, float f, bool b, char c, int* pi, T* pt) { (void)~b; (void)~c; (void)~pi; // expected-error {{invalid argument type}} - (void)~pt; // FIXME: we should be able to give an error here. + (void)~pt; // expected-error {{invalid argument type}} } diff --git a/clang/test/CXX/over/over.oper/over.oper.general/p1.cpp b/clang/test/CXX/over/over.oper/over.oper.general/p1.cpp new file mode 100644 index 000000000000..d49fb0645751 --- /dev/null +++ b/clang/test/CXX/over/over.oper/over.oper.general/p1.cpp @@ -0,0 +1,173 @@ +// RUN: %clang_cc1 -std=c++20 -verify -Wno-unused %s + +template +void operator->*(T, U); + +template +void operator+(T, U); + +template +void operator-(T, U); + +template +void operator*(T, U); + +template +void operator/(T, U); + +template +void operator%(T, U); + +template +void operator^(T, U); + +template +void operator&(T, U); + +template +void operator|(T, U); + +template +void operator+=(T, U); + +template +void operator-=(T, U); + +template +void operator*=(T, U); + +template +void operator/=(T, U); + +template +void operator%=(T, U); + +template +void operator^=(T, U); + +template +void operator&=(T, U); + +template +void operator|=(T, U); + +template +void operator==(T, U); + +template +void operator!=(T, U); + +template +void operator<(T, U); + +template +void operator>(T, U); + +template +void operator<=(T, U); + +template +void operator>=(T, U); + +template +void operator<=>(T, U); + +template +void operator&&(T, U); + +template +void operator||(T, U); + +template +void operator<<(T, U); + +template +void operator>>(T, U); + +template +void operator<<=(T, U); + +template +void operator>>=(T, U); + +template +void operator,(T, U); + +template +void operator*(T); + +template +void operator&(T); + +template +void operator+(T); + +template +void operator-(T); + +template +void operator!(T); + +template +void operator~(T); + +template +void operator++(T); + +template +void operator--(T); + +template +void operator++(T, int); + +template +void operator--(T, int); + +template +void f(int *x) { + [&](auto *y) { + *y; + &y; + +y; + -y; // expected-error {{invalid argument type 'auto *' to unary expression}} + !y; + ~y; // expected-error {{invalid argument type 'auto *' to unary expression}} + ++y; + --y; + y++; + y--; + y->*x; + y + x; + y - x; + y * x; + y / x; + y % x; + y ^ x; + y & x; + y | x; + y += x; + y -= x; + y *= x; + y /= x; + y %= x; + y ^= x; + y &= x; + y |= x; + y == x; + y != x; + y < x; + y > x; + y <= x; + y >= x; + y <=> x; + y && x; + y || x; + y << x; + y >> x; + y <<= x; + y >>= x; + y, x; + }; +} + +template void f(int*); diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp index 3ca7c6c7eb8e..982e5372f5b0 100644 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp @@ -357,17 +357,14 @@ namespace N0 { a->A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} a->B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - // FIXME: An overloaded unary 'operator*' is built for these - // even though the operand is a pointer (to a dependent type). - // Type::isOverloadableType should return false for such cases. - (*this).x4; - (*this).B::x4; - (*this).A::x4; - (*this).B::A::x4; - (*this).f4(); - (*this).B::f4(); - (*this).A::f4(); - (*this).B::A::f4(); + (*this).x4; // expected-error{{no member named 'x4' in 'B'}} + (*this).B::x4; // expected-error{{no member named 'x4' in 'B'}} + (*this).A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} + (*this).B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} + (*this).f4(); // expected-error{{no member named 'f4' in 'B'}} + (*this).B::f4(); // expected-error{{no member named 'f4' in 'B'}} + (*this).A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} + (*this).B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} b.x4; // expected-error{{no member named 'x4' in 'B'}} b.B::x4; // expected-error{{no member named 'x4' in 'B'}} @@ -399,15 +396,13 @@ namespace N1 { f<0>(); this->f<0>(); a->f<0>(); - // FIXME: This should not require 'template'! - (*this).f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + (*this).f<0>(); b.f<0>(); x.f<0>(); this->x.f<0>(); a->x.f<0>(); - // FIXME: This should not require 'template'! - (*this).x.f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + (*this).x.f<0>(); b.x.f<0>(); // FIXME: None of these should require 'template'! diff --git a/clang/test/Frontend/noderef_templates.cpp b/clang/test/Frontend/noderef_templates.cpp index 5fde6efd87c7..9e54cd5d7889 100644 --- a/clang/test/Frontend/noderef_templates.cpp +++ b/clang/test/Frontend/noderef_templates.cpp @@ -3,8 +3,8 @@ #define NODEREF __attribute__((noderef)) template -int func(T NODEREF *a) { // expected-note 2 {{a declared here}} - return *a + 1; // expected-warning 2 {{dereferencing a; was declared with a 'noderef' type}} +int func(T NODEREF *a) { // expected-note 3 {{a declared here}} + return *a + 1; // expected-warning 3 {{dereferencing a; was declared with a 'noderef' type}} } void func() { diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp b/clang/test/SemaCXX/cxx2b-deducing-this.cpp index 5f29a955e053..aa64530bd5be 100644 --- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp +++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp @@ -19,7 +19,7 @@ struct S { // new and delete are implicitly static void *operator new(this unsigned long); // expected-error{{an explicit object parameter cannot appear in a static function}} void operator delete(this void*); // expected-error{{an explicit object parameter cannot appear in a static function}} - + void g(this auto) const; // expected-error{{explicit object member function cannot have 'const' qualifier}} void h(this auto) &; // expected-error{{explicit object member function cannot have '&' qualifier}} void i(this auto) &&; // expected-error{{explicit object member function cannot have '&&' qualifier}} @@ -198,9 +198,7 @@ void func(int i) { void TestMutationInLambda() { [i = 0](this auto &&){ i++; }(); [i = 0](this auto){ i++; }(); - [i = 0](this const auto&){ i++; }(); - // expected-error@-1 {{cannot assign to a variable captured by copy in a non-mutable lambda}} - // expected-note@-2 {{in instantiation of}} + [i = 0](this const auto&){ i++; }(); // expected-error {{cannot assign to a variable captured by copy in a non-mutable lambda}} int x; const auto l1 = [x](this auto&) { x = 42; }; // expected-error {{cannot assign to a variable captured by copy in a non-mutable lambda}} diff --git a/clang/test/SemaTemplate/class-template-spec.cpp b/clang/test/SemaTemplate/class-template-spec.cpp index 56b8207bd9a4..faa54c367538 100644 --- a/clang/test/SemaTemplate/class-template-spec.cpp +++ b/clang/test/SemaTemplate/class-template-spec.cpp @@ -18,7 +18,7 @@ int test_specs(A *a1, A *a2) { return a1->x + a2->y; } -int test_incomplete_specs(A *a1, +int test_incomplete_specs(A *a1, A *a2) { (void)a1->x; // expected-error{{member access into incomplete type}} @@ -39,7 +39,7 @@ template <> struct X { int foo(); }; // #1 template <> struct X { int bar(); }; // #2 typedef int int_type; -void testme(X *x1, X *x2) { +void testme(X *x1, X *x2) { (void)x1->foo(); // okay: refers to #1 (void)x2->bar(); // okay: refers to #2 } @@ -53,7 +53,7 @@ struct A { A::A() { } // Make sure we can see specializations defined before the primary template. -namespace N{ +namespace N{ template struct A0; } @@ -97,7 +97,7 @@ namespace M { template<> struct ::A; // expected-error{{must occur at global scope}} } -template<> struct N::B { +template<> struct N::B { int testf(int x) { return f(x); } }; @@ -138,9 +138,9 @@ namespace PR18009 { template struct C { template struct S; - template struct S {}; // expected-error {{depends on a template parameter of the partial specialization}} + template struct S {}; // ok }; - C c; // expected-note {{in instantiation of}} + C c; template struct outer { template struct inner {}; diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index c08deb903f12..f26140675fd4 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1572,9 +1572,9 @@ TEST_P(ASTMatchersTest, IsArrow_MatchesMemberVariablesViaArrow) { EXPECT_TRUE( matches("template class Y { void x() { this->m; } int m; };", memberExpr(isArrow()))); - EXPECT_TRUE( - notMatches("template class Y { void x() { (*this).m; } };", - cxxDependentScopeMemberExpr(isArrow()))); + EXPECT_TRUE(notMatches( + "template class Y { void x() { (*this).m; } int m; };", + memberExpr(isArrow()))); } TEST_P(ASTMatchersTest, IsArrow_MatchesStaticMemberVariablesViaArrow) { -- GitLab From 3a4c1b9b4428b08d4475decf74c11e0d328c5842 Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Thu, 16 May 2024 09:55:36 +0800 Subject: [PATCH 444/578] [Serialization] Read the initializer for interesting static variables before consuming it (#92218) Close https://github.com/llvm/llvm-project/issues/91418 Since we load the variable's initializers lazily, it'd be problematic if the initializers dependent on each other. For example, ``` SomeType a = ...; SomeType b = a; ``` Previously, when we load variable `b`, we need to load the initializer, then we need to load `a`. We can only mark the variable `b` as loaded after we load `a`. Then `a` is always initialized before `b`. However, it is not true after we implement lazy loading for initializers. So here we try to load the initializers of static variables to make sure they are passed to code generator by order. If we read any thing interesting, we would consume that before emitting the current declaration. --- clang/lib/Serialization/ASTReaderDecl.cpp | 29 ++- clang/test/Modules/pr91418.cppm | 67 +++++ clang/test/OpenMP/nvptx_lambda_capturing.cpp | 246 +++++++++---------- 3 files changed, 216 insertions(+), 126 deletions(-) create mode 100644 clang/test/Modules/pr91418.cppm diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 0c647086e304..a6254b70560c 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -4186,12 +4186,35 @@ void ASTReader::PassInterestingDeclsToConsumer() { GetDecl(ID); EagerlyDeserializedDecls.clear(); - while (!PotentiallyInterestingDecls.empty()) { - Decl *D = PotentiallyInterestingDecls.front(); - PotentiallyInterestingDecls.pop_front(); + auto ConsumingPotentialInterestingDecls = [this]() { + while (!PotentiallyInterestingDecls.empty()) { + Decl *D = PotentiallyInterestingDecls.front(); + PotentiallyInterestingDecls.pop_front(); + if (isConsumerInterestedIn(D)) + PassInterestingDeclToConsumer(D); + } + }; + std::deque MaybeInterestingDecls = + std::move(PotentiallyInterestingDecls); + assert(PotentiallyInterestingDecls.empty()); + while (!MaybeInterestingDecls.empty()) { + Decl *D = MaybeInterestingDecls.front(); + MaybeInterestingDecls.pop_front(); + // Since we load the variable's initializers lazily, it'd be problematic + // if the initializers dependent on each other. So here we try to load the + // initializers of static variables to make sure they are passed to code + // generator by order. If we read anything interesting, we would consume + // that before emitting the current declaration. + if (auto *VD = dyn_cast(D); + VD && VD->isFileVarDecl() && !VD->isExternallyVisible()) + VD->getInit(); + ConsumingPotentialInterestingDecls(); if (isConsumerInterestedIn(D)) PassInterestingDeclToConsumer(D); } + + // If we add any new potential interesting decl in the last call, consume it. + ConsumingPotentialInterestingDecls(); } void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { diff --git a/clang/test/Modules/pr91418.cppm b/clang/test/Modules/pr91418.cppm new file mode 100644 index 000000000000..33fec992439d --- /dev/null +++ b/clang/test/Modules/pr91418.cppm @@ -0,0 +1,67 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -x c++-header %t/foo.h \ +// RUN: -emit-pch -o %t/foo.pch +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/use.cpp -include-pch \ +// RUN: %t/foo.pch -emit-llvm -o - | FileCheck %t/use.cpp + +//--- foo.h +#ifndef FOO_H +#define FOO_H +typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16))); + +static __inline__ __m128 __attribute__((__always_inline__, __min_vector_width__(128))) +_mm_setr_ps(float __z, float __y, float __x, float __w) +{ + return __extension__ (__m128){ __z, __y, __x, __w }; +} + +typedef __m128 VR; + +inline VR MakeVR( float X, float Y, float Z, float W ) +{ + return _mm_setr_ps( X, Y, Z, W ); +} + +extern "C" float sqrtf(float); + +namespace VectorSinConstantsSSE +{ + float a = (16 * sqrtf(0.225f)); + VR A = MakeVR(a, a, a, a); + static const float b = (16 * sqrtf(0.225f)); + static const VR B = MakeVR(b, b, b, b); +} + +#endif // FOO_H + +//--- use.cpp +#include "foo.h" +float use() { + return VectorSinConstantsSSE::A[0] + VectorSinConstantsSSE::A[1] + + VectorSinConstantsSSE::A[2] + VectorSinConstantsSSE::A[3] + + VectorSinConstantsSSE::B[0] + VectorSinConstantsSSE::B[1] + + VectorSinConstantsSSE::B[2] + VectorSinConstantsSSE::B[3]; +} + +// CHECK: define{{.*}}@__cxx_global_var_init( +// CHECK: store{{.*}}[[a_RESULT:%[a-zA-Z0-9]+]], ptr @_ZN21VectorSinConstantsSSE1aE + +// CHECK: define{{.*}}@__cxx_global_var_init.1( +// CHECK: [[A_CALL:%[a-zA-Z0-9]+]] = call{{.*}}@_Z6MakeVRffff( +// CHECK: store{{.*}}[[A_CALL]], ptr @_ZN21VectorSinConstantsSSE1AE + +// CHECK: define{{.*}}@__cxx_global_var_init.2( +// CHECK: [[B_CALL:%[a-zA-Z0-9]+]] = call{{.*}}@_Z6MakeVRffff( +// CHECK: store{{.*}}[[B_CALL]], ptr @_ZN21VectorSinConstantsSSEL1BE + +// CHECK: define{{.*}}@__cxx_global_var_init.3( +// CHECK: store{{.*}}[[b_RESULT:%[a-zA-Z0-9]+]], ptr @_ZN21VectorSinConstantsSSEL1bE + +// CHECK: @_GLOBAL__sub_I_use.cpp +// CHECK: call{{.*}}@__cxx_global_var_init( +// CHECK: call{{.*}}@__cxx_global_var_init.1( +// CHECK: call{{.*}}@__cxx_global_var_init.3( +// CHECK: call{{.*}}@__cxx_global_var_init.2( diff --git a/clang/test/OpenMP/nvptx_lambda_capturing.cpp b/clang/test/OpenMP/nvptx_lambda_capturing.cpp index 641fbc38dd6b..efea8d4a0561 100644 --- a/clang/test/OpenMP/nvptx_lambda_capturing.cpp +++ b/clang/test/OpenMP/nvptx_lambda_capturing.cpp @@ -1165,8 +1165,113 @@ int main(int argc, char **argv) { // CHECK2-NEXT: ret void // // +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l27 +// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[L1:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 +// CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 +// CHECK3-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_target_init(ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l27_kernel_environment, ptr [[DYN_PTR]]) +// CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP2]], -1 +// CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] +// CHECK3: user_code.entry: +// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[L1]], ptr align 8 [[TMP3]], i64 8, i1 false) +// CHECK3-NEXT: store ptr [[L1]], ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP4]], i32 0, i32 0 +// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK3-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[CALL:%.*]] = call noundef i32 @_ZZN1S3fooEvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(8) [[TMP6]]) #[[ATTR7:[0-9]+]] +// CHECK3-NEXT: call void @__kmpc_target_deinit() +// CHECK3-NEXT: ret void +// CHECK3: worker.exit: +// CHECK3-NEXT: ret void +// +// +// CHECK3-LABEL: define {{[^@]+}}@_ZZN1S3fooEvENKUlvE_clEv +// CHECK3-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) #[[ATTR2:[0-9]+]] comdat align 2 { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[CLASS_ANON:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP2:%.*]] = load i32, ptr [[A]], align 4 +// CHECK3-NEXT: ret i32 [[TMP2]] +// +// +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29 +// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR3:[0-9]+]] { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [2 x ptr], align 8 +// CHECK3-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 +// CHECK3-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_target_init(ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_kernel_environment, ptr [[DYN_PTR]]) +// CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP2]], -1 +// CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] +// CHECK3: user_code.entry: +// CHECK3-NEXT: [[TMP3:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) +// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 0 +// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 1 +// CHECK3-NEXT: store ptr [[TMP4]], ptr [[TMP6]], align 8 +// CHECK3-NEXT: call void @__kmpc_parallel_51(ptr @[[GLOB1]], i32 [[TMP3]], i32 1, i32 -1, i32 -1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_omp_outlined, ptr null, ptr [[CAPTURED_VARS_ADDRS]], i64 2) +// CHECK3-NEXT: call void @__kmpc_target_deinit() +// CHECK3-NEXT: ret void +// CHECK3: worker.exit: +// CHECK3-NEXT: ret void +// +// +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_omp_outlined +// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR4:[0-9]+]] { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[L1:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 +// CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 +// CHECK3-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 +// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[L1]], ptr align 8 [[TMP2]], i64 8, i1 false) +// CHECK3-NEXT: store ptr [[L1]], ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP3]], i32 0, i32 0 +// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 +// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[CALL:%.*]] = call noundef i32 @_ZZN1S3fooEvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(8) [[TMP5]]) #[[ATTR7]] +// CHECK3-NEXT: ret void +// +// // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l41 -// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], i64 noundef [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], i64 noundef [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR0]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[ARGC_ADDR:%.*]] = alloca i64, align 8 @@ -1178,7 +1283,7 @@ int main(int argc, char **argv) { // CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L3:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 +// CHECK3-NEXT: [[L3:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8 // CHECK3-NEXT: [[_TMP4:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[B5:%.*]] = alloca i32, align 4 // CHECK3-NEXT: [[_TMP6:%.*]] = alloca ptr, align 8 @@ -1214,20 +1319,20 @@ int main(int argc, char **argv) { // CHECK3-NEXT: store i32 [[TMP9]], ptr [[C7]], align 4 // CHECK3-NEXT: store ptr [[C7]], ptr [[_TMP8]], align 8 // CHECK3-NEXT: [[TMP10:%.*]] = load ptr, ptr [[_TMP4]], align 8 -// CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP10]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP10]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[ARGC_ADDR]], ptr [[TMP11]], align 8 -// CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP10]], i32 0, i32 1 +// CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP10]], i32 0, i32 1 // CHECK3-NEXT: [[TMP13:%.*]] = load ptr, ptr [[_TMP6]], align 8 // CHECK3-NEXT: store ptr [[TMP13]], ptr [[TMP12]], align 8 -// CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP10]], i32 0, i32 2 +// CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP10]], i32 0, i32 2 // CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP8]], align 8 // CHECK3-NEXT: store ptr [[TMP15]], ptr [[TMP14]], align 8 -// CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP10]], i32 0, i32 3 +// CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP10]], i32 0, i32 3 // CHECK3-NEXT: store ptr [[D_ADDR]], ptr [[TMP16]], align 8 -// CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP10]], i32 0, i32 4 +// CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP10]], i32 0, i32 4 // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP17]], align 8 // CHECK3-NEXT: [[TMP18:%.*]] = load ptr, ptr [[_TMP4]], align 8 -// CHECK3-NEXT: [[CALL:%.*]] = call noundef i64 @"_ZZ4mainENK3$_0clEv"(ptr noundef nonnull align 8 dereferenceable(40) [[TMP18]]) #[[ATTR7:[0-9]+]] +// CHECK3-NEXT: [[CALL:%.*]] = call noundef i64 @"_ZZ4mainENK3$_0clEv"(ptr noundef nonnull align 8 dereferenceable(40) [[TMP18]]) #[[ATTR7]] // CHECK3-NEXT: call void @__kmpc_target_deinit() // CHECK3-NEXT: ret void // CHECK3: worker.exit: @@ -1235,7 +1340,7 @@ int main(int argc, char **argv) { // // // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l43 -// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR3:[0-9]+]] { +// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR3]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[ARGC_ADDR:%.*]] = alloca ptr, align 8 @@ -1267,7 +1372,7 @@ int main(int argc, char **argv) { // CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP5]], -1 // CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] // CHECK3: user_code.entry: -// CHECK3-NEXT: [[TMP6:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) +// CHECK3-NEXT: [[TMP6:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) // CHECK3-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP]], align 8 // CHECK3-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP1]], align 8 // CHECK3-NEXT: [[TMP9:%.*]] = load ptr, ptr [[D_ADDR]], align 8 @@ -1292,7 +1397,7 @@ int main(int argc, char **argv) { // // // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l43_omp_outlined -// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR4:[0-9]+]] { +// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR4]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1305,7 +1410,7 @@ int main(int argc, char **argv) { // CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L3:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 +// CHECK3-NEXT: [[L3:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8 // CHECK3-NEXT: [[_TMP4:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[ARGC5:%.*]] = alloca i32, align 4 // CHECK3-NEXT: [[B6:%.*]] = alloca i32, align 4 @@ -1345,128 +1450,23 @@ int main(int argc, char **argv) { // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP3]], align 4 // CHECK3-NEXT: store i32 [[TMP11]], ptr [[A10]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = load ptr, ptr [[_TMP4]], align 8 -// CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP12]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP12]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[ARGC5]], ptr [[TMP13]], align 8 -// CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP12]], i32 0, i32 1 +// CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP12]], i32 0, i32 1 // CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP7]], align 8 // CHECK3-NEXT: store ptr [[TMP15]], ptr [[TMP14]], align 8 -// CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP12]], i32 0, i32 2 +// CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP12]], i32 0, i32 2 // CHECK3-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP9]], align 8 // CHECK3-NEXT: store ptr [[TMP17]], ptr [[TMP16]], align 8 -// CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP12]], i32 0, i32 3 +// CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP12]], i32 0, i32 3 // CHECK3-NEXT: store ptr [[D_ADDR]], ptr [[TMP18]], align 8 -// CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP12]], i32 0, i32 4 +// CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP12]], i32 0, i32 4 // CHECK3-NEXT: store ptr [[A10]], ptr [[TMP19]], align 8 // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[_TMP4]], align 8 // CHECK3-NEXT: [[CALL:%.*]] = call noundef i64 @"_ZZ4mainENK3$_0clEv"(ptr noundef nonnull align 8 dereferenceable(40) [[TMP20]]) #[[ATTR7]] // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l27 -// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR0]] { -// CHECK3-NEXT: entry: -// CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L1:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8 -// CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 -// CHECK3-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_target_init(ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l27_kernel_environment, ptr [[DYN_PTR]]) -// CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP2]], -1 -// CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] -// CHECK3: user_code.entry: -// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8 -// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[L1]], ptr align 8 [[TMP3]], i64 8, i1 false) -// CHECK3-NEXT: store ptr [[L1]], ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP4]], i32 0, i32 0 -// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 -// CHECK3-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[CALL:%.*]] = call noundef i32 @_ZZN1S3fooEvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(8) [[TMP6]]) #[[ATTR7]] -// CHECK3-NEXT: call void @__kmpc_target_deinit() -// CHECK3-NEXT: ret void -// CHECK3: worker.exit: -// CHECK3-NEXT: ret void -// -// -// CHECK3-LABEL: define {{[^@]+}}@_ZZN1S3fooEvENKUlvE_clEv -// CHECK3-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) #[[ATTR2:[0-9]+]] comdat align 2 { -// CHECK3-NEXT: entry: -// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[CLASS_ANON_1:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 -// CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP2:%.*]] = load i32, ptr [[A]], align 4 -// CHECK3-NEXT: ret i32 [[TMP2]] -// -// -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29 -// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR3]] { -// CHECK3-NEXT: entry: -// CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [2 x ptr], align 8 -// CHECK3-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 -// CHECK3-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_target_init(ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_kernel_environment, ptr [[DYN_PTR]]) -// CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP2]], -1 -// CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] -// CHECK3: user_code.entry: -// CHECK3-NEXT: [[TMP3:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) -// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 -// CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 0 -// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 -// CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 1 -// CHECK3-NEXT: store ptr [[TMP4]], ptr [[TMP6]], align 8 -// CHECK3-NEXT: call void @__kmpc_parallel_51(ptr @[[GLOB1]], i32 [[TMP3]], i32 1, i32 -1, i32 -1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_omp_outlined, ptr null, ptr [[CAPTURED_VARS_ADDRS]], i64 2) -// CHECK3-NEXT: call void @__kmpc_target_deinit() -// CHECK3-NEXT: ret void -// CHECK3: worker.exit: -// CHECK3-NEXT: ret void -// -// -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_omp_outlined -// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR4]] { -// CHECK3-NEXT: entry: -// CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L1:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8 -// CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 -// CHECK3-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 -// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8 -// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[L1]], ptr align 8 [[TMP2]], i64 8, i1 false) -// CHECK3-NEXT: store ptr [[L1]], ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP3]], i32 0, i32 0 -// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 -// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[CALL:%.*]] = call noundef i32 @_ZZN1S3fooEvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(8) [[TMP5]]) #[[ATTR7]] -// CHECK3-NEXT: ret void -// -// // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooIZN1S3fooEvEUlvE_EiRKT__l18 // CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[T:%.*]]) #[[ATTR3]] { // CHECK3-NEXT: entry: @@ -1500,7 +1500,7 @@ int main(int argc, char **argv) { // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[T_ADDR:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[T1:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8 +// CHECK3-NEXT: [[T1:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 // CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK3-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 -- GitLab From 1dd0d3cf40f21b842dbee107b3d203db9fbaa4ae Mon Sep 17 00:00:00 2001 From: Dhruv Chawla Date: Thu, 16 May 2024 08:08:06 +0530 Subject: [PATCH 445/578] [AArch64][GISel] Fold COPY(y:gpr, DUP(x:fpr, i)) -> UMOV(y:gpr, x:fpr, i) (#89017) This patch adds a peephole to AArch64PostSelectOptimize for codegen that is caused by RegBankSelect limiting G_EXTRACT_VECTOR_ELT only to FPR registers in both the input and output registers. This can cause a generation of COPY from FPR to GPR when, for example, the output register of the G_EXTRACT_VECTOR_ELT is used in a branch condition. This was noticed when looking at codegen differences between SDAG and GI for the s1279 kernel in the TSVC benchmark. --- .../GISel/AArch64PostSelectOptimize.cpp | 68 ++++++++- llvm/test/CodeGen/AArch64/aarch64-mulv.ll | 117 +++++---------- llvm/test/CodeGen/AArch64/aarch64-smull.ll | 133 ++++++++---------- llvm/test/CodeGen/AArch64/arm64-neon-copy.ll | 12 +- llvm/test/CodeGen/AArch64/bitcast.ll | 24 ++-- llvm/test/CodeGen/AArch64/insertextract.ll | 13 +- llvm/test/CodeGen/AArch64/ptradd.ll | 7 +- llvm/test/CodeGen/AArch64/reduce-and.ll | 42 +++--- llvm/test/CodeGen/AArch64/reduce-or.ll | 42 +++--- llvm/test/CodeGen/AArch64/reduce-xor.ll | 42 +++--- 10 files changed, 238 insertions(+), 262 deletions(-) diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostSelectOptimize.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostSelectOptimize.cpp index 11866f2dd186..e9aed60595e6 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64PostSelectOptimize.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64PostSelectOptimize.cpp @@ -48,6 +48,7 @@ private: bool doPeepholeOpts(MachineBasicBlock &MBB); /// Look for cross regclass copies that can be trivially eliminated. bool foldSimpleCrossClassCopies(MachineInstr &MI); + bool foldCopyDup(MachineInstr &MI); }; } // end anonymous namespace @@ -105,7 +106,10 @@ unsigned getNonFlagSettingVariant(unsigned Opc) { bool AArch64PostSelectOptimize::doPeepholeOpts(MachineBasicBlock &MBB) { bool Changed = false; for (auto &MI : make_early_inc_range(make_range(MBB.begin(), MBB.end()))) { - Changed |= foldSimpleCrossClassCopies(MI); + bool CurrentIterChanged = foldSimpleCrossClassCopies(MI); + if (!CurrentIterChanged) + CurrentIterChanged |= foldCopyDup(MI); + Changed |= CurrentIterChanged; } return Changed; } @@ -158,6 +162,68 @@ bool AArch64PostSelectOptimize::foldSimpleCrossClassCopies(MachineInstr &MI) { return true; } +bool AArch64PostSelectOptimize::foldCopyDup(MachineInstr &MI) { + if (!MI.isCopy()) + return false; + + auto *MF = MI.getMF(); + auto &MRI = MF->getRegInfo(); + auto *TII = MF->getSubtarget().getInstrInfo(); + + // Optimize COPY(y:GPR, DUP(x:FPR, i)) -> UMOV(y:GPR, x:FPR, i). + // Here Dst is y and Src is the result of DUP. + Register Dst = MI.getOperand(0).getReg(); + Register Src = MI.getOperand(1).getReg(); + + if (!Dst.isVirtual() || !Src.isVirtual()) + return false; + + auto TryMatchDUP = [&](const TargetRegisterClass *GPRRegClass, + const TargetRegisterClass *FPRRegClass, unsigned DUP, + unsigned UMOV) { + if (MRI.getRegClassOrNull(Dst) != GPRRegClass || + MRI.getRegClassOrNull(Src) != FPRRegClass) + return false; + + // There is a special case when one of the uses is COPY(z:FPR, y:GPR). + // In this case, we get COPY(z:FPR, COPY(y:GPR, DUP(x:FPR, i))), which can + // be folded by peephole-opt into just DUP(z:FPR, i), so this transform is + // not worthwhile in that case. + for (auto &Use : MRI.use_nodbg_instructions(Dst)) { + if (!Use.isCopy()) + continue; + + Register UseOp0 = Use.getOperand(0).getReg(); + Register UseOp1 = Use.getOperand(1).getReg(); + if (UseOp0.isPhysical() || UseOp1.isPhysical()) + return false; + + if (MRI.getRegClassOrNull(UseOp0) == FPRRegClass && + MRI.getRegClassOrNull(UseOp1) == GPRRegClass) + return false; + } + + MachineInstr *SrcMI = MRI.getUniqueVRegDef(Src); + if (!SrcMI || SrcMI->getOpcode() != DUP || !MRI.hasOneNonDBGUse(Src)) + return false; + + Register DupSrc = SrcMI->getOperand(1).getReg(); + int64_t DupImm = SrcMI->getOperand(2).getImm(); + + BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(UMOV), Dst) + .addReg(DupSrc) + .addImm(DupImm); + SrcMI->eraseFromParent(); + MI.eraseFromParent(); + return true; + }; + + return TryMatchDUP(&AArch64::GPR32RegClass, &AArch64::FPR32RegClass, + AArch64::DUPi32, AArch64::UMOVvi32) || + TryMatchDUP(&AArch64::GPR64RegClass, &AArch64::FPR64RegClass, + AArch64::DUPi64, AArch64::UMOVvi64); +} + bool AArch64PostSelectOptimize::optimizeNZCVDefs(MachineBasicBlock &MBB) { // If we find a dead NZCV implicit-def, we // - try to convert the operation to a non-flag-setting equivalent diff --git a/llvm/test/CodeGen/AArch64/aarch64-mulv.ll b/llvm/test/CodeGen/AArch64/aarch64-mulv.ll index 7b7ca9d8ffc2..e11ae9a25159 100644 --- a/llvm/test/CodeGen/AArch64/aarch64-mulv.ll +++ b/llvm/test/CodeGen/AArch64/aarch64-mulv.ll @@ -25,22 +25,13 @@ declare i64 @llvm.vector.reduce.mul.v4i64(<4 x i64>) declare i128 @llvm.vector.reduce.mul.v2i128(<2 x i128>) define i8 @mulv_v2i8(<2 x i8> %a) { -; CHECK-SD-LABEL: mulv_v2i8: -; CHECK-SD: // %bb.0: // %entry -; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-SD-NEXT: mov w8, v0.s[1] -; CHECK-SD-NEXT: fmov w9, s0 -; CHECK-SD-NEXT: mul w0, w9, w8 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: mulv_v2i8: -; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-GI-NEXT: mov s1, v0.s[1] -; CHECK-GI-NEXT: fmov w8, s0 -; CHECK-GI-NEXT: fmov w9, s1 -; CHECK-GI-NEXT: mul w0, w8, w9 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: mulv_v2i8: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: mov w8, v0.s[1] +; CHECK-NEXT: fmov w9, s0 +; CHECK-NEXT: mul w0, w9, w8 +; CHECK-NEXT: ret entry: %arg1 = call i8 @llvm.vector.reduce.mul.v2i8(<2 x i8> %a) ret i8 %arg1 @@ -230,22 +221,13 @@ entry: } define i16 @mulv_v2i16(<2 x i16> %a) { -; CHECK-SD-LABEL: mulv_v2i16: -; CHECK-SD: // %bb.0: // %entry -; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-SD-NEXT: mov w8, v0.s[1] -; CHECK-SD-NEXT: fmov w9, s0 -; CHECK-SD-NEXT: mul w0, w9, w8 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: mulv_v2i16: -; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-GI-NEXT: mov s1, v0.s[1] -; CHECK-GI-NEXT: fmov w8, s0 -; CHECK-GI-NEXT: fmov w9, s1 -; CHECK-GI-NEXT: mul w0, w8, w9 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: mulv_v2i16: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: mov w8, v0.s[1] +; CHECK-NEXT: fmov w9, s0 +; CHECK-NEXT: mul w0, w9, w8 +; CHECK-NEXT: ret entry: %arg1 = call i16 @llvm.vector.reduce.mul.v2i16(<2 x i16> %a) ret i16 %arg1 @@ -372,22 +354,13 @@ entry: } define i32 @mulv_v2i32(<2 x i32> %a) { -; CHECK-SD-LABEL: mulv_v2i32: -; CHECK-SD: // %bb.0: // %entry -; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-SD-NEXT: mov w8, v0.s[1] -; CHECK-SD-NEXT: fmov w9, s0 -; CHECK-SD-NEXT: mul w0, w9, w8 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: mulv_v2i32: -; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-GI-NEXT: mov s1, v0.s[1] -; CHECK-GI-NEXT: fmov w8, s0 -; CHECK-GI-NEXT: fmov w9, s1 -; CHECK-GI-NEXT: mul w0, w8, w9 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: mulv_v2i32: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: mov w8, v0.s[1] +; CHECK-NEXT: fmov w9, s0 +; CHECK-NEXT: mul w0, w9, w8 +; CHECK-NEXT: ret entry: %arg1 = call i32 @llvm.vector.reduce.mul.v2i32(<2 x i32> %a) ret i32 %arg1 @@ -424,10 +397,9 @@ define i32 @mulv_v4i32(<4 x i32> %a) { ; CHECK-GI: // %bb.0: // %entry ; CHECK-GI-NEXT: mov d1, v0.d[1] ; CHECK-GI-NEXT: mul v0.2s, v0.2s, v1.2s -; CHECK-GI-NEXT: mov s1, v0.s[1] -; CHECK-GI-NEXT: fmov w8, s0 -; CHECK-GI-NEXT: fmov w9, s1 -; CHECK-GI-NEXT: mul w0, w8, w9 +; CHECK-GI-NEXT: mov w8, v0.s[1] +; CHECK-GI-NEXT: fmov w9, s0 +; CHECK-GI-NEXT: mul w0, w9, w8 ; CHECK-GI-NEXT: ret entry: %arg1 = call i32 @llvm.vector.reduce.mul.v4i32(<4 x i32> %a) @@ -452,10 +424,9 @@ define i32 @mulv_v8i32(<8 x i32> %a) { ; CHECK-GI-NEXT: mul v0.2s, v0.2s, v2.2s ; CHECK-GI-NEXT: mul v1.2s, v1.2s, v3.2s ; CHECK-GI-NEXT: mul v0.2s, v0.2s, v1.2s -; CHECK-GI-NEXT: mov s1, v0.s[1] -; CHECK-GI-NEXT: fmov w8, s0 -; CHECK-GI-NEXT: fmov w9, s1 -; CHECK-GI-NEXT: mul w0, w8, w9 +; CHECK-GI-NEXT: mov w8, v0.s[1] +; CHECK-GI-NEXT: fmov w9, s0 +; CHECK-GI-NEXT: mul w0, w9, w8 ; CHECK-GI-NEXT: ret entry: %arg1 = call i32 @llvm.vector.reduce.mul.v8i32(<8 x i32> %a) @@ -463,20 +434,12 @@ entry: } define i64 @mulv_v2i64(<2 x i64> %a) { -; CHECK-SD-LABEL: mulv_v2i64: -; CHECK-SD: // %bb.0: // %entry -; CHECK-SD-NEXT: mov x8, v0.d[1] -; CHECK-SD-NEXT: fmov x9, d0 -; CHECK-SD-NEXT: mul x0, x9, x8 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: mulv_v2i64: -; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: mov d1, v0.d[1] -; CHECK-GI-NEXT: fmov x8, d0 -; CHECK-GI-NEXT: fmov x9, d1 -; CHECK-GI-NEXT: mul x0, x8, x9 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: mulv_v2i64: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov x8, v0.d[1] +; CHECK-NEXT: fmov x9, d0 +; CHECK-NEXT: mul x0, x9, x8 +; CHECK-NEXT: ret entry: %arg1 = call i64 @llvm.vector.reduce.mul.v2i64(<2 x i64> %a) ret i64 %arg1 @@ -522,14 +485,12 @@ define i64 @mulv_v4i64(<4 x i64> %a) { ; ; CHECK-GI-LABEL: mulv_v4i64: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: mov d2, v0.d[1] -; CHECK-GI-NEXT: mov d3, v1.d[1] -; CHECK-GI-NEXT: fmov x8, d0 -; CHECK-GI-NEXT: fmov x9, d2 -; CHECK-GI-NEXT: fmov x10, d3 -; CHECK-GI-NEXT: mul x8, x8, x9 -; CHECK-GI-NEXT: fmov x9, d1 -; CHECK-GI-NEXT: mul x9, x9, x10 +; CHECK-GI-NEXT: mov x8, v0.d[1] +; CHECK-GI-NEXT: fmov x10, d0 +; CHECK-GI-NEXT: mov x9, v1.d[1] +; CHECK-GI-NEXT: mul x8, x10, x8 +; CHECK-GI-NEXT: fmov x10, d1 +; CHECK-GI-NEXT: mul x9, x10, x9 ; CHECK-GI-NEXT: mul x0, x8, x9 ; CHECK-GI-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/aarch64-smull.ll b/llvm/test/CodeGen/AArch64/aarch64-smull.ll index 540471a05901..307aa397eabb 100644 --- a/llvm/test/CodeGen/AArch64/aarch64-smull.ll +++ b/llvm/test/CodeGen/AArch64/aarch64-smull.ll @@ -279,17 +279,15 @@ define <2 x i64> @smull_zext_v2i32_v2i64(ptr %A, ptr %B) nounwind { ; CHECK-GI-NEXT: ldr d0, [x1] ; CHECK-GI-NEXT: sshll v0.2d, v0.2s, #0 ; CHECK-GI-NEXT: fmov d1, x8 -; CHECK-GI-NEXT: mov d3, v0.d[1] +; CHECK-GI-NEXT: fmov x11, d0 ; CHECK-GI-NEXT: mov v1.d[1], x9 -; CHECK-GI-NEXT: fmov x9, d0 -; CHECK-GI-NEXT: fmov x10, d3 -; CHECK-GI-NEXT: mov d2, v1.d[1] -; CHECK-GI-NEXT: fmov x8, d1 +; CHECK-GI-NEXT: mov x9, v0.d[1] +; CHECK-GI-NEXT: fmov x10, d1 +; CHECK-GI-NEXT: mov x8, v1.d[1] +; CHECK-GI-NEXT: mul x10, x10, x11 ; CHECK-GI-NEXT: mul x8, x8, x9 -; CHECK-GI-NEXT: fmov x9, d2 -; CHECK-GI-NEXT: mul x9, x9, x10 -; CHECK-GI-NEXT: fmov d0, x8 -; CHECK-GI-NEXT: mov v0.d[1], x9 +; CHECK-GI-NEXT: fmov d0, x10 +; CHECK-GI-NEXT: mov v0.d[1], x8 ; CHECK-GI-NEXT: ret %load.A = load <2 x i16>, ptr %A %load.B = load <2 x i32>, ptr %B @@ -324,16 +322,14 @@ define <2 x i64> @smull_zext_and_v2i32_v2i64(ptr %A, ptr %B) nounwind { ; CHECK-GI-NEXT: ldr d1, [x1] ; CHECK-GI-NEXT: sshll v1.2d, v1.2s, #0 ; CHECK-GI-NEXT: ushll v0.2d, v0.2s, #0 -; CHECK-GI-NEXT: mov d3, v1.d[1] -; CHECK-GI-NEXT: fmov x9, d1 -; CHECK-GI-NEXT: mov d2, v0.d[1] -; CHECK-GI-NEXT: fmov x8, d0 +; CHECK-GI-NEXT: fmov x11, d1 +; CHECK-GI-NEXT: mov x9, v1.d[1] +; CHECK-GI-NEXT: fmov x10, d0 +; CHECK-GI-NEXT: mov x8, v0.d[1] +; CHECK-GI-NEXT: mul x10, x10, x11 ; CHECK-GI-NEXT: mul x8, x8, x9 -; CHECK-GI-NEXT: fmov x10, d3 -; CHECK-GI-NEXT: fmov x9, d2 -; CHECK-GI-NEXT: mul x9, x9, x10 -; CHECK-GI-NEXT: fmov d0, x8 -; CHECK-GI-NEXT: mov v0.d[1], x9 +; CHECK-GI-NEXT: fmov d0, x10 +; CHECK-GI-NEXT: mov v0.d[1], x8 ; CHECK-GI-NEXT: ret %load.A = load <2 x i32>, ptr %A %and.A = and <2 x i32> %load.A, @@ -1052,16 +1048,14 @@ define <2 x i64> @smull_extvec_v2i32_v2i64(<2 x i32> %arg) nounwind { ; CHECK-GI-NEXT: adrp x8, .LCPI36_0 ; CHECK-GI-NEXT: sshll v0.2d, v0.2s, #0 ; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI36_0] -; CHECK-GI-NEXT: mov d2, v0.d[1] -; CHECK-GI-NEXT: mov d3, v1.d[1] -; CHECK-GI-NEXT: fmov x8, d0 -; CHECK-GI-NEXT: fmov x9, d1 +; CHECK-GI-NEXT: fmov x10, d0 +; CHECK-GI-NEXT: fmov x11, d1 +; CHECK-GI-NEXT: mov x8, v0.d[1] +; CHECK-GI-NEXT: mov x9, v1.d[1] +; CHECK-GI-NEXT: mul x10, x10, x11 ; CHECK-GI-NEXT: mul x8, x8, x9 -; CHECK-GI-NEXT: fmov x9, d2 -; CHECK-GI-NEXT: fmov x10, d3 -; CHECK-GI-NEXT: mul x9, x9, x10 -; CHECK-GI-NEXT: fmov d0, x8 -; CHECK-GI-NEXT: mov v0.d[1], x9 +; CHECK-GI-NEXT: fmov d0, x10 +; CHECK-GI-NEXT: mov v0.d[1], x8 ; CHECK-GI-NEXT: ret %tmp3 = sext <2 x i32> %arg to <2 x i64> %tmp4 = mul <2 x i64> %tmp3, @@ -1169,16 +1163,14 @@ define <2 x i64> @umull_extvec_v2i32_v2i64(<2 x i32> %arg) nounwind { ; CHECK-GI-NEXT: adrp x8, .LCPI40_0 ; CHECK-GI-NEXT: ushll v0.2d, v0.2s, #0 ; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI40_0] -; CHECK-GI-NEXT: mov d2, v0.d[1] -; CHECK-GI-NEXT: mov d3, v1.d[1] -; CHECK-GI-NEXT: fmov x8, d0 -; CHECK-GI-NEXT: fmov x9, d1 +; CHECK-GI-NEXT: fmov x10, d0 +; CHECK-GI-NEXT: fmov x11, d1 +; CHECK-GI-NEXT: mov x8, v0.d[1] +; CHECK-GI-NEXT: mov x9, v1.d[1] +; CHECK-GI-NEXT: mul x10, x10, x11 ; CHECK-GI-NEXT: mul x8, x8, x9 -; CHECK-GI-NEXT: fmov x9, d2 -; CHECK-GI-NEXT: fmov x10, d3 -; CHECK-GI-NEXT: mul x9, x9, x10 -; CHECK-GI-NEXT: fmov d0, x8 -; CHECK-GI-NEXT: mov v0.d[1], x9 +; CHECK-GI-NEXT: fmov d0, x10 +; CHECK-GI-NEXT: mov v0.d[1], x8 ; CHECK-GI-NEXT: ret %tmp3 = zext <2 x i32> %arg to <2 x i64> %tmp4 = mul <2 x i64> %tmp3, @@ -1272,17 +1264,15 @@ define <2 x i64> @amull_extvec_v2i32_v2i64(<2 x i32> %arg) nounwind { ; CHECK-GI-NEXT: adrp x8, .LCPI43_0 ; CHECK-GI-NEXT: ushll v0.2d, v0.2s, #0 ; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI43_0] -; CHECK-GI-NEXT: mov d2, v0.d[1] -; CHECK-GI-NEXT: mov d3, v1.d[1] -; CHECK-GI-NEXT: fmov x8, d0 -; CHECK-GI-NEXT: fmov x9, d1 +; CHECK-GI-NEXT: fmov x10, d0 +; CHECK-GI-NEXT: fmov x11, d1 +; CHECK-GI-NEXT: mov x8, v0.d[1] +; CHECK-GI-NEXT: mov x9, v1.d[1] ; CHECK-GI-NEXT: movi v1.2d, #0x000000ffffffff +; CHECK-GI-NEXT: mul x10, x10, x11 ; CHECK-GI-NEXT: mul x8, x8, x9 -; CHECK-GI-NEXT: fmov x9, d2 -; CHECK-GI-NEXT: fmov x10, d3 -; CHECK-GI-NEXT: mul x9, x9, x10 -; CHECK-GI-NEXT: fmov d0, x8 -; CHECK-GI-NEXT: mov v0.d[1], x9 +; CHECK-GI-NEXT: fmov d0, x10 +; CHECK-GI-NEXT: mov v0.d[1], x8 ; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b ; CHECK-GI-NEXT: ret %tmp3 = zext <2 x i32> %arg to <2 x i64> @@ -1901,17 +1891,15 @@ define <2 x i64> @umull_and_v2i64(<2 x i32> %src1, <2 x i64> %src2) { ; CHECK-GI: // %bb.0: // %entry ; CHECK-GI-NEXT: movi v2.2d, #0x000000000000ff ; CHECK-GI-NEXT: ushll v0.2d, v0.2s, #0 -; CHECK-GI-NEXT: fmov x8, d0 +; CHECK-GI-NEXT: fmov x10, d0 +; CHECK-GI-NEXT: mov x8, v0.d[1] ; CHECK-GI-NEXT: and v1.16b, v1.16b, v2.16b -; CHECK-GI-NEXT: mov d2, v0.d[1] -; CHECK-GI-NEXT: mov d3, v1.d[1] -; CHECK-GI-NEXT: fmov x9, d1 +; CHECK-GI-NEXT: fmov x11, d1 +; CHECK-GI-NEXT: mov x9, v1.d[1] +; CHECK-GI-NEXT: mul x10, x10, x11 ; CHECK-GI-NEXT: mul x8, x8, x9 -; CHECK-GI-NEXT: fmov x9, d2 -; CHECK-GI-NEXT: fmov x10, d3 -; CHECK-GI-NEXT: mul x9, x9, x10 -; CHECK-GI-NEXT: fmov d0, x8 -; CHECK-GI-NEXT: mov v0.d[1], x9 +; CHECK-GI-NEXT: fmov d0, x10 +; CHECK-GI-NEXT: mov v0.d[1], x8 ; CHECK-GI-NEXT: ret entry: %in1 = zext <2 x i32> %src1 to <2 x i64> @@ -1947,26 +1935,22 @@ define <4 x i64> @umull_and_v4i64(<4 x i32> %src1, <4 x i64> %src2) { ; CHECK-GI-NEXT: ushll v4.2d, v0.2s, #0 ; CHECK-GI-NEXT: ushll2 v0.2d, v0.4s, #0 ; CHECK-GI-NEXT: fmov x8, d4 +; CHECK-GI-NEXT: mov x10, v4.d[1] +; CHECK-GI-NEXT: mov x13, v0.d[1] ; CHECK-GI-NEXT: and v1.16b, v1.16b, v3.16b ; CHECK-GI-NEXT: and v2.16b, v2.16b, v3.16b -; CHECK-GI-NEXT: mov d3, v4.d[1] ; CHECK-GI-NEXT: fmov x9, d1 -; CHECK-GI-NEXT: mov d4, v1.d[1] -; CHECK-GI-NEXT: fmov x10, d2 -; CHECK-GI-NEXT: mov d1, v0.d[1] +; CHECK-GI-NEXT: fmov x12, d2 +; CHECK-GI-NEXT: mov x11, v1.d[1] +; CHECK-GI-NEXT: mov x14, v2.d[1] ; CHECK-GI-NEXT: mul x8, x8, x9 ; CHECK-GI-NEXT: fmov x9, d0 -; CHECK-GI-NEXT: mov d0, v2.d[1] -; CHECK-GI-NEXT: fmov x11, d4 -; CHECK-GI-NEXT: mul x9, x9, x10 -; CHECK-GI-NEXT: fmov x10, d3 -; CHECK-GI-NEXT: fmov x12, d0 -; CHECK-GI-NEXT: fmov d0, x8 ; CHECK-GI-NEXT: mul x10, x10, x11 -; CHECK-GI-NEXT: fmov x11, d1 -; CHECK-GI-NEXT: fmov d1, x9 -; CHECK-GI-NEXT: mul x11, x11, x12 +; CHECK-GI-NEXT: mul x9, x9, x12 +; CHECK-GI-NEXT: fmov d0, x8 +; CHECK-GI-NEXT: mul x11, x13, x14 ; CHECK-GI-NEXT: mov v0.d[1], x10 +; CHECK-GI-NEXT: fmov d1, x9 ; CHECK-GI-NEXT: mov v1.d[1], x11 ; CHECK-GI-NEXT: ret entry: @@ -1999,20 +1983,17 @@ define <4 x i64> @umull_and_v4i64_dup(<4 x i32> %src1, i64 %src2) { ; CHECK-GI-NEXT: ushll v1.2d, v0.2s, #0 ; CHECK-GI-NEXT: ushll2 v0.2d, v0.4s, #0 ; CHECK-GI-NEXT: dup v2.2d, x8 -; CHECK-GI-NEXT: mov d3, v1.d[1] ; CHECK-GI-NEXT: fmov x8, d1 -; CHECK-GI-NEXT: fmov x10, d0 -; CHECK-GI-NEXT: mov d1, v2.d[1] +; CHECK-GI-NEXT: fmov x12, d0 +; CHECK-GI-NEXT: mov x10, v1.d[1] ; CHECK-GI-NEXT: fmov x9, d2 -; CHECK-GI-NEXT: mov d2, v0.d[1] +; CHECK-GI-NEXT: mov x11, v2.d[1] +; CHECK-GI-NEXT: mov x13, v0.d[1] ; CHECK-GI-NEXT: mul x8, x8, x9 -; CHECK-GI-NEXT: fmov x11, d1 -; CHECK-GI-NEXT: fmov x12, d2 -; CHECK-GI-NEXT: mul x9, x10, x9 -; CHECK-GI-NEXT: fmov x10, d3 +; CHECK-GI-NEXT: mul x9, x12, x9 ; CHECK-GI-NEXT: mul x10, x10, x11 ; CHECK-GI-NEXT: fmov d0, x8 -; CHECK-GI-NEXT: mul x11, x12, x11 +; CHECK-GI-NEXT: mul x11, x13, x11 ; CHECK-GI-NEXT: fmov d1, x9 ; CHECK-GI-NEXT: mov v0.d[1], x10 ; CHECK-GI-NEXT: mov v1.d[1], x11 diff --git a/llvm/test/CodeGen/AArch64/arm64-neon-copy.ll b/llvm/test/CodeGen/AArch64/arm64-neon-copy.ll index 749d6071c98d..43d5ab5ab54e 100644 --- a/llvm/test/CodeGen/AArch64/arm64-neon-copy.ll +++ b/llvm/test/CodeGen/AArch64/arm64-neon-copy.ll @@ -1488,8 +1488,7 @@ define <4 x i16> @test_dup_v2i32_v4i16(<2 x i32> %a) { ; CHECK-GI-LABEL: test_dup_v2i32_v4i16: ; CHECK-GI: // %bb.0: // %entry ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-GI-NEXT: mov s0, v0.s[1] -; CHECK-GI-NEXT: fmov w8, s0 +; CHECK-GI-NEXT: mov w8, v0.s[1] ; CHECK-GI-NEXT: dup v0.4h, w8 ; CHECK-GI-NEXT: ret entry: @@ -1510,8 +1509,7 @@ define <8 x i16> @test_dup_v4i32_v8i16(<4 x i32> %a) { ; ; CHECK-GI-LABEL: test_dup_v4i32_v8i16: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: mov s0, v0.s[3] -; CHECK-GI-NEXT: fmov w8, s0 +; CHECK-GI-NEXT: mov w8, v0.s[3] ; CHECK-GI-NEXT: dup v0.8h, w8 ; CHECK-GI-NEXT: ret entry: @@ -1578,8 +1576,7 @@ define <8 x i16> @test_dup_v2i64_v8i16(<2 x i64> %a) { ; ; CHECK-GI-LABEL: test_dup_v2i64_v8i16: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: mov d0, v0.d[1] -; CHECK-GI-NEXT: fmov x8, d0 +; CHECK-GI-NEXT: mov x8, v0.d[1] ; CHECK-GI-NEXT: dup v0.8h, w8 ; CHECK-GI-NEXT: ret entry: @@ -1626,8 +1623,7 @@ define <4 x i16> @test_dup_v4i32_v4i16(<4 x i32> %a) { ; ; CHECK-GI-LABEL: test_dup_v4i32_v4i16: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: mov s0, v0.s[1] -; CHECK-GI-NEXT: fmov w8, s0 +; CHECK-GI-NEXT: mov w8, v0.s[1] ; CHECK-GI-NEXT: dup v0.4h, w8 ; CHECK-GI-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/bitcast.ll b/llvm/test/CodeGen/AArch64/bitcast.ll index e0851fd8739e..5de99586f7fc 100644 --- a/llvm/test/CodeGen/AArch64/bitcast.ll +++ b/llvm/test/CodeGen/AArch64/bitcast.ll @@ -517,10 +517,8 @@ define <4 x i64> @bitcast_v8i32_v4i64(<8 x i32> %a, <8 x i32> %b){ ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: add v0.4s, v0.4s, v2.4s ; CHECK-GI-NEXT: add v1.4s, v1.4s, v3.4s -; CHECK-GI-NEXT: mov d2, v0.d[1] -; CHECK-GI-NEXT: mov d3, v1.d[1] -; CHECK-GI-NEXT: fmov x8, d2 -; CHECK-GI-NEXT: fmov x9, d3 +; CHECK-GI-NEXT: mov x8, v0.d[1] +; CHECK-GI-NEXT: mov x9, v1.d[1] ; CHECK-GI-NEXT: mov v0.d[1], x8 ; CHECK-GI-NEXT: mov v1.d[1], x9 ; CHECK-GI-NEXT: ret @@ -578,10 +576,8 @@ define <4 x i64> @bitcast_v16i16_v4i64(<16 x i16> %a, <16 x i16> %b){ ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: add v0.8h, v0.8h, v2.8h ; CHECK-GI-NEXT: add v1.8h, v1.8h, v3.8h -; CHECK-GI-NEXT: mov d2, v0.d[1] -; CHECK-GI-NEXT: mov d3, v1.d[1] -; CHECK-GI-NEXT: fmov x8, d2 -; CHECK-GI-NEXT: fmov x9, d3 +; CHECK-GI-NEXT: mov x8, v0.d[1] +; CHECK-GI-NEXT: mov x9, v1.d[1] ; CHECK-GI-NEXT: mov v0.d[1], x8 ; CHECK-GI-NEXT: mov v1.d[1], x9 ; CHECK-GI-NEXT: ret @@ -622,14 +618,10 @@ define <8 x i64> @bitcast_v16i32_v8i64(<16 x i32> %a, <16 x i32> %b){ ; CHECK-GI-NEXT: add v1.4s, v1.4s, v5.4s ; CHECK-GI-NEXT: add v2.4s, v2.4s, v6.4s ; CHECK-GI-NEXT: add v3.4s, v3.4s, v7.4s -; CHECK-GI-NEXT: mov d4, v0.d[1] -; CHECK-GI-NEXT: mov d5, v1.d[1] -; CHECK-GI-NEXT: mov d6, v2.d[1] -; CHECK-GI-NEXT: mov d7, v3.d[1] -; CHECK-GI-NEXT: fmov x8, d4 -; CHECK-GI-NEXT: fmov x9, d5 -; CHECK-GI-NEXT: fmov x10, d6 -; CHECK-GI-NEXT: fmov x11, d7 +; CHECK-GI-NEXT: mov x8, v0.d[1] +; CHECK-GI-NEXT: mov x9, v1.d[1] +; CHECK-GI-NEXT: mov x10, v2.d[1] +; CHECK-GI-NEXT: mov x11, v3.d[1] ; CHECK-GI-NEXT: mov v0.d[1], x8 ; CHECK-GI-NEXT: mov v1.d[1], x9 ; CHECK-GI-NEXT: mov v2.d[1], x10 diff --git a/llvm/test/CodeGen/AArch64/insertextract.ll b/llvm/test/CodeGen/AArch64/insertextract.ll index c6b2d07231bf..8b82004388b0 100644 --- a/llvm/test/CodeGen/AArch64/insertextract.ll +++ b/llvm/test/CodeGen/AArch64/insertextract.ll @@ -983,13 +983,12 @@ define <3 x i32> @insert_v3i32_0(<3 x i32> %a, i32 %b, i32 %c) { ; ; CHECK-GI-LABEL: insert_v3i32_0: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: mov s1, v0.s[1] -; CHECK-GI-NEXT: mov s2, v0.s[2] -; CHECK-GI-NEXT: fmov s0, w0 -; CHECK-GI-NEXT: fmov w8, s1 -; CHECK-GI-NEXT: mov v0.s[1], w8 -; CHECK-GI-NEXT: fmov w8, s2 -; CHECK-GI-NEXT: mov v0.s[2], w8 +; CHECK-GI-NEXT: mov w8, v0.s[1] +; CHECK-GI-NEXT: fmov s1, w0 +; CHECK-GI-NEXT: mov w9, v0.s[2] +; CHECK-GI-NEXT: mov v1.s[1], w8 +; CHECK-GI-NEXT: mov v1.s[2], w9 +; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: ret entry: %d = insertelement <3 x i32> %a, i32 %b, i32 0 diff --git a/llvm/test/CodeGen/AArch64/ptradd.ll b/llvm/test/CodeGen/AArch64/ptradd.ll index 107db8723c64..af283f6a093e 100644 --- a/llvm/test/CodeGen/AArch64/ptradd.ll +++ b/llvm/test/CodeGen/AArch64/ptradd.ll @@ -81,13 +81,12 @@ define void @vector_gep_v3i32(<3 x ptr> %b, <3 x i32> %off, ptr %p) { ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 ; CHECK-GI-NEXT: smov x9, v3.s[1] -; CHECK-GI-NEXT: mov s3, v3.s[2] ; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] ; CHECK-GI-NEXT: fmov d1, x8 -; CHECK-GI-NEXT: fmov x8, d2 +; CHECK-GI-NEXT: mov w8, v3.s[2] ; CHECK-GI-NEXT: mov v1.d[1], x9 -; CHECK-GI-NEXT: fmov w9, s3 -; CHECK-GI-NEXT: add x8, x8, w9, sxtw +; CHECK-GI-NEXT: fmov x9, d2 +; CHECK-GI-NEXT: add x8, x9, w8, sxtw ; CHECK-GI-NEXT: add v0.2d, v0.2d, v1.2d ; CHECK-GI-NEXT: str x8, [x0, #16] ; CHECK-GI-NEXT: str q0, [x0] diff --git a/llvm/test/CodeGen/AArch64/reduce-and.ll b/llvm/test/CodeGen/AArch64/reduce-and.ll index 62ad45b21296..8ca521327c2e 100644 --- a/llvm/test/CodeGen/AArch64/reduce-and.ll +++ b/llvm/test/CodeGen/AArch64/reduce-and.ll @@ -30,10 +30,9 @@ define i1 @test_redand_v2i1(<2 x i1> %a) { ; GISEL-LABEL: test_redand_v2i1: ; GISEL: // %bb.0: ; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: and w8, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: and w8, w9, w8 ; GISEL-NEXT: and w0, w8, #0x1 ; GISEL-NEXT: ret %or_result = call i1 @llvm.vector.reduce.and.v2i1(<2 x i1> %a) @@ -457,10 +456,9 @@ define i32 @test_redand_v2i32(<2 x i32> %a) { ; GISEL-LABEL: test_redand_v2i32: ; GISEL: // %bb.0: ; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: and w0, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: and w0, w9, w8 ; GISEL-NEXT: ret %and_result = call i32 @llvm.vector.reduce.and.v2i32(<2 x i32> %a) ret i32 %and_result @@ -480,10 +478,9 @@ define i32 @test_redand_v4i32(<4 x i32> %a) { ; GISEL: // %bb.0: ; GISEL-NEXT: mov d1, v0.d[1] ; GISEL-NEXT: and v0.8b, v0.8b, v1.8b -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: and w0, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: and w0, w9, w8 ; GISEL-NEXT: ret %and_result = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %a) ret i32 %and_result @@ -505,10 +502,9 @@ define i32 @test_redand_v8i32(<8 x i32> %a) { ; GISEL-NEXT: and v0.16b, v0.16b, v1.16b ; GISEL-NEXT: mov d1, v0.d[1] ; GISEL-NEXT: and v0.8b, v0.8b, v1.8b -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: and w0, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: and w0, w9, w8 ; GISEL-NEXT: ret %and_result = call i32 @llvm.vector.reduce.and.v8i32(<8 x i32> %a) ret i32 %and_result @@ -524,10 +520,9 @@ define i64 @test_redand_v2i64(<2 x i64> %a) { ; ; GISEL-LABEL: test_redand_v2i64: ; GISEL: // %bb.0: -; GISEL-NEXT: mov d1, v0.d[1] -; GISEL-NEXT: fmov x8, d0 -; GISEL-NEXT: fmov x9, d1 -; GISEL-NEXT: and x0, x8, x9 +; GISEL-NEXT: mov x8, v0.d[1] +; GISEL-NEXT: fmov x9, d0 +; GISEL-NEXT: and x0, x9, x8 ; GISEL-NEXT: ret %and_result = call i64 @llvm.vector.reduce.and.v2i64(<2 x i64> %a) ret i64 %and_result @@ -545,10 +540,9 @@ define i64 @test_redand_v4i64(<4 x i64> %a) { ; GISEL-LABEL: test_redand_v4i64: ; GISEL: // %bb.0: ; GISEL-NEXT: and v0.16b, v0.16b, v1.16b -; GISEL-NEXT: mov d1, v0.d[1] -; GISEL-NEXT: fmov x8, d0 -; GISEL-NEXT: fmov x9, d1 -; GISEL-NEXT: and x0, x8, x9 +; GISEL-NEXT: mov x8, v0.d[1] +; GISEL-NEXT: fmov x9, d0 +; GISEL-NEXT: and x0, x9, x8 ; GISEL-NEXT: ret %and_result = call i64 @llvm.vector.reduce.and.v4i64(<4 x i64> %a) ret i64 %and_result diff --git a/llvm/test/CodeGen/AArch64/reduce-or.ll b/llvm/test/CodeGen/AArch64/reduce-or.ll index 20c498d36fde..aac31ce8b71b 100644 --- a/llvm/test/CodeGen/AArch64/reduce-or.ll +++ b/llvm/test/CodeGen/AArch64/reduce-or.ll @@ -30,10 +30,9 @@ define i1 @test_redor_v2i1(<2 x i1> %a) { ; GISEL-LABEL: test_redor_v2i1: ; GISEL: // %bb.0: ; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: orr w8, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: orr w8, w9, w8 ; GISEL-NEXT: and w0, w8, #0x1 ; GISEL-NEXT: ret %or_result = call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> %a) @@ -459,10 +458,9 @@ define i32 @test_redor_v2i32(<2 x i32> %a) { ; GISEL-LABEL: test_redor_v2i32: ; GISEL: // %bb.0: ; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: orr w0, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: orr w0, w9, w8 ; GISEL-NEXT: ret %or_result = call i32 @llvm.vector.reduce.or.v2i32(<2 x i32> %a) ret i32 %or_result @@ -482,10 +480,9 @@ define i32 @test_redor_v4i32(<4 x i32> %a) { ; GISEL: // %bb.0: ; GISEL-NEXT: mov d1, v0.d[1] ; GISEL-NEXT: orr v0.8b, v0.8b, v1.8b -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: orr w0, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: orr w0, w9, w8 ; GISEL-NEXT: ret %or_result = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %a) ret i32 %or_result @@ -507,10 +504,9 @@ define i32 @test_redor_v8i32(<8 x i32> %a) { ; GISEL-NEXT: orr v0.16b, v0.16b, v1.16b ; GISEL-NEXT: mov d1, v0.d[1] ; GISEL-NEXT: orr v0.8b, v0.8b, v1.8b -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: orr w0, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: orr w0, w9, w8 ; GISEL-NEXT: ret %or_result = call i32 @llvm.vector.reduce.or.v8i32(<8 x i32> %a) ret i32 %or_result @@ -526,10 +522,9 @@ define i64 @test_redor_v2i64(<2 x i64> %a) { ; ; GISEL-LABEL: test_redor_v2i64: ; GISEL: // %bb.0: -; GISEL-NEXT: mov d1, v0.d[1] -; GISEL-NEXT: fmov x8, d0 -; GISEL-NEXT: fmov x9, d1 -; GISEL-NEXT: orr x0, x8, x9 +; GISEL-NEXT: mov x8, v0.d[1] +; GISEL-NEXT: fmov x9, d0 +; GISEL-NEXT: orr x0, x9, x8 ; GISEL-NEXT: ret %or_result = call i64 @llvm.vector.reduce.or.v2i64(<2 x i64> %a) ret i64 %or_result @@ -547,10 +542,9 @@ define i64 @test_redor_v4i64(<4 x i64> %a) { ; GISEL-LABEL: test_redor_v4i64: ; GISEL: // %bb.0: ; GISEL-NEXT: orr v0.16b, v0.16b, v1.16b -; GISEL-NEXT: mov d1, v0.d[1] -; GISEL-NEXT: fmov x8, d0 -; GISEL-NEXT: fmov x9, d1 -; GISEL-NEXT: orr x0, x8, x9 +; GISEL-NEXT: mov x8, v0.d[1] +; GISEL-NEXT: fmov x9, d0 +; GISEL-NEXT: orr x0, x9, x8 ; GISEL-NEXT: ret %or_result = call i64 @llvm.vector.reduce.or.v4i64(<4 x i64> %a) ret i64 %or_result diff --git a/llvm/test/CodeGen/AArch64/reduce-xor.ll b/llvm/test/CodeGen/AArch64/reduce-xor.ll index b8ca99e003b6..9a00172f9476 100644 --- a/llvm/test/CodeGen/AArch64/reduce-xor.ll +++ b/llvm/test/CodeGen/AArch64/reduce-xor.ll @@ -27,10 +27,9 @@ define i1 @test_redxor_v2i1(<2 x i1> %a) { ; GISEL-LABEL: test_redxor_v2i1: ; GISEL: // %bb.0: ; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: eor w8, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: eor w8, w9, w8 ; GISEL-NEXT: and w0, w8, #0x1 ; GISEL-NEXT: ret %or_result = call i1 @llvm.vector.reduce.xor.v2i1(<2 x i1> %a) @@ -448,10 +447,9 @@ define i32 @test_redxor_v2i32(<2 x i32> %a) { ; GISEL-LABEL: test_redxor_v2i32: ; GISEL: // %bb.0: ; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: eor w0, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: eor w0, w9, w8 ; GISEL-NEXT: ret %xor_result = call i32 @llvm.vector.reduce.xor.v2i32(<2 x i32> %a) ret i32 %xor_result @@ -471,10 +469,9 @@ define i32 @test_redxor_v4i32(<4 x i32> %a) { ; GISEL: // %bb.0: ; GISEL-NEXT: mov d1, v0.d[1] ; GISEL-NEXT: eor v0.8b, v0.8b, v1.8b -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: eor w0, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: eor w0, w9, w8 ; GISEL-NEXT: ret %xor_result = call i32 @llvm.vector.reduce.xor.v4i32(<4 x i32> %a) ret i32 %xor_result @@ -496,10 +493,9 @@ define i32 @test_redxor_v8i32(<8 x i32> %a) { ; GISEL-NEXT: eor v0.16b, v0.16b, v1.16b ; GISEL-NEXT: mov d1, v0.d[1] ; GISEL-NEXT: eor v0.8b, v0.8b, v1.8b -; GISEL-NEXT: mov s1, v0.s[1] -; GISEL-NEXT: fmov w8, s0 -; GISEL-NEXT: fmov w9, s1 -; GISEL-NEXT: eor w0, w8, w9 +; GISEL-NEXT: mov w8, v0.s[1] +; GISEL-NEXT: fmov w9, s0 +; GISEL-NEXT: eor w0, w9, w8 ; GISEL-NEXT: ret %xor_result = call i32 @llvm.vector.reduce.xor.v8i32(<8 x i32> %a) ret i32 %xor_result @@ -515,10 +511,9 @@ define i64 @test_redxor_v2i64(<2 x i64> %a) { ; ; GISEL-LABEL: test_redxor_v2i64: ; GISEL: // %bb.0: -; GISEL-NEXT: mov d1, v0.d[1] -; GISEL-NEXT: fmov x8, d0 -; GISEL-NEXT: fmov x9, d1 -; GISEL-NEXT: eor x0, x8, x9 +; GISEL-NEXT: mov x8, v0.d[1] +; GISEL-NEXT: fmov x9, d0 +; GISEL-NEXT: eor x0, x9, x8 ; GISEL-NEXT: ret %xor_result = call i64 @llvm.vector.reduce.xor.v2i64(<2 x i64> %a) ret i64 %xor_result @@ -536,10 +531,9 @@ define i64 @test_redxor_v4i64(<4 x i64> %a) { ; GISEL-LABEL: test_redxor_v4i64: ; GISEL: // %bb.0: ; GISEL-NEXT: eor v0.16b, v0.16b, v1.16b -; GISEL-NEXT: mov d1, v0.d[1] -; GISEL-NEXT: fmov x8, d0 -; GISEL-NEXT: fmov x9, d1 -; GISEL-NEXT: eor x0, x8, x9 +; GISEL-NEXT: mov x8, v0.d[1] +; GISEL-NEXT: fmov x9, d0 +; GISEL-NEXT: eor x0, x9, x8 ; GISEL-NEXT: ret %xor_result = call i64 @llvm.vector.reduce.xor.v4i64(<4 x i64> %a) ret i64 %xor_result -- GitLab From 31c903890a905d203de3303eaaa63063754ffbca Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 16 May 2024 11:53:11 +0900 Subject: [PATCH 446/578] [SeparateConstOffsetFromGEP] Add additional inbounds preservation tests (NFC) Adding these for NVPTX because for AMDGPU the problematic -1 case does not get reordered in the first place. --- .../NVPTX/lower-gep-reorder.ll | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/lower-gep-reorder.ll b/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/lower-gep-reorder.ll index 43dda1ae1517..ec1cbb9e61c0 100644 --- a/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/lower-gep-reorder.ll +++ b/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/lower-gep-reorder.ll @@ -63,3 +63,44 @@ end: call void asm sideeffect "; use $0", "v"(ptr %idx3) ret void } + +define void @inboundsPossiblyNegative1(ptr %in.ptr, i64 %in.idx1) { +; CHECK-LABEL: define void @inboundsPossiblyNegative1( +; CHECK-SAME: ptr [[IN_PTR:%.*]], i64 [[IN_IDX1:%.*]]) { +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr <2 x i8>, ptr [[IN_PTR]], i64 [[IN_IDX1]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <2 x i8>, ptr [[TMP0]], i64 1 +; CHECK-NEXT: ret void +; + %const1 = getelementptr inbounds <2 x i8>, ptr %in.ptr, i64 1 + %idx1 = getelementptr inbounds <2 x i8>, ptr %const1, i64 %in.idx1 + ret void +} + +define void @inboundsPossiblyNegative2(ptr %in.ptr, i64 %in.idx1) { +; CHECK-LABEL: define void @inboundsPossiblyNegative2( +; CHECK-SAME: ptr [[IN_PTR:%.*]], i64 [[IN_IDX1:%.*]]) { +; CHECK-NEXT: [[IN_IDX1_NNEG:%.*]] = and i64 [[IN_IDX1]], 9223372036854775807 +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <2 x i8>, ptr [[IN_PTR]], i64 [[IN_IDX1_NNEG]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <2 x i8>, ptr [[TMP0]], i64 -1 +; CHECK-NEXT: ret void +; + %in.idx1.nneg = and i64 %in.idx1, 9223372036854775807 + %const1 = getelementptr inbounds <2 x i8>, ptr %in.ptr, i64 -1 + %idx1 = getelementptr inbounds <2 x i8>, ptr %const1, i64 %in.idx1.nneg + ret void +} + +define void @inboundsNonNegative(ptr %in.ptr, i64 %in.idx1) { +; CHECK-LABEL: define void @inboundsNonNegative( +; CHECK-SAME: ptr [[IN_PTR:%.*]], i64 [[IN_IDX1:%.*]]) { +; CHECK-NEXT: [[IDXPROM:%.*]] = and i64 [[IN_IDX1]], 9223372036854775807 +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <2 x i8>, ptr [[IN_PTR]], i64 [[IDXPROM]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <2 x i8>, ptr [[TMP0]], i64 1 +; CHECK-NEXT: ret void +; + %in.idx1.nneg = and i64 %in.idx1, 9223372036854775807 + %const1 = getelementptr inbounds <2 x i8>, ptr %in.ptr, i64 1 + %idx1 = getelementptr inbounds <2 x i8>, ptr %const1, i64 %in.idx1.nneg + ret void +} + -- GitLab From b4d1a606c7492d827aff6ff0c1c109adff1253b9 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 16 May 2024 11:54:38 +0900 Subject: [PATCH 447/578] [SeparateConstOffsetFromGEP] Check correct index for non-negativity We were checking the index of GEP twice, instead of checking both GEP and PtrGEP. --- llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp | 2 +- .../SeparateConstOffsetFromGEP/NVPTX/lower-gep-reorder.ll | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp index 1a9eaf28f6e4..7ac1f43b7b6a 100644 --- a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp +++ b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp @@ -1001,7 +1001,7 @@ bool SeparateConstOffsetFromGEP::reorderGEP(GetElementPtrInst *GEP, auto KnownGEPIdx = computeKnownBits(GEPIdx->get(), *DL); IsChainInBounds &= KnownGEPIdx.isNonNegative(); if (IsChainInBounds) { - auto PtrGEPIdx = GEP->indices().begin(); + auto PtrGEPIdx = PtrGEP->indices().begin(); auto KnownPtrGEPIdx = computeKnownBits(PtrGEPIdx->get(), *DL); IsChainInBounds &= KnownPtrGEPIdx.isNonNegative(); } diff --git a/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/lower-gep-reorder.ll b/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/lower-gep-reorder.ll index ec1cbb9e61c0..23b4a4f788ae 100644 --- a/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/lower-gep-reorder.ll +++ b/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/lower-gep-reorder.ll @@ -80,8 +80,8 @@ define void @inboundsPossiblyNegative2(ptr %in.ptr, i64 %in.idx1) { ; CHECK-LABEL: define void @inboundsPossiblyNegative2( ; CHECK-SAME: ptr [[IN_PTR:%.*]], i64 [[IN_IDX1:%.*]]) { ; CHECK-NEXT: [[IN_IDX1_NNEG:%.*]] = and i64 [[IN_IDX1]], 9223372036854775807 -; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <2 x i8>, ptr [[IN_PTR]], i64 [[IN_IDX1_NNEG]] -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <2 x i8>, ptr [[TMP0]], i64 -1 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <2 x i8>, ptr [[IN_PTR]], i64 [[IN_IDX1_NNEG]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr <2 x i8>, ptr [[TMP1]], i64 -1 ; CHECK-NEXT: ret void ; %in.idx1.nneg = and i64 %in.idx1, 9223372036854775807 -- GitLab From 83e61d03deaaa8f4dd8395cfa753af7b38f74b24 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 16 May 2024 12:20:18 +0900 Subject: [PATCH 448/578] [SeparateConstOffsetFromGEP] Add tests for multiple indices (NFC) --- .../AMDGPU/reorder-gep.ll | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/llvm/test/Transforms/SeparateConstOffsetFromGEP/AMDGPU/reorder-gep.ll b/llvm/test/Transforms/SeparateConstOffsetFromGEP/AMDGPU/reorder-gep.ll index b4119f0b50b4..a7ca5b93c361 100644 --- a/llvm/test/Transforms/SeparateConstOffsetFromGEP/AMDGPU/reorder-gep.ll +++ b/llvm/test/Transforms/SeparateConstOffsetFromGEP/AMDGPU/reorder-gep.ll @@ -284,3 +284,29 @@ entry: %idx3 = getelementptr i8, ptr addrspace(3) %const3, i64 %in.idx2 ret void } + +define void @multiple_index_maybe_neg(ptr %in.ptr, i64 %in.idx1) { +; CHECK-LABEL: define void @multiple_index_maybe_neg( +; CHECK-SAME: ptr [[IN_PTR:%.*]], i64 [[IN_IDX1:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[CONST1:%.*]] = getelementptr inbounds [2 x <2 x i8>], ptr [[IN_PTR]], i64 0, i64 1 +; CHECK-NEXT: [[IDX1:%.*]] = getelementptr inbounds [2 x <2 x i8>], ptr [[CONST1]], i64 0, i64 [[IN_IDX1]] +; CHECK-NEXT: ret void +; + %const1 = getelementptr inbounds [2 x <2 x i8>], ptr %in.ptr, i64 0, i64 1 + %idx1 = getelementptr inbounds [2 x <2 x i8>], ptr %const1, i64 0, i64 %in.idx1 + ret void +} + +define void @multiple_index_nonneg(ptr %in.ptr, i64 %in.idx1) { +; CHECK-LABEL: define void @multiple_index_nonneg( +; CHECK-SAME: ptr [[IN_PTR:%.*]], i64 [[IN_IDX1:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[IN_IDX1_NNEG:%.*]] = and i64 [[IN_IDX1]], 9223372036854775807 +; CHECK-NEXT: [[CONST1:%.*]] = getelementptr inbounds [2 x <2 x i8>], ptr [[IN_PTR]], i64 0, i64 1 +; CHECK-NEXT: [[IDX1:%.*]] = getelementptr inbounds [2 x <2 x i8>], ptr [[CONST1]], i64 0, i64 [[IN_IDX1_NNEG]] +; CHECK-NEXT: ret void +; + %in.idx1.nneg = and i64 %in.idx1, 9223372036854775807 + %const1 = getelementptr inbounds [2 x <2 x i8>], ptr %in.ptr, i64 0, i64 1 + %idx1 = getelementptr inbounds [2 x <2 x i8>], ptr %const1, i64 0, i64 %in.idx1.nneg + ret void +} -- GitLab From e91ea1b5d88805ebf7657da57ca6a7577374e4ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jim=20M=2E=20R=2E=20Teichgr=C3=A4ber?= Date: Thu, 16 May 2024 05:38:15 +0200 Subject: [PATCH 449/578] [Clang] Disallow VLA type compound literals (#91891) C99-C23 6.5.2.5 says: The type name shall specify an object type or an array of unknown size, but not a variable length array type. Fixes #89835. --- clang/docs/ReleaseNotes.rst | 3 +++ .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaExpr.cpp | 19 +++++++++++++------ clang/test/C/C2x/n2900_n3011.c | 8 +++++++- clang/test/C/C2x/n2900_n3011_2.c | 16 ---------------- clang/test/Sema/compound-literal.c | 13 ++++++++++++- 6 files changed, 37 insertions(+), 24 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 11812c355f8d..be4cded27632 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -570,6 +570,9 @@ Bug Fixes in This Version - Clang will no longer emit a duplicate -Wunused-value warning for an expression `(A, B)` which evaluates to glvalue `B` that can be converted to non ODR-use. (#GH45783) +- Clang now correctly disallows VLA type compound literals, e.g. ``(int[size]){}``, + as the C standard mandates. (#GH89835) + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6100fba51005..e648b503ac03 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3371,6 +3371,8 @@ def err_field_with_address_space : Error< "field may not be qualified with an address space">; def err_compound_literal_with_address_space : Error< "compound literal in function scope may not be qualified with an address space">; +def err_compound_literal_with_vla_type : Error< + "compound literal cannot be of variable-length array type">; def err_address_space_mismatch_templ_inst : Error< "conflicting address space qualifiers are provided between types %0 and %1">; def err_attr_objc_ownership_redundant : Error< diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 50569c1cd536..cc507524e2fc 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7130,12 +7130,19 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, // init a VLA in C++ in all cases (such as with non-trivial constructors). // FIXME: should we allow this construct in C++ when it makes sense to do // so? - std::optional NumInits; - if (const auto *ILE = dyn_cast(LiteralExpr)) - NumInits = ILE->getNumInits(); - if ((LangOpts.CPlusPlus || NumInits.value_or(0)) && - !tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc, - diag::err_variable_object_no_init)) + // + // But: C99-C23 6.5.2.5 Compound literals constraint 1: The type name + // shall specify an object type or an array of unknown size, but not a + // variable length array type. This seems odd, as it allows int a[size] = + // {}; but forbids int a[size] = (int[size]){}; As this is what the + // standard says, this is what's implemented here for C (except for the + // extension that permits constant foldable size arrays) + + auto diagID = LangOpts.CPlusPlus + ? diag::err_variable_object_no_init + : diag::err_compound_literal_with_vla_type; + if (!tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc, + diagID)) return ExprError(); } } else if (!literalType->isDependentType() && diff --git a/clang/test/C/C2x/n2900_n3011.c b/clang/test/C/C2x/n2900_n3011.c index 4350aa140691..82a3b16c8acd 100644 --- a/clang/test/C/C2x/n2900_n3011.c +++ b/clang/test/C/C2x/n2900_n3011.c @@ -27,8 +27,14 @@ void test(void) { compat-warning {{use of an empty initializer is incompatible with C standards before C23}} int vla[i] = {}; // compat-warning {{use of an empty initializer is incompatible with C standards before C23}} \ pedantic-warning {{use of an empty initializer is a C23 extension}} + // C99 6.5.2.5 Compound literals constraint 1: The type name shall specify an + // object type or an array of unknown size, but not a variable length array + // type. int *compound_literal_vla = (int[i]){}; // compat-warning {{use of an empty initializer is incompatible with C standards before C23}} \ - pedantic-warning {{use of an empty initializer is a C23 extension}} + pedantic-warning {{use of an empty initializer is a C23 extension}}\ + compat-error {{compound literal cannot be of variable-length array type}} \ + pedantic-error {{compound literal cannot be of variable-length array type}}\ + struct T { int i; diff --git a/clang/test/C/C2x/n2900_n3011_2.c b/clang/test/C/C2x/n2900_n3011_2.c index eb15fbf905c8..ab659d636d15 100644 --- a/clang/test/C/C2x/n2900_n3011_2.c +++ b/clang/test/C/C2x/n2900_n3011_2.c @@ -76,22 +76,6 @@ void test_zero_size_vla() { // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}} %[[VLA]], i8 0, i64 %[[BYTES_TO_COPY]], i1 false) } -void test_compound_literal_vla() { - int num_elts = 12; - int *compound_literal_vla = (int[num_elts]){}; - // CHECK: define {{.*}} void @test_compound_literal_vla - // CHECK-NEXT: entry: - // CHECK-NEXT: %[[NUM_ELTS_PTR:.+]] = alloca i32 - // CHECK-NEXT: %[[COMP_LIT_VLA:.+]] = alloca ptr - // CHECK-NEXT: %[[COMP_LIT:.+]] = alloca i32 - // CHECK-NEXT: store i32 12, ptr %[[NUM_ELTS_PTR]] - // CHECK-NEXT: %[[NUM_ELTS:.+]] = load i32, ptr %[[NUM_ELTS_PTR]] - // CHECK-NEXT: %[[NUM_ELTS_EXT:.+]] = zext i32 %[[NUM_ELTS]] to i64 - // CHECK-NEXT: %[[BYTES_TO_COPY:.+]] = mul nuw i64 %[[NUM_ELTS_EXT]], 4 - // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}} %[[COMP_LIT]], i8 0, i64 %[[BYTES_TO_COPY]], i1 false) - // CHECK-NEXT: store ptr %[[COMP_LIT]], ptr %[[COMP_LIT_VLA]] -} - void test_nested_structs() { struct T t1 = { 1, {} }; struct T t2 = { 1, { 2, {} } }; diff --git a/clang/test/Sema/compound-literal.c b/clang/test/Sema/compound-literal.c index a64b6f9e5dfa..3ed53d670d38 100644 --- a/clang/test/Sema/compound-literal.c +++ b/clang/test/Sema/compound-literal.c @@ -29,7 +29,7 @@ int main(int argc, char **argv) { struct Incomplete; // expected-note{{forward declaration of 'struct Incomplete'}} struct Incomplete* I1 = &(struct Incomplete){1, 2, 3}; // expected-error {{variable has incomplete type}} void IncompleteFunc(unsigned x) { - struct Incomplete* I2 = (struct foo[x]){1, 2, 3}; // expected-error {{variable-sized object may not be initialized}} + struct Incomplete* I2 = (struct foo[x]){1, 2, 3}; // expected-error {{compound literal cannot be of variable-length array type}} (void){1,2,3}; // expected-error {{variable has incomplete type}} (void(void)) { 0 }; // expected-error{{illegal initializer type 'void (void)'}} } @@ -42,3 +42,14 @@ int (^block)(int) = ^(int i) { int *array = (int[]) {i, i + 2, i + 4}; return array[i]; }; + +// C99 6.5.2.5 Compound literals constraint 1: The type name shall specify an object type or an array of unknown size, but not a variable length array type. +// So check that VLA type compound literals are rejected (see https://github.com/llvm/llvm-project/issues/89835). +void vla(int n) { + int size = 5; + (void)(int[size]){}; // expected-warning {{use of an empty initializer is a C23 extension}} + // expected-error@-1 {{compound literal cannot be of variable-length array type}} + (void)(int[size]){1}; // expected-error {{compound literal cannot be of variable-length array type}} + (void)(int[size]){1,2,3}; // expected-error {{compound literal cannot be of variable-length array type}} + (void)(int[size]){1,2,3,4,5}; // expected-error {{compound literal cannot be of variable-length array type}} +} -- GitLab From 90fbc5bbcdc7d35d57157e4cc0459470d473f2ae Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 15 May 2024 20:38:55 -0700 Subject: [PATCH 450/578] [MCAsmParser] Simplify. NFC --- llvm/lib/MC/MCParser/AsmParser.cpp | 22 ++++++---------------- llvm/lib/MC/MCParser/MCAsmParser.cpp | 1 - 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 46c1caa940c5..009465d11d78 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -833,11 +833,8 @@ AsmParser::~AsmParser() { void AsmParser::printMacroInstantiations() { // Print the active macro instantiation stack. - for (std::vector::const_reverse_iterator - it = ActiveMacros.rbegin(), - ie = ActiveMacros.rend(); - it != ie; ++it) - printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note, + for (MacroInstantiation *M : reverse(ActiveMacros)) + printMessage(M->InstantiationLoc, SourceMgr::DK_Note, "while in macro instantiation"); } @@ -1510,9 +1507,7 @@ bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) { // As a special case, we support 'a op b @ modifier' by rewriting the // expression to include the modifier. This is inefficient, but in general we // expect users to use 'a@modifier op b'. - if (Lexer.getKind() == AsmToken::At) { - Lex(); - + if (parseOptionalToken(AsmToken::At)) { if (Lexer.isNot(AsmToken::Identifier)) return TokError("unexpected symbol modifier following '@'"); @@ -2708,10 +2703,8 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) { if (Lexer.is(AsmToken::Comma)) break; - if (Lexer.is(AsmToken::Space)) { + if (parseOptionalToken(AsmToken::Space)) SpaceEaten = true; - Lexer.Lex(); // Eat spaces - } // Spaces can delimit parameters, but could also be part an expression. // If the token after a space is an operator, add the token and the next @@ -2722,9 +2715,7 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) { Lexer.Lex(); // Whitespace after an operator can be ignored. - if (Lexer.is(AsmToken::Space)) - Lexer.Lex(); - + parseOptionalToken(AsmToken::Space); continue; } } @@ -2865,8 +2856,7 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M, return Failure; } - if (Lexer.is(AsmToken::Comma)) - Lex(); + parseOptionalToken(AsmToken::Comma); } return TokError("too many positional arguments"); diff --git a/llvm/lib/MC/MCParser/MCAsmParser.cpp b/llvm/lib/MC/MCParser/MCAsmParser.cpp index bfeba3108cb4..236585fc9082 100644 --- a/llvm/lib/MC/MCParser/MCAsmParser.cpp +++ b/llvm/lib/MC/MCParser/MCAsmParser.cpp @@ -99,7 +99,6 @@ bool MCAsmParser::TokError(const Twine &Msg, SMRange Range) { } bool MCAsmParser::Error(SMLoc L, const Twine &Msg, SMRange Range) { - MCPendingError PErr; PErr.Loc = L; Msg.toVector(PErr.Msg); -- GitLab From ce961c5607dd5c2d181117938720e410b406a49f Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Thu, 16 May 2024 07:44:08 +0400 Subject: [PATCH 451/578] [lldb] Fixed the TestFdLeak test (#92273) Use `os.devnull` instead of `/dev/null`. --- lldb/test/API/functionalities/avoids-fd-leak/TestFdLeak.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/test/API/functionalities/avoids-fd-leak/TestFdLeak.py b/lldb/test/API/functionalities/avoids-fd-leak/TestFdLeak.py index e4f5cd3a03f8..c840d38df5c7 100644 --- a/lldb/test/API/functionalities/avoids-fd-leak/TestFdLeak.py +++ b/lldb/test/API/functionalities/avoids-fd-leak/TestFdLeak.py @@ -26,7 +26,7 @@ class AvoidsFdLeakTestCase(TestBase): @skipIfTargetAndroid() # Android have some other file descriptors open by the shell @skipIfDarwinEmbedded # # debugserver on ios has an extra fd open on launch def test_fd_leak_log(self): - self.do_test(["log enable -f '/dev/null' lldb commands"]) + self.do_test(["log enable -f '{}' lldb commands".format(os.devnull)]) def do_test(self, commands): self.build() -- GitLab From b11a6607cb6522c58dfbd5f54239e7daa281368e Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Wed, 15 May 2024 21:01:57 -0700 Subject: [PATCH 452/578] [clang-format][NFC] Reformat with 18.1.5 --- clang/lib/Format/UnwrappedLineParser.cpp | 3 ++- clang/tools/clang-format/ClangFormat.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 4f1c2c5114e9..2236a49e4b76 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -47,7 +47,8 @@ void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line, OS << Prefix; NewLine = false; } - OS << I->Tok->Tok.getName() << "[" << "T=" << (unsigned)I->Tok->getType() + OS << I->Tok->Tok.getName() << "[" + << "T=" << (unsigned)I->Tok->getType() << ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText << "\"] "; for (SmallVectorImpl::const_iterator diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 01f7c6047726..3fa5f81a3576 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -336,7 +336,8 @@ static void outputReplacementXML(StringRef Text) { static void outputReplacementsXML(const Replacements &Replaces) { for (const auto &R : Replaces) { - outs() << ""; outputReplacementXML(R.getReplacementText()); outs() << "\n"; -- GitLab From 526553b25131a69d9d6426e17c7b69c2ba27144f Mon Sep 17 00:00:00 2001 From: Yusuke MINATO Date: Thu, 16 May 2024 13:16:07 +0900 Subject: [PATCH 453/578] [flang] Add nsw flag to do-variable increment with a new option (#91579) This patch adds nsw flag to the increment of do-variables when a new option is enabled. NOTE 11.10 in the Fortran 2018 standard says they never overflow. See also the discussion in #74709 and the following discourse post. https://discourse.llvm.org/t/rfc-add-nsw-flags-to-arithmetic-integer-operations-using-the-option-fno-wrapv/77584/5 --- clang/include/clang/Driver/Options.td | 4 + clang/lib/Driver/ToolChains/Flang.cpp | 1 + flang/include/flang/Lower/LoweringOptions.def | 4 + .../flang/Optimizer/Transforms/Passes.h | 4 +- .../flang/Optimizer/Transforms/Passes.td | 5 +- flang/include/flang/Tools/CLOptions.inc | 13 +- flang/include/flang/Tools/CrossToolHelpers.h | 1 + flang/lib/Frontend/CompilerInvocation.cpp | 6 + flang/lib/Frontend/FrontendActions.cpp | 3 + flang/lib/Lower/Bridge.cpp | 12 +- flang/lib/Lower/IO.cpp | 9 +- .../Transforms/ControlFlowConverter.cpp | 44 +++- flang/test/Driver/frontend-forwarding.f90 | 2 + flang/test/Fir/loop01.fir | 211 ++++++++++++++++++ flang/test/Lower/array-substring.f90 | 40 ++++ flang/test/Lower/do_loop.f90 | 42 ++++ flang/test/Lower/do_loop_unstructured.f90 | 189 +++++++++++++++- flang/test/Lower/infinite_loop.f90 | 34 +++ flang/test/Lower/io-implied-do-fixes.f90 | 51 ++++- flang/tools/bbc/bbc.cpp | 7 + 20 files changed, 659 insertions(+), 23 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index e579f1a0a366..7bb781667e92 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6550,6 +6550,10 @@ def flang_deprecated_no_hlfir : Flag<["-"], "flang-deprecated-no-hlfir">, Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>, HelpText<"Do not use HLFIR lowering (deprecated)">; +def flang_experimental_integer_overflow : Flag<["-"], "flang-experimental-integer-overflow">, + Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>, + HelpText<"Add nsw flag to internal operations such as do-variable increment (experimental)">; + //===----------------------------------------------------------------------===// // FLangOption + CoreOption + NoXarchOption //===----------------------------------------------------------------------===// diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index d275528b6905..42ca060186fd 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -139,6 +139,7 @@ void Flang::addCodegenOptions(const ArgList &Args, Args.addAllArgs(CmdArgs, {options::OPT_flang_experimental_hlfir, options::OPT_flang_deprecated_no_hlfir, + options::OPT_flang_experimental_integer_overflow, options::OPT_fno_ppc_native_vec_elem_order, options::OPT_fppc_native_vec_elem_order}); } diff --git a/flang/include/flang/Lower/LoweringOptions.def b/flang/include/flang/Lower/LoweringOptions.def index be080a4d29d7..7594a57a2629 100644 --- a/flang/include/flang/Lower/LoweringOptions.def +++ b/flang/include/flang/Lower/LoweringOptions.def @@ -34,5 +34,9 @@ ENUM_LOWERINGOPT(NoPPCNativeVecElemOrder, unsigned, 1, 0) /// On by default. ENUM_LOWERINGOPT(Underscoring, unsigned, 1, 1) +/// If true, add nsw flags to loop variable increments. +/// Off by default. +ENUM_LOWERINGOPT(NSWOnLoopVarInc, unsigned, 1, 0) + #undef LOWERINGOPT #undef ENUM_LOWERINGOPT diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h index ae1d72a3526b..25fe61488f4f 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.h +++ b/flang/include/flang/Optimizer/Transforms/Passes.h @@ -54,6 +54,7 @@ namespace fir { std::unique_ptr createAffineDemotionPass(); std::unique_ptr createArrayValueCopyPass(fir::ArrayValueCopyOptions options = {}); +std::unique_ptr createCFGConversionPassWithNSW(); std::unique_ptr createExternalNameConversionPass(); std::unique_ptr createExternalNameConversionPass(bool appendUnderscore); @@ -89,7 +90,8 @@ createFunctionAttrPass(FunctionAttrTypes &functionAttr, bool noInfsFPMath, bool noSignedZerosFPMath, bool unsafeFPMath); void populateCfgConversionRewrites(mlir::RewritePatternSet &patterns, - bool forceLoopToExecuteOnce = false); + bool forceLoopToExecuteOnce = false, + bool setNSW = false); // declarative passes #define GEN_PASS_REGISTRATION diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index e22c1b5f338b..622c9465754c 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -151,7 +151,10 @@ def CFGConversion : Pass<"cfg-conversion"> { let options = [ Option<"forceLoopToExecuteOnce", "always-execute-loop-body", "bool", /*default=*/"false", - "force the body of a loop to execute at least once"> + "force the body of a loop to execute at least once">, + Option<"setNSW", "set-nsw", "bool", + /*default=*/"false", + "set nsw on loop variable increment"> ]; } diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc index cc3431d5b71d..1817dd6ca4a7 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -148,9 +148,14 @@ static void addCanonicalizerPassWithoutRegionSimplification( pm.addPass(mlir::createCanonicalizerPass(config)); } -inline void addCfgConversionPass(mlir::PassManager &pm) { - addNestedPassToAllTopLevelOperationsConditionally( - pm, disableCfgConversion, fir::createCFGConversion); +inline void addCfgConversionPass( + mlir::PassManager &pm, const MLIRToLLVMPassPipelineConfig &config) { + if (config.NSWOnLoopVarInc) + addNestedPassToAllTopLevelOperationsConditionally( + pm, disableCfgConversion, fir::createCFGConversionPassWithNSW); + else + addNestedPassToAllTopLevelOperationsConditionally( + pm, disableCfgConversion, fir::createCFGConversion); } inline void addAVC( @@ -290,7 +295,7 @@ inline void createDefaultFIROptimizerPassPipeline( pm.addPass(fir::createAliasTagsPass()); // convert control flow to CFG form - fir::addCfgConversionPass(pm); + fir::addCfgConversionPass(pm, pc); pm.addPass(mlir::createConvertSCFToCFPass()); pm.addPass(mlir::createCanonicalizerPass(config)); diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h index f79520707714..77b68fc6187f 100644 --- a/flang/include/flang/Tools/CrossToolHelpers.h +++ b/flang/include/flang/Tools/CrossToolHelpers.h @@ -122,6 +122,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks { bool NoSignedZerosFPMath = false; ///< Set no-signed-zeros-fp-math attribute for functions. bool UnsafeFPMath = false; ///< Set unsafe-fp-math attribute for functions. + bool NSWOnLoopVarInc = false; ///< Add nsw flag to loop variable increments. }; struct OffloadModuleOpts { diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index e8a8c90045d9..50c3e8b0113b 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -1206,6 +1206,12 @@ bool CompilerInvocation::createFromArgs( invoc.loweringOpts.setNoPPCNativeVecElemOrder(true); } + // -flang-experimental-integer-overflow + if (args.hasArg( + clang::driver::options::OPT_flang_experimental_integer_overflow)) { + invoc.loweringOpts.setNSWOnLoopVarInc(true); + } + // Preserve all the remark options requested, i.e. -Rpass, -Rpass-missed or // -Rpass-analysis. This will be used later when processing and outputting the // remarks generated by LLVM in ExecuteCompilerInvocation.cpp. diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 4341c104a69d..b1b6391f1439 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -818,6 +818,9 @@ void CodeGenAction::generateLLVMIR() { config.VScaleMax = vsr->second; } + if (ci.getInvocation().getLoweringOpts().getNSWOnLoopVarInc()) + config.NSWOnLoopVarInc = true; + // Create the pass pipeline fir::createMLIRToLLVMPassPipeline(pm, config, getCurrentFile()); (void)mlir::applyPassManagerCLOptions(pm); diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 596049fcfc92..afbc1122de86 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -2007,6 +2007,11 @@ private: void genFIRIncrementLoopEnd(IncrementLoopNestInfo &incrementLoopNestInfo) { assert(!incrementLoopNestInfo.empty() && "empty loop nest"); mlir::Location loc = toLocation(); + mlir::arith::IntegerOverflowFlags flags{}; + if (getLoweringOptions().getNSWOnLoopVarInc()) + flags = bitEnumSet(flags, mlir::arith::IntegerOverflowFlags::nsw); + auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get( + builder->getContext(), flags); for (auto it = incrementLoopNestInfo.rbegin(), rend = incrementLoopNestInfo.rend(); it != rend; ++it) { @@ -2021,7 +2026,8 @@ private: builder->setInsertionPointToEnd(info.doLoop.getBody()); llvm::SmallVector results; results.push_back(builder->create( - loc, info.doLoop.getInductionVar(), info.doLoop.getStep())); + loc, info.doLoop.getInductionVar(), info.doLoop.getStep(), + iofAttr)); // Step loopVariable to help optimizations such as vectorization. // Induction variable elimination will clean up as necessary. mlir::Value step = builder->createConvert( @@ -2029,7 +2035,7 @@ private: mlir::Value loopVar = builder->create(loc, info.loopVariable); results.push_back( - builder->create(loc, loopVar, step)); + builder->create(loc, loopVar, step, iofAttr)); builder->create(loc, results); builder->setInsertionPointAfter(info.doLoop); // The loop control variable may be used after the loop. @@ -2054,7 +2060,7 @@ private: if (info.hasRealControl) value = builder->create(loc, value, step); else - value = builder->create(loc, value, step); + value = builder->create(loc, value, step, iofAttr); builder->create(loc, value, info.loopVariable); genBranch(info.headerBlock); diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp index ed0afad9197d..97ef991cb399 100644 --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -928,6 +928,11 @@ static void genIoLoop(Fortran::lower::AbstractConverter &converter, Fortran::lower::StatementContext stmtCtx; fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::Location loc = converter.getCurrentLocation(); + mlir::arith::IntegerOverflowFlags flags{}; + if (converter.getLoweringOptions().getNSWOnLoopVarInc()) + flags = bitEnumSet(flags, mlir::arith::IntegerOverflowFlags::nsw); + auto iofAttr = + mlir::arith::IntegerOverflowFlagsAttr::get(builder.getContext(), flags); makeNextConditionalOn(builder, loc, checkResult, ok, inLoop); const auto &itemList = std::get<0>(ioImpliedDo.t); const auto &control = std::get<1>(ioImpliedDo.t); @@ -965,7 +970,7 @@ static void genIoLoop(Fortran::lower::AbstractConverter &converter, genItemList(ioImpliedDo); builder.setInsertionPointToEnd(doLoopOp.getBody()); mlir::Value result = builder.create( - loc, doLoopOp.getInductionVar(), doLoopOp.getStep()); + loc, doLoopOp.getInductionVar(), doLoopOp.getStep(), iofAttr); builder.create(loc, result); builder.setInsertionPointAfter(doLoopOp); // The loop control variable may be used after the loop. @@ -1007,7 +1012,7 @@ static void genIoLoop(Fortran::lower::AbstractConverter &converter, mlir::OpResult iterateResult = builder.getBlock()->back().getResult(0); mlir::Value inductionResult0 = iterWhileOp.getInductionVar(); auto inductionResult1 = builder.create( - loc, inductionResult0, iterWhileOp.getStep()); + loc, inductionResult0, iterWhileOp.getStep(), iofAttr); auto inductionResult = builder.create( loc, iterateResult, inductionResult1, inductionResult0); llvm::SmallVector results = {inductionResult, iterateResult}; diff --git a/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp b/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp index a62f6cde0e09..a233e7fbdcd1 100644 --- a/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp +++ b/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp @@ -43,14 +43,19 @@ class CfgLoopConv : public mlir::OpRewritePattern { public: using OpRewritePattern::OpRewritePattern; - CfgLoopConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce) + CfgLoopConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce, bool setNSW) : mlir::OpRewritePattern(ctx), - forceLoopToExecuteOnce(forceLoopToExecuteOnce) {} + forceLoopToExecuteOnce(forceLoopToExecuteOnce), setNSW(setNSW) {} mlir::LogicalResult matchAndRewrite(DoLoopOp loop, mlir::PatternRewriter &rewriter) const override { auto loc = loop.getLoc(); + mlir::arith::IntegerOverflowFlags flags{}; + if (setNSW) + flags = bitEnumSet(flags, mlir::arith::IntegerOverflowFlags::nsw); + auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get( + rewriter.getContext(), flags); // Create the start and end blocks that will wrap the DoLoopOp with an // initalizer and an end point @@ -104,7 +109,7 @@ public: rewriter.setInsertionPointToEnd(lastBlock); auto iv = conditionalBlock->getArgument(0); mlir::Value steppedIndex = - rewriter.create(loc, iv, step); + rewriter.create(loc, iv, step, iofAttr); assert(steppedIndex && "must be a Value"); auto lastArg = conditionalBlock->getNumArguments() - 1; auto itersLeft = conditionalBlock->getArgument(lastArg); @@ -142,6 +147,7 @@ public: private: bool forceLoopToExecuteOnce; + bool setNSW; }; /// Convert `fir.if` to control-flow @@ -149,7 +155,7 @@ class CfgIfConv : public mlir::OpRewritePattern { public: using OpRewritePattern::OpRewritePattern; - CfgIfConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce) + CfgIfConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce, bool setNSW) : mlir::OpRewritePattern(ctx) {} mlir::LogicalResult @@ -214,13 +220,19 @@ class CfgIterWhileConv : public mlir::OpRewritePattern { public: using OpRewritePattern::OpRewritePattern; - CfgIterWhileConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce) - : mlir::OpRewritePattern(ctx) {} + CfgIterWhileConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce, + bool setNSW) + : mlir::OpRewritePattern(ctx), setNSW(setNSW) {} mlir::LogicalResult matchAndRewrite(fir::IterWhileOp whileOp, mlir::PatternRewriter &rewriter) const override { auto loc = whileOp.getLoc(); + mlir::arith::IntegerOverflowFlags flags{}; + if (setNSW) + flags = bitEnumSet(flags, mlir::arith::IntegerOverflowFlags::nsw); + auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get( + rewriter.getContext(), flags); // Start by splitting the block containing the 'fir.do_loop' into two parts. // The part before will get the init code, the part after will be the end @@ -248,7 +260,8 @@ public: auto *terminator = lastBodyBlock->getTerminator(); rewriter.setInsertionPointToEnd(lastBodyBlock); auto step = whileOp.getStep(); - mlir::Value stepped = rewriter.create(loc, iv, step); + mlir::Value stepped = + rewriter.create(loc, iv, step, iofAttr); assert(stepped && "must be a Value"); llvm::SmallVector loopCarried; @@ -305,6 +318,9 @@ public: rewriter.replaceOp(whileOp, args); return success(); } + +private: + bool setNSW; }; /// Convert FIR structured control flow ops to CFG ops. @@ -312,10 +328,13 @@ class CfgConversion : public fir::impl::CFGConversionBase { public: using CFGConversionBase::CFGConversionBase; + CfgConversion(bool setNSW) { this->setNSW = setNSW; } + void runOnOperation() override { auto *context = &this->getContext(); mlir::RewritePatternSet patterns(context); - fir::populateCfgConversionRewrites(patterns, this->forceLoopToExecuteOnce); + fir::populateCfgConversionRewrites(patterns, this->forceLoopToExecuteOnce, + this->setNSW); mlir::ConversionTarget target(*context); target.addLegalDialect( - patterns.getContext(), forceLoopToExecuteOnce); + patterns.getContext(), forceLoopToExecuteOnce, setNSW); +} + +std::unique_ptr fir::createCFGConversionPassWithNSW() { + return std::make_unique(true); } diff --git a/flang/test/Driver/frontend-forwarding.f90 b/flang/test/Driver/frontend-forwarding.f90 index eac9773ce25c..35adb47b5686 100644 --- a/flang/test/Driver/frontend-forwarding.f90 +++ b/flang/test/Driver/frontend-forwarding.f90 @@ -19,6 +19,7 @@ ! RUN: -fversion-loops-for-stride \ ! RUN: -flang-experimental-hlfir \ ! RUN: -flang-deprecated-no-hlfir \ +! RUN: -flang-experimental-integer-overflow \ ! RUN: -fno-ppc-native-vector-element-order \ ! RUN: -fppc-native-vector-element-order \ ! RUN: -mllvm -print-before-all \ @@ -50,6 +51,7 @@ ! CHECK: "-fversion-loops-for-stride" ! CHECK: "-flang-experimental-hlfir" ! CHECK: "-flang-deprecated-no-hlfir" +! CHECK: "-flang-experimental-integer-overflow" ! CHECK: "-fno-ppc-native-vector-element-order" ! CHECK: "-fppc-native-vector-element-order" ! CHECK: "-Rpass" diff --git a/flang/test/Fir/loop01.fir b/flang/test/Fir/loop01.fir index 72ca1c3989e4..c1cbb522c378 100644 --- a/flang/test/Fir/loop01.fir +++ b/flang/test/Fir/loop01.fir @@ -1,4 +1,5 @@ // RUN: fir-opt --split-input-file --cfg-conversion %s | FileCheck %s +// RUN: fir-opt --split-input-file --cfg-conversion="set-nsw=true" %s | FileCheck %s --check-prefix=NSW func.func @x(%lb : index, %ub : index, %step : index, %b : i1, %addr : !fir.ref) { fir.do_loop %iv = %lb to %ub step %step unordered { @@ -43,6 +44,34 @@ func.func private @f2() -> i1 // CHECK: } // CHECK: func private @f2() -> i1 +// NSW: func @x(%[[VAL_0:.*]]: index, %[[VAL_1:.*]]: index, %[[VAL_2:.*]]: index, %[[VAL_3:.*]]: i1, %[[VAL_4:.*]]: !fir.ref) { +// NSW: %[[VAL_5:.*]] = arith.subi %[[VAL_1]], %[[VAL_0]] : index +// NSW: %[[VAL_6:.*]] = arith.addi %[[VAL_5]], %[[VAL_2]] : index +// NSW: %[[VAL_7:.*]] = arith.divsi %[[VAL_6]], %[[VAL_2]] : index +// NSW: br ^bb1(%[[VAL_0]], %[[VAL_7]] : index, index) +// NSW: ^bb1(%[[VAL_8:.*]]: index, %[[VAL_9:.*]]: index): +// NSW: %[[VAL_10:.*]] = arith.constant 0 : index +// NSW: %[[VAL_11:.*]] = arith.cmpi sgt, %[[VAL_9]], %[[VAL_10]] : index +// NSW: cond_br %[[VAL_11]], ^bb2, ^bb6 +// NSW: ^bb2: +// NSW: cond_br %[[VAL_3]], ^bb3, ^bb4 +// NSW: ^bb3: +// NSW: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ref +// NSW: br ^bb5 +// NSW: ^bb4: +// NSW: %[[VAL_12:.*]] = arith.constant 0 : index +// NSW: fir.store %[[VAL_12]] to %[[VAL_4]] : !fir.ref +// NSW: br ^bb5 +// NSW: ^bb5: +// NSW: %[[VAL_13:.*]] = arith.addi %[[VAL_8]], %[[VAL_2]] overflow : index +// NSW: %[[VAL_14:.*]] = arith.constant 1 : index +// NSW: %[[VAL_15:.*]] = arith.subi %[[VAL_9]], %[[VAL_14]] : index +// NSW: br ^bb1(%[[VAL_13]], %[[VAL_15]] : index, index) +// NSW: ^bb6: +// NSW: return +// NSW: } +// NSW: func private @f2() -> i1 + // ----- func.func @x2(%lo : index, %up : index, %ok : i1) { @@ -79,6 +108,29 @@ func.func private @f3(i16) // CHECK: } // CHECK: func private @f3(i16) +// NSW: func @x2(%[[VAL_0:.*]]: index, %[[VAL_1:.*]]: index, %[[VAL_2:.*]]: i1) { +// NSW: %[[VAL_3:.*]] = arith.constant 1 : index +// NSW: br ^bb1(%[[VAL_0]], %[[VAL_2]] : index, i1) +// NSW: ^bb1(%[[VAL_4:.*]]: index, %[[VAL_5:.*]]: i1): +// NSW: %[[VAL_6:.*]] = arith.constant 0 : index +// NSW: %[[VAL_7:.*]] = arith.cmpi slt, %[[VAL_6]], %[[VAL_3]] : index +// NSW: %[[VAL_8:.*]] = arith.cmpi sle, %[[VAL_4]], %[[VAL_1]] : index +// NSW: %[[VAL_9:.*]] = arith.cmpi slt, %[[VAL_3]], %[[VAL_6]] : index +// NSW: %[[VAL_10:.*]] = arith.cmpi sle, %[[VAL_1]], %[[VAL_4]] : index +// NSW: %[[VAL_11:.*]] = arith.andi %[[VAL_7]], %[[VAL_8]] : i1 +// NSW: %[[VAL_12:.*]] = arith.andi %[[VAL_9]], %[[VAL_10]] : i1 +// NSW: %[[VAL_13:.*]] = arith.ori %[[VAL_11]], %[[VAL_12]] : i1 +// NSW: %[[VAL_14:.*]] = arith.andi %[[VAL_5]], %[[VAL_13]] : i1 +// NSW: cond_br %[[VAL_14]], ^bb2, ^bb3 +// NSW: ^bb2: +// NSW: %[[VAL_15:.*]] = fir.call @f2() : () -> i1 +// NSW: %[[VAL_16:.*]] = arith.addi %[[VAL_4]], %[[VAL_3]] overflow : index +// NSW: br ^bb1(%[[VAL_16]], %[[VAL_15]] : index, i1) +// NSW: ^bb3: +// NSW: return +// NSW: } +// NSW: func private @f3(i16) + // ----- // do_loop with an extra loop-carried value @@ -115,6 +167,29 @@ func.func @x3(%lo : index, %up : index) -> i1 { // CHECK: return %[[VAL_8]] : i1 // CHECK: } +// NSW-LABEL: func @x3( +// NSW-SAME: %[[VAL_0:.*]]: index, +// NSW-SAME: %[[VAL_1:.*]]: index) -> i1 { +// NSW: %[[VAL_2:.*]] = arith.constant 1 : index +// NSW: %[[VAL_3:.*]] = arith.constant true +// NSW: %[[VAL_4:.*]] = arith.subi %[[VAL_1]], %[[VAL_0]] : index +// NSW: %[[VAL_5:.*]] = arith.addi %[[VAL_4]], %[[VAL_2]] : index +// NSW: %[[VAL_6:.*]] = arith.divsi %[[VAL_5]], %[[VAL_2]] : index +// NSW: br ^bb1(%[[VAL_0]], %[[VAL_3]], %[[VAL_6]] : index, i1, index) +// NSW: ^bb1(%[[VAL_7:.*]]: index, %[[VAL_8:.*]]: i1, %[[VAL_9:.*]]: index): +// NSW: %[[VAL_10:.*]] = arith.constant 0 : index +// NSW: %[[VAL_11:.*]] = arith.cmpi sgt, %[[VAL_9]], %[[VAL_10]] : index +// NSW: cond_br %[[VAL_11]], ^bb2, ^bb3 +// NSW: ^bb2: +// NSW: %[[VAL_12:.*]] = fir.call @f2() : () -> i1 +// NSW: %[[VAL_13:.*]] = arith.addi %[[VAL_7]], %[[VAL_2]] overflow : index +// NSW: %[[VAL_14:.*]] = arith.constant 1 : index +// NSW: %[[VAL_15:.*]] = arith.subi %[[VAL_9]], %[[VAL_14]] : index +// NSW: br ^bb1(%[[VAL_13]], %[[VAL_12]], %[[VAL_15]] : index, i1, index) +// NSW: ^bb3: +// NSW: return %[[VAL_8]] : i1 +// NSW: } + // ----- // iterate_while with an extra loop-carried value @@ -160,6 +235,34 @@ func.func private @f4(i32) -> i1 // CHECK: } // CHECK: func private @f4(i32) -> i1 +// NSW-LABEL: func @y3( +// NSW-SAME: %[[VAL_0:.*]]: index, +// NSW-SAME: %[[VAL_1:.*]]: index) -> i1 { +// NSW: %[[VAL_2:.*]] = arith.constant 1 : index +// NSW: %[[VAL_3:.*]] = arith.constant true +// NSW: %[[VAL_4:.*]] = fir.call @f2() : () -> i1 +// NSW: br ^bb1(%[[VAL_0]], %[[VAL_3]], %[[VAL_4]] : index, i1, i1) +// NSW: ^bb1(%[[VAL_5:.*]]: index, %[[VAL_6:.*]]: i1, %[[VAL_7:.*]]: i1): +// NSW: %[[VAL_8:.*]] = arith.constant 0 : index +// NSW: %[[VAL_9:.*]] = arith.cmpi slt, %[[VAL_8]], %[[VAL_2]] : index +// NSW: %[[VAL_10:.*]] = arith.cmpi sle, %[[VAL_5]], %[[VAL_1]] : index +// NSW: %[[VAL_11:.*]] = arith.cmpi slt, %[[VAL_2]], %[[VAL_8]] : index +// NSW: %[[VAL_12:.*]] = arith.cmpi sle, %[[VAL_1]], %[[VAL_5]] : index +// NSW: %[[VAL_13:.*]] = arith.andi %[[VAL_9]], %[[VAL_10]] : i1 +// NSW: %[[VAL_14:.*]] = arith.andi %[[VAL_11]], %[[VAL_12]] : i1 +// NSW: %[[VAL_15:.*]] = arith.ori %[[VAL_13]], %[[VAL_14]] : i1 +// NSW: %[[VAL_16:.*]] = arith.andi %[[VAL_6]], %[[VAL_15]] : i1 +// NSW: cond_br %[[VAL_16]], ^bb2, ^bb3 +// NSW: ^bb2: +// NSW: %[[VAL_17:.*]] = fir.call @f2() : () -> i1 +// NSW: %[[VAL_18:.*]] = arith.addi %[[VAL_5]], %[[VAL_2]] overflow : index +// NSW: br ^bb1(%[[VAL_18]], %[[VAL_6]], %[[VAL_17]] : index, i1, i1) +// NSW: ^bb3: +// NSW: %[[VAL_19:.*]] = arith.andi %[[VAL_6]], %[[VAL_7]] : i1 +// NSW: return %[[VAL_19]] : i1 +// NSW: } +// NSW: func private @f4(i32) -> i1 + // ----- // do_loop that returns the final value of the induction @@ -196,6 +299,29 @@ func.func @x4(%lo : index, %up : index) -> index { // CHECK: return %[[VAL_6]] : index // CHECK: } +// NSW-LABEL: func @x4( +// NSW-SAME: %[[VAL_0:.*]]: index, +// NSW-SAME: %[[VAL_1:.*]]: index) -> index { +// NSW: %[[VAL_2:.*]] = arith.constant 1 : index +// NSW: %[[VAL_3:.*]] = arith.subi %[[VAL_1]], %[[VAL_0]] : index +// NSW: %[[VAL_4:.*]] = arith.addi %[[VAL_3]], %[[VAL_2]] : index +// NSW: %[[VAL_5:.*]] = arith.divsi %[[VAL_4]], %[[VAL_2]] : index +// NSW: br ^bb1(%[[VAL_0]], %[[VAL_5]] : index, index) +// NSW: ^bb1(%[[VAL_6:.*]]: index, %[[VAL_7:.*]]: index): +// NSW: %[[VAL_8:.*]] = arith.constant 0 : index +// NSW: %[[VAL_9:.*]] = arith.cmpi sgt, %[[VAL_7]], %[[VAL_8]] : index +// NSW: cond_br %[[VAL_9]], ^bb2, ^bb3 +// NSW: ^bb2: +// NSW: %[[VAL_10:.*]] = fir.convert %[[VAL_6]] : (index) -> i32 +// NSW: %[[VAL_11:.*]] = fir.call @f4(%[[VAL_10]]) : (i32) -> i1 +// NSW: %[[VAL_12:.*]] = arith.addi %[[VAL_6]], %[[VAL_2]] overflow : index +// NSW: %[[VAL_13:.*]] = arith.constant 1 : index +// NSW: %[[VAL_14:.*]] = arith.subi %[[VAL_7]], %[[VAL_13]] : index +// NSW: br ^bb1(%[[VAL_12]], %[[VAL_14]] : index, index) +// NSW: ^bb3: +// NSW: return %[[VAL_6]] : index +// NSW: } + // ----- // iterate_while that returns the final value of both inductions @@ -236,6 +362,32 @@ func.func @y4(%lo : index, %up : index) -> index { // CHECK: return %[[VAL_4]] : index // CHECK: } +// NSW-LABEL: func @y4( +// NSW-SAME: %[[VAL_0:.*]]: index, +// NSW-SAME: %[[VAL_1:.*]]: index) -> index { +// NSW: %[[VAL_2:.*]] = arith.constant 1 : index +// NSW: %[[VAL_3:.*]] = arith.constant true +// NSW: br ^bb1(%[[VAL_0]], %[[VAL_3]] : index, i1) +// NSW: ^bb1(%[[VAL_4:.*]]: index, %[[VAL_5:.*]]: i1): +// NSW: %[[VAL_6:.*]] = arith.constant 0 : index +// NSW: %[[VAL_7:.*]] = arith.cmpi slt, %[[VAL_6]], %[[VAL_2]] : index +// NSW: %[[VAL_8:.*]] = arith.cmpi sle, %[[VAL_4]], %[[VAL_1]] : index +// NSW: %[[VAL_9:.*]] = arith.cmpi slt, %[[VAL_2]], %[[VAL_6]] : index +// NSW: %[[VAL_10:.*]] = arith.cmpi sle, %[[VAL_1]], %[[VAL_4]] : index +// NSW: %[[VAL_11:.*]] = arith.andi %[[VAL_7]], %[[VAL_8]] : i1 +// NSW: %[[VAL_12:.*]] = arith.andi %[[VAL_9]], %[[VAL_10]] : i1 +// NSW: %[[VAL_13:.*]] = arith.ori %[[VAL_11]], %[[VAL_12]] : i1 +// NSW: %[[VAL_14:.*]] = arith.andi %[[VAL_5]], %[[VAL_13]] : i1 +// NSW: cond_br %[[VAL_14]], ^bb2, ^bb3 +// NSW: ^bb2: +// NSW: %[[VAL_15:.*]] = fir.convert %[[VAL_4]] : (index) -> i32 +// NSW: %[[VAL_16:.*]] = fir.call @f4(%[[VAL_15]]) : (i32) -> i1 +// NSW: %[[VAL_17:.*]] = arith.addi %[[VAL_4]], %[[VAL_2]] overflow : index +// NSW: br ^bb1(%[[VAL_17]], %[[VAL_16]] : index, i1) +// NSW: ^bb3: +// NSW: return %[[VAL_4]] : index +// NSW: } + // ----- // do_loop that returns the final induction value @@ -277,6 +429,31 @@ func.func @x5(%lo : index, %up : index) -> index { // CHECK: return %[[VAL_7]] : index // CHECK: } +// NSW-LABEL: func @x5( +// NSW-SAME: %[[VAL_0:.*]]: index, +// NSW-SAME: %[[VAL_1:.*]]: index) -> index { +// NSW: %[[VAL_2:.*]] = arith.constant 1 : index +// NSW: %[[VAL_3:.*]] = arith.constant 42 : i16 +// NSW: %[[VAL_4:.*]] = arith.subi %[[VAL_1]], %[[VAL_0]] : index +// NSW: %[[VAL_5:.*]] = arith.addi %[[VAL_4]], %[[VAL_2]] : index +// NSW: %[[VAL_6:.*]] = arith.divsi %[[VAL_5]], %[[VAL_2]] : index +// NSW: br ^bb1(%[[VAL_0]], %[[VAL_3]], %[[VAL_6]] : index, i16, index) +// NSW: ^bb1(%[[VAL_7:.*]]: index, %[[VAL_8:.*]]: i16, %[[VAL_9:.*]]: index): +// NSW: %[[VAL_10:.*]] = arith.constant 0 : index +// NSW: %[[VAL_11:.*]] = arith.cmpi sgt, %[[VAL_9]], %[[VAL_10]] : index +// NSW: cond_br %[[VAL_11]], ^bb2, ^bb3 +// NSW: ^bb2: +// NSW: %[[VAL_12:.*]] = fir.call @f2() : () -> i1 +// NSW: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i1) -> i16 +// NSW: %[[VAL_14:.*]] = arith.addi %[[VAL_7]], %[[VAL_2]] overflow : index +// NSW: %[[VAL_15:.*]] = arith.constant 1 : index +// NSW: %[[VAL_16:.*]] = arith.subi %[[VAL_9]], %[[VAL_15]] : index +// NSW: br ^bb1(%[[VAL_14]], %[[VAL_13]], %[[VAL_16]] : index, i16, index) +// NSW: ^bb3: +// NSW: fir.call @f3(%[[VAL_8]]) : (i16) -> () +// NSW: return %[[VAL_7]] : index +// NSW: } + // ----- // iterate_while that returns the both induction values @@ -331,3 +508,37 @@ func.func @y5(%lo : index, %up : index) -> index { // CHECK: fir.call @f3(%[[VAL_7]]) : (i16) -> () // CHECK: return %[[VAL_5]] : index // CHECK: } + +// NSW-LABEL: func @y5( +// NSW-SAME: %[[VAL_0:.*]]: index, +// NSW-SAME: %[[VAL_1:.*]]: index) -> index { +// NSW: %[[VAL_2:.*]] = arith.constant 1 : index +// NSW: %[[VAL_3:.*]] = arith.constant 42 : i16 +// NSW: %[[VAL_4:.*]] = arith.constant true +// NSW: br ^bb1(%[[VAL_0]], %[[VAL_4]], %[[VAL_3]] : index, i1, i16) +// NSW: ^bb1(%[[VAL_5:.*]]: index, %[[VAL_6:.*]]: i1, %[[VAL_7:.*]]: i16): +// NSW: %[[VAL_8:.*]] = arith.constant 0 : index +// NSW: %[[VAL_9:.*]] = arith.cmpi slt, %[[VAL_8]], %[[VAL_2]] : index +// NSW: %[[VAL_10:.*]] = arith.cmpi sle, %[[VAL_5]], %[[VAL_1]] : index +// NSW: %[[VAL_11:.*]] = arith.cmpi slt, %[[VAL_2]], %[[VAL_8]] : index +// NSW: %[[VAL_12:.*]] = arith.cmpi sle, %[[VAL_1]], %[[VAL_5]] : index +// NSW: %[[VAL_13:.*]] = arith.andi %[[VAL_9]], %[[VAL_10]] : i1 +// NSW: %[[VAL_14:.*]] = arith.andi %[[VAL_11]], %[[VAL_12]] : i1 +// NSW: %[[VAL_15:.*]] = arith.ori %[[VAL_13]], %[[VAL_14]] : i1 +// NSW: %[[VAL_16:.*]] = arith.andi %[[VAL_6]], %[[VAL_15]] : i1 +// NSW: cond_br %[[VAL_16]], ^bb2, ^bb3 +// NSW: ^bb2: +// NSW: %[[VAL_17:.*]] = fir.call @f2() : () -> i1 +// NSW: %[[VAL_18:.*]] = fir.convert %[[VAL_17]] : (i1) -> i16 +// NSW: %[[VAL_19:.*]] = arith.addi %[[VAL_5]], %[[VAL_2]] overflow : index +// NSW: br ^bb1(%[[VAL_19]], %[[VAL_17]], %[[VAL_18]] : index, i1, i16) +// NSW: ^bb3: +// NSW: cond_br %[[VAL_6]], ^bb4, ^bb5 +// NSW: ^bb4: +// NSW: %[[VAL_20:.*]] = arith.constant 0 : i32 +// NSW: %[[VAL_21:.*]] = fir.call @f4(%[[VAL_20]]) : (i32) -> i1 +// NSW: br ^bb5 +// NSW: ^bb5: +// NSW: fir.call @f3(%[[VAL_7]]) : (i16) -> () +// NSW: return %[[VAL_5]] : index +// NSW: } diff --git a/flang/test/Lower/array-substring.f90 b/flang/test/Lower/array-substring.f90 index 421c4b28ac8f..2e283997e3e0 100644 --- a/flang/test/Lower/array-substring.f90 +++ b/flang/test/Lower/array-substring.f90 @@ -1,4 +1,5 @@ ! RUN: bbc -hlfir=false %s -o - | FileCheck %s +! RUN: bbc -hlfir=false -integer-overflow %s -o - | FileCheck %s --check-prefix=NSW ! CHECK-LABEL: func @_QPtest( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1>{{.*}}) -> !fir.array<1x!fir.logical<4>> { @@ -45,3 +46,42 @@ function test(C) test = C(1:1)(1:8) == (/'ABCDabcd'/) end function test + +! NSW-LABEL: func @_QPtest( +! NSW-SAME: %[[VAL_0:.*]]: !fir.boxchar<1>{{.*}}) -> !fir.array<1x!fir.logical<4>> { +! NSW-DAG: %[[VAL_1:.*]] = arith.constant 1 : index +! NSW-DAG: %[[VAL_2:.*]] = arith.constant 0 : index +! NSW-DAG: %[[VAL_3:.*]] = arith.constant 0 : i32 +! NSW-DAG: %[[VAL_4:.*]] = arith.constant 8 : index +! NSW: %[[VAL_6:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref>, index) +! NSW: %[[VAL_7:.*]] = fir.convert %[[VAL_6]]#0 : (!fir.ref>) -> !fir.ref>> +! NSW: %[[VAL_8:.*]] = fir.alloca !fir.array<1x!fir.logical<4>> {bindc_name = "test", uniq_name = "_QFtestEtest"} +! NSW: %[[VAL_9:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> +! NSW: %[[VAL_10:.*]] = fir.slice %[[VAL_1]], %[[VAL_1]], %[[VAL_1]] : (index, index, index) -> !fir.slice<1> +! NSW: %[[VAL_11:.*]] = fir.address_of(@_QQ{{.*}}) : !fir.ref>> +! NSW: br ^bb1(%[[VAL_2]], %[[VAL_1]] : index, index) +! NSW: ^bb1(%[[VAL_12:.*]]: index, %[[VAL_13:.*]]: index): +! NSW: %[[VAL_14:.*]] = arith.cmpi sgt, %[[VAL_13]], %[[VAL_2]] : index +! NSW: cond_br %[[VAL_14]], ^bb2, ^bb3 +! NSW: ^bb2: +! NSW: %[[VAL_15:.*]] = arith.addi %[[VAL_12]], %[[VAL_1]] : index +! NSW: %[[VAL_16:.*]] = fir.array_coor %[[VAL_7]](%[[VAL_9]]) {{\[}}%[[VAL_10]]] %[[VAL_15]] : (!fir.ref>>, !fir.shape<1>, !fir.slice<1>, index) -> !fir.ref> +! NSW: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (!fir.ref>) -> !fir.ref>> +! NSW: %[[VAL_18:.*]] = fir.coordinate_of %[[VAL_17]], %[[VAL_2]] : (!fir.ref>>, index) -> !fir.ref> +! NSW: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (!fir.ref>) -> !fir.ref> +! NSW: %[[VAL_20:.*]] = fir.array_coor %[[VAL_11]](%[[VAL_9]]) %[[VAL_15]] : (!fir.ref>>, !fir.shape<1>, index) -> !fir.ref> +! NSW: %[[VAL_21:.*]] = fir.convert %[[VAL_19]] : (!fir.ref>) -> !fir.ref +! NSW: %[[VAL_22:.*]] = fir.convert %[[VAL_20]] : (!fir.ref>) -> !fir.ref +! NSW: %[[VAL_23:.*]] = fir.convert %[[VAL_4]] : (index) -> i64 +! NSW: %[[VAL_24:.*]] = fir.call @_FortranACharacterCompareScalar1(%[[VAL_21]], %[[VAL_22]], %[[VAL_23]], %[[VAL_23]]) {{.*}}: (!fir.ref, !fir.ref, i64, i64) -> i32 +! NSW: %[[VAL_25:.*]] = arith.cmpi eq, %[[VAL_24]], %[[VAL_3]] : i32 +! NSW: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! NSW: %[[VAL_27:.*]] = fir.array_coor %[[VAL_8]](%[[VAL_9]]) %[[VAL_15]] : (!fir.ref>>, !fir.shape<1>, index) -> !fir.ref> +! NSW: fir.store %[[VAL_26]] to %[[VAL_27]] : !fir.ref> +! NSW: %[[VAL_15_NSW:.*]] = arith.addi %[[VAL_12]], %[[VAL_1]] overflow : index +! NSW: %[[VAL_28:.*]] = arith.subi %[[VAL_13]], %[[VAL_1]] : index +! NSW: br ^bb1(%[[VAL_15_NSW]], %[[VAL_28]] : index, index) +! NSW: ^bb3: +! NSW: %[[VAL_29:.*]] = fir.load %[[VAL_8]] : !fir.ref>> +! NSW: return %[[VAL_29]] : !fir.array<1x!fir.logical<4>> +! NSW: } diff --git a/flang/test/Lower/do_loop.f90 b/flang/test/Lower/do_loop.f90 index d9c83658ee25..a46e6c947391 100644 --- a/flang/test/Lower/do_loop.f90 +++ b/flang/test/Lower/do_loop.f90 @@ -1,5 +1,6 @@ ! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false -o - %s | FileCheck %s ! RUN: %flang_fc1 -mllvm --use-desc-for-alloc=false -emit-fir -flang-deprecated-no-hlfir -o - %s | FileCheck %s +! RUN: %flang_fc1 -mllvm --use-desc-for-alloc=false -emit-fir -flang-deprecated-no-hlfir -flang-experimental-integer-overflow -o - %s | FileCheck %s --check-prefix=NSW ! Simple tests for structured ordered loops with loop-control. ! Tests the structure of the loop, storage to index variable and return and @@ -7,8 +8,10 @@ ! Test a simple loop with the final value of the index variable read outside the loop ! CHECK-LABEL: simple_loop +! NSW-LABEL: simple_loop subroutine simple_loop ! CHECK: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_loopEi"} + ! NSW: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_loopEi"} integer :: i ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 @@ -18,14 +21,18 @@ subroutine simple_loop ! CHECK: %[[C1:.*]] = arith.constant 1 : index ! CHECK: %[[LB:.*]] = fir.convert %[[C1_CVT]] : (index) -> i32 ! CHECK: %[[LI_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = + ! NSW: %[[LI_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = ! CHECK-SAME: %[[C1_CVT]] to %[[C5_CVT]] step %[[C1]] ! CHECK-SAME: iter_args(%[[IV:.*]] = %[[LB]]) -> (index, i32) { do i=1,5 ! CHECK: fir.store %[[IV]] to %[[I_REF]] : !fir.ref ! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[C1]] : index + ! NSW: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[C1:.*]] overflow : index ! CHECK: %[[STEPCAST:.*]] = fir.convert %[[C1]] : (index) -> i32 ! CHECK: %[[IVLOAD:.*]] = fir.load %[[I_REF]] : !fir.ref + ! NSW: %[[IVLOAD:.*]] = fir.load %[[I_REF]] : !fir.ref ! CHECK: %[[IVINC:.*]] = arith.addi %[[IVLOAD]], %[[STEPCAST]] : i32 + ! NSW: %[[IVINC:.*]] = arith.addi %[[IVLOAD]], %[[STEPCAST:.*]] overflow : i32 ! CHECK: fir.result %[[LI_NEXT]], %[[IVINC]] : index, i32 ! CHECK: } end do @@ -37,11 +44,14 @@ end subroutine ! Test a 2-nested loop with a body composed of a reduction. Values are read from a 2d array. ! CHECK-LABEL: nested_loop +! NSW-LABEL: nested_loop subroutine nested_loop ! CHECK: %[[ARR_REF:.*]] = fir.alloca !fir.array<5x5xi32> {bindc_name = "arr", uniq_name = "_QFnested_loopEarr"} ! CHECK: %[[ASUM_REF:.*]] = fir.alloca i32 {bindc_name = "asum", uniq_name = "_QFnested_loopEasum"} ! CHECK: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFnested_loopEi"} + ! NSW: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFnested_loopEi"} ! CHECK: %[[J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFnested_loopEj"} + ! NSW: %[[J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFnested_loopEj"} integer :: asum, arr(5,5) integer :: i, j asum = 0 @@ -52,6 +62,7 @@ subroutine nested_loop ! CHECK: %[[ST_I:.*]] = arith.constant 1 : index ! CHECK: %[[I_LB:.*]] = fir.convert %[[S_I_CVT]] : (index) -> i32 ! CHECK: %[[I_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = + ! NSW: %[[I_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = ! CHECK-SAME: %[[S_I_CVT]] to %[[E_I_CVT]] step %[[ST_I]] ! CHECK-SAME: iter_args(%[[I_IV:.*]] = %[[I_LB]]) -> (index, i32) { do i=1,5 @@ -63,6 +74,7 @@ subroutine nested_loop ! CHECK: %[[ST_J:.*]] = arith.constant 1 : index ! CHECK: %[[J_LB:.*]] = fir.convert %[[S_J_CVT]] : (index) -> i32 ! CHECK: %[[J_RES:.*]]:2 = fir.do_loop %[[LJ:[^ ]*]] = + ! NSW: %[[J_RES:.*]]:2 = fir.do_loop %[[LJ:[^ ]*]] = ! CHECK-SAME: %[[S_J_CVT]] to %[[E_J_CVT]] step %[[ST_J]] ! CHECK-SAME: iter_args(%[[J_IV:.*]] = %[[J_LB]]) -> (index, i32) { do j=1,5 @@ -82,17 +94,23 @@ subroutine nested_loop ! CHECK: fir.store %[[ASUM_NEW]] to %[[ASUM_REF]] : !fir.ref asum = asum + arr(i,j) ! CHECK: %[[LJ_NEXT:.*]] = arith.addi %[[LJ]], %[[ST_J]] : index + ! NSW: %[[LJ_NEXT:.*]] = arith.addi %[[LJ]], %[[ST_J:.*]] overflow : index ! CHECK: %[[J_STEPCAST:.*]] = fir.convert %[[ST_J]] : (index) -> i32 ! CHECK: %[[J_IVLOAD:.*]] = fir.load %[[J_REF]] : !fir.ref + ! NSW: %[[J_IVLOAD:.*]] = fir.load %[[J_REF]] : !fir.ref ! CHECK: %[[J_IVINC:.*]] = arith.addi %[[J_IVLOAD]], %[[J_STEPCAST]] : i32 + ! NSW: %[[J_IVINC:.*]] = arith.addi %[[J_IVLOAD]], %[[J_STEPCAST:.*]] overflow : i32 ! CHECK: fir.result %[[LJ_NEXT]], %[[J_IVINC]] : index, i32 ! CHECK: } end do ! CHECK: fir.store %[[J_RES]]#1 to %[[J_REF]] : !fir.ref ! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_I]] : index + ! NSW: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_I:.*]] overflow : index ! CHECK: %[[I_STEPCAST:.*]] = fir.convert %[[ST_I]] : (index) -> i32 ! CHECK: %[[I_IVLOAD:.*]] = fir.load %[[I_REF]] : !fir.ref + ! NSW: %[[I_IVLOAD:.*]] = fir.load %[[I_REF]] : !fir.ref ! CHECK: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST]] : i32 + ! NSW: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST:.*]] overflow : i32 ! CHECK: fir.result %[[LI_NEXT]], %[[I_IVINC]] : index, i32 ! CHECK: } end do @@ -101,9 +119,11 @@ end subroutine ! Test a downcounting loop ! CHECK-LABEL: down_counting_loop +! NSW-LABEL: down_counting_loop subroutine down_counting_loop() integer :: i ! CHECK: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFdown_counting_loopEi"} + ! NSW: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFdown_counting_loopEi"} ! CHECK: %[[C5:.*]] = arith.constant 5 : i32 ! CHECK: %[[C5_CVT:.*]] = fir.convert %[[C5]] : (i32) -> index @@ -113,14 +133,18 @@ subroutine down_counting_loop() ! CHECK: %[[CMINUS1_STEP_CVT:.*]] = fir.convert %[[CMINUS1]] : (i32) -> index ! CHECK: %[[I_LB:.*]] = fir.convert %[[C5_CVT]] : (index) -> i32 ! CHECK: %[[I_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = + ! NSW: %[[I_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = ! CHECK-SAME: %[[C5_CVT]] to %[[C1_CVT]] step %[[CMINUS1_STEP_CVT]] ! CHECK-SAME: iter_args(%[[I_IV:.*]] = %[[I_LB]]) -> (index, i32) { do i=5,1,-1 ! CHECK: fir.store %[[I_IV]] to %[[I_REF]] : !fir.ref ! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[CMINUS1_STEP_CVT]] : index + ! NSW: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[CMINUS1_STEP_CVT:.*]] overflow : index ! CHECK: %[[I_STEPCAST:.*]] = fir.convert %[[CMINUS1_STEP_CVT]] : (index) -> i32 ! CHECK: %[[I_IVLOAD:.*]] = fir.load %[[I_REF]] : !fir.ref + ! NSW: %[[I_IVLOAD:.*]] = fir.load %[[I_REF]] : !fir.ref ! CHECK: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST]] : i32 + ! NSW: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST:.*]] overflow : i32 ! CHECK: fir.result %[[LI_NEXT]], %[[I_IVINC]] : index, i32 ! CHECK: } end do @@ -129,6 +153,7 @@ end subroutine ! Test a general loop with a variable step ! CHECK-LABEL: loop_with_variable_step +! NSW-LABEL: loop_with_variable_step ! CHECK-SAME: (%[[S_REF:.*]]: !fir.ref {fir.bindc_name = "s"}, %[[E_REF:.*]]: !fir.ref {fir.bindc_name = "e"}, %[[ST_REF:.*]]: !fir.ref {fir.bindc_name = "st"}) { subroutine loop_with_variable_step(s,e,st) integer :: s, e, st @@ -141,14 +166,18 @@ subroutine loop_with_variable_step(s,e,st) ! CHECK: %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i32) -> index ! CHECK: %[[I_LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i32 ! CHECK: %[[I_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = + ! NSW: %[[I_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = ! CHECK-SAME: %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] ! CHECK-SAME: iter_args(%[[I_IV:.*]] = %[[I_LB]]) -> (index, i32) { do i=s,e,st ! CHECK: fir.store %[[I_IV]] to %[[I_REF]] : !fir.ref ! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_CVT]] : index + ! NSW: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_CVT:.*]] overflow : index ! CHECK: %[[I_STEPCAST:.*]] = fir.convert %[[ST_CVT]] : (index) -> i32 ! CHECK: %[[I_IVLOAD:.*]] = fir.load %[[I_REF]] : !fir.ref + ! NSW: %[[I_IVLOAD:.*]] = fir.load %[[I_REF]] : !fir.ref ! CHECK: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST]] : i32 + ! NSW: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST:.*]] overflow : i32 ! CHECK: fir.result %[[LI_NEXT]], %[[I_IVINC]] : index, i32 ! CHECK: } end do @@ -157,11 +186,13 @@ end subroutine ! Test usage of pointer variables as index, start, end and step variables ! CHECK-LABEL: loop_with_pointer_variables +! NSW-LABEL: loop_with_pointer_variables ! CHECK-SAME: (%[[S_REF:.*]]: !fir.ref {fir.bindc_name = "s", fir.target}, %[[E_REF:.*]]: !fir.ref {fir.bindc_name = "e", fir.target}, %[[ST_REF:.*]]: !fir.ref {fir.bindc_name = "st", fir.target}) { subroutine loop_with_pointer_variables(s,e,st) ! CHECK: %[[E_PTR_REF:.*]] = fir.alloca !fir.ptr {uniq_name = "_QFloop_with_pointer_variablesEeptr.addr"} ! CHECK: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", fir.target, uniq_name = "_QFloop_with_pointer_variablesEi"} ! CHECK: %[[I_PTR_REF:.*]] = fir.alloca !fir.ptr {uniq_name = "_QFloop_with_pointer_variablesEiptr.addr"} +! NSW: %[[I_PTR_REF:.*]] = fir.alloca !fir.ptr {uniq_name = "_QFloop_with_pointer_variablesEiptr.addr"} ! CHECK: %[[S_PTR_REF:.*]] = fir.alloca !fir.ptr {uniq_name = "_QFloop_with_pointer_variablesEsptr.addr"} ! CHECK: %[[ST_PTR_REF:.*]] = fir.alloca !fir.ptr {uniq_name = "_QFloop_with_pointer_variablesEstptr.addr"} integer, target :: i @@ -182,6 +213,7 @@ subroutine loop_with_pointer_variables(s,e,st) stptr => st ! CHECK: %[[I_PTR:.*]] = fir.load %[[I_PTR_REF]] : !fir.ref> +! NSW: %[[I_PTR:.*]] = fir.load %[[I_PTR_REF]] : !fir.ref> ! CHECK: %[[S_PTR:.*]] = fir.load %[[S_PTR_REF]] : !fir.ref> ! CHECK: %[[S:.*]] = fir.load %[[S_PTR]] : !fir.ptr ! CHECK: %[[S_CVT:.*]] = fir.convert %[[S]] : (i32) -> index @@ -193,14 +225,18 @@ subroutine loop_with_pointer_variables(s,e,st) ! CHECK: %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i32) -> index ! CHECK: %[[I_LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i32 ! CHECK: %[[I_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = +! NSW: %[[I_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = ! CHECK-SAME: %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] ! CHECK-SAME: iter_args(%[[I_IV:.*]] = %[[I_LB]]) -> (index, i32) { do iptr=sptr,eptr,stptr ! CHECK: fir.store %[[I_IV]] to %[[I_PTR]] : !fir.ptr ! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_CVT]] : index +! NSW: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_CVT:.*]] overflow : index ! CHECK: %[[I_STEPCAST:.*]] = fir.convert %[[ST_CVT]] : (index) -> i32 ! CHECK: %[[I_IVLOAD:.*]] = fir.load %[[I_PTR]] : !fir.ptr +! NSW: %[[I_IVLOAD:.*]] = fir.load %[[I_PTR]] : !fir.ptr ! CHECK: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST]] : i32 +! NSW: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST:.*]] overflow : i32 ! CHECK: fir.result %[[LI_NEXT]], %[[I_IVINC]] : index, i32 end do ! CHECK: } @@ -209,9 +245,11 @@ end subroutine ! Test usage of non-default integer kind for loop control and loop index variable ! CHECK-LABEL: loop_with_non_default_integer +! NSW-LABEL: loop_with_non_default_integer ! CHECK-SAME: (%[[S_REF:.*]]: !fir.ref {fir.bindc_name = "s"}, %[[E_REF:.*]]: !fir.ref {fir.bindc_name = "e"}, %[[ST_REF:.*]]: !fir.ref {fir.bindc_name = "st"}) { subroutine loop_with_non_default_integer(s,e,st) ! CHECK: %[[I_REF:.*]] = fir.alloca i64 {bindc_name = "i", uniq_name = "_QFloop_with_non_default_integerEi"} + ! NSW: %[[I_REF:.*]] = fir.alloca i64 {bindc_name = "i", uniq_name = "_QFloop_with_non_default_integerEi"} integer(kind=8):: i ! CHECK: %[[S:.*]] = fir.load %[[S_REF]] : !fir.ref ! CHECK: %[[S_CVT:.*]] = fir.convert %[[S]] : (i64) -> index @@ -223,14 +261,18 @@ subroutine loop_with_non_default_integer(s,e,st) ! CHECK: %[[I_LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i64 ! CHECK: %[[I_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = + ! NSW: %[[I_RES:.*]]:2 = fir.do_loop %[[LI:[^ ]*]] = ! CHECK-SAME: %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] ! CHECK-SAME: iter_args(%[[I_IV:.*]] = %[[I_LB]]) -> (index, i64) { do i=s,e,st ! CHECK: fir.store %[[I_IV]] to %[[I_REF]] : !fir.ref ! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_CVT]] : index + ! NSW: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_CVT:.*]] overflow : index ! CHECK: %[[I_STEPCAST:.*]] = fir.convert %[[ST_CVT]] : (index) -> i64 ! CHECK: %[[I_IVLOAD:.*]] = fir.load %[[I_REF]] : !fir.ref + ! NSW: %[[I_IVLOAD:.*]] = fir.load %[[I_REF]] : !fir.ref ! CHECK: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST]] : i64 + ! NSW: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST:.*]] overflow : i64 ! CHECK: fir.result %[[LI_NEXT]], %[[I_IVINC]] : index, i64 end do ! CHECK: } diff --git a/flang/test/Lower/do_loop_unstructured.f90 b/flang/test/Lower/do_loop_unstructured.f90 index c6bdd4b64ce3..e1a669e09c9a 100644 --- a/flang/test/Lower/do_loop_unstructured.f90 +++ b/flang/test/Lower/do_loop_unstructured.f90 @@ -1,5 +1,6 @@ ! RUN: bbc -emit-fir -hlfir=false -o - %s | FileCheck %s ! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -o - %s | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -flang-experimental-integer-overflow -o - %s | FileCheck %s --check-prefix=NSW ! Tests for unstructured loops. @@ -44,6 +45,36 @@ end subroutine ! CHECK: ^[[EXIT]]: ! CHECK: return +! NSW-LABEL: simple_unstructured +! NSW: %[[TRIP_VAR_REF:.*]] = fir.alloca i32 +! NSW: %[[LOOP_VAR_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_unstructuredEi"} +! NSW: %[[ONE:.*]] = arith.constant 1 : i32 +! NSW: %[[HUNDRED:.*]] = arith.constant 100 : i32 +! NSW: %[[STEP_ONE:.*]] = arith.constant 1 : i32 +! NSW: %[[TMP1:.*]] = arith.subi %[[HUNDRED]], %[[ONE]] : i32 +! NSW: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[STEP_ONE]] : i32 +! NSW: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[STEP_ONE]] : i32 +! NSW: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_REF]] : !fir.ref +! NSW: fir.store %[[ONE]] to %[[LOOP_VAR_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER:.*]] +! NSW: ^[[HEADER]]: +! NSW: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref +! NSW: %[[ZERO:.*]] = arith.constant 0 : i32 +! NSW: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32 +! NSW: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]] +! NSW: ^[[BODY]]: +! NSW: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref +! NSW: %[[ONE_1:.*]] = arith.constant 1 : i32 +! NSW: %[[TRIP_VAR_NEXT:.*]] = arith.subi %[[TRIP_VAR]], %[[ONE_1]] : i32 +! NSW: fir.store %[[TRIP_VAR_NEXT]] to %[[TRIP_VAR_REF]] : !fir.ref +! NSW: %[[LOOP_VAR:.*]] = fir.load %[[LOOP_VAR_REF]] : !fir.ref +! NSW: %[[STEP_ONE_2:.*]] = arith.constant 1 : i32 +! NSW: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP_ONE_2]] overflow : i32 +! NSW: fir.store %[[LOOP_VAR_NEXT]] to %[[LOOP_VAR_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER]] +! NSW: ^[[EXIT]]: +! NSW: return + ! Test an unstructured loop with a step. Mostly similar to the previous one. ! Only difference is a non-unit step. subroutine simple_unstructured_with_step() @@ -83,6 +114,36 @@ end subroutine ! CHECK: ^[[EXIT]]: ! CHECK: return +! NSW-LABEL: simple_unstructured_with_step +! NSW: %[[TRIP_VAR_REF:.*]] = fir.alloca i32 +! NSW: %[[LOOP_VAR_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_unstructured_with_stepEi"} +! NSW: %[[ONE:.*]] = arith.constant 1 : i32 +! NSW: %[[HUNDRED:.*]] = arith.constant 100 : i32 +! NSW: %[[STEP:.*]] = arith.constant 2 : i32 +! NSW: %[[TMP1:.*]] = arith.subi %[[HUNDRED]], %[[ONE]] : i32 +! NSW: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[STEP]] : i32 +! NSW: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[STEP]] : i32 +! NSW: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_REF]] : !fir.ref +! NSW: fir.store %[[ONE]] to %[[LOOP_VAR_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER:.*]] +! NSW: ^[[HEADER]]: +! NSW: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref +! NSW: %[[ZERO:.*]] = arith.constant 0 : i32 +! NSW: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32 +! NSW: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]] +! NSW: ^[[BODY]]: +! NSW: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref +! NSW: %[[ONE_1:.*]] = arith.constant 1 : i32 +! NSW: %[[TRIP_VAR_NEXT:.*]] = arith.subi %[[TRIP_VAR]], %[[ONE_1]] : i32 +! NSW: fir.store %[[TRIP_VAR_NEXT]] to %[[TRIP_VAR_REF]] : !fir.ref +! NSW: %[[LOOP_VAR:.*]] = fir.load %[[LOOP_VAR_REF]] : !fir.ref +! NSW: %[[STEP_2:.*]] = arith.constant 2 : i32 +! NSW: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP_2]] overflow : i32 +! NSW: fir.store %[[LOOP_VAR_NEXT]] to %[[LOOP_VAR_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER]] +! NSW: ^[[EXIT]]: +! NSW: return + ! Test a three nested unstructured loop. Three nesting is the basic case where ! we have loops that are neither innermost or outermost. subroutine nested_unstructured() @@ -180,6 +241,90 @@ end subroutine ! CHECK: ^[[EXIT_I]]: ! CHECK: return +! NSW-LABEL: nested_unstructured +! NSW: %[[TRIP_VAR_K_REF:.*]] = fir.alloca i32 +! NSW: %[[TRIP_VAR_J_REF:.*]] = fir.alloca i32 +! NSW: %[[TRIP_VAR_I_REF:.*]] = fir.alloca i32 +! NSW: %[[LOOP_VAR_I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFnested_unstructuredEi"} +! NSW: %[[LOOP_VAR_J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFnested_unstructuredEj"} +! NSW: %[[LOOP_VAR_K_REF:.*]] = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFnested_unstructuredEk"} +! NSW: %[[I_START:.*]] = arith.constant 1 : i32 +! NSW: %[[I_END:.*]] = arith.constant 100 : i32 +! NSW: %[[I_STEP:.*]] = arith.constant 1 : i32 +! NSW: %[[TMP1:.*]] = arith.subi %[[I_END]], %[[I_START]] : i32 +! NSW: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[I_STEP]] : i32 +! NSW: %[[TRIP_COUNT_I:.*]] = arith.divsi %[[TMP2]], %[[I_STEP]] : i32 +! NSW: fir.store %[[TRIP_COUNT_I]] to %[[TRIP_VAR_I_REF]] : !fir.ref +! NSW: fir.store %[[I_START]] to %[[LOOP_VAR_I_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER_I:.*]] +! NSW: ^[[HEADER_I]]: +! NSW: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref +! NSW: %[[ZERO_1:.*]] = arith.constant 0 : i32 +! NSW: %[[COND_I:.*]] = arith.cmpi sgt, %[[TRIP_VAR_I]], %[[ZERO_1]] : i32 +! NSW: cf.cond_br %[[COND_I]], ^[[BODY_I:.*]], ^[[EXIT_I:.*]] +! NSW: ^[[BODY_I]]: +! NSW: %[[J_START:.*]] = arith.constant 1 : i32 +! NSW: %[[J_END:.*]] = arith.constant 200 : i32 +! NSW: %[[J_STEP:.*]] = arith.constant 1 : i32 +! NSW: %[[TMP3:.*]] = arith.subi %[[J_END]], %[[J_START]] : i32 +! NSW: %[[TMP4:.*]] = arith.addi %[[TMP3]], %[[J_STEP]] : i32 +! NSW: %[[TRIP_COUNT_J:.*]] = arith.divsi %[[TMP4]], %[[J_STEP]] : i32 +! NSW: fir.store %[[TRIP_COUNT_J]] to %[[TRIP_VAR_J_REF]] : !fir.ref +! NSW: fir.store %[[J_START]] to %[[LOOP_VAR_J_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER_J:.*]] +! NSW: ^[[HEADER_J]]: +! NSW: %[[TRIP_VAR_J:.*]] = fir.load %[[TRIP_VAR_J_REF]] : !fir.ref +! NSW: %[[ZERO_2:.*]] = arith.constant 0 : i32 +! NSW: %[[COND_J:.*]] = arith.cmpi sgt, %[[TRIP_VAR_J]], %[[ZERO_2]] : i32 +! NSW: cf.cond_br %[[COND_J]], ^[[BODY_J:.*]], ^[[EXIT_J:.*]] +! NSW: ^[[BODY_J]]: +! NSW: %[[K_START:.*]] = arith.constant 1 : i32 +! NSW: %[[K_END:.*]] = arith.constant 300 : i32 +! NSW: %[[K_STEP:.*]] = arith.constant 1 : i32 +! NSW: %[[TMP3:.*]] = arith.subi %[[K_END]], %[[K_START]] : i32 +! NSW: %[[TMP4:.*]] = arith.addi %[[TMP3]], %[[K_STEP]] : i32 +! NSW: %[[TRIP_COUNT_K:.*]] = arith.divsi %[[TMP4]], %[[K_STEP]] : i32 +! NSW: fir.store %[[TRIP_COUNT_K]] to %[[TRIP_VAR_K_REF]] : !fir.ref +! NSW: fir.store %[[K_START]] to %[[LOOP_VAR_K_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER_K:.*]] +! NSW: ^[[HEADER_K]]: +! NSW: %[[TRIP_VAR_K:.*]] = fir.load %[[TRIP_VAR_K_REF]] : !fir.ref +! NSW: %[[ZERO_2:.*]] = arith.constant 0 : i32 +! NSW: %[[COND_K:.*]] = arith.cmpi sgt, %[[TRIP_VAR_K]], %[[ZERO_2]] : i32 +! NSW: cf.cond_br %[[COND_K]], ^[[BODY_K:.*]], ^[[EXIT_K:.*]] +! NSW: ^[[BODY_K]]: +! NSW: %[[TRIP_VAR_K:.*]] = fir.load %[[TRIP_VAR_K_REF]] : !fir.ref +! NSW: %[[ONE_1:.*]] = arith.constant 1 : i32 +! NSW: %[[TRIP_VAR_K_NEXT:.*]] = arith.subi %[[TRIP_VAR_K]], %[[ONE_1]] : i32 +! NSW: fir.store %[[TRIP_VAR_K_NEXT]] to %[[TRIP_VAR_K_REF]] : !fir.ref +! NSW: %[[LOOP_VAR_K:.*]] = fir.load %[[LOOP_VAR_K_REF]] : !fir.ref +! NSW: %[[K_STEP_2:.*]] = arith.constant 1 : i32 +! NSW: %[[LOOP_VAR_K_NEXT:.*]] = arith.addi %[[LOOP_VAR_K]], %[[K_STEP_2]] overflow : i32 +! NSW: fir.store %[[LOOP_VAR_K_NEXT]] to %[[LOOP_VAR_K_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER_K]] +! NSW: ^[[EXIT_K]]: +! NSW: %[[TRIP_VAR_J:.*]] = fir.load %[[TRIP_VAR_J_REF]] : !fir.ref +! NSW: %[[ONE_1:.*]] = arith.constant 1 : i32 +! NSW: %[[TRIP_VAR_J_NEXT:.*]] = arith.subi %[[TRIP_VAR_J]], %[[ONE_1]] : i32 +! NSW: fir.store %[[TRIP_VAR_J_NEXT]] to %[[TRIP_VAR_J_REF]] : !fir.ref +! NSW: %[[LOOP_VAR_J:.*]] = fir.load %[[LOOP_VAR_J_REF]] : !fir.ref +! NSW: %[[J_STEP_2:.*]] = arith.constant 1 : i32 +! NSW: %[[LOOP_VAR_J_NEXT:.*]] = arith.addi %[[LOOP_VAR_J]], %[[J_STEP_2]] overflow : i32 +! NSW: fir.store %[[LOOP_VAR_J_NEXT]] to %[[LOOP_VAR_J_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER_J]] +! NSW: ^[[EXIT_J]]: +! NSW: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref +! NSW: %[[ONE_1:.*]] = arith.constant 1 : i32 +! NSW: %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[ONE_1]] : i32 +! NSW: fir.store %[[TRIP_VAR_I_NEXT]] to %[[TRIP_VAR_I_REF]] : !fir.ref +! NSW: %[[LOOP_VAR_I:.*]] = fir.load %[[LOOP_VAR_I_REF]] : !fir.ref +! NSW: %[[I_STEP_2:.*]] = arith.constant 1 : i32 +! NSW: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %[[I_STEP_2]] overflow : i32 +! NSW: fir.store %[[LOOP_VAR_I_NEXT]] to %[[LOOP_VAR_I_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER_I]] +! NSW: ^[[EXIT_I]]: +! NSW: return + ! Test the existence of a structured loop inside an unstructured loop. ! Only minimal checks are inserted for the structured loop. subroutine nested_structured_in_unstructured() @@ -211,9 +356,12 @@ end subroutine ! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]] ! CHECK: ^[[BODY]]: ! CHECK: %{{.*}} = fir.do_loop %[[J_INDEX:[^ ]*]] = -! CHECK-SAME: %{{.*}} to %{{.*}} step %{{[^ ]*}} +! CHECK-SAME: %{{.*}} to %{{.*}} step %[[ST:[^ ]*]] ! CHECK-SAME: iter_args(%[[J_IV:.*]] = %{{.*}}) -> (index, i32) { ! CHECK: fir.store %[[J_IV]] to %[[LOOP_VAR_J_REF]] : !fir.ref +! CHECK: %[[J_INDEX_NEXT:.*]] = arith.addi %[[J_INDEX]], %[[ST]] : index +! CHECK: %[[LOOP_VAR_J:.*]] = fir.load %[[LOOP_VAR_J_REF]] : !fir.ref +! CHECK: %[[LOOP_VAR_J_NEXT:.*]] = arith.addi %[[LOOP_VAR_J]], %{{[^ ]*}} : i32 ! CHECK: } ! CHECK: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref ! CHECK: %[[C1_3:.*]] = arith.constant 1 : i32 @@ -226,3 +374,42 @@ end subroutine ! CHECK: cf.br ^[[HEADER]] ! CHECK: ^[[EXIT]]: ! CHECK: return + +! NSW-LABEL: nested_structured_in_unstructured +! NSW: %[[TRIP_VAR_I_REF:.*]] = fir.alloca i32 +! NSW: %[[LOOP_VAR_I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFnested_structured_in_unstructuredEi"} +! NSW: %[[LOOP_VAR_J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFnested_structured_in_unstructuredEj"} +! NSW: %[[I_START:.*]] = arith.constant 1 : i32 +! NSW: %[[I_END:.*]] = arith.constant 100 : i32 +! NSW: %[[I_STEP:.*]] = arith.constant 1 : i32 +! NSW: %[[TMP1:.*]] = arith.subi %[[I_END]], %[[I_START]] : i32 +! NSW: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[I_STEP]] : i32 +! NSW: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[I_STEP]] : i32 +! NSW: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_I_REF]] : !fir.ref +! NSW: fir.store %[[I_START]] to %[[LOOP_VAR_I_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER:.*]] +! NSW: ^[[HEADER]]: +! NSW: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref +! NSW: %[[ZERO:.*]] = arith.constant 0 : i32 +! NSW: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32 +! NSW: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]] +! NSW: ^[[BODY]]: +! NSW: %{{.*}} = fir.do_loop %[[J_INDEX:[^ ]*]] = +! NSW-SAME: %{{.*}} to %{{.*}} step %[[ST:[^ ]*]] +! NSW-SAME: iter_args(%[[J_IV:.*]] = %{{.*}}) -> (index, i32) { +! NSW: fir.store %[[J_IV]] to %[[LOOP_VAR_J_REF]] : !fir.ref +! NSW: %[[J_INDEX_NEXT:.*]] = arith.addi %[[J_INDEX]], %[[ST]] overflow : index +! NSW: %[[LOOP_VAR_J:.*]] = fir.load %[[LOOP_VAR_J_REF]] : !fir.ref +! NSW: %[[LOOP_VAR_J_NEXT:.*]] = arith.addi %[[LOOP_VAR_J]], %{{[^ ]*}} overflow : i32 +! NSW: } +! NSW: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref +! NSW: %[[C1_3:.*]] = arith.constant 1 : i32 +! NSW: %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[C1_3]] : i32 +! NSW: fir.store %[[TRIP_VAR_I_NEXT]] to %[[TRIP_VAR_I_REF]] : !fir.ref +! NSW: %[[LOOP_VAR_I:.*]] = fir.load %[[LOOP_VAR_I_REF]] : !fir.ref +! NSW: %[[I_STEP_2:.*]] = arith.constant 1 : i32 +! NSW: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %[[I_STEP_2]] overflow : i32 +! NSW: fir.store %[[LOOP_VAR_I_NEXT]] to %[[LOOP_VAR_I_REF]] : !fir.ref +! NSW: cf.br ^[[HEADER]] +! NSW: ^[[EXIT]]: +! NSW: return diff --git a/flang/test/Lower/infinite_loop.f90 b/flang/test/Lower/infinite_loop.f90 index 0450e2c4485f..6942dda8d7a2 100644 --- a/flang/test/Lower/infinite_loop.f90 +++ b/flang/test/Lower/infinite_loop.f90 @@ -1,5 +1,6 @@ ! RUN: bbc -emit-fir -hlfir=false -o - %s | FileCheck %s ! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -o - %s | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -flang-experimental-integer-overflow -o - %s | FileCheck %s --check-prefix=NSW ! Tests for infinite loop. @@ -106,6 +107,39 @@ end subroutine ! CHECK: ^[[RETURN]]: ! CHECK: return +! NSW-LABEL: structured_loop_in_infinite +! NSW-SAME: %[[I_REF:.*]]: !fir.ref +! NSW: %[[J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFstructured_loop_in_infiniteEj"} +! NSW: cf.br ^[[BODY1:.*]] +! NSW: ^[[BODY1]]: +! NSW: %[[I:.*]] = fir.load %[[I_REF]] : !fir.ref +! NSW: %[[C100:.*]] = arith.constant 100 : i32 +! NSW: %[[COND:.*]] = arith.cmpi sgt, %[[I]], %[[C100]] : i32 +! NSW: cf.cond_br %[[COND]], ^[[EXIT:.*]], ^[[BODY2:.*]] +! NSW: ^[[EXIT]]: +! NSW: cf.br ^[[RETURN:.*]] +! NSW: ^[[BODY2:.*]]: +! NSW: %[[C1:.*]] = arith.constant 1 : i32 +! NSW: %[[C1_INDEX:.*]] = fir.convert %[[C1]] : (i32) -> index +! NSW: %[[C10:.*]] = arith.constant 10 : i32 +! NSW: %[[C10_INDEX:.*]] = fir.convert %[[C10]] : (i32) -> index +! NSW: %[[C1_1:.*]] = arith.constant 1 : index +! NSW: %[[J_LB:.*]] = fir.convert %[[C1_INDEX]] : (index) -> i32 +! NSW: %[[J_FINAL:.*]]:2 = fir.do_loop %[[J:[^ ]*]] = +! NSW-SAME: %[[C1_INDEX]] to %[[C10_INDEX]] step %[[C1_1]] +! NSW-SAME: iter_args(%[[J_IV:.*]] = %[[J_LB]]) -> (index, i32) { +! NSW: fir.store %[[J_IV]] to %[[J_REF]] : !fir.ref +! NSW: %[[J_NEXT:.*]] = arith.addi %[[J]], %[[C1_1]] overflow : index +! NSW: %[[J_STEPCAST:.*]] = fir.convert %[[C1_1]] : (index) -> i32 +! NSW: %[[J_IVLOAD:.*]] = fir.load %[[J_REF]] : !fir.ref +! NSW: %[[J_IVINC:.*]] = arith.addi %[[J_IVLOAD]], %[[J_STEPCAST]] overflow : i32 +! NSW: fir.result %[[J_NEXT]], %[[J_IVINC]] : index, i32 +! NSW: } +! NSW: fir.store %[[J_FINAL]]#1 to %[[J_REF]] : !fir.ref +! NSW: cf.br ^[[BODY1]] +! NSW: ^[[RETURN]]: +! NSW: return + subroutine empty_infinite_in_while(i) integer :: i do while (i .gt. 50) diff --git a/flang/test/Lower/io-implied-do-fixes.f90 b/flang/test/Lower/io-implied-do-fixes.f90 index a309efa17f12..a6c115fa80de 100644 --- a/flang/test/Lower/io-implied-do-fixes.f90 +++ b/flang/test/Lower/io-implied-do-fixes.f90 @@ -1,4 +1,5 @@ ! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s +! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false -integer-overflow %s -o - | FileCheck %s --check-prefix=NSW ! UNSUPPORTED: system-windows ! CHECK-LABEL: func @_QPido1 @@ -7,9 +8,23 @@ ! CHECK: %[[J_VAL_FINAL:.*]] = fir.do_loop %[[J_VAL:.*]] = %{{.*}} to %{{.*}} step %{{.*}} -> index { ! CHECK: %[[J_VAL_CVT1:.*]] = fir.convert %[[J_VAL]] : (index) -> i32 ! CHECK: fir.store %[[J_VAL_CVT1]] to %[[J_ADDR]] : !fir.ptr +! CHECK: %[[J_VAL_NEXT:.*]] = arith.addi %[[J_VAL]], %{{[^ ]*}} : index +! CHECK: fir.result %[[J_VAL_NEXT]] : index ! CHECK: } ! CHECK: %[[J_VAL_CVT2:.*]] = fir.convert %[[J_VAL_FINAL]] : (index) -> i32 ! CHECK: fir.store %[[J_VAL_CVT2]] to %[[J_ADDR]] : !fir.ptr + +! NSW-LABEL: func @_QPido1 +! NSW: %[[J_REF_ADDR:.*]] = fir.alloca !fir.ptr {uniq_name = "_QFido1Eiptr.addr"} +! NSW: %[[J_ADDR:.*]] = fir.load %[[J_REF_ADDR]] : !fir.ref> +! NSW: %[[J_VAL_FINAL:.*]] = fir.do_loop %[[J_VAL:.*]] = %{{.*}} to %{{.*}} step %{{.*}} -> index { +! NSW: %[[J_VAL_CVT1:.*]] = fir.convert %[[J_VAL]] : (index) -> i32 +! NSW: fir.store %[[J_VAL_CVT1]] to %[[J_ADDR]] : !fir.ptr +! NSW: %[[J_VAL_NEXT:.*]] = arith.addi %[[J_VAL]], %{{[^ ]*}} overflow : index +! NSW: fir.result %[[J_VAL_NEXT]] : index +! NSW: } +! NSW: %[[J_VAL_CVT2:.*]] = fir.convert %[[J_VAL_FINAL]] : (index) -> i32 +! NSW: fir.store %[[J_VAL_CVT2]] to %[[J_ADDR]] : !fir.ptr subroutine ido1 integer, pointer :: iptr integer, target :: itgt @@ -23,9 +38,23 @@ end subroutine ! CHECK: %[[J_VAL_FINAL:.*]] = fir.do_loop %[[J_VAL:.*]] = %{{.*}} to %{{.*}} step %{{.*}} -> index { ! CHECK: %[[J_VAL_CVT1:.*]] = fir.convert %[[J_VAL]] : (index) -> i32 ! CHECK: fir.store %[[J_VAL_CVT1]] to %[[J_ADDR]] : !fir.heap +! CHECK: %[[J_VAL_NEXT:.*]] = arith.addi %[[J_VAL]], %{{[^ ]*}} : index +! CHECK: fir.result %[[J_VAL_NEXT]] : index ! CHECK: } ! CHECK: %[[J_VAL_CVT2:.*]] = fir.convert %[[J_VAL_FINAL]] : (index) -> i32 ! CHECK: fir.store %[[J_VAL_CVT2]] to %[[J_ADDR]] : !fir.heap + +! NSW-LABEL: func @_QPido2 +! NSW: %[[J_REF_ADDR:.*]] = fir.alloca !fir.heap {uniq_name = "_QFido2Eiptr.addr"} +! NSW: %[[J_ADDR:.*]] = fir.load %[[J_REF_ADDR]] : !fir.ref> +! NSW: %[[J_VAL_FINAL:.*]] = fir.do_loop %[[J_VAL:.*]] = %{{.*}} to %{{.*}} step %{{.*}} -> index { +! NSW: %[[J_VAL_CVT1:.*]] = fir.convert %[[J_VAL]] : (index) -> i32 +! NSW: fir.store %[[J_VAL_CVT1]] to %[[J_ADDR]] : !fir.heap +! NSW: %[[J_VAL_NEXT:.*]] = arith.addi %[[J_VAL]], %{{[^ ]*}} overflow : index +! NSW: fir.result %[[J_VAL_NEXT]] : index +! NSW: } +! NSW: %[[J_VAL_CVT2:.*]] = fir.convert %[[J_VAL_FINAL]] : (index) -> i32 +! NSW: fir.store %[[J_VAL_CVT2]] to %[[J_ADDR]] : !fir.heap subroutine ido2 integer, allocatable :: iptr allocate(iptr) @@ -35,12 +64,32 @@ end subroutine ! CHECK-LABEL: func @_QPido3 ! CHECK: %[[J_REF_ADDR:.*]] = fir.alloca !fir.heap {uniq_name = "_QFido3Ej.addr"} ! CHECK: %[[J_ADDR:.*]] = fir.load %[[J_REF_ADDR]] : !fir.ref> -! CHECK: %[[J_VAL_FINAL:.*]]:2 = fir.iterate_while (%[[J_VAL:.*]] = %{{.*}} to %{{.*}} step %{{.*}}) and ({{.*}}) -> (index, i1) { +! CHECK: %[[J_VAL_FINAL:.*]]:2 = fir.iterate_while (%[[J_VAL:.*]] = %{{.*}} to %{{.*}} step %{{.*}}) and (%[[OK:.*]] = {{.*}}) -> (index, i1) { ! CHECK: %[[J_VAL_CVT1:.*]] = fir.convert %[[J_VAL]] : (index) -> i32 ! CHECK: fir.store %[[J_VAL_CVT1]] to %[[J_ADDR]] : !fir.heap +! CHECK: %[[RES:.*]] = fir.if %[[OK]] -> (i1) { +! CHECK: } +! CHECK: %[[J_VAL_INC:.*]] = arith.addi %[[J_VAL]], %{{[^ ]*}} : index +! CHECK: %[[J_VAL_NEXT:.*]] = arith.select %[[RES]], %[[J_VAL_INC]], %[[J_VAL]] : index +! CHECK: fir.result %[[J_VAL_NEXT]], %[[RES]] : index, i1 ! CHECK: } ! CHECK: %[[J_VAL_CVT2:.*]] = fir.convert %[[J_VAL_FINAL]]#0 : (index) -> i32 ! CHECK: fir.store %[[J_VAL_CVT2]] to %[[J_ADDR]] : !fir.heap {uniq_name = "_QFido3Ej.addr"} +! NSW: %[[J_ADDR:.*]] = fir.load %[[J_REF_ADDR]] : !fir.ref> +! NSW: %[[J_VAL_FINAL:.*]]:2 = fir.iterate_while (%[[J_VAL:.*]] = %{{.*}} to %{{.*}} step %{{.*}}) and (%[[OK:.*]] = {{.*}}) -> (index, i1) { +! NSW: %[[J_VAL_CVT1:.*]] = fir.convert %[[J_VAL]] : (index) -> i32 +! NSW: fir.store %[[J_VAL_CVT1]] to %[[J_ADDR]] : !fir.heap +! NSW: %[[RES:.*]] = fir.if %[[OK]] -> (i1) { +! NSW: } +! NSW: %[[J_VAL_INC:.*]] = arith.addi %[[J_VAL]], %{{[^ ]*}} overflow : index +! NSW: %[[J_VAL_NEXT:.*]] = arith.select %[[RES]], %[[J_VAL_INC]], %[[J_VAL]] : index +! NSW: fir.result %[[J_VAL_NEXT]], %[[RES]] : index, i1 +! NSW: } +! NSW: %[[J_VAL_CVT2:.*]] = fir.convert %[[J_VAL_FINAL]]#0 : (index) -> i32 +! NSW: fir.store %[[J_VAL_CVT2]] to %[[J_ADDR]] : !fir.heap llvm::cl::desc("Override host target triple"), llvm::cl::init("")); +static llvm::cl::opt + setNSW("integer-overflow", + llvm::cl::desc("add nsw flag to internal operations"), + llvm::cl::init(false)); + #define FLANG_EXCLUDE_CODEGEN #include "flang/Tools/CLOptions.inc" @@ -355,6 +360,7 @@ static mlir::LogicalResult convertFortranSourceToMLIR( Fortran::lower::LoweringOptions loweringOptions{}; loweringOptions.setNoPPCNativeVecElemOrder(enableNoPPCNativeVecElemOrder); loweringOptions.setLowerToHighLevelFIR(useHLFIR || emitHLFIR); + loweringOptions.setNSWOnLoopVarInc(setNSW); std::vector envDefaults = {}; auto burnside = Fortran::lower::LoweringBridge::create( ctx, semanticsContext, defKinds, semanticsContext.intrinsics(), @@ -432,6 +438,7 @@ static mlir::LogicalResult convertFortranSourceToMLIR( // Add O2 optimizer pass pipeline. MLIRToLLVMPassPipelineConfig config(llvm::OptimizationLevel::O2); + config.NSWOnLoopVarInc = setNSW; fir::registerDefaultInlinerPass(config); fir::createDefaultFIROptimizerPassPipeline(pm, config); } -- GitLab From 3cc445a6608dc0e88f7d5f16501ef827199cf0c4 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 15 May 2024 21:40:58 -0700 Subject: [PATCH 454/578] [MCAsmParser] Simplify expandMacro The error checking is only for .macro directives. Move it to the .macro parser to remove one parameter. --- llvm/lib/MC/MCParser/AsmParser.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 009465d11d78..33287c6529ca 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -295,10 +295,9 @@ private: void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, ArrayRef Parameters); - bool expandMacro(raw_svector_ostream &OS, StringRef Body, + bool expandMacro(raw_svector_ostream &OS, const MCAsmMacro &Macro, ArrayRef Parameters, - ArrayRef A, bool EnableAtPseudoVariable, - SMLoc L); + ArrayRef A, bool EnableAtPseudoVariable); /// Are macros enabled in the parser? bool areMacrosEnabled() {return MacrosEnabledFlag;} @@ -2496,17 +2495,16 @@ static bool isIdentifierChar(char c) { c == '.'; } -bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, +bool AsmParser::expandMacro(raw_svector_ostream &OS, const MCAsmMacro &Macro, ArrayRef Parameters, ArrayRef A, - bool EnableAtPseudoVariable, SMLoc L) { + bool EnableAtPseudoVariable) { unsigned NParameters = Parameters.size(); bool HasVararg = NParameters ? Parameters.back().Vararg : false; - if ((!IsDarwin || NParameters != 0) && NParameters != A.size()) - return Error(L, "Wrong number of arguments"); // A macro without parameters is handled differently on Darwin: // gas accepts no arguments and does no substitutions + StringRef Body = Macro.Body; while (!Body.empty()) { // Scan for the next substitution. std::size_t End = Body.size(), Pos = 0; @@ -2882,10 +2880,11 @@ bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { // Macro instantiation is lexical, unfortunately. We construct a new buffer // to hold the macro body with substitutions. SmallString<256> Buf; - StringRef Body = M->Body; raw_svector_ostream OS(Buf); - if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc())) + if ((!IsDarwin || M->Parameters.size()) && M->Parameters.size() != A.size()) + return Error(getTok().getLoc(), "Wrong number of arguments"); + if (expandMacro(OS, *M, M->Parameters, A, true)) return true; // We include the .endmacro in the buffer as our cue to exit the macro @@ -5694,8 +5693,7 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) { raw_svector_ostream OS(Buf); while (Count--) { // Note that the AtPseudoVariable is disabled for instantiations of .rep(t). - if (expandMacro(OS, M->Body, std::nullopt, std::nullopt, false, - getTok().getLoc())) + if (expandMacro(OS, *M, std::nullopt, std::nullopt, false)) return true; } instantiateMacroLikeBody(M, DirectiveLoc, OS); @@ -5726,7 +5724,7 @@ bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { for (const MCAsmMacroArgument &Arg : A) { // Note that the AtPseudoVariable is enabled for instantiations of .irp. // This is undocumented, but GAS seems to support it. - if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc())) + if (expandMacro(OS, *M, Parameter, Arg, true)) return true; } @@ -5768,7 +5766,7 @@ bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) { // Note that the AtPseudoVariable is enabled for instantiations of .irpc. // This is undocumented, but GAS seems to support it. - if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc())) + if (expandMacro(OS, *M, Parameter, Arg, true)) return true; } -- GitLab From 245b7b65cb341ac5499fabf62f28fdbbc39bc7d7 Mon Sep 17 00:00:00 2001 From: jiajie zhang <56027356+JumpMasterJJ@users.noreply.github.com> Date: Thu, 16 May 2024 12:42:01 +0800 Subject: [PATCH 455/578] [flang] Add ETIME runtime and lowering intrinsics implementation (#90578) This patch add support of intrinsics GNU extension ETIME https://github.com/llvm/llvm-project/issues/84205. Some usage info and example has been added to `flang/docs/Intrinsics.md`. The patch contains both the lowering and the runtime code and works on both Windows and Linux. | System | Implmentation | |-----------|--------------------| | Windows| GetProcessTimes | | Linux |times | --- etime-function.mlir | 25 +++++ flang/docs/Intrinsics.md | 52 ++++++++++ .../flang/Optimizer/Builder/IntrinsicCall.h | 12 ++- .../Optimizer/Builder/Runtime/Intrinsics.h | 2 + flang/include/flang/Runtime/time-intrinsic.h | 3 + flang/lib/Evaluate/intrinsics.cpp | 26 ++++- flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 99 +++++++++++++++++++ .../Optimizer/Builder/Runtime/Intrinsics.cpp | 14 +++ flang/runtime/time-intrinsic.cpp | 70 ++++++++++++- flang/runtime/tools.h | 9 ++ .../test/Lower/Intrinsics/etime-function.f90 | 24 +++++ flang/test/Lower/Intrinsics/etime.f90 | 21 ++++ flang/test/Semantics/etime.f90 | 30 ++++++ 13 files changed, 382 insertions(+), 5 deletions(-) create mode 100644 etime-function.mlir create mode 100644 flang/test/Lower/Intrinsics/etime-function.f90 create mode 100644 flang/test/Lower/Intrinsics/etime.f90 create mode 100644 flang/test/Semantics/etime.f90 diff --git a/etime-function.mlir b/etime-function.mlir new file mode 100644 index 000000000000..740dfd4866aa --- /dev/null +++ b/etime-function.mlir @@ -0,0 +1,25 @@ +module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<4xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry, dense<32> : vector<4xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry, dense<64> : vector<4xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry, dense<32> : vector<4xi64>>, #dlti.dl_entry<"dlti.endianness", "little">, #dlti.dl_entry<"dlti.stack_alignment", 128 : i64>>, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.target_triple = "x86_64-unknown-linux-gnu"} { + func.func @_QPetime_test(%arg0: !fir.ref> {fir.bindc_name = "values"}, %arg1: !fir.ref {fir.bindc_name = "time"}) { + %c9_i32 = arith.constant 9 : i32 + %c2 = arith.constant 2 : index + %0 = fir.alloca f32 + %1 = fir.declare %arg1 {uniq_name = "_QFetime_testEtime"} : (!fir.ref) -> !fir.ref + %2 = fir.shape %c2 : (index) -> !fir.shape<1> + %3 = fir.declare %arg0(%2) {uniq_name = "_QFetime_testEvalues"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + %4 = fir.embox %3(%2) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + %5 = fir.embox %0 : (!fir.ref) -> !fir.box + %6 = fir.address_of(@_QQclX116781708dcf8f012d7ec1e40d743d97) : !fir.ref> + %7 = fir.convert %4 : (!fir.box>) -> !fir.box + %8 = fir.convert %5 : (!fir.box) -> !fir.box + %9 = fir.convert %6 : (!fir.ref>) -> !fir.ref + %10 = fir.call @_FortranAEtime(%7, %8, %9, %c9_i32) fastmath : (!fir.box, !fir.box, !fir.ref, i32) -> none + %11 = fir.load %0 : !fir.ref + fir.store %11 to %1 : !fir.ref + return + } + func.func private @_FortranAEtime(!fir.box, !fir.box, !fir.ref, i32) -> none attributes {fir.runtime} + fir.global linkonce @_QQclX116781708dcf8f012d7ec1e40d743d97 constant : !fir.char<1,71> { + %0 = fir.string_lit "/home/jump/llvm-project/flang/test/Lower/Intrinsics/etime-function.f90\00"(71) : !fir.char<1,71> + fir.has_value %0 : !fir.char<1,71> + } +} diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md index 848619cb65d9..41129b10083b 100644 --- a/flang/docs/Intrinsics.md +++ b/flang/docs/Intrinsics.md @@ -916,3 +916,55 @@ used in constant expressions have currently no folding support at all. - If a condition occurs that would assign a nonzero value to `CMDSTAT` but the `CMDSTAT` variable is not present, error termination is initiated. - On POSIX-compatible systems, the child process (async process) will be terminated with no effect on the parent process (continues). - On Windows, error termination is not initiated. + +### Non-Standard Intrinsics: ETIME + +#### Description +`ETIME(VALUES, TIME)` returns the number of seconds of runtime since the start of the process’s execution in *TIME*. *VALUES* returns the user and system components of this time in `VALUES(1)` and `VALUES(2)` respectively. *TIME* is equal to `VALUES(1) + VALUES(2)`. + +On some systems, the underlying timings are represented using types with sufficiently small limits that overflows (wrap around) are possible, such as 32-bit types. Therefore, the values returned by this intrinsic might be, or become, negative, or numerically less than previous values, during a single run of the compiled program. + +This intrinsic is provided in both subroutine and function forms; however, only one form can be used in any given program unit. + +*VALUES* and *TIME* are `INTENT(OUT)` and provide the following: + + +| | | +|---------------|-----------------------------------| +| `VALUES(1)` | User time in seconds. | +| `VALUES(2)` | System time in seconds. | +| `TIME` | Run time since start in seconds. | + +#### Usage and Info + +- **Standard:** GNU extension +- **Class:** Subroutine, function +- **Syntax:** `CALL ETIME(VALUES, TIME)` +- **Arguments:** +- **Return value** Elapsed time in seconds since the start of program execution. + +| Argument | Description | +|------------|-----------------------------------------------------------------------| +| `VALUES` | The type shall be REAL(4), DIMENSION(2). | +| `TIME` | The type shall be REAL(4). | + +#### Example +Here is an example usage from [Gfortran ETIME](https://gcc.gnu.org/onlinedocs/gfortran/ETIME.html) +```Fortran +program test_etime + integer(8) :: i, j + real, dimension(2) :: tarray + real :: result + call ETIME(tarray, result) + print *, result + print *, tarray(1) + print *, tarray(2) + do i=1,100000000 ! Just a delay + j = i * i - i + end do + call ETIME(tarray, result) + print *, result + print *, tarray(1) + print *, tarray(2) +end program test_etime +``` \ No newline at end of file diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index b7d060926761..977a69af5281 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -222,6 +222,8 @@ struct IntrinsicLibrary { fir::ExtendedValue genEoshift(mlir::Type, llvm::ArrayRef); void genExit(llvm::ArrayRef); void genExecuteCommandLine(mlir::ArrayRef args); + fir::ExtendedValue genEtime(std::optional, + mlir::ArrayRef args); mlir::Value genExponent(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genExtendsTypeOf(mlir::Type, llvm::ArrayRef); @@ -400,8 +402,10 @@ struct IntrinsicLibrary { using ElementalGenerator = decltype(&IntrinsicLibrary::genAbs); using ExtendedGenerator = decltype(&IntrinsicLibrary::genLenTrim); using SubroutineGenerator = decltype(&IntrinsicLibrary::genDateAndTime); - using Generator = - std::variant; + /// The generator for intrinsic that has both function and subroutine form. + using DualGenerator = decltype(&IntrinsicLibrary::genEtime); + using Generator = std::variant; /// All generators can be outlined. This will build a function named /// "fir."+ + "." + and generate the @@ -442,6 +446,10 @@ struct IntrinsicLibrary { llvm::ArrayRef args); mlir::Value invokeGenerator(SubroutineGenerator generator, llvm::ArrayRef args); + mlir::Value invokeGenerator(DualGenerator generator, + llvm::ArrayRef args); + mlir::Value invokeGenerator(DualGenerator generator, mlir::Type resultType, + llvm::ArrayRef args); /// Get pointer to unrestricted intrinsic. Generate the related unrestricted /// intrinsic if it is not defined yet. diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h index 737c631e45c1..7497a4bc3564 100644 --- a/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h @@ -44,6 +44,8 @@ void genDateAndTime(fir::FirOpBuilder &, mlir::Location, std::optional date, std::optional time, std::optional zone, mlir::Value values); +void genEtime(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value values, mlir::Value time); void genRandomInit(fir::FirOpBuilder &, mlir::Location, mlir::Value repeatable, mlir::Value imageDistinct); diff --git a/flang/include/flang/Runtime/time-intrinsic.h b/flang/include/flang/Runtime/time-intrinsic.h index 650c02436ee4..80490a17e455 100644 --- a/flang/include/flang/Runtime/time-intrinsic.h +++ b/flang/include/flang/Runtime/time-intrinsic.h @@ -43,6 +43,9 @@ void RTNAME(DateAndTime)(char *date, std::size_t dateChars, char *time, const char *source = nullptr, int line = 0, const Descriptor *values = nullptr); +void RTNAME(Etime)(const Descriptor *values, const Descriptor *time, + const char *sourceFile, int line); + } // extern "C" } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_TIME_INTRINSIC_H_ diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 441a762c930d..ded277877f49 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -454,6 +454,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {"erf", {{"x", SameReal}}, SameReal}, {"erfc", {{"x", SameReal}}, SameReal}, {"erfc_scaled", {{"x", SameReal}}, SameReal}, + {"etime", + {{"values", TypePattern{RealType, KindCode::exactKind, 4}, Rank::vector, + Optionality::required, common::Intent::Out}}, + TypePattern{RealType, KindCode::exactKind, 4}}, {"exp", {{"x", SameFloating}}, SameFloating}, {"exp", {{"x", SameFloating}}, SameFloating}, {"exponent", {{"x", AnyReal}}, DefaultInt}, @@ -1342,6 +1346,12 @@ static const IntrinsicInterface intrinsicSubroutine[]{ {"values", AnyInt, Rank::vector, Optionality::optional, common::Intent::Out}}, {}, Rank::elemental, IntrinsicClass::impureSubroutine}, + {"etime", + {{"values", TypePattern{RealType, KindCode::exactKind, 4}, Rank::vector, + Optionality::required, common::Intent::Out}, + {"time", TypePattern{RealType, KindCode::exactKind, 4}, + Rank::scalar, Optionality::required, common::Intent::Out}}, + {}, Rank::elemental, IntrinsicClass::impureSubroutine}, {"execute_command_line", {{"command", DefaultChar, Rank::scalar}, {"wait", AnyLogical, Rank::scalar, Optionality::optional}, @@ -2484,6 +2494,7 @@ public: bool IsIntrinsic(const std::string &) const; bool IsIntrinsicFunction(const std::string &) const; bool IsIntrinsicSubroutine(const std::string &) const; + bool IsDualIntrinsic(const std::string &) const; IntrinsicClass GetIntrinsicClass(const std::string &) const; std::string GetGenericIntrinsicName(const std::string &) const; @@ -2545,6 +2556,17 @@ bool IntrinsicProcTable::Implementation::IsIntrinsic( const std::string &name) const { return IsIntrinsicFunction(name) || IsIntrinsicSubroutine(name); } +bool IntrinsicProcTable::Implementation::IsDualIntrinsic( + const std::string &name) const { + // Collection for some intrinsics with function and subroutine form, + // in order to pass the semantic check. + static const std::string dualIntrinsic[]{{"etime"}}; + + return std::find_if(std::begin(dualIntrinsic), std::end(dualIntrinsic), + [&name](const std::string &dualName) { + return dualName == name; + }) != std::end(dualIntrinsic); +} IntrinsicClass IntrinsicProcTable::Implementation::GetIntrinsicClass( const std::string &name) const { @@ -3083,7 +3105,7 @@ std::optional IntrinsicProcTable::Implementation::Probe( return specificCall; } } - if (IsIntrinsicFunction(call.name)) { + if (IsIntrinsicFunction(call.name) && !IsDualIntrinsic(call.name)) { context.messages().Say( "Cannot use intrinsic function '%s' as a subroutine"_err_en_US, call.name); @@ -3218,7 +3240,7 @@ std::optional IntrinsicProcTable::Implementation::Probe( } if (specificBuffer.empty() && genericBuffer.empty() && - IsIntrinsicSubroutine(call.name)) { + IsIntrinsicSubroutine(call.name) && !IsDualIntrinsic(call.name)) { context.messages().Say( "Cannot use intrinsic subroutine '%s' as a function"_err_en_US, call.name); diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index 58064d23eb08..ae7e65098744 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -35,6 +35,7 @@ #include "flang/Optimizer/Builder/Runtime/Stop.h" #include "flang/Optimizer/Builder/Runtime/Transformational.h" #include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Dialect/Support/FIRContext.h" #include "flang/Optimizer/Support/FatalError.h" @@ -49,6 +50,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include #include #define DEBUG_TYPE "flang-lower-intrinsic" @@ -222,6 +224,10 @@ static constexpr IntrinsicHandler handlers[]{ {"boundary", asBox, handleDynamicOptional}, {"dim", asValue}}}, /*isElemental=*/false}, + {"etime", + &I::genEtime, + {{{"values", asBox}, {"time", asBox}}}, + /*isElemental=*/false}, {"execute_command_line", &I::genExecuteCommandLine, {{{"command", asBox}, @@ -1682,6 +1688,24 @@ IntrinsicLibrary::genElementalCall( return mlir::Value(); } +template <> +fir::ExtendedValue +IntrinsicLibrary::genElementalCall( + DualGenerator generator, llvm::StringRef name, mlir::Type resultType, + llvm::ArrayRef args, bool outline) { + assert(resultType.getImpl() && "expect elemental intrinsic to be functions"); + + for (const fir::ExtendedValue &arg : args) + if (!arg.getUnboxed() && !arg.getCharBox()) + // fir::emitFatalError(loc, "nonscalar intrinsic argument"); + crashOnMissingIntrinsic(loc, name); + if (outline) + return outlineInExtendedWrapper(generator, name, resultType, args); + + return std::invoke(generator, *this, std::optional{resultType}, + args); +} + static fir::ExtendedValue invokeHandler(IntrinsicLibrary::ElementalGenerator generator, const IntrinsicHandler &handler, @@ -1725,6 +1749,22 @@ invokeHandler(IntrinsicLibrary::SubroutineGenerator generator, return mlir::Value{}; } +static fir::ExtendedValue +invokeHandler(IntrinsicLibrary::DualGenerator generator, + const IntrinsicHandler &handler, + std::optional resultType, + llvm::ArrayRef args, bool outline, + IntrinsicLibrary &lib) { + if (handler.isElemental) + return lib.genElementalCall(generator, handler.name, mlir::Type{}, args, + outline); + if (outline) + return lib.outlineInExtendedWrapper(generator, handler.name, resultType, + args); + + return std::invoke(generator, lib, resultType, args); +} + std::pair IntrinsicLibrary::genIntrinsicCall(llvm::StringRef specificName, std::optional resultType, @@ -1820,6 +1860,34 @@ IntrinsicLibrary::invokeGenerator(SubroutineGenerator generator, return {}; } +mlir::Value +IntrinsicLibrary::invokeGenerator(DualGenerator generator, + llvm::ArrayRef args) { + llvm::SmallVector extendedArgs; + for (mlir::Value arg : args) + extendedArgs.emplace_back(toExtendedValue(arg, builder, loc)); + std::invoke(generator, *this, std::optional{}, extendedArgs); + return {}; +} + +mlir::Value +IntrinsicLibrary::invokeGenerator(DualGenerator generator, + mlir::Type resultType, + llvm::ArrayRef args) { + llvm::SmallVector extendedArgs; + for (mlir::Value arg : args) + extendedArgs.emplace_back(toExtendedValue(arg, builder, loc)); + + if (resultType.getImpl() == nullptr) { + // TODO: + assert(false && "result type is null"); + } + + auto extendedResult = std::invoke( + generator, *this, std::optional{resultType}, extendedArgs); + return toValue(extendedResult, builder, loc); +} + //===----------------------------------------------------------------------===// // Intrinsic Procedure Mangling //===----------------------------------------------------------------------===// @@ -3235,6 +3303,37 @@ void IntrinsicLibrary::genExecuteCommandLine( exitstatBox, cmdstatBox, cmdmsgBox); } +// ETIME +fir::ExtendedValue +IntrinsicLibrary::genEtime(std::optional resultType, + llvm::ArrayRef args) { + assert((args.size() == 2 && !resultType.has_value()) || + (args.size() == 1 && resultType.has_value())); + + mlir::Value values = fir::getBase(args[0]); + if (resultType.has_value()) { + // function form + if (!values) + fir::emitFatalError(loc, "expected VALUES parameter"); + + auto timeAddr = builder.createTemporary(loc, *resultType); + auto timeBox = builder.createBox(loc, timeAddr); + fir::runtime::genEtime(builder, loc, values, timeBox); + return builder.create(loc, timeAddr); + } else { + // subroutine form + mlir::Value time = fir::getBase(args[1]); + if (!values) + fir::emitFatalError(loc, "expected VALUES parameter"); + if (!time) + fir::emitFatalError(loc, "expected TIME parameter"); + + fir::runtime::genEtime(builder, loc, values, time); + return {}; + } + return {}; +} + // EXIT void IntrinsicLibrary::genExit(llvm::ArrayRef args) { assert(args.size() == 1); diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp index 8b78a1688c73..3f36d639861b 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp @@ -106,6 +106,20 @@ void fir::runtime::genDateAndTime(fir::FirOpBuilder &builder, builder.create(loc, callee, args); } +void fir::runtime::genEtime(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value values, mlir::Value time) { + auto runtimeFunc = fir::runtime::getRuntimeFunc(loc, builder); + mlir::FunctionType runtimeFuncTy = runtimeFunc.getFunctionType(); + + mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); + mlir::Value sourceLine = + fir::factory::locationToLineNo(builder, loc, runtimeFuncTy.getInput(3)); + + llvm::SmallVector args = fir::runtime::createArguments( + builder, loc, runtimeFuncTy, values, time, sourceFile, sourceLine); + builder.create(loc, runtimeFunc, args); +} + void fir::runtime::genRandomInit(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value repeatable, mlir::Value imageDistinct) { diff --git a/flang/runtime/time-intrinsic.cpp b/flang/runtime/time-intrinsic.cpp index 68d63253139f..989d4f804c5f 100644 --- a/flang/runtime/time-intrinsic.cpp +++ b/flang/runtime/time-intrinsic.cpp @@ -19,8 +19,12 @@ #include #include #include -#ifndef _WIN32 +#ifdef _WIN32 +#include "flang/Common/windows-include.h" +#else #include // gettimeofday +#include +#include #endif // CPU_TIME (Fortran 2018 16.9.57) @@ -370,5 +374,69 @@ void RTNAME(DateAndTime)(char *date, std::size_t dateChars, char *time, terminator, date, dateChars, time, timeChars, zone, zoneChars, values); } +void RTNAME(Etime)(const Descriptor *values, const Descriptor *time, + const char *sourceFile, int line) { + Fortran::runtime::Terminator terminator{sourceFile, line}; + + double usrTime = -1.0, sysTime = -1.0, realTime = -1.0; + +#ifdef _WIN32 + FILETIME creationTime; + FILETIME exitTime; + FILETIME kernelTime; + FILETIME userTime; + + if (GetProcessTimes(GetCurrentProcess(), &creationTime, &exitTime, + &kernelTime, &userTime) == 0) { + ULARGE_INTEGER userSystemTime; + ULARGE_INTEGER kernelSystemTime; + + memcpy(&userSystemTime, &userTime, sizeof(FILETIME)); + memcpy(&kernelSystemTime, &kernelTime, sizeof(FILETIME)); + + usrTime = ((double)(userSystemTime.QuadPart)) / 10000000.0; + sysTime = ((double)(kernelSystemTime.QuadPart)) / 10000000.0; + realTime = usrTime + sysTime; + } +#else + struct tms tms; + if (times(&tms) != -1) { + usrTime = ((double)(tms.tms_utime)) / sysconf(_SC_CLK_TCK); + sysTime = ((double)(tms.tms_stime)) / sysconf(_SC_CLK_TCK); + realTime = usrTime + sysTime; + } +#endif + + if (values) { + auto typeCode{values->type().GetCategoryAndKind()}; + // ETIME values argument must have decimal range == 2. + RUNTIME_CHECK(terminator, + values->rank() == 1 && values->GetDimension(0).Extent() == 2 && + typeCode && typeCode->first == Fortran::common::TypeCategory::Real); + // Only accept KIND=4 here. + int kind{typeCode->second}; + RUNTIME_CHECK(terminator, kind == 4); + + ApplyFloatingPointKind( + kind, terminator, *values, /* atIndex = */ 0, usrTime); + ApplyFloatingPointKind( + kind, terminator, *values, /* atIndex = */ 1, sysTime); + } + + if (time) { + auto typeCode{time->type().GetCategoryAndKind()}; + // ETIME time argument must have decimal range == 0. + RUNTIME_CHECK(terminator, + time->rank() == 0 && typeCode && + typeCode->first == Fortran::common::TypeCategory::Real); + // Only accept KIND=4 here. + int kind{typeCode->second}; + RUNTIME_CHECK(terminator, kind == 4); + + ApplyFloatingPointKind( + kind, terminator, *time, /* atIndex = */ 0, realTime); + } +} + } // extern "C" } // namespace Fortran::runtime diff --git a/flang/runtime/tools.h b/flang/runtime/tools.h index 52049c511f13..dc12e5c4533e 100644 --- a/flang/runtime/tools.h +++ b/flang/runtime/tools.h @@ -99,6 +99,15 @@ template struct StoreIntegerAt { } }; +// Helper to store floating value in result[at]. +template struct StoreFloatingPointAt { + RT_API_ATTRS void operator()(const Fortran::runtime::Descriptor &result, + std::size_t at, std::double_t value) const { + *result.ZeroBasedIndexedElement>(at) = value; + } +}; + // Validate a KIND= argument RT_API_ATTRS void CheckIntegerKind( Terminator &, int kind, const char *intrinsic); diff --git a/flang/test/Lower/Intrinsics/etime-function.f90 b/flang/test/Lower/Intrinsics/etime-function.f90 new file mode 100644 index 000000000000..c47d509af535 --- /dev/null +++ b/flang/test/Lower/Intrinsics/etime-function.f90 @@ -0,0 +1,24 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: func.func @_QPetime_test( +! CHECK-SAME: %[[valuesArg:.*]]: !fir.ref> {fir.bindc_name = "values"}, +! CHECK-SAME: %[[timeArg:.*]]: !fir.ref {fir.bindc_name = "time"}) { +subroutine etime_test(values, time) + REAL(4), DIMENSION(2) :: values + REAL(4) :: time + time = etime(values) + ! CHECK-NEXT: %[[c9:.*]] = arith.constant 9 : i32 + ! CHECK-NEXT: %[[c2:.*]] = arith.constant 2 : index + ! CHECK-NEXT: %[[timeTmpAddr:.*]] = fir.alloca f32 + ! CHECK-NEXT: %[[timeDeclare:.*]] = fir.declare %[[timeArg]] {uniq_name = "_QFetime_testEtime"} : (!fir.ref) -> !fir.ref + ! CHECK-NEXT: %[[shape:.*]] = fir.shape %[[c2]] : (index) -> !fir.shape<1> + ! CHECK-NEXT: %[[valuesDeclare:.*]] = fir.declare %[[valuesArg]](%[[shape]]) {uniq_name = "_QFetime_testEvalues"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + ! CHECK-NEXT: %[[valuesBox:.*]] = fir.embox %[[valuesDeclare]](%[[shape]]) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + ! CHECK-NEXT: %[[timeTmpBox:.*]] = fir.embox %[[timeTmpAddr]] : (!fir.ref) -> !fir.box + ! CHECK: %[[values:.*]] = fir.convert %[[valuesBox]] : (!fir.box>) -> !fir.box + ! CHECK: %[[timeTmp:.*]] = fir.convert %[[timeTmpBox]] : (!fir.box) -> !fir.box + ! CHECK: %[[VAL_9:.*]] = fir.call @_FortranAEtime(%[[values]], %[[timeTmp]], %[[VAL_7:.*]], %[[c9]]) fastmath : (!fir.box, !fir.box, !fir.ref, i32) -> none + ! CHECK-NEXT: %[[timeValue:.*]] = fir.load %[[timeTmpAddr]] : !fir.ref + ! CHECK-NEXT: fir.store %[[timeValue]] to %[[timeDeclare]] : !fir.ref + ! CHECK-NEXT: return +end subroutine etime_test \ No newline at end of file diff --git a/flang/test/Lower/Intrinsics/etime.f90 b/flang/test/Lower/Intrinsics/etime.f90 new file mode 100644 index 000000000000..e5e7984a340c --- /dev/null +++ b/flang/test/Lower/Intrinsics/etime.f90 @@ -0,0 +1,21 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: func.func @_QPetime_test( +! CHECK-SAME: %[[valuesArg:.*]]: !fir.ref> {fir.bindc_name = "values"}, +! CHECK-SAME: %[[timeArg:.*]]: !fir.ref {fir.bindc_name = "time"}) { +subroutine etime_test(values, time) + REAL(4), DIMENSION(2) :: values + REAL(4) :: time + call etime(values, time) + ! CHECK-NEXT: %[[c9:.*]] = arith.constant 9 : i32 + ! CHECK-NEXT: %[[c2:.*]] = arith.constant 2 : index + ! CHECK-NEXT: %[[timeDeclare:.*]] = fir.declare %[[timeArg]] {uniq_name = "_QFetime_testEtime"} : (!fir.ref) -> !fir.ref + ! CHECK-NEXT: %[[shape:.*]] = fir.shape %[[c2]] : (index) -> !fir.shape<1> + ! CHECK-NEXT: %[[valuesDeclare:.*]] = fir.declare %[[valuesArg]](%[[shape]]) {uniq_name = "_QFetime_testEvalues"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + ! CHECK-NEXT: %[[valuesBox:.*]] = fir.embox %[[valuesDeclare]](%[[shape]]) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + ! CHECK-NEXT: %[[timeBox:.*]] = fir.embox %[[timeDeclare]] : (!fir.ref) -> !fir.box + ! CHECK: %[[values:.*]] = fir.convert %[[valuesBox]] : (!fir.box>) -> !fir.box + ! CHECK: %[[time:.*]] = fir.convert %[[timeBox]] : (!fir.box) -> !fir.box + ! CHECK: %[[VAL_9:.*]] = fir.call @_FortranAEtime(%[[values]], %[[time]], %[[VAL_7:.*]], %[[c9]]) fastmath : (!fir.box, !fir.box, !fir.ref, i32) -> none + ! CHECK-NEXT: return +end subroutine etime_test \ No newline at end of file diff --git a/flang/test/Semantics/etime.f90 b/flang/test/Semantics/etime.f90 new file mode 100644 index 000000000000..28735c2a7aac --- /dev/null +++ b/flang/test/Semantics/etime.f90 @@ -0,0 +1,30 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic +! Tests for the ETIME intrinsics + +subroutine bad_kind_error(values, time) + REAL(KIND=8), DIMENSION(2) :: values + REAL(KIND=8) :: time + !ERROR: Actual argument for 'values=' has bad type or kind 'REAL(8)' + call etime(values, time) +end subroutine bad_kind_error + +subroutine bad_args_error(values) + REAL(KIND=4), DIMENSION(2) :: values + !ERROR: missing mandatory 'time=' argument + call etime(values) +end subroutine bad_args_error + +subroutine bad_apply_form(values) + REAL(KIND=4), DIMENSION(2) :: values + REAL(KIND=4) :: time + !Declaration of 'etime' + call etime(values, time) + !ERROR: Cannot call subroutine 'etime' like a function + time = etime(values) +end subroutine bad_apply_form + +subroutine good_kind_equal(values, time) + REAL(KIND=4), DIMENSION(2) :: values + REAL(KIND=4) :: time + call etime(values, time) +end subroutine good_kind_equal \ No newline at end of file -- GitLab From f2d74002fdad2171b62392eaedf38aac7e4fb50d Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 15 May 2024 21:46:31 -0700 Subject: [PATCH 456/578] [LegalizeVectorOps][X86] Add ISD::ABDS/ABSDU to the list of opcodes handled by LegalizeVectorOps. (#92332) The expand code is present, but we were missing the type query code so the nodes would be ignored until LegalizeDAG. --- .../SelectionDAG/LegalizeVectorOps.cpp | 2 ++ llvm/test/CodeGen/X86/midpoint-int-vec-128.ll | 32 +++++++++---------- llvm/test/CodeGen/X86/midpoint-int-vec-256.ll | 32 +++++++++---------- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp index 423df9ae6b2a..6acbc044d673 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @@ -367,6 +367,8 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) { case ISD::ROTL: case ISD::ROTR: case ISD::ABS: + case ISD::ABDS: + case ISD::ABDU: case ISD::BSWAP: case ISD::BITREVERSE: case ISD::CTLZ: diff --git a/llvm/test/CodeGen/X86/midpoint-int-vec-128.ll b/llvm/test/CodeGen/X86/midpoint-int-vec-128.ll index 5a6375e08bca..c6e8b7532505 100644 --- a/llvm/test/CodeGen/X86/midpoint-int-vec-128.ll +++ b/llvm/test/CodeGen/X86/midpoint-int-vec-128.ll @@ -1991,14 +1991,14 @@ define <8 x i16> @vec128_i16_unsigned_reg_reg(<8 x i16> %a1, <8 x i16> %a2) noun ; ; AVX512VL-FALLBACK-LABEL: vec128_i16_unsigned_reg_reg: ; AVX512VL-FALLBACK: # %bb.0: -; AVX512VL-FALLBACK-NEXT: vpmaxuw %xmm1, %xmm0, %xmm2 -; AVX512VL-FALLBACK-NEXT: vpminuw %xmm1, %xmm0, %xmm1 -; AVX512VL-FALLBACK-NEXT: vpsubw %xmm1, %xmm2, %xmm2 -; AVX512VL-FALLBACK-NEXT: vpsrlw $1, %xmm2, %xmm2 -; AVX512VL-FALLBACK-NEXT: vpcmpeqw %xmm1, %xmm0, %xmm1 -; AVX512VL-FALLBACK-NEXT: vpternlogq $15, %xmm1, %xmm1, %xmm1 -; AVX512VL-FALLBACK-NEXT: vpxor %xmm1, %xmm2, %xmm2 -; AVX512VL-FALLBACK-NEXT: vpsubw %xmm1, %xmm2, %xmm1 +; AVX512VL-FALLBACK-NEXT: vpminuw %xmm1, %xmm0, %xmm2 +; AVX512VL-FALLBACK-NEXT: vpmaxuw %xmm1, %xmm0, %xmm1 +; AVX512VL-FALLBACK-NEXT: vpsubw %xmm2, %xmm1, %xmm1 +; AVX512VL-FALLBACK-NEXT: vpsrlw $1, %xmm1, %xmm1 +; AVX512VL-FALLBACK-NEXT: vpcmpeqw %xmm2, %xmm0, %xmm2 +; AVX512VL-FALLBACK-NEXT: vpternlogq $15, %xmm2, %xmm2, %xmm2 +; AVX512VL-FALLBACK-NEXT: vpxor %xmm2, %xmm1, %xmm1 +; AVX512VL-FALLBACK-NEXT: vpsubw %xmm2, %xmm1, %xmm1 ; AVX512VL-FALLBACK-NEXT: vpaddw %xmm0, %xmm1, %xmm0 ; AVX512VL-FALLBACK-NEXT: retq ; @@ -2784,14 +2784,14 @@ define <16 x i8> @vec128_i8_unsigned_reg_reg(<16 x i8> %a1, <16 x i8> %a2) nounw ; ; AVX512VL-FALLBACK-LABEL: vec128_i8_unsigned_reg_reg: ; AVX512VL-FALLBACK: # %bb.0: -; AVX512VL-FALLBACK-NEXT: vpmaxub %xmm1, %xmm0, %xmm2 -; AVX512VL-FALLBACK-NEXT: vpminub %xmm1, %xmm0, %xmm1 -; AVX512VL-FALLBACK-NEXT: vpsubb %xmm1, %xmm2, %xmm2 -; AVX512VL-FALLBACK-NEXT: vpsrlw $1, %xmm2, %xmm2 -; AVX512VL-FALLBACK-NEXT: vpcmpeqb %xmm1, %xmm0, %xmm1 -; AVX512VL-FALLBACK-NEXT: vpternlogq $15, %xmm1, %xmm1, %xmm1 -; AVX512VL-FALLBACK-NEXT: vpternlogd $108, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm1, %xmm2 -; AVX512VL-FALLBACK-NEXT: vpsubb %xmm1, %xmm2, %xmm1 +; AVX512VL-FALLBACK-NEXT: vpminub %xmm1, %xmm0, %xmm2 +; AVX512VL-FALLBACK-NEXT: vpmaxub %xmm1, %xmm0, %xmm1 +; AVX512VL-FALLBACK-NEXT: vpsubb %xmm2, %xmm1, %xmm1 +; AVX512VL-FALLBACK-NEXT: vpsrlw $1, %xmm1, %xmm1 +; AVX512VL-FALLBACK-NEXT: vpcmpeqb %xmm2, %xmm0, %xmm2 +; AVX512VL-FALLBACK-NEXT: vpternlogq $15, %xmm2, %xmm2, %xmm2 +; AVX512VL-FALLBACK-NEXT: vpternlogd $108, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm2, %xmm1 +; AVX512VL-FALLBACK-NEXT: vpsubb %xmm2, %xmm1, %xmm1 ; AVX512VL-FALLBACK-NEXT: vpaddb %xmm0, %xmm1, %xmm0 ; AVX512VL-FALLBACK-NEXT: retq ; diff --git a/llvm/test/CodeGen/X86/midpoint-int-vec-256.ll b/llvm/test/CodeGen/X86/midpoint-int-vec-256.ll index e880a1acc9e8..cc08396ae8c7 100644 --- a/llvm/test/CodeGen/X86/midpoint-int-vec-256.ll +++ b/llvm/test/CodeGen/X86/midpoint-int-vec-256.ll @@ -1445,14 +1445,14 @@ define <16 x i16> @vec256_i16_unsigned_reg_reg(<16 x i16> %a1, <16 x i16> %a2) n ; ; AVX512VL-FALLBACK-LABEL: vec256_i16_unsigned_reg_reg: ; AVX512VL-FALLBACK: # %bb.0: -; AVX512VL-FALLBACK-NEXT: vpmaxuw %ymm1, %ymm0, %ymm2 -; AVX512VL-FALLBACK-NEXT: vpminuw %ymm1, %ymm0, %ymm1 -; AVX512VL-FALLBACK-NEXT: vpsubw %ymm1, %ymm2, %ymm2 -; AVX512VL-FALLBACK-NEXT: vpsrlw $1, %ymm2, %ymm2 -; AVX512VL-FALLBACK-NEXT: vpcmpeqw %ymm1, %ymm0, %ymm1 -; AVX512VL-FALLBACK-NEXT: vpternlogq $15, %ymm1, %ymm1, %ymm1 -; AVX512VL-FALLBACK-NEXT: vpxor %ymm1, %ymm2, %ymm2 -; AVX512VL-FALLBACK-NEXT: vpsubw %ymm1, %ymm2, %ymm1 +; AVX512VL-FALLBACK-NEXT: vpminuw %ymm1, %ymm0, %ymm2 +; AVX512VL-FALLBACK-NEXT: vpmaxuw %ymm1, %ymm0, %ymm1 +; AVX512VL-FALLBACK-NEXT: vpsubw %ymm2, %ymm1, %ymm1 +; AVX512VL-FALLBACK-NEXT: vpsrlw $1, %ymm1, %ymm1 +; AVX512VL-FALLBACK-NEXT: vpcmpeqw %ymm2, %ymm0, %ymm2 +; AVX512VL-FALLBACK-NEXT: vpternlogq $15, %ymm2, %ymm2, %ymm2 +; AVX512VL-FALLBACK-NEXT: vpxor %ymm2, %ymm1, %ymm1 +; AVX512VL-FALLBACK-NEXT: vpsubw %ymm2, %ymm1, %ymm1 ; AVX512VL-FALLBACK-NEXT: vpaddw %ymm0, %ymm1, %ymm0 ; AVX512VL-FALLBACK-NEXT: retq ; @@ -2210,14 +2210,14 @@ define <32 x i8> @vec256_i8_unsigned_reg_reg(<32 x i8> %a1, <32 x i8> %a2) nounw ; ; AVX512VL-FALLBACK-LABEL: vec256_i8_unsigned_reg_reg: ; AVX512VL-FALLBACK: # %bb.0: -; AVX512VL-FALLBACK-NEXT: vpmaxub %ymm1, %ymm0, %ymm2 -; AVX512VL-FALLBACK-NEXT: vpminub %ymm1, %ymm0, %ymm1 -; AVX512VL-FALLBACK-NEXT: vpsubb %ymm1, %ymm2, %ymm2 -; AVX512VL-FALLBACK-NEXT: vpsrlw $1, %ymm2, %ymm2 -; AVX512VL-FALLBACK-NEXT: vpcmpeqb %ymm1, %ymm0, %ymm1 -; AVX512VL-FALLBACK-NEXT: vpternlogq $15, %ymm1, %ymm1, %ymm1 -; AVX512VL-FALLBACK-NEXT: vpternlogd $108, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm1, %ymm2 -; AVX512VL-FALLBACK-NEXT: vpsubb %ymm1, %ymm2, %ymm1 +; AVX512VL-FALLBACK-NEXT: vpminub %ymm1, %ymm0, %ymm2 +; AVX512VL-FALLBACK-NEXT: vpmaxub %ymm1, %ymm0, %ymm1 +; AVX512VL-FALLBACK-NEXT: vpsubb %ymm2, %ymm1, %ymm1 +; AVX512VL-FALLBACK-NEXT: vpsrlw $1, %ymm1, %ymm1 +; AVX512VL-FALLBACK-NEXT: vpcmpeqb %ymm2, %ymm0, %ymm2 +; AVX512VL-FALLBACK-NEXT: vpternlogq $15, %ymm2, %ymm2, %ymm2 +; AVX512VL-FALLBACK-NEXT: vpternlogd $108, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm2, %ymm1 +; AVX512VL-FALLBACK-NEXT: vpsubb %ymm2, %ymm1, %ymm1 ; AVX512VL-FALLBACK-NEXT: vpaddb %ymm0, %ymm1, %ymm0 ; AVX512VL-FALLBACK-NEXT: retq ; -- GitLab From 487b43cdc9fff9e370b8ea948c0cc19ca817aa86 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 15 May 2024 21:47:29 -0700 Subject: [PATCH 457/578] [RISCV] Pass subvector type to isLegalInterleavedAccessType in getInterleavedMemoryOpCost. (#91825) isLegalInterleavedAccessType expects the subvector type, but getInterleavedMemoryOpCost is called with the full vector type. So we need to divide by Factor. --- .../Target/RISCV/RISCVTargetTransformInfo.cpp | 19 +- .../RISCV/interleaved-accesses.ll | 566 ++++++++---------- .../LoopVectorize/RISCV/interleaved-cost.ll | 4 +- 3 files changed, 259 insertions(+), 330 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index 4d2479fc233f..b73ed208ed74 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -613,14 +613,19 @@ InstructionCost RISCVTTIImpl::getInterleavedMemoryOpCost( std::pair LT = getTypeLegalizationCost(VTy); // Need to make sure type has't been scalarized if (LT.second.isVector()) { - auto *LegalVTy = VectorType::get(VTy->getElementType(), - LT.second.getVectorElementCount()); - // FIXME: We use the memory op cost of the *legalized* type here, becuase - // it's getMemoryOpCost returns a really expensive cost for types like - // <6 x i8>, which show up when doing interleaves of Factor=3 etc. - // Should the memory op cost of these be cheaper? - if (TLI->isLegalInterleavedAccessType(LegalVTy, Factor, Alignment, + auto *SubVecTy = + VectorType::get(VTy->getElementType(), + VTy->getElementCount().divideCoefficientBy(Factor)); + + if (VTy->getElementCount().isKnownMultipleOf(Factor) && + TLI->isLegalInterleavedAccessType(SubVecTy, Factor, Alignment, AddressSpace, DL)) { + // FIXME: We use the memory op cost of the *legalized* type here, + // because it's getMemoryOpCost returns a really expensive cost for + // types like <6 x i8>, which show up when doing interleaves of + // Factor=3 etc. Should the memory op cost of these be cheaper? + auto *LegalVTy = VectorType::get(VTy->getElementType(), + LT.second.getVectorElementCount()); InstructionCost LegalMemCost = getMemoryOpCost( Opcode, LegalVTy, Alignment, AddressSpace, CostKind); return LT.first + LegalMemCost; diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/interleaved-accesses.ll b/llvm/test/Transforms/LoopVectorize/RISCV/interleaved-accesses.ll index 576dc0833fa3..87bc77cb7767 100644 --- a/llvm/test/Transforms/LoopVectorize/RISCV/interleaved-accesses.ll +++ b/llvm/test/Transforms/LoopVectorize/RISCV/interleaved-accesses.ll @@ -393,23 +393,23 @@ define void @load_store_factor3_i32(ptr %p) { ; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 3 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[TMP2]], i32 0 -; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <6 x i32>, ptr [[TMP3]], align 4 -; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <6 x i32> [[WIDE_VEC]], <6 x i32> poison, <2 x i32> -; CHECK-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <6 x i32> [[WIDE_VEC]], <6 x i32> poison, <2 x i32> -; CHECK-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <6 x i32> [[WIDE_VEC]], <6 x i32> poison, <2 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = add <2 x i32> [[STRIDED_VEC]], +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <24 x i32>, ptr [[TMP3]], align 4 +; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <24 x i32> [[WIDE_VEC]], <24 x i32> poison, <8 x i32> +; CHECK-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <24 x i32> [[WIDE_VEC]], <24 x i32> poison, <8 x i32> +; CHECK-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <24 x i32> [[WIDE_VEC]], <24 x i32> poison, <8 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = add <8 x i32> [[STRIDED_VEC]], ; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[TMP1]], 1 -; CHECK-NEXT: [[TMP6:%.*]] = add <2 x i32> [[STRIDED_VEC1]], +; CHECK-NEXT: [[TMP6:%.*]] = add <8 x i32> [[STRIDED_VEC1]], ; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[TMP5]], 1 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i32, ptr [[P]], i64 [[TMP7]] -; CHECK-NEXT: [[TMP9:%.*]] = add <2 x i32> [[STRIDED_VEC2]], +; CHECK-NEXT: [[TMP9:%.*]] = add <8 x i32> [[STRIDED_VEC2]], ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i32, ptr [[TMP8]], i32 -2 -; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP6]], <4 x i32> -; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <2 x i32> [[TMP9]], <2 x i32> poison, <4 x i32> -; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <6 x i32> -; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <6 x i32> [[TMP13]], <6 x i32> poison, <6 x i32> -; CHECK-NEXT: store <6 x i32> [[INTERLEAVED_VEC]], ptr [[TMP10]], align 4 -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <8 x i32> [[TMP4]], <8 x i32> [[TMP6]], <16 x i32> +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <8 x i32> [[TMP9]], <8 x i32> poison, <16 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <16 x i32> [[TMP11]], <16 x i32> [[TMP12]], <24 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <24 x i32> [[TMP13]], <24 x i32> poison, <24 x i32> +; CHECK-NEXT: store <24 x i32> [[INTERLEAVED_VEC]], ptr [[TMP10]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 ; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024 ; CHECK-NEXT: br i1 [[TMP14]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] ; CHECK: middle.block: @@ -451,23 +451,23 @@ define void @load_store_factor3_i32(ptr %p) { ; FIXED-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 3 ; FIXED-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]] ; FIXED-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[TMP2]], i32 0 -; FIXED-NEXT: [[WIDE_VEC:%.*]] = load <6 x i32>, ptr [[TMP3]], align 4 -; FIXED-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <6 x i32> [[WIDE_VEC]], <6 x i32> poison, <2 x i32> -; FIXED-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <6 x i32> [[WIDE_VEC]], <6 x i32> poison, <2 x i32> -; FIXED-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <6 x i32> [[WIDE_VEC]], <6 x i32> poison, <2 x i32> -; FIXED-NEXT: [[TMP4:%.*]] = add <2 x i32> [[STRIDED_VEC]], +; FIXED-NEXT: [[WIDE_VEC:%.*]] = load <24 x i32>, ptr [[TMP3]], align 4 +; FIXED-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <24 x i32> [[WIDE_VEC]], <24 x i32> poison, <8 x i32> +; FIXED-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <24 x i32> [[WIDE_VEC]], <24 x i32> poison, <8 x i32> +; FIXED-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <24 x i32> [[WIDE_VEC]], <24 x i32> poison, <8 x i32> +; FIXED-NEXT: [[TMP4:%.*]] = add <8 x i32> [[STRIDED_VEC]], ; FIXED-NEXT: [[TMP5:%.*]] = add i64 [[TMP1]], 1 -; FIXED-NEXT: [[TMP6:%.*]] = add <2 x i32> [[STRIDED_VEC1]], +; FIXED-NEXT: [[TMP6:%.*]] = add <8 x i32> [[STRIDED_VEC1]], ; FIXED-NEXT: [[TMP7:%.*]] = add i64 [[TMP5]], 1 ; FIXED-NEXT: [[TMP8:%.*]] = getelementptr i32, ptr [[P]], i64 [[TMP7]] -; FIXED-NEXT: [[TMP9:%.*]] = add <2 x i32> [[STRIDED_VEC2]], +; FIXED-NEXT: [[TMP9:%.*]] = add <8 x i32> [[STRIDED_VEC2]], ; FIXED-NEXT: [[TMP10:%.*]] = getelementptr i32, ptr [[TMP8]], i32 -2 -; FIXED-NEXT: [[TMP11:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP6]], <4 x i32> -; FIXED-NEXT: [[TMP12:%.*]] = shufflevector <2 x i32> [[TMP9]], <2 x i32> poison, <4 x i32> -; FIXED-NEXT: [[TMP13:%.*]] = shufflevector <4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <6 x i32> -; FIXED-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <6 x i32> [[TMP13]], <6 x i32> poison, <6 x i32> -; FIXED-NEXT: store <6 x i32> [[INTERLEAVED_VEC]], ptr [[TMP10]], align 4 -; FIXED-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 +; FIXED-NEXT: [[TMP11:%.*]] = shufflevector <8 x i32> [[TMP4]], <8 x i32> [[TMP6]], <16 x i32> +; FIXED-NEXT: [[TMP12:%.*]] = shufflevector <8 x i32> [[TMP9]], <8 x i32> poison, <16 x i32> +; FIXED-NEXT: [[TMP13:%.*]] = shufflevector <16 x i32> [[TMP11]], <16 x i32> [[TMP12]], <24 x i32> +; FIXED-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <24 x i32> [[TMP13]], <24 x i32> poison, <24 x i32> +; FIXED-NEXT: store <24 x i32> [[INTERLEAVED_VEC]], ptr [[TMP10]], align 4 +; FIXED-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 ; FIXED-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024 ; FIXED-NEXT: br i1 [[TMP14]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] ; FIXED: middle.block: @@ -509,23 +509,23 @@ define void @load_store_factor3_i32(ptr %p) { ; SCALABLE-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 3 ; SCALABLE-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP1]] ; SCALABLE-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[TMP2]], i32 0 -; SCALABLE-NEXT: [[WIDE_VEC:%.*]] = load <6 x i32>, ptr [[TMP3]], align 4 -; SCALABLE-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <6 x i32> [[WIDE_VEC]], <6 x i32> poison, <2 x i32> -; SCALABLE-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <6 x i32> [[WIDE_VEC]], <6 x i32> poison, <2 x i32> -; SCALABLE-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <6 x i32> [[WIDE_VEC]], <6 x i32> poison, <2 x i32> -; SCALABLE-NEXT: [[TMP4:%.*]] = add <2 x i32> [[STRIDED_VEC]], +; SCALABLE-NEXT: [[WIDE_VEC:%.*]] = load <24 x i32>, ptr [[TMP3]], align 4 +; SCALABLE-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <24 x i32> [[WIDE_VEC]], <24 x i32> poison, <8 x i32> +; SCALABLE-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <24 x i32> [[WIDE_VEC]], <24 x i32> poison, <8 x i32> +; SCALABLE-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <24 x i32> [[WIDE_VEC]], <24 x i32> poison, <8 x i32> +; SCALABLE-NEXT: [[TMP4:%.*]] = add <8 x i32> [[STRIDED_VEC]], ; SCALABLE-NEXT: [[TMP5:%.*]] = add i64 [[TMP1]], 1 -; SCALABLE-NEXT: [[TMP6:%.*]] = add <2 x i32> [[STRIDED_VEC1]], +; SCALABLE-NEXT: [[TMP6:%.*]] = add <8 x i32> [[STRIDED_VEC1]], ; SCALABLE-NEXT: [[TMP7:%.*]] = add i64 [[TMP5]], 1 ; SCALABLE-NEXT: [[TMP8:%.*]] = getelementptr i32, ptr [[P]], i64 [[TMP7]] -; SCALABLE-NEXT: [[TMP9:%.*]] = add <2 x i32> [[STRIDED_VEC2]], +; SCALABLE-NEXT: [[TMP9:%.*]] = add <8 x i32> [[STRIDED_VEC2]], ; SCALABLE-NEXT: [[TMP10:%.*]] = getelementptr i32, ptr [[TMP8]], i32 -2 -; SCALABLE-NEXT: [[TMP11:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP6]], <4 x i32> -; SCALABLE-NEXT: [[TMP12:%.*]] = shufflevector <2 x i32> [[TMP9]], <2 x i32> poison, <4 x i32> -; SCALABLE-NEXT: [[TMP13:%.*]] = shufflevector <4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <6 x i32> -; SCALABLE-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <6 x i32> [[TMP13]], <6 x i32> poison, <6 x i32> -; SCALABLE-NEXT: store <6 x i32> [[INTERLEAVED_VEC]], ptr [[TMP10]], align 4 -; SCALABLE-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 +; SCALABLE-NEXT: [[TMP11:%.*]] = shufflevector <8 x i32> [[TMP4]], <8 x i32> [[TMP6]], <16 x i32> +; SCALABLE-NEXT: [[TMP12:%.*]] = shufflevector <8 x i32> [[TMP9]], <8 x i32> poison, <16 x i32> +; SCALABLE-NEXT: [[TMP13:%.*]] = shufflevector <16 x i32> [[TMP11]], <16 x i32> [[TMP12]], <24 x i32> +; SCALABLE-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <24 x i32> [[TMP13]], <24 x i32> poison, <24 x i32> +; SCALABLE-NEXT: store <24 x i32> [[INTERLEAVED_VEC]], ptr [[TMP10]], align 4 +; SCALABLE-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 ; SCALABLE-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024 ; SCALABLE-NEXT: br i1 [[TMP14]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] ; SCALABLE: middle.block: @@ -589,54 +589,38 @@ exit: define void @load_store_factor3_i64(ptr %p) { ; CHECK-LABEL: @load_store_factor3_i64( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 2 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 1024, [[TMP1]] -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 2 -; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP3]] -; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 1024, [[N_MOD_VF]] -; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 2 -; CHECK-NEXT: [[TMP6:%.*]] = call @llvm.experimental.stepvector.nxv2i64() -; CHECK-NEXT: [[TMP7:%.*]] = add [[TMP6]], zeroinitializer -; CHECK-NEXT: [[TMP8:%.*]] = mul [[TMP7]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[INDUCTION:%.*]] = add zeroinitializer, [[TMP8]] -; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP10:%.*]] = mul i64 [[TMP9]], 2 -; CHECK-NEXT: [[TMP11:%.*]] = mul i64 1, [[TMP10]] -; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement poison, i64 [[TMP11]], i64 0 -; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector [[DOTSPLATINSERT]], poison, zeroinitializer ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_IND:%.*]] = phi [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP12:%.*]] = mul [[VEC_IND]], shufflevector ( insertelement ( poison, i64 3, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i64, ptr [[P:%.*]], [[TMP12]] -; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP13]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; CHECK-NEXT: [[TMP14:%.*]] = add [[WIDE_MASKED_GATHER]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP14]], [[TMP13]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; CHECK-NEXT: [[TMP15:%.*]] = add [[TMP12]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i64, ptr [[P]], [[TMP15]] -; CHECK-NEXT: [[WIDE_MASKED_GATHER1:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP16]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; CHECK-NEXT: [[TMP17:%.*]] = add [[WIDE_MASKED_GATHER1]], shufflevector ( insertelement ( poison, i64 2, i64 0), poison, zeroinitializer) -; CHECK-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP17]], [[TMP16]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; CHECK-NEXT: [[TMP18:%.*]] = add [[TMP15]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i64, ptr [[P]], [[TMP18]] -; CHECK-NEXT: [[WIDE_MASKED_GATHER2:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP19]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; CHECK-NEXT: [[TMP20:%.*]] = add [[WIDE_MASKED_GATHER2]], shufflevector ( insertelement ( poison, i64 3, i64 0), poison, zeroinitializer) -; CHECK-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP20]], [[TMP19]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP5]] -; CHECK-NEXT: [[VEC_IND_NEXT]] = add [[VEC_IND]], [[DOTSPLAT]] -; CHECK-NEXT: [[TMP21:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP21]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 3 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[TMP1]] +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[TMP2]], i32 0 +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <12 x i64>, ptr [[TMP3]], align 8 +; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <12 x i64> [[WIDE_VEC]], <12 x i64> poison, <4 x i32> +; CHECK-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <12 x i64> [[WIDE_VEC]], <12 x i64> poison, <4 x i32> +; CHECK-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <12 x i64> [[WIDE_VEC]], <12 x i64> poison, <4 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = add <4 x i64> [[STRIDED_VEC]], +; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[TMP1]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = add <4 x i64> [[STRIDED_VEC1]], +; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[TMP5]], 1 +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i64, ptr [[P]], i64 [[TMP7]] +; CHECK-NEXT: [[TMP9:%.*]] = add <4 x i64> [[STRIDED_VEC2]], +; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i64, ptr [[TMP8]], i32 -2 +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <4 x i64> [[TMP4]], <4 x i64> [[TMP6]], <8 x i32> +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <4 x i64> [[TMP9]], <4 x i64> poison, <8 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <8 x i64> [[TMP11]], <8 x i64> [[TMP12]], <12 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <12 x i64> [[TMP13]], <12 x i64> poison, <12 x i32> +; CHECK-NEXT: store <12 x i64> [[INTERLEAVED_VEC]], ptr [[TMP10]], align 8 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024 +; CHECK-NEXT: br i1 [[TMP14]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] ; CHECK: middle.block: -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 1024, [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 1024, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[NEXTI:%.*]], [[LOOP]] ] @@ -668,26 +652,29 @@ define void @load_store_factor3_i64(ptr %p) { ; FIXED-NEXT: br label [[VECTOR_BODY:%.*]] ; FIXED: vector.body: ; FIXED-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; FIXED-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ , [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] -; FIXED-NEXT: [[TMP0:%.*]] = mul <4 x i64> [[VEC_IND]], -; FIXED-NEXT: [[TMP1:%.*]] = getelementptr i64, ptr [[P:%.*]], <4 x i64> [[TMP0]] -; FIXED-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP1]], i32 8, <4 x i1> , <4 x i64> poison) -; FIXED-NEXT: [[TMP2:%.*]] = add <4 x i64> [[WIDE_MASKED_GATHER]], -; FIXED-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[TMP2]], <4 x ptr> [[TMP1]], i32 8, <4 x i1> ) -; FIXED-NEXT: [[TMP3:%.*]] = add <4 x i64> [[TMP0]], -; FIXED-NEXT: [[TMP4:%.*]] = getelementptr i64, ptr [[P]], <4 x i64> [[TMP3]] -; FIXED-NEXT: [[WIDE_MASKED_GATHER1:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP4]], i32 8, <4 x i1> , <4 x i64> poison) -; FIXED-NEXT: [[TMP5:%.*]] = add <4 x i64> [[WIDE_MASKED_GATHER1]], -; FIXED-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[TMP5]], <4 x ptr> [[TMP4]], i32 8, <4 x i1> ) -; FIXED-NEXT: [[TMP6:%.*]] = add <4 x i64> [[TMP3]], -; FIXED-NEXT: [[TMP7:%.*]] = getelementptr i64, ptr [[P]], <4 x i64> [[TMP6]] -; FIXED-NEXT: [[WIDE_MASKED_GATHER2:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP7]], i32 8, <4 x i1> , <4 x i64> poison) -; FIXED-NEXT: [[TMP8:%.*]] = add <4 x i64> [[WIDE_MASKED_GATHER2]], -; FIXED-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[TMP8]], <4 x ptr> [[TMP7]], i32 8, <4 x i1> ) +; FIXED-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 +; FIXED-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 3 +; FIXED-NEXT: [[TMP2:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[TMP1]] +; FIXED-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[TMP2]], i32 0 +; FIXED-NEXT: [[WIDE_VEC:%.*]] = load <12 x i64>, ptr [[TMP3]], align 8 +; FIXED-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <12 x i64> [[WIDE_VEC]], <12 x i64> poison, <4 x i32> +; FIXED-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <12 x i64> [[WIDE_VEC]], <12 x i64> poison, <4 x i32> +; FIXED-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <12 x i64> [[WIDE_VEC]], <12 x i64> poison, <4 x i32> +; FIXED-NEXT: [[TMP4:%.*]] = add <4 x i64> [[STRIDED_VEC]], +; FIXED-NEXT: [[TMP5:%.*]] = add i64 [[TMP1]], 1 +; FIXED-NEXT: [[TMP6:%.*]] = add <4 x i64> [[STRIDED_VEC1]], +; FIXED-NEXT: [[TMP7:%.*]] = add i64 [[TMP5]], 1 +; FIXED-NEXT: [[TMP8:%.*]] = getelementptr i64, ptr [[P]], i64 [[TMP7]] +; FIXED-NEXT: [[TMP9:%.*]] = add <4 x i64> [[STRIDED_VEC2]], +; FIXED-NEXT: [[TMP10:%.*]] = getelementptr i64, ptr [[TMP8]], i32 -2 +; FIXED-NEXT: [[TMP11:%.*]] = shufflevector <4 x i64> [[TMP4]], <4 x i64> [[TMP6]], <8 x i32> +; FIXED-NEXT: [[TMP12:%.*]] = shufflevector <4 x i64> [[TMP9]], <4 x i64> poison, <8 x i32> +; FIXED-NEXT: [[TMP13:%.*]] = shufflevector <8 x i64> [[TMP11]], <8 x i64> [[TMP12]], <12 x i32> +; FIXED-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <12 x i64> [[TMP13]], <12 x i64> poison, <12 x i32> +; FIXED-NEXT: store <12 x i64> [[INTERLEAVED_VEC]], ptr [[TMP10]], align 8 ; FIXED-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; FIXED-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], -; FIXED-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024 -; FIXED-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; FIXED-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024 +; FIXED-NEXT: br i1 [[TMP14]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] ; FIXED: middle.block: ; FIXED-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]] ; FIXED: scalar.ph: @@ -718,54 +705,38 @@ define void @load_store_factor3_i64(ptr %p) { ; ; SCALABLE-LABEL: @load_store_factor3_i64( ; SCALABLE-NEXT: entry: -; SCALABLE-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() -; SCALABLE-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 2 -; SCALABLE-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 1024, [[TMP1]] -; SCALABLE-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; SCALABLE-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; SCALABLE: vector.ph: -; SCALABLE-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64() -; SCALABLE-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 2 -; SCALABLE-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP3]] -; SCALABLE-NEXT: [[N_VEC:%.*]] = sub i64 1024, [[N_MOD_VF]] -; SCALABLE-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() -; SCALABLE-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 2 -; SCALABLE-NEXT: [[TMP6:%.*]] = call @llvm.experimental.stepvector.nxv2i64() -; SCALABLE-NEXT: [[TMP7:%.*]] = add [[TMP6]], zeroinitializer -; SCALABLE-NEXT: [[TMP8:%.*]] = mul [[TMP7]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[INDUCTION:%.*]] = add zeroinitializer, [[TMP8]] -; SCALABLE-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64() -; SCALABLE-NEXT: [[TMP10:%.*]] = mul i64 [[TMP9]], 2 -; SCALABLE-NEXT: [[TMP11:%.*]] = mul i64 1, [[TMP10]] -; SCALABLE-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement poison, i64 [[TMP11]], i64 0 -; SCALABLE-NEXT: [[DOTSPLAT:%.*]] = shufflevector [[DOTSPLATINSERT]], poison, zeroinitializer ; SCALABLE-NEXT: br label [[VECTOR_BODY:%.*]] ; SCALABLE: vector.body: ; SCALABLE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; SCALABLE-NEXT: [[VEC_IND:%.*]] = phi [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] -; SCALABLE-NEXT: [[TMP12:%.*]] = mul [[VEC_IND]], shufflevector ( insertelement ( poison, i64 3, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[TMP13:%.*]] = getelementptr i64, ptr [[P:%.*]], [[TMP12]] -; SCALABLE-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP13]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; SCALABLE-NEXT: [[TMP14:%.*]] = add [[WIDE_MASKED_GATHER]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP14]], [[TMP13]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; SCALABLE-NEXT: [[TMP15:%.*]] = add [[TMP12]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[TMP16:%.*]] = getelementptr i64, ptr [[P]], [[TMP15]] -; SCALABLE-NEXT: [[WIDE_MASKED_GATHER1:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP16]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; SCALABLE-NEXT: [[TMP17:%.*]] = add [[WIDE_MASKED_GATHER1]], shufflevector ( insertelement ( poison, i64 2, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP17]], [[TMP16]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; SCALABLE-NEXT: [[TMP18:%.*]] = add [[TMP15]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[TMP19:%.*]] = getelementptr i64, ptr [[P]], [[TMP18]] -; SCALABLE-NEXT: [[WIDE_MASKED_GATHER2:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP19]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; SCALABLE-NEXT: [[TMP20:%.*]] = add [[WIDE_MASKED_GATHER2]], shufflevector ( insertelement ( poison, i64 3, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP20]], [[TMP19]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; SCALABLE-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP5]] -; SCALABLE-NEXT: [[VEC_IND_NEXT]] = add [[VEC_IND]], [[DOTSPLAT]] -; SCALABLE-NEXT: [[TMP21:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; SCALABLE-NEXT: br i1 [[TMP21]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; SCALABLE-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 +; SCALABLE-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 3 +; SCALABLE-NEXT: [[TMP2:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[TMP1]] +; SCALABLE-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[TMP2]], i32 0 +; SCALABLE-NEXT: [[WIDE_VEC:%.*]] = load <12 x i64>, ptr [[TMP3]], align 8 +; SCALABLE-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <12 x i64> [[WIDE_VEC]], <12 x i64> poison, <4 x i32> +; SCALABLE-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <12 x i64> [[WIDE_VEC]], <12 x i64> poison, <4 x i32> +; SCALABLE-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <12 x i64> [[WIDE_VEC]], <12 x i64> poison, <4 x i32> +; SCALABLE-NEXT: [[TMP4:%.*]] = add <4 x i64> [[STRIDED_VEC]], +; SCALABLE-NEXT: [[TMP5:%.*]] = add i64 [[TMP1]], 1 +; SCALABLE-NEXT: [[TMP6:%.*]] = add <4 x i64> [[STRIDED_VEC1]], +; SCALABLE-NEXT: [[TMP7:%.*]] = add i64 [[TMP5]], 1 +; SCALABLE-NEXT: [[TMP8:%.*]] = getelementptr i64, ptr [[P]], i64 [[TMP7]] +; SCALABLE-NEXT: [[TMP9:%.*]] = add <4 x i64> [[STRIDED_VEC2]], +; SCALABLE-NEXT: [[TMP10:%.*]] = getelementptr i64, ptr [[TMP8]], i32 -2 +; SCALABLE-NEXT: [[TMP11:%.*]] = shufflevector <4 x i64> [[TMP4]], <4 x i64> [[TMP6]], <8 x i32> +; SCALABLE-NEXT: [[TMP12:%.*]] = shufflevector <4 x i64> [[TMP9]], <4 x i64> poison, <8 x i32> +; SCALABLE-NEXT: [[TMP13:%.*]] = shufflevector <8 x i64> [[TMP11]], <8 x i64> [[TMP12]], <12 x i32> +; SCALABLE-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <12 x i64> [[TMP13]], <12 x i64> poison, <12 x i32> +; SCALABLE-NEXT: store <12 x i64> [[INTERLEAVED_VEC]], ptr [[TMP10]], align 8 +; SCALABLE-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; SCALABLE-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024 +; SCALABLE-NEXT: br i1 [[TMP14]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] ; SCALABLE: middle.block: -; SCALABLE-NEXT: [[CMP_N:%.*]] = icmp eq i64 1024, [[N_VEC]] -; SCALABLE-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] +; SCALABLE-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]] ; SCALABLE: scalar.ph: -; SCALABLE-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; SCALABLE-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 1024, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] ; SCALABLE-NEXT: br label [[LOOP:%.*]] ; SCALABLE: loop: ; SCALABLE-NEXT: [[I:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[NEXTI:%.*]], [[LOOP]] ] @@ -823,79 +794,57 @@ exit: define void @load_store_factor8(ptr %p) { ; CHECK-LABEL: @load_store_factor8( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 2 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 1024, [[TMP1]] -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 2 -; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP3]] -; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 1024, [[N_MOD_VF]] -; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 2 -; CHECK-NEXT: [[TMP6:%.*]] = call @llvm.experimental.stepvector.nxv2i64() -; CHECK-NEXT: [[TMP7:%.*]] = add [[TMP6]], zeroinitializer -; CHECK-NEXT: [[TMP8:%.*]] = mul [[TMP7]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[INDUCTION:%.*]] = add zeroinitializer, [[TMP8]] -; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP10:%.*]] = mul i64 [[TMP9]], 2 -; CHECK-NEXT: [[TMP11:%.*]] = mul i64 1, [[TMP10]] -; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement poison, i64 [[TMP11]], i64 0 -; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector [[DOTSPLATINSERT]], poison, zeroinitializer ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_IND:%.*]] = phi [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP12:%.*]] = shl [[VEC_IND]], shufflevector ( insertelement ( poison, i64 3, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i64, ptr [[P:%.*]], [[TMP12]] -; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP13]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; CHECK-NEXT: [[TMP14:%.*]] = add [[WIDE_MASKED_GATHER]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP14]], [[TMP13]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; CHECK-NEXT: [[TMP15:%.*]] = add [[TMP12]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i64, ptr [[P]], [[TMP15]] -; CHECK-NEXT: [[WIDE_MASKED_GATHER1:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP16]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; CHECK-NEXT: [[TMP17:%.*]] = add [[WIDE_MASKED_GATHER1]], shufflevector ( insertelement ( poison, i64 2, i64 0), poison, zeroinitializer) -; CHECK-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP17]], [[TMP16]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; CHECK-NEXT: [[TMP18:%.*]] = add [[TMP15]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i64, ptr [[P]], [[TMP18]] -; CHECK-NEXT: [[WIDE_MASKED_GATHER2:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP19]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; CHECK-NEXT: [[TMP20:%.*]] = add [[WIDE_MASKED_GATHER2]], shufflevector ( insertelement ( poison, i64 3, i64 0), poison, zeroinitializer) -; CHECK-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP20]], [[TMP19]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; CHECK-NEXT: [[TMP21:%.*]] = add [[TMP18]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP22:%.*]] = getelementptr i64, ptr [[P]], [[TMP21]] -; CHECK-NEXT: [[WIDE_MASKED_GATHER3:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP22]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; CHECK-NEXT: [[TMP23:%.*]] = add [[WIDE_MASKED_GATHER3]], shufflevector ( insertelement ( poison, i64 4, i64 0), poison, zeroinitializer) -; CHECK-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP23]], [[TMP22]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; CHECK-NEXT: [[TMP24:%.*]] = add [[TMP21]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i64, ptr [[P]], [[TMP24]] -; CHECK-NEXT: [[WIDE_MASKED_GATHER4:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP25]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; CHECK-NEXT: [[TMP26:%.*]] = add [[WIDE_MASKED_GATHER4]], shufflevector ( insertelement ( poison, i64 5, i64 0), poison, zeroinitializer) -; CHECK-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP26]], [[TMP25]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; CHECK-NEXT: [[TMP27:%.*]] = add [[TMP24]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP28:%.*]] = getelementptr i64, ptr [[P]], [[TMP27]] -; CHECK-NEXT: [[WIDE_MASKED_GATHER5:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP28]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; CHECK-NEXT: [[TMP29:%.*]] = add [[WIDE_MASKED_GATHER5]], shufflevector ( insertelement ( poison, i64 6, i64 0), poison, zeroinitializer) -; CHECK-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP29]], [[TMP28]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; CHECK-NEXT: [[TMP30:%.*]] = add [[TMP27]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP31:%.*]] = getelementptr i64, ptr [[P]], [[TMP30]] -; CHECK-NEXT: [[WIDE_MASKED_GATHER6:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP31]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; CHECK-NEXT: [[TMP32:%.*]] = add [[WIDE_MASKED_GATHER6]], shufflevector ( insertelement ( poison, i64 7, i64 0), poison, zeroinitializer) -; CHECK-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP32]], [[TMP31]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; CHECK-NEXT: [[TMP33:%.*]] = add [[TMP30]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[TMP34:%.*]] = getelementptr i64, ptr [[P]], [[TMP33]] -; CHECK-NEXT: [[WIDE_MASKED_GATHER7:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP34]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; CHECK-NEXT: [[TMP35:%.*]] = add [[WIDE_MASKED_GATHER7]], shufflevector ( insertelement ( poison, i64 8, i64 0), poison, zeroinitializer) -; CHECK-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP35]], [[TMP34]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP5]] -; CHECK-NEXT: [[VEC_IND_NEXT]] = add [[VEC_IND]], [[DOTSPLAT]] -; CHECK-NEXT: [[TMP36:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP36]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] +; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 3 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[TMP1]] +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[TMP2]], i32 0 +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <16 x i64>, ptr [[TMP3]], align 8 +; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; CHECK-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; CHECK-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; CHECK-NEXT: [[STRIDED_VEC3:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; CHECK-NEXT: [[STRIDED_VEC4:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; CHECK-NEXT: [[STRIDED_VEC5:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; CHECK-NEXT: [[STRIDED_VEC6:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; CHECK-NEXT: [[STRIDED_VEC7:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = add <2 x i64> [[STRIDED_VEC]], +; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[TMP1]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = add <2 x i64> [[STRIDED_VEC1]], +; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[TMP5]], 1 +; CHECK-NEXT: [[TMP8:%.*]] = add <2 x i64> [[STRIDED_VEC2]], +; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[TMP7]], 1 +; CHECK-NEXT: [[TMP10:%.*]] = add <2 x i64> [[STRIDED_VEC3]], +; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP9]], 1 +; CHECK-NEXT: [[TMP12:%.*]] = add <2 x i64> [[STRIDED_VEC4]], +; CHECK-NEXT: [[TMP13:%.*]] = add i64 [[TMP11]], 1 +; CHECK-NEXT: [[TMP14:%.*]] = add <2 x i64> [[STRIDED_VEC5]], +; CHECK-NEXT: [[TMP15:%.*]] = add i64 [[TMP13]], 1 +; CHECK-NEXT: [[TMP16:%.*]] = add <2 x i64> [[STRIDED_VEC6]], +; CHECK-NEXT: [[TMP17:%.*]] = add i64 [[TMP15]], 1 +; CHECK-NEXT: [[TMP18:%.*]] = getelementptr i64, ptr [[P]], i64 [[TMP17]] +; CHECK-NEXT: [[TMP19:%.*]] = add <2 x i64> [[STRIDED_VEC7]], +; CHECK-NEXT: [[TMP20:%.*]] = getelementptr i64, ptr [[TMP18]], i32 -7 +; CHECK-NEXT: [[TMP21:%.*]] = shufflevector <2 x i64> [[TMP4]], <2 x i64> [[TMP6]], <4 x i32> +; CHECK-NEXT: [[TMP22:%.*]] = shufflevector <2 x i64> [[TMP8]], <2 x i64> [[TMP10]], <4 x i32> +; CHECK-NEXT: [[TMP23:%.*]] = shufflevector <2 x i64> [[TMP12]], <2 x i64> [[TMP14]], <4 x i32> +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <2 x i64> [[TMP16]], <2 x i64> [[TMP19]], <4 x i32> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <4 x i64> [[TMP21]], <4 x i64> [[TMP22]], <8 x i32> +; CHECK-NEXT: [[TMP26:%.*]] = shufflevector <4 x i64> [[TMP23]], <4 x i64> [[TMP24]], <8 x i32> +; CHECK-NEXT: [[TMP27:%.*]] = shufflevector <8 x i64> [[TMP25]], <8 x i64> [[TMP26]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i64> [[TMP27]], <16 x i64> poison, <16 x i32> +; CHECK-NEXT: store <16 x i64> [[INTERLEAVED_VEC]], ptr [[TMP20]], align 8 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP28:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024 +; CHECK-NEXT: br i1 [[TMP28]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] ; CHECK: middle.block: -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 1024, [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 1024, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[NEXTI:%.*]], [[LOOP]] ] @@ -952,51 +901,48 @@ define void @load_store_factor8(ptr %p) { ; FIXED-NEXT: br label [[VECTOR_BODY:%.*]] ; FIXED: vector.body: ; FIXED-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; FIXED-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ , [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] -; FIXED-NEXT: [[TMP0:%.*]] = shl <4 x i64> [[VEC_IND]], -; FIXED-NEXT: [[TMP1:%.*]] = getelementptr i64, ptr [[P:%.*]], <4 x i64> [[TMP0]] -; FIXED-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP1]], i32 8, <4 x i1> , <4 x i64> poison) -; FIXED-NEXT: [[TMP2:%.*]] = add <4 x i64> [[WIDE_MASKED_GATHER]], -; FIXED-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[TMP2]], <4 x ptr> [[TMP1]], i32 8, <4 x i1> ) -; FIXED-NEXT: [[TMP3:%.*]] = add <4 x i64> [[TMP0]], -; FIXED-NEXT: [[TMP4:%.*]] = getelementptr i64, ptr [[P]], <4 x i64> [[TMP3]] -; FIXED-NEXT: [[WIDE_MASKED_GATHER1:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP4]], i32 8, <4 x i1> , <4 x i64> poison) -; FIXED-NEXT: [[TMP5:%.*]] = add <4 x i64> [[WIDE_MASKED_GATHER1]], -; FIXED-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[TMP5]], <4 x ptr> [[TMP4]], i32 8, <4 x i1> ) -; FIXED-NEXT: [[TMP6:%.*]] = add <4 x i64> [[TMP3]], -; FIXED-NEXT: [[TMP7:%.*]] = getelementptr i64, ptr [[P]], <4 x i64> [[TMP6]] -; FIXED-NEXT: [[WIDE_MASKED_GATHER2:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP7]], i32 8, <4 x i1> , <4 x i64> poison) -; FIXED-NEXT: [[TMP8:%.*]] = add <4 x i64> [[WIDE_MASKED_GATHER2]], -; FIXED-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[TMP8]], <4 x ptr> [[TMP7]], i32 8, <4 x i1> ) -; FIXED-NEXT: [[TMP9:%.*]] = add <4 x i64> [[TMP6]], -; FIXED-NEXT: [[TMP10:%.*]] = getelementptr i64, ptr [[P]], <4 x i64> [[TMP9]] -; FIXED-NEXT: [[WIDE_MASKED_GATHER3:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP10]], i32 8, <4 x i1> , <4 x i64> poison) -; FIXED-NEXT: [[TMP11:%.*]] = add <4 x i64> [[WIDE_MASKED_GATHER3]], -; FIXED-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[TMP11]], <4 x ptr> [[TMP10]], i32 8, <4 x i1> ) -; FIXED-NEXT: [[TMP12:%.*]] = add <4 x i64> [[TMP9]], -; FIXED-NEXT: [[TMP13:%.*]] = getelementptr i64, ptr [[P]], <4 x i64> [[TMP12]] -; FIXED-NEXT: [[WIDE_MASKED_GATHER4:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP13]], i32 8, <4 x i1> , <4 x i64> poison) -; FIXED-NEXT: [[TMP14:%.*]] = add <4 x i64> [[WIDE_MASKED_GATHER4]], -; FIXED-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[TMP14]], <4 x ptr> [[TMP13]], i32 8, <4 x i1> ) -; FIXED-NEXT: [[TMP15:%.*]] = add <4 x i64> [[TMP12]], -; FIXED-NEXT: [[TMP16:%.*]] = getelementptr i64, ptr [[P]], <4 x i64> [[TMP15]] -; FIXED-NEXT: [[WIDE_MASKED_GATHER5:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP16]], i32 8, <4 x i1> , <4 x i64> poison) -; FIXED-NEXT: [[TMP17:%.*]] = add <4 x i64> [[WIDE_MASKED_GATHER5]], -; FIXED-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[TMP17]], <4 x ptr> [[TMP16]], i32 8, <4 x i1> ) -; FIXED-NEXT: [[TMP18:%.*]] = add <4 x i64> [[TMP15]], -; FIXED-NEXT: [[TMP19:%.*]] = getelementptr i64, ptr [[P]], <4 x i64> [[TMP18]] -; FIXED-NEXT: [[WIDE_MASKED_GATHER6:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP19]], i32 8, <4 x i1> , <4 x i64> poison) -; FIXED-NEXT: [[TMP20:%.*]] = add <4 x i64> [[WIDE_MASKED_GATHER6]], -; FIXED-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[TMP20]], <4 x ptr> [[TMP19]], i32 8, <4 x i1> ) -; FIXED-NEXT: [[TMP21:%.*]] = add <4 x i64> [[TMP18]], -; FIXED-NEXT: [[TMP22:%.*]] = getelementptr i64, ptr [[P]], <4 x i64> [[TMP21]] -; FIXED-NEXT: [[WIDE_MASKED_GATHER7:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[TMP22]], i32 8, <4 x i1> , <4 x i64> poison) -; FIXED-NEXT: [[TMP23:%.*]] = add <4 x i64> [[WIDE_MASKED_GATHER7]], -; FIXED-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[TMP23]], <4 x ptr> [[TMP22]], i32 8, <4 x i1> ) -; FIXED-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; FIXED-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], -; FIXED-NEXT: [[TMP24:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024 -; FIXED-NEXT: br i1 [[TMP24]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] +; FIXED-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 +; FIXED-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 3 +; FIXED-NEXT: [[TMP2:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[TMP1]] +; FIXED-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[TMP2]], i32 0 +; FIXED-NEXT: [[WIDE_VEC:%.*]] = load <16 x i64>, ptr [[TMP3]], align 8 +; FIXED-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; FIXED-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; FIXED-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; FIXED-NEXT: [[STRIDED_VEC3:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; FIXED-NEXT: [[STRIDED_VEC4:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; FIXED-NEXT: [[STRIDED_VEC5:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; FIXED-NEXT: [[STRIDED_VEC6:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; FIXED-NEXT: [[STRIDED_VEC7:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; FIXED-NEXT: [[TMP4:%.*]] = add <2 x i64> [[STRIDED_VEC]], +; FIXED-NEXT: [[TMP5:%.*]] = add i64 [[TMP1]], 1 +; FIXED-NEXT: [[TMP6:%.*]] = add <2 x i64> [[STRIDED_VEC1]], +; FIXED-NEXT: [[TMP7:%.*]] = add i64 [[TMP5]], 1 +; FIXED-NEXT: [[TMP8:%.*]] = add <2 x i64> [[STRIDED_VEC2]], +; FIXED-NEXT: [[TMP9:%.*]] = add i64 [[TMP7]], 1 +; FIXED-NEXT: [[TMP10:%.*]] = add <2 x i64> [[STRIDED_VEC3]], +; FIXED-NEXT: [[TMP11:%.*]] = add i64 [[TMP9]], 1 +; FIXED-NEXT: [[TMP12:%.*]] = add <2 x i64> [[STRIDED_VEC4]], +; FIXED-NEXT: [[TMP13:%.*]] = add i64 [[TMP11]], 1 +; FIXED-NEXT: [[TMP14:%.*]] = add <2 x i64> [[STRIDED_VEC5]], +; FIXED-NEXT: [[TMP15:%.*]] = add i64 [[TMP13]], 1 +; FIXED-NEXT: [[TMP16:%.*]] = add <2 x i64> [[STRIDED_VEC6]], +; FIXED-NEXT: [[TMP17:%.*]] = add i64 [[TMP15]], 1 +; FIXED-NEXT: [[TMP18:%.*]] = getelementptr i64, ptr [[P]], i64 [[TMP17]] +; FIXED-NEXT: [[TMP19:%.*]] = add <2 x i64> [[STRIDED_VEC7]], +; FIXED-NEXT: [[TMP20:%.*]] = getelementptr i64, ptr [[TMP18]], i32 -7 +; FIXED-NEXT: [[TMP21:%.*]] = shufflevector <2 x i64> [[TMP4]], <2 x i64> [[TMP6]], <4 x i32> +; FIXED-NEXT: [[TMP22:%.*]] = shufflevector <2 x i64> [[TMP8]], <2 x i64> [[TMP10]], <4 x i32> +; FIXED-NEXT: [[TMP23:%.*]] = shufflevector <2 x i64> [[TMP12]], <2 x i64> [[TMP14]], <4 x i32> +; FIXED-NEXT: [[TMP24:%.*]] = shufflevector <2 x i64> [[TMP16]], <2 x i64> [[TMP19]], <4 x i32> +; FIXED-NEXT: [[TMP25:%.*]] = shufflevector <4 x i64> [[TMP21]], <4 x i64> [[TMP22]], <8 x i32> +; FIXED-NEXT: [[TMP26:%.*]] = shufflevector <4 x i64> [[TMP23]], <4 x i64> [[TMP24]], <8 x i32> +; FIXED-NEXT: [[TMP27:%.*]] = shufflevector <8 x i64> [[TMP25]], <8 x i64> [[TMP26]], <16 x i32> +; FIXED-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i64> [[TMP27]], <16 x i64> poison, <16 x i32> +; FIXED-NEXT: store <16 x i64> [[INTERLEAVED_VEC]], ptr [[TMP20]], align 8 +; FIXED-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 +; FIXED-NEXT: [[TMP28:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024 +; FIXED-NEXT: br i1 [[TMP28]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] ; FIXED: middle.block: ; FIXED-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]] ; FIXED: scalar.ph: @@ -1052,79 +998,57 @@ define void @load_store_factor8(ptr %p) { ; ; SCALABLE-LABEL: @load_store_factor8( ; SCALABLE-NEXT: entry: -; SCALABLE-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() -; SCALABLE-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 2 -; SCALABLE-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 1024, [[TMP1]] -; SCALABLE-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; SCALABLE-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; SCALABLE: vector.ph: -; SCALABLE-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64() -; SCALABLE-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 2 -; SCALABLE-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP3]] -; SCALABLE-NEXT: [[N_VEC:%.*]] = sub i64 1024, [[N_MOD_VF]] -; SCALABLE-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() -; SCALABLE-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 2 -; SCALABLE-NEXT: [[TMP6:%.*]] = call @llvm.experimental.stepvector.nxv2i64() -; SCALABLE-NEXT: [[TMP7:%.*]] = add [[TMP6]], zeroinitializer -; SCALABLE-NEXT: [[TMP8:%.*]] = mul [[TMP7]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[INDUCTION:%.*]] = add zeroinitializer, [[TMP8]] -; SCALABLE-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64() -; SCALABLE-NEXT: [[TMP10:%.*]] = mul i64 [[TMP9]], 2 -; SCALABLE-NEXT: [[TMP11:%.*]] = mul i64 1, [[TMP10]] -; SCALABLE-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement poison, i64 [[TMP11]], i64 0 -; SCALABLE-NEXT: [[DOTSPLAT:%.*]] = shufflevector [[DOTSPLATINSERT]], poison, zeroinitializer ; SCALABLE-NEXT: br label [[VECTOR_BODY:%.*]] ; SCALABLE: vector.body: ; SCALABLE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; SCALABLE-NEXT: [[VEC_IND:%.*]] = phi [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] -; SCALABLE-NEXT: [[TMP12:%.*]] = shl [[VEC_IND]], shufflevector ( insertelement ( poison, i64 3, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[TMP13:%.*]] = getelementptr i64, ptr [[P:%.*]], [[TMP12]] -; SCALABLE-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP13]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; SCALABLE-NEXT: [[TMP14:%.*]] = add [[WIDE_MASKED_GATHER]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP14]], [[TMP13]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; SCALABLE-NEXT: [[TMP15:%.*]] = add [[TMP12]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[TMP16:%.*]] = getelementptr i64, ptr [[P]], [[TMP15]] -; SCALABLE-NEXT: [[WIDE_MASKED_GATHER1:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP16]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; SCALABLE-NEXT: [[TMP17:%.*]] = add [[WIDE_MASKED_GATHER1]], shufflevector ( insertelement ( poison, i64 2, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP17]], [[TMP16]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; SCALABLE-NEXT: [[TMP18:%.*]] = add [[TMP15]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[TMP19:%.*]] = getelementptr i64, ptr [[P]], [[TMP18]] -; SCALABLE-NEXT: [[WIDE_MASKED_GATHER2:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP19]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; SCALABLE-NEXT: [[TMP20:%.*]] = add [[WIDE_MASKED_GATHER2]], shufflevector ( insertelement ( poison, i64 3, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP20]], [[TMP19]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; SCALABLE-NEXT: [[TMP21:%.*]] = add [[TMP18]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[TMP22:%.*]] = getelementptr i64, ptr [[P]], [[TMP21]] -; SCALABLE-NEXT: [[WIDE_MASKED_GATHER3:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP22]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; SCALABLE-NEXT: [[TMP23:%.*]] = add [[WIDE_MASKED_GATHER3]], shufflevector ( insertelement ( poison, i64 4, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP23]], [[TMP22]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; SCALABLE-NEXT: [[TMP24:%.*]] = add [[TMP21]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[TMP25:%.*]] = getelementptr i64, ptr [[P]], [[TMP24]] -; SCALABLE-NEXT: [[WIDE_MASKED_GATHER4:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP25]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; SCALABLE-NEXT: [[TMP26:%.*]] = add [[WIDE_MASKED_GATHER4]], shufflevector ( insertelement ( poison, i64 5, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP26]], [[TMP25]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; SCALABLE-NEXT: [[TMP27:%.*]] = add [[TMP24]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[TMP28:%.*]] = getelementptr i64, ptr [[P]], [[TMP27]] -; SCALABLE-NEXT: [[WIDE_MASKED_GATHER5:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP28]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; SCALABLE-NEXT: [[TMP29:%.*]] = add [[WIDE_MASKED_GATHER5]], shufflevector ( insertelement ( poison, i64 6, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP29]], [[TMP28]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; SCALABLE-NEXT: [[TMP30:%.*]] = add [[TMP27]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[TMP31:%.*]] = getelementptr i64, ptr [[P]], [[TMP30]] -; SCALABLE-NEXT: [[WIDE_MASKED_GATHER6:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP31]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; SCALABLE-NEXT: [[TMP32:%.*]] = add [[WIDE_MASKED_GATHER6]], shufflevector ( insertelement ( poison, i64 7, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP32]], [[TMP31]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; SCALABLE-NEXT: [[TMP33:%.*]] = add [[TMP30]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: [[TMP34:%.*]] = getelementptr i64, ptr [[P]], [[TMP33]] -; SCALABLE-NEXT: [[WIDE_MASKED_GATHER7:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[TMP34]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), poison) -; SCALABLE-NEXT: [[TMP35:%.*]] = add [[WIDE_MASKED_GATHER7]], shufflevector ( insertelement ( poison, i64 8, i64 0), poison, zeroinitializer) -; SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[TMP35]], [[TMP34]], i32 8, shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer)) -; SCALABLE-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP5]] -; SCALABLE-NEXT: [[VEC_IND_NEXT]] = add [[VEC_IND]], [[DOTSPLAT]] -; SCALABLE-NEXT: [[TMP36:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; SCALABLE-NEXT: br i1 [[TMP36]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] +; SCALABLE-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 +; SCALABLE-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 3 +; SCALABLE-NEXT: [[TMP2:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[TMP1]] +; SCALABLE-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[TMP2]], i32 0 +; SCALABLE-NEXT: [[WIDE_VEC:%.*]] = load <16 x i64>, ptr [[TMP3]], align 8 +; SCALABLE-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; SCALABLE-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; SCALABLE-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; SCALABLE-NEXT: [[STRIDED_VEC3:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; SCALABLE-NEXT: [[STRIDED_VEC4:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; SCALABLE-NEXT: [[STRIDED_VEC5:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; SCALABLE-NEXT: [[STRIDED_VEC6:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; SCALABLE-NEXT: [[STRIDED_VEC7:%.*]] = shufflevector <16 x i64> [[WIDE_VEC]], <16 x i64> poison, <2 x i32> +; SCALABLE-NEXT: [[TMP4:%.*]] = add <2 x i64> [[STRIDED_VEC]], +; SCALABLE-NEXT: [[TMP5:%.*]] = add i64 [[TMP1]], 1 +; SCALABLE-NEXT: [[TMP6:%.*]] = add <2 x i64> [[STRIDED_VEC1]], +; SCALABLE-NEXT: [[TMP7:%.*]] = add i64 [[TMP5]], 1 +; SCALABLE-NEXT: [[TMP8:%.*]] = add <2 x i64> [[STRIDED_VEC2]], +; SCALABLE-NEXT: [[TMP9:%.*]] = add i64 [[TMP7]], 1 +; SCALABLE-NEXT: [[TMP10:%.*]] = add <2 x i64> [[STRIDED_VEC3]], +; SCALABLE-NEXT: [[TMP11:%.*]] = add i64 [[TMP9]], 1 +; SCALABLE-NEXT: [[TMP12:%.*]] = add <2 x i64> [[STRIDED_VEC4]], +; SCALABLE-NEXT: [[TMP13:%.*]] = add i64 [[TMP11]], 1 +; SCALABLE-NEXT: [[TMP14:%.*]] = add <2 x i64> [[STRIDED_VEC5]], +; SCALABLE-NEXT: [[TMP15:%.*]] = add i64 [[TMP13]], 1 +; SCALABLE-NEXT: [[TMP16:%.*]] = add <2 x i64> [[STRIDED_VEC6]], +; SCALABLE-NEXT: [[TMP17:%.*]] = add i64 [[TMP15]], 1 +; SCALABLE-NEXT: [[TMP18:%.*]] = getelementptr i64, ptr [[P]], i64 [[TMP17]] +; SCALABLE-NEXT: [[TMP19:%.*]] = add <2 x i64> [[STRIDED_VEC7]], +; SCALABLE-NEXT: [[TMP20:%.*]] = getelementptr i64, ptr [[TMP18]], i32 -7 +; SCALABLE-NEXT: [[TMP21:%.*]] = shufflevector <2 x i64> [[TMP4]], <2 x i64> [[TMP6]], <4 x i32> +; SCALABLE-NEXT: [[TMP22:%.*]] = shufflevector <2 x i64> [[TMP8]], <2 x i64> [[TMP10]], <4 x i32> +; SCALABLE-NEXT: [[TMP23:%.*]] = shufflevector <2 x i64> [[TMP12]], <2 x i64> [[TMP14]], <4 x i32> +; SCALABLE-NEXT: [[TMP24:%.*]] = shufflevector <2 x i64> [[TMP16]], <2 x i64> [[TMP19]], <4 x i32> +; SCALABLE-NEXT: [[TMP25:%.*]] = shufflevector <4 x i64> [[TMP21]], <4 x i64> [[TMP22]], <8 x i32> +; SCALABLE-NEXT: [[TMP26:%.*]] = shufflevector <4 x i64> [[TMP23]], <4 x i64> [[TMP24]], <8 x i32> +; SCALABLE-NEXT: [[TMP27:%.*]] = shufflevector <8 x i64> [[TMP25]], <8 x i64> [[TMP26]], <16 x i32> +; SCALABLE-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i64> [[TMP27]], <16 x i64> poison, <16 x i32> +; SCALABLE-NEXT: store <16 x i64> [[INTERLEAVED_VEC]], ptr [[TMP20]], align 8 +; SCALABLE-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 +; SCALABLE-NEXT: [[TMP28:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024 +; SCALABLE-NEXT: br i1 [[TMP28]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] ; SCALABLE: middle.block: -; SCALABLE-NEXT: [[CMP_N:%.*]] = icmp eq i64 1024, [[N_VEC]] -; SCALABLE-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] +; SCALABLE-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]] ; SCALABLE: scalar.ph: -; SCALABLE-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; SCALABLE-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 1024, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] ; SCALABLE-NEXT: br label [[LOOP:%.*]] ; SCALABLE: loop: ; SCALABLE-NEXT: [[I:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[NEXTI:%.*]], [[LOOP]] ] diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/interleaved-cost.ll b/llvm/test/Transforms/LoopVectorize/RISCV/interleaved-cost.ll index a724ef87abb3..7bfd2eaad574 100644 --- a/llvm/test/Transforms/LoopVectorize/RISCV/interleaved-cost.ll +++ b/llvm/test/Transforms/LoopVectorize/RISCV/interleaved-cost.ll @@ -72,12 +72,12 @@ entry: ; VF_8: Found an estimated cost of 0 for VF 8 For instruction: store i8 %a1, ptr %p1, align 1 ; VF_8-NEXT: Found an estimated cost of 3 for VF 8 For instruction: store i8 %a2, ptr %p2, align 1 ; VF_16-LABEL: Checking a loop in 'i8_factor_3' -; VF_16: Found an estimated cost of 48 for VF 16 For instruction: %l0 = load i8, ptr %p0, align 1 +; VF_16: Found an estimated cost of 5 for VF 16 For instruction: %l0 = load i8, ptr %p0, align 1 ; VF_16-NEXT: Found an estimated cost of 0 for VF 16 For instruction: %l1 = load i8, ptr %p1, align 1 ; VF_16-NEXT: Found an estimated cost of 0 for VF 16 For instruction: %l2 = load i8, ptr %p2, align 1 ; VF_16: Found an estimated cost of 0 for VF 16 For instruction: store i8 %a0, ptr %p0, align 1 ; VF_16: Found an estimated cost of 0 for VF 16 For instruction: store i8 %a1, ptr %p1, align 1 -; VF_16-NEXT: Found an estimated cost of 48 for VF 16 For instruction: store i8 %a2, ptr %p2, align 1 +; VF_16-NEXT: Found an estimated cost of 5 for VF 16 For instruction: store i8 %a2, ptr %p2, align 1 for.body: %i = phi i64 [ 0, %entry ], [ %i.next, %for.body ] %p0 = getelementptr inbounds %i8.3, ptr %data, i64 %i, i32 0 -- GitLab From 6bf185920bd6831efc151d7d4158d6390006c50b Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Thu, 16 May 2024 14:44:58 +1000 Subject: [PATCH 458/578] [ORC] Support visionOS in LC_BUILD_VERSIONs for JITDylibs. rdar://127846581 --- llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp index 2b397b2d48e7..b477a48af290 100644 --- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp +++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp @@ -277,6 +277,10 @@ MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple(const Triple &TT, Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR : MachO::PLATFORM_WATCHOS; break; + case Triple::XROS: + Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_XROS_SIMULATOR + : MachO::PLATFORM_XROS; + break; default: return std::nullopt; } -- GitLab From 566fbb450092bf8c9f966a6ab1b0381626e3e535 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Thu, 16 May 2024 12:57:28 +0800 Subject: [PATCH 459/578] [RISCV] Defer creating RISCVInsertVSETVLI to avoid leak with -stop-after (#92303) As noted in https://github.com/llvm/llvm-project/pull/91440#discussion_r1601976425, if the pass pipeline stops early because of -stop-after any allocated passes added with insertPass will not be freed if they haven't already been added. This was showing up as a failure on the address sanitizer buildbots. We can fix it by instead passing the pass ID instead so that allocation is deferred. --- llvm/lib/Target/RISCV/RISCV.h | 1 + llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp | 1 + llvm/lib/Target/RISCV/RISCVTargetMachine.cpp | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCV.h b/llvm/lib/Target/RISCV/RISCV.h index d405395dcf9e..2b8688c5de61 100644 --- a/llvm/lib/Target/RISCV/RISCV.h +++ b/llvm/lib/Target/RISCV/RISCV.h @@ -60,6 +60,7 @@ void initializeRISCVExpandAtomicPseudoPass(PassRegistry &); FunctionPass *createRISCVInsertVSETVLIPass(); void initializeRISCVInsertVSETVLIPass(PassRegistry &); +extern char &RISCVInsertVSETVLIID; FunctionPass *createRISCVCoalesceVSETVLIPass(); void initializeRISCVCoalesceVSETVLIPass(PassRegistry &); diff --git a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp index 363007d7b68b..324ce5cb5ed7 100644 --- a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp +++ b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp @@ -868,6 +868,7 @@ private: } // end anonymous namespace char RISCVInsertVSETVLI::ID = 0; +char &llvm::RISCVInsertVSETVLIID = RISCVInsertVSETVLI::ID; INITIALIZE_PASS(RISCVInsertVSETVLI, DEBUG_TYPE, RISCV_INSERT_VSETVLI_NAME, false, false) diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp index 5d598a275a00..5aab138dae40 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -548,9 +548,9 @@ void RISCVPassConfig::addPreRegAlloc() { // Run RISCVInsertVSETVLI after PHI elimination. On O1 and above do it after // register coalescing so needVSETVLIPHI doesn't need to look through COPYs. if (TM->getOptLevel() == CodeGenOptLevel::None) - insertPass(&PHIEliminationID, createRISCVInsertVSETVLIPass()); + insertPass(&PHIEliminationID, &RISCVInsertVSETVLIID); else - insertPass(&RegisterCoalescerID, createRISCVInsertVSETVLIPass()); + insertPass(&RegisterCoalescerID, &RISCVInsertVSETVLIID); } void RISCVPassConfig::addFastRegAlloc() { -- GitLab From 70a926cfb1d4af326be5afe6419991aeff8f44b2 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Thu, 16 May 2024 02:39:04 -0300 Subject: [PATCH 460/578] [clang] NFC: Add a few more interesting test cases for CWG2398 --- clang/test/SemaTemplate/cwg2398.cpp | 58 +++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/clang/test/SemaTemplate/cwg2398.cpp b/clang/test/SemaTemplate/cwg2398.cpp index a20155486b12..d163354b2e5f 100644 --- a/clang/test/SemaTemplate/cwg2398.cpp +++ b/clang/test/SemaTemplate/cwg2398.cpp @@ -137,3 +137,61 @@ namespace ttp_defaults { // old-error@-2 {{template template argument has different template parameters}} // old-error@-3 {{explicit instantiation of 'f' does not refer to a function template}} } // namespace ttp_defaults + +namespace ttp_only { + template