aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2014-05-08 11:35:19 +0930
committerAlan Modra <amodra@gcc.gnu.org>2014-05-08 11:35:19 +0930
commit42aea2d8f9282b7bb34fedc7f125840a393ee639 (patch)
tree40a7b0a9c432a98bf6b9d6e62ddc5371a87001e7 /gcc
parent7500b256b0f314c4dab8a590cffc6c58efa3ab23 (diff)
downloadgcc-42aea2d8f9282b7bb34fedc7f125840a393ee639.zip
gcc-42aea2d8f9282b7bb34fedc7f125840a393ee639.tar.gz
gcc-42aea2d8f9282b7bb34fedc7f125840a393ee639.tar.bz2
re PR target/60737 (rs6000 expand_block_clear uses word stores on double word pointer)
PR target/60737 * config/rs6000/rs6000.c (expand_block_move): Allow 64-bit loads and stores when -mno-strict-align at any alignment. (expand_block_clear): Similarly. Also correct calculation of instruction count. From-SVN: r210201
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/rs6000/rs6000.c52
2 files changed, 53 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 569dae1..354cdb9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2014-05-08 Alan Modra <amodra@gmail.com>
+
+ PR target/60737
+ * config/rs6000/rs6000.c (expand_block_move): Allow 64-bit
+ loads and stores when -mno-strict-align at any alignment.
+ (expand_block_clear): Similarly. Also correct calculation of
+ instruction count.
+
2014-05-07 Thomas Preud'homme <thomas.preudhomme@arm.com>
PR middle-end/39246
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 2de6125..7b19b42 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -15443,7 +15443,7 @@ expand_block_clear (rtx operands[])
load zero and three to do clearing. */
if (TARGET_ALTIVEC && align >= 128)
clear_step = 16;
- else if (TARGET_POWERPC64 && align >= 32)
+ else if (TARGET_POWERPC64 && (align >= 64 || !STRICT_ALIGNMENT))
clear_step = 8;
else if (TARGET_SPE && align >= 64)
clear_step = 8;
@@ -15471,12 +15471,27 @@ expand_block_clear (rtx operands[])
mode = V2SImode;
}
else if (bytes >= 8 && TARGET_POWERPC64
- /* 64-bit loads and stores require word-aligned
- displacements. */
- && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
+ && (align >= 64 || !STRICT_ALIGNMENT))
{
clear_bytes = 8;
mode = DImode;
+ if (offset == 0 && align < 64)
+ {
+ rtx addr;
+
+ /* If the address form is reg+offset with offset not a
+ multiple of four, reload into reg indirect form here
+ rather than waiting for reload. This way we get one
+ reload, not one per store. */
+ addr = XEXP (orig_dest, 0);
+ if ((GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM)
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT
+ && (INTVAL (XEXP (addr, 1)) & 3) != 0)
+ {
+ addr = copy_addr_to_reg (addr);
+ orig_dest = replace_equiv_address (orig_dest, addr);
+ }
+ }
}
else if (bytes >= 4 && (align >= 32 || !STRICT_ALIGNMENT))
{ /* move 4 bytes */
@@ -15604,13 +15619,36 @@ expand_block_move (rtx operands[])
gen_func.movmemsi = gen_movmemsi_4reg;
}
else if (bytes >= 8 && TARGET_POWERPC64
- /* 64-bit loads and stores require word-aligned
- displacements. */
- && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
+ && (align >= 64 || !STRICT_ALIGNMENT))
{
move_bytes = 8;
mode = DImode;
gen_func.mov = gen_movdi;
+ if (offset == 0 && align < 64)
+ {
+ rtx addr;
+
+ /* If the address form is reg+offset with offset not a
+ multiple of four, reload into reg indirect form here
+ rather than waiting for reload. This way we get one
+ reload, not one per load and/or store. */
+ addr = XEXP (orig_dest, 0);
+ if ((GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM)
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT
+ && (INTVAL (XEXP (addr, 1)) & 3) != 0)
+ {
+ addr = copy_addr_to_reg (addr);
+ orig_dest = replace_equiv_address (orig_dest, addr);
+ }
+ addr = XEXP (orig_src, 0);
+ if ((GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM)
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT
+ && (INTVAL (XEXP (addr, 1)) & 3) != 0)
+ {
+ addr = copy_addr_to_reg (addr);
+ orig_src = replace_equiv_address (orig_src, addr);
+ }
+ }
}
else if (TARGET_STRING && bytes > 4 && !TARGET_POWERPC64)
{ /* move up to 8 bytes at a time */