Commit 76bd29f6 by Jakub Jelinek Committed by Jakub Jelinek

re PR rtl-optimization/55717 (ICE in form_sum, at reload.c:5400)

	PR debug/55717
	* rtlhooks-def.h (RTL_HOOKS_GEN_LOWPART_NO_EMIT): Define to
	gen_lowpart_if_possible.
	(gen_lowpart_no_emit_general): Remove prototype.
	* rtlhooks.c (gen_lowpart_no_emit_general): Removed.
	* simplify-rtx.c (simplify_unary_operation_1, 
	simplify_binary_operation_1): Continue simplifying if
	rtl_hooks.gen_lowpart_no_emit returns NULL_RTX.
	* dwarf2out.c (mem_loc_descriptor) <case TRUNCATE>: Handle
	truncation like lowpart SUBREG.

	* testsuite/g++.dg/opt/pr55717.C: New test.

From-SVN: r194575
parent 07146f23
2012-12-18 Jakub Jelinek <jakub@redhat.com>
PR debug/55717
* rtlhooks-def.h (RTL_HOOKS_GEN_LOWPART_NO_EMIT): Define to
gen_lowpart_if_possible.
(gen_lowpart_no_emit_general): Remove prototype.
* rtlhooks.c (gen_lowpart_no_emit_general): Removed.
* simplify-rtx.c (simplify_unary_operation_1,
simplify_binary_operation_1): Continue simplifying if
rtl_hooks.gen_lowpart_no_emit returns NULL_RTX.
* dwarf2out.c (mem_loc_descriptor) <case TRUNCATE>: Handle
truncation like lowpart SUBREG.
2012-12-17 Gerald Pfeifer <gerald@pfeifer.com> 2012-12-17 Gerald Pfeifer <gerald@pfeifer.com>
* doc/contrib.texi (Contributors): Update Kaveh Ghazi's entry; * doc/contrib.texi (Contributors): Update Kaveh Ghazi's entry;
...@@ -11840,6 +11840,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, ...@@ -11840,6 +11840,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
dw_loc_descr_ref mem_loc_result = NULL; dw_loc_descr_ref mem_loc_result = NULL;
enum dwarf_location_atom op; enum dwarf_location_atom op;
dw_loc_descr_ref op0, op1; dw_loc_descr_ref op0, op1;
rtx inner = NULL_RTX;
if (mode == VOIDmode) if (mode == VOIDmode)
mode = GET_MODE (rtl); mode = GET_MODE (rtl);
...@@ -11869,35 +11870,39 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, ...@@ -11869,35 +11870,39 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
contains the given subreg. */ contains the given subreg. */
if (!subreg_lowpart_p (rtl)) if (!subreg_lowpart_p (rtl))
break; break;
inner = SUBREG_REG (rtl);
case TRUNCATE:
if (inner == NULL_RTX)
inner = XEXP (rtl, 0);
if (GET_MODE_CLASS (mode) == MODE_INT if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_CLASS (GET_MODE (SUBREG_REG (rtl))) == MODE_INT && GET_MODE_CLASS (GET_MODE (inner)) == MODE_INT
&& (GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE && (GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE
#ifdef POINTERS_EXTEND_UNSIGNED #ifdef POINTERS_EXTEND_UNSIGNED
|| (mode == Pmode && mem_mode != VOIDmode) || (mode == Pmode && mem_mode != VOIDmode)
#endif #endif
) )
&& GET_MODE_SIZE (GET_MODE (SUBREG_REG (rtl))) <= DWARF2_ADDR_SIZE) && GET_MODE_SIZE (GET_MODE (inner)) <= DWARF2_ADDR_SIZE)
{ {
mem_loc_result = mem_loc_descriptor (SUBREG_REG (rtl), mem_loc_result = mem_loc_descriptor (inner,
GET_MODE (SUBREG_REG (rtl)), GET_MODE (inner),
mem_mode, initialized); mem_mode, initialized);
break; break;
} }
if (dwarf_strict) if (dwarf_strict)
break; break;
if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (rtl)))) if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (inner)))
break; break;
if (GET_MODE_SIZE (mode) != GET_MODE_SIZE (GET_MODE (SUBREG_REG (rtl))) if (GET_MODE_SIZE (mode) != GET_MODE_SIZE (GET_MODE (inner))
&& (GET_MODE_CLASS (mode) != MODE_INT && (GET_MODE_CLASS (mode) != MODE_INT
|| GET_MODE_CLASS (GET_MODE (SUBREG_REG (rtl))) != MODE_INT)) || GET_MODE_CLASS (GET_MODE (inner)) != MODE_INT))
break; break;
else else
{ {
dw_die_ref type_die; dw_die_ref type_die;
dw_loc_descr_ref cvt; dw_loc_descr_ref cvt;
mem_loc_result = mem_loc_descriptor (SUBREG_REG (rtl), mem_loc_result = mem_loc_descriptor (inner,
GET_MODE (SUBREG_REG (rtl)), GET_MODE (inner),
mem_mode, initialized); mem_mode, initialized);
if (mem_loc_result == NULL) if (mem_loc_result == NULL)
break; break;
...@@ -11909,7 +11914,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, ...@@ -11909,7 +11914,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
break; break;
} }
if (GET_MODE_SIZE (mode) if (GET_MODE_SIZE (mode)
!= GET_MODE_SIZE (GET_MODE (SUBREG_REG (rtl)))) != GET_MODE_SIZE (GET_MODE (inner)))
cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0); cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
else else
cvt = new_loc_descr (DW_OP_GNU_reinterpret, 0, 0); cvt = new_loc_descr (DW_OP_GNU_reinterpret, 0, 0);
...@@ -12666,7 +12671,6 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, ...@@ -12666,7 +12671,6 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
break; break;
case COMPARE: case COMPARE:
case TRUNCATE:
/* In theory, we could implement the above. */ /* In theory, we could implement the above. */
/* DWARF cannot represent the unsigned compare operations /* DWARF cannot represent the unsigned compare operations
natively. */ natively. */
......
/* Default macros to initialize an rtl_hooks data structure. /* Default macros to initialize an rtl_hooks data structure.
Copyright 2004, 2005, 2007, 2008 Free Software Foundation, Inc. Copyright 2004, 2005, 2007, 2008, 2012 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "rtl.h" #include "rtl.h"
#define RTL_HOOKS_GEN_LOWPART gen_lowpart_general #define RTL_HOOKS_GEN_LOWPART gen_lowpart_general
#define RTL_HOOKS_GEN_LOWPART_NO_EMIT gen_lowpart_no_emit_general #define RTL_HOOKS_GEN_LOWPART_NO_EMIT gen_lowpart_if_possible
#define RTL_HOOKS_REG_NONZERO_REG_BITS reg_nonzero_bits_general #define RTL_HOOKS_REG_NONZERO_REG_BITS reg_nonzero_bits_general
#define RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES reg_num_sign_bit_copies_general #define RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES reg_num_sign_bit_copies_general
#define RTL_HOOKS_REG_TRUNCATED_TO_MODE reg_truncated_to_mode_general #define RTL_HOOKS_REG_TRUNCATED_TO_MODE reg_truncated_to_mode_general
...@@ -38,7 +38,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -38,7 +38,6 @@ along with GCC; see the file COPYING3. If not see
} }
extern rtx gen_lowpart_general (enum machine_mode, rtx); extern rtx gen_lowpart_general (enum machine_mode, rtx);
extern rtx gen_lowpart_no_emit_general (enum machine_mode, rtx);
extern rtx reg_nonzero_bits_general (const_rtx, enum machine_mode, const_rtx, extern rtx reg_nonzero_bits_general (const_rtx, enum machine_mode, const_rtx,
enum machine_mode, enum machine_mode,
unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
......
/* Generic hooks for the RTL middle-end. /* Generic hooks for the RTL middle-end.
Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011, 2012
Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -79,18 +80,6 @@ gen_lowpart_general (enum machine_mode mode, rtx x) ...@@ -79,18 +80,6 @@ gen_lowpart_general (enum machine_mode mode, rtx x)
} }
} }
/* Similar to gen_lowpart, but cannot emit any instruction via
copy_to_reg or force_reg. Mainly used in simplify-rtx.c. */
rtx
gen_lowpart_no_emit_general (enum machine_mode mode, rtx x)
{
rtx result = gen_lowpart_if_possible (mode, x);
if (result)
return result;
else
return x;
}
rtx rtx
reg_num_sign_bit_copies_general (const_rtx x ATTRIBUTE_UNUSED, reg_num_sign_bit_copies_general (const_rtx x ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
......
...@@ -873,7 +873,9 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) ...@@ -873,7 +873,9 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
simplify_gen_unary (NOT, inner_mode, const1_rtx, simplify_gen_unary (NOT, inner_mode, const1_rtx,
inner_mode), inner_mode),
XEXP (SUBREG_REG (op), 1)); XEXP (SUBREG_REG (op), 1));
return rtl_hooks.gen_lowpart_no_emit (mode, x); temp = rtl_hooks.gen_lowpart_no_emit (mode, x);
if (temp)
return temp;
} }
/* Apply De Morgan's laws to reduce number of patterns for machines /* Apply De Morgan's laws to reduce number of patterns for machines
...@@ -1029,7 +1031,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) ...@@ -1029,7 +1031,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
{ {
if (TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op))) if (TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op)))
return rtl_hooks.gen_lowpart_no_emit (mode, op); {
temp = rtl_hooks.gen_lowpart_no_emit (mode, op);
if (temp)
return temp;
}
/* We can't handle truncation to a partial integer mode here /* We can't handle truncation to a partial integer mode here
because we don't know the real bitsize of the partial because we don't know the real bitsize of the partial
integer mode. */ integer mode. */
...@@ -1048,7 +1054,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) ...@@ -1048,7 +1054,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
if (GET_MODE_NUNITS (mode) == 1 if (GET_MODE_NUNITS (mode) == 1
&& (TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op)) && (TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op))
|| truncated_to_mode (mode, op))) || truncated_to_mode (mode, op)))
return rtl_hooks.gen_lowpart_no_emit (mode, op); {
temp = rtl_hooks.gen_lowpart_no_emit (mode, op);
if (temp)
return temp;
}
/* A truncate of a comparison can be replaced with a subreg if /* A truncate of a comparison can be replaced with a subreg if
STORE_FLAG_VALUE permits. This is like the previous test, STORE_FLAG_VALUE permits. This is like the previous test,
...@@ -1057,7 +1067,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) ...@@ -1057,7 +1067,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
if (HWI_COMPUTABLE_MODE_P (mode) if (HWI_COMPUTABLE_MODE_P (mode)
&& COMPARISON_P (op) && COMPARISON_P (op)
&& (STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0) && (STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0)
return rtl_hooks.gen_lowpart_no_emit (mode, op); {
temp = rtl_hooks.gen_lowpart_no_emit (mode, op);
if (temp)
return temp;
}
/* A truncate of a memory is just loading the low part of the memory /* A truncate of a memory is just loading the low part of the memory
if we are not changing the meaning of the address. */ if we are not changing the meaning of the address. */
...@@ -1065,7 +1079,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) ...@@ -1065,7 +1079,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
&& !VECTOR_MODE_P (mode) && !VECTOR_MODE_P (mode)
&& !MEM_VOLATILE_P (op) && !MEM_VOLATILE_P (op)
&& !mode_dependent_address_p (XEXP (op, 0), MEM_ADDR_SPACE (op))) && !mode_dependent_address_p (XEXP (op, 0), MEM_ADDR_SPACE (op)))
return rtl_hooks.gen_lowpart_no_emit (mode, op); {
temp = rtl_hooks.gen_lowpart_no_emit (mode, op);
if (temp)
return temp;
}
break; break;
...@@ -1298,7 +1316,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) ...@@ -1298,7 +1316,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
&& SUBREG_PROMOTED_VAR_P (op) && SUBREG_PROMOTED_VAR_P (op)
&& ! SUBREG_PROMOTED_UNSIGNED_P (op) && ! SUBREG_PROMOTED_UNSIGNED_P (op)
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))) && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
return rtl_hooks.gen_lowpart_no_emit (mode, op); {
temp = rtl_hooks.gen_lowpart_no_emit (mode, op);
if (temp)
return temp;
}
/* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>). /* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>).
(sign_extend:M (zero_extend:N <X>)) is (zero_extend:M <X>). */ (sign_extend:M (zero_extend:N <X>)) is (zero_extend:M <X>). */
...@@ -1330,9 +1352,10 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) ...@@ -1330,9 +1352,10 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
{ {
rtx inner = rtx inner =
rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0)); rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0));
return simplify_gen_unary (GET_CODE (op) == ASHIFTRT if (inner)
? SIGN_EXTEND : ZERO_EXTEND, return simplify_gen_unary (GET_CODE (op) == ASHIFTRT
mode, inner, tmode); ? SIGN_EXTEND : ZERO_EXTEND,
mode, inner, tmode);
} }
} }
...@@ -1360,7 +1383,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) ...@@ -1360,7 +1383,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
&& SUBREG_PROMOTED_VAR_P (op) && SUBREG_PROMOTED_VAR_P (op)
&& SUBREG_PROMOTED_UNSIGNED_P (op) > 0 && SUBREG_PROMOTED_UNSIGNED_P (op) > 0
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))) && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
return rtl_hooks.gen_lowpart_no_emit (mode, op); {
temp = rtl_hooks.gen_lowpart_no_emit (mode, op);
if (temp)
return temp;
}
/* Extending a widening multiplication should be canonicalized to /* Extending a widening multiplication should be canonicalized to
a wider widening multiplication. */ a wider widening multiplication. */
...@@ -1425,7 +1452,8 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) ...@@ -1425,7 +1452,8 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
{ {
rtx inner = rtx inner =
rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0)); rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0));
return simplify_gen_unary (ZERO_EXTEND, mode, inner, tmode); if (inner)
return simplify_gen_unary (ZERO_EXTEND, mode, inner, tmode);
} }
} }
...@@ -3095,7 +3123,11 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, ...@@ -3095,7 +3123,11 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
} }
/* x/1 is x. */ /* x/1 is x. */
if (trueop1 == CONST1_RTX (mode)) if (trueop1 == CONST1_RTX (mode))
return rtl_hooks.gen_lowpart_no_emit (mode, op0); {
tem = rtl_hooks.gen_lowpart_no_emit (mode, op0);
if (tem)
return tem;
}
/* Convert divide by power of two into shift. */ /* Convert divide by power of two into shift. */
if (CONST_INT_P (trueop1) if (CONST_INT_P (trueop1)
&& (val = exact_log2 (UINTVAL (trueop1))) > 0) && (val = exact_log2 (UINTVAL (trueop1))) > 0)
...@@ -3154,12 +3186,17 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, ...@@ -3154,12 +3186,17 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
} }
/* x/1 is x. */ /* x/1 is x. */
if (trueop1 == CONST1_RTX (mode)) if (trueop1 == CONST1_RTX (mode))
return rtl_hooks.gen_lowpart_no_emit (mode, op0); {
tem = rtl_hooks.gen_lowpart_no_emit (mode, op0);
if (tem)
return tem;
}
/* x/-1 is -x. */ /* x/-1 is -x. */
if (trueop1 == constm1_rtx) if (trueop1 == constm1_rtx)
{ {
rtx x = rtl_hooks.gen_lowpart_no_emit (mode, op0); rtx x = rtl_hooks.gen_lowpart_no_emit (mode, op0);
return simplify_gen_unary (NEG, mode, x, mode); if (x)
return simplify_gen_unary (NEG, mode, x, mode);
} }
} }
break; break;
......
2012-12-18 Jakub Jelinek <jakub@redhat.com>
PR debug/55717
* testsuite/g++.dg/opt/pr55717.C: New test.
2012-12-17 Andrew Stubbs <ams@codesourcery.com> 2012-12-17 Andrew Stubbs <ams@codesourcery.com>
Ulrich Weigand <ulrich.weigand@linaro.org> Ulrich Weigand <ulrich.weigand@linaro.org>
......
// PR debug/55717
// { dg-do compile }
// { dg-options "-O -g" }
struct DebugOnly {};
template <class T>
struct StripConst { typedef T result; };
class TempAllocPolicy {};
template <class T>
class HashTableEntry
{
unsigned keyHash;
template <class, class, class>
friend class HashTable;
T t;
void setLive (unsigned hn) { keyHash = hn; }
};
template <class T, class HashPolicy, class>
struct HashTable
{
typedef typename HashPolicy::KeyType Key;
typedef typename HashPolicy::Lookup Lookup;
typedef HashTableEntry <T> Entry;
struct Range
{
Range () {}
Entry *cur, end;
bool empty () { return false; }
T front () { return T (); }
};
struct Enum : public Range
{
HashTable table;
bool removed;
template <class Map>
Enum (Map map) : Range (map.all ()), table (map.impl), removed () {}
void rekeyFront (Lookup l, Key)
{
T t = this->cur->t;
table.putNewInfallible (l, t);
}
void rekeyFront (Key k)
{
rekeyFront (k, k);
}
};
unsigned entryCount;
unsigned sCollisionBit;
unsigned prepareHash (Lookup l)
{
unsigned keyHash (HashPolicy::hash (l));
return keyHash & sCollisionBit;
}
static Entry *entryp;
Entry *findFreeEntry (unsigned) { return entryp; }
void putNewInfallible (Lookup l, T)
{
unsigned keyHash = prepareHash (l);
Entry *entry = findFreeEntry (keyHash);
entry->setLive (keyHash);
entryCount++;
}
};
template <class Key>
struct HashMapEntry { Key key; };
template <class Key, class Value, class HashPolicy = DebugOnly, class AllocPolicy = TempAllocPolicy>
struct HashMap
{
typedef HashMapEntry <Key> Entry;
struct MapHashPolicy : HashPolicy
{
typedef Key KeyType;
};
typedef HashTable <Entry, MapHashPolicy, AllocPolicy> Impl;
Impl impl;
typedef typename Impl::Range Range;
Range all () { return Range (); }
typedef typename Impl::Enum Enum;
};
class FreeOp;
struct AllocationSiteKey;
typedef HashMap <AllocationSiteKey, DebugOnly, AllocationSiteKey, TempAllocPolicy> AllocationSiteTable;
struct TypeCompartment
{
AllocationSiteTable *allocationSiteTable;
void sweep (FreeOp *);
};
struct JSScript { unsigned *code; };
bool IsScriptMarked (JSScript **);
struct AllocationSiteKey
{
JSScript *script;
unsigned offset : 24;
int kind;
typedef AllocationSiteKey Lookup;
static unsigned hash (AllocationSiteKey key) { return (long (key.script->code + key.offset)) ^ key.kind; }
};
void
TypeCompartment::sweep (FreeOp *)
{
for (AllocationSiteTable::Enum e (*allocationSiteTable); !e.empty ();)
{
AllocationSiteKey key = e.front ().key;
IsScriptMarked (&key.script);
e.rekeyFront (key);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment