[PATCH] Optimize NE/EQ comparisons of narrow integer types in debug info (PR debug/49676)

Jakub Jelinek jakub@redhat.com
Fri Jul 8 21:49:00 GMT 2011


Hi!

E.g. on
   extern void d (int);
   void __attribute__((noinline, noclone))
   self (int i)
   {
     if (i == 200)
       self (i + 1);
     else
       d (i + 2);
   }
this patch saves two bytes in the location description of the call site
value where we have a SImode comparison with 200, by emitting
DW_OP_const4u 0xffffffff DW_OP_and DW_OP_const1u 200 DW_OP_ne
instead of
DW_OP_const1u 32 DW_OP_shl DW_OP_constu (200LL << 32) DW_OP_ne
For EQ/NE it really doesn't matter if we do the comparison with sign
extended or zero extended values, so if doing it zero-extended
is shorter, let's do it that way.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2011-07-08  Jakub Jelinek  <jakub@redhat.com>

	PR debug/49676
	* dwarf2out.c (size_of_int_loc_descriptor): New function.
	(address_of_int_loc_descriptor): Use it.
	(scompare_loc_descriptor): Optimize EQ/NE comparison with
	constant.

--- gcc/dwarf2out.c.jj	2011-07-08 15:09:38.000000000 +0200
+++ gcc/dwarf2out.c	2011-07-08 17:19:38.000000000 +0200
@@ -10848,44 +10848,53 @@ int_loc_descriptor (HOST_WIDE_INT i)
   return new_loc_descr (op, i, 0);
 }
 
-/* Return loc description representing "address" of integer value.
-   This can appear only as toplevel expression.  */
+/* Return size_of_locs (int_loc_descriptor (i)) without
+   actually allocating it.  */
 
-static dw_loc_descr_ref
-address_of_int_loc_descriptor (int size, HOST_WIDE_INT i)
+static unsigned long
+size_of_int_loc_descriptor (HOST_WIDE_INT i)
 {
-  int litsize;
-  dw_loc_descr_ref loc_result = NULL;
-
-  if (!(dwarf_version >= 4 || !dwarf_strict))
-    return NULL;
-
   if (i >= 0)
     {
       if (i <= 31)
-	litsize = 1;
+	return 1;
       else if (i <= 0xff)
-	litsize = 2;
+	return 2;
       else if (i <= 0xffff)
-	litsize = 3;
+	return 3;
       else if (HOST_BITS_PER_WIDE_INT == 32
 	       || i <= 0xffffffff)
-	litsize = 5;
+	return 5;
       else
-	litsize = 1 + size_of_uleb128 ((unsigned HOST_WIDE_INT) i);
+	return 1 + size_of_uleb128 ((unsigned HOST_WIDE_INT) i);
     }
   else
     {
       if (i >= -0x80)
-	litsize = 2;
+	return 2;
       else if (i >= -0x8000)
-	litsize = 3;
+	return 3;
       else if (HOST_BITS_PER_WIDE_INT == 32
 	       || i >= -0x80000000)
-	litsize = 5;
+	return 5;
       else
-	litsize = 1 + size_of_sleb128 (i);
+	return 1 + size_of_sleb128 (i);
     }
+}
+
+/* Return loc description representing "address" of integer value.
+   This can appear only as toplevel expression.  */
+
+static dw_loc_descr_ref
+address_of_int_loc_descriptor (int size, HOST_WIDE_INT i)
+{
+  int litsize;
+  dw_loc_descr_ref loc_result = NULL;
+
+  if (!(dwarf_version >= 4 || !dwarf_strict))
+    return NULL;
+
+  litsize = size_of_int_loc_descriptor (i);
   /* Determine if DW_OP_stack_value or DW_OP_implicit_value
      is more compact.  For DW_OP_stack_value we need:
      litsize + 1 (DW_OP_stack_value)
@@ -11284,6 +11293,28 @@ scompare_loc_descriptor (enum dwarf_loca
 		  && (unsigned HOST_WIDE_INT) INTVAL (XEXP (rtl, 1))
 		     == (INTVAL (XEXP (rtl, 1)) & GET_MODE_MASK (op_mode)))))
 	return compare_loc_descriptor (op, op0, op1);
+
+      /* EQ/NE comparison against constant in narrower type than
+	 DWARF2_ADDR_SIZE can be performed either as
+	 DW_OP_const1u <shift> DW_OP_shl DW_OP_const* <cst << shift>
+	 DW_OP_{eq,ne}
+	 or
+	 DW_OP_const*u <mode_mask> DW_OP_and DW_OP_const* <cst & mode_mask>
+	 DW_OP_{eq,ne}.  Pick whatever is shorter.  */
+      if (CONST_INT_P (XEXP (rtl, 1))
+	  && GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT
+	  && (size_of_int_loc_descriptor (shift) + 1
+	      + size_of_int_loc_descriptor (INTVAL (XEXP (rtl, 1)) << shift)
+	      >= size_of_int_loc_descriptor (GET_MODE_MASK (op_mode)) + 1
+		 + size_of_int_loc_descriptor (INTVAL (XEXP (rtl, 1))
+					       & GET_MODE_MASK (op_mode))))
+	{
+	  add_loc_descr (&op0, int_loc_descriptor (GET_MODE_MASK (op_mode)));
+	  add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
+	  op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1))
+				    & GET_MODE_MASK (op_mode));
+	  return compare_loc_descriptor (op, op0, op1);
+	}
     }
   add_loc_descr (&op0, int_loc_descriptor (shift));
   add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0));

	Jakub



More information about the Gcc-patches mailing list