aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Baylis <charles.baylis@linaro.org>2016-01-20 20:46:26 +0000
committerYvan Roux <yvan.roux@linaro.org>2016-01-22 10:12:09 +0100
commitb5709d728ac886b958608f83b3e8c2c0b53f0afa (patch)
tree6076c5f728d7a7e9dca7eed7c41e3c837f844699
parentf87104e6c458f4bd46408813c9de99e1e9f4d738 (diff)
gcc/
Backport from trunk r231304. 2015-12-04 James Greenhalgh <james.greenhalgh@arm.com> * config/aarch64/aarch64.md (add<mode>3_pluslong): Add register constraints. gcc/testsuite/ Backport from trunk r231304. 2015-12-04 James Greenhalgh <james.greenhalgh@arm.com> * gcc.c-torture/compile/20151204.c: New. gcc/ Backport from trunk r232540. 2016-01-18 Richard Henderson <rth@redhat.com> PR target/69176 * config/aarch64/aarch64.md (add<GPI>3): Move long immediate operands to pseudo only if CSE is expected. Split long immediate operands only after reload, and for the stack pointer. (*add<GPI>3_pluslong): Remove. (*addsi3_aarch64, *adddi3_aarch64): Merge into... (*add<GPI>3_aarch64): ... here. Add r/rk/Upl alternative. (*addsi3_aarch64_uxtw): Add r/rk/Upl alternative. (*add<GPI>3 peepholes): New. (*add<GPI>3 splitters): New. * config/aarch64/constraints.md (Upl): New. * config/aarch64/predicates.md (aarch64_pluslong_strict_immedate): New. Change-Id: Id8d5f626e6819a2a469ab97bd5e730b4fbef02c4
-rw-r--r--gcc/config/aarch64/aarch64.md162
-rw-r--r--gcc/config/aarch64/constraints.md5
-rw-r--r--gcc/config/aarch64/predicates.md4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20151204.c19
4 files changed, 121 insertions, 69 deletions
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 9398a3d6584..8139a42fe35 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1580,96 +1580,120 @@
(plus:GPI (match_operand:GPI 1 "register_operand" "")
(match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
""
- "
- if (!aarch64_plus_operand (operands[2], VOIDmode))
+{
+ if (aarch64_pluslong_strict_immedate (operands[2], <MODE>mode))
{
- if (can_create_pseudo_p ())
- {
- rtx tmp = gen_reg_rtx (<MODE>mode);
- emit_move_insn (tmp, operands[2]);
- operands[2] = tmp;
- }
- else
+ /* Give CSE the opportunity to share this constant across additions. */
+ if (!cse_not_expected && can_create_pseudo_p ())
+ operands[2] = force_reg (<MODE>mode, operands[2]);
+
+ /* Split will refuse to operate on a modification to the stack pointer.
+ Aid the prologue and epilogue expanders by splitting this now. */
+ else if (reload_completed && operands[0] == stack_pointer_rtx)
{
- 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)));
+ HOST_WIDE_INT i = INTVAL (operands[2]);
+ HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_PLUS (<MODE>mode, operands[1],
+ GEN_INT (i - s))));
operands[1] = operands[0];
- operands[2] = GEN_INT (imm);
+ operands[2] = GEN_INT (s);
}
}
- "
-)
-
-;; 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);
- }
- "
-)
+})
-(define_insn "*addsi3_aarch64"
+(define_insn "*add<mode>3_aarch64"
[(set
- (match_operand:SI 0 "register_operand" "=rk,rk,w,rk")
- (plus:SI
- (match_operand:SI 1 "register_operand" "%rk,rk,w,rk")
- (match_operand:SI 2 "aarch64_plus_operand" "I,r,w,J")))]
+ (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r")
+ (plus:GPI
+ (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk")
+ (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Upl")))]
""
"@
- add\\t%w0, %w1, %2
- add\\t%w0, %w1, %w2
- add\\t%0.2s, %1.2s, %2.2s
- sub\\t%w0, %w1, #%n2"
- [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm")
- (set_attr "simd" "*,*,yes,*")]
+ add\\t%<w>0, %<w>1, %2
+ add\\t%<w>0, %<w>1, %<w>2
+ add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
+ sub\\t%<w>0, %<w>1, #%n2
+ #"
+ [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple")
+ (set_attr "simd" "*,*,yes,*,*")]
)
;; zero_extend version of above
(define_insn "*addsi3_aarch64_uxtw"
[(set
- (match_operand:DI 0 "register_operand" "=rk,rk,rk")
+ (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
(zero_extend:DI
- (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk")
- (match_operand:SI 2 "aarch64_plus_operand" "I,r,J"))))]
+ (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
+ (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Upl"))))]
""
"@
add\\t%w0, %w1, %2
add\\t%w0, %w1, %w2
- sub\\t%w0, %w1, #%n2"
- [(set_attr "type" "alu_imm,alu_sreg,alu_imm")]
+ sub\\t%w0, %w1, #%n2
+ #"
+ [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
)
-(define_insn "*adddi3_aarch64"
- [(set
- (match_operand:DI 0 "register_operand" "=rk,rk,rk,w")
- (plus:DI
- (match_operand:DI 1 "register_operand" "%rk,rk,rk,w")
- (match_operand:DI 2 "aarch64_plus_operand" "I,r,J,w")))]
- ""
- "@
- add\\t%x0, %x1, %2
- add\\t%x0, %x1, %x2
- sub\\t%x0, %x1, #%n2
- add\\t%d0, %d1, %d2"
- [(set_attr "type" "alu_imm,alu_sreg,alu_imm,neon_add")
- (set_attr "simd" "*,*,*,yes")]
+;; If there's a free register, and we can load the constant with a
+;; single instruction, do so. This has a chance to improve scheduling.
+(define_peephole2
+ [(match_scratch:GPI 3 "r")
+ (set (match_operand:GPI 0 "register_operand")
+ (plus:GPI
+ (match_operand:GPI 1 "register_operand")
+ (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
+ "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
+ [(set (match_dup 3) (match_dup 2))
+ (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
+)
+
+(define_peephole2
+ [(match_scratch:SI 3 "r")
+ (set (match_operand:DI 0 "register_operand")
+ (zero_extend:DI
+ (plus:SI
+ (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
+ "aarch64_move_imm (INTVAL (operands[2]), SImode)"
+ [(set (match_dup 3) (match_dup 2))
+ (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
+)
+
+;; After peephole2 has had a chance to run, split any remaining long
+;; additions into two add immediates.
+(define_split
+ [(set (match_operand:GPI 0 "register_operand")
+ (plus:GPI
+ (match_operand:GPI 1 "register_operand")
+ (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
+ "epilogue_completed"
+ [(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 i = INTVAL (operands[2]);
+ HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
+ operands[3] = GEN_INT (i - s);
+ operands[4] = GEN_INT (s);
+ }
+)
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand")
+ (zero_extend:DI
+ (plus:SI
+ (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
+ "epilogue_completed"
+ [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
+ (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
+ {
+ HOST_WIDE_INT i = INTVAL (operands[2]);
+ HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
+ operands[3] = GEN_INT (i - s);
+ operands[4] = GEN_INT (s);
+ operands[5] = gen_lowpart (SImode, operands[0]);
+ }
)
(define_expand "addti3"
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index 9dc21089154..f99db207424 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -35,6 +35,11 @@
(and (match_code "const_int")
(match_test "aarch64_uimm12_shift (ival)")))
+(define_constraint "Upl"
+ "@internal A constant that matches two uses of add instructions."
+ (and (match_code "const_int")
+ (match_test "aarch64_pluslong_strict_immedate (op, VOIDmode)")))
+
(define_constraint "J"
"A constant that can be used with a SUB operation (once negated)."
(and (match_code "const_int")
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index 2d68475b191..cd235acf73a 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -100,6 +100,10 @@
(and (match_code "const_int")
(match_test "(INTVAL (op) < 0xffffff && INTVAL (op) > -0xffffff)")))
+(define_predicate "aarch64_pluslong_strict_immedate"
+ (and (match_operand 0 "aarch64_pluslong_immediate")
+ (not (match_operand 0 "aarch64_plus_immediate"))))
+
(define_predicate "aarch64_pluslong_operand"
(ior (match_operand 0 "register_operand")
(match_operand 0 "aarch64_pluslong_immediate")))
diff --git a/gcc/testsuite/gcc.c-torture/compile/20151204.c b/gcc/testsuite/gcc.c-torture/compile/20151204.c
new file mode 100644
index 00000000000..036316ced95
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20151204.c
@@ -0,0 +1,19 @@
+typedef __SIZE_TYPE__ size_t;
+
+int strcmp (const char*, const char*);
+void *memchr (const void *, int, size_t);
+char* strncpy (char *, const char *, size_t);
+
+int
+main (int argc, char** argv)
+{
+ char target[32753] = "A";
+ char buffer[32753];
+ char *x;
+ x = buffer;
+
+ if (strcmp (target, "A")
+ || memchr (target, 'A', 0) != ((void *) 0))
+ if (strncpy (x, "", 4) != x);
+ return 0;
+}