From f76c5d2505ef28107fdb2b56c47fb60dc7c68bdc Mon Sep 17 00:00:00 2001 From: ArtherusAA Date: Fri, 12 Nov 2021 14:02:24 +0000 Subject: [PATCH 01/14] feat tsar: add remove_redarray pragma --- include/tsar/Support/Directives.td | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/tsar/Support/Directives.td b/include/tsar/Support/Directives.td index f0e2024e..55498d62 100644 --- a/include/tsar/Support/Directives.td +++ b/include/tsar/Support/Directives.td @@ -139,6 +139,9 @@ def Rename : Clause<"rename", Transform>; def LoopInterchange : Clause<"interchange", Transform, [LParen, PPIdentifier, Comma, PPIdentifier, RParen]>; +def RemoveRedarray : Clause<"remove_redarray", Transform, + [LParen, Identifier, ZeroOrMore<[Comma, Identifier]>, RParen]>; + def Replace : Clause<"replace", Transform, [ZeroOrOne<[LParen, Identifier, ZeroOrMore<[Comma, Identifier]>, RParen]>]>; From 5ab742522c6eb534289b7084950eb18f5941897b Mon Sep 17 00:00:00 2001 From: ArtherusAA Date: Fri, 26 Nov 2021 14:39:10 +0000 Subject: [PATCH 02/14] feat remove_redarray: add ClangRemoveRedarrayVisitor(draft) --- include/tsar/Support/Directives.td | 2 +- lib/Transform/Clang/RemoveRedarray.cpp | 657 +++++++++++++++++++++++++ 2 files changed, 658 insertions(+), 1 deletion(-) create mode 100644 lib/Transform/Clang/RemoveRedarray.cpp diff --git a/include/tsar/Support/Directives.td b/include/tsar/Support/Directives.td index 55498d62..b113cd6d 100644 --- a/include/tsar/Support/Directives.td +++ b/include/tsar/Support/Directives.td @@ -140,7 +140,7 @@ def LoopInterchange : Clause<"interchange", Transform, [LParen, PPIdentifier, Comma, PPIdentifier, RParen]>; def RemoveRedarray : Clause<"remove_redarray", Transform, - [LParen, Identifier, ZeroOrMore<[Comma, Identifier]>, RParen]>; + [LParen, Identifier, Comma, NumericConstant, RParen]>; def Replace : Clause<"replace", Transform, [ZeroOrOne<[LParen, Identifier, ZeroOrMore<[Comma, Identifier]>, RParen]>]>; diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp new file mode 100644 index 00000000..d851580d --- /dev/null +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -0,0 +1,657 @@ +//===--- LoopInterchange.cpp - Loop Interchagne (Clang) ---------*- C++ -*-===// +// +// Traits Static Analyzer (SAPFOR) +// +// Copyright 2021 DVM System Group +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +// +// This file implements a pass to perform remove redarray in C programs. +// +//===----------------------------------------------------------------------===// + +#include "tsar/ADT/SpanningTreeRelation.h" +#include "tsar/Analysis/AnalysisServer.h" +#include "tsar/Analysis/Clang/CanonicalLoop.h" +#include "tsar/Analysis/Clang/DIMemoryMatcher.h" +#include "tsar/Analysis/Clang/GlobalInfoExtractor.h" +#include "tsar/Analysis/Clang/MemoryMatcher.h" +#include "tsar/Analysis/Clang/NoMacroAssert.h" +#include "tsar/Analysis/Clang/PerfectLoop.h" +#include "tsar/Analysis/DFRegionInfo.h" +#include "tsar/Analysis/Memory/ClonedDIMemoryMatcher.h" +#include "tsar/Analysis/Memory/DIClientServerInfo.h" +#include "tsar/Analysis/Memory/DIDependencyAnalysis.h" +#include "tsar/Analysis/Memory/DIEstimateMemory.h" +#include "tsar/Analysis/Memory/DIMemoryTrait.h" +#include "tsar/Analysis/Memory/EstimateMemory.h" +#include "tsar/Analysis/Memory/MemoryAccessUtils.h" +#include "tsar/Analysis/Memory/MemoryTraitUtils.h" +#include "tsar/Analysis/Memory/Passes.h" +#include "tsar/Analysis/Memory/Utils.h" +#include "tsar/Core/Query.h" +#include "tsar/Frontend/Clang/Pragma.h" +#include "tsar/Frontend/Clang/TransformationContext.h" +#include "tsar/Support/Clang/Diagnostic.h" +#include "tsar/Support/GlobalOptions.h" +#include "tsar/Support/MetadataUtils.h" +#include "tsar/Transform/Clang/Passes.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; +using namespace tsar; + +#undef DEBUG_TYPE +#define DEBUG_TYPE "clang-remove-redarray" +#define DEBUG_PREFIX "[REMOVE REDARRAY]: " + +namespace { +class ClangRemoveRedarray : public FunctionPass, private bcl::Uncopyable { +public: + static char ID; + + ClangRemoveRedarray() : FunctionPass(ID) { + initializeClangRemoveRedarrayPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +class ClangRemoveRedarrayInfo final : public tsar::PassGroupInfo { + void addBeforePass(legacy::PassManager &Passes) const override; + void addAfterPass(legacy::PassManager &Passes) const override; +}; +} // namespace + +void ClangRemoveRedarrayInfo::addBeforePass( + legacy::PassManager &Passes) const { + addImmutableAliasAnalysis(Passes); + addInitialTransformations(Passes); + Passes.add(createAnalysisSocketImmutableStorage()); + Passes.add(createDIMemoryTraitPoolStorage()); + Passes.add(createDIMemoryEnvironmentStorage()); + Passes.add(createDIEstimateMemoryPass()); + Passes.add(createDIMemoryAnalysisServer()); + Passes.add(createAnalysisWaitServerPass()); + Passes.add(createMemoryMatcherPass()); + Passes.add(createAnalysisWaitServerPass()); +} + +void ClangRemoveRedarrayInfo::addAfterPass(legacy::PassManager &Passes) const { + Passes.add(createAnalysisReleaseServerPass()); + Passes.add(createAnalysisCloseConnectionPass()); +} + +void ClangRemoveRedarray::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.setPreservesAll(); +} + +char ClangRemoveRedarray::ID = 0; + +INITIALIZE_PASS_IN_GROUP_BEGIN(ClangRemoveRedarray, "clang-remove-redarray", + "Remove Redarray (Clang)", false, false, + TransformationQueryManager::getPassRegistry()) +INITIALIZE_PASS_IN_GROUP_INFO(ClangRemoveRedarrayInfo) +INITIALIZE_PASS_DEPENDENCY(AnalysisClientServerMatcherWrapper) +INITIALIZE_PASS_DEPENDENCY(CanonicalLoopPass) +INITIALIZE_PASS_DEPENDENCY(ClangDIMemoryMatcherPass) +INITIALIZE_PASS_DEPENDENCY(ClangGlobalInfoPass) +INITIALIZE_PASS_DEPENDENCY(ClonedDIMemoryMatcherWrapper) +INITIALIZE_PASS_DEPENDENCY(DIDependencyAnalysisPass) +INITIALIZE_PASS_DEPENDENCY(DIEstimateMemoryPass) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(EstimateMemoryPass) +INITIALIZE_PASS_DEPENDENCY(GlobalOptionsImmutableWrapper) +INITIALIZE_PASS_DEPENDENCY(MemoryMatcherImmutableWrapper) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(TransformationEnginePass) +INITIALIZE_PASS_IN_GROUP_END(ClangRemoveRedarray, "clang-remove-redarray", + "Remove Redarray (Clang)", false, false, + TransformationQueryManager::getPassRegistry()) + +namespace { +class RedarrayClauseVisitor + : public clang::RecursiveASTVisitor { +public: + explicit RedarrayClauseVisitor( + SmallVectorImpl> &Ls) + : mLiterals(Ls) {} + bool VisitStringLiteral(clang::StringLiteral *SL) { + if (SL->getString() != getName(ClauseId::RemoveRedarray)) + mLiterals.emplace_back(SL, mClause); + return true; + } + + void setClause(clang::Stmt *C) noexcept { mClause = C; } + +private: + SmallVectorImpl> &mLiterals; + clang::Stmt *mClause{nullptr}; +}; + +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + +class ClangRemoveRedarrayVisitor + : public clang::RecursiveASTVisitor { + enum LoopKind : uint8_t { + Ok = 0, + NotCanonical = 1u << 0, + NotPerfect = 1u << 1, + NotAnalyzed = 1u << 2, + HasDependency = 1u << 3, + LLVM_MARK_AS_BITMASK_ENUM(HasDependency) + }; + + using VarList = SmallVector; + + using LoopNest = SmallVector< + std::tuple, + 4>; + +public: + ClangRemoveRedarrayVisitor(ClangRemoveRedarray &P, llvm::Function &F, + ClangTransformationContext *TfmCtx, + const ASTImportInfo &ImportInfo) + : mImportInfo(ImportInfo), mRewriter(TfmCtx->getRewriter()), + mSrcMgr(mRewriter.getSourceMgr()), mLangOpts(mRewriter.getLangOpts()), + mRawInfo(P.getAnalysis().getRawInfo()), + mGlobalOpts( + P.getAnalysis().getOptions()), + mMemMatcher(P.getAnalysis()->Matcher), + mDIMemMatcher(P.getAnalysis().getMatcher()), + mPerfectLoopInfo( + P.getAnalysis().getPerfectLoopInfo()), + mCanonicalLoopInfo( + P.getAnalysis().getCanonicalLoopInfo()), + mAT(P.getAnalysis().getAliasTree()), + mTLI(P.getAnalysis().getTLI(F)), + mDT(P.getAnalysis().getDomTree()), + mDIMInfo(P.getAnalysis().getAliasTree(), P, F) { + if (mDIMInfo.isValid()) + mSTR = SpanningTreeRelation{mDIMInfo.DIAT}; + } + + bool TraverseForStmt(clang::ForStmt *FS) { + if (mStatus != GET_REFERENCES) + return RecursiveASTVisitor::TraverseForStmt(FS); + auto CanonicalItr{find_if(mCanonicalLoopInfo, [FS](auto *Info) { + return Info->getASTLoop() == FS; + })}; + auto IsCanonical{false}, IsPerfect{false}; + mInductions.emplace_back(nullptr, nullptr, FS, Ok, VarList{}, nullptr); + if (CanonicalItr != mCanonicalLoopInfo.end() && + (*CanonicalItr)->isCanonical()) { + IsCanonical = true; + IsPerfect = mPerfectLoopInfo.count((*CanonicalItr)->getLoop()); + auto VarItr{mMemMatcher.find((*CanonicalItr)->getInduction())}; + std::get(mInductions.back()) = VarItr->get(); + std::get(mInductions.back()) = *CanonicalItr; + } + if (!IsCanonical) + std::get(mInductions.back()) |= NotCanonical; + if (!IsPerfect) + std::get(mInductions.back()) |= NotPerfect; + if (!mIsStrict || !IsCanonical) { + if (!IsCanonical) + std::get(mInductions.back()) |= NotAnalyzed; + return RecursiveASTVisitor::TraverseForStmt(FS); + } + auto Dependency{false}; + auto *L{(*CanonicalItr)->getLoop()->getLoop()}; + if (!mDIMInfo.isValid()) { + std::get(mInductions.back()) |= NotAnalyzed; + return RecursiveASTVisitor::TraverseForStmt(FS); + } + auto *DIDepSet{mDIMInfo.findFromClient(*L)}; + if (!DIDepSet) { + std::get(mInductions.back()) |= NotAnalyzed; + return RecursiveASTVisitor::TraverseForStmt(FS); + } + DenseSet Coverage; + accessCoverage(*DIDepSet, *mDIMInfo.DIAT, Coverage, + mGlobalOpts.IgnoreRedundantMemory); + if (!Coverage.empty()) + for (auto &Trait : *DIDepSet) { + if (!Coverage.count(Trait.getNode()) || hasNoDep(Trait) || + Trait.is_any()) + continue; + if(Trait.is_any() && + Trait.size() == 1) { + if (auto DIEM{ + dyn_cast((*Trait.begin())->getMemory())}; + DIEM && DIEM->getExpression()->getNumElements() == 0) { + auto *ClientDIM{ + mDIMInfo.getClientMemory(const_cast(DIEM))}; + assert(ClientDIM && "Origin memory must exist!"); + auto VarToDI{mDIMemMatcher.find( + cast(ClientDIM)->getVariable())}; + if (Trait.is()) { + if (VarToDI->template get() == + std::get(mInductions.back())) { + std::get(mInductions.back()) = DIEM; + continue; + } + } else { + std::get(mInductions.back()) + .push_back(VarToDI->template get()); + continue; + } + } + } + std::get(mInductions.back()) |= HasDependency; + break; + } + return RecursiveASTVisitor::TraverseForStmt(FS); + } + + bool TraverseDecl(clang::Decl *D) { + if (!D) + return RecursiveASTVisitor::TraverseDecl(D); + if (mStatus == TRAVERSE_STMT) { + toDiag(mSrcMgr.getDiagnostics(), D->getLocation(), + tsar::diag::warn_interchange_not_for_loop); // TODO: change this warning + resetVisitor(); + } + return RecursiveASTVisitor::TraverseDecl(D); + } + + bool TraverseStmt(clang::Stmt *S) { + if (!S) + return RecursiveASTVisitor::TraverseStmt(S); + switch (mStatus) { + case SEARCH_PRAGMA: { + Pragma P{*S}; + llvm::SmallVector Clauses; + if (!findClause(P, ClauseId::RemoveRedarray, Clauses)) + return RecursiveASTVisitor::TraverseStmt(S); + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "found remove_redarray clause\n"); + RedarrayClauseVisitor SCV{mSwaps}; + for (auto *C : Clauses) { + SCV.setClause(C); + SCV.TraverseStmt(C); + } + mIsStrict = !findClause(P, ClauseId::NoStrict, Clauses); + LLVM_DEBUG(if (!mIsStrict) dbgs() + << DEBUG_PREFIX << "found 'nostrict' clause\n"); + llvm::SmallVector ToRemove; + auto IsPossible{pragmaRangeToRemove(P, Clauses, mSrcMgr, mLangOpts, + mImportInfo, ToRemove)}; + if (!IsPossible.first) + if (IsPossible.second & PragmaFlags::IsInMacro) + toDiag(mSrcMgr.getDiagnostics(), Clauses.front()->getBeginLoc(), + tsar::diag::warn_remove_directive_in_macro); + else if (IsPossible.second & PragmaFlags::IsInHeader) + toDiag(mSrcMgr.getDiagnostics(), Clauses.front()->getBeginLoc(), + tsar::diag::warn_remove_directive_in_include); + else + toDiag(mSrcMgr.getDiagnostics(), Clauses.front()->getBeginLoc(), + tsar::diag::warn_remove_directive); + clang::Rewriter::RewriteOptions RemoveEmptyLine; + /// TODO (kaniandr@gmail.com): it seems that RemoveLineIfEmpty is + /// set to true then removing (in RewriterBuffer) works incorrect. + RemoveEmptyLine.RemoveLineIfEmpty = false; + for (auto SR : ToRemove) + mRewriter.RemoveText(SR, RemoveEmptyLine); + Clauses.clear(); + mStatus = TRAVERSE_STMT; + return true; + } + case TRAVERSE_STMT: { + if (!isa(S)) { + toDiag(mSrcMgr.getDiagnostics(), S->getBeginLoc(), + tsar::diag::warn_interchange_not_for_loop); // TODO: change this warn + resetVisitor(); + return RecursiveASTVisitor::TraverseStmt(S); + } + bool HasMacro{false}; + for_each_macro(S, mSrcMgr, mLangOpts, mRawInfo.Macros, + [&HasMacro, this](clang::SourceLocation Loc) { + if (!HasMacro) { + toDiag(mSrcMgr.getDiagnostics(), Loc, + tsar::diag::note_assert_no_macro); + HasMacro = true; + } + }); + if (HasMacro) { + resetVisitor(); + return RecursiveASTVisitor::TraverseStmt(S); + } + mStatus = GET_REFERENCES; + auto Res = TraverseForStmt(cast(S)); + if (!Res) { + resetVisitor(); + return false; + } + // Match induction names from clauses to loop induction variables. + unsigned MaxIdx{0}; + llvm::SmallVector ValueSwaps; + for (auto [Literal, Clause] : mSwaps) { + auto Str{Literal->getString()}; + unsigned InductIdx{0}, InductIdxE = mInductions.size(); + for (; InductIdx < InductIdxE; ++InductIdx) { + if (!std::get(mInductions[InductIdx])) + continue; + if (std::get(mInductions[InductIdx])->getName() == + Str) { + ValueSwaps.push_back( + std::get(mInductions[InductIdx])); + MaxIdx = (InductIdx > MaxIdx) ? InductIdx : MaxIdx; + break; + } + } + if (InductIdx == InductIdxE) { + toDiag(mSrcMgr.getDiagnostics(), Clause->getBeginLoc(), + tsar::diag::warn_disable_loop_interchange); + toDiag(mSrcMgr.getDiagnostics(), Literal->getBeginLoc(), + tsar::diag::note_interchange_induction_mismatch) + << Str; + resetVisitor(); + return RecursiveASTVisitor::TraverseStmt(S); + } + } + // Check whether transfromation is possible. + auto checkLoop = [this](unsigned I, unsigned MaxIdx) { + auto checkPrivatizable = [](VarList &L, auto I, auto EI) { + for (auto *V : L) + if (EI == std::find_if(I, EI, [V](auto &Induct) { + return std::get(Induct) == V; + })) + return false; + + return true; + }; + if (std::get(mInductions[I]) & NotCanonical) { + toDiag(mSrcMgr.getDiagnostics(), + std::get(mInductions[I])->getBeginLoc(), + tsar::diag::warn_interchange_not_canonical); + } else if (std::get(mInductions[I]) & HasDependency) { + toDiag(mSrcMgr.getDiagnostics(), + std::get(mInductions[I])->getBeginLoc(), + tsar::diag::warn_interchange_dependency); + } else if (!mIsStrict) { + return true; + } else if (std::get(mInductions[I]) & NotAnalyzed) { + toDiag(mSrcMgr.getDiagnostics(), + std::get(mInductions[I])->getBeginLoc(), + tsar::diag::warn_interchange_no_analysis); + } else if (!checkPrivatizable(std::get(mInductions[I]), + mInductions.begin() + I + 1, + mInductions.end())) { + toDiag(mSrcMgr.getDiagnostics(), + std::get(mInductions[I])->getBeginLoc(), + tsar::diag::warn_interchange_dependency); + } else if (auto *For{isMemoryAccessedIn( + std::get(mInductions[I]), + std::get(mInductions[I]) + ->getLoop() + ->getLoop(), + mInductions.begin() + I + 1, + mInductions.begin() + MaxIdx + 1)}) { + toDiag(mSrcMgr.getDiagnostics(), + std::get(mInductions[I])->getBeginLoc(), + tsar::diag::warn_disable_loop_interchange); + toDiag(mSrcMgr.getDiagnostics(), For->getBeginLoc(), + tsar::diag::note_interchange_irregular_loop_nest); + } else { + return true; + } + return false; + }; + auto IsPossible(true); + for (auto I{0u}; I < MaxIdx; I++) { + if (std::get(mInductions[I]) & NotPerfect) { + IsPossible = false; + toDiag(mSrcMgr.getDiagnostics(), + std::get(mInductions[I])->getBeginLoc(), + tsar::diag::warn_interchange_not_perfect); + } else { + IsPossible &= checkLoop(I, MaxIdx); + } + } + // Check the innermost loop which participates in the transformation. + // Note, the it may have not canonical loop form. + IsPossible &= checkLoop(MaxIdx, MaxIdx); + if (!IsPossible) { + resetVisitor(); + return RecursiveASTVisitor::TraverseStmt(S); + } + // Deduce new order. + SmallVector Order; + std::transform(mInductions.begin(), mInductions.begin() + MaxIdx + 1, + std::back_inserter(Order), + [](auto &I) { return std::get(I); }); + for (unsigned I{0}, EI = ValueSwaps.size(); I < EI; I += 2) { + auto FirstItr{find(Order, ValueSwaps[I])}; + assert(FirstItr != Order.end() && "Induction must exist!"); + auto SecondItr{find(Order, ValueSwaps[I + 1])}; + assert(SecondItr != Order.end() && "Induction must exist!"); + std::swap(*FirstItr, *SecondItr); + } + // Collect sources of loop headers before the transformation. Note, do not + // use Rewriter::ReplaceText(SourceRange, SourceRange) because it uses + // Rewriter::getRangeSize(SourceRange) to compute a length of a destination + // as well as a length of a source and this method uses rewritten text to + // collect size. Thus, the size of the source can be computed in the wrong + // way because the transformation of outer loops has already taken place. + SmallVector Sources; + for (auto I{0u}; I < MaxIdx + 1; I++) { + clang::SourceRange Source{ + std::get(mInductions[I])->getInit()->getBeginLoc(), + std::get(mInductions[I])->getInc()->getEndLoc()}; + Sources.push_back(mRewriter.getRewrittenText(Source)); + } + // Interchange loop headers. + for (auto I{0u}; I < MaxIdx + 1 ; I++) { + if (Order[I] != std::get(mInductions[I])) { + auto OriginItr{find_if(mInductions, [What = Order[I]](auto &Induct) { + return std::get(Induct) == What; + })}; + clang::SourceRange Destination( + std::get(mInductions[I]) + ->getInit() + ->getBeginLoc(), + std::get(mInductions[I]) + ->getInc() + ->getEndLoc()); + mRewriter.ReplaceText( + Destination, + Sources[std::distance(mInductions.begin(), OriginItr)]); + } + } + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << ": finish pragma processing\n"); + resetVisitor(); + return true; + } + } + return RecursiveASTVisitor::TraverseStmt(S); + } + + +private: + void resetVisitor() { + mStatus = SEARCH_PRAGMA; + mSwaps.clear(); + mInductions.clear(); + } + + /// Return true if a specified induction variable `DIM` of a loop `L` may be + /// accessed in an any header of specified canonical loops. + clang::ForStmt *isMemoryAccessedIn(const DIMemory *DIM, const Loop *L, + LoopNest::iterator I, + LoopNest::iterator EI) { + assert(DIM && + "Results of canonical loop analysis must be available for a loop!"); + for (auto &Induct : make_range(I, EI)) { + if (isMemoryAccessedIn( + DIM, std::get(Induct)->getStart()) || + isMemoryAccessedIn( + DIM, std::get(Induct)->getEnd()) || + isMemoryAccessedIn( + DIM, L, std::get(Induct)->getStep())) + return std::get(Induct); + } + return nullptr; + } + + /// Return true if a specified induction variable `DIM` of a loop `L` may be + /// accessed in a specified expression `S`. + bool isMemoryAccessedIn(const DIMemory *DIM, const Loop *L, const SCEV *S) { + if (!S) + return true; + struct SCEVMemorySearch { + SCEVMemorySearch(const Loop *Lp) : L(Lp) {} + bool follow(const SCEV *S) { + if (auto *AddRec{dyn_cast(S)}; + AddRec && AddRec->getLoop() == L) + L = nullptr; + else if (auto *Unknown{dyn_cast(S)}) + Values.push_back(Unknown->getValue()); + return true; + } + bool isDone() { + // Finish search if reference to a loop has been found. + return !L; + } + SmallVector Values; + const Loop *L; + } Visitor{L}; + visitAll(S, Visitor); + if (!Visitor.L) + return true; + for (auto *V : Visitor.Values) + if (isMemoryAccessedIn(DIM, V)) + return true; + return false; + } + + /// Return true if a specified induction variable `DIM` of a loop `L` may be + /// accessed in a specified value `V`. + bool isMemoryAccessedIn(const DIMemory *DIM, Value *V) { + if (!V) + return true; + if (isa(V)) + return false; + if (auto *Inst{dyn_cast(V)}) { + auto &DL{Inst->getModule()->getDataLayout()}; + bool Result{false}; + auto DIN{DIM->getAliasNode()}; + for_each_memory( + *Inst, mTLI, + [this, DIN, &DL, &Result](Instruction &, MemoryLocation &&Loc, + unsigned, AccessInfo R, AccessInfo W) { + if (Result) + return; + if (R == AccessInfo::No && W == AccessInfo::No) + return; + auto EM{mAT.find(Loc)}; + assert(EM && "Estimate memory location must not be null!"); + auto *DIM{mDIMInfo.findFromClient(*EM->getTopLevelParent(), DL, mDT) + .get()}; + Result = !DIM || !mSTR->isUnreachable(DIM->getAliasNode(), DIN); + }, + [this, DIN, &Result](Instruction &I, AccessInfo, AccessInfo) { + return; + if (Result || (Result = !isa(I))) + return; + auto *DIM{mDIMInfo.findFromClient(I, mDT, DIUnknownMemory::NoFlags) + .get()}; + assert(DIM && "Metadata-level memory must be available!"); + Result = !DIM || !mSTR->isUnreachable(DIM->getAliasNode(), DIN); + }); + if (Result) + return true; + for (auto &Op : Inst->operands()) + if (!isa(Op) && !isa(Op) && + isMemoryAccessedIn(DIM, Op)) + return true; + } + return false; + } + + const ASTImportInfo mImportInfo; + clang::Rewriter &mRewriter; + clang::SourceManager &mSrcMgr; + const clang::LangOptions &mLangOpts; + ClangGlobalInfoPass::RawInfo &mRawInfo; + const GlobalOptions &mGlobalOpts; + MemoryMatchInfo::MemoryMatcher &mMemMatcher; + const ClangDIMemoryMatcherPass::DIMemoryMatcher &mDIMemMatcher; + const CanonicalLoopSet &mCanonicalLoopInfo; + PerfectLoopInfo &mPerfectLoopInfo; + AliasTree &mAT; + TargetLibraryInfo &mTLI; + DominatorTree &mDT; + DIMemoryClientServerInfo mDIMInfo; + std::optional> mSTR; + bool mIsStrict{true}; + enum Status { + SEARCH_PRAGMA, + TRAVERSE_STMT, + GET_REFERENCES + } mStatus{SEARCH_PRAGMA}; + SmallVector, 4> mSwaps; + LoopNest mInductions; +}; +} // namespace + +bool ClangLoopInterchange::runOnFunction(Function &F) { + auto *DISub{findMetadata(&F)}; + if (!DISub) + return false; + auto *CU{DISub->getUnit()}; + if (!isC(CU->getSourceLanguage()) && !isCXX(CU->getSourceLanguage())) + return false; + auto &TfmInfo{getAnalysis()}; + auto *TfmCtx{TfmInfo ? dyn_cast_or_null( + TfmInfo->getContext(*CU)) + : nullptr}; + if (!TfmCtx || !TfmCtx->hasInstance()) { + F.getContext().emitError("can not transform sources" + ": transformation context is not available"); + return false; + } + auto *FD{TfmCtx->getDeclForMangledName(F.getName())}; + if (!FD) + return false; + ASTImportInfo ImportStub; + const auto *ImportInfo{&ImportStub}; + if (auto *ImportPass = getAnalysisIfAvailable()) + ImportInfo = &ImportPass->getImportInfo(); + ClangLoopInterchangeVisitor(*this, F, TfmCtx, *ImportInfo).TraverseDecl(FD); + return false; +} From 59ca7f41ce5ceca8710507ba66887b0930040482 Mon Sep 17 00:00:00 2001 From: ArtherusAA Date: Fri, 10 Dec 2021 10:19:45 +0000 Subject: [PATCH 03/14] remove_redarray: in progress --- lib/Transform/Clang/RemoveRedarray.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index d851580d..8da4e84a 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -360,6 +360,7 @@ class ClangRemoveRedarrayVisitor // Match induction names from clauses to loop induction variables. unsigned MaxIdx{0}; llvm::SmallVector ValueSwaps; + int for (auto [Literal, Clause] : mSwaps) { auto Str{Literal->getString()}; unsigned InductIdx{0}, InductIdxE = mInductions.size(); @@ -625,6 +626,7 @@ class ClangRemoveRedarrayVisitor GET_REFERENCES } mStatus{SEARCH_PRAGMA}; SmallVector, 4> mSwaps; + LoopNest mInductions; }; } // namespace From 02dd51c6b728bfbf06ee03b5e1363e8bc0de8d4c Mon Sep 17 00:00:00 2001 From: ArtherusAA Date: Fri, 10 Dec 2021 14:22:28 +0000 Subject: [PATCH 04/14] in progress --- lib/Transform/Clang/RemoveRedarray.cpp | 37 ++++++-------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index 8da4e84a..fbfb4aa0 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -207,13 +207,13 @@ class ClangRemoveRedarrayVisitor } bool TraverseForStmt(clang::ForStmt *FS) { - if (mStatus != GET_REFERENCES) + if (mStatus != REPLACE_ARRAY_ACCESSES) return RecursiveASTVisitor::TraverseForStmt(FS); auto CanonicalItr{find_if(mCanonicalLoopInfo, [FS](auto *Info) { return Info->getASTLoop() == FS; })}; auto IsCanonical{false}, IsPerfect{false}; - mInductions.emplace_back(nullptr, nullptr, FS, Ok, VarList{}, nullptr); + //mInductions.emplace_back(nullptr, nullptr, FS, Ok, VarList{}, nullptr); if (CanonicalItr != mCanonicalLoopInfo.end() && (*CanonicalItr)->isCanonical()) { IsCanonical = true; @@ -328,6 +328,7 @@ class ClangRemoveRedarrayVisitor for (auto SR : ToRemove) mRewriter.RemoveText(SR, RemoveEmptyLine); Clauses.clear(); + // TODO: insert variable declaration here mStatus = TRAVERSE_STMT; return true; } @@ -351,8 +352,9 @@ class ClangRemoveRedarrayVisitor resetVisitor(); return RecursiveASTVisitor::TraverseStmt(S); } - mStatus = GET_REFERENCES; + mStatus = REPLACE_ARRAY_ACCESSES; auto Res = TraverseForStmt(cast(S)); + // TODO: insert array filling somewhere here if (!Res) { resetVisitor(); return false; @@ -360,31 +362,8 @@ class ClangRemoveRedarrayVisitor // Match induction names from clauses to loop induction variables. unsigned MaxIdx{0}; llvm::SmallVector ValueSwaps; - int - for (auto [Literal, Clause] : mSwaps) { - auto Str{Literal->getString()}; - unsigned InductIdx{0}, InductIdxE = mInductions.size(); - for (; InductIdx < InductIdxE; ++InductIdx) { - if (!std::get(mInductions[InductIdx])) - continue; - if (std::get(mInductions[InductIdx])->getName() == - Str) { - ValueSwaps.push_back( - std::get(mInductions[InductIdx])); - MaxIdx = (InductIdx > MaxIdx) ? InductIdx : MaxIdx; - break; - } - } - if (InductIdx == InductIdxE) { - toDiag(mSrcMgr.getDiagnostics(), Clause->getBeginLoc(), - tsar::diag::warn_disable_loop_interchange); - toDiag(mSrcMgr.getDiagnostics(), Literal->getBeginLoc(), - tsar::diag::note_interchange_induction_mismatch) - << Str; - resetVisitor(); - return RecursiveASTVisitor::TraverseStmt(S); - } - } + + // Check whether transfromation is possible. auto checkLoop = [this](unsigned I, unsigned MaxIdx) { auto checkPrivatizable = [](VarList &L, auto I, auto EI) { @@ -623,7 +602,7 @@ class ClangRemoveRedarrayVisitor enum Status { SEARCH_PRAGMA, TRAVERSE_STMT, - GET_REFERENCES + REPLACE_ARRAY_ACCESSES } mStatus{SEARCH_PRAGMA}; SmallVector, 4> mSwaps; From 95ab930042b749bb4ccc867743cf09cfce46cc48 Mon Sep 17 00:00:00 2001 From: ArtherusAA Date: Fri, 17 Dec 2021 14:19:58 +0000 Subject: [PATCH 05/14] remove_redarray: raw untested version done --- lib/Transform/Clang/RemoveRedarray.cpp | 244 +++++++++++++++++-------- 1 file changed, 163 insertions(+), 81 deletions(-) diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index fbfb4aa0..8d74c2cf 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -206,88 +206,102 @@ class ClangRemoveRedarrayVisitor mSTR = SpanningTreeRelation{mDIMInfo.DIAT}; } - bool TraverseForStmt(clang::ForStmt *FS) { - if (mStatus != REPLACE_ARRAY_ACCESSES) - return RecursiveASTVisitor::TraverseForStmt(FS); - auto CanonicalItr{find_if(mCanonicalLoopInfo, [FS](auto *Info) { - return Info->getASTLoop() == FS; - })}; - auto IsCanonical{false}, IsPerfect{false}; - //mInductions.emplace_back(nullptr, nullptr, FS, Ok, VarList{}, nullptr); - if (CanonicalItr != mCanonicalLoopInfo.end() && - (*CanonicalItr)->isCanonical()) { - IsCanonical = true; - IsPerfect = mPerfectLoopInfo.count((*CanonicalItr)->getLoop()); - auto VarItr{mMemMatcher.find((*CanonicalItr)->getInduction())}; - std::get(mInductions.back()) = VarItr->get(); - std::get(mInductions.back()) = *CanonicalItr; + // bool TraverseForStmt(clang::ForStmt *FS) { + // if (mStatus != REPLACE_ARRAY_ACCESSES) + // return RecursiveASTVisitor::TraverseForStmt(FS); + // auto CanonicalItr{find_if(mCanonicalLoopInfo, [FS](auto *Info) { + // return Info->getASTLoop() == FS; + // })}; + // auto IsCanonical{false}, IsPerfect{false}; + // //mInductions.emplace_back(nullptr, nullptr, FS, Ok, VarList{}, nullptr); + // if (CanonicalItr != mCanonicalLoopInfo.end() && + // (*CanonicalItr)->isCanonical()) { + // IsCanonical = true; + // IsPerfect = mPerfectLoopInfo.count((*CanonicalItr)->getLoop()); + // auto VarItr{mMemMatcher.find((*CanonicalItr)->getInduction())}; + // std::get(mInductions.back()) = VarItr->get(); + // std::get(mInductions.back()) = *CanonicalItr; + // } + // if (!IsCanonical) + // std::get(mInductions.back()) |= NotCanonical; + // if (!IsPerfect) + // std::get(mInductions.back()) |= NotPerfect; + // if (!mIsStrict || !IsCanonical) { + // if (!IsCanonical) + // std::get(mInductions.back()) |= NotAnalyzed; + // return RecursiveASTVisitor::TraverseForStmt(FS); + // } + // auto Dependency{false}; + // auto *L{(*CanonicalItr)->getLoop()->getLoop()}; + // if (!mDIMInfo.isValid()) { + // std::get(mInductions.back()) |= NotAnalyzed; + // return RecursiveASTVisitor::TraverseForStmt(FS); + // } + // auto *DIDepSet{mDIMInfo.findFromClient(*L)}; + // if (!DIDepSet) { + // std::get(mInductions.back()) |= NotAnalyzed; + // return RecursiveASTVisitor::TraverseForStmt(FS); + // } + // DenseSet Coverage; + // accessCoverage(*DIDepSet, *mDIMInfo.DIAT, Coverage, + // mGlobalOpts.IgnoreRedundantMemory); + // if (!Coverage.empty()) + // for (auto &Trait : *DIDepSet) { + // if (!Coverage.count(Trait.getNode()) || hasNoDep(Trait) || + // Trait.is_any()) + // continue; + // if(Trait.is_any() && + // Trait.size() == 1) { + // if (auto DIEM{ + // dyn_cast((*Trait.begin())->getMemory())}; + // DIEM && DIEM->getExpression()->getNumElements() == 0) { + // auto *ClientDIM{ + // mDIMInfo.getClientMemory(const_cast(DIEM))}; + // assert(ClientDIM && "Origin memory must exist!"); + // auto VarToDI{mDIMemMatcher.find( + // cast(ClientDIM)->getVariable())}; + // if (Trait.is()) { + // if (VarToDI->template get() == + // std::get(mInductions.back())) { + // std::get(mInductions.back()) = DIEM; + // continue; + // } + // } else { + // std::get(mInductions.back()) + // .push_back(VarToDI->template get()); + // continue; + // } + // } + // } + // std::get(mInductions.back()) |= HasDependency; + // break; + // } + // return RecursiveASTVisitor::TraverseForStmt(FS); + // } + + // bool TraverseDecl(clang::Decl *D) { + // if (!D) + // return RecursiveASTVisitor::TraverseDecl(D); + // if (mStatus == TRAVERSE_STMT) { + // toDiag(mSrcMgr.getDiagnostics(), D->getLocation(), + // tsar::diag::warn_interchange_not_for_loop); // TODO: change this warning + // resetVisitor(); + // } + // return RecursiveASTVisitor::TraverseDecl(D); + // } + + bool TraverseBinaryOperator(clang::BinaryOperator * B) { + if (mStatus != GET_ALL_ARRAY_SUBSCRIPTS) { + return RecursiveASTVisitor::TraverseBinaryOperator(B); } - if (!IsCanonical) - std::get(mInductions.back()) |= NotCanonical; - if (!IsPerfect) - std::get(mInductions.back()) |= NotPerfect; - if (!mIsStrict || !IsCanonical) { - if (!IsCanonical) - std::get(mInductions.back()) |= NotAnalyzed; - return RecursiveASTVisitor::TraverseForStmt(FS); - } - auto Dependency{false}; - auto *L{(*CanonicalItr)->getLoop()->getLoop()}; - if (!mDIMInfo.isValid()) { - std::get(mInductions.back()) |= NotAnalyzed; - return RecursiveASTVisitor::TraverseForStmt(FS); - } - auto *DIDepSet{mDIMInfo.findFromClient(*L)}; - if (!DIDepSet) { - std::get(mInductions.back()) |= NotAnalyzed; - return RecursiveASTVisitor::TraverseForStmt(FS); - } - DenseSet Coverage; - accessCoverage(*DIDepSet, *mDIMInfo.DIAT, Coverage, - mGlobalOpts.IgnoreRedundantMemory); - if (!Coverage.empty()) - for (auto &Trait : *DIDepSet) { - if (!Coverage.count(Trait.getNode()) || hasNoDep(Trait) || - Trait.is_any()) - continue; - if(Trait.is_any() && - Trait.size() == 1) { - if (auto DIEM{ - dyn_cast((*Trait.begin())->getMemory())}; - DIEM && DIEM->getExpression()->getNumElements() == 0) { - auto *ClientDIM{ - mDIMInfo.getClientMemory(const_cast(DIEM))}; - assert(ClientDIM && "Origin memory must exist!"); - auto VarToDI{mDIMemMatcher.find( - cast(ClientDIM)->getVariable())}; - if (Trait.is()) { - if (VarToDI->template get() == - std::get(mInductions.back())) { - std::get(mInductions.back()) = DIEM; - continue; - } - } else { - std::get(mInductions.back()) - .push_back(VarToDI->template get()); - continue; - } - } - } - std::get(mInductions.back()) |= HasDependency; - break; - } - return RecursiveASTVisitor::TraverseForStmt(FS); + return TraverseStmt(B); } - bool TraverseDecl(clang::Decl *D) { - if (!D) - return RecursiveASTVisitor::TraverseDecl(D); - if (mStatus == TRAVERSE_STMT) { - toDiag(mSrcMgr.getDiagnostics(), D->getLocation(), - tsar::diag::warn_interchange_not_for_loop); // TODO: change this warning - resetVisitor(); + bool TraverseUnaryOperator(clang::UnaryOperator *U) { + if (mStatus != GET_ALL_ARRAY_SUBSCRIPTS) { + return RecursiveASTVisitor::TraverseUnaryOperator(U); } - return RecursiveASTVisitor::TraverseDecl(D); + return TraverseStmt(U); } bool TraverseStmt(clang::Stmt *S) { @@ -352,8 +366,24 @@ class ClangRemoveRedarrayVisitor resetVisitor(); return RecursiveASTVisitor::TraverseStmt(S); } - mStatus = REPLACE_ARRAY_ACCESSES; - auto Res = TraverseForStmt(cast(S)); + auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; + auto [SizeLiteral, SizeStmt] = mSwaps[1]; + std::string ArrName = ArrayLiteral->GetString(); + ArrName += "_subscr_"; + std::string ToInsert = cast(S)->GetType().GetAsString(); + for (int i = 0; i < cast(SizeStmt.GetValue()); i++) { // getValue probably does not work + if (i > 0) { + ToInsert += ","; + } + ToInsert += (" " + ArrName + std::to_string(i)); + } + ToInsert += (";" + std::endl); + mRewriter.InsertTextBefore(S->GetBeginLoc(), + ToInsert); // insert array variables + // definitions here + mStatus = FIND_OP; + return RecursiveASTVisitor::TraverseStmt(S); + //auto Res = TraverseForStmt(cast(S)); // TODO: insert array filling somewhere here if (!Res) { resetVisitor(); @@ -477,6 +507,54 @@ class ClangRemoveRedarrayVisitor resetVisitor(); return true; } + case FIND_OP: { + if (!isa(S) && !isa(S)) { + return RecursiveASTVisitor::TraverseStmt(S); + } + mStatus = GET_ALL_ARRAY_SUBSCRIPTS; + if (isa(S)) { + auto Res = TraverseBinaryOperator(cast(S)); + } else { + auto Res = TraverseUnaryOperator(cast(S)); + } + mStatus = FIND_OP; + if (mArraySubscriptExpr.size() == 0) { + return RecursiveASTVisitor::TraverseStmt(S); + } + std::string CaseBody = mRewriter.getRewrittenText(S->getBeginLoc(), S->getEndLoc()); + auto ArrSize = cast(SizeStmt.GetValue()); // this probably does not work + auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; + std::string ArrName = ArrayLiteral->GetString(); + ArrName += "_subscr_"; + for (auto Subscr: mArraySubscriptExpr) { + mRewriter.ReplaceText(Subscr->getBeginLoc(), SUbscr->getEndLoc(), ArrName + "0"); // for now, for test purposes + } + } + case GET_ALL_ARRAY_SUBSCRIPTS: { + if (!isa(S)) { + return RecursiveASTVisitor::TraverseStmt(S); + } + mIsSubscriptUseful = false; + mStatus = CHECK_SUBSCRIPT; + auto Res = TraverseStmt(S); + mStatus = GET_ALL_ARRAY_SUBSCRIPTS; + if (mIsSubscriptUseful) { + mArraySubscriptExpr.push_back(cast(S)); + } + return RecursiveASTVisitor::TraverseStmt(S); + } + case CHECK_SUBSCRIPT: { + if (!isa(S)) { + return RecursiveASTVisitor::TraverseStmt(S); + } + auto Arr = cast(S); + auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; + if (ArrayLiteral->GetString() == Arr->GetNameInfo().GetName()) { + mIsSubscriptUseful = true; + return true; + } + return RecursiveASTVisitor::TraverseStmt(S); + } } return RecursiveASTVisitor::TraverseStmt(S); } @@ -602,9 +680,13 @@ class ClangRemoveRedarrayVisitor enum Status { SEARCH_PRAGMA, TRAVERSE_STMT, - REPLACE_ARRAY_ACCESSES + FIND_OP, + GET_ALL_ARRAY_SUBSCRIPTS, + CHECK_SUBSCRIPT, } mStatus{SEARCH_PRAGMA}; SmallVector, 4> mSwaps; + std::vector mArraySubscriptExpr; + bool mIsSubscriptUseful; LoopNest mInductions; }; From 3564f0d56411f69883fb1cc0d145d9f4aac2ecaf Mon Sep 17 00:00:00 2001 From: ArtherusAA Date: Fri, 17 Dec 2021 14:23:45 +0000 Subject: [PATCH 06/14] remove_redarray: minor fix --- lib/Transform/Clang/RemoveRedarray.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index 8d74c2cf..814254f3 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -527,7 +527,7 @@ class ClangRemoveRedarrayVisitor std::string ArrName = ArrayLiteral->GetString(); ArrName += "_subscr_"; for (auto Subscr: mArraySubscriptExpr) { - mRewriter.ReplaceText(Subscr->getBeginLoc(), SUbscr->getEndLoc(), ArrName + "0"); // for now, for test purposes + mRewriter.ReplaceText(Subscr->getBeginLoc(), Subscr->getEndLoc(), ArrName + "0"); // for now, for test purposes } } case GET_ALL_ARRAY_SUBSCRIPTS: { From 5e2a78e8b2e60247ea1292c14f588dc07718732a Mon Sep 17 00:00:00 2001 From: ArtherusAA Date: Fri, 24 Dec 2021 10:53:50 +0000 Subject: [PATCH 07/14] remove_redarray: compilable code --- include/tsar/Transform/Clang/Passes.h | 2 + lib/Transform/Clang/CMakeLists.txt | 3 +- lib/Transform/Clang/Passes.cpp | 1 + lib/Transform/Clang/RemoveRedarray.cpp | 493 +++++++++++++------------ 4 files changed, 264 insertions(+), 235 deletions(-) diff --git a/include/tsar/Transform/Clang/Passes.h b/include/tsar/Transform/Clang/Passes.h index dcb9dc5f..5ff7bf86 100644 --- a/include/tsar/Transform/Clang/Passes.h +++ b/include/tsar/Transform/Clang/Passes.h @@ -112,6 +112,8 @@ void initializeClangLoopInterchangePass(PassRegistry &Registry); /// Initialize a pass to reverse loop. void initializeClangLoopReversePass(PassRegistry &Registry); +void initializeClangRemoveRedarrayPass(PassRegistry &Registry); + /// Create a pass to reverse loop. ModulePass *createClangLoopReverse(); } diff --git a/lib/Transform/Clang/CMakeLists.txt b/lib/Transform/Clang/CMakeLists.txt index d5eef742..9b46d4d1 100644 --- a/lib/Transform/Clang/CMakeLists.txt +++ b/lib/Transform/Clang/CMakeLists.txt @@ -2,7 +2,8 @@ set(TRANSFORM_SOURCES Passes.cpp ExprPropagation.cpp Inline.cpp RenameLocal.cpp DeadDeclsElimination.cpp Format.cpp OpenMPAutoPar.cpp DVMHWriter.cpp SharedMemoryAutoPar.cpp DVMHDirecitves.cpp DVMHSMAutoPar.cpp DVMHDataTransferIPO.cpp StructureReplacement.cpp LoopInterchange.cpp - LoopReversal.cpp) + LoopReversal.cpp RemoveRedarray.cpp) + if(MSVC_IDE) file(GLOB_RECURSE TRANSFORM_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/lib/Transform/Clang/Passes.cpp b/lib/Transform/Clang/Passes.cpp index 1414a706..780428db 100644 --- a/lib/Transform/Clang/Passes.cpp +++ b/lib/Transform/Clang/Passes.cpp @@ -38,5 +38,6 @@ void llvm::initializeClangTransform(PassRegistry &Registry) { initializeClangDVMHSMParallelizationPass(Registry); initializeDVMHDataTransferIPOPassPass(Registry); initializeClangLoopInterchangePass(Registry); + initializeClangRemoveRedarrayPass(Registry); initializeClangLoopReversePass(Registry); } diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index 814254f3..d7053873 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -201,7 +201,8 @@ class ClangRemoveRedarrayVisitor mAT(P.getAnalysis().getAliasTree()), mTLI(P.getAnalysis().getTLI(F)), mDT(P.getAnalysis().getDomTree()), - mDIMInfo(P.getAnalysis().getAliasTree(), P, F) { + mDIMInfo(P.getAnalysis().getAliasTree(), P, F) + { if (mDIMInfo.isValid()) mSTR = SpanningTreeRelation{mDIMInfo.DIAT}; } @@ -279,16 +280,23 @@ class ClangRemoveRedarrayVisitor // return RecursiveASTVisitor::TraverseForStmt(FS); // } - // bool TraverseDecl(clang::Decl *D) { - // if (!D) - // return RecursiveASTVisitor::TraverseDecl(D); - // if (mStatus == TRAVERSE_STMT) { - // toDiag(mSrcMgr.getDiagnostics(), D->getLocation(), - // tsar::diag::warn_interchange_not_for_loop); // TODO: change this warning - // resetVisitor(); - // } - // return RecursiveASTVisitor::TraverseDecl(D); - // } + bool TraverseVarDecl(clang::VarDecl *VD) { + if (mStatus == FIND_INDEX) { + mIndex = VD; + } + return RecursiveASTVisitor::TraverseDecl(VD); + } + + bool TraverseDecl(clang::Decl *D) { + if (!D) + return RecursiveASTVisitor::TraverseDecl(D); + if (mStatus == TRAVERSE_STMT) { + toDiag(mSrcMgr.getDiagnostics(), D->getLocation(), + tsar::diag::warn_interchange_not_for_loop); // TODO: change this warning + resetVisitor(); + } + return RecursiveASTVisitor::TraverseDecl(D); + } bool TraverseBinaryOperator(clang::BinaryOperator * B) { if (mStatus != GET_ALL_ARRAY_SUBSCRIPTS) { @@ -368,144 +376,156 @@ class ClangRemoveRedarrayVisitor } auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; auto [SizeLiteral, SizeStmt] = mSwaps[1]; - std::string ArrName = ArrayLiteral->GetString(); + std::string ArrName = ArrayLiteral->getString().str(); ArrName += "_subscr_"; - std::string ToInsert = cast(S)->GetType().GetAsString(); - for (int i = 0; i < cast(SizeStmt.GetValue()); i++) { // getValue probably does not work + std::string ToInsert = cast(S)->getType().getAsString(); + for (int i = 0; i < cast(SizeStmt)->getValue().getSExtValue(); i++) { if (i > 0) { ToInsert += ","; } ToInsert += (" " + ArrName + std::to_string(i)); } - ToInsert += (";" + std::endl); - mRewriter.InsertTextBefore(S->GetBeginLoc(), + ToInsert += (";\n"); + mRewriter.InsertTextBefore(S->getBeginLoc(), ToInsert); // insert array variables // definitions here + mStatus = FIND_INDEX; + auto Res = RecursiveASTVisitor::TraverseStmt(S); mStatus = FIND_OP; - return RecursiveASTVisitor::TraverseStmt(S); + Res = RecursiveASTVisitor::TraverseStmt(S); + // fill array here + return true; + //auto Res = TraverseForStmt(cast(S)); // TODO: insert array filling somewhere here - if (!Res) { - resetVisitor(); - return false; - } - // Match induction names from clauses to loop induction variables. - unsigned MaxIdx{0}; - llvm::SmallVector ValueSwaps; - - - // Check whether transfromation is possible. - auto checkLoop = [this](unsigned I, unsigned MaxIdx) { - auto checkPrivatizable = [](VarList &L, auto I, auto EI) { - for (auto *V : L) - if (EI == std::find_if(I, EI, [V](auto &Induct) { - return std::get(Induct) == V; - })) - return false; - - return true; - }; - if (std::get(mInductions[I]) & NotCanonical) { - toDiag(mSrcMgr.getDiagnostics(), - std::get(mInductions[I])->getBeginLoc(), - tsar::diag::warn_interchange_not_canonical); - } else if (std::get(mInductions[I]) & HasDependency) { - toDiag(mSrcMgr.getDiagnostics(), - std::get(mInductions[I])->getBeginLoc(), - tsar::diag::warn_interchange_dependency); - } else if (!mIsStrict) { - return true; - } else if (std::get(mInductions[I]) & NotAnalyzed) { - toDiag(mSrcMgr.getDiagnostics(), - std::get(mInductions[I])->getBeginLoc(), - tsar::diag::warn_interchange_no_analysis); - } else if (!checkPrivatizable(std::get(mInductions[I]), - mInductions.begin() + I + 1, - mInductions.end())) { - toDiag(mSrcMgr.getDiagnostics(), - std::get(mInductions[I])->getBeginLoc(), - tsar::diag::warn_interchange_dependency); - } else if (auto *For{isMemoryAccessedIn( - std::get(mInductions[I]), - std::get(mInductions[I]) - ->getLoop() - ->getLoop(), - mInductions.begin() + I + 1, - mInductions.begin() + MaxIdx + 1)}) { - toDiag(mSrcMgr.getDiagnostics(), - std::get(mInductions[I])->getBeginLoc(), - tsar::diag::warn_disable_loop_interchange); - toDiag(mSrcMgr.getDiagnostics(), For->getBeginLoc(), - tsar::diag::note_interchange_irregular_loop_nest); - } else { - return true; - } - return false; - }; - auto IsPossible(true); - for (auto I{0u}; I < MaxIdx; I++) { - if (std::get(mInductions[I]) & NotPerfect) { - IsPossible = false; - toDiag(mSrcMgr.getDiagnostics(), - std::get(mInductions[I])->getBeginLoc(), - tsar::diag::warn_interchange_not_perfect); - } else { - IsPossible &= checkLoop(I, MaxIdx); - } - } - // Check the innermost loop which participates in the transformation. - // Note, the it may have not canonical loop form. - IsPossible &= checkLoop(MaxIdx, MaxIdx); - if (!IsPossible) { - resetVisitor(); - return RecursiveASTVisitor::TraverseStmt(S); - } - // Deduce new order. - SmallVector Order; - std::transform(mInductions.begin(), mInductions.begin() + MaxIdx + 1, - std::back_inserter(Order), - [](auto &I) { return std::get(I); }); - for (unsigned I{0}, EI = ValueSwaps.size(); I < EI; I += 2) { - auto FirstItr{find(Order, ValueSwaps[I])}; - assert(FirstItr != Order.end() && "Induction must exist!"); - auto SecondItr{find(Order, ValueSwaps[I + 1])}; - assert(SecondItr != Order.end() && "Induction must exist!"); - std::swap(*FirstItr, *SecondItr); - } - // Collect sources of loop headers before the transformation. Note, do not - // use Rewriter::ReplaceText(SourceRange, SourceRange) because it uses - // Rewriter::getRangeSize(SourceRange) to compute a length of a destination - // as well as a length of a source and this method uses rewritten text to - // collect size. Thus, the size of the source can be computed in the wrong - // way because the transformation of outer loops has already taken place. - SmallVector Sources; - for (auto I{0u}; I < MaxIdx + 1; I++) { - clang::SourceRange Source{ - std::get(mInductions[I])->getInit()->getBeginLoc(), - std::get(mInductions[I])->getInc()->getEndLoc()}; - Sources.push_back(mRewriter.getRewrittenText(Source)); - } - // Interchange loop headers. - for (auto I{0u}; I < MaxIdx + 1 ; I++) { - if (Order[I] != std::get(mInductions[I])) { - auto OriginItr{find_if(mInductions, [What = Order[I]](auto &Induct) { - return std::get(Induct) == What; - })}; - clang::SourceRange Destination( - std::get(mInductions[I]) - ->getInit() - ->getBeginLoc(), - std::get(mInductions[I]) - ->getInc() - ->getEndLoc()); - mRewriter.ReplaceText( - Destination, - Sources[std::distance(mInductions.begin(), OriginItr)]); - } - } - LLVM_DEBUG(dbgs() << DEBUG_PREFIX << ": finish pragma processing\n"); - resetVisitor(); - return true; + // if (!Res) { + // resetVisitor(); + // return false; + // } + // // Match induction names from clauses to loop induction variables. + // unsigned MaxIdx{0}; + // llvm::SmallVector ValueSwaps; + + + // // Check whether transfromation is possible. + // auto checkLoop = [this](unsigned I, unsigned MaxIdx) { + // auto checkPrivatizable = [](VarList &L, auto I, auto EI) { + // for (auto *V : L) + // if (EI == std::find_if(I, EI, [V](auto &Induct) { + // return std::get(Induct) == V; + // })) + // return false; + + // return true; + // }; + // if (std::get(mInductions[I]) & NotCanonical) { + // toDiag(mSrcMgr.getDiagnostics(), + // std::get(mInductions[I])->getBeginLoc(), + // tsar::diag::warn_interchange_not_canonical); + // } else if (std::get(mInductions[I]) & HasDependency) { + // toDiag(mSrcMgr.getDiagnostics(), + // std::get(mInductions[I])->getBeginLoc(), + // tsar::diag::warn_interchange_dependency); + // } else if (!mIsStrict) { + // return true; + // } else if (std::get(mInductions[I]) & NotAnalyzed) { + // toDiag(mSrcMgr.getDiagnostics(), + // std::get(mInductions[I])->getBeginLoc(), + // tsar::diag::warn_interchange_no_analysis); + // } else if (!checkPrivatizable(std::get(mInductions[I]), + // mInductions.begin() + I + 1, + // mInductions.end())) { + // toDiag(mSrcMgr.getDiagnostics(), + // std::get(mInductions[I])->getBeginLoc(), + // tsar::diag::warn_interchange_dependency); + // } else if (auto *For{isMemoryAccessedIn( + // std::get(mInductions[I]), + // std::get(mInductions[I]) + // ->getLoop() + // ->getLoop(), + // mInductions.begin() + I + 1, + // mInductions.begin() + MaxIdx + 1)}) { + // toDiag(mSrcMgr.getDiagnostics(), + // std::get(mInductions[I])->getBeginLoc(), + // tsar::diag::warn_disable_loop_interchange); + // toDiag(mSrcMgr.getDiagnostics(), For->getBeginLoc(), + // tsar::diag::note_interchange_irregular_loop_nest); + // } else { + // return true; + // } + // return false; + // }; + // auto IsPossible(true); + // for (auto I{0u}; I < MaxIdx; I++) { + // if (std::get(mInductions[I]) & NotPerfect) { + // IsPossible = false; + // toDiag(mSrcMgr.getDiagnostics(), + // std::get(mInductions[I])->getBeginLoc(), + // tsar::diag::warn_interchange_not_perfect); + // } else { + // IsPossible &= checkLoop(I, MaxIdx); + // } + // } + // // Check the innermost loop which participates in the transformation. + // // Note, the it may have not canonical loop form. + // IsPossible &= checkLoop(MaxIdx, MaxIdx); + // if (!IsPossible) { + // resetVisitor(); + // return RecursiveASTVisitor::TraverseStmt(S); + // } + // // Deduce new order. + // SmallVector Order; + // std::transform(mInductions.begin(), mInductions.begin() + MaxIdx + 1, + // std::back_inserter(Order), + // [](auto &I) { return std::get(I); }); + // for (unsigned I{0}, EI = ValueSwaps.size(); I < EI; I += 2) { + // auto FirstItr{find(Order, ValueSwaps[I])}; + // assert(FirstItr != Order.end() && "Induction must exist!"); + // auto SecondItr{find(Order, ValueSwaps[I + 1])}; + // assert(SecondItr != Order.end() && "Induction must exist!"); + // std::swap(*FirstItr, *SecondItr); + // } + // // Collect sources of loop headers before the transformation. Note, do not + // // use Rewriter::ReplaceText(SourceRange, SourceRange) because it uses + // // Rewriter::getRangeSize(SourceRange) to compute a length of a destination + // // as well as a length of a source and this method uses rewritten text to + // // collect size. Thus, the size of the source can be computed in the wrong + // // way because the transformation of outer loops has already taken place. + // SmallVector Sources; + // for (auto I{0u}; I < MaxIdx + 1; I++) { + // clang::SourceRange Source{ + // std::get(mInductions[I])->getInit()->getBeginLoc(), + // std::get(mInductions[I])->getInc()->getEndLoc()}; + // Sources.push_back(mRewriter.getRewrittenText(Source)); + // } + // // Interchange loop headers. + // for (auto I{0u}; I < MaxIdx + 1 ; I++) { + // if (Order[I] != std::get(mInductions[I])) { + // auto OriginItr{find_if(mInductions, [What = Order[I]](auto &Induct) { + // return std::get(Induct) == What; + // })}; + // clang::SourceRange Destination( + // std::get(mInductions[I]) + // ->getInit() + // ->getBeginLoc(), + // std::get(mInductions[I]) + // ->getInc() + // ->getEndLoc()); + // mRewriter.ReplaceText( + // Destination, + // Sources[std::distance(mInductions.begin(), OriginItr)]); + // } + // } + // LLVM_DEBUG(dbgs() << DEBUG_PREFIX << ": finish pragma processing\n"); + // resetVisitor(); + // return true; + } + case FIND_INDEX: { + // if (!isa(S)) { + // return RecursiveASTVisitor::TraverseStmt(S); + // } + // mIndex = cast(S); + return RecursiveASTVisitor::TraverseStmt(S); } case FIND_OP: { if (!isa(S) && !isa(S)) { @@ -521,14 +541,17 @@ class ClangRemoveRedarrayVisitor if (mArraySubscriptExpr.size() == 0) { return RecursiveASTVisitor::TraverseStmt(S); } - std::string CaseBody = mRewriter.getRewrittenText(S->getBeginLoc(), S->getEndLoc()); - auto ArrSize = cast(SizeStmt.GetValue()); // this probably does not work + auto [SizeLiteral, SizeStmt] = mSwaps[1]; + std::string CaseBody = mRewriter.getRewrittenText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc())); + auto ArrSize = cast(SizeStmt)->getValue().getSExtValue(); auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; - std::string ArrName = ArrayLiteral->GetString(); + std::string ArrName = ArrayLiteral->getString().str(); ArrName += "_subscr_"; + auto IndexName = mIndex->getName(); for (auto Subscr: mArraySubscriptExpr) { - mRewriter.ReplaceText(Subscr->getBeginLoc(), Subscr->getEndLoc(), ArrName + "0"); // for now, for test purposes + mRewriter.ReplaceText(clang::SourceRange(Subscr->getBeginLoc(), Subscr->getEndLoc()), ArrName + "0"); // for now, for test purposes } + return RecursiveASTVisitor::TraverseStmt(S); } case GET_ALL_ARRAY_SUBSCRIPTS: { if (!isa(S)) { @@ -549,7 +572,7 @@ class ClangRemoveRedarrayVisitor } auto Arr = cast(S); auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; - if (ArrayLiteral->GetString() == Arr->GetNameInfo().GetName()) { + if (ArrayLiteral->getString().str() == Arr->getNameInfo().getName().getAsString()) { mIsSubscriptUseful = true; return true; } @@ -569,97 +592,97 @@ class ClangRemoveRedarrayVisitor /// Return true if a specified induction variable `DIM` of a loop `L` may be /// accessed in an any header of specified canonical loops. - clang::ForStmt *isMemoryAccessedIn(const DIMemory *DIM, const Loop *L, - LoopNest::iterator I, - LoopNest::iterator EI) { - assert(DIM && - "Results of canonical loop analysis must be available for a loop!"); - for (auto &Induct : make_range(I, EI)) { - if (isMemoryAccessedIn( - DIM, std::get(Induct)->getStart()) || - isMemoryAccessedIn( - DIM, std::get(Induct)->getEnd()) || - isMemoryAccessedIn( - DIM, L, std::get(Induct)->getStep())) - return std::get(Induct); - } - return nullptr; - } + // clang::ForStmt *isMemoryAccessedIn(const DIMemory *DIM, const Loop *L, + // LoopNest::iterator I, + // LoopNest::iterator EI) { + // assert(DIM && + // "Results of canonical loop analysis must be available for a loop!"); + // for (auto &Induct : make_range(I, EI)) { + // if (isMemoryAccessedIn( + // DIM, std::get(Induct)->getStart()) || + // isMemoryAccessedIn( + // DIM, std::get(Induct)->getEnd()) || + // isMemoryAccessedIn( + // DIM, L, std::get(Induct)->getStep())) + // return std::get(Induct); + // } + // return nullptr; + // } - /// Return true if a specified induction variable `DIM` of a loop `L` may be - /// accessed in a specified expression `S`. - bool isMemoryAccessedIn(const DIMemory *DIM, const Loop *L, const SCEV *S) { - if (!S) - return true; - struct SCEVMemorySearch { - SCEVMemorySearch(const Loop *Lp) : L(Lp) {} - bool follow(const SCEV *S) { - if (auto *AddRec{dyn_cast(S)}; - AddRec && AddRec->getLoop() == L) - L = nullptr; - else if (auto *Unknown{dyn_cast(S)}) - Values.push_back(Unknown->getValue()); - return true; - } - bool isDone() { - // Finish search if reference to a loop has been found. - return !L; - } - SmallVector Values; - const Loop *L; - } Visitor{L}; - visitAll(S, Visitor); - if (!Visitor.L) - return true; - for (auto *V : Visitor.Values) - if (isMemoryAccessedIn(DIM, V)) - return true; - return false; - } + // /// Return true if a specified induction variable `DIM` of a loop `L` may be + // /// accessed in a specified expression `S`. + // bool isMemoryAccessedIn(const DIMemory *DIM, const Loop *L, const SCEV *S) { + // if (!S) + // return true; + // struct SCEVMemorySearch { + // SCEVMemorySearch(const Loop *Lp) : L(Lp) {} + // bool follow(const SCEV *S) { + // if (auto *AddRec{dyn_cast(S)}; + // AddRec && AddRec->getLoop() == L) + // L = nullptr; + // else if (auto *Unknown{dyn_cast(S)}) + // Values.push_back(Unknown->getValue()); + // return true; + // } + // bool isDone() { + // // Finish search if reference to a loop has been found. + // return !L; + // } + // SmallVector Values; + // const Loop *L; + // } Visitor{L}; + // visitAll(S, Visitor); + // if (!Visitor.L) + // return true; + // for (auto *V : Visitor.Values) + // if (isMemoryAccessedIn(DIM, V)) + // return true; + // return false; + // } - /// Return true if a specified induction variable `DIM` of a loop `L` may be - /// accessed in a specified value `V`. - bool isMemoryAccessedIn(const DIMemory *DIM, Value *V) { - if (!V) - return true; - if (isa(V)) - return false; - if (auto *Inst{dyn_cast(V)}) { - auto &DL{Inst->getModule()->getDataLayout()}; - bool Result{false}; - auto DIN{DIM->getAliasNode()}; - for_each_memory( - *Inst, mTLI, - [this, DIN, &DL, &Result](Instruction &, MemoryLocation &&Loc, - unsigned, AccessInfo R, AccessInfo W) { - if (Result) - return; - if (R == AccessInfo::No && W == AccessInfo::No) - return; - auto EM{mAT.find(Loc)}; - assert(EM && "Estimate memory location must not be null!"); - auto *DIM{mDIMInfo.findFromClient(*EM->getTopLevelParent(), DL, mDT) - .get()}; - Result = !DIM || !mSTR->isUnreachable(DIM->getAliasNode(), DIN); - }, - [this, DIN, &Result](Instruction &I, AccessInfo, AccessInfo) { - return; - if (Result || (Result = !isa(I))) - return; - auto *DIM{mDIMInfo.findFromClient(I, mDT, DIUnknownMemory::NoFlags) - .get()}; - assert(DIM && "Metadata-level memory must be available!"); - Result = !DIM || !mSTR->isUnreachable(DIM->getAliasNode(), DIN); - }); - if (Result) - return true; - for (auto &Op : Inst->operands()) - if (!isa(Op) && !isa(Op) && - isMemoryAccessedIn(DIM, Op)) - return true; - } - return false; - } + // /// Return true if a specified induction variable `DIM` of a loop `L` may be + // /// accessed in a specified value `V`. + // bool isMemoryAccessedIn(const DIMemory *DIM, Value *V) { + // if (!V) + // return true; + // if (isa(V)) + // return false; + // if (auto *Inst{dyn_cast(V)}) { + // auto &DL{Inst->getModule()->getDataLayout()}; + // bool Result{false}; + // auto DIN{DIM->getAliasNode()}; + // for_each_memory( + // *Inst, mTLI, + // [this, DIN, &DL, &Result](Instruction &, MemoryLocation &&Loc, + // unsigned, AccessInfo R, AccessInfo W) { + // if (Result) + // return; + // if (R == AccessInfo::No && W == AccessInfo::No) + // return; + // auto EM{mAT.find(Loc)}; + // assert(EM && "Estimate memory location must not be null!"); + // auto *DIM{mDIMInfo.findFromClient(*EM->getTopLevelParent(), DL, mDT) + // .get()}; + // Result = !DIM || !mSTR->isUnreachable(DIM->getAliasNode(), DIN); + // }, + // [this, DIN, &Result](Instruction &I, AccessInfo, AccessInfo) { + // return; + // if (Result || (Result = !isa(I))) + // return; + // auto *DIM{mDIMInfo.findFromClient(I, mDT, DIUnknownMemory::NoFlags) + // .get()}; + // assert(DIM && "Metadata-level memory must be available!"); + // Result = !DIM || !mSTR->isUnreachable(DIM->getAliasNode(), DIN); + // }); + // if (Result) + // return true; + // for (auto &Op : Inst->operands()) + // if (!isa(Op) && !isa(Op) && + // isMemoryAccessedIn(DIM, Op)) + // return true; + // } + // return false; + // } const ASTImportInfo mImportInfo; clang::Rewriter &mRewriter; @@ -680,6 +703,7 @@ class ClangRemoveRedarrayVisitor enum Status { SEARCH_PRAGMA, TRAVERSE_STMT, + FIND_INDEX, FIND_OP, GET_ALL_ARRAY_SUBSCRIPTS, CHECK_SUBSCRIPT, @@ -687,12 +711,13 @@ class ClangRemoveRedarrayVisitor SmallVector, 4> mSwaps; std::vector mArraySubscriptExpr; bool mIsSubscriptUseful; + clang::VarDecl* mIndex; LoopNest mInductions; }; } // namespace -bool ClangLoopInterchange::runOnFunction(Function &F) { +bool ClangRemoveRedarray::runOnFunction(Function &F) { auto *DISub{findMetadata(&F)}; if (!DISub) return false; @@ -715,6 +740,6 @@ bool ClangLoopInterchange::runOnFunction(Function &F) { const auto *ImportInfo{&ImportStub}; if (auto *ImportPass = getAnalysisIfAvailable()) ImportInfo = &ImportPass->getImportInfo(); - ClangLoopInterchangeVisitor(*this, F, TfmCtx, *ImportInfo).TraverseDecl(FD); + ClangRemoveRedarrayVisitor(*this, F, TfmCtx, *ImportInfo).TraverseDecl(FD); return false; } From bd9f47cd9a2637bd594d8f83987efd86df10608b Mon Sep 17 00:00:00 2001 From: ArtherusAA Date: Sun, 6 Feb 2022 09:48:28 +0000 Subject: [PATCH 08/14] fix --- lib/Transform/Clang/RemoveRedarray.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index d7053873..cc68286b 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -542,15 +542,22 @@ class ClangRemoveRedarrayVisitor return RecursiveASTVisitor::TraverseStmt(S); } auto [SizeLiteral, SizeStmt] = mSwaps[1]; - std::string CaseBody = mRewriter.getRewrittenText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc())); - auto ArrSize = cast(SizeStmt)->getValue().getSExtValue(); - auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; - std::string ArrName = ArrayLiteral->getString().str(); - ArrName += "_subscr_"; auto IndexName = mIndex->getName(); - for (auto Subscr: mArraySubscriptExpr) { - mRewriter.ReplaceText(clang::SourceRange(Subscr->getBeginLoc(), Subscr->getEndLoc()), ArrName + "0"); // for now, for test purposes +// std::string CaseBody = mRewriter.getRewrittenText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc())); + std::string switchText = "switch (" + IndexName + ") {\n"; + for (int i = 0; i < std::stoi(SizeLiteral->getString.str()); i++) { + ExternalRewriter Canvas(clang::SourceRange(S->getBeginLoc(), S->getEndLoc()), mSrcMgr, mLangOpts); + auto ArrSize = cast(SizeStmt)->getValue().getSExtValue(); + auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; + std::string ArrName = ArrayLiteral->getString().str(); + ArrName += "_subscr_"; + for (auto Subscr: mArraySubscriptExpr) { + Canvas.ReplaceText(clang::SourceRange(Subscr->getBeginLoc(), Subscr->getEndLoc()), ArrName + std::to_string(i)); + } + std::string caseBody = Canvas.getRewrittenText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc())); + switchText += "case " + std::to_string(i) + ":\n" + caseBody + "\nbreak;\n"; } + switchText += "}"; return RecursiveASTVisitor::TraverseStmt(S); } case GET_ALL_ARRAY_SUBSCRIPTS: { From 0d35933269660bd45c70ce655358daed0c92c5d9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Feb 2022 21:33:15 +0300 Subject: [PATCH 09/14] remove_redarray: test logs --- lib/Transform/Clang/RemoveRedarray.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index cc68286b..21f2e584 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -62,10 +62,13 @@ using namespace llvm; using namespace tsar; +#define LLVM_DEBUG(X) X + #undef DEBUG_TYPE #define DEBUG_TYPE "clang-remove-redarray" #define DEBUG_PREFIX "[REMOVE REDARRAY]: " + namespace { class ClangRemoveRedarray : public FunctionPass, private bcl::Uncopyable { public: @@ -313,6 +316,7 @@ class ClangRemoveRedarrayVisitor } bool TraverseStmt(clang::Stmt *S) { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "launch remove_redarray\n"); if (!S) return RecursiveASTVisitor::TraverseStmt(S); switch (mStatus) { @@ -544,8 +548,8 @@ class ClangRemoveRedarrayVisitor auto [SizeLiteral, SizeStmt] = mSwaps[1]; auto IndexName = mIndex->getName(); // std::string CaseBody = mRewriter.getRewrittenText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc())); - std::string switchText = "switch (" + IndexName + ") {\n"; - for (int i = 0; i < std::stoi(SizeLiteral->getString.str()); i++) { + std::string switchText = "switch (" + IndexName.str() + ") {\n"; + for (int i = 0; i < std::stoi(SizeLiteral->getString().str()); i++) { ExternalRewriter Canvas(clang::SourceRange(S->getBeginLoc(), S->getEndLoc()), mSrcMgr, mLangOpts); auto ArrSize = cast(SizeStmt)->getValue().getSExtValue(); auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; @@ -554,7 +558,7 @@ class ClangRemoveRedarrayVisitor for (auto Subscr: mArraySubscriptExpr) { Canvas.ReplaceText(clang::SourceRange(Subscr->getBeginLoc(), Subscr->getEndLoc()), ArrName + std::to_string(i)); } - std::string caseBody = Canvas.getRewrittenText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc())); + std::string caseBody = Canvas.getRewrittenText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc())).str(); switchText += "case " + std::to_string(i) + ":\n" + caseBody + "\nbreak;\n"; } switchText += "}"; @@ -725,6 +729,9 @@ class ClangRemoveRedarrayVisitor } // namespace bool ClangRemoveRedarray::runOnFunction(Function &F) { + + dbgs() << DEBUG_PREFIX << "launch remove_redarray\n"; + auto *DISub{findMetadata(&F)}; if (!DISub) return false; From be0a450a347702dc48c76e3325f4807ab8dba508 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Feb 2022 00:56:40 +0300 Subject: [PATCH 10/14] temp fix --- lib/Transform/Clang/RemoveRedarray.cpp | 33 +++++++++++++++++++------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index 21f2e584..5dd868e8 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -90,11 +90,14 @@ class ClangRemoveRedarrayInfo final : public tsar::PassGroupInfo { void ClangRemoveRedarrayInfo::addBeforePass( legacy::PassManager &Passes) const { + dbgs() << DEBUG_PREFIX << "launch before_pass remove_redarray\n"; addImmutableAliasAnalysis(Passes); addInitialTransformations(Passes); Passes.add(createAnalysisSocketImmutableStorage()); Passes.add(createDIMemoryTraitPoolStorage()); Passes.add(createDIMemoryEnvironmentStorage()); + Passes.add(createGlobalsAccessStorage()); + Passes.add(createGlobalsAccessCollector()); Passes.add(createDIEstimateMemoryPass()); Passes.add(createDIMemoryAnalysisServer()); Passes.add(createAnalysisWaitServerPass()); @@ -108,7 +111,8 @@ void ClangRemoveRedarrayInfo::addAfterPass(legacy::PassManager &Passes) const { } void ClangRemoveRedarray::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + dbgs() << DEBUG_PREFIX << "launch getAnalysisUsage remove_redarray\n"; + //AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addRequired(); @@ -120,7 +124,8 @@ void ClangRemoveRedarray::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); AU.addRequired(); AU.addRequired(); - AU.setPreservesAll(); + //AU.setPreservesAll(); + dbgs() << DEBUG_PREFIX << "end getAnalysisUsage remove_redarray\n"; } char ClangRemoveRedarray::ID = 0; @@ -129,12 +134,13 @@ INITIALIZE_PASS_IN_GROUP_BEGIN(ClangRemoveRedarray, "clang-remove-redarray", "Remove Redarray (Clang)", false, false, TransformationQueryManager::getPassRegistry()) INITIALIZE_PASS_IN_GROUP_INFO(ClangRemoveRedarrayInfo) -INITIALIZE_PASS_DEPENDENCY(AnalysisClientServerMatcherWrapper) +//INITIALIZE_PASS_DEPENDENCY(AnalysisClientServerMatcherWrapper) INITIALIZE_PASS_DEPENDENCY(CanonicalLoopPass) +INITIALIZE_PASS_DEPENDENCY(ClangPerfectLoopPass) INITIALIZE_PASS_DEPENDENCY(ClangDIMemoryMatcherPass) INITIALIZE_PASS_DEPENDENCY(ClangGlobalInfoPass) -INITIALIZE_PASS_DEPENDENCY(ClonedDIMemoryMatcherWrapper) -INITIALIZE_PASS_DEPENDENCY(DIDependencyAnalysisPass) +//INITIALIZE_PASS_DEPENDENCY(ClonedDIMemoryMatcherWrapper) +//INITIALIZE_PASS_DEPENDENCY(DIDependencyAnalysisPass) INITIALIZE_PASS_DEPENDENCY(DIEstimateMemoryPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(EstimateMemoryPass) @@ -284,13 +290,15 @@ class ClangRemoveRedarrayVisitor // } bool TraverseVarDecl(clang::VarDecl *VD) { + dbgs() << DEBUG_PREFIX << "launch VarDecl remove_redarray\n"; if (mStatus == FIND_INDEX) { mIndex = VD; } - return RecursiveASTVisitor::TraverseDecl(VD); + return RecursiveASTVisitor::TraverseVarDecl(VD); } bool TraverseDecl(clang::Decl *D) { + dbgs() << DEBUG_PREFIX << "launch Decl remove_redarray\n"; if (!D) return RecursiveASTVisitor::TraverseDecl(D); if (mStatus == TRAVERSE_STMT) { @@ -302,6 +310,7 @@ class ClangRemoveRedarrayVisitor } bool TraverseBinaryOperator(clang::BinaryOperator * B) { + dbgs() << DEBUG_PREFIX << "launch BinaryOperator remove_redarray\n"; if (mStatus != GET_ALL_ARRAY_SUBSCRIPTS) { return RecursiveASTVisitor::TraverseBinaryOperator(B); } @@ -309,6 +318,7 @@ class ClangRemoveRedarrayVisitor } bool TraverseUnaryOperator(clang::UnaryOperator *U) { + dbgs() << DEBUG_PREFIX << "launch UnaryOperator remove_redarray\n"; if (mStatus != GET_ALL_ARRAY_SUBSCRIPTS) { return RecursiveASTVisitor::TraverseUnaryOperator(U); } @@ -316,7 +326,7 @@ class ClangRemoveRedarrayVisitor } bool TraverseStmt(clang::Stmt *S) { - LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "launch remove_redarray\n"); + dbgs() << DEBUG_PREFIX << "launch Stmt remove_redarray\n"; if (!S) return RecursiveASTVisitor::TraverseStmt(S); switch (mStatus) { @@ -730,30 +740,37 @@ class ClangRemoveRedarrayVisitor bool ClangRemoveRedarray::runOnFunction(Function &F) { - dbgs() << DEBUG_PREFIX << "launch remove_redarray\n"; + dbgs() << DEBUG_PREFIX << "launch runOnFunction remove_redarray\n"; auto *DISub{findMetadata(&F)}; if (!DISub) return false; + dbgs() << DEBUG_PREFIX << "DISub initialized runOnFunction remove_redarray\n"; auto *CU{DISub->getUnit()}; if (!isC(CU->getSourceLanguage()) && !isCXX(CU->getSourceLanguage())) return false; + dbgs() << DEBUG_PREFIX << "getSourceLanguage runOnFunction remove_redarray\n"; auto &TfmInfo{getAnalysis()}; + dbgs() << DEBUG_PREFIX << "getAnalysis runOnFunction remove_redarray\n"; auto *TfmCtx{TfmInfo ? dyn_cast_or_null( TfmInfo->getContext(*CU)) : nullptr}; + dbgs() << DEBUG_PREFIX << "TfmInfo ClangTransformationContext runOnFunction remove_redarray\n"; if (!TfmCtx || !TfmCtx->hasInstance()) { F.getContext().emitError("can not transform sources" ": transformation context is not available"); return false; } + dbgs() << DEBUG_PREFIX << "TfmCtx runOnFunction remove_redarray\n"; auto *FD{TfmCtx->getDeclForMangledName(F.getName())}; if (!FD) return false; + dbgs() << DEBUG_PREFIX << "FD runOnFunction remove_redarray\n"; ASTImportInfo ImportStub; const auto *ImportInfo{&ImportStub}; if (auto *ImportPass = getAnalysisIfAvailable()) ImportInfo = &ImportPass->getImportInfo(); + dbgs() << DEBUG_PREFIX << "end of runOnFunction remove_redarray\n"; ClangRemoveRedarrayVisitor(*this, F, TfmCtx, *ImportInfo).TraverseDecl(FD); return false; } From d02aae7d0158c352ef15e7a9dfeaf540aa9efe6d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Apr 2022 01:00:09 +0300 Subject: [PATCH 11/14] remove-redarray working --- lib/Transform/Clang/RemoveRedarray.cpp | 361 +++---------------------- 1 file changed, 38 insertions(+), 323 deletions(-) diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index 5dd868e8..f37d0785 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -112,7 +112,6 @@ void ClangRemoveRedarrayInfo::addAfterPass(legacy::PassManager &Passes) const { void ClangRemoveRedarray::getAnalysisUsage(AnalysisUsage &AU) const { dbgs() << DEBUG_PREFIX << "launch getAnalysisUsage remove_redarray\n"; - //AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addRequired(); @@ -134,13 +133,10 @@ INITIALIZE_PASS_IN_GROUP_BEGIN(ClangRemoveRedarray, "clang-remove-redarray", "Remove Redarray (Clang)", false, false, TransformationQueryManager::getPassRegistry()) INITIALIZE_PASS_IN_GROUP_INFO(ClangRemoveRedarrayInfo) -//INITIALIZE_PASS_DEPENDENCY(AnalysisClientServerMatcherWrapper) INITIALIZE_PASS_DEPENDENCY(CanonicalLoopPass) INITIALIZE_PASS_DEPENDENCY(ClangPerfectLoopPass) INITIALIZE_PASS_DEPENDENCY(ClangDIMemoryMatcherPass) INITIALIZE_PASS_DEPENDENCY(ClangGlobalInfoPass) -//INITIALIZE_PASS_DEPENDENCY(ClonedDIMemoryMatcherWrapper) -//INITIALIZE_PASS_DEPENDENCY(DIDependencyAnalysisPass) INITIALIZE_PASS_DEPENDENCY(DIEstimateMemoryPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(EstimateMemoryPass) @@ -157,18 +153,29 @@ class RedarrayClauseVisitor : public clang::RecursiveASTVisitor { public: explicit RedarrayClauseVisitor( - SmallVectorImpl> &Ls) + SmallVectorImpl> &Ls) : mLiterals(Ls) {} bool VisitStringLiteral(clang::StringLiteral *SL) { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "visit string literal RedarrayClauseVisitor, string: " << SL->getString() << "\n"); if (SL->getString() != getName(ClauseId::RemoveRedarray)) - mLiterals.emplace_back(SL, mClause); + mLiterals.emplace_back(SL->getString(), mClause); return true; } + bool VisitDeclRefExpr(clang::DeclRefExpr* DE) { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "visit decl ref expr RedarrayClauseVisitor, found: " << DE->getNameInfo().getAsString() << "\n"); + mLiterals.emplace_back(DE->getNameInfo().getAsString(), DE); + return true; + } + bool VisitIntegerLiteral(clang::IntegerLiteral* DE) { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "visit IntegerLiteral RedarrayClauseVisitor\n"); + mLiterals.emplace_back("", DE); + return true; + } void setClause(clang::Stmt *C) noexcept { mClause = C; } private: - SmallVectorImpl> &mLiterals; + SmallVectorImpl> &mLiterals; clang::Stmt *mClause{nullptr}; }; @@ -198,7 +205,7 @@ class ClangRemoveRedarrayVisitor const ASTImportInfo &ImportInfo) : mImportInfo(ImportInfo), mRewriter(TfmCtx->getRewriter()), mSrcMgr(mRewriter.getSourceMgr()), mLangOpts(mRewriter.getLangOpts()), - mRawInfo(P.getAnalysis().getRawInfo()), + mRawInfo(P.getAnalysis().getGlobalInfo(TfmCtx)->RI), mGlobalOpts( P.getAnalysis().getOptions()), mMemMatcher(P.getAnalysis()->Matcher), @@ -216,81 +223,8 @@ class ClangRemoveRedarrayVisitor mSTR = SpanningTreeRelation{mDIMInfo.DIAT}; } - // bool TraverseForStmt(clang::ForStmt *FS) { - // if (mStatus != REPLACE_ARRAY_ACCESSES) - // return RecursiveASTVisitor::TraverseForStmt(FS); - // auto CanonicalItr{find_if(mCanonicalLoopInfo, [FS](auto *Info) { - // return Info->getASTLoop() == FS; - // })}; - // auto IsCanonical{false}, IsPerfect{false}; - // //mInductions.emplace_back(nullptr, nullptr, FS, Ok, VarList{}, nullptr); - // if (CanonicalItr != mCanonicalLoopInfo.end() && - // (*CanonicalItr)->isCanonical()) { - // IsCanonical = true; - // IsPerfect = mPerfectLoopInfo.count((*CanonicalItr)->getLoop()); - // auto VarItr{mMemMatcher.find((*CanonicalItr)->getInduction())}; - // std::get(mInductions.back()) = VarItr->get(); - // std::get(mInductions.back()) = *CanonicalItr; - // } - // if (!IsCanonical) - // std::get(mInductions.back()) |= NotCanonical; - // if (!IsPerfect) - // std::get(mInductions.back()) |= NotPerfect; - // if (!mIsStrict || !IsCanonical) { - // if (!IsCanonical) - // std::get(mInductions.back()) |= NotAnalyzed; - // return RecursiveASTVisitor::TraverseForStmt(FS); - // } - // auto Dependency{false}; - // auto *L{(*CanonicalItr)->getLoop()->getLoop()}; - // if (!mDIMInfo.isValid()) { - // std::get(mInductions.back()) |= NotAnalyzed; - // return RecursiveASTVisitor::TraverseForStmt(FS); - // } - // auto *DIDepSet{mDIMInfo.findFromClient(*L)}; - // if (!DIDepSet) { - // std::get(mInductions.back()) |= NotAnalyzed; - // return RecursiveASTVisitor::TraverseForStmt(FS); - // } - // DenseSet Coverage; - // accessCoverage(*DIDepSet, *mDIMInfo.DIAT, Coverage, - // mGlobalOpts.IgnoreRedundantMemory); - // if (!Coverage.empty()) - // for (auto &Trait : *DIDepSet) { - // if (!Coverage.count(Trait.getNode()) || hasNoDep(Trait) || - // Trait.is_any()) - // continue; - // if(Trait.is_any() && - // Trait.size() == 1) { - // if (auto DIEM{ - // dyn_cast((*Trait.begin())->getMemory())}; - // DIEM && DIEM->getExpression()->getNumElements() == 0) { - // auto *ClientDIM{ - // mDIMInfo.getClientMemory(const_cast(DIEM))}; - // assert(ClientDIM && "Origin memory must exist!"); - // auto VarToDI{mDIMemMatcher.find( - // cast(ClientDIM)->getVariable())}; - // if (Trait.is()) { - // if (VarToDI->template get() == - // std::get(mInductions.back())) { - // std::get(mInductions.back()) = DIEM; - // continue; - // } - // } else { - // std::get(mInductions.back()) - // .push_back(VarToDI->template get()); - // continue; - // } - // } - // } - // std::get(mInductions.back()) |= HasDependency; - // break; - // } - // return RecursiveASTVisitor::TraverseForStmt(FS); - // } bool TraverseVarDecl(clang::VarDecl *VD) { - dbgs() << DEBUG_PREFIX << "launch VarDecl remove_redarray\n"; if (mStatus == FIND_INDEX) { mIndex = VD; } @@ -298,7 +232,6 @@ class ClangRemoveRedarrayVisitor } bool TraverseDecl(clang::Decl *D) { - dbgs() << DEBUG_PREFIX << "launch Decl remove_redarray\n"; if (!D) return RecursiveASTVisitor::TraverseDecl(D); if (mStatus == TRAVERSE_STMT) { @@ -310,23 +243,20 @@ class ClangRemoveRedarrayVisitor } bool TraverseBinaryOperator(clang::BinaryOperator * B) { - dbgs() << DEBUG_PREFIX << "launch BinaryOperator remove_redarray\n"; if (mStatus != GET_ALL_ARRAY_SUBSCRIPTS) { return RecursiveASTVisitor::TraverseBinaryOperator(B); } - return TraverseStmt(B); + return RecursiveASTVisitor::TraverseBinaryOperator(B); } bool TraverseUnaryOperator(clang::UnaryOperator *U) { - dbgs() << DEBUG_PREFIX << "launch UnaryOperator remove_redarray\n"; if (mStatus != GET_ALL_ARRAY_SUBSCRIPTS) { return RecursiveASTVisitor::TraverseUnaryOperator(U); } - return TraverseStmt(U); + return RecursiveASTVisitor::TraverseUnaryOperator(U); } bool TraverseStmt(clang::Stmt *S) { - dbgs() << DEBUG_PREFIX << "launch Stmt remove_redarray\n"; if (!S) return RecursiveASTVisitor::TraverseStmt(S); switch (mStatus) { @@ -369,6 +299,7 @@ class ClangRemoveRedarrayVisitor return true; } case TRAVERSE_STMT: { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "enter traverse_stmt stage\n"); if (!isa(S)) { toDiag(mSrcMgr.getDiagnostics(), S->getBeginLoc(), tsar::diag::warn_interchange_not_for_loop); // TODO: change this warn @@ -388,11 +319,11 @@ class ClangRemoveRedarrayVisitor resetVisitor(); return RecursiveASTVisitor::TraverseStmt(S); } - auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; + auto [ArrName, ArrayStmt] = mSwaps[0]; auto [SizeLiteral, SizeStmt] = mSwaps[1]; - std::string ArrName = ArrayLiteral->getString().str(); ArrName += "_subscr_"; - std::string ToInsert = cast(S)->getType().getAsString(); + std::string ToInsert = cast(ArrayStmt)->getType().getAsString(); + ToInsert.erase(ToInsert.find('['), ToInsert.find(']')); for (int i = 0; i < cast(SizeStmt)->getValue().getSExtValue(); i++) { if (i > 0) { ToInsert += ","; @@ -407,138 +338,10 @@ class ClangRemoveRedarrayVisitor auto Res = RecursiveASTVisitor::TraverseStmt(S); mStatus = FIND_OP; Res = RecursiveASTVisitor::TraverseStmt(S); - // fill array here return true; - //auto Res = TraverseForStmt(cast(S)); - // TODO: insert array filling somewhere here - // if (!Res) { - // resetVisitor(); - // return false; - // } - // // Match induction names from clauses to loop induction variables. - // unsigned MaxIdx{0}; - // llvm::SmallVector ValueSwaps; - - - // // Check whether transfromation is possible. - // auto checkLoop = [this](unsigned I, unsigned MaxIdx) { - // auto checkPrivatizable = [](VarList &L, auto I, auto EI) { - // for (auto *V : L) - // if (EI == std::find_if(I, EI, [V](auto &Induct) { - // return std::get(Induct) == V; - // })) - // return false; - - // return true; - // }; - // if (std::get(mInductions[I]) & NotCanonical) { - // toDiag(mSrcMgr.getDiagnostics(), - // std::get(mInductions[I])->getBeginLoc(), - // tsar::diag::warn_interchange_not_canonical); - // } else if (std::get(mInductions[I]) & HasDependency) { - // toDiag(mSrcMgr.getDiagnostics(), - // std::get(mInductions[I])->getBeginLoc(), - // tsar::diag::warn_interchange_dependency); - // } else if (!mIsStrict) { - // return true; - // } else if (std::get(mInductions[I]) & NotAnalyzed) { - // toDiag(mSrcMgr.getDiagnostics(), - // std::get(mInductions[I])->getBeginLoc(), - // tsar::diag::warn_interchange_no_analysis); - // } else if (!checkPrivatizable(std::get(mInductions[I]), - // mInductions.begin() + I + 1, - // mInductions.end())) { - // toDiag(mSrcMgr.getDiagnostics(), - // std::get(mInductions[I])->getBeginLoc(), - // tsar::diag::warn_interchange_dependency); - // } else if (auto *For{isMemoryAccessedIn( - // std::get(mInductions[I]), - // std::get(mInductions[I]) - // ->getLoop() - // ->getLoop(), - // mInductions.begin() + I + 1, - // mInductions.begin() + MaxIdx + 1)}) { - // toDiag(mSrcMgr.getDiagnostics(), - // std::get(mInductions[I])->getBeginLoc(), - // tsar::diag::warn_disable_loop_interchange); - // toDiag(mSrcMgr.getDiagnostics(), For->getBeginLoc(), - // tsar::diag::note_interchange_irregular_loop_nest); - // } else { - // return true; - // } - // return false; - // }; - // auto IsPossible(true); - // for (auto I{0u}; I < MaxIdx; I++) { - // if (std::get(mInductions[I]) & NotPerfect) { - // IsPossible = false; - // toDiag(mSrcMgr.getDiagnostics(), - // std::get(mInductions[I])->getBeginLoc(), - // tsar::diag::warn_interchange_not_perfect); - // } else { - // IsPossible &= checkLoop(I, MaxIdx); - // } - // } - // // Check the innermost loop which participates in the transformation. - // // Note, the it may have not canonical loop form. - // IsPossible &= checkLoop(MaxIdx, MaxIdx); - // if (!IsPossible) { - // resetVisitor(); - // return RecursiveASTVisitor::TraverseStmt(S); - // } - // // Deduce new order. - // SmallVector Order; - // std::transform(mInductions.begin(), mInductions.begin() + MaxIdx + 1, - // std::back_inserter(Order), - // [](auto &I) { return std::get(I); }); - // for (unsigned I{0}, EI = ValueSwaps.size(); I < EI; I += 2) { - // auto FirstItr{find(Order, ValueSwaps[I])}; - // assert(FirstItr != Order.end() && "Induction must exist!"); - // auto SecondItr{find(Order, ValueSwaps[I + 1])}; - // assert(SecondItr != Order.end() && "Induction must exist!"); - // std::swap(*FirstItr, *SecondItr); - // } - // // Collect sources of loop headers before the transformation. Note, do not - // // use Rewriter::ReplaceText(SourceRange, SourceRange) because it uses - // // Rewriter::getRangeSize(SourceRange) to compute a length of a destination - // // as well as a length of a source and this method uses rewritten text to - // // collect size. Thus, the size of the source can be computed in the wrong - // // way because the transformation of outer loops has already taken place. - // SmallVector Sources; - // for (auto I{0u}; I < MaxIdx + 1; I++) { - // clang::SourceRange Source{ - // std::get(mInductions[I])->getInit()->getBeginLoc(), - // std::get(mInductions[I])->getInc()->getEndLoc()}; - // Sources.push_back(mRewriter.getRewrittenText(Source)); - // } - // // Interchange loop headers. - // for (auto I{0u}; I < MaxIdx + 1 ; I++) { - // if (Order[I] != std::get(mInductions[I])) { - // auto OriginItr{find_if(mInductions, [What = Order[I]](auto &Induct) { - // return std::get(Induct) == What; - // })}; - // clang::SourceRange Destination( - // std::get(mInductions[I]) - // ->getInit() - // ->getBeginLoc(), - // std::get(mInductions[I]) - // ->getInc() - // ->getEndLoc()); - // mRewriter.ReplaceText( - // Destination, - // Sources[std::distance(mInductions.begin(), OriginItr)]); - // } - // } - // LLVM_DEBUG(dbgs() << DEBUG_PREFIX << ": finish pragma processing\n"); - // resetVisitor(); - // return true; } case FIND_INDEX: { - // if (!isa(S)) { - // return RecursiveASTVisitor::TraverseStmt(S); - // } - // mIndex = cast(S); return RecursiveASTVisitor::TraverseStmt(S); } case FIND_OP: { @@ -547,9 +350,9 @@ class ClangRemoveRedarrayVisitor } mStatus = GET_ALL_ARRAY_SUBSCRIPTS; if (isa(S)) { - auto Res = TraverseBinaryOperator(cast(S)); + auto Res = RecursiveASTVisitor::TraverseBinaryOperator(cast(S)); } else { - auto Res = TraverseUnaryOperator(cast(S)); + auto Res = RecursiveASTVisitor::TraverseUnaryOperator(cast(S)); } mStatus = FIND_OP; if (mArraySubscriptExpr.size() == 0) { @@ -557,21 +360,21 @@ class ClangRemoveRedarrayVisitor } auto [SizeLiteral, SizeStmt] = mSwaps[1]; auto IndexName = mIndex->getName(); -// std::string CaseBody = mRewriter.getRewrittenText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc())); std::string switchText = "switch (" + IndexName.str() + ") {\n"; - for (int i = 0; i < std::stoi(SizeLiteral->getString().str()); i++) { + for (int i = 0; i < cast(SizeStmt)->getValue().getSExtValue(); i++) { ExternalRewriter Canvas(clang::SourceRange(S->getBeginLoc(), S->getEndLoc()), mSrcMgr, mLangOpts); auto ArrSize = cast(SizeStmt)->getValue().getSExtValue(); - auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; - std::string ArrName = ArrayLiteral->getString().str(); + auto [ArrName, ArrayStmt] = mSwaps[0]; ArrName += "_subscr_"; for (auto Subscr: mArraySubscriptExpr) { Canvas.ReplaceText(clang::SourceRange(Subscr->getBeginLoc(), Subscr->getEndLoc()), ArrName + std::to_string(i)); } std::string caseBody = Canvas.getRewrittenText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc())).str(); - switchText += "case " + std::to_string(i) + ":\n" + caseBody + "\nbreak;\n"; + switchText += "case " + std::to_string(i) + ":\n" + caseBody + ";\nbreak;\n"; } switchText += "}"; + mRewriter.ReplaceText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc()), switchText); + clearArraySubscr(); return RecursiveASTVisitor::TraverseStmt(S); } case GET_ALL_ARRAY_SUBSCRIPTS: { @@ -580,7 +383,7 @@ class ClangRemoveRedarrayVisitor } mIsSubscriptUseful = false; mStatus = CHECK_SUBSCRIPT; - auto Res = TraverseStmt(S); + auto Res = RecursiveASTVisitor::TraverseStmt(S); mStatus = GET_ALL_ARRAY_SUBSCRIPTS; if (mIsSubscriptUseful) { mArraySubscriptExpr.push_back(cast(S)); @@ -592,8 +395,8 @@ class ClangRemoveRedarrayVisitor return RecursiveASTVisitor::TraverseStmt(S); } auto Arr = cast(S); - auto [ArrayLiteral, ArrayStmt] = mSwaps[0]; - if (ArrayLiteral->getString().str() == Arr->getNameInfo().getName().getAsString()) { + auto [ArrName, ArrayStmt] = mSwaps[0]; + if (ArrName == Arr->getNameInfo().getName().getAsString()) { mIsSubscriptUseful = true; return true; } @@ -611,105 +414,17 @@ class ClangRemoveRedarrayVisitor mInductions.clear(); } - /// Return true if a specified induction variable `DIM` of a loop `L` may be - /// accessed in an any header of specified canonical loops. - // clang::ForStmt *isMemoryAccessedIn(const DIMemory *DIM, const Loop *L, - // LoopNest::iterator I, - // LoopNest::iterator EI) { - // assert(DIM && - // "Results of canonical loop analysis must be available for a loop!"); - // for (auto &Induct : make_range(I, EI)) { - // if (isMemoryAccessedIn( - // DIM, std::get(Induct)->getStart()) || - // isMemoryAccessedIn( - // DIM, std::get(Induct)->getEnd()) || - // isMemoryAccessedIn( - // DIM, L, std::get(Induct)->getStep())) - // return std::get(Induct); - // } - // return nullptr; - // } - - // /// Return true if a specified induction variable `DIM` of a loop `L` may be - // /// accessed in a specified expression `S`. - // bool isMemoryAccessedIn(const DIMemory *DIM, const Loop *L, const SCEV *S) { - // if (!S) - // return true; - // struct SCEVMemorySearch { - // SCEVMemorySearch(const Loop *Lp) : L(Lp) {} - // bool follow(const SCEV *S) { - // if (auto *AddRec{dyn_cast(S)}; - // AddRec && AddRec->getLoop() == L) - // L = nullptr; - // else if (auto *Unknown{dyn_cast(S)}) - // Values.push_back(Unknown->getValue()); - // return true; - // } - // bool isDone() { - // // Finish search if reference to a loop has been found. - // return !L; - // } - // SmallVector Values; - // const Loop *L; - // } Visitor{L}; - // visitAll(S, Visitor); - // if (!Visitor.L) - // return true; - // for (auto *V : Visitor.Values) - // if (isMemoryAccessedIn(DIM, V)) - // return true; - // return false; - // } - - // /// Return true if a specified induction variable `DIM` of a loop `L` may be - // /// accessed in a specified value `V`. - // bool isMemoryAccessedIn(const DIMemory *DIM, Value *V) { - // if (!V) - // return true; - // if (isa(V)) - // return false; - // if (auto *Inst{dyn_cast(V)}) { - // auto &DL{Inst->getModule()->getDataLayout()}; - // bool Result{false}; - // auto DIN{DIM->getAliasNode()}; - // for_each_memory( - // *Inst, mTLI, - // [this, DIN, &DL, &Result](Instruction &, MemoryLocation &&Loc, - // unsigned, AccessInfo R, AccessInfo W) { - // if (Result) - // return; - // if (R == AccessInfo::No && W == AccessInfo::No) - // return; - // auto EM{mAT.find(Loc)}; - // assert(EM && "Estimate memory location must not be null!"); - // auto *DIM{mDIMInfo.findFromClient(*EM->getTopLevelParent(), DL, mDT) - // .get()}; - // Result = !DIM || !mSTR->isUnreachable(DIM->getAliasNode(), DIN); - // }, - // [this, DIN, &Result](Instruction &I, AccessInfo, AccessInfo) { - // return; - // if (Result || (Result = !isa(I))) - // return; - // auto *DIM{mDIMInfo.findFromClient(I, mDT, DIUnknownMemory::NoFlags) - // .get()}; - // assert(DIM && "Metadata-level memory must be available!"); - // Result = !DIM || !mSTR->isUnreachable(DIM->getAliasNode(), DIN); - // }); - // if (Result) - // return true; - // for (auto &Op : Inst->operands()) - // if (!isa(Op) && !isa(Op) && - // isMemoryAccessedIn(DIM, Op)) - // return true; - // } - // return false; - // } + void clearArraySubscr() { + mArraySubscriptExpr.clear(); + } + + const ASTImportInfo mImportInfo; clang::Rewriter &mRewriter; clang::SourceManager &mSrcMgr; const clang::LangOptions &mLangOpts; - ClangGlobalInfoPass::RawInfo &mRawInfo; + ClangGlobalInfo::RawInfo &mRawInfo; const GlobalOptions &mGlobalOpts; MemoryMatchInfo::MemoryMatcher &mMemMatcher; const ClangDIMemoryMatcherPass::DIMemoryMatcher &mDIMemMatcher; @@ -729,7 +444,7 @@ class ClangRemoveRedarrayVisitor GET_ALL_ARRAY_SUBSCRIPTS, CHECK_SUBSCRIPT, } mStatus{SEARCH_PRAGMA}; - SmallVector, 4> mSwaps; + SmallVector, 4> mSwaps; std::vector mArraySubscriptExpr; bool mIsSubscriptUseful; clang::VarDecl* mIndex; From 80dd5396cfb97c387f4d0fd2bce24b91aa2c5ff4 Mon Sep 17 00:00:00 2001 From: ArtherusAA Date: Sun, 24 Apr 2022 20:03:27 +0300 Subject: [PATCH 12/14] write array filling after for --- lib/Transform/Clang/RemoveRedarray.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index f37d0785..ea8d9893 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -321,6 +321,7 @@ class ClangRemoveRedarrayVisitor } auto [ArrName, ArrayStmt] = mSwaps[0]; auto [SizeLiteral, SizeStmt] = mSwaps[1]; + std::string OldArrName = ArrName; ArrName += "_subscr_"; std::string ToInsert = cast(ArrayStmt)->getType().getAsString(); ToInsert.erase(ToInsert.find('['), ToInsert.find(']')); @@ -338,6 +339,11 @@ class ClangRemoveRedarrayVisitor auto Res = RecursiveASTVisitor::TraverseStmt(S); mStatus = FIND_OP; Res = RecursiveASTVisitor::TraverseStmt(S); + ToInsert = ""; + for (int i = 0; i < cast(SizeStmt)->getValue().getSExtValue(); i++) { + ToInsert += OldArrName + "[" + std::to_string(i) + "] = " + ArrName + std::to_string(i) + ";\n"; + } + mRewriter.InsertTextAfterToken(S->getEndLoc(), ToInsert); return true; } From 88775d2e0de9501f3f3467890cc6a4628b234e00 Mon Sep 17 00:00:00 2001 From: ArtherusAA Date: Fri, 13 May 2022 20:57:36 +0300 Subject: [PATCH 13/14] review fix --- include/tsar/Support/Directives.td | 3 +- lib/Transform/Clang/RemoveRedarray.cpp | 154 +++++++++++++++++-------- 2 files changed, 109 insertions(+), 48 deletions(-) diff --git a/include/tsar/Support/Directives.td b/include/tsar/Support/Directives.td index b113cd6d..11917363 100644 --- a/include/tsar/Support/Directives.td +++ b/include/tsar/Support/Directives.td @@ -140,7 +140,8 @@ def LoopInterchange : Clause<"interchange", Transform, [LParen, PPIdentifier, Comma, PPIdentifier, RParen]>; def RemoveRedarray : Clause<"remove_redarray", Transform, - [LParen, Identifier, Comma, NumericConstant, RParen]>; + [LParen, Identifier, LSquare, NumericConstant, RSquare, + ZeroOrMore<[Comma, Identifier, LSquare, NumericConstant, RSquare]>, RParen]>; def Replace : Clause<"replace", Transform, [ZeroOrOne<[LParen, Identifier, ZeroOrMore<[Comma, Identifier]>, RParen]>]>; diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index ea8d9893..1867e509 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -62,8 +62,6 @@ using namespace llvm; using namespace tsar; -#define LLVM_DEBUG(X) X - #undef DEBUG_TYPE #define DEBUG_TYPE "clang-remove-redarray" #define DEBUG_PREFIX "[REMOVE REDARRAY]: " @@ -90,7 +88,6 @@ class ClangRemoveRedarrayInfo final : public tsar::PassGroupInfo { void ClangRemoveRedarrayInfo::addBeforePass( legacy::PassManager &Passes) const { - dbgs() << DEBUG_PREFIX << "launch before_pass remove_redarray\n"; addImmutableAliasAnalysis(Passes); addInitialTransformations(Passes); Passes.add(createAnalysisSocketImmutableStorage()); @@ -111,7 +108,6 @@ void ClangRemoveRedarrayInfo::addAfterPass(legacy::PassManager &Passes) const { } void ClangRemoveRedarray::getAnalysisUsage(AnalysisUsage &AU) const { - dbgs() << DEBUG_PREFIX << "launch getAnalysisUsage remove_redarray\n"; AU.addRequired(); AU.addRequired(); AU.addRequired(); @@ -124,7 +120,6 @@ void ClangRemoveRedarray::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); AU.addRequired(); //AU.setPreservesAll(); - dbgs() << DEBUG_PREFIX << "end getAnalysisUsage remove_redarray\n"; } char ClangRemoveRedarray::ID = 0; @@ -153,8 +148,10 @@ class RedarrayClauseVisitor : public clang::RecursiveASTVisitor { public: explicit RedarrayClauseVisitor( - SmallVectorImpl> &Ls) - : mLiterals(Ls) {} + SmallVectorImpl> &Ls, + std::vector> &decls, + std::vector> &sizes) + : mLiterals(Ls), mDecls(decls), mSizes(sizes) {} bool VisitStringLiteral(clang::StringLiteral *SL) { LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "visit string literal RedarrayClauseVisitor, string: " << SL->getString() << "\n"); if (SL->getString() != getName(ClauseId::RemoveRedarray)) @@ -164,11 +161,13 @@ class RedarrayClauseVisitor bool VisitDeclRefExpr(clang::DeclRefExpr* DE) { LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "visit decl ref expr RedarrayClauseVisitor, found: " << DE->getNameInfo().getAsString() << "\n"); mLiterals.emplace_back(DE->getNameInfo().getAsString(), DE); + mDecls.emplace_back(DE->getNameInfo().getAsString(), DE); return true; } bool VisitIntegerLiteral(clang::IntegerLiteral* DE) { LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "visit IntegerLiteral RedarrayClauseVisitor\n"); mLiterals.emplace_back("", DE); + mSizes.emplace_back("", DE); return true; } @@ -176,6 +175,8 @@ class RedarrayClauseVisitor private: SmallVectorImpl> &mLiterals; + std::vector> &mDecls; + std::vector> &mSizes; clang::Stmt *mClause{nullptr}; }; @@ -256,6 +257,12 @@ class ClangRemoveRedarrayVisitor return RecursiveASTVisitor::TraverseUnaryOperator(U); } + std::string addSuffix(std::string prefix) { + int i = 0; + while (mRawInfo.Identifiers.count(prefix + std::to_string(i)) > 0) { i++; } + return prefix + std::to_string(i); + } + bool TraverseStmt(clang::Stmt *S) { if (!S) return RecursiveASTVisitor::TraverseStmt(S); @@ -266,7 +273,7 @@ class ClangRemoveRedarrayVisitor if (!findClause(P, ClauseId::RemoveRedarray, Clauses)) return RecursiveASTVisitor::TraverseStmt(S); LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "found remove_redarray clause\n"); - RedarrayClauseVisitor SCV{mSwaps}; + RedarrayClauseVisitor SCV{mSwaps, mDecls, mSizes}; for (auto *C : Clauses) { SCV.setClause(C); SCV.TraverseStmt(C); @@ -319,31 +326,52 @@ class ClangRemoveRedarrayVisitor resetVisitor(); return RecursiveASTVisitor::TraverseStmt(S); } - auto [ArrName, ArrayStmt] = mSwaps[0]; - auto [SizeLiteral, SizeStmt] = mSwaps[1]; - std::string OldArrName = ArrName; - ArrName += "_subscr_"; - std::string ToInsert = cast(ArrayStmt)->getType().getAsString(); - ToInsert.erase(ToInsert.find('['), ToInsert.find(']')); - for (int i = 0; i < cast(SizeStmt)->getValue().getSExtValue(); i++) { - if (i > 0) { - ToInsert += ","; - } - ToInsert += (" " + ArrName + std::to_string(i)); + if (mDecls.size() != mSizes.size()) { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "number of arrays does not match number of their sizes\n"); + return false; + } + for (int i = 0; i < mDecls.size(); i++) { + auto [ArrName, ArrayStmt] = mDecls[i]; + auto [SizeLiteral, SizeStmt] = mSizes[i]; + const clang::Type* ArrayType = cast(ArrayStmt)->getType().getTypePtr(); + if (!isa(ArrayType) && !isa(ArrayType)) { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "statement in the pragma is not array or pointer\n"); + return false; + } + std::string ToInsert; + if (isa(ArrayType)) { + ToInsert = cast(ArrayType)->getElementType().getAsString(); + } + else if (isa(ArrayType)) { + ToInsert = cast(ArrayType)->getPointeeType().getAsString(); + } + arrayVarNames[ArrName] = std::vector(); + for (int i = 0; i < cast(SizeStmt)->getValue().getSExtValue(); i++) { + if (i > 0) { + ToInsert += ","; + } + std::string newVarName = addSuffix(ArrName + "_subscr_" + std::to_string(i) + "_"); + arrayVarNames[ArrName].push_back(newVarName); + ToInsert += (" " + newVarName + " = " + ArrName + "[" + std::to_string(i) + "]"); + } + ToInsert += (";\n"); + mRewriter.InsertTextBefore(S->getBeginLoc(), + ToInsert); // insert array variables + // definitions here } - ToInsert += (";\n"); - mRewriter.InsertTextBefore(S->getBeginLoc(), - ToInsert); // insert array variables - // definitions here mStatus = FIND_INDEX; auto Res = RecursiveASTVisitor::TraverseStmt(S); mStatus = FIND_OP; Res = RecursiveASTVisitor::TraverseStmt(S); - ToInsert = ""; - for (int i = 0; i < cast(SizeStmt)->getValue().getSExtValue(); i++) { - ToInsert += OldArrName + "[" + std::to_string(i) + "] = " + ArrName + std::to_string(i) + ";\n"; + for (int i = 0; i < mDecls.size(); i++) { + auto [ArrName, ArrayStmt] = mDecls[i]; + auto [SizeLiteral, SizeStmt] = mSizes[i]; + std::string ToInsert = ""; + for (int i = 0; i < cast(SizeStmt)->getValue().getSExtValue(); i++) { + ToInsert += ArrName + "[" + std::to_string(i) + "] = " + arrayVarNames[ArrName][i] + ";\n"; + } + mRewriter.InsertTextAfterToken(S->getEndLoc(), ToInsert); } - mRewriter.InsertTextAfterToken(S->getEndLoc(), ToInsert); return true; } @@ -357,23 +385,56 @@ class ClangRemoveRedarrayVisitor mStatus = GET_ALL_ARRAY_SUBSCRIPTS; if (isa(S)) { auto Res = RecursiveASTVisitor::TraverseBinaryOperator(cast(S)); - } else { + } else if (isa(S)) { auto Res = RecursiveASTVisitor::TraverseUnaryOperator(cast(S)); } + else { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "unsupported operator\n"); + return false; + } mStatus = FIND_OP; if (mArraySubscriptExpr.size() == 0) { return RecursiveASTVisitor::TraverseStmt(S); } - auto [SizeLiteral, SizeStmt] = mSwaps[1]; - auto IndexName = mIndex->getName(); - std::string switchText = "switch (" + IndexName.str() + ") {\n"; + int declIndex = -1; + for (int i = 0; i < mDecls.size(); i++) { + auto [SizeLiteral, SizeStmt] = mSizes[i]; + auto [ArrName, ArrayStmt] = mDecls[i]; + if (mRewriter.getRewrittenText(mArraySubscriptExpr[0]->getLHS()->getSourceRange()) == ArrName) { + declIndex = i; + } + } + if (declIndex == -1) { + return RecursiveASTVisitor::TraverseStmt(S); + } + for (int j = 1; j < mArraySubscriptExpr.size(); j++) { + if (mRewriter.getRewrittenText(mArraySubscriptExpr[j]->getLHS()->getSourceRange()) != + mRewriter.getRewrittenText(mArraySubscriptExpr[0]->getLHS()->getSourceRange())) { + bool arrayJInPragma = false; + bool array0InPragma = false; + for (int i = 0; i < mDecls.size(); i++) { + auto [ArrName, ArrayStmt] = mDecls[i]; + if (ArrName == mRewriter.getRewrittenText(mArraySubscriptExpr[0]->getLHS()->getSourceRange())) { + array0InPragma = true; + } + if (ArrName == mRewriter.getRewrittenText(mArraySubscriptExpr[j]->getLHS()->getSourceRange())) { + arrayJInPragma = true; + } + } + if (arrayJInPragma && array0InPragma) { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "different arrays in operator are not yet supported\n"); + return false; + } + } + } + auto [ArrName, ArrayStmt] = mDecls[declIndex]; + auto [SizeLiteral, SizeStmt] = mSizes[declIndex]; + std::string switchText = "switch (" + mRewriter.getRewrittenText(mArraySubscriptExpr[0]->getRHS()->getSourceRange()) + ") {\n"; for (int i = 0; i < cast(SizeStmt)->getValue().getSExtValue(); i++) { ExternalRewriter Canvas(clang::SourceRange(S->getBeginLoc(), S->getEndLoc()), mSrcMgr, mLangOpts); auto ArrSize = cast(SizeStmt)->getValue().getSExtValue(); - auto [ArrName, ArrayStmt] = mSwaps[0]; - ArrName += "_subscr_"; for (auto Subscr: mArraySubscriptExpr) { - Canvas.ReplaceText(clang::SourceRange(Subscr->getBeginLoc(), Subscr->getEndLoc()), ArrName + std::to_string(i)); + Canvas.ReplaceText(clang::SourceRange(Subscr->getBeginLoc(), Subscr->getEndLoc()), arrayVarNames[ArrName][i]); } std::string caseBody = Canvas.getRewrittenText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc())).str(); switchText += "case " + std::to_string(i) + ":\n" + caseBody + ";\nbreak;\n"; @@ -401,10 +462,12 @@ class ClangRemoveRedarrayVisitor return RecursiveASTVisitor::TraverseStmt(S); } auto Arr = cast(S); - auto [ArrName, ArrayStmt] = mSwaps[0]; - if (ArrName == Arr->getNameInfo().getName().getAsString()) { - mIsSubscriptUseful = true; - return true; + for (int i = 0; i < mDecls.size(); i++) { + auto [ArrName, ArrayStmt] = mDecls[i]; + if (ArrName == Arr->getNameInfo().getName().getAsString()) { + mIsSubscriptUseful = true; + return true; + } } return RecursiveASTVisitor::TraverseStmt(S); } @@ -417,7 +480,10 @@ class ClangRemoveRedarrayVisitor void resetVisitor() { mStatus = SEARCH_PRAGMA; mSwaps.clear(); + mDecls.clear(); + mSizes.clear(); mInductions.clear(); + arrayVarNames.clear(); } void clearArraySubscr() { @@ -451,6 +517,9 @@ class ClangRemoveRedarrayVisitor CHECK_SUBSCRIPT, } mStatus{SEARCH_PRAGMA}; SmallVector, 4> mSwaps; + std::vector> mDecls; + std::vector> mSizes; + std::map > arrayVarNames; std::vector mArraySubscriptExpr; bool mIsSubscriptUseful; clang::VarDecl* mIndex; @@ -461,37 +530,28 @@ class ClangRemoveRedarrayVisitor bool ClangRemoveRedarray::runOnFunction(Function &F) { - dbgs() << DEBUG_PREFIX << "launch runOnFunction remove_redarray\n"; - auto *DISub{findMetadata(&F)}; if (!DISub) return false; - dbgs() << DEBUG_PREFIX << "DISub initialized runOnFunction remove_redarray\n"; auto *CU{DISub->getUnit()}; if (!isC(CU->getSourceLanguage()) && !isCXX(CU->getSourceLanguage())) return false; - dbgs() << DEBUG_PREFIX << "getSourceLanguage runOnFunction remove_redarray\n"; auto &TfmInfo{getAnalysis()}; - dbgs() << DEBUG_PREFIX << "getAnalysis runOnFunction remove_redarray\n"; auto *TfmCtx{TfmInfo ? dyn_cast_or_null( TfmInfo->getContext(*CU)) : nullptr}; - dbgs() << DEBUG_PREFIX << "TfmInfo ClangTransformationContext runOnFunction remove_redarray\n"; if (!TfmCtx || !TfmCtx->hasInstance()) { F.getContext().emitError("can not transform sources" ": transformation context is not available"); return false; } - dbgs() << DEBUG_PREFIX << "TfmCtx runOnFunction remove_redarray\n"; auto *FD{TfmCtx->getDeclForMangledName(F.getName())}; if (!FD) return false; - dbgs() << DEBUG_PREFIX << "FD runOnFunction remove_redarray\n"; ASTImportInfo ImportStub; const auto *ImportInfo{&ImportStub}; if (auto *ImportPass = getAnalysisIfAvailable()) ImportInfo = &ImportPass->getImportInfo(); - dbgs() << DEBUG_PREFIX << "end of runOnFunction remove_redarray\n"; ClangRemoveRedarrayVisitor(*this, F, TfmCtx, *ImportInfo).TraverseDecl(FD); return false; } From 62d2bf8fb63211e6760652089b0b4173d0730b8b Mon Sep 17 00:00:00 2001 From: ArtherusAA Date: Tue, 24 May 2022 20:08:25 +0300 Subject: [PATCH 14/14] fix checks for remove-redarray --- lib/Transform/Clang/RemoveRedarray.cpp | 48 ++++++++++++++++++++------ 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/lib/Transform/Clang/RemoveRedarray.cpp b/lib/Transform/Clang/RemoveRedarray.cpp index 1867e509..5d9b3c91 100644 --- a/lib/Transform/Clang/RemoveRedarray.cpp +++ b/lib/Transform/Clang/RemoveRedarray.cpp @@ -330,6 +330,7 @@ class ClangRemoveRedarrayVisitor LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "number of arrays does not match number of their sizes\n"); return false; } + std::string variableDeclaration = ""; for (int i = 0; i < mDecls.size(); i++) { auto [ArrName, ArrayStmt] = mDecls[i]; auto [SizeLiteral, SizeStmt] = mSizes[i]; @@ -355,22 +356,31 @@ class ClangRemoveRedarrayVisitor ToInsert += (" " + newVarName + " = " + ArrName + "[" + std::to_string(i) + "]"); } ToInsert += (";\n"); - mRewriter.InsertTextBefore(S->getBeginLoc(), - ToInsert); // insert array variables - // definitions here + variableDeclaration += ToInsert; } mStatus = FIND_INDEX; auto Res = RecursiveASTVisitor::TraverseStmt(S); mStatus = FIND_OP; Res = RecursiveASTVisitor::TraverseStmt(S); - for (int i = 0; i < mDecls.size(); i++) { - auto [ArrName, ArrayStmt] = mDecls[i]; - auto [SizeLiteral, SizeStmt] = mSizes[i]; - std::string ToInsert = ""; - for (int i = 0; i < cast(SizeStmt)->getValue().getSExtValue(); i++) { - ToInsert += ArrName + "[" + std::to_string(i) + "] = " + arrayVarNames[ArrName][i] + ";\n"; + if (checksPassed) { + mRewriter.InsertTextBefore(S->getBeginLoc(), + variableDeclaration); // insert array variables + // definitions here + for (int i = 0; i < rangeToReplace.size(); i++) { + mRewriter.ReplaceText(rangeToReplace[i], textToReplace[i]); } - mRewriter.InsertTextAfterToken(S->getEndLoc(), ToInsert); + for (int i = 0; i < mDecls.size(); i++) { + auto [ArrName, ArrayStmt] = mDecls[i]; + auto [SizeLiteral, SizeStmt] = mSizes[i]; + std::string ToInsert = ""; + for (int i = 0; i < cast(SizeStmt)->getValue().getSExtValue(); i++) { + ToInsert += ArrName + "[" + std::to_string(i) + "] = " + arrayVarNames[ArrName][i] + ";\n"; + } + mRewriter.InsertTextAfterToken(S->getEndLoc(), ToInsert); + } + } + else { + return false; } return true; @@ -423,6 +433,7 @@ class ClangRemoveRedarrayVisitor } if (arrayJInPragma && array0InPragma) { LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "different arrays in operator are not yet supported\n"); + checksPassed = false; return false; } } @@ -440,7 +451,16 @@ class ClangRemoveRedarrayVisitor switchText += "case " + std::to_string(i) + ":\n" + caseBody + ";\nbreak;\n"; } switchText += "}"; - mRewriter.ReplaceText(clang::SourceRange(S->getBeginLoc(), S->getEndLoc()), switchText); + bool sourceRangeInArray = false; + for (auto range : rangeToReplace) { + if (range.fullyContains(S->getSourceRange())) { + sourceRangeInArray = true; + } + } + if (!sourceRangeInArray) { + rangeToReplace.push_back(S->getSourceRange()); + textToReplace.push_back(switchText); + } clearArraySubscr(); return RecursiveASTVisitor::TraverseStmt(S); } @@ -484,6 +504,9 @@ class ClangRemoveRedarrayVisitor mSizes.clear(); mInductions.clear(); arrayVarNames.clear(); + rangeToReplace.clear(); + textToReplace.clear(); + checksPassed = true; } void clearArraySubscr() { @@ -521,7 +544,10 @@ class ClangRemoveRedarrayVisitor std::vector> mSizes; std::map > arrayVarNames; std::vector mArraySubscriptExpr; + std::vector rangeToReplace; + std::vector textToReplace; bool mIsSubscriptUseful; + bool checksPassed = true; clang::VarDecl* mIndex; LoopNest mInductions;