This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR target/34403
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 10 Dec 2007 21:17:40 +0100
- Subject: [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 ();
}