summaryrefslogtreecommitdiff
path: root/gcc/config/aarch64/aarch64.c
diff options
context:
space:
mode:
authorWilco Dijkstra <wdijkstr@arm.com>2015-09-20 16:37:39 +0000
committerJiong Wang <jiwang@gcc.gnu.org>2015-09-20 16:37:39 +0000
commit62c8d76c1037198e2400ff2f55adddf352988af7 (patch)
treeaa3bab41a992a32959eee1f52224617e80a453c9 /gcc/config/aarch64/aarch64.c
parenta64c73a2f00ab4ab6a7485b34626d07ea2b2d519 (diff)
downloadgcc-62c8d76c1037198e2400ff2f55adddf352988af7.tar.gz
[AArch64][2/5] Improve aarch64_internal_mov_immediate by using faster algorithm
2015-09-20 Wilco Dijkstra <wdijkstr@arm.com> * config/aarch64/aarch64.c (aarch64_internal_mov_immediate): Replace slow immediate matching loops with a faster algorithm. From-SVN: r227947
Diffstat (limited to 'gcc/config/aarch64/aarch64.c')
-rw-r--r--gcc/config/aarch64/aarch64.c96
1 files changed, 23 insertions, 73 deletions
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 2e7b9ec0567..8097c35041b 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -1442,7 +1442,7 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
unsigned HOST_WIDE_INT mask;
int i;
bool first;
- unsigned HOST_WIDE_INT val;
+ unsigned HOST_WIDE_INT val, val2;
bool subtargets;
rtx subtarget;
int one_match, zero_match, first_not_ffff_match;
@@ -1569,85 +1569,35 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
}
}
- /* See if we can do it by arithmetically combining two
- immediates. */
- for (i = 0; i < AARCH64_NUM_BITMASKS; i++)
+ if (zero_match != 2 && one_match != 2)
{
- int j;
- mask = 0xffff;
+ /* Try emitting a bitmask immediate with a movk replacing 16 bits.
+ For a 64-bit bitmask try whether changing 16 bits to all ones or
+ zeroes creates a valid bitmask. To check any repeated bitmask,
+ try using 16 bits from the other 32-bit half of val. */
- if (aarch64_uimm12_shift (val - aarch64_bitmasks[i])
- || aarch64_uimm12_shift (-val + aarch64_bitmasks[i]))
+ for (i = 0; i < 64; i += 16, mask <<= 16)
{
- if (generate)
- {
- subtarget = subtargets ? gen_reg_rtx (DImode) : dest;
- emit_insn (gen_rtx_SET (subtarget,
- GEN_INT (aarch64_bitmasks[i])));
- emit_insn (gen_adddi3 (dest, subtarget,
- GEN_INT (val - aarch64_bitmasks[i])));
- }
- num_insns += 2;
- return num_insns;
+ val2 = val & ~mask;
+ if (val2 != val && aarch64_bitmask_imm (val2, mode))
+ break;
+ val2 = val | mask;
+ if (val2 != val && aarch64_bitmask_imm (val2, mode))
+ break;
+ val2 = val2 & ~mask;
+ val2 = val2 | (((val2 >> 32) | (val2 << 32)) & mask);
+ if (val2 != val && aarch64_bitmask_imm (val2, mode))
+ break;
}
-
- for (j = 0; j < 64; j += 16, mask <<= 16)
+ if (i != 64)
{
- if ((aarch64_bitmasks[i] & ~mask) == (val & ~mask))
+ if (generate)
{
- if (generate)
- {
- emit_insn (gen_rtx_SET (dest,
- GEN_INT (aarch64_bitmasks[i])));
- emit_insn (gen_insv_immdi (dest, GEN_INT (j),
- GEN_INT ((val >> j) & 0xffff)));
- }
- num_insns += 2;
- return num_insns;
+ emit_insn (gen_rtx_SET (dest, GEN_INT (val2)));
+ emit_insn (gen_insv_immdi (dest, GEN_INT (i),
+ GEN_INT ((val >> i) & 0xffff)));
}
- }
- }
-
- /* See if we can do it by logically combining two immediates. */
- for (i = 0; i < AARCH64_NUM_BITMASKS; i++)
- {
- if ((aarch64_bitmasks[i] & val) == aarch64_bitmasks[i])
- {
- int j;
-
- for (j = i + 1; j < AARCH64_NUM_BITMASKS; j++)
- if (val == (aarch64_bitmasks[i] | aarch64_bitmasks[j]))
- {
- if (generate)
- {
- subtarget = subtargets ? gen_reg_rtx (mode) : dest;
- emit_insn (gen_rtx_SET (subtarget,
- GEN_INT (aarch64_bitmasks[i])));
- emit_insn (gen_iordi3 (dest, subtarget,
- GEN_INT (aarch64_bitmasks[j])));
- }
- num_insns += 2;
- return num_insns;
- }
- }
- else if ((val & aarch64_bitmasks[i]) == val)
- {
- int j;
-
- for (j = i + 1; j < AARCH64_NUM_BITMASKS; j++)
- if (val == (aarch64_bitmasks[j] & aarch64_bitmasks[i]))
- {
- if (generate)
- {
- subtarget = subtargets ? gen_reg_rtx (mode) : dest;
- emit_insn (gen_rtx_SET (subtarget,
- GEN_INT (aarch64_bitmasks[j])));
- emit_insn (gen_anddi3 (dest, subtarget,
- GEN_INT (aarch64_bitmasks[i])));
- }
- num_insns += 2;
- return num_insns;
- }
+ return 2;
}
}