diff --git a/ir/globals.cpp b/ir/globals.cpp index 62bb7c31c..f4a3e75d1 100644 --- a/ir/globals.cpp +++ b/ir/globals.cpp @@ -42,6 +42,7 @@ bool has_ptr_arg = true; bool has_initializes_attr = true; bool has_null_block = true; bool null_is_dereferenceable = false; +bool has_globals_diff_align = true; bool does_int_mem_access = true; bool does_ptr_mem_access = true; bool does_ptr_store = true; diff --git a/ir/globals.h b/ir/globals.h index 478318f06..5c66219c3 100644 --- a/ir/globals.h +++ b/ir/globals.h @@ -87,6 +87,9 @@ extern bool has_null_block; extern bool null_is_dereferenceable; +/// Whether there is at least one global with different alignment in src/tgt +extern bool has_globals_diff_align; + /// Whether the programs do memory accesses that load/store int/ptrs extern bool does_int_mem_access; extern bool does_ptr_mem_access; diff --git a/ir/memory.cpp b/ir/memory.cpp index 181960b32..326e9012f 100644 --- a/ir/memory.cpp +++ b/ir/memory.cpp @@ -2126,6 +2126,9 @@ Memory::alloc(const expr *size, uint64_t align, BlockKind blockKind, expr nooverflow = true; if (size) { size_zext = size->zextOrTrunc(bits_size_t); + // we round up the size statically instead of creating a large expr later + if (!has_globals_diff_align) + size_zext = size_zext.round_up(expr::mkUInt(align, bits_size_t)); nooverflow = size->bits() <= bits_size_t ? true : size->extract(size->bits()-1, bits_size_t) == 0; } diff --git a/ir/pointer.cpp b/ir/pointer.cpp index 595d8f8f1..93f80a16b 100644 --- a/ir/pointer.cpp +++ b/ir/pointer.cpp @@ -331,7 +331,11 @@ expr Pointer::blockSizeOffsetT() const { } expr Pointer::blockSizeAligned() const { - return blockSize().round_up_bits(blockAlignment().zextOrTrunc(bits_size_t)); + auto size = blockSize(); + // programs can't observe whether the size was increased up to alignment + if (!has_globals_diff_align) + return size; + return size.round_up_bits(blockAlignment().zextOrTrunc(bits_size_t)); } expr Pointer::blockSizeAlignedOffsetT() const { @@ -456,7 +460,8 @@ expr Pointer::inbounds(bool simplify_ptr) { expr Pointer::blockAlignment() const { return getValue("blk_align", m.local_blk_align, m.non_local_blk_align, - expr::mkUInt(0, Memory::bitsAlignmentInfo()), true); + expr::mkUInt(0, Memory::bitsAlignmentInfo()), + has_globals_diff_align); } expr Pointer::isBlockAligned(uint64_t align, bool exact) const { diff --git a/tools/transform.cpp b/tools/transform.cpp index 62236402e..ad45c6511 100644 --- a/tools/transform.cpp +++ b/tools/transform.cpp @@ -960,6 +960,7 @@ static void calculateAndInitConstants(Transform &t) { uint64_t glb_alloc_aligned_size = 0; num_consts_src = 0; + has_globals_diff_align = false; for (auto GV : globals_src) { if (GV->isConst()) @@ -974,7 +975,10 @@ static void calculateAndInitConstants(Transform &t) { [GVT](auto *GV) -> bool { return GVT->getName() == GV->getName(); }); if (I == globals_src.end()) { ++num_globals; + } else { + has_globals_diff_align |= GVT->getAlignment() != (*I)->getAlignment(); } + glb_alloc_aligned_size = add_saturate(glb_alloc_aligned_size, aligned_alloc_size(GVT->size(), GVT->getAlignment()));