Skip to content

Commit

Permalink
add support for nneg
Browse files Browse the repository at this point in the history
  • Loading branch information
nunoplopes committed Oct 30, 2023
1 parent 013f7aa commit b66d170
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 33 deletions.
57 changes: 31 additions & 26 deletions ir/instr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1534,51 +1534,57 @@ void ConversionOp::print(ostream &os) const {
case Int2Ptr: str = "int2ptr "; break;
}

os << getName() << " = " << str << *val << print_type(getType(), " to ", "");
os << getName() << " = " << str;
if (flags & NNEG)
os << "nneg ";
os << *val << print_type(getType(), " to ", "");
}

StateValue ConversionOp::toSMT(State &s) const {
auto v = s[*val];
function<expr(expr &&, const Type &)> fn;
function<StateValue(expr &&, const Type &)> fn;

switch (op) {
case SExt:
fn = [](auto &&val, auto &to_type) -> expr {
return val.sext(to_type.bits() - val.bits());
fn = [](auto &&val, auto &to_type) -> StateValue {
return {val.sext(to_type.bits() - val.bits()), true};
};
break;
case ZExt:
fn = [](auto &&val, auto &to_type) -> expr {
return val.zext(to_type.bits() - val.bits());
fn = [&](auto &&val, auto &to_type) -> StateValue {
return { val.zext(to_type.bits() - val.bits()),
(flags & NNEG) ? !val.isNegative() : true };
};
break;
case Trunc:
fn = [](auto &&val, auto &to_type) -> expr {
return val.trunc(to_type.bits());
fn = [](auto &&val, auto &to_type) -> StateValue {
return {val.trunc(to_type.bits()), true};
};
break;
case BitCast:
break;
// NOP: ptr vect -> ptr vect
if (getType().isVectorType() &&
getType().getAsAggregateType()->getChild(0).isPtrType())
return v;

return getType().fromInt(val->getType().toInt(s, std::move(v)));

case Ptr2Int:
fn = [&](auto &&val, auto &to_type) -> expr {
return s.getMemory().ptr2int(val).zextOrTrunc(to_type.bits());
fn = [&](auto &&val, auto &to_type) -> StateValue {
return {s.getMemory().ptr2int(val).zextOrTrunc(to_type.bits()), true};
};
break;
case Int2Ptr:
fn = [&](auto &&val, auto &to_type) -> expr {
return s.getMemory().int2ptr(val);
fn = [&](auto &&val, auto &to_type) -> StateValue {
return {s.getMemory().int2ptr(val), true};
};
break;
}

if (op == BitCast) {
// NOP: ptr vect -> ptr vect
if (getType().isVectorType() &&
getType().getAsAggregateType()->getChild(0).isPtrType())
return v;

return getType().fromInt(val->getType().toInt(s, std::move(v)));
}
auto scalar = [&](StateValue &&v, const Type &to_type) -> StateValue {
auto [v2, np] = fn(std::move(v.value), to_type);
return { std::move(v2), v.non_poison && np };
};

if (getType().isVectorType()) {
vector<StateValue> vals;
Expand All @@ -1587,14 +1593,12 @@ StateValue ConversionOp::toSMT(State &s) const {
auto valty = val->getType().getAsAggregateType();

for (unsigned i = 0; i != elems; ++i) {
auto vi = valty->extract(v, i);
vals.emplace_back(fn(std::move(vi.value), retty->getChild(i)),
std::move(vi.non_poison));
vals.emplace_back(scalar(valty->extract(v, i), retty->getChild(i)));
}
return retty->aggregateVals(vals);
}

return { fn(std::move(v.value), getType()), std::move(v.non_poison) };
return scalar(std::move(v), getType());
}

expr ConversionOp::getTypeConstraints(const Function &f) const {
Expand Down Expand Up @@ -1635,7 +1639,8 @@ expr ConversionOp::getTypeConstraints(const Function &f) const {
}

unique_ptr<Instr> ConversionOp::dup(Function &f, const string &suffix) const {
return make_unique<ConversionOp>(getType(), getName() + suffix, *val, op);
return
make_unique<ConversionOp>(getType(), getName() + suffix, *val, op, flags);
}


Expand Down
7 changes: 5 additions & 2 deletions ir/instr.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,17 @@ class TestOp final : public Instr {
class ConversionOp final : public Instr {
public:
enum Op { SExt, ZExt, Trunc, BitCast, Ptr2Int, Int2Ptr };
enum Flags { None = 0, NNEG = 1 << 0 };

private:
Value *val;
Op op;
unsigned flags;

public:
ConversionOp(Type &type, std::string &&name, Value &val, Op op)
: Instr(type, std::move(name)), val(&val), op(op) {}
ConversionOp(Type &type, std::string &&name, Value &val, Op op,
unsigned flags = None)
: Instr(type, std::move(name)), val(&val), op(op), flags(flags) {}

Op getOp() const { return op; }
Value& getValue() const { return *val; }
Expand Down
10 changes: 8 additions & 2 deletions llvm_util/llvm2alive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,15 @@ class llvm2alive_ : public llvm::InstVisitor<llvm2alive_, unique_ptr<Instr>> {
case llvm::Instruction::IntToPtr: op = ConversionOp::Int2Ptr; break;
default: has_non_fp = false; break;
}
if (has_non_fp)
if (has_non_fp) {
unsigned flags = 0;
if (const auto *NNI = dyn_cast<llvm::PossiblyNonNegInst>(&i)) {
if (NNI->hasNonNeg())
flags |= ConversionOp::NNEG;
}
RETURN_IDENTIFIER(
make_unique<ConversionOp>(*ty, value_name(i), *val, op));
make_unique<ConversionOp>(*ty, value_name(i), *val, op, flags));
}
}

FpConversionOp::Op op;
Expand Down
4 changes: 1 addition & 3 deletions smt/expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,7 @@ bool expr::isSMax() const {
}

expr expr::isNegative() const {
C();
auto bit = bits() - 1;
return extract(bit, bit) == 1;
return sign() == 1;
}

unsigned expr::bits() const {
Expand Down
9 changes: 9 additions & 0 deletions tests/alive-tv/nneg.srctgt.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
define i16 @src(i8 %x) {
%r = zext nneg i8 %x to i16
ret i16 %r
}

define i16 @tgt(i8 %x) {
%r = sext i8 %x to i16
ret i16 %r
}

0 comments on commit b66d170

Please sign in to comment.