CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
128 lines
4.8 KiB
C++
128 lines
4.8 KiB
C++
//===- MovedLoans.cpp - Moved Loans Analysis --------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the MovedLoansAnalysis, a forward dataflow analysis that
|
|
// tracks which loans have been moved out of their original storage location
|
|
// at each program point.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/Analysis/Analyses/LifetimeSafety/MovedLoans.h"
|
|
#include "Dataflow.h"
|
|
#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
|
|
#include "clang/Analysis/Analyses/LifetimeSafety/LiveOrigins.h"
|
|
#include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h"
|
|
#include "clang/Analysis/Analyses/LifetimeSafety/Loans.h"
|
|
#include "clang/Analysis/Analyses/LifetimeSafety/Utils.h"
|
|
|
|
namespace clang::lifetimes::internal {
|
|
namespace {
|
|
struct Lattice {
|
|
MovedLoansMap MovedLoans = MovedLoansMap(nullptr);
|
|
|
|
explicit Lattice(MovedLoansMap MovedLoans) : MovedLoans(MovedLoans) {}
|
|
|
|
Lattice() = default;
|
|
|
|
bool operator==(const Lattice &Other) const {
|
|
return MovedLoans == Other.MovedLoans;
|
|
}
|
|
bool operator!=(const Lattice &Other) const { return !(*this == Other); }
|
|
};
|
|
|
|
class AnalysisImpl
|
|
: public DataflowAnalysis<AnalysisImpl, Lattice, Direction::Forward> {
|
|
public:
|
|
AnalysisImpl(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
|
|
const LoanPropagationAnalysis &LoanPropagation,
|
|
const LiveOriginsAnalysis &LiveOrigins,
|
|
const LoanManager &LoanMgr,
|
|
MovedLoansMap::Factory &MovedLoansMapFactory)
|
|
: DataflowAnalysis(C, AC, F), LoanPropagation(LoanPropagation),
|
|
LiveOrigins(LiveOrigins), LoanMgr(LoanMgr),
|
|
MovedLoansMapFactory(MovedLoansMapFactory) {}
|
|
|
|
using Base::transfer;
|
|
|
|
StringRef getAnalysisName() const { return "MovedLoans"; }
|
|
|
|
Lattice getInitialState() { return Lattice{}; }
|
|
|
|
/// Merges moved loan state from different control flow paths. When a loan
|
|
/// is moved on multiple paths, picks the lexically earliest move expression.
|
|
Lattice join(Lattice A, Lattice B) {
|
|
MovedLoansMap MovedLoans = utils::join(
|
|
A.MovedLoans, B.MovedLoans, MovedLoansMapFactory,
|
|
[](const Expr *const *MoveA, const Expr *const *MoveB) -> const Expr * {
|
|
assert(MoveA || MoveB);
|
|
if (!MoveA)
|
|
return *MoveB;
|
|
if (!MoveB)
|
|
return *MoveA;
|
|
return (*MoveA)->getExprLoc() < (*MoveB)->getExprLoc() ? *MoveA
|
|
: *MoveB;
|
|
},
|
|
utils::JoinKind::Asymmetric);
|
|
return Lattice(MovedLoans);
|
|
}
|
|
|
|
/// Marks all live loans sharing the same access path as the moved origin as
|
|
/// potentially moved.
|
|
Lattice transfer(Lattice In, const MovedOriginFact &F) {
|
|
MovedLoansMap MovedLoans = In.MovedLoans;
|
|
OriginID MovedOrigin = F.getMovedOrigin();
|
|
LoanSet ImmediatelyMovedLoans = LoanPropagation.getLoans(MovedOrigin, &F);
|
|
auto IsInvalidated = [&](const AccessPath &Path) {
|
|
for (LoanID LID : ImmediatelyMovedLoans) {
|
|
const Loan *MovedLoan = LoanMgr.getLoan(LID);
|
|
if (MovedLoan->getAccessPath() == Path)
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
for (auto [O, _] : LiveOrigins.getLiveOriginsAt(&F))
|
|
for (LoanID LiveLoan : LoanPropagation.getLoans(O, &F)) {
|
|
const Loan *LiveLoanPtr = LoanMgr.getLoan(LiveLoan);
|
|
if (IsInvalidated(LiveLoanPtr->getAccessPath()))
|
|
MovedLoans =
|
|
MovedLoansMapFactory.add(MovedLoans, LiveLoan, F.getMoveExpr());
|
|
}
|
|
return Lattice(MovedLoans);
|
|
}
|
|
|
|
MovedLoansMap getMovedLoans(ProgramPoint P) { return getState(P).MovedLoans; }
|
|
|
|
private:
|
|
const LoanPropagationAnalysis &LoanPropagation;
|
|
const LiveOriginsAnalysis &LiveOrigins;
|
|
const LoanManager &LoanMgr;
|
|
MovedLoansMap::Factory &MovedLoansMapFactory;
|
|
};
|
|
} // namespace
|
|
|
|
class MovedLoansAnalysis::Impl final : public AnalysisImpl {
|
|
using AnalysisImpl::AnalysisImpl;
|
|
};
|
|
|
|
MovedLoansAnalysis::MovedLoansAnalysis(
|
|
const CFG &C, AnalysisDeclContext &AC, FactManager &F,
|
|
const LoanPropagationAnalysis &LoanPropagation,
|
|
const LiveOriginsAnalysis &LiveOrigins, const LoanManager &LoanMgr,
|
|
MovedLoansMap::Factory &MovedLoansMapFactory)
|
|
: PImpl(std::make_unique<Impl>(C, AC, F, LoanPropagation, LiveOrigins,
|
|
LoanMgr, MovedLoansMapFactory)) {
|
|
PImpl->run();
|
|
}
|
|
|
|
MovedLoansAnalysis::~MovedLoansAnalysis() = default;
|
|
|
|
MovedLoansMap MovedLoansAnalysis::getMovedLoans(ProgramPoint P) const {
|
|
return PImpl->getMovedLoans(P);
|
|
}
|
|
} // namespace clang::lifetimes::internal
|