aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorWilco Dijkstra <wdijkstr@arm.com>2015-11-24 14:46:05 +0000
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>2015-11-24 14:46:05 +0000
commit4e55c7c347fe797af3aaee1dedb46230168c371b (patch)
tree475563192f5c4761ec5549b18b37857bf35de2fe /gcc
parent6b2f9bb6228bca4b610a6645a60e1557d65b14ef (diff)
downloadgcc-4e55c7c347fe797af3aaee1dedb46230168c371b.zip
gcc-4e55c7c347fe797af3aaee1dedb46230168c371b.tar.gz
gcc-4e55c7c347fe797af3aaee1dedb46230168c371b.tar.bz2
[PATCH][AArch64] Improve add immediate expansion
gcc/ * gcc/config/aarch64/aarch64.md (add<mode>3): Block early expansion into 2 add instructions. (add<mode>3_pluslong): New pattern to combine complex immediates into 2 additions. From-SVN: r230814
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/aarch64/aarch64.md54
2 files changed, 42 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5203b28..6a5ebde 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2015-11-24 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * gcc/config/aarch64/aarch64.md (add<mode>3):
+ Block early expansion into 2 add instructions.
+ (add<mode>3_pluslong): New pattern to combine complex
+ immediates into 2 additions.
+
2015-11-24 Segher Boessenkool <segher@kernel.crashing.org>
PR target/66217
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 28a7f8c..c11e8ec 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1588,30 +1588,46 @@
(match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
""
"
- if (! aarch64_plus_operand (operands[2], VOIDmode))
+ if (!aarch64_plus_operand (operands[2], VOIDmode))
{
- HOST_WIDE_INT imm = INTVAL (operands[2]);
-
- if (aarch64_move_imm (imm, <MODE>mode) && can_create_pseudo_p ())
- {
+ if (can_create_pseudo_p ())
+ {
rtx tmp = gen_reg_rtx (<MODE>mode);
emit_move_insn (tmp, operands[2]);
operands[2] = tmp;
- }
+ }
else
- {
- rtx subtarget = ((optimize && can_create_pseudo_p ())
- ? gen_reg_rtx (<MODE>mode) : operands[0]);
-
- if (imm < 0)
- imm = -(-imm & ~0xfff);
- else
- imm &= ~0xfff;
-
- emit_insn (gen_add<mode>3 (subtarget, operands[1], GEN_INT (imm)));
- operands[1] = subtarget;
- operands[2] = GEN_INT (INTVAL (operands[2]) - imm);
- }
+ {
+ HOST_WIDE_INT imm = INTVAL (operands[2]);
+ imm = imm >= 0 ? imm & 0xfff : -(-imm & 0xfff);
+ emit_insn (gen_add<mode>3 (operands[0], operands[1],
+ GEN_INT (INTVAL (operands[2]) - imm)));
+ operands[1] = operands[0];
+ operands[2] = GEN_INT (imm);
+ }
+ }
+ "
+)
+
+;; Find add with a 2-instruction immediate and merge into 2 add instructions.
+
+(define_insn_and_split "*add<mode>3_pluslong"
+ [(set
+ (match_operand:GPI 0 "register_operand" "")
+ (plus:GPI (match_operand:GPI 1 "register_operand" "")
+ (match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
+ "!aarch64_plus_operand (operands[2], VOIDmode)
+ && !aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
+ "#"
+ "&& true"
+ [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
+ (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
+ "
+ {
+ HOST_WIDE_INT imm = INTVAL (operands[2]);
+ imm = imm >= 0 ? imm & 0xfff : -(-imm & 0xfff);
+ operands[3] = GEN_INT (INTVAL (operands[2]) - imm);
+ operands[4] = GEN_INT (imm);
}
"
)