From: Richard Sandiford Date: Sun, 10 Sep 2006 19:36:20 +0000 (+0000) Subject: re PR target/29006 (Incorrect zeroing of unaligned 64-bit fields on MIPS targets) X-Git-Tag: releases/gcc-4.0.4~377 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9d4790fe4873780dab0fb5a42e32206affc805f9;p=thirdparty%2Fgcc.git re PR target/29006 (Incorrect zeroing of unaligned 64-bit fields on MIPS targets) gcc/ PR target/29006 * config/mips/mips-protos.h (mips_mem_fits_mode_p): Declare. * config/mips/mips.c (mips_expand_unaligned_store): Use the mode returned by mode_for_size, rather than the mode of src itself, to choose between 32-bit and 64-bit patterns. (mips_mem_fits_mode_p): New function. * config/mips/mips.md (mov_l, mov_r): Use it to check that the size of the source matches the size of the destination. (mov_l, mov_r): Likewise. gcc/testsuite/ PR target/29006 * gcc.c-torture/execute/pr29006.c: New test. From-SVN: r116824 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1a9812b335b2..609f0a7a8f9e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2006-09-10 Richard Sandiford + + PR target/29006 + * config/mips/mips-protos.h (mips_mem_fits_mode_p): Declare. + * config/mips/mips.c (mips_expand_unaligned_store): Use the mode + returned by mode_for_size, rather than the mode of src itself, + to choose between 32-bit and 64-bit patterns. + (mips_mem_fits_mode_p): New function. + * config/mips/mips.md (mov_l, mov_r): Use it to check + that the size of the source matches the size of the destination. + (mov_l, mov_r): Likewise. + 2006-09-06 Matthias Klose * Makefile.in (s-macro_list): Conform to POSIX rules in single quoted diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 8569d429959b..21fc7f357ddf 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -148,6 +148,7 @@ extern void mips_va_start (tree, rtx); extern bool mips_expand_unaligned_load (rtx, rtx, unsigned int, int); extern bool mips_expand_unaligned_store (rtx, rtx, unsigned int, int); +extern bool mips_mem_fits_mode_p (enum machine_mode mode, rtx x); extern void override_options (void); extern void mips_conditional_register_usage (void); extern void mips_order_regs_for_local_alloc (void); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 0dd7e0b6ffcd..e443bdd62e16 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -3950,13 +3950,15 @@ bool mips_expand_unaligned_store (rtx dest, rtx src, unsigned int width, int bitpos) { rtx left, right; + enum machine_mode mode; if (!mips_get_unaligned_mem (&dest, width, bitpos, &left, &right)) return false; - src = gen_lowpart (mode_for_size (width, MODE_INT, 0), src); + mode = mode_for_size (width, MODE_INT, 0); + src = gen_lowpart (mode, src); - if (GET_MODE (src) == DImode) + if (mode == DImode) { emit_insn (gen_mov_sdl (dest, src, left)); emit_insn (gen_mov_sdr (copy_rtx (dest), copy_rtx (src), right)); @@ -3968,6 +3970,20 @@ mips_expand_unaligned_store (rtx dest, rtx src, unsigned int width, int bitpos) } return true; } + +/* Return true if X is a MEM with the same size as MODE. */ + +bool +mips_mem_fits_mode_p (enum machine_mode mode, rtx x) +{ + rtx size; + + if (!MEM_P (x)) + return false; + + size = MEM_SIZE (x); + return size && INTVAL (size) == GET_MODE_SIZE (mode); +} /* Set up globals to generate code for the ISA or processor described by INFO. */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 44c22f5e58e7..a7b47fdf13bf 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -2835,7 +2835,7 @@ beq\t%2,%.,1b\;\ (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m") (match_operand:QI 2 "memory_operand" "m")] UNSPEC_LOAD_LEFT))] - "!TARGET_MIPS16" + "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[1])" "l\t%0,%2" [(set_attr "type" "load") (set_attr "mode" "")]) @@ -2846,7 +2846,7 @@ beq\t%2,%.,1b\;\ (match_operand:QI 2 "memory_operand" "m") (match_operand:GPR 3 "register_operand" "0")] UNSPEC_LOAD_RIGHT))] - "!TARGET_MIPS16" + "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[1])" "r\t%0,%2" [(set_attr "type" "load") (set_attr "mode" "")]) @@ -2856,7 +2856,7 @@ beq\t%2,%.,1b\;\ (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ") (match_operand:QI 2 "memory_operand" "m")] UNSPEC_STORE_LEFT))] - "!TARGET_MIPS16" + "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[0])" "l\t%z1,%2" [(set_attr "type" "store") (set_attr "mode" "")]) @@ -2867,7 +2867,7 @@ beq\t%2,%.,1b\;\ (match_operand:QI 2 "memory_operand" "m") (match_dup 0)] UNSPEC_STORE_RIGHT))] - "!TARGET_MIPS16" + "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[0])" "r\t%z1,%2" [(set_attr "type" "store") (set_attr "mode" "")]) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f653f619a47a..64ffd93c35e4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-09-10 Richard Sandiford + + PR target/29006 + * gcc.c-torture/execute/pr29006.c: New test. + 2006-08-28 Volker Reichelt PR c++/28860 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr29006.c b/gcc/testsuite/gcc.c-torture/execute/pr29006.c new file mode 100644 index 000000000000..4d1f1388465d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr29006.c @@ -0,0 +1,3 @@ +struct __attribute__((__packed__)) s { char c; unsigned long long x; }; +void __attribute__((__noinline__)) foo (struct s *s) { s->x = 0; } +int main (void) { struct s s = { 1, ~0ULL }; foo (&s); return s.x != 0; }