Skip to content

Commit ec20240

Browse files
committed
Simplify pointer casts of pointer arithmetic
This permits simplifying, e.g., `(char*)(ptr + 1) + -1` to `(char*)ptr` when `ptr` is `unsigned char*`. This, in turn, avoids different formulae produced on AArch64 (where `char` is unsigned) and Apple Silicon/macOS (where `char` is signed, as is the case on x86).
1 parent 7ff3d66 commit ec20240

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

src/util/simplify_expr.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,45 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
10121012
}
10131013
}
10141014

1015+
// Push a pointer typecast into pointer arithmetic
1016+
// (T)(ptr + int) ---> (T)ptr + sizeof(inner-st)/sizeof(outer-st)*int
1017+
// when the inner subtype's size is a multiple of the outer subtype's size
1018+
if(
1019+
expr_type.id() == ID_pointer && op_type.id() == ID_pointer &&
1020+
expr.op().id() == ID_plus)
1021+
{
1022+
const auto step =
1023+
pointer_offset_size(to_pointer_type(op_type).base_type(), ns);
1024+
const auto new_step =
1025+
pointer_offset_size(to_pointer_type(expr_type).base_type(), ns);
1026+
1027+
if(
1028+
step.has_value() && *step != 0 && new_step.has_value() &&
1029+
*new_step != 0 && *step >= *new_step && *step % *new_step == 0)
1030+
{
1031+
const typet size_t_type(size_type());
1032+
auto new_expr = expr.op();
1033+
new_expr.type() = expr.type();
1034+
1035+
for(auto &op : new_expr.operands())
1036+
{
1037+
if(op.type().id() == ID_pointer)
1038+
{
1039+
exprt new_op = simplify_typecast(typecast_exprt{op, expr.type()});
1040+
op = std::move(new_op);
1041+
}
1042+
else if(*step > *new_step)
1043+
{
1044+
exprt new_op = simplify_mult(
1045+
mult_exprt{from_integer(*step / *new_step, op.type()), op});
1046+
op = std::move(new_op);
1047+
}
1048+
}
1049+
1050+
return changed(simplify_plus(to_plus_expr(new_expr)));
1051+
}
1052+
}
1053+
10151054
const irep_idt &expr_type_id=expr_type.id();
10161055
const exprt &operand = expr.op();
10171056
const irep_idt &op_type_id=op_type.id();

0 commit comments

Comments
 (0)