public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Siddhesh Poyarekar <siddhesh@gotplt.org>
To: gcc-patches@gcc.gnu.org
Cc: jakub@redhat.com
Subject: [PATCH 10/10] tree-object-size: Handle dynamic offsets
Date: Wed, 10 Nov 2021 00:31:36 +0530	[thread overview]
Message-ID: <20211109190137.1107736-11-siddhesh@gotplt.org> (raw)
In-Reply-To: <20211109190137.1107736-1-siddhesh@gotplt.org>

Compute whole sizes for objects to allow offsets to be negative for
dynamic object sizes.  This way, the returned object size would be
precise even for negative offsets as long as the offset is within bounds
of the object.

gcc/ChangeLog:

	* tree-object-size.c (addr_object_size, expr_object_size,
	plus_stmt_object_size, cond_expr_object_size,
	phi_dynamic_object_size, parm_object_size): Add new wholesize
	argument and handle whole sizes.
	(object_whole_sizes): New vector array.
	(object_sizes_grow, object_sizes_release, object_sizes_get,
	object_sizes_set, object_sizes_initialize): Add new wholesize
	argument to manage object_whole_sizes arrays.
	(size_for_offset): Get offset from wholesize if available.
	(estimate_size): Handle COMPOUND_EXPR.
	(gimplify_size_expressions): Also remove the whole size SSA.
	(bundle_whole_size): New function.
	(ssa_object_size): Remove function.
	(collect_object_sizes_for): Return a tree and accept new
	wholesize argument.
	(init_object_sizes): Allocate object_whole_sizes.
	(fini_object_sizes): Free object_whole_sizes.

gcc/testsuite/ChangeLog:

	* gcc.dg/builtin-dynamic-object-size-0.c: Add new tests.

Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
---
 .../gcc.dg/builtin-dynamic-object-size-0.c    |  87 ++++
 gcc/tree-object-size.c                        | 423 ++++++++++++------
 2 files changed, 383 insertions(+), 127 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c
index a1db63b2d45..3b38b915593 100644
--- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c
+++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c
@@ -273,6 +273,25 @@ test_substring (size_t sz, size_t off)
   return __builtin_dynamic_object_size (&str[off], 0);
 }
 
+size_t
+__attribute__ ((noinline))
+test_substring_ptrplus (size_t sz, size_t off)
+{
+  int str[sz];
+
+  return __builtin_dynamic_object_size (str + off, 0);
+}
+
+size_t
+__attribute__ ((noinline))
+test_substring_ptrplus2 (size_t sz, size_t off, size_t off2)
+{
+  int str[sz];
+  int *ptr = &str[off];
+
+  return __builtin_dynamic_object_size (ptr + off2, 0);
+}
+
 size_t
 __attribute__ ((access (__read_write__, 1, 2)))
 test_parmsz_simple (void *obj, size_t sz)
@@ -280,6 +299,40 @@ test_parmsz_simple (void *obj, size_t sz)
   return __builtin_dynamic_object_size (obj, 0);
 }
 
+size_t
+__attribute__ ((noinline))
+__attribute__ ((access (__read_write__, 1, 2)))
+test_parmsz (void *obj, size_t sz, size_t off)
+{
+  return __builtin_dynamic_object_size (obj + off, 0);
+}
+
+size_t
+__attribute__ ((noinline))
+__attribute__ ((access (__read_write__, 1, 2)))
+test_parmsz_scale (int *obj, size_t sz, size_t off)
+{
+  return __builtin_dynamic_object_size (obj + off, 0);
+}
+
+size_t
+__attribute__ ((noinline))
+__attribute__ ((access (__read_write__, 1, 2)))
+test_loop (int *obj, size_t sz, size_t start, size_t end, int incr)
+{
+  int *ptr = obj + start;
+
+  for (int i = start; i != end; i = i + incr)
+    {
+      ptr = ptr + incr;
+      if (__builtin_dynamic_object_size (ptr, 0) == 0)
+	return 0;
+    }
+
+  return __builtin_dynamic_object_size (ptr, 0);
+}
+
+
 unsigned nfails = 0;
 
 #define FAIL() ({ \
@@ -357,6 +410,14 @@ main (int argc, char **argv)
   size_t objsz = 0;
   if (test_dynarray_struct_subobj2 (42, 4, &objsz) != objsz - 4 - 12)
     FAIL ();
+  if (test_substring_ptrplus (128, 4) != (128 - 4) * sizeof (int))
+    FAIL ();
+  if (test_substring_ptrplus (128, 142) != 0)
+    FAIL ();
+  if (test_substring_ptrplus2 (128, 4, 4) != (128 - 8) * sizeof (int))
+    FAIL ();
+  if (test_substring_ptrplus2 (128, 4, -3) != (128 - 1) * sizeof (int))
+    FAIL ();
   if (test_dynarray_cond (0) != 16)
     FAIL ();
   if (test_dynarray_cond (1) != 8)
@@ -368,6 +429,32 @@ main (int argc, char **argv)
   if (test_parmsz_simple (argv[0], __builtin_strlen (argv[0]) + 1)
       != __builtin_strlen (argv[0]) + 1)
     FAIL ();
+  if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1, -1) != 0)
+    FAIL ();
+  if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1, 0)
+      != __builtin_strlen (argv[0]) + 1)
+    FAIL ();
+  if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1,
+		   __builtin_strlen (argv[0])) != 1)
+    FAIL ();
+  if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1,
+		   __builtin_strlen (argv[0]) + 2) != 0)
+    FAIL ();
+  int in[42];
+  if (test_parmsz_scale (in, 42, 2) != 40 * sizeof (int))
+    FAIL ();
+  if (test_loop (in, 42, 0, 32, 1) != 10 * sizeof (int))
+    FAIL ();
+  if (test_loop (in, 42, 32, -1, -1) != 0)
+    FAIL ();
+  if (test_loop (in, 42, 32, 10, -1) != 32 * sizeof (int))
+    FAIL ();
+  if (test_loop (in, 42, 42, 0, -1) != 42 * sizeof (int))
+    FAIL ();
+  if (test_loop (in, 42, 44, 0, -1) != 0)
+    FAIL ();
+  if (test_loop (in, 42, 20, 52, 1) != 0)
+    FAIL ();
 
   if (nfails > 0)
     __builtin_abort ();
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 865fc3feea5..d82937de6ba 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -57,14 +57,14 @@ enum
 
 static tree compute_object_offset (const_tree, const_tree);
 static bool addr_object_size (struct object_size_info *,
-			      const_tree, int, tree *);
+			      const_tree, int, tree *, tree *t = NULL);
 static tree alloc_object_size (const gcall *, int);
 static tree pass_through_call (const gcall *);
-static void collect_object_sizes_for (struct object_size_info *, tree);
-static tree expr_object_size (struct object_size_info *, tree);
-static tree ssa_object_size (struct object_size_info *, tree, tree);
-static tree plus_stmt_object_size (struct object_size_info *, gimple *);
-static tree cond_expr_object_size (struct object_size_info *, gimple *);
+static tree collect_object_sizes_for (struct object_size_info *, tree,
+				      tree *t = NULL);
+static tree expr_object_size (struct object_size_info *, tree, tree *);
+static tree plus_stmt_object_size (struct object_size_info *, tree, tree *);
+static tree cond_expr_object_size (struct object_size_info *, tree, tree *);
 static void init_offset_limit (void);
 
 /* object_sizes[0] is upper bound for number of bytes till the end of
@@ -90,6 +90,9 @@ static void init_offset_limit (void);
    - Its value in object_sizes is an expression that evaluates to the size.  */
 static vec<tree> object_sizes[OST_END];
 
+/* Whole size expressions are only needed for dynamic object sizes.  */
+static vec<tree> object_whole_sizes[OST_DYNAMIC];
+
 /* Bitmaps what object sizes have been computed already.  */
 static bitmap computed[OST_END];
 
@@ -149,21 +152,35 @@ size_unknown (int object_size_type)
   return size_int (unknown (object_size_type));
 }
 
-/* Grow object_sizes[OBJECT_SIZE_TYPE] to num_ssa_names.  */
+/* Grow object_sizes[OBJECT_SIZE_TYPE] and if WHOLE is true,
+   object_whole_sizes[OBJECT_SIZE_TYPE]  to num_ssa_names.  */
 
 static inline void
-object_sizes_grow (int object_size_type)
+object_sizes_grow (int object_size_type, bool whole = false)
 {
   if (num_ssa_names > object_sizes[object_size_type].length ())
     object_sizes[object_size_type].safe_grow (num_ssa_names, true);
+  if (whole)
+    {
+      gcc_assert (object_size_type & OST_DYNAMIC);
+      object_size_type &= ~OST_DYNAMIC;
+      if (num_ssa_names > object_whole_sizes[object_size_type].length ())
+	object_whole_sizes[object_size_type].safe_grow (num_ssa_names, true);
+    }
 }
 
 /* Release object_sizes[OBJECT_SIZE_TYPE].  */
 
 static inline void
-object_sizes_release (int object_size_type)
+object_sizes_release (int object_size_type, bool whole = false)
 {
   object_sizes[object_size_type].release ();
+  if (whole)
+    {
+      gcc_assert (object_size_type & OST_DYNAMIC);
+      object_size_type &= ~OST_DYNAMIC;
+      object_whole_sizes[object_size_type].release ();
+    }
 }
 
 /* Return true if object_sizes[OBJECT_SIZE_TYPE][VARNO] is unknown.  */
@@ -178,8 +195,16 @@ object_sizes_unknown_p (int object_size_type, unsigned varno)
 /* Return size for VARNO corresponding to OSI.  */
 
 static inline tree
-object_sizes_get (struct object_size_info *osi, unsigned varno)
+object_sizes_get (struct object_size_info *osi, unsigned varno,
+		  bool whole = false)
 {
+  if (whole)
+    {
+      int object_size_type = osi->object_size_type;
+      gcc_assert (object_size_type & OST_DYNAMIC);
+      object_size_type &= ~OST_DYNAMIC;
+      return object_whole_sizes[object_size_type][varno];
+    }
   return object_sizes[osi->object_size_type][varno];
 }
 
@@ -187,22 +212,38 @@ object_sizes_get (struct object_size_info *osi, unsigned varno)
 
 static inline void
 object_sizes_initialize (struct object_size_info *osi, unsigned varno,
-			 tree val = NULL_TREE)
+			 tree val, bool whole = false)
 {
   int object_size_type = osi->object_size_type;
 
-  if (!val)
-    val = size_initval (object_size_type);
   object_sizes[object_size_type][varno] = val;
+  if (whole)
+    {
+      object_size_type = osi->object_size_type;
+      gcc_assert (object_size_type & OST_DYNAMIC);
+      object_size_type &= ~OST_DYNAMIC;
+      object_whole_sizes[object_size_type][varno] = val;
+    }
 }
 
 /* Set size for VARNO corresponding to OSI to VAL if it is the new minimum or
    maximum.  */
 
 static inline void
-object_sizes_set (struct object_size_info *osi, unsigned varno, tree val)
+object_sizes_set (struct object_size_info *osi, unsigned varno, tree val,
+		  bool whole = false)
 {
   int object_size_type = osi->object_size_type;
+
+  if (whole)
+    {
+      int object_size_type = osi->object_size_type;
+      gcc_assert (object_size_type & OST_DYNAMIC);
+      object_size_type &= ~OST_DYNAMIC;
+      object_whole_sizes[object_size_type][varno] = val;
+      return;
+    }
+
   tree curval = object_sizes[object_size_type][varno];
 
   /* Object size is set at most twice, once to put in an SSA name to resolve
@@ -239,11 +280,21 @@ init_offset_limit (void)
   offset_limit /= 2;
 }
 
-/* Bytes at end of the object with SZ from offset OFFSET. */
+/* Bytes at end of the object with SZ from offset OFFSET.  If WHOLESIZE is
+   present, use it to allow negative OFFSET to the extent that it does not
+   underflow WHOLESIZE.  */
 
 static tree
-size_for_offset (tree sz, tree offset)
+size_for_offset (tree sz, tree offset, tree wholesize = NULL_TREE)
 {
+  if (wholesize)
+    {
+      offset = size_binop (PLUS_EXPR, size_binop (MAX_EXPR, wholesize, sz),
+			   offset);
+      offset = size_binop (MINUS_EXPR, offset, sz);
+      sz = wholesize;
+    }
+
   return size_binop (MINUS_EXPR, size_binop (MAX_EXPR, sz, offset), offset);
 }
 
@@ -360,7 +411,7 @@ decl_init_size (tree decl, bool min)
 
 static bool
 addr_object_size (struct object_size_info *osi, const_tree ptr,
-		  int object_size_type, tree *psize)
+		  int object_size_type, tree *psize, tree *wholesize)
 {
   tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
 
@@ -369,6 +420,8 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
   /* Set to unknown and overwrite just before returning if the size
      could be determined.  */
   *psize = size_unknown (object_size_type);
+  if (wholesize)
+    *wholesize = size_unknown (object_size_type);
 
   pt_var = TREE_OPERAND (ptr, 0);
   while (handled_component_p (pt_var))
@@ -391,21 +444,13 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
       else
 	{
 	  tree var = TREE_OPERAND (pt_var, 0);
-	  collect_object_sizes_for (osi, var);
-	  if (bitmap_bit_p (computed[object_size_type],
-			    SSA_NAME_VERSION (var)))
-	    sz = object_sizes_get (osi, SSA_NAME_VERSION (var));
-	  else
+	  sz = collect_object_sizes_for (osi, var);
+	  if (!bitmap_bit_p (computed[object_size_type],
+			     SSA_NAME_VERSION (var)))
 	    sz = size_unknown (object_size_type);
 	}
       if (!size_unknown_p (sz, object_size_type))
-	{
-	  tree offset = TREE_OPERAND (pt_var, 1);
-	  if (TREE_CODE (offset) != INTEGER_CST)
-	    sz = size_unknown (object_size_type);
-	  else
-	    sz = size_for_offset (sz, offset);
-	}
+	sz = size_for_offset (sz, TREE_OPERAND (pt_var, 1));
 
       if (!size_unknown_p (sz, object_size_type)
 	  && (TREE_CODE (sz) != INTEGER_CST
@@ -570,6 +615,8 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
 
   if (size_known_p (bytes, object_size_type))
     {
+      if ((object_size_type & OST_DYNAMIC) && wholesize)
+	*wholesize = object_size_type & OST_SUBOBJECT ? bytes : pt_var_size;
       *psize = bytes;
       return true;
     }
@@ -766,6 +813,8 @@ estimate_size (object_size_info *osi, tree size, bitmap *visitlog = NULL)
 	    }
 	  return size_binop (code, ret, off);
 	}
+    case COMPOUND_EXPR:
+      return estimate_size (osi, TREE_OPERAND (size, 1), visitlog);
     case INTEGER_CST:
     default:
       return size;
@@ -943,6 +992,13 @@ gimplify_size_expressions (object_size_info *osi)
 	      if (stmt)
 		{
 		  gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+		  remove_phi_node (&gsi, false);
+
+		  /* Also remove the whole size SSA.  */
+		  stmt = SSA_NAME_DEF_STMT (object_sizes_get (osi, varno,
+							      true));
+		  gcc_checking_assert (stmt);
+		  gsi = gsi_for_stmt (stmt);
 		  remove_phi_node (&gsi, true);
 		}
 	      bitmap_set_bit (tempsize_free, i);
@@ -1043,7 +1099,7 @@ compute_builtin_object_size (tree ptr, int object_size_type,
       bitmap_iterator bi;
       unsigned int i;
 
-      object_sizes_grow (object_size_type);
+      object_sizes_grow (object_size_type, object_size_type & OST_DYNAMIC);
       if (dump_file)
 	{
 	  fprintf (dump_file, "Computing %s %s%sobject size for ",
@@ -1142,10 +1198,52 @@ make_or_get_tempsize (struct object_size_info *osi, unsigned varno)
   return ssa;
 }
 
+static tree
+bundle_whole_size (struct object_size_info *osi, tree var, tree res,
+		   tree *wholesize)
+{
+  int object_size_type = osi->object_size_type;
+
+  if (!(object_size_type & OST_DYNAMIC)
+      || size_unknown_p (res, object_size_type))
+    return res;
+
+  tree cur = NULL_TREE;
+
+  /* Get the temp SSA name if we created one for a dependency loop.  */
+  if (TREE_CODE (var) == SSA_NAME)
+    cur = object_sizes_get (osi, SSA_NAME_VERSION (var), true);
+
+  /* If we need to gimplify WHOLERES, fold it into a compound expression
+     along with RES so that their statements are emitted together.  */
+  if (cur && TREE_CODE (cur) == SSA_NAME)
+    {
+      unsigned wno = SSA_NAME_VERSION (cur);
+      if (bitmap_bit_p (osi->reexamine, wno))
+	bitmap_clear_bit (osi->reexamine, wno);
+      else
+	cur = NULL_TREE;
+    }
+  else if (!is_gimple_variable (*wholesize)
+	   && TREE_CODE (*wholesize) != INTEGER_CST)
+    cur = make_ssa_name (sizetype);
+  else
+    cur = NULL_TREE;
+
+  if (cur)
+    {
+      res = size_binop (COMPOUND_EXPR,
+			size_binop (MODIFY_EXPR, cur, *wholesize),
+			res);
+      *wholesize = cur;
+    }
+  return res;
+}
+
 /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME.  */
 
 static tree
-expr_object_size (struct object_size_info *osi, tree value)
+expr_object_size (struct object_size_info *osi, tree value, tree *wholesize)
 {
   int object_size_type = osi->object_size_type;
   tree bytes;
@@ -1153,14 +1251,17 @@ expr_object_size (struct object_size_info *osi, tree value)
   if (TREE_CODE (value) == WITH_SIZE_EXPR)
     value = TREE_OPERAND (value, 0);
 
-  /* Pointer variables should have been handled by ssa_object_size.  */
+  /* Pointer variables should have been handled by
+     collect_object_sizes_for.  */
   gcc_assert (TREE_CODE (value) != SSA_NAME
 	      || !POINTER_TYPE_P (TREE_TYPE (value)));
 
   if (TREE_CODE (value) == ADDR_EXPR
-      && addr_object_size (osi, value, object_size_type, &bytes))
-    return bytes;
+      && addr_object_size (osi, value, object_size_type, &bytes, wholesize))
+    return bundle_whole_size (osi, value, bytes, wholesize);
 
+  if (wholesize)
+    *wholesize = size_unknown (object_size_type);
   return size_unknown (object_size_type);
 }
 
@@ -1168,16 +1269,20 @@ expr_object_size (struct object_size_info *osi, tree value)
 /* Compute object_sizes for PTR, defined to the result of a call.  */
 
 static tree
-call_object_size (struct object_size_info *osi, gcall *call)
+call_object_size (struct object_size_info *osi, tree var, tree *wholesize)
 {
   int object_size_type = osi->object_size_type;
+  gcall *call = as_a <gcall *> (SSA_NAME_DEF_STMT (var));
 
   gcc_assert (is_gimple_call (call));
 
   tree bytes = alloc_object_size (call, object_size_type);
 
+  if (wholesize)
+    *wholesize = bytes;
+
   if (size_known_p (bytes, object_size_type))
-    return bytes;
+    return bundle_whole_size (osi, var, bytes, wholesize);
 
   return  size_unknown (object_size_type);
 }
@@ -1186,44 +1291,25 @@ call_object_size (struct object_size_info *osi, gcall *call)
 /* Compute object_sizes for PTR, defined to an unknown value.  */
 
 static tree
-unknown_object_size (struct object_size_info *osi)
+unknown_object_size (struct object_size_info *osi, tree *wholesize)
 {
   int object_size_type = osi->object_size_type;
+  if (wholesize)
+    *wholesize = size_unknown (object_size_type);
   return size_unknown (object_size_type);
 }
 
 
-/* Return object size of ORIG + OFFSET.  */
-
-static tree
-ssa_object_size (struct object_size_info *osi, tree orig, tree offset)
-{
-  int object_size_type = osi->object_size_type;
-  tree orig_bytes;
-
-  if (compare_tree_int (offset, offset_limit) >= 0)
-    return size_unknown (object_size_type);
-
-  collect_object_sizes_for (osi, orig);
-
-  orig_bytes = object_sizes_get (osi, SSA_NAME_VERSION (orig));
-  if (!size_unknown_p (orig_bytes, object_size_type)
-      && !integer_zerop (offset))
-    orig_bytes = size_for_offset (orig_bytes, offset);
-
-  return orig_bytes;
-}
-
-
 /* Compute object_sizes for VAR, defined to the result of an assignment
    with operator POINTER_PLUS_EXPR.  */
 
 static tree
-plus_stmt_object_size (struct object_size_info *osi, gimple *stmt)
+plus_stmt_object_size (struct object_size_info *osi, tree var, tree *wholesize)
 {
   int object_size_type = osi->object_size_type;
   tree bytes;
   tree op0, op1;
+  gimple *stmt = SSA_NAME_DEF_STMT (var);
 
   if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
     {
@@ -1240,29 +1326,24 @@ plus_stmt_object_size (struct object_size_info *osi, gimple *stmt)
   else
     gcc_unreachable ();
 
-  /* Handle PTR + OFFSET here.  */
-  if (TREE_CODE (op1) == INTEGER_CST
-      && (TREE_CODE (op0) == SSA_NAME
-	  || TREE_CODE (op0) == ADDR_EXPR))
-    {
-      if (TREE_CODE (op0) == SSA_NAME)
-	bytes = ssa_object_size (osi, op0, op1);
-      else
-	{
-          /* op0 will be ADDR_EXPR here.  */
-	  addr_object_size (osi, op0, object_size_type, &bytes);
-	  if (size_unknown_p (bytes, object_size_type))
-	    ;
-	  else if (compare_tree_int (op1, offset_limit) > 0)
-	    bytes = size_unknown (object_size_type);
-	  else if (!integer_zerop (op1))
-	    bytes = size_for_offset (bytes, op1);
-	}
-    }
+  if (!(object_size_type & OST_DYNAMIC)
+      && (TREE_CODE (op1) != INTEGER_CST
+	  || compare_tree_int (op1, offset_limit) > 0))
+    return size_unknown (object_size_type);
+
+  if (TREE_CODE (op0) == SSA_NAME)
+    bytes = collect_object_sizes_for (osi, op0, wholesize);
+  else if (TREE_CODE (op0) == ADDR_EXPR)
+    addr_object_size (osi, op0, object_size_type, &bytes, wholesize);
   else
     bytes = size_unknown (object_size_type);
 
-  return bytes;
+  if (!size_unknown_p (bytes, object_size_type))
+    bytes = size_for_offset (bytes, op1, wholesize ? *wholesize : NULL_TREE);
+  else if (wholesize)
+    *wholesize = size_unknown (object_size_type);
+
+  return bundle_whole_size (osi, var, bytes, wholesize);
 }
 
 
@@ -1270,34 +1351,48 @@ plus_stmt_object_size (struct object_size_info *osi, gimple *stmt)
    a COND_EXPR.  */
 
 static tree
-cond_expr_object_size (struct object_size_info *osi, gimple *stmt)
+cond_expr_object_size (struct object_size_info *osi, tree var, tree *wholesize)
 {
   tree then_, else_;
   int object_size_type = osi->object_size_type;
-  tree thenbytes, elsebytes;
+  tree thenbytes, elsebytes, thenwhole, elsewhole;
+  gimple *stmt = SSA_NAME_DEF_STMT (var);
 
   gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR);
 
+  if (!(object_size_type & OST_DYNAMIC))
+    wholesize = NULL;
+
   then_ = gimple_assign_rhs2 (stmt);
   else_ = gimple_assign_rhs3 (stmt);
 
   if (TREE_CODE (then_) == SSA_NAME)
-    thenbytes = ssa_object_size (osi, then_, size_int (0));
+    thenbytes = collect_object_sizes_for (osi, then_, wholesize);
   else
-    thenbytes = expr_object_size (osi, then_);
+    thenbytes = expr_object_size (osi, then_, wholesize);
+
+  thenwhole = wholesize ? *wholesize : NULL_TREE;
 
   if (TREE_CODE (else_) == SSA_NAME)
-    elsebytes = ssa_object_size (osi, else_, size_int (0));
+    elsebytes = collect_object_sizes_for (osi, else_, wholesize);
   else
-    elsebytes = expr_object_size (osi, else_);
+    elsebytes = expr_object_size (osi, else_, wholesize);
+
+  elsewhole = wholesize ? *wholesize : NULL_TREE;
 
   if (size_unknown_p (thenbytes, object_size_type)
       || size_unknown_p (elsebytes, object_size_type))
     return size_unknown (object_size_type);
 
   if (object_size_type & OST_DYNAMIC)
-    return fold_build3 (COND_EXPR, sizetype, gimple_assign_rhs1 (stmt),
-			thenbytes, elsebytes);
+    {
+      gcc_checking_assert (elsewhole && thenwhole);
+      *wholesize = fold_build3 (COND_EXPR, sizetype, gimple_assign_rhs1 (stmt),
+				thenwhole, elsewhole);
+      tree res = fold_build3 (COND_EXPR, sizetype, gimple_assign_rhs1 (stmt),
+			      thenbytes, elsebytes);
+      return bundle_whole_size (osi, var, res, wholesize);
+    }
 
   return size_binop (OST_TREE_CODE (object_size_type), thenbytes, elsebytes);
 }
@@ -1316,9 +1411,9 @@ phi_object_size (struct object_size_info *osi, gimple *stmt)
       tree phires;
 
       if (TREE_CODE (rhs) == SSA_NAME)
-	phires = ssa_object_size (osi, rhs, size_int (0));
+	phires = collect_object_sizes_for (osi, rhs);
       else
-	phires = expr_object_size (osi, rhs);
+	phires = expr_object_size (osi, rhs, NULL);
 
       res = size_binop (OST_TREE_CODE (object_size_type), res, phires);
 
@@ -1329,42 +1424,69 @@ phi_object_size (struct object_size_info *osi, gimple *stmt)
 }
 
 static tree
-phi_dynamic_object_size (struct object_size_info *osi, tree var)
+phi_dynamic_object_size (struct object_size_info *osi, tree var,
+			 tree *wholesize)
 {
   int object_size_type = osi->object_size_type;
   unsigned int varno = SSA_NAME_VERSION (var);
   gimple *stmt = SSA_NAME_DEF_STMT (var);
   unsigned i, num_args = gimple_phi_num_args (stmt);
-  tree res;
+  tree res, wholeres;
 
-  vec<tree> sizes;
+  vec<tree> sizes, wholesizes;
   sizes.create (0);
+  wholesizes.create (0);
   sizes.safe_grow (num_args);
+  wholesizes.safe_grow (num_args);
 
   /* Bail out if the size of any of the PHI arguments cannot be
      determined.  */
   for (i = 0; i < num_args; i++)
     {
       tree rhs = gimple_phi_arg_def (stmt, i);
-      tree sz;
+      tree sz, cur_whole;
 
       if (TREE_CODE (rhs) != SSA_NAME)
-	sz = expr_object_size (osi, rhs);
+	sz = expr_object_size (osi, rhs, &cur_whole);
       else
-	sz = ssa_object_size (osi, rhs, size_int (0));
+	sz = collect_object_sizes_for (osi, rhs, &cur_whole);
 
-      if (size_unknown_p (sz, object_size_type))
+      if (size_unknown_p (sz, object_size_type)
+	  || size_unknown_p (cur_whole, object_size_type))
 	break;
 
+      if (!is_gimple_variable (cur_whole)
+	  && TREE_CODE (cur_whole) != INTEGER_CST)
+	{
+	  tree tmp = make_ssa_name (sizetype);
+	  tmp = size_binop (MODIFY_EXPR, tmp, cur_whole);
+	  sz = size_binop (COMPOUND_EXPR, tmp, sz);
+	  cur_whole = tmp;
+	}
       sizes[i] = sz;
+      wholesizes[i] = cur_whole;
     }
 
   if (i == num_args)
     {
       res = make_or_get_tempsize (osi, varno);
+      wholeres = object_sizes_get (osi, varno, true);
+      if (TREE_CODE (wholeres) != SSA_NAME)
+	{
+	  gcc_checking_assert (TREE_CODE (wholeres) == INTEGER_CST);
+	  gcc_checking_assert (compare_tree_int (wholeres,
+						 initval (object_size_type))
+			       == 0);
+	  wholeres = make_ssa_name (sizetype);
+	}
+      else
+	/* We don't reexamine whole sizes on their own.  */
+	bitmap_clear_bit (osi->reexamine, SSA_NAME_VERSION (wholeres));
+
       bitmap_set_bit (osi->phiresults, SSA_NAME_VERSION (res));
       object_sizes_initialize (osi, SSA_NAME_VERSION (res), res);
 
+      gphi *wholephi = create_phi_node (wholeres, gimple_bb (stmt));
       gphi *phi = create_phi_node (res, gimple_bb (stmt));
       gphi *obj_phi =  as_a <gphi *> (stmt);
 
@@ -1377,6 +1499,11 @@ phi_dynamic_object_size (struct object_size_info *osi, tree var)
 	      sizes[i] = ssa;
 	    }
 
+	  /* We're guaranteed to get gimple variables for whole sizes through
+	     expr_object_size and collect_object_sizes_for.  */
+	  add_phi_arg (wholephi, wholesizes[i],
+		       gimple_phi_arg_edge (obj_phi, i),
+		       gimple_phi_arg_location (obj_phi, i));
 	  add_phi_arg (phi, sizes[i],
 		       gimple_phi_arg_edge (obj_phi, i),
 		       gimple_phi_arg_location (obj_phi, i));
@@ -1387,20 +1514,26 @@ phi_dynamic_object_size (struct object_size_info *osi, tree var)
 	  print_generic_expr (dump_file, var, dump_flags);
 	  fprintf (dump_file, ": PHI Node with result: ");
 	  print_gimple_stmt (dump_file, phi, dump_flags);
+	  fprintf (dump_file, " and wholephi: ");
+	  print_gimple_stmt (dump_file, wholephi, dump_flags);
 	}
+      *wholesize = wholeres;
     }
   else
-    res = size_unknown (object_size_type);
+    {
+      res = size_unknown (object_size_type);
+      *wholesize = size_unknown (object_size_type);
+    }
 
   sizes.release ();
-
+  wholesizes.release ();
   return res;
 }
 
 /* Find size of an object passed as a parameter to the function.  */
 
 static tree
-parm_object_size (struct object_size_info *osi, tree var)
+parm_object_size (struct object_size_info *osi, tree var, tree *wholesize)
 {
   int object_size_type = osi->object_size_type;
   tree parm = SSA_NAME_VAR (var);
@@ -1414,7 +1547,7 @@ parm_object_size (struct object_size_info *osi, tree var)
     }
 
   if (!(object_size_type & OST_DYNAMIC) || !POINTER_TYPE_P (TREE_TYPE (parm)))
-    return expr_object_size (osi, parm);
+    return expr_object_size (osi, parm, wholesize);
 
   /* Look for access attribute.  */
   rdwr_map rdwr_idx;
@@ -1422,6 +1555,7 @@ parm_object_size (struct object_size_info *osi, tree var)
   tree fndecl = cfun->decl;
   const attr_access *access = get_parm_access (rdwr_idx, parm, fndecl);
   tree typesize = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (parm)));
+  tree sz = NULL_TREE;
 
   if (access && access->sizarg != UINT_MAX)
     {
@@ -1436,17 +1570,21 @@ parm_object_size (struct object_size_info *osi, tree var)
 
       if (arg != NULL_TREE && INTEGRAL_TYPE_P (TREE_TYPE (arg)))
 	{
-	  tree sz = get_or_create_ssa_default_def (cfun, arg);
+	  sz = get_or_create_ssa_default_def (cfun, arg);
 	  if (sz != NULL_TREE)
 	    {
 	      sz = fold_convert (sizetype, sz);
 	      if (typesize)
 		sz = size_binop (MULT_EXPR, sz, typesize);
-	      return sz;
 	    }
 	}
     }
-  return size_unknown (object_size_type);
+  if (sz == NULL_TREE)
+    sz = size_unknown (object_size_type);
+
+  if (wholesize)
+    *wholesize = sz;
+  return bundle_whole_size (osi, var, sz, wholesize);
 }
 
 /* Compute object sizes for VAR.
@@ -1469,23 +1607,32 @@ parm_object_size (struct object_size_info *osi, tree var)
    Otherwise, object size is the maximum of object sizes of variables
    that it might be set to.  */
 
-static void
-collect_object_sizes_for (struct object_size_info *osi, tree var)
+static tree
+collect_object_sizes_for (struct object_size_info *osi, tree var,
+			  tree *wholesize)
 {
   int object_size_type = osi->object_size_type;
   unsigned int varno = SSA_NAME_VERSION (var);
+  tree res, wholeres = NULL_TREE;
   gimple *stmt;
-  tree res;
+
+  if ((object_size_type & OST_DYNAMIC) && !wholesize)
+    wholesize = &wholeres;
 
   if (bitmap_bit_p (computed[object_size_type], varno))
-    return;
+    {
+      if (wholesize)
+	*wholesize = object_sizes_get (osi, varno, true);
+      return object_sizes_get (osi, varno);
+    }
 
   /* We want to evaluate the self-referencing object only once.  */
   if (bitmap_set_bit (osi->visited, varno))
     {
       /* Initialize to 0 for maximum size and M1U for minimum size so that
 	 it gets immediately overridden.  */
-      object_sizes_initialize (osi, varno);
+      object_sizes_initialize (osi, varno, size_initval (object_size_type),
+			       object_size_type & OST_DYNAMIC);
     }
   else
     {
@@ -1497,6 +1644,19 @@ collect_object_sizes_for (struct object_size_info *osi, tree var)
 	  fprintf (dump_file, "\n");
 	}
       res = make_or_get_tempsize (osi, varno);
+      if (wholesize)
+	{
+	  tree tmp = object_sizes_get (osi, varno, true);
+	  if (TREE_CODE (tmp) == INTEGER_CST)
+	    *wholesize = make_tempsize (osi, varno);
+	  else
+	    {
+	      gcc_assert (TREE_CODE (res) == SSA_NAME
+			  && bitmap_bit_p (osi->reexamine,
+					   SSA_NAME_VERSION (tmp)));
+	      *wholesize = tmp;
+	    }
+	}
       goto out;
     }
 
@@ -1517,58 +1677,57 @@ collect_object_sizes_for (struct object_size_info *osi, tree var)
 	if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
 	    || (gimple_assign_rhs_code (stmt) == ADDR_EXPR
 		&& TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF))
-	  res = plus_stmt_object_size (osi, stmt);
+	  res = plus_stmt_object_size (osi, var, wholesize);
 	else if (gimple_assign_rhs_code (stmt) == COND_EXPR)
-	  res = cond_expr_object_size (osi, stmt);
+	  res = cond_expr_object_size (osi, var, wholesize);
 	else if (gimple_assign_single_p (stmt)
 		 || gimple_assign_unary_nop_p (stmt))
 	  {
 	    if (TREE_CODE (rhs) == SSA_NAME
 		&& POINTER_TYPE_P (TREE_TYPE (rhs)))
-	      res = ssa_object_size (osi, rhs, size_int (0));
+	      res = collect_object_sizes_for (osi, rhs, wholesize);
 	    else
-	       res = expr_object_size (osi, rhs);
+	       res = expr_object_size (osi, rhs, wholesize);
 	  }
 	else
-	  res = unknown_object_size (osi);
+	  res = unknown_object_size (osi, wholesize);
 	break;
       }
 
     case GIMPLE_CALL:
       {
-	gcall *call_stmt = as_a <gcall *> (stmt);
-	tree arg = pass_through_call (call_stmt);
+	tree arg = pass_through_call (as_a <gcall *> (stmt));
 	if (arg)
 	  {
 	    if (TREE_CODE (arg) == SSA_NAME
 		&& POINTER_TYPE_P (TREE_TYPE (arg)))
-	      res = ssa_object_size (osi, arg, size_int (0));
+	      res = collect_object_sizes_for (osi, arg, wholesize);
 	    else
-	      res = expr_object_size (osi, arg);
+	      res = expr_object_size (osi, arg, wholesize);
 	  }
 	else
-	  res = call_object_size (osi, call_stmt);
+	  res = call_object_size (osi, var, wholesize);
 	break;
       }
 
     case GIMPLE_ASM:
       /* Pointers defined by __asm__ statements can point anywhere.  */
-      res = size_unknown (object_size_type);
+      res = unknown_object_size (osi, wholesize);
       break;
 
     case GIMPLE_NOP:
       if (SSA_NAME_VAR (var)
 	  && TREE_CODE (SSA_NAME_VAR (var)) == PARM_DECL)
-	res = parm_object_size (osi, var);
+	res = parm_object_size (osi, var, wholesize);
       else
 	/* Uninitialized SSA names point nowhere.  */
-	res = size_unknown (object_size_type);
+	res = unknown_object_size (osi, wholesize);
       break;
 
     case GIMPLE_PHI:
       {
 	if (object_size_type & OST_DYNAMIC)
-	  res = phi_dynamic_object_size (osi, var);
+	  res = phi_dynamic_object_size (osi, var, wholesize);
 	else
 	  res = phi_object_size (osi, stmt);
 	break;
@@ -1578,16 +1737,26 @@ collect_object_sizes_for (struct object_size_info *osi, tree var)
       gcc_unreachable ();
     }
 
-  if ((object_size_type & OST_DYNAMIC)
-      && TREE_CODE (res) != INTEGER_CST && !is_gimple_variable (res))
+  res = bundle_whole_size (osi, var, res, wholesize);
+
+  if (wholesize)
+    gcc_checking_assert (TREE_CODE (*wholesize) == INTEGER_CST
+			 || is_gimple_variable (*wholesize));
+
+  if ((object_size_type & OST_DYNAMIC) && TREE_CODE (res) != INTEGER_CST
+      && !is_gimple_variable (res))
     {
       tree ssa = make_or_get_tempsize (osi, varno);
       object_sizes_initialize (osi, SSA_NAME_VERSION (ssa), res);
       res = ssa;
     }
+
   bitmap_set_bit (computed[object_size_type], varno);
 out:
   object_sizes_set (osi, varno, res);
+  if (object_size_type & OST_DYNAMIC)
+    object_sizes_set (osi, varno, *wholesize, true);
+  return res;
 }
 
 
@@ -1603,7 +1772,7 @@ init_object_sizes (void)
 
   for (object_size_type = 0; object_size_type < OST_END; object_size_type++)
     {
-      object_sizes_grow (object_size_type);
+      object_sizes_grow (object_size_type, object_size_type >= OST_DYNAMIC);
       computed[object_size_type] = BITMAP_ALLOC (NULL);
     }
 
@@ -1620,7 +1789,7 @@ fini_object_sizes (void)
 
   for (object_size_type = 0; object_size_type < OST_END; object_size_type++)
     {
-      object_sizes_release (object_size_type);
+      object_sizes_release (object_size_type, object_size_type >= OST_DYNAMIC);
       BITMAP_FREE (computed[object_size_type]);
     }
 }
-- 
2.31.1


  parent reply	other threads:[~2021-11-09 19:02 UTC|newest]

Thread overview: 97+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-09 19:01 [PATCH 00/10] __builtin_dynamic_object_size Siddhesh Poyarekar
2021-11-09 19:01 ` [PATCH 01/10] tree-object-size: Replace magic numbers with enums Siddhesh Poyarekar
2021-11-19 16:00   ` Jakub Jelinek
2021-11-09 19:01 ` [PATCH 02/10] tree-object-size: Abstract object_sizes array Siddhesh Poyarekar
2021-11-19 16:18   ` Jakub Jelinek
2021-11-19 16:53     ` Siddhesh Poyarekar
2021-11-09 19:01 ` [PATCH 03/10] tree-object-size: Use tree instead of HOST_WIDE_INT Siddhesh Poyarekar
2021-11-19 17:06   ` Jakub Jelinek
2021-11-19 19:01     ` Siddhesh Poyarekar
2021-11-19 19:16       ` Jakub Jelinek
2021-11-22  8:41         ` Richard Biener
2021-11-22 10:11       ` Siddhesh Poyarekar
2021-11-22 10:31         ` Jakub Jelinek
2021-11-22 12:00           ` Siddhesh Poyarekar
2021-11-22 12:31             ` Siddhesh Poyarekar
2021-11-22 12:32               ` Jakub Jelinek
2021-11-23 11:58                 ` Jakub Jelinek
2021-11-23 13:33                   ` Siddhesh Poyarekar
2021-11-09 19:01 ` [PATCH 04/10] tree-object-size: Single pass dependency loop resolution Siddhesh Poyarekar
2021-11-23 12:07   ` Jakub Jelinek
2021-11-23 13:44     ` Siddhesh Poyarekar
2021-11-23 14:22       ` Jakub Jelinek
2021-11-09 19:01 ` [PATCH 05/10] __builtin_dynamic_object_size: Recognize builtin Siddhesh Poyarekar
2021-11-23 12:41   ` Jakub Jelinek
2021-11-23 13:53     ` Siddhesh Poyarekar
2021-11-23 14:00       ` Jakub Jelinek
2021-11-09 19:01 ` [PATCH 06/10] tree-object-size: Support dynamic sizes in conditions Siddhesh Poyarekar
2021-11-23 15:12   ` Jakub Jelinek
2021-11-23 15:36     ` Siddhesh Poyarekar
2021-11-23 15:38       ` Siddhesh Poyarekar
2021-11-23 16:17         ` Jakub Jelinek
2021-11-23 15:52       ` Jakub Jelinek
2021-11-23 16:00         ` Siddhesh Poyarekar
2021-11-23 16:19           ` Jakub Jelinek
2021-11-09 19:01 ` [PATCH 07/10] tree-object-size: Handle function parameters Siddhesh Poyarekar
2021-11-09 19:01 ` [PATCH 08/10] tree-object-size: Handle GIMPLE_CALL Siddhesh Poyarekar
2021-11-09 19:01 ` [PATCH 09/10] tree-object-size: Dynamic sizes for ADDR_EXPR Siddhesh Poyarekar
2021-11-09 19:01 ` Siddhesh Poyarekar [this message]
2021-11-19 15:56 ` [PATCH 00/10] __builtin_dynamic_object_size Jakub Jelinek
2021-11-26  5:28 ` [PATCH v3 0/8] __builtin_dynamic_object_size Siddhesh Poyarekar
2021-11-26  5:28   ` [PATCH v3 1/8] tree-object-size: Replace magic numbers with enums Siddhesh Poyarekar
2021-11-26 16:46     ` Jakub Jelinek
2021-11-26 17:53       ` Siddhesh Poyarekar
2021-11-26 18:01         ` Jakub Jelinek
2021-11-26  5:28   ` [PATCH v3 2/8] tree-object-size: Abstract object_sizes array Siddhesh Poyarekar
2021-11-26 16:47     ` Jakub Jelinek
2021-11-26  5:28   ` [PATCH v3 3/8] tree-object-size: Save sizes as trees and support negative offsets Siddhesh Poyarekar
2021-11-26 16:56     ` Jakub Jelinek
2021-11-26 17:59       ` Siddhesh Poyarekar
2021-11-26 18:04         ` Jakub Jelinek
2021-11-26 18:07           ` Siddhesh Poyarekar
2021-11-26  5:28   ` [PATCH v3 4/8] __builtin_dynamic_object_size: Recognize builtin Siddhesh Poyarekar
2021-11-26  5:28   ` [PATCH v3 5/8] tree-object-size: Support dynamic sizes in conditions Siddhesh Poyarekar
2021-11-26  5:28   ` [PATCH v3 6/8] tree-object-size: Handle function parameters Siddhesh Poyarekar
2021-11-26  5:28   ` [PATCH v3 7/8] tree-object-size: Handle GIMPLE_CALL Siddhesh Poyarekar
2021-11-26  5:28   ` [PATCH v3 8/8] tree-object-size: Dynamic sizes for ADDR_EXPR Siddhesh Poyarekar
2021-11-26  5:38   ` [PATCH v3 0/8] __builtin_dynamic_object_size Siddhesh Poyarekar
2021-12-01 14:27 ` [PATCH v4 0/6] __builtin_dynamic_object_size Siddhesh Poyarekar
2021-12-01 14:27   ` [PATCH v4 1/6] tree-object-size: Use trees and support negative offsets Siddhesh Poyarekar
2021-12-15 15:21     ` Jakub Jelinek
2021-12-15 17:12       ` Siddhesh Poyarekar
2021-12-15 18:43         ` Jakub Jelinek
2021-12-16  0:41           ` Siddhesh Poyarekar
2021-12-16 15:49             ` Jakub Jelinek
2021-12-16 18:56               ` Siddhesh Poyarekar
2021-12-16 21:16                 ` Jakub Jelinek
2021-12-01 14:27   ` [PATCH v4 2/6] __builtin_dynamic_object_size: Recognize builtin Siddhesh Poyarekar
2021-12-15 15:24     ` Jakub Jelinek
2021-12-16  2:16       ` Siddhesh Poyarekar
2021-12-01 14:27   ` [PATCH v4 3/6] tree-object-size: Support dynamic sizes in conditions Siddhesh Poyarekar
2021-12-15 16:24     ` Jakub Jelinek
2021-12-15 17:56       ` Siddhesh Poyarekar
2021-12-15 18:52         ` Jakub Jelinek
2021-12-01 14:27   ` [PATCH v4 4/6] tree-object-size: Handle function parameters Siddhesh Poyarekar
2021-12-01 14:27   ` [PATCH v4 5/6] tree-object-size: Handle GIMPLE_CALL Siddhesh Poyarekar
2021-12-01 14:27   ` [PATCH v4 6/6] tree-object-size: Dynamic sizes for ADDR_EXPR Siddhesh Poyarekar
2021-12-18 12:35 ` [PATCH v5 0/4] __builtin_dynamic_object_size Siddhesh Poyarekar
2021-12-18 12:35   ` [PATCH v5 1/4] tree-object-size: Support dynamic sizes in conditions Siddhesh Poyarekar
2022-01-10 10:37     ` Jakub Jelinek
2022-01-10 23:55       ` Siddhesh Poyarekar
2021-12-18 12:35   ` [PATCH v5 2/4] tree-object-size: Handle function parameters Siddhesh Poyarekar
2022-01-10 10:50     ` Jakub Jelinek
2022-01-11  0:32       ` Siddhesh Poyarekar
2021-12-18 12:35   ` [PATCH v5 3/4] tree-object-size: Handle GIMPLE_CALL Siddhesh Poyarekar
2022-01-10 11:03     ` Jakub Jelinek
2021-12-18 12:35   ` [PATCH v5 4/4] tree-object-size: Dynamic sizes for ADDR_EXPR Siddhesh Poyarekar
2022-01-10 11:09     ` Jakub Jelinek
2022-01-04  3:24   ` [PING][PATCH v5 0/4] __builtin_dynamic_object_size Siddhesh Poyarekar
2022-01-11  8:57 ` [PATCH v6 " Siddhesh Poyarekar
2022-01-11  8:57   ` [PATCH v6 1/4] tree-object-size: Support dynamic sizes in conditions Siddhesh Poyarekar
2022-01-11  9:43     ` Jakub Jelinek
2022-01-11  9:44       ` Siddhesh Poyarekar
2022-01-11  8:57   ` [PATCH v6 2/4] tree-object-size: Handle function parameters Siddhesh Poyarekar
2022-01-11  9:44     ` Jakub Jelinek
2022-01-11  8:57   ` [PATCH v6 3/4] tree-object-size: Handle GIMPLE_CALL Siddhesh Poyarekar
2022-01-11  8:57   ` [PATCH v6 4/4] tree-object-size: Dynamic sizes for ADDR_EXPR Siddhesh Poyarekar
2022-01-11  9:47     ` Jakub Jelinek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211109190137.1107736-11-siddhesh@gotplt.org \
    --to=siddhesh@gotplt.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).