Skip to content

Commit faf59b5

Browse files
authored
Add support for samesign flag (#1098)
1 parent 3127683 commit faf59b5

File tree

4 files changed

+43
-16
lines changed

4 files changed

+43
-16
lines changed

ir/instr.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "smt/expr.h"
99
#include "smt/exprs.h"
1010
#include "smt/solver.h"
11+
#include "state_value.h"
1112
#include "util/compiler.h"
1213
#include "util/config.h"
1314
#include <algorithm>
@@ -2635,8 +2636,11 @@ InlineAsm::InlineAsm(Type &type, string &&name, const string &asm_str,
26352636
std::move(attrs)) {}
26362637

26372638

2638-
ICmp::ICmp(Type &type, string &&name, Cond cond, Value &a, Value &b)
2639-
: Instr(type, std::move(name)), a(&a), b(&b), cond(cond), defined(cond != Any) {
2639+
ICmp::ICmp(Type &type, string &&name, Cond cond, Value &a, Value &b,
2640+
unsigned flags)
2641+
: Instr(type, std::move(name)), a(&a), b(&b), cond(cond), flags(flags),
2642+
defined(cond != Any) {
2643+
assert((flags & SameSign) == flags);
26402644
if (!defined)
26412645
cond_name = getName() + "_cond";
26422646
}
@@ -2684,34 +2688,36 @@ void ICmp::print(ostream &os) const {
26842688
case UGT: condtxt = "ugt "; break;
26852689
case Any: condtxt = ""; break;
26862690
}
2687-
os << getName() << " = icmp " << condtxt << *a << ", " << b->getName();
2691+
os << getName() << " = icmp ";
2692+
if (flags & SameSign)
2693+
os << "samesign ";
2694+
os << condtxt << *a << ", " << b->getName();
26882695
switch (pcmode) {
26892696
case INTEGRAL: break;
26902697
case PROVENANCE: os << ", use_provenance"; break;
26912698
case OFFSETONLY: os << ", offsetonly"; break;
26922699
}
26932700
}
26942701

2695-
static expr build_icmp_chain(const expr &var,
2696-
const function<expr(ICmp::Cond)> &fn,
2697-
ICmp::Cond cond = ICmp::Any,
2698-
expr last = expr()) {
2702+
static StateValue build_icmp_chain(const expr &var,
2703+
const function<StateValue(ICmp::Cond)> &fn,
2704+
ICmp::Cond cond = ICmp::Any,
2705+
StateValue last = StateValue()) {
26992706
auto old_cond = cond;
27002707
cond = ICmp::Cond(cond - 1);
27012708

27022709
if (old_cond == ICmp::Any)
27032710
return build_icmp_chain(var, fn, cond, fn(cond));
27042711

2705-
auto e = expr::mkIf(var == cond, fn(cond), last);
2712+
auto e = StateValue::mkIf(var == cond, fn(cond), last);
27062713
return cond == 0 ? e : build_icmp_chain(var, fn, cond, std::move(e));
27072714
}
27082715

27092716
StateValue ICmp::toSMT(State &s) const {
27102717
auto &a_eval = s[*a];
27112718
auto &b_eval = s[*b];
27122719

2713-
function<expr(const expr&, const expr&, Cond)> fn =
2714-
[&](auto &av, auto &bv, Cond cond) {
2720+
auto cmp = [](const expr &av, const expr &bv, Cond cond) {
27152721
switch (cond) {
27162722
case EQ: return av == bv;
27172723
case NE: return av != bv;
@@ -2729,8 +2735,15 @@ StateValue ICmp::toSMT(State &s) const {
27292735
UNREACHABLE();
27302736
};
27312737

2738+
function<StateValue(const expr &, const expr &, Cond)> fn =
2739+
[&](auto &av, auto &bv, Cond cond) -> StateValue {
2740+
return {cmp(av, bv, cond),
2741+
flags & SameSign ? av.sign() == bv.sign() : expr(true)};
2742+
};
2743+
27322744
if (isPtrCmp()) {
2733-
fn = [this, &s, fn](const expr &av, const expr &bv, Cond cond) {
2745+
fn = [this, &s, fn](const expr &av, const expr &bv,
2746+
Cond cond) -> StateValue {
27342747
auto &m = s.getMemory();
27352748
Pointer lhs(m, av);
27362749
Pointer rhs(m, bv);
@@ -2742,7 +2755,7 @@ StateValue ICmp::toSMT(State &s) const {
27422755
return fn(lhs.getAddress(), rhs.getAddress(), cond);
27432756
case PROVENANCE:
27442757
assert(cond == EQ || cond == NE);
2745-
return cond == EQ ? lhs == rhs : lhs != rhs;
2758+
return {cond == EQ ? lhs == rhs : lhs != rhs, true};
27462759
case OFFSETONLY:
27472760
return fn(lhs.getOffset(), rhs.getOffset(), cond);
27482761
}
@@ -2753,7 +2766,8 @@ StateValue ICmp::toSMT(State &s) const {
27532766
auto scalar = [&](const StateValue &a, const StateValue &b) -> StateValue {
27542767
auto fn2 = [&](Cond c) { return fn(a.value, b.value, c); };
27552768
auto v = cond != Any ? fn2(cond) : build_icmp_chain(cond_var(), fn2);
2756-
return { v.toBVBool(), a.non_poison && b.non_poison };
2769+
return {v.value.toBVBool(),
2770+
a.non_poison && b.non_poison && std::move(v.non_poison)};
27572771
};
27582772

27592773
auto &elem_ty = a->getType();
@@ -2777,7 +2791,7 @@ expr ICmp::getTypeConstraints(const Function &f) const {
27772791
}
27782792

27792793
unique_ptr<Instr> ICmp::dup(Function &f, const string &suffix) const {
2780-
return make_unique<ICmp>(getType(), getName() + suffix, cond, *a, *b);
2794+
return make_unique<ICmp>(getType(), getName() + suffix, cond, *a, *b, flags);
27812795
}
27822796

27832797

ir/instr.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,17 +418,20 @@ class ICmp final : public Instr {
418418
PROVENANCE, // compare pointer provenance & offsets
419419
OFFSETONLY // cmp ofs only. meaningful only when ptrs are based on same obj
420420
};
421+
enum Flags { None = 0, SameSign = 1 << 0 };
421422

422423
private:
423424
Value *a, *b;
424425
std::string cond_name;
425426
Cond cond;
427+
unsigned flags;
426428
bool defined;
427429
PtrCmpMode pcmode = INTEGRAL;
428430
smt::expr cond_var() const;
429431

430432
public:
431-
ICmp(Type &type, std::string &&name, Cond cond, Value &a, Value &b);
433+
ICmp(Type &type, std::string &&name, Cond cond, Value &a, Value &b,
434+
unsigned flags = None);
432435

433436
bool isPtrCmp() const;
434437
PtrCmpMode getPtrCmpMode() const { return pcmode; }

llvm_util/llvm2alive.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,8 @@ class llvm2alive_ : public llvm::InstVisitor<llvm2alive_, unique_ptr<Instr>> {
507507
default:
508508
UNREACHABLE();
509509
}
510-
return make_unique<ICmp>(*ty, value_name(i), cond, *a, *b);
510+
return make_unique<ICmp>(*ty, value_name(i), cond, *a, *b,
511+
i.hasSameSign() ? ICmp::SameSign : ICmp::None);
511512
}
512513

513514
RetTy visitFCmpInst(llvm::FCmpInst &i) {

tests/alive-tv/samesign.srctgt.ll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
define i1 @src(i8 %x, i8 %y) {
2+
%cmp = icmp samesign slt i8 %x, %y
3+
ret i1 %cmp
4+
}
5+
6+
define i1 @tgt(i8 %x, i8 %y) {
7+
%cmp = icmp samesign ult i8 %x, %y
8+
ret i1 %cmp
9+
}

0 commit comments

Comments
 (0)