aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>2009-06-13 12:49:25 +0000
committerRichard Earnshaw <rearnsha@gcc.gnu.org>2009-06-13 12:49:25 +0000
commit81beb0316c9ec1b53f038de4721929d444f5e406 (patch)
tree9462413f39917293691b2f80a1691fc920688266 /gcc/config/arm
parent98f6c6001353550dbafae02051371d2bef236b99 (diff)
downloadgcc-81beb0316c9ec1b53f038de4721929d444f5e406.zip
gcc-81beb0316c9ec1b53f038de4721929d444f5e406.tar.gz
gcc-81beb0316c9ec1b53f038de4721929d444f5e406.tar.bz2
re PR target/40327 (Use fewer instructions to add some constants to register)
PR target/40327 * arm/constraints.md (Pa, Pb): New constraints. * arm/arm.md (thumb1_addsi3): Support more complex additions. Add a split pattern to deal with them. From-SVN: r148452
Diffstat (limited to 'gcc/config/arm')
-rw-r--r--gcc/config/arm/arm.md29
-rw-r--r--gcc/config/arm/constraints.md13
2 files changed, 36 insertions, 6 deletions
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 5f3a5e0..40e41c5 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -640,10 +640,10 @@
;; register. Trying to reload it will always fail catastrophically,
;; so never allow those alternatives to match if reloading is needed.
-(define_insn "*thumb1_addsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O")))]
+(define_insn_and_split "*thumb1_addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k,l,l")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k,0,l")
+ (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O,Pa,Pb")))]
"TARGET_THUMB1"
"*
static const char * const asms[] =
@@ -654,7 +654,9 @@
\"add\\t%0, %0, %2\",
\"add\\t%0, %0, %2\",
\"add\\t%0, %1, %2\",
- \"add\\t%0, %1, %2\"
+ \"add\\t%0, %1, %2\",
+ \"#\",
+ \"#\"
};
if ((which_alternative == 2 || which_alternative == 6)
&& GET_CODE (operands[2]) == CONST_INT
@@ -662,7 +664,22 @@
return \"sub\\t%0, %1, #%n2\";
return asms[which_alternative];
"
- [(set_attr "length" "2")]
+ "&& reload_completed && CONST_INT_P (operands[2])
+ && operands[1] != stack_pointer_rtx
+ && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)"
+ [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
+ {
+ HOST_WIDE_INT offset = INTVAL (operands[2]);
+ if (offset > 255)
+ offset = 255;
+ else if (offset < -255)
+ offset = -255;
+
+ operands[3] = GEN_INT (offset);
+ operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
+ }
+ [(set_attr "length" "2,2,2,2,2,2,2,4,4")]
)
;; Reloading and elimination of the frame pointer can
diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md
index 6cefa4e..f71599e 100644
--- a/gcc/config/arm/constraints.md
+++ b/gcc/config/arm/constraints.md
@@ -30,6 +30,7 @@
;; The following multi-letter normal constraints have been used:
;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv
+;; in Thumb-1 state: Pa, Pb
;; The following memory constraints have been used:
;; in ARM/Thumb-2 state: Q, Ut, Uv, Uy, Un, Um, Us
@@ -129,6 +130,18 @@
(match_test "TARGET_THUMB1 && ival >= -508 && ival <= 508
&& ((ival & 3) == 0)")))
+(define_constraint "Pa"
+ "@internal In Thumb-1 state a constant in the range -510 to +510"
+ (and (match_code "const_int")
+ (match_test "TARGET_THUMB1 && ival >= -510 && ival <= 510
+ && (ival > 255 || ival < -255)")))
+
+(define_constraint "Pb"
+ "@internal In Thumb-1 state a constant in the range -262 to +262"
+ (and (match_code "const_int")
+ (match_test "TARGET_THUMB1 && ival >= -262 && ival <= 262
+ && (ival > 255 || ival < -255)")))
+
(define_constraint "G"
"In ARM/Thumb-2 state a valid FPA immediate constant."
(and (match_code "const_double")