This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR target/34403


This is a regression present on the mainline.  The ICE triggered by the 
attached C++ testcase can be reproduced with

void foo(char *dest, char *src)
{
  __builtin_memcpy (dest, src, 0xfffffffc);
}

pr34403.c: In function 'foo':
pr34403.c:4: error: verify_flow_info: Wrong frequency of block 7 -1247
pr34403.c:4: error: verify_flow_info: Wrong frequency of block 6 -2248
pr34403.c:4: error: verify_flow_info: Wrong probability of edge 5->5 12499
pr34403.c:4: error: verify_flow_info: Wrong probability of edge 5->6 -2499
pr34403.c:4: internal compiler error: verify_flow_info failed
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.


The problem stems from the new string operation code in the i386 back-end, 
more specifically:

static void
expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
			       rtx destptr, rtx srcptr, rtx value,
			       rtx count, enum machine_mode mode, int unroll,
			       int expected_size)
[...]

  if (expected_size != -1)
    {
      expected_size /= GET_MODE_SIZE (mode) * unroll;
      if (expected_size == 0)
	predict_jump (0);
      else if (expected_size > REG_BR_PROB_BASE)
	predict_jump (REG_BR_PROB_BASE - 1);
      else
        predict_jump (REG_BR_PROB_BASE - (REG_BR_PROB_BASE + expected_size / 
2) / expected_size);
    }
  else
    predict_jump (REG_BR_PROB_BASE * 80 / 100);

because expected_size is negative here.


We could skip the prediction in this case, but then the compiler emits a loop 
whose counter overflows at runtime, so I think that the safest solution is to 
punt and to emit a call to memcpy instead.

Tested on i586-suse-linux, OK for mainline?


2007-12-10  Eric Botcazou  <ebotcazou@libertysurf.fr>

	PR target/34403
	* config/i386/i386.c (ix86_expand_movmem): Punt if the count is large.
	(ix86_expand_setmem): Likewise.


2007-12-10  Eric Botcazou  <ebotcazou@libertysurf.fr>

	* g++.dg/opt/memcpy1.C: New test.


-- 
Eric Botcazou
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 130706)
+++ config/i386/i386.c	(working copy)
@@ -15279,7 +15279,7 @@ smallest_pow2_greater_than (int val)
 }
 
 /* Expand string move (memcpy) operation.  Use i386 string operations when
-   profitable.  expand_clrmem contains similar code. The code depends upon
+   profitable.  expand_setmem contains similar code.  The code depends upon
    architecture, block size and alignment, but always has the same
    overall structure:
 
@@ -15330,6 +15330,10 @@ ix86_expand_movmem (rtx dst, rtx src, rt
   if (CONST_INT_P (expected_size_exp) && count == 0)
     expected_size = INTVAL (expected_size_exp);
 
+  /* Make sure we don't need to care about overflow later on.  */
+  if (count > ((unsigned HOST_WIDE_INT) 1 << 30))
+    return 0;
+
   /* Step 0: Decide on preferred algorithm, desired alignment and
      size of chunks to be copied by main loop.  */
 
@@ -15654,6 +15658,10 @@ ix86_expand_setmem (rtx dst, rtx count_e
   if (CONST_INT_P (expected_size_exp) && count == 0)
     expected_size = INTVAL (expected_size_exp);
 
+  /* Make sure we don't need to care about overflow later on.  */
+  if (count > ((unsigned HOST_WIDE_INT) 1 << 30))
+    return 0;
+
   /* Step 0: Decide on preferred algorithm, desired alignment and
      size of chunks to be copied by main loop.  */
 
// PR target/34403
// Origin: Martin Michlmayr <tbm@cyrius.com>

// { dg-do compile }
// { dg-options "-O" }

typedef unsigned char uint8_t;
typedef uint8_t uint8;
typedef long unsigned int size_t;
class csVector2
{
public:float x;
};
class csBox2
{
};
struct iBase
{
};
struct iClipper2D:public virtual iBase
{
};
template < class Class > class scfImplementation:public virtual iBase
{
};
template < class Class, class I1 > class scfImplementation1:public
scfImplementation < Class >,
  public I1
{
};
class csClipper:public scfImplementation1 < csClipper, iClipper2D >
{
};
class csBoxClipper:public csClipper
{
  csBox2 region;
  virtual uint8 Clip (csVector2 * InPolygon, size_t InCount,
                      csVector2 * OutPolygon, size_t & OutCount);
};
struct StatusOutputNone
{
};
namespace CS
{
  template < typename BoxTest, typename StatusOutput > class BoxClipper
  {
    BoxTest boxTest;
    StatusOutput statOut;
    const csBox2 & region;
    csVector2 *InP;
    size_t InV;
    csVector2 *OutP;
    size_t OutV;
  public:  BoxClipper (const BoxTest & boxTest, const StatusOutput & statOut,
                  const csBox2 & region, csVector2 * InP, size_t InV,
                  csVector2 * OutP):boxTest (boxTest), statOut (statOut),
      region (region), InP (InP), InV (InV), OutP (OutP), OutV (-1)
    {
    }
    uint8 Clip ()
    {
      __builtin_memcpy (this->OutP, InP, OutV * sizeof (csVector2));
    }
  };
}
struct BoxTestAll
{
};
uint8
csBoxClipper::Clip (csVector2 * InPolygon, size_t InCount,
                    csVector2 * OutPolygon, size_t & OutCount)
{
  BoxTestAll b;
  StatusOutputNone n;
  CS::BoxClipper < BoxTestAll, StatusOutputNone > boxClip (b, n, region,
                                                           InPolygon, InCount,
                                                           OutPolygon);
  uint8 Clipped = boxClip.Clip ();
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]