Skip to content

Commit

Permalink
Add support for nowrap flags to trunc (#1024)
Browse files Browse the repository at this point in the history
  • Loading branch information
antoniofrighetto authored Mar 29, 2024
1 parent 2285557 commit 2fccad2
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 6 deletions.
31 changes: 29 additions & 2 deletions ir/instr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1507,6 +1507,21 @@ unique_ptr<Instr> TestOp::dup(Function &f, const string &suffix) const {
return make_unique<TestOp>(getType(), getName() + suffix, *lhs, *rhs, op);
}

ConversionOp::ConversionOp(Type &type, std::string &&name, Value &val, Op op,
unsigned flags)
: Instr(type, std::move(name)), val(&val), op(op), flags(flags) {
switch (op) {
case ZExt:
assert((flags & NNEG) == flags);
break;
case Trunc:
assert((flags & (NSW | NUW)) == flags);
break;
default:
assert(flags == 0);
break;
}
}

vector<Value*> ConversionOp::operands() const {
return { val };
Expand Down Expand Up @@ -1538,6 +1553,10 @@ void ConversionOp::print(ostream &os) const {
os << getName() << " = " << str;
if (flags & NNEG)
os << "nneg ";
if (flags & NSW)
os << "nsw ";
if (flags & NUW)
os << "nuw ";
os << *val << print_type(getType(), " to ", "");
}

Expand All @@ -1558,8 +1577,16 @@ StateValue ConversionOp::toSMT(State &s) const {
};
break;
case Trunc:
fn = [](auto &&val, auto &to_type) -> StateValue {
return {val.trunc(to_type.bits()), true};
fn = [this](auto &&val, auto &to_type) -> StateValue {
AndExpr non_poison;
unsigned orig_bits = val.bits();
unsigned trunc_bits = to_type.bits();
expr val_truncated = val.trunc(trunc_bits);
if (flags & NUW)
non_poison.add(val_truncated.zext(orig_bits - trunc_bits) == val);
if (flags & NSW)
non_poison.add(val_truncated.sext(orig_bits - trunc_bits) == val);
return {std::move(val_truncated), non_poison()};
};
break;
case BitCast:
Expand Down
5 changes: 2 additions & 3 deletions ir/instr.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ 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 };
enum Flags { None = 0, NNEG = 1 << 0, NSW = 1 << 1, NUW = 1 << 2 };

private:
Value *val;
Expand All @@ -268,8 +268,7 @@ class ConversionOp final : public Instr {

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

Op getOp() const { return op; }
Value& getValue() const { return *val; }
Expand Down
8 changes: 7 additions & 1 deletion llvm_util/llvm2alive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Operator.h"
#include "llvm/Support/ModRef.h"
#include <sstream>
Expand Down Expand Up @@ -308,6 +309,11 @@ class llvm2alive_ : public llvm::InstVisitor<llvm2alive_, unique_ptr<Instr>> {
if (const auto *NNI = dyn_cast<llvm::PossiblyNonNegInst>(&i)) {
if (NNI->hasNonNeg())
flags |= ConversionOp::NNEG;
} else if (const auto *TI = dyn_cast<llvm::TruncInst>(&i)) {
if (TI->hasNoUnsignedWrap())
flags |= ConversionOp::NUW;
if (TI->hasNoSignedWrap())
flags |= ConversionOp::NSW;
}
RETURN_IDENTIFIER(
make_unique<ConversionOp>(*ty, value_name(i), *val, op, flags));
Expand Down
9 changes: 9 additions & 0 deletions tests/alive-tv/nsw.trunc.srctgt.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
define i8 @src(i8 %x) {
%trunc = trunc nsw i8 %x to i1
%sext = sext i1 %trunc to i8
ret i8 %sext
}

define i8 @tgt(i8 %x) {
ret i8 %x
}
9 changes: 9 additions & 0 deletions tests/alive-tv/nuw.trunc.srctgt.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
define i8 @src(i8 %x) {
%trunc = trunc nuw i8 %x to i1
%zext = zext i1 %trunc to i8
ret i8 %zext
}

define i8 @tgt(i8 %x) {
ret i8 %x
}

0 comments on commit 2fccad2

Please sign in to comment.