This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fixing addressof bug.
- To: egcs-patches at cygnus dot com
- Subject: Fixing addressof bug.
- From: Vladimir Makarov <vmakarov at cygnus dot com>
- Date: Wed, 5 May 1999 16:39:27 -0400
For the following C++ code
extern void traceIt ( const char *, ...);
class Class1 {
public:
char num;
char inst;
};
class GblTable {
public:
void getInfo (Class1 lpId);
};
extern GblTable& lp;
extern Class1 ttt;
void getInfo (Class1 lpId);
void crapIt()
{
Class1 whatzit = ttt;
if (whatzit.num > 10)
{
return;
}
lp.getInfo( whatzit );
traceIt ( "string2", whatzit.num ) ;
}
Gcc for i960 generates after the first CSE for whatzit.num:
(insn 15 14 16 (set (reg:SI 44)
(lshiftrt:SI (reg:SI 45)
(const_int 24 [0x18]))) 149 {lshrsi3} (nil)
(expr_list:REG_EQUAL (zero_extend:SI (mem/s:QI (addressof:SI (reg/v:HI 46) 43) 0))
(nil)))
(mem/s:HI (addressof:SI (reg/v:HI 46) 43) 0) is only present in RTL
and there are no other occurences (mem/s:QI (addressof:SI (reg/v:HI
46) 43) 0)). Therefore GCC cannot change (mem/s:QI (addressof:SI
(reg/v:HI 46) 43) 0)) in the note and make abort. The following patch
solves the problem and also improve code for changing addressof in
notes. The patch has been commited into egcs repository.
Wed May 5 16:26:13 1999 Vladimir Makarov <vmakarov@tofu.to.cygnus.com>
* function.c (purge_addressof_replacements): Rename into
purge_bitfield_addressof_replacements.
(purge_addressof_replacements): New variable.
(purge_addressof_1): Add code for changing addressof in notes for
field values which are extracted by usage MEM with narrower mode.
(purge_addressof): Initialize purge_bitfield_addressof_replacements.
Index: function.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/function.c,v
retrieving revision 1.89
retrieving revision 1.90
diff -p -c -r1.89 -r1.90
*** function.c 1999/04/26 22:51:05 1.89
--- function.c 1999/05/05 13:30:51 1.90
*************** put_addressof_into_stack (r, ht)
*** 3031,3036 ****
--- 3031,3044 ----
/* List of replacements made below in purge_addressof_1 when creating
bitfield insertions. */
+ static rtx purge_bitfield_addressof_replacements;
+
+ /* List of replacements made below in purge_addressof_1 for patterns
+ (MEM (ADDRESSOF (REG ...))). The key of the list entry is the
+ corresponding (ADDRESSOF (REG ...)) and value is a substitution for
+ the all pattern. List PURGE_BITFIELD_ADDRESSOF_REPLACEMENTS is not
+ enough in complex cases, e.g. when some field values can be
+ extracted by usage MEM with narrower mode. */
static rtx purge_addressof_replacements;
/* Helper function for purge_addressof. See if the rtx expression at *LOC
*************** purge_addressof_1 (loc, insn, force, sto
*** 3110,3160 ****
was replaced by. */
rtx tem;
! for (tem = purge_addressof_replacements; tem != NULL_RTX;
tem = XEXP (XEXP (tem, 1), 1))
! {
! rtx y = XEXP (tem, 0);
! if (GET_CODE (y) == MEM
! && rtx_equal_p (XEXP (x, 0), XEXP (y, 0)))
! {
! /* It can happen that the note may speak of things in
! a wider (or just different) mode than the code did.
! This is especially true of REG_RETVAL. */
!
! rtx z = XEXP (XEXP (tem, 1), 0);
! if (GET_MODE (x) != GET_MODE (y))
! {
! if (GET_CODE (z) == SUBREG && SUBREG_WORD (z) == 0)
! z = SUBREG_REG (z);
!
! /* ??? If we'd gotten into any of the really complex
! cases below, I'm not sure we can do a proper
! replacement. Might we be able to delete the
! note in some cases? */
! if (GET_MODE_SIZE (GET_MODE (x))
! < GET_MODE_SIZE (GET_MODE (y)))
! abort ();
!
! if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
! && (GET_MODE_SIZE (GET_MODE (x))
! > GET_MODE_SIZE (GET_MODE (z))))
! {
! /* This can occur as a result in invalid
! pointer casts, e.g. float f; ...
! *(long long int *)&f.
! ??? We could emit a warning here, but
! without a line number that wouldn't be
! very helpful. */
! z = gen_rtx_SUBREG (GET_MODE (x), z, 0);
! }
! else
! z = gen_lowpart (GET_MODE (x), z);
! }
!
! *loc = z;
! return;
! }
! }
/* There should always be such a replacement. */
abort ();
--- 3118,3171 ----
was replaced by. */
rtx tem;
! for (tem = purge_bitfield_addressof_replacements;
! tem != NULL_RTX;
tem = XEXP (XEXP (tem, 1), 1))
! if (rtx_equal_p (x, XEXP (tem, 0)))
! {
! *loc = XEXP (XEXP (tem, 1), 0);
! return;
! }
!
! /* See comment for purge_addressof_replacements. */
! for (tem = purge_addressof_replacements;
! tem != NULL_RTX;
! tem = XEXP (XEXP (tem, 1), 1))
! if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
! {
! rtx z = XEXP (XEXP (tem, 1), 0);
!
! if (GET_MODE (x) == GET_MODE (z)
! || (GET_CODE (XEXP (XEXP (tem, 1), 0)) != REG
! && GET_CODE (XEXP (XEXP (tem, 1), 0)) != SUBREG))
! abort ();
!
! /* It can happen that the note may speak of things
! in a wider (or just different) mode than the
! code did. This is especially true of
! REG_RETVAL. */
!
! if (GET_CODE (z) == SUBREG && SUBREG_WORD (z) == 0)
! z = SUBREG_REG (z);
!
! if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
! && (GET_MODE_SIZE (GET_MODE (x))
! > GET_MODE_SIZE (GET_MODE (z))))
! {
! /* This can occur as a result in invalid
! pointer casts, e.g. float f; ...
! *(long long int *)&f.
! ??? We could emit a warning here, but
! without a line number that wouldn't be
! very helpful. */
! z = gen_rtx_SUBREG (GET_MODE (x), z, 0);
! }
! else
! z = gen_lowpart (GET_MODE (x), z);
!
! *loc = z;
! return;
! }
/* There should always be such a replacement. */
abort ();
*************** purge_addressof_1 (loc, insn, force, sto
*** 3242,3251 ****
/* Remember the replacement so that the same one can be done
on the REG_NOTES. */
! purge_addressof_replacements
= gen_rtx_EXPR_LIST (VOIDmode, x,
! gen_rtx_EXPR_LIST (VOIDmode, val,
! purge_addressof_replacements));
/* We replaced with a reg -- all done. */
return;
--- 3253,3263 ----
/* Remember the replacement so that the same one can be done
on the REG_NOTES. */
! purge_bitfield_addressof_replacements
= gen_rtx_EXPR_LIST (VOIDmode, x,
! gen_rtx_EXPR_LIST
! (VOIDmode, val,
! purge_bitfield_addressof_replacements));
/* We replaced with a reg -- all done. */
return;
*************** purge_addressof_1 (loc, insn, force, sto
*** 3255,3264 ****
{
/* Remember the replacement so that the same one can be done
on the REG_NOTES. */
! purge_addressof_replacements
! = gen_rtx_EXPR_LIST (VOIDmode, x,
! gen_rtx_EXPR_LIST (VOIDmode, sub,
! purge_addressof_replacements));
goto restart;
}
give_up:;
--- 3267,3290 ----
{
/* Remember the replacement so that the same one can be done
on the REG_NOTES. */
! if (GET_CODE (sub) == REG || GET_CODE (sub) == SUBREG)
! {
! rtx tem;
!
! for (tem = purge_addressof_replacements;
! tem != NULL_RTX;
! tem = XEXP (XEXP (tem, 1), 1))
! if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
! {
! XEXP (XEXP (tem, 1), 0) = sub;
! return;
! }
! purge_addressof_replacements
! = gen_rtx (EXPR_LIST, VOIDmode, XEXP (x, 0),
! gen_rtx_EXPR_LIST (VOIDmode, sub,
! purge_addressof_replacements));
! return;
! }
goto restart;
}
give_up:;
*************** purge_addressof (insns)
*** 3440,3445 ****
--- 3466,3472 ----
/* Clean up. */
hash_table_free (&ht);
+ purge_bitfield_addressof_replacements = 0;
purge_addressof_replacements = 0;
}