Convert CFN_BUILT_IN_STRLEN to range-ops.
authorAndrew MacLeod <amacleod@redhat.com>
Tue, 20 Sep 2022 23:05:03 +0000 (19:05 -0400)
committerAndrew MacLeod <amacleod@redhat.com>
Thu, 22 Sep 2022 18:48:29 +0000 (14:48 -0400)
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case
for CFN_BUILT_IN_STRLEN.
* gimple-range-op.cc (class cfn_strlen): New.
(gimple_range_op_handler::maybe_builtin_call): Set arguments.

gcc/gimple-range-fold.cc
gcc/gimple-range-op.cc

index d445270..d22fb0e 100644 (file)
@@ -908,27 +908,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
        return true;
       }
 
-    case CFN_BUILT_IN_STRLEN:
-      if (tree lhs = gimple_call_lhs (call))
-       if (ptrdiff_type_node
-           && (TYPE_PRECISION (ptrdiff_type_node)
-               == TYPE_PRECISION (TREE_TYPE (lhs))))
-         {
-           tree type = TREE_TYPE (lhs);
-           tree max = vrp_val_max (ptrdiff_type_node);
-           wide_int wmax
-             = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
-           tree range_min = build_zero_cst (type);
-           // To account for the terminating NULL, the maximum length
-           // is one less than the maximum array size, which in turn
-           // is one less than PTRDIFF_MAX (or SIZE_MAX where it's
-           // smaller than the former type).
-           // FIXME: Use max_object_size() - 1 here.
-           tree range_max = wide_int_to_tree (type, wmax - 2);
-           r.set (range_min, range_max);
-           return true;
-         }
-      break;
     default:
       break;
     }
index 09b7dd2..f9161b5 100644 (file)
@@ -611,6 +611,30 @@ cfn_ubsan op_cfn_ubsan_add (PLUS_EXPR);
 cfn_ubsan op_cfn_ubsan_sub (MINUS_EXPR);
 cfn_ubsan op_cfn_ubsan_mul (MULT_EXPR);
 
+
+// Implement range operator for CFN_BUILT_IN_STRLEN
+class cfn_strlen : public range_operator
+{
+public:
+  using range_operator::fold_range;
+  virtual bool fold_range (irange &r, tree type, const irange &,
+                          const irange &, relation_kind) const
+  {
+    tree max = vrp_val_max (ptrdiff_type_node);
+    wide_int wmax
+      = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
+    tree range_min = build_zero_cst (type);
+    // To account for the terminating NULL, the maximum length
+    // is one less than the maximum array size, which in turn
+    // is one less than PTRDIFF_MAX (or SIZE_MAX where it's
+    // smaller than the former type).
+    // FIXME: Use max_object_size() - 1 here.
+    tree range_max = wide_int_to_tree (type, wmax - 2);
+    r.set (range_min, range_max);
+    return true;
+  }
+} op_cfn_strlen;
+
 // Set up a gimple_range_op_handler for any built in function which can be
 // supported via range-ops.
 
@@ -711,6 +735,19 @@ gimple_range_op_handler::maybe_builtin_call ()
       m_int = &op_cfn_ubsan_mul;
       break;
 
+    case CFN_BUILT_IN_STRLEN:
+      {
+       tree lhs = gimple_call_lhs (call);
+       if (lhs && ptrdiff_type_node && (TYPE_PRECISION (ptrdiff_type_node)
+                                        == TYPE_PRECISION (TREE_TYPE (lhs))))
+         {
+           m_op1 = gimple_call_arg (call, 0);
+           m_valid = true;
+           m_int = &op_cfn_strlen;
+         }
+       break;
+      }
+
     default:
       break;
     }