don't register non-const AggregateValue as constant
MODIFY
ir/function.cpp
ir/function.cpp
@@ -129,6 +129,10 @@ void Function::addUndef(unique_ptr<UndefValue> &&u) {
undefs.emplace_back(move(u));
}
+void Function::addAggregate(unique_ptr<AggregateValue> &&a) {
+ aggregates.emplace_back(move(a));
+}
+
void Function::addInput(unique_ptr<Value> &&i) {
assert(dynamic_cast<Input *>(i.get()) ||
dynamic_cast<ConstantInput*>(i.get()));

MODIFY
ir/function.h
ir/function.h
@@ -62,6 +62,7 @@ class Function final {
std::vector<std::unique_ptr<Value>> constants;
std::vector<std::unique_ptr<Predicate>> predicates;
std::vector<std::unique_ptr<Value>> undefs;
+ std::vector<std::unique_ptr<AggregateValue>> aggregates;
std::vector<std::unique_ptr<Value>> inputs;
public:
@@ -99,6 +100,8 @@ public:
return undefs;
}
+ void addAggregate(std::unique_ptr<AggregateValue> &&a);
+
void addInput(std::unique_ptr<Value> &&c);
util::const_strip_unique_ptr<decltype(inputs)> getInputs() const {
return inputs;

MODIFY
ir/instr.cpp
ir/instr.cpp
@@ -579,8 +579,10 @@ StateValue UnaryOp::toSMT(State &s) const {
switch (op) {
case Copy:
- fn = [](auto v) { return v; };
- break;
+ if (dynamic_cast<AggregateValue *>(val))
+ // Aggregate value is not registered at state.
+ return val->toSMT(s);
+ return s[*val];
case BitReverse:
fn = [](auto v) { return v.bitreverse(); };
break;

MODIFY
llvm_util/known_fns.cpp
llvm_util/known_fns.cpp
@@ -21,14 +21,15 @@ namespace llvm_util {
pair<unique_ptr<Instr>, bool>
known_call(llvm::CallInst &i, const llvm::TargetLibraryInfo &TLI,
BasicBlock &BB,
- function<Value*(llvm::ConstantExpr *)> constexpr_conv) {
+ function<Value*(llvm::ConstantExpr *)> constexpr_conv,
+ function<Value*(AggregateValue *)> copy_inserter) {
auto ty = llvm_type2alive(i.getType());
if (!ty)
RETURN_FAIL_KNOWN();
vector<Value*> args;
for (auto &arg : i.args()) {
- auto a = get_operand(arg, constexpr_conv);
+ auto a = get_operand(arg, constexpr_conv, copy_inserter);
if (!a)
RETURN_FAIL_KNOWN();
args.emplace_back(a);

MODIFY
llvm_util/known_fns.h
llvm_util/known_fns.h
@@ -25,6 +25,7 @@ namespace llvm_util {
std::pair<std::unique_ptr<IR::Instr>, bool>
known_call(llvm::CallInst &i, const llvm::TargetLibraryInfo &TLI,
IR::BasicBlock &BB,
- std::function<IR::Value*(llvm::ConstantExpr *)> constexpr_conv);
+ std::function<IR::Value*(llvm::ConstantExpr *)> constexpr_conv,
+ std::function<IR::Value*(IR::AggregateValue *)> copy_inserter);
}

MODIFY
llvm_util/llvm2alive.cpp
llvm_util/llvm2alive.cpp
@@ -21,6 +21,7 @@ namespace {
ostream *out;
unsigned constexpr_idx;
+unsigned copy_idx;
#if 0
string_view s(llvm::StringRef str) {
@@ -93,9 +94,20 @@ class llvm2alive_ : public llvm::InstVisitor<llvm2alive_, unique_ptr<Instr>> {
return i;
}
+
+ Value* copy_inserter(AggregateValue *ag) {
+ auto v = make_unique<UnaryOp>(*const_cast<Type *>(&ag->getType()),
+ "%__copy_" + to_string(copy_idx++), *ag,
+ UnaryOp::Copy);
+ auto val = v.get();
+ BB->addInstr(move(v));
+ return val;
+ }
+
auto get_operand(llvm::Value *v) {
return llvm_util::get_operand(v,
- [this](auto I) { return convert_constexpr(I); });
+ [this](auto I) { return convert_constexpr(I); },
+ [&](auto ag) { return copy_inserter(ag); });
}
public:
@@ -206,7 +218,8 @@ public:
RetTy visitCallInst(llvm::CallInst &i) {
auto [call_val, known] = known_call(i, TLI, *BB,
- [this](auto I) { return convert_constexpr(I); });
+ [this](auto I) { return convert_constexpr(I); },
+ [this](auto ag) { return copy_inserter(ag); });
if (call_val)
RETURN_IDENTIFIER(move(call_val));
@@ -708,7 +721,7 @@ public:
char *end_ptr;
auto numeric_id = strtoul(chrs, &end_ptr, 10);
- if (end_ptr - chrs != name.size())
+ if ((unsigned)(end_ptr - chrs) != (unsigned)name.size())
return M->getGlobalVariable(name, true);
else {
auto itr = M->global_begin(), end = M->global_end();

MODIFY
llvm_util/utils.cpp
llvm_util/utils.cpp
@@ -189,7 +189,8 @@ Value* make_intconst(uint64_t val, int bits) {
Value* get_operand(llvm::Value *v,
- function<Value*(llvm::ConstantExpr*)> constexpr_conv) {
+ function<Value*(llvm::ConstantExpr*)> constexpr_conv,
+ function<Value*(AggregateValue*)> copy_inserter) {
if (isa<llvm::Instruction>(v) || isa<llvm::Argument>(v))
return identifiers[v];
@@ -282,7 +283,7 @@ Value* get_operand(llvm::Value *v,
return gvar;
}
- auto fillAggregateValues = [&constexpr_conv](AggregateType *aty,
+ auto fillAggregateValues = [&](AggregateType *aty,
function<llvm::Value *(unsigned)> get_elem, vector<Value*> &vals) -> bool
{
unsigned opi = 0;
@@ -297,7 +298,7 @@ Value* get_operand(llvm::Value *v,
current_fn->addConstant(move(poison));
vals.emplace_back(ret);
} else {
- if (auto op = get_operand(get_elem(opi), constexpr_conv))
+ if (auto op = get_operand(get_elem(opi), constexpr_conv, copy_inserter))
vals.emplace_back(op);
else
return false;
@@ -315,8 +316,15 @@ Value* get_operand(llvm::Value *v,
auto val = make_unique<AggregateValue>(*ty, move(vals));
auto ret = val.get();
+ if (all_of(cnst->op_begin(), cnst->op_end(), [](auto &V) -> bool
+ { return llvm::isa<llvm::UndefValue>(V) ||
+ llvm::isa<llvm::ConstantInt>(V); })) {
current_fn->addConstant(move(val));
return ret;
+ } else {
+ current_fn->addAggregate(move(val));
+ return copy_inserter(ret);
+ }
}
if (auto cnst = dyn_cast<llvm::ConstantDataSequential>(v)) {

MODIFY
llvm_util/utils.h
llvm_util/utils.h
@@ -16,6 +16,7 @@ class Value;
}
namespace IR {
+class AggregateValue;
class BasicBlock;
class Function;
class Type;
@@ -34,7 +35,8 @@ IR::Type* llvm_type2alive(const llvm::Type *ty);
IR::Value* make_intconst(uint64_t val, int bits);
IR::Value* get_operand(llvm::Value *v,
- std::function<IR::Value*(llvm::ConstantExpr *)> constexpr_conv);
+ std::function<IR::Value*(llvm::ConstantExpr *)> constexpr_conv,
+ std::function<IR::Value*(IR::AggregateValue *)> copy_inserter);
void add_identifier(const llvm::Value &llvm, IR::Value &v);

ADD
tests/alive-tv/constexpr/aggregate3.src.ll
+@a = constant i32 0
+@x = constant { i8*, i8* } { i8* bitcast (i32* @a to i8*), i8* bitcast (i32* @a to i8*) }
+@y = constant { i64, i64 } { i64 sub (i64 ptrtoint (i32* @a to i64), i64 1), i64 0 }
+
+ define i64 @f() {
+ %a = load { i8*, i8* }, { i8*, i8* }* @x
+ %z = load { i64, i64 }, { i64, i64 }* @y
+ %b = extractvalue {i64, i64} %z, 0
+ ret i64 %b
+ }

ADD
tests/alive-tv/constexpr/aggregate3.tgt.ll
+@a = constant i32 0
+@x = constant { i8*, i8* } { i8* bitcast (i32* @a to i8*), i8* bitcast (i32* @a to i8*) }
+@y = constant { i64, i64 } { i64 sub (i64 ptrtoint (i32* @a to i64), i64 1), i64 0 }
+
+ define i64 @f() {
+ %a = load { i8*, i8* }, { i8*, i8* }* @x
+ %z = load { i64, i64 }, { i64, i64 }* @y
+ ret i64 sub (i64 ptrtoint (i32* @a to i64), i64 1)
+ }

ADD
tests/alive-tv/constexpr/ret.src.ll
+define <2 x i32> @f() {
+ ret <2 x i32> <i32 0, i32 1>
+}

ADD
tests/alive-tv/constexpr/ret.tgt.ll
+define <2 x i32> @f() {
+ ret <2 x i32> <i32 0, i32 1>
+}

ADD
tests/alive-tv/constexpr/shufflevector-nocopy.src.ll
+; Check whether this example does not cause crash
+define <4 x i32> @f(<4 x i32> %x, <4 x i32> %y) {
+ %z = shufflevector <4 x i32> %x, <4 x i32> %y, <4 x i32> <i32 0, i32 1, i32 undef, i32 3>
+ ret <4 x i32> %z
+}
+

ADD
tests/alive-tv/constexpr/shufflevector-nocopy.tgt.ll
+define <4 x i32> @f(<4 x i32> %x, <4 x i32> %y) {
+ %z = shufflevector <4 x i32> %x, <4 x i32> %y, <4 x i32> <i32 0, i32 1, i32 undef, i32 3>
+ ret <4 x i32> %z
+}
+

don't register non-const AggregateValue as constant (#219)