--- gcc/dwarf2out.c.jj	2011-07-11 10:39:50.000000000 +0200
+++ gcc/dwarf2out.c	2011-07-11 14:38:07.000000000 +0200
@@ -10135,6 +10135,21 @@ multiple_reg_loc_descriptor (rtx rtl, rt
   return loc_result;
 }
 
+static unsigned long size_of_int_loc_descriptor (HOST_WIDE_INT);
+
+/* Return a location descriptor that designates a constant i,
+   as a compound operation from constant (i >> shift), constant shift
+   and DW_OP_shl.  */
+
+static dw_loc_descr_ref
+int_shift_loc_descriptor (HOST_WIDE_INT i, int shift)
+{
+  dw_loc_descr_ref ret = int_loc_descriptor (i >> shift);
+  add_loc_descr (&ret, int_loc_descriptor (shift));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_shl, 0, 0));
+  return ret;
+}
+
 /* Return a location descriptor that designates a constant.  */
 
 static dw_loc_descr_ref
@@ -10146,15 +10161,45 @@ int_loc_descriptor (HOST_WIDE_INT i)
      defaulting to the LEB encoding.  */
   if (i >= 0)
     {
+      int clz = clz_hwi (i);
+      int ctz = ctz_hwi (i);
       if (i <= 31)
 	op = (enum dwarf_location_atom) (DW_OP_lit0 + i);
       else if (i <= 0xff)
 	op = DW_OP_const1u;
       else if (i <= 0xffff)
 	op = DW_OP_const2u;
-      else if (HOST_BITS_PER_WIDE_INT == 32
-	       || i <= 0xffffffff)
+      else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 5
+	       && clz + 5 + 255 >= HOST_BITS_PER_WIDE_INT)
+	/* DW_OP_litX DW_OP_litY DW_OP_shl takes just 3 bytes and
+	   DW_OP_litX DW_OP_const1u Y DW_OP_shl takes just 4 bytes,
+	   while DW_OP_const4u is 5 bytes.  */
+	return int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT - clz - 5);
+      else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 8
+	       && clz + 8 + 31 >= HOST_BITS_PER_WIDE_INT)
+	/* DW_OP_const1u X DW_OP_litY DW_OP_shl takes just 4 bytes,
+	   while DW_OP_const4u is 5 bytes.  */
+	return int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT - clz - 8);
+      else if (HOST_BITS_PER_WIDE_INT == 32 || i <= 0xffffffff)
 	op = DW_OP_const4u;
+      else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 8
+	       && clz + 8 + 255 >= HOST_BITS_PER_WIDE_INT)
+	/* DW_OP_const1u X DW_OP_const1u Y DW_OP_shl takes just 5 bytes,
+	   while DW_OP_constu of constant >= 0x100000000 takes at least
+	   6 bytes.  */
+	return int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT - clz - 8);
+      else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 16
+	       && clz + 16 + (size_of_uleb128 (i) > 5 ? 255 : 31)
+		  >= HOST_BITS_PER_WIDE_INT)
+	/* DW_OP_const2u X DW_OP_litY DW_OP_shl takes just 5 bytes,
+	   DW_OP_const2u X DW_OP_const1u Y DW_OP_shl takes 6 bytes,
+	   while DW_OP_constu takes in this case at least 6 bytes.  */
+	return int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT - clz - 16);
+      else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 32
+	       && clz + 32 + 31 >= HOST_BITS_PER_WIDE_INT
+	       && size_of_uleb128 (i) > 6)
+	/* DW_OP_const4u X DW_OP_litY DW_OP_shl takes just 7 bytes.  */
+	return int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT - clz - 32);
       else
 	op = DW_OP_constu;
     }
@@ -10164,35 +10209,88 @@ int_loc_descriptor (HOST_WIDE_INT i)
 	op = DW_OP_const1s;
       else if (i >= -0x8000)
 	op = DW_OP_const2s;
-      else if (HOST_BITS_PER_WIDE_INT == 32
-	       || i >= -0x80000000)
-	op = DW_OP_const4s;
+      else if (HOST_BITS_PER_WIDE_INT == 32 || i >= -0x80000000)
+	{
+	  if (size_of_int_loc_descriptor (i) < 5)
+	    {
+	      dw_loc_descr_ref ret = int_loc_descriptor (-i);
+	      add_loc_descr (&ret, new_loc_descr (DW_OP_neg, 0, 0));
+	      return ret;
+	    }
+	  op = DW_OP_const4s;
+	}
       else
-	op = DW_OP_consts;
+	{
+	  if (size_of_int_loc_descriptor (i)
+	      < (unsigned long) 1 + size_of_sleb128 (i))
+	    {
+	      dw_loc_descr_ref ret = int_loc_descriptor (-i);
+	      add_loc_descr (&ret, new_loc_descr (DW_OP_neg, 0, 0));
+	      return ret;
+	    }
+	  op = DW_OP_consts;
+	}
     }
 
   return new_loc_descr (op, i, 0);
 }
 
+/* Return size_of_locs (int_shift_loc_descriptor (i, shift))
+   without actually allocating it.  */
+
+static unsigned long
+size_of_int_shift_loc_descriptor (HOST_WIDE_INT i, int shift)
+{
+  return size_of_int_loc_descriptor (i >> shift)
+	 + size_of_int_loc_descriptor (shift)
+	 + 1;
+}
+
 /* Return size_of_locs (int_loc_descriptor (i)) without
    actually allocating it.  */
 
 static unsigned long
 size_of_int_loc_descriptor (HOST_WIDE_INT i)
 {
+  unsigned long s;
+
   if (i >= 0)
     {
+      int clz, ctz;
       if (i <= 31)
 	return 1;
       else if (i <= 0xff)
 	return 2;
       else if (i <= 0xffff)
 	return 3;
-      else if (HOST_BITS_PER_WIDE_INT == 32
-	       || i <= 0xffffffff)
+      clz = clz_hwi (i);
+      ctz = ctz_hwi (i);
+      if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 5
+	  && clz + 5 + 255 >= HOST_BITS_PER_WIDE_INT)
+	return size_of_int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT
+						    - clz - 5);
+      else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 8
+	       && clz + 8 + 31 >= HOST_BITS_PER_WIDE_INT)
+	return size_of_int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT
+						    - clz - 8);
+      else if (HOST_BITS_PER_WIDE_INT == 32 || i <= 0xffffffff)
 	return 5;
+      s = size_of_uleb128 ((unsigned HOST_WIDE_INT) i);
+      if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 8
+	  && clz + 8 + 255 >= HOST_BITS_PER_WIDE_INT)
+	return size_of_int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT
+						    - clz - 8);
+      else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 16
+	       && clz + 16 + (s > 5 ? 255 : 31) >= HOST_BITS_PER_WIDE_INT)
+	return size_of_int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT
+						    - clz - 16);
+      else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 32
+	       && clz + 32 + 31 >= HOST_BITS_PER_WIDE_INT
+	       && s > 6)
+	return size_of_int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT
+						    - clz - 32);
       else
-	return 1 + size_of_uleb128 ((unsigned HOST_WIDE_INT) i);
+	return 1 + s;
     }
   else
     {
@@ -10200,11 +10298,27 @@ size_of_int_loc_descriptor (HOST_WIDE_IN
 	return 2;
       else if (i >= -0x8000)
 	return 3;
-      else if (HOST_BITS_PER_WIDE_INT == 32
-	       || i >= -0x80000000)
-	return 5;
+      else if (HOST_BITS_PER_WIDE_INT == 32 || i >= -0x80000000)
+	{
+	  if (-(unsigned HOST_WIDE_INT) i != (unsigned HOST_WIDE_INT) i)
+	    {
+	      s = size_of_int_loc_descriptor (-i) + 1;
+	      if (s < 5)
+		return s;
+	    }
+	  return 5;
+	}
       else
-	return 1 + size_of_sleb128 (i);
+	{
+	  unsigned long r = 1 + size_of_sleb128 (i);
+	  if (-(unsigned HOST_WIDE_INT) i != (unsigned HOST_WIDE_INT) i)
+	    {
+	      s = size_of_int_loc_descriptor (-i) + 1;
+	      if (s < r)
+		return s;
+	    }
+	  return r;
+	}
     }
 }
 
@@ -11818,8 +11932,27 @@ mem_loc_descriptor (rtx rtl, enum machin
 	      || GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT))
 	{
 	  dw_die_ref type_die = base_type_for_mode (mode, 1);
+	  enum machine_mode amode;
 	  if (type_die == NULL)
 	    return NULL;
+	  amode = mode_for_size (DWARF2_ADDR_SIZE * BITS_PER_UNIT,
+				 MODE_INT, 0);
+	  if (INTVAL (rtl) >= 0
+	      && amode != BLKmode
+	      && trunc_int_for_mode (INTVAL (rtl), amode) == INTVAL (rtl)
+	      /* const DW_OP_GNU_convert <XXX> vs.
+		 DW_OP_GNU_const_type <XXX, 1, const>.  */
+	      && size_of_int_loc_descriptor (INTVAL (rtl)) + 1 + 1
+		 < (unsigned long) 1 + 1 + 1 + GET_MODE_SIZE (mode))
+	    {
+	      mem_loc_result = int_loc_descriptor (INTVAL (rtl));
+	      op0 = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+	      op0->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+	      op0->dw_loc_oprnd1.v.val_die_ref.die = type_die;
+	      op0->dw_loc_oprnd1.v.val_die_ref.external = 0;
+	      add_loc_descr (&mem_loc_result, op0);
+	      return mem_loc_result;
+	    }
 	  mem_loc_result = new_loc_descr (DW_OP_GNU_const_type, 0,
 					  INTVAL (rtl));
 	  mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
@@ -20962,6 +21095,19 @@ resolve_addr_in_expr (dw_loc_descr_ref l
 	    && resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL))
 	  return false;
 	break;
+      case DW_OP_plus_uconst:
+	if (size_of_loc_descr (loc)
+	    > size_of_int_loc_descriptor (loc->dw_loc_oprnd1.v.val_unsigned)
+	      + 1
+	    && loc->dw_loc_oprnd1.v.val_unsigned > 0)
+	  {
+	    dw_loc_descr_ref repl
+	      = int_loc_descriptor (loc->dw_loc_oprnd1.v.val_unsigned);
+	    add_loc_descr (&repl, new_loc_descr (DW_OP_plus, 0, 0));
+	    add_loc_descr (&repl, loc->dw_loc_next);
+	    *loc = *repl;
+	  }
+	break;
       case DW_OP_implicit_value:
 	if (loc->dw_loc_oprnd2.val_class == dw_val_class_addr
 	    && resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL))
--- gcc/testsuite/gcc.dg/guality/csttest.c.jj	2011-07-11 13:55:12.000000000 +0200
+++ gcc/testsuite/gcc.dg/guality/csttest.c	2011-07-11 14:20:00.000000000 +0200
@@ -0,0 +1,63 @@
+/* PR debug/49676 */
+/* { dg-do run { target lp64 } } */
+/* { dg-options "-g" } */
+
+volatile int v;
+
+__attribute__((noinline, noclone))
+unsigned long long
+foo (unsigned long long x)
+{
+  unsigned long long a = x * (0x17ULL << 31);	/* { dg-final { gdb-test 29 "a" "(0x17ULL << 31)" } } */
+  unsigned long long b = x * (0x7ULL << 33);	/* { dg-final { gdb-test 29 "b" "(0x7ULL << 33)" } } */
+  unsigned long long c = x * (0x1ULL << 35);	/* { dg-final { gdb-test 29 "c" "(0x1ULL << 35)" } } */
+  unsigned long long d = x * (0x17ULL << 15);	/* { dg-final { gdb-test 29 "d" "(0x17ULL << 15)" } } */
+  unsigned long long e = x * (0x17ULL << 50);	/* { dg-final { gdb-test 29 "e" "(0x17ULL << 50)" } } */
+  unsigned long long f = x * (0x37ULL << 31);	/* { dg-final { gdb-test 29 "f" "(0x37ULL << 31)" } } */
+  unsigned long long g = x * (0x37ULL << 50);	/* { dg-final { gdb-test 29 "g" "(0x37ULL << 50)" } } */
+  unsigned long long h = x * (0x1efULL << 33);	/* { dg-final { gdb-test 29 "h" "(0x1efULL << 33)" } } */
+  unsigned long long i = x * (0x1efULL << 50);	/* { dg-final { gdb-test 29 "i" "(0x1efULL << 50)" } } */
+  unsigned long long j = x * -(0x17ULL << 31);	/* { dg-final { gdb-test 29 "j" "-(0x17ULL << 31)" } } */
+  unsigned long long k = x * -(0x7ULL << 33);	/* { dg-final { gdb-test 29 "k" "-(0x7ULL << 33)" } } */
+  unsigned long long l = x * -(0x1ULL << 35);	/* { dg-final { gdb-test 29 "l" "-(0x1ULL << 35)" } } */
+  unsigned long long m = x * -(0x17ULL << 15);	/* { dg-final { gdb-test 29 "m" "-(0x17ULL << 15)" } } */
+  unsigned long long n = x * -(0x17ULL << 50);	/* { dg-final { gdb-test 29 "n" "-(0x17ULL << 50)" } } */
+  unsigned long long o = x * -(0x37ULL << 31);	/* { dg-final { gdb-test 29 "o" "-(0x37ULL << 31)" } } */
+  unsigned long long p = x * -(0x37ULL << 50);	/* { dg-final { gdb-test 29 "p" "-(0x37ULL << 50)" } } */
+  unsigned long long q = x * -(0x1efULL << 33);	/* { dg-final { gdb-test 29 "q" "-(0x1efULL << 33)" } } */
+  unsigned long long r = x * -(0x1efULL << 50);	/* { dg-final { gdb-test 29 "r" "-(0x1efULL << 50)" } } */
+  v++;
+  return x;
+}
+
+__attribute__((noinline, noclone))
+unsigned long long
+bar (unsigned long long x)
+{
+  unsigned long long a = (x & 255) + (0x17ULL << 31);	/* { dg-final { gdb-test 55 "a" "(0x17ULL << 31)" } } */
+  unsigned long long b = (x & 255) + (0x7ULL << 33);	/* { dg-final { gdb-test 55 "b" "(0x7ULL << 33)" } } */
+  unsigned long long c = (x & 255) + (0x1ULL << 35);	/* { dg-final { gdb-test 55 "c" "(0x1ULL << 35)" } } */
+  unsigned long long d = (x & 255) + (0x17ULL << 15);	/* { dg-final { gdb-test 55 "d" "(0x17ULL << 15)" } } */
+  unsigned long long e = (x & 255) + (0x17ULL << 50);	/* { dg-final { gdb-test 55 "e" "(0x17ULL << 50)" } } */
+  unsigned long long f = (x & 255) + (0x37ULL << 31);	/* { dg-final { gdb-test 55 "f" "(0x37ULL << 31)" } } */
+  unsigned long long g = (x & 255) + (0x37ULL << 50);	/* { dg-final { gdb-test 55 "g" "(0x37ULL << 50)" } } */
+  unsigned long long h = (x & 255) + (0x1efULL << 33);	/* { dg-final { gdb-test 55 "h" "(0x1efULL << 33)" } } */
+  unsigned long long i = (x & 255) + (0x1efULL << 50);	/* { dg-final { gdb-test 55 "i" "(0x1efULL << 50)" } } */
+  unsigned long long j = (x & 255) + -(0x17ULL << 31);	/* { dg-final { gdb-test 55 "j" "-(0x17ULL << 31)" } } */
+  unsigned long long k = (x & 255) + -(0x7ULL << 33);	/* { dg-final { gdb-test 55 "k" "-(0x7ULL << 33)" } } */
+  unsigned long long l = (x & 255) + -(0x1ULL << 35);	/* { dg-final { gdb-test 55 "l" "-(0x1ULL << 35)" } } */
+  unsigned long long m = (x & 255) + -(0x17ULL << 15);	/* { dg-final { gdb-test 55 "m" "-(0x17ULL << 15)" } } */
+  unsigned long long n = (x & 255) + -(0x17ULL << 50);	/* { dg-final { gdb-test 55 "n" "-(0x17ULL << 50)" } } */
+  unsigned long long o = (x & 255) + -(0x37ULL << 31);	/* { dg-final { gdb-test 55 "o" "-(0x37ULL << 31)" } } */
+  unsigned long long p = (x & 255) + -(0x37ULL << 50);	/* { dg-final { gdb-test 55 "p" "-(0x37ULL << 50)" } } */
+  unsigned long long q = (x & 255) + -(0x1efULL << 33);	/* { dg-final { gdb-test 55 "q" "-(0x1efULL << 33)" } } */
+  unsigned long long r = (x & 255) + -(0x1efULL << 50);	/* { dg-final { gdb-test 55 "r" "-(0x1efULL << 50)" } } */
+  v++;
+  return x;
+}
+
+int
+main ()
+{
+  return foo (1) + bar (256) - 257;
+}
