memory: support byte size > 8 bits in memset
MODIFY
ir/instr.h
ir/instr.h
@@ -532,6 +532,7 @@ public:
align(align) {}
Value& getBytes() const { return *bytes; }
+ unsigned getAlign() const { return align; }
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
@@ -390,8 +390,7 @@ expr Pointer::get_offset_sizet() const {
}
expr Pointer::get_attrs() const {
- assert(bits_for_ptrattrs > 0);
- return p.extract(bits_for_ptrattrs - 1, 0);
+ return bits_for_ptrattrs ? p.extract(bits_for_ptrattrs - 1, 0) : expr();
}
expr Pointer::get_value(const char *name, const FunctionExpr &local_fn,
@@ -451,7 +450,7 @@ expr Pointer::short_ptr() const {
Pointer Pointer::operator+(const expr &bytes) const {
return { m, get_bid(), get_offset() + bytes.zextOrTrunc(bits_for_offset),
- bits_for_ptrattrs ? get_attrs() : expr() };
+ get_attrs() };
}
Pointer Pointer::operator+(unsigned bytes) const {
@@ -1434,8 +1433,8 @@ StateValue Memory::load(const expr &p, const Type &type, unsigned align,
vector<Byte> loadedBytes;
bytecount /= bytesz;
for (unsigned i = 0; i < bytecount; ++i) {
- auto ptr_i = ptr + (little_endian ? i * bytesz :
- (bytecount - i - 1) * bytesz);
+ auto ptr_i = ptr + (little_endian ? i * bytesz
+ : (bytecount - i - 1) * bytesz);
loadedBytes.emplace_back(*this, ::load(ptr_i, local_block_val,
non_local_block_val));
}
@@ -1463,17 +1462,23 @@ static expr ptr_deref_within(const Pointer &idx, const Pointer &ptr,
void Memory::memset(const expr &p, const StateValue &val, const expr &bytesize,
unsigned align) {
assert(!memory_unused());
- assert(bits_byte == 8);
assert(!val.isValid() || val.bits() == 8);
+ unsigned bytesz = bits_byte / 8;
Pointer ptr(*this, p);
ptr.is_dereferenceable(bytesize, align, true);
- vector<Byte> bytes = valueToBytes(val, IntType("", bits_byte), *this, state);
+ auto wval = val;
+ for (unsigned i = 1; i < bytesz; ++i) {
+ wval = wval.concat(val);
+ }
+ assert(!val.isValid() || wval.bits() == bits_byte);
+
+ auto bytes = valueToBytes(wval, IntType("", bits_byte), *this, state);
assert(bytes.size() == 1);
uint64_t n;
- if (bytesize.isUInt(n) && n <= 4) {
- for (unsigned i = 0; i < n; ++i) {
+ if (bytesize.isUInt(n) && (n / bytesz) <= 4) {
+ for (unsigned i = 0; i < n; i += bytesz) {
store(ptr + i, bytes[0](), local_block_val, non_local_block_val);
}
} else {

MODIFY
ir/state_value.cpp
ir/state_value.cpp
@@ -37,7 +37,9 @@ StateValue StateValue::zextOrTrunc(unsigned tobw) const {
}
StateValue StateValue::concat(const StateValue &other) const {
- return { value.concat(other.value), non_poison.concat(other.non_poison) };
+ return { value.concat(other.value),
+ non_poison.isBool() ? expr(non_poison)
+ : non_poison.concat(other.non_poison) };
}
bool StateValue::isValid() const {

MODIFY
tests/alive-tv/memory/memset-store.src.ll
tests/alive-tv/memory/memset-store.src.ll
@@ -8,3 +8,10 @@ define i32 @f() {
%v = load i32, i32* @x
ret i32 %v
}
+
+define i32 @f2() {
+ %p = bitcast i32* @x to i8*
+ call void @llvm.memset.p0i8.i8(i8* align 4 %p, i8 1, i32 4, i1 0)
+ %v = load i32, i32* @x
+ ret i32 %v
+}

MODIFY
tests/alive-tv/memory/memset-store.tgt.ll
tests/alive-tv/memory/memset-store.tgt.ll
@@ -7,3 +7,9 @@ define i32 @f() {
%v = load i32, i32* @x
ret i32 %v
}
+
+define i32 @f2() {
+ store i32 16843009, i32* @x ; 0x01010101
+ %v = load i32, i32* @x
+ ret i32 %v
+}

MODIFY
tools/transform.cpp
tools/transform.cpp
@@ -563,13 +563,19 @@ static uint64_t get_access_size(const Type &ty) {
static uint64_t get_access_size(const Instr &inst) {
if (dynamic_cast<const Calloc*>(&inst) ||
- dynamic_cast<const Memcpy*>(&inst) ||
- dynamic_cast<const Memset*>(&inst)) {
+ dynamic_cast<const Memcpy *>(&inst)) {
// TODO
does_int_mem_access = true;
return 1;
}
+ if (auto i = dynamic_cast<const Memset*>(&inst)) {
+ does_int_mem_access = true;
+ if (auto bytes = get_int(i->getBytes()))
+ return gcd(i->getAlign(), *bytes);
+ return 1;
+ }
+
Type *value_ty;
unsigned align;
if (auto st = dynamic_cast<const Store*>(&inst)) {
@@ -579,8 +585,7 @@ static uint64_t get_access_size(const Instr &inst) {
} else if (auto ld = dynamic_cast<const Load*>(&inst)) {
value_ty = &ld->getType();
align = ld->getAlign();
- }
- else
+ } else
return 0;
does_ptr_mem_access |= hasPtr(*value_ty);
@@ -769,28 +774,29 @@ static void calculateAndInitConstants(Transform &t) {
little_endian = t.src.isLittleEndian();
if (config::debug)
- config::dbg() << "num_max_nonlocals_inst: " << num_max_nonlocals_inst << "\n"
- "num_locals: " << num_locals << "\n"
- "num_nonlocals_src: " << num_nonlocals_src << "\n"
- "num_nonlocals: " << num_nonlocals << "\n"
- "bits_for_bid: " << bits_for_bid << "\n"
- "bits_for_offset: " << bits_for_offset << "\n"
- "bits_program_pointer: " << bits_program_pointer << "\n"
- "max_alloc_size: " << max_alloc_size << "\n"
- "max_mem_access: " << max_mem_access << "\n"
- "bits_size_t: " << bits_size_t << "\n"
- "bits_byte: " << bits_byte << "\n"
- "little_endian: " << little_endian << "\n"
- "nullptr_is_used: " << nullptr_is_used << "\n"
- "has_int2ptr: " << has_int2ptr << "\n"
- "has_ptr2int: " << has_ptr2int << "\n"
- "has_malloc: " << has_malloc << "\n"
- "has_free: " << has_free << "\n"
- "does_ptr_store: " << does_ptr_store << "\n"
- "does_ptr_mem_access: " << does_ptr_mem_access << "\n"
- "does_int_mem_access: " << does_int_mem_access << "\n"
- "does_sub_byte_access: " << does_sub_byte_access << "\n"
- ;
+ config::dbg() << "num_max_nonlocals_inst: " << num_max_nonlocals_inst
+ << "\nnum_locals: " << num_locals
+ << "\nnum_nonlocals_src: " << num_nonlocals_src
+ << "\nnum_nonlocals: " << num_nonlocals
+ << "\nbits_for_bid: " << bits_for_bid
+ << "\nbits_for_offset: " << bits_for_offset
+ << "\nbits_size_t: " << bits_size_t
+ << "\nbits_program_pointer: " << bits_program_pointer
+ << "\nmax_alloc_size: " << max_alloc_size
+ << "\nmin_access_size: " << min_access_size
+ << "\nmax_mem_access: " << max_mem_access
+ << "\nbits_byte: " << bits_byte
+ << "\nlittle_endian: " << little_endian
+ << "\nnullptr_is_used: " << nullptr_is_used
+ << "\nhas_int2ptr: " << has_int2ptr
+ << "\nhas_ptr2int: " << has_ptr2int
+ << "\nhas_malloc: " << has_malloc
+ << "\nhas_free: " << has_free
+ << "\ndoes_ptr_store: " << does_ptr_store
+ << "\ndoes_ptr_mem_access: " << does_ptr_mem_access
+ << "\ndoes_int_mem_access: " << does_int_mem_access
+ << "\ndoes_sub_byte_access: " << does_sub_byte_access
+ << "\n";
}

memory: support byte size > 8 bits in memset