aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Bolton <ian.bolton@arm.com>2014-08-07 13:42:22 +0000
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>2014-08-07 13:42:22 +0000
commitc747993a621cc69309e3a9e9fddeba09f470fb86 (patch)
tree33cb0a390bf1a450247bc8a61461e48e49b446b4
parent4da2eb985b6a7c3cf4893d9ab6ab93e158ceb0cf (diff)
downloadgcc-c747993a621cc69309e3a9e9fddeba09f470fb86.zip
gcc-c747993a621cc69309e3a9e9fddeba09f470fb86.tar.gz
gcc-c747993a621cc69309e3a9e9fddeba09f470fb86.tar.bz2
[AArch64] Use MOVN to generate 64-bit negative immediates where sensible
* config/aarch64/aarch64.c (aarch64_expand_mov_immediate): Use MOVN when one of the half-words is 0xffff. Co-Authored-By: Kyrylo Tkachov <kyrylo.tkachov@arm.com> From-SVN: r213711
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/aarch64/aarch64.c45
2 files changed, 38 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index be1e703..e121b9e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2014-08-07 Ian Bolton <ian.bolton@arm.com>
+ Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_expand_mov_immediate):
+ Use MOVN when one of the half-words is 0xffff.
+
2014-08-07 Marat Zakirov <m.zakirov@samsung.com>
* config/arm/thumb1.md (*thumb1_movqi_insn): Copy of thumb1_movhi_insn.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 1165428..832bcf3 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -1006,7 +1006,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
unsigned HOST_WIDE_INT val;
bool subtargets;
rtx subtarget;
- int one_match, zero_match;
+ int one_match, zero_match, first_not_ffff_match;
gcc_assert (mode == SImode || mode == DImode);
@@ -1107,29 +1107,48 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
one_match = 0;
zero_match = 0;
mask = 0xffff;
+ first_not_ffff_match = -1;
for (i = 0; i < 64; i += 16, mask <<= 16)
{
- if ((val & mask) == 0)
- zero_match++;
- else if ((val & mask) == mask)
+ if ((val & mask) == mask)
one_match++;
+ else
+ {
+ if (first_not_ffff_match < 0)
+ first_not_ffff_match = i;
+ if ((val & mask) == 0)
+ zero_match++;
+ }
}
if (one_match == 2)
{
- mask = 0xffff;
- for (i = 0; i < 64; i += 16, mask <<= 16)
+ /* Set one of the quarters and then insert back into result. */
+ mask = 0xffffll << first_not_ffff_match;
+ emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_INT (val | mask)));
+ emit_insn (gen_insv_immdi (dest, GEN_INT (first_not_ffff_match),
+ GEN_INT ((val >> first_not_ffff_match)
+ & 0xffff)));
+ return;
+ }
+
+ if (one_match > zero_match)
+ {
+ /* Set either first three quarters or all but the third. */
+ mask = 0xffffll << (16 - first_not_ffff_match);
+ emit_insn (gen_rtx_SET (VOIDmode, dest,
+ GEN_INT (val | mask | 0xffffffff00000000ull)));
+
+ /* Now insert other two quarters. */
+ for (i = first_not_ffff_match + 16, mask <<= (first_not_ffff_match << 1);
+ i < 64; i += 16, mask <<= 16)
{
if ((val & mask) != mask)
- {
- emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_INT (val | mask)));
- emit_insn (gen_insv_immdi (dest, GEN_INT (i),
- GEN_INT ((val >> i) & 0xffff)));
- return;
- }
+ emit_insn (gen_insv_immdi (dest, GEN_INT (i),
+ GEN_INT ((val >> i) & 0xffff)));
}
- gcc_unreachable ();
+ return;
}
if (zero_match == 2)