Skip to content

Commit e670cc2

Browse files
committed
Use LatticeDomain<int64_t> instead of int64_t in IDE-LCA
1 parent 59e1ea6 commit e670cc2

5 files changed

Lines changed: 85 additions & 84 deletions

File tree

include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "phasar/PhasarLLVM/DataFlowSolver/IfdsIde/EdgeFunctionComposer.h"
2020
#include "phasar/PhasarLLVM/DataFlowSolver/IfdsIde/IDETabulationProblem.h"
2121
#include "phasar/PhasarLLVM/Domain/AnalysisDomain.h"
22+
#include "phasar/PhasarLLVM/Utils/LatticeDomain.h"
2223

2324
namespace llvm {
2425
class Instruction;
@@ -31,7 +32,7 @@ namespace psr {
3132

3233
struct IDELinearConstantAnalysisDomain : public LLVMAnalysisDomainDefault {
3334
// int64_t corresponds to llvm's type of constant integer
34-
using l_t = int64_t;
35+
using l_t = LatticeDomain<int64_t>;
3536
};
3637

3738
class LLVMBasedICFG;
@@ -176,10 +177,10 @@ class IDELinearConstantAnalysis
176177
public std::enable_shared_from_this<GenConstant> {
177178
private:
178179
const unsigned GenConstantId;
179-
const l_t IntConst;
180+
const int64_t IntConst;
180181

181182
public:
182-
explicit GenConstant(l_t IntConst);
183+
explicit GenConstant(int64_t IntConst);
183184

184185
l_t computeTarget(l_t Source) override;
185186

@@ -253,7 +254,7 @@ class IDELinearConstantAnalysis
253254
* @param rop right operand
254255
* @return Result of binary operation
255256
*/
256-
static l_t executeBinOperation(unsigned Op, l_t Lop, l_t Rop);
257+
static l_t executeBinOperation(unsigned Op, l_t LVal, l_t RVal);
257258

258259
static char opToChar(unsigned Op);
259260

include/phasar/PhasarLLVM/Utils/LatticeDomain.h

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/Support/ErrorHandling.h"
1414

1515
#include <iostream>
16+
#include <type_traits>
1617
#include <variant>
1718

1819
namespace psr {
@@ -22,8 +23,7 @@ namespace psr {
2223
/// the lattice.
2324
struct Top {};
2425

25-
static inline std::ostream &operator<<(std::ostream &OS,
26-
[[maybe_unused]] const Top &T) {
26+
static inline std::ostream &operator<<(std::ostream &OS, Top /*unused*/) {
2727
return OS << "Top";
2828
}
2929

@@ -32,8 +32,7 @@ static inline std::ostream &operator<<(std::ostream &OS,
3232
/// of the lattice.
3333
struct Bottom {};
3434

35-
static inline std::ostream &operator<<(std::ostream &OS,
36-
[[maybe_unused]] const Bottom &B) {
35+
static inline std::ostream &operator<<(std::ostream &OS, Bottom /*unused*/) {
3736
return OS << "Bottom";
3837
}
3938

@@ -42,33 +41,43 @@ template <typename L> using LatticeDomain = std::variant<L, Top, Bottom>;
4241

4342
template <typename L>
4443
inline std::ostream &operator<<(std::ostream &OS, const LatticeDomain<L> &LD) {
45-
if (auto T = std::get_if<Top>(&LD)) {
46-
return OS << *T;
47-
}
48-
if (auto B = std::get_if<Bottom>(&LD)) {
49-
return OS << *B;
50-
}
51-
return OS << std::get<L>(LD);
44+
std::visit([&OS](const auto &LVal) { OS << LVal; }, LD);
45+
return OS;
5246
}
5347

5448
template <typename L>
5549
inline bool operator==(const LatticeDomain<L> &Lhs,
5650
const LatticeDomain<L> &Rhs) {
57-
if (std::holds_alternative<Top>(Lhs) && std::holds_alternative<Top>(Rhs)) {
58-
return true;
59-
}
60-
if (std::holds_alternative<Bottom>(Lhs) &&
61-
std::holds_alternative<Bottom>(Rhs)) {
62-
return true;
51+
if (Lhs.index() != Rhs.index()) {
52+
return false;
6353
}
54+
6455
if (auto LhsPtr = std::get_if<L>(&Lhs)) {
6556
if (auto RhsPtr = std::get_if<L>(&Rhs)) {
6657
return *LhsPtr == *RhsPtr;
6758
}
6859
}
60+
61+
return true;
62+
}
63+
64+
template <
65+
typename L, typename LL,
66+
typename = std::void_t<decltype(std::declval<LL>() == std::declval<L>())>>
67+
inline bool operator==(const LL &Lhs, const LatticeDomain<L> Rhs) {
68+
if (const auto *RVal = std::get_if<L>(&Rhs)) {
69+
return Lhs == *RVal;
70+
}
6971
return false;
7072
}
7173

74+
template <
75+
typename L, typename LL,
76+
typename = std::void_t<decltype(std::declval<LL>() == std::declval<L>())>>
77+
inline bool operator==(const LatticeDomain<L> Lhs, const LL &Rhs) {
78+
return Rhs == Lhs;
79+
}
80+
7281
template <typename L>
7382
inline bool operator!=(const LatticeDomain<L> &Lhs,
7483
const LatticeDomain<L> &Rhs) {

lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp

Lines changed: 50 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,10 @@ unsigned IDELinearConstantAnalysis::CurrGenConstantId = 0; // NOLINT
4545
unsigned IDELinearConstantAnalysis::CurrLCAIDId = 0; // NOLINT
4646
unsigned IDELinearConstantAnalysis::CurrBinaryId = 0; // NOLINT
4747

48-
const IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::TOP =
49-
std::numeric_limits<IDELinearConstantAnalysis::l_t>::min();
48+
const IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::TOP = Top{};
5049

5150
const IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::BOTTOM =
52-
std::numeric_limits<IDELinearConstantAnalysis::l_t>::max();
51+
Bottom{};
5352

5453
IDELinearConstantAnalysis::IDELinearConstantAnalysis(
5554
const ProjectIRDB *IRDB, const LLVMTypeHierarchy *TH,
@@ -470,8 +469,7 @@ IDELinearConstantAnalysis::LCAEdgeFunctionComposer::joinWith(
470469
return std::make_shared<AllBottom<l_t>>(BOTTOM);
471470
}
472471

473-
IDELinearConstantAnalysis::GenConstant::GenConstant(
474-
IDELinearConstantAnalysis::l_t IntConst)
472+
IDELinearConstantAnalysis::GenConstant::GenConstant(int64_t IntConst)
475473
: GenConstantId(++CurrGenConstantId), IntConst(IntConst) {}
476474

477475
IDELinearConstantAnalysis::l_t
@@ -502,7 +500,7 @@ IDELinearConstantAnalysis::GenConstant::composeWith(
502500
return std::make_shared<AllBottom<l_t>>(BOTTOM);
503501
}
504502

505-
return std::make_shared<GenConstant>(Res);
503+
return std::make_shared<GenConstant>(std::get<int64_t>(Res));
506504
}
507505

508506
std::shared_ptr<EdgeFunction<IDELinearConstantAnalysis::l_t>>
@@ -583,11 +581,6 @@ IDELinearConstantAnalysis::BinOp::computeTarget(l_t Source) {
583581
<< "Curr Node : " << llvmIRToString(CurrNode));
584582
LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' ');
585583

586-
llvm::errs() << "BinOp::computeTarget(" << Source << ") with Op: " << Op
587-
<< ", Lop: " << llvmIRToShortString(Lop)
588-
<< ", Rop: " << llvmIRToShortString(Rop)
589-
<< ", at CurrNode: " << llvmIRToString(CurrNode) << '\n';
590-
591584
if (LLVMZeroValue::isLLVMZeroValue(CurrNode) &&
592585
llvm::isa<llvm::ConstantInt>(Lop) && llvm::isa<llvm::ConstantInt>(Rop)) {
593586
const auto *Lic = llvm::cast<llvm::ConstantInt>(Lop);
@@ -667,30 +660,28 @@ void IDELinearConstantAnalysis::BinOp::print(std::ostream &OS,
667660
}
668661

669662
char IDELinearConstantAnalysis::opToChar(const unsigned Op) {
670-
char OpAsChar;
671663
switch (Op) {
672664
case llvm::Instruction::Add:
673-
OpAsChar = '+';
674-
break;
665+
return '+';
675666
case llvm::Instruction::Sub:
676-
OpAsChar = '-';
677-
break;
667+
return '-';
678668
case llvm::Instruction::Mul:
679-
OpAsChar = '*';
680-
break;
669+
return '*';
681670
case llvm::Instruction::UDiv:
682671
case llvm::Instruction::SDiv:
683-
OpAsChar = '/';
684-
break;
672+
return '/';
685673
case llvm::Instruction::URem:
686674
case llvm::Instruction::SRem:
687-
OpAsChar = '%';
688-
break;
675+
return '%';
676+
case llvm::Instruction::And:
677+
return '&';
678+
case llvm::Instruction::Or:
679+
return '|';
680+
case llvm::Instruction::Xor:
681+
return '^';
689682
default:
690-
OpAsChar = ' ';
691-
break;
683+
return ' ';
692684
}
693-
return OpAsChar;
694685
}
695686

696687
bool IDELinearConstantAnalysis::isEntryPoint(
@@ -699,66 +690,72 @@ bool IDELinearConstantAnalysis::isEntryPoint(
699690
}
700691

701692
IDELinearConstantAnalysis::l_t
702-
IDELinearConstantAnalysis::executeBinOperation(const unsigned Op, l_t Lop,
703-
l_t Rop) {
693+
IDELinearConstantAnalysis::executeBinOperation(const unsigned Op, l_t LVal,
694+
l_t RVal) {
695+
696+
auto *LopPtr = std::get_if<int64_t>(&LVal);
697+
auto *RopPtr = std::get_if<int64_t>(&RVal);
704698

705-
if (Lop == BOTTOM || Rop == BOTTOM) {
699+
if (!LopPtr || !RopPtr) {
706700
return BOTTOM;
707701
}
708702

703+
auto Lop = *LopPtr;
704+
auto Rop = *RopPtr;
705+
709706
// default initialize with BOTTOM (all information)
710-
l_t Res = BOTTOM;
707+
int64_t Res;
711708
switch (Op) {
712709
case llvm::Instruction::Add:
713710
if (llvm::AddOverflow(Lop, Rop, Res)) {
714-
Res = BOTTOM;
711+
return BOTTOM;
715712
}
716-
break;
713+
return Res;
717714

718715
case llvm::Instruction::Sub:
719716
if (llvm::SubOverflow(Lop, Rop, Res)) {
720-
Res = BOTTOM;
717+
return BOTTOM;
721718
}
722-
break;
719+
return Res;
723720

724721
case llvm::Instruction::Mul:
725722
if (llvm::MulOverflow(Lop, Rop, Res)) {
726-
Res = BOTTOM;
723+
return BOTTOM;
727724
}
728-
break;
725+
return Res;
729726

730727
case llvm::Instruction::UDiv:
731728
case llvm::Instruction::SDiv:
732-
/// MIN is TOP, so already handled
733-
734-
// if (Lop == std::numeric_limits<IDELinearConstantAnalysis::l_t>::min() &&
735-
// Rop == -1) { // Would produce and overflow, as the complement of min
736-
// is
737-
// // not representable in a signed type.
738-
// return BOTTOM;
739-
// }
740-
if (Rop == 0) { // Division by zero is UB, so we return TOP
729+
if (Lop == std::numeric_limits<int64_t>::min() &&
730+
Rop == -1) { // Would produce and overflow, as the complement of min is
731+
// not representable in a signed type.
732+
return TOP;
733+
}
734+
if (Rop == 0) { // Division by zero is UB, so we return Bot
741735
return BOTTOM;
742736
}
743-
Res = Lop / Rop;
744-
break;
737+
return Lop / Rop;
745738

746739
case llvm::Instruction::URem:
747740
case llvm::Instruction::SRem:
748-
if (Rop == 0) { // Division by zero is UB, so we return TOP
741+
if (Rop == 0) { // Division by zero is UB, so we return Bot
749742
return BOTTOM;
750743
}
751-
Res = Lop % Rop;
752-
break;
753-
744+
return Lop % Rop;
745+
746+
case llvm::Instruction::And:
747+
return Lop & Rop;
748+
case llvm::Instruction::Or:
749+
return Lop | Rop;
750+
case llvm::Instruction::Xor:
751+
return Lop ^ Rop;
754752
default:
755753
LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG)
756754
<< "Operation not supported by "
757755
"IDELinearConstantAnalysis::"
758756
"executeBinOperation()");
759-
break;
757+
return BOTTOM;
760758
}
761-
return Res;
762759
}
763760

764761
void IDELinearConstantAnalysis::printNode(std::ostream &OS, n_t Stmt) const {
@@ -776,13 +773,7 @@ void IDELinearConstantAnalysis::printFunction(std::ostream &OS,
776773
}
777774

778775
void IDELinearConstantAnalysis::printEdgeFact(std::ostream &OS, l_t L) const {
779-
if (L == BOTTOM) {
780-
OS << "Bottom";
781-
} else if (L == TOP) {
782-
OS << "Top";
783-
} else {
784-
OS << L;
785-
}
776+
OS << L;
786777
}
787778

788779
void IDELinearConstantAnalysis::emitTextReport(

unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ class IDELinearConstantAnalysisTest : public ::testing::Test {
2323
unittest::PathToLLTestFiles + "linear_constant/";
2424

2525
// Function - Line Nr - Variable - Value
26-
using LCACompactResult_t =
27-
std::tuple<std::string, std::size_t, std::string, int64_t>;
26+
using LCACompactResult_t = std::tuple<std::string, std::size_t, std::string,
27+
IDELinearConstantAnalysisDomain::l_t>;
2828
std::unique_ptr<ProjectIRDB> IRDB;
2929

3030
void SetUp() override { boost::log::core::get()->set_logging_enabled(false); }

unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ class IDELinearConstantAnalysisTest : public ::testing::Test {
2424
const std::set<std::string> EntryPoints = {"main"};
2525

2626
// Function - Line Nr - Variable - Value
27-
using LCACompactResult_t =
28-
std::tuple<std::string, std::size_t, std::string, int64_t>;
27+
using LCACompactResult_t = std::tuple<std::string, std::size_t, std::string,
28+
IDELinearConstantAnalysisDomain::l_t>;
2929
std::unique_ptr<ProjectIRDB> IRDB;
3030

3131
void SetUp() override { boost::log::core::get()->set_logging_enabled(false); }

0 commit comments

Comments
 (0)