@@ -595,10 +595,35 @@ simplify_exprt::simplify_minus(const minus_exprt &expr)
595595 is_number (minus_expr.type ()) && operands[0 ].type ().id () == ID_pointer &&
596596 operands[1 ].type ().id () == ID_pointer)
597597 {
598- // pointer arithmetic: rewrite "p-p" to "0"
598+ exprt ptr_op0 = simplify_object (operands[0 ]).expr ;
599+ exprt ptr_op1 = simplify_object (operands[1 ]).expr ;
599600
600- if (operands[0 ]==operands[1 ])
601- return from_integer (0 , minus_expr.type ());
601+ auto address_of = expr_try_dynamic_cast<address_of_exprt>(ptr_op0);
602+ if (ptr_op0 == ptr_op1 && address_of)
603+ {
604+ exprt offset_op0 = simplify_pointer_offset (
605+ pointer_offset_exprt{operands[0 ], minus_expr.type ()});
606+ exprt offset_op1 = simplify_pointer_offset (
607+ pointer_offset_exprt{operands[1 ], minus_expr.type ()});
608+
609+ const auto object_size =
610+ pointer_offset_size (address_of->object ().type (), ns);
611+ auto element_size =
612+ size_of_expr (to_pointer_type (operands[0 ].type ()).base_type (), ns);
613+
614+ if (
615+ offset_op0.is_constant () && offset_op1.is_constant () &&
616+ object_size.has_value () && element_size.has_value () &&
617+ numeric_cast_v<mp_integer>(to_constant_expr (offset_op0)) <=
618+ *object_size &&
619+ numeric_cast_v<mp_integer>(to_constant_expr (offset_op1)) <=
620+ *object_size)
621+ {
622+ return changed (simplify_rec (div_exprt{
623+ minus_exprt{offset_op0, offset_op1},
624+ typecast_exprt{*element_size, minus_expr.type ()}}));
625+ }
626+ }
602627 }
603628
604629 return unchanged (expr);
0 commit comments