case BIT_AND_EXPR:
case BIT_IOR_EXPR:
// Bitwise operations on single bits are logical too.
- if (types_compatible_p (TREE_TYPE (gimple_assign_rhs1 (gs)),
+ if (range_compatible_p (TREE_TYPE (gimple_assign_rhs1 (gs)),
boolean_type_node))
return true;
break;
// This is complicated by the fact that Ada has multi-bit booleans,
// so true can be ~[0, 0] (i.e. [1,MAX]).
tree type = r.type ();
- gcc_checking_assert (types_compatible_p (type, boolean_type_node));
+ gcc_checking_assert (range_compatible_p (type, boolean_type_node));
return (r.singleton_p () || !r.contains_p (build_zero_cst (type)));
}
// If NAME can be calculated on the edge, use that.
if (m_gori_map->is_export_p (name, e->src))
- return compute_operand_range (r, stmt, lhs, name);
-
- // Otherwise see if NAME is derived from something that can be
- // calculated. This performs no dynamic lookups whatsover, so it is
- // low cost.
+ {
+ if (compute_operand_range (r, stmt, lhs, name))
+ {
+ // Sometimes compatible types get interchanged. See PR97360.
+ // Make sure we are returning the type of the thing we asked for.
+ if (!r.undefined_p () && r.type () != TREE_TYPE (name))
+ {
+ gcc_checking_assert (range_compatible_p (r.type (),
+ TREE_TYPE (name)));
+ range_cast (r, TREE_TYPE (name));
+ }
+ return true;
+ }
+ }
return false;
}
logical_stmt_cache::cacheable_p (gimple *stmt, const irange *lhs_range) const
{
if (gimple_code (stmt) == GIMPLE_ASSIGN
- && types_compatible_p (TREE_TYPE (gimple_assign_lhs (stmt)),
+ && range_compatible_p (TREE_TYPE (gimple_assign_lhs (stmt)),
boolean_type_node)
&& TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
{
{
if (r.undefined_p ())
return true;
+ // We sometimes get compatible types copied from operands, make sure
+ // the correct type is being returned.
if (name && TREE_TYPE (name) != r.type ())
- range_cast (r, TREE_TYPE (name));
+ {
+ gcc_checking_assert (range_compatible_p (r.type (),
+ TREE_TYPE (name)));
+ range_cast (r, TREE_TYPE (name));
+ }
return true;
}
return false;
else
gcc_assert (range_of_expr (r, name, s));
gcc_checking_assert (r.undefined_p ()
- || types_compatible_p (r.type(), TREE_TYPE (name)));
+ || range_compatible_p (r.type (), TREE_TYPE (name)));
}
// Calculate a range for NAME on edge E and return it in R.
range_on_exit (r, e->src, name);
gcc_checking_assert (r.undefined_p ()
- || types_compatible_p (r.type(), TREE_TYPE (name)));
+ || range_compatible_p (r.type(), TREE_TYPE (name)));
// Check to see if NAME is defined on edge e.
if (m_cache.outgoing_edge_range_p (edge_range, e, name))
return NULL_TREE;
}
+// Return true if TYPE1 and TYPE2 are compatible range types.
+
+static inline bool
+range_compatible_p (tree type1, tree type2)
+{
+ // types_compatible_p requires conversion in both directions to be useless.
+ // GIMPLE only requires a cast one way in order to be compatible.
+ // Ranges really only need the sign and precision to be the same.
+ return (TYPE_PRECISION (type1) == TYPE_PRECISION (type2)
+ && TYPE_SIGN (type1) == TYPE_SIGN (type2));
+}
+
// Return the legacy GCC global range for NAME if it has one, otherwise
// return VARYING.