memory: also consider load/store/memcpy/memset for offset bitwidth computation
MODIFY
ir/instr.h
ir/instr.h
@@ -127,7 +127,7 @@ public:
: Instr(type, std::move(name)), val(&val), op(op) {}
Op getOp() const { return op; }
- Value* getValue() const { return val; }
+ Value& getValue() const { return *val; }
std::vector<Value*> operands() const override;
void rauw(const Value &what, Value &with) override;
void print(std::ostream &os) const override;
@@ -426,8 +426,6 @@ public:
StateValue toSMT(State &s) const override;
smt::expr getTypeConstraints(const Function &f) const override;
std::unique_ptr<Instr> dup(const std::string &suffix) const override;
- Value *getNum() const { return num; }
- Value *getSize() const { return size; }
};
@@ -471,7 +469,7 @@ public:
: Instr(type, std::move(name)), ptr(&ptr), inbounds(inbounds) {}
void addIdx(unsigned obj_size, Value &idx);
- Value* getPtr() const { return ptr; }
+ Value& getPtr() const { return *ptr; }
auto& getIdxs() const { return idxs; }
std::vector<Value*> operands() const override;
@@ -490,7 +488,7 @@ public:
Load(Type &type, std::string &&name, Value &ptr, unsigned align)
: Instr(type, std::move(name)), ptr(&ptr), align(align) {}
- Value* getPtr() const { return ptr; }
+ Value& getPtr() const { return *ptr; }
std::vector<Value*> operands() const override;
unsigned getAlign() const { return align; }
void rauw(const Value &what, Value &with) override;
@@ -509,8 +507,8 @@ public:
: Instr(Type::voidTy, "store"), ptr(&ptr), val(&val), align(align) {}
std::vector<Value*> operands() const override;
- Value *getValue() const { return val; }
- Value *getPointer() const { return ptr; }
+ Value& getValue() const { return *val; }
+ Value& getPtr() const { return *ptr; }
unsigned getAlign() const { return align; }
void rauw(const Value &what, Value &with) override;
void print(std::ostream &os) const override;
@@ -528,6 +526,7 @@ public:
: Instr(Type::voidTy, "memset"), ptr(&ptr), val(&val), bytes(&bytes),
align(align) {}
+ Value& getBytes() const { return *bytes; }
std::vector<Value*> operands() const override;
void rauw(const Value &what, Value &with) override;
void print(std::ostream &os) const override;
@@ -547,6 +546,7 @@ public:
: Instr(Type::voidTy, "memcpy"), dst(&dst), src(&src), bytes(&bytes),
align_dst(align_dst), align_src(align_src), move(move) {}
+ Value& getBytes() const { return *bytes; }
std::vector<Value*> operands() const override;
void rauw(const Value &what, Value &with) override;
void print(std::ostream &os) const override;

MODIFY
ir/memory.cpp
ir/memory.cpp
@@ -481,7 +481,7 @@ expr Pointer::is_aligned(unsigned align) const {
if (align == 1)
return true;
- auto bits = ilog2(align);
+ auto bits = min(ilog2(align), bits_for_offset);
if (!observes_addresses())
// This is stricter than checking get_address(), but as addresses are not

MODIFY
tools/transform.cpp
tools/transform.cpp
@@ -412,13 +412,13 @@ static bool may_be_nonlocal(Value *ptr) {
continue;
if (auto gep = dynamic_cast<GEP*>(ptr)) {
- todo.emplace_back(gep->getPtr());
+ todo.emplace_back(&gep->getPtr());
continue;
}
if (auto c = dynamic_cast<ConversionOp*>(ptr)) {
if (c->getOp() == ConversionOp::BitCast) {
- todo.emplace_back(c->getValue());
+ todo.emplace_back(&c->getValue());
continue;
}
}
@@ -440,12 +440,20 @@ static bool returns_nonlocal(const Instr &inst) {
return num_ptrs(inst.getType());
if (auto load = dynamic_cast<const Load *>(&inst)) {
- if (may_be_nonlocal(load->getPtr()))
+ if (may_be_nonlocal(&load->getPtr()))
return num_ptrs(inst.getType());
}
return 0u;
}
+static optional<int64_t> get_int(const Value &val) {
+ if (auto i = dynamic_cast<const IntConst*>(&val)) {
+ if (auto n = i->getInt())
+ return *n;
+ }
+ return {};
+}
+
static uint64_t max_gep(const Instr &inst) {
if (auto conv = dynamic_cast<const ConversionOp*>(&inst)) {
// if addresses are observed, then expose full ptr range
@@ -457,17 +465,30 @@ static uint64_t max_gep(const Instr &inst) {
if (auto gep = dynamic_cast<const GEP*>(&inst)) {
int64_t off = 0;
for (auto &[mul, v] : gep->getIdxs()) {
- if (auto i = dynamic_cast<IntConst*>(v)) {
- if (auto n = i->getInt()) {
+ if (auto n = get_int(*v)) {
off += mul * *n;
continue;
}
- }
return UINT64_MAX;
}
return abs(off);
}
-
+ if (auto load = dynamic_cast<const Load*>(&inst)) {
+ return divide_up(load->getType().bits(), 8);
+ }
+ if (auto store = dynamic_cast<const Store*>(&inst)) {
+ return divide_up(store->getValue().bits(), 8);
+ }
+ if (auto cpy = dynamic_cast<const Memcpy*>(&inst)) {
+ if (auto bytes = get_int(cpy->getBytes()))
+ return *bytes;
+ return UINT64_MAX;
+ }
+ if (auto memset = dynamic_cast<const Memset*>(&inst)) {
+ if (auto bytes = get_int(memset->getBytes()))
+ return *bytes;
+ return UINT64_MAX;
+ }
return 0;
}
@@ -505,7 +526,7 @@ static void calculateAndInitConstants(Transform &t) {
Type *value_ty;
unsigned align;
if (auto st = dynamic_cast<const Store *>(&inst)) {
- value_ty = &st->getValue()->getType();
+ value_ty = &st->getValue().getType();
align = st->getAlign();
does_ptr_store |= hasPtr(*value_ty);
} else if (auto ld = dynamic_cast<const Load *>(&inst)) {

memory: also consider load/store/memcpy/memset for offset bitwidth computation