aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorUros Bizjak <uros@gcc.gnu.org>2012-03-02 18:03:36 +0100
committerUros Bizjak <uros@gcc.gnu.org>2012-03-02 18:03:36 +0100
commit2b57045bfc0c746c5bbc952cf8a4da70548b5775 (patch)
treede672f41ad561e09e8cfbbfb2c60a2a8adcc5ed0 /gcc/config
parent08c3865834b9965affb39529e6209002d0fe73e5 (diff)
downloadgcc-2b57045bfc0c746c5bbc952cf8a4da70548b5775.zip
gcc-2b57045bfc0c746c5bbc952cf8a4da70548b5775.tar.gz
gcc-2b57045bfc0c746c5bbc952cf8a4da70548b5775.tar.bz2
re PR target/46716 (wrong code generated with -mno-sse2 -m64)
PR target/46716 * config/i386/i386.c (construct_container): Use gen_reg_or_parallel to pass the argument in the register of "natural" mode. testsuite/ChangeLog: PR target/46716 * gcc.target/i386/pr46176.c: New test. From-SVN: r184802
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386.c69
1 files changed, 42 insertions, 27 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f93583f..65c4c42 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -5829,7 +5829,8 @@ classify_argument (enum machine_mode mode, const_tree type,
{
HOST_WIDE_INT bytes =
(mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
- int words = (bytes + (bit_offset % 64) / 8 + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+ int words
+ = (bytes + (bit_offset % 64) / 8 + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
/* Variable sized entities are always passed/returned in memory. */
if (bytes < 0)
@@ -5879,7 +5880,8 @@ classify_argument (enum machine_mode mode, const_tree type,
misaligned integers. */
if (DECL_BIT_FIELD (field))
{
- for (i = (int_bit_position (field) + (bit_offset % 64)) / 8 / 8;
+ for (i = (int_bit_position (field)
+ + (bit_offset % 64)) / 8 / 8;
i < ((int_bit_position (field) + (bit_offset % 64))
+ tree_low_cst (DECL_SIZE (field), 0)
+ 63) / 8 / 8; i++)
@@ -5919,7 +5921,8 @@ classify_argument (enum machine_mode mode, const_tree type,
+ bit_offset) % 256);
if (!num)
return 0;
- pos = (int_bit_position (field) + (bit_offset % 64)) / 8 / 8;
+ pos = (int_bit_position (field)
+ + (bit_offset % 64)) / 8 / 8;
for (i = 0; i < num && (i + pos) < words; i++)
classes[i + pos] =
merge_classes (subclasses[i], classes[i + pos]);
@@ -6336,21 +6339,27 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode,
default:
gcc_unreachable ();
}
- if (n == 2 && regclass[0] == X86_64_SSE_CLASS
- && regclass[1] == X86_64_SSEUP_CLASS && mode != BLKmode)
- return gen_rtx_REG (mode, SSE_REGNO (sse_regno));
+ if (n == 2
+ && regclass[0] == X86_64_SSE_CLASS
+ && regclass[1] == X86_64_SSEUP_CLASS
+ && mode != BLKmode)
+ return gen_reg_or_parallel (mode, orig_mode,
+ SSE_REGNO (sse_regno));
if (n == 4
&& regclass[0] == X86_64_SSE_CLASS
&& regclass[1] == X86_64_SSEUP_CLASS
&& regclass[2] == X86_64_SSEUP_CLASS
&& regclass[3] == X86_64_SSEUP_CLASS
&& mode != BLKmode)
- return gen_rtx_REG (mode, SSE_REGNO (sse_regno));
-
+ return gen_reg_or_parallel (mode, orig_mode,
+ SSE_REGNO (sse_regno));
if (n == 2
- && regclass[0] == X86_64_X87_CLASS && regclass[1] == X86_64_X87UP_CLASS)
+ && regclass[0] == X86_64_X87_CLASS
+ && regclass[1] == X86_64_X87UP_CLASS)
return gen_rtx_REG (XFmode, FIRST_STACK_REG);
- if (n == 2 && regclass[0] == X86_64_INTEGER_CLASS
+
+ if (n == 2
+ && regclass[0] == X86_64_INTEGER_CLASS
&& regclass[1] == X86_64_INTEGER_CLASS
&& (mode == CDImode || mode == TImode || mode == TFmode)
&& intreg[0] + 1 == intreg[1])
@@ -6369,31 +6378,36 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode,
case X86_64_INTEGERSI_CLASS:
/* Merge TImodes on aligned occasions here too. */
if (i * 8 + 8 > bytes)
- tmpmode = mode_for_size ((bytes - i * 8) * BITS_PER_UNIT, MODE_INT, 0);
+ tmpmode
+ = mode_for_size ((bytes - i * 8) * BITS_PER_UNIT, MODE_INT, 0);
else if (regclass[i] == X86_64_INTEGERSI_CLASS)
tmpmode = SImode;
else
tmpmode = DImode;
- /* We've requested 24 bytes we don't have mode for. Use DImode. */
+ /* We've requested 24 bytes we
+ don't have mode for. Use DImode. */
if (tmpmode == BLKmode)
tmpmode = DImode;
- exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (tmpmode, *intreg),
- GEN_INT (i*8));
+ exp [nexps++]
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (tmpmode, *intreg),
+ GEN_INT (i*8));
intreg++;
break;
case X86_64_SSESF_CLASS:
- exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (SFmode,
- SSE_REGNO (sse_regno)),
- GEN_INT (i*8));
+ exp [nexps++]
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SFmode,
+ SSE_REGNO (sse_regno)),
+ GEN_INT (i*8));
sse_regno++;
break;
case X86_64_SSEDF_CLASS:
- exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (DFmode,
- SSE_REGNO (sse_regno)),
- GEN_INT (i*8));
+ exp [nexps++]
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (DFmode,
+ SSE_REGNO (sse_regno)),
+ GEN_INT (i*8));
sse_regno++;
break;
case X86_64_SSE_CLASS:
@@ -6423,10 +6437,11 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode,
default:
gcc_unreachable ();
}
- exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (tmpmode,
- SSE_REGNO (sse_regno)),
- GEN_INT (pos*8));
+ exp [nexps++]
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (tmpmode,
+ SSE_REGNO (sse_regno)),
+ GEN_INT (pos*8));
sse_regno++;
break;
default: