Hi,

As described in PR53447, many 64bit ALU operations with constant can be
optimized to use corresponding 32bit instructions with immediate operands.

This is the first part of the patches that deals with 64bit add. It directly
extends the patterns adddi3, arm_adddi3 and adddi3_neon to handle constant
operands.

Tested on arm qemu without regression.

OK for trunk?

thanks
Carrot

2012-05-26  Wei Guozhi  <car...@google.com>

        PR target/53447
        * gcc.target/arm/pr53447-1.c: New testcase.


2012-05-26  Wei Guozhi  <car...@google.com>

        PR target/53447
        * config/arm/arm-protos.h (const_ok_for_adddi): New prototype.
        * config/arm/arm.c (const_ok_for_adddi): New function.
        * config/arm/constraints.md (Dd): New constraint.
        * config/arm/arm.md (adddi3): Extend it to handle constants.
        (arm_adddi3): Likewise.
        * config/arm/neon.md (adddi3_neon): Likewise.


Index: testsuite/gcc.target/arm/pr53447-1.c
===================================================================
--- testsuite/gcc.target/arm/pr53447-1.c        (revision 0)
+++ testsuite/gcc.target/arm/pr53447-1.c        (revision 0)
@@ -0,0 +1,8 @@
+/* { dg-options "-O2" }  */
+/* { dg-require-effective-target arm32 } */
+/* { dg-final { scan-assembler-not "mov" } } */
+
+void t0p(long long * p)
+{
+  *p += 0x100000001;
+}
Index: config/arm/arm.c
===================================================================
--- config/arm/arm.c    (revision 187751)
+++ config/arm/arm.c    (working copy)
@@ -2497,6 +2497,17 @@
     }
 }

+/* Return TRUE if int I is a valid immediate constant used by pattern
+   arm_adddi3.  */
+int
+const_ok_for_adddi (HOST_WIDE_INT i)
+{
+  HOST_WIDE_INT high = (i >> 32) & 0xFFFFFFFF;
+  HOST_WIDE_INT low = i & 0xFFFFFFFF;
+  return (const_ok_for_arm (high)
+         && (const_ok_for_arm (low) || const_ok_for_arm (-low)));
+}
+
 /* Emit a sequence of insns to handle a large constant.
    CODE is the code of the operation required, it can be any of SET, PLUS,
    IOR, AND, XOR, MINUS;
Index: config/arm/arm-protos.h
===================================================================
--- config/arm/arm-protos.h     (revision 187751)
+++ config/arm/arm-protos.h     (working copy)
@@ -47,6 +47,7 @@
 extern bool arm_small_register_classes_for_mode_p (enum machine_mode);
 extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode);
 extern bool arm_modes_tieable_p (enum machine_mode, enum machine_mode);
+extern int const_ok_for_adddi (HOST_WIDE_INT);
 extern int const_ok_for_arm (HOST_WIDE_INT);
 extern int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
 extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
Index: config/arm/neon.md
===================================================================
--- config/arm/neon.md  (revision 187751)
+++ config/arm/neon.md  (working copy)
@@ -588,9 +588,9 @@
 )

 (define_insn "adddi3_neon"
-  [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w")
-        (plus:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,w")
-                 (match_operand:DI 2 "s_register_operand" "w,r,0,w")))
+  [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w,?&r,?&r,?&r")
+        (plus:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,w,r,0,r")
+                 (match_operand:DI 2 "reg_or_int_operand" "w,r,0,w,r,Dd,Dd")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_NEON"
 {
@@ -600,13 +600,16 @@
     case 3: return "vadd.i64\t%P0, %P1, %P2";
     case 1: return "#";
     case 2: return "#";
+    case 4: return "#";
+    case 5: return "#";
+    case 6: return "#";
     default: gcc_unreachable ();
     }
 }
-  [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
-   (set_attr "conds" "*,clob,clob,*")
-   (set_attr "length" "*,8,8,*")
-   (set_attr "arch" "nota8,*,*,onlya8")]
+  [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1,*,*,*")
+   (set_attr "conds" "*,clob,clob,*,clob,clob,clob")
+   (set_attr "length" "*,8,8,*,*,*,*")
+   (set_attr "arch" "nota8,*,*,onlya8,*,*,*")]
 )

 (define_insn "*sub<mode>3_neon"
Index: config/arm/constraints.md
===================================================================
--- config/arm/constraints.md   (revision 187751)
+++ config/arm/constraints.md   (working copy)
@@ -29,7 +29,7 @@
 ;; in Thumb-1 state: I, J, K, L, M, N, O

 ;; The following multi-letter normal constraints have been used:
-;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di, Dt, Dz
+;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, Dl, DL, Dv, Dy, Di, Dt, Dz
 ;; in Thumb-1 state: Pa, Pb, Pc, Pd, Pe
 ;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py

@@ -251,6 +251,12 @@
       (match_test "TARGET_32BIT && arm_const_double_inline_cost (op) == 4
                   && !(optimize_size || arm_ld_sched)")))

+(define_constraint "Dd"
+ "@internal
+ In ARM/Thumb-2 state a const_int that can be used by insn adddi."
+ (and (match_code "const_int")
+      (match_test "TARGET_32BIT && const_ok_for_adddi (ival)")))
+
 (define_constraint "Di"
  "@internal
   In ARM/Thumb-2 state a const_int or const_double where both the high
Index: config/arm/arm.md
===================================================================
--- config/arm/arm.md   (revision 187751)
+++ config/arm/arm.md   (working copy)
@@ -574,10 +574,21 @@
  [(parallel
    [(set (match_operand:DI           0 "s_register_operand" "")
          (plus:DI (match_operand:DI 1 "s_register_operand" "")
-                  (match_operand:DI 2 "s_register_operand" "")))
+                  (match_operand:DI 2 "reg_or_int_operand" "")))
     (clobber (reg:CC CC_REGNUM))])]
   "TARGET_EITHER"
   "
+  if (GET_CODE (operands[2]) == CONST_INT)
+    {
+      if (TARGET_32BIT && const_ok_for_adddi (INTVAL (operands[2])))
+       {
+         emit_insn (gen_arm_adddi3 (operands[0], operands[1], operands[2]));
+         DONE;
+       }
+      else
+       operands[2] = force_reg (DImode, operands[2]);
+    }
+
   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
     {
       if (!cirrus_fp_register (operands[0], DImode))
@@ -609,10 +620,10 @@
   [(set_attr "length" "4")]
 )

-(define_insn_and_split "*arm_adddi3"
-  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
-       (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
-                (match_operand:DI 2 "s_register_operand" "r,  0")))
+(define_insn_and_split "arm_adddi3"
+  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r,&r,&r,&r")
+       (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
+                (match_operand:DI 2 "reg_or_int_operand" "r,  0, r, Dd,Dd")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
   "#"
@@ -630,8 +641,17 @@
     operands[0] = gen_lowpart (SImode, operands[0]);
     operands[4] = gen_highpart (SImode, operands[1]);
     operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[5] = gen_highpart (SImode, operands[2]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
+    if (GET_CODE (operands[2]) == CONST_INT)
+      {
+       HOST_WIDE_INT v = INTVAL (operands[2]);
+       operands[5] = GEN_INT (ARM_SIGN_EXTEND ((v >> 32) & 0xFFFFFFFF));
+       operands[2] = GEN_INT (ARM_SIGN_EXTEND (v & 0xFFFFFFFF));
+      }
+    else
+      {
+       operands[5] = gen_highpart (SImode, operands[2]);
+       operands[2] = gen_lowpart (SImode, operands[2]);
+      }
   }"
   [(set_attr "conds" "clob")
    (set_attr "length" "8")]

Reply via email to