]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[AArch64] Use MOVN to generate 64-bit negative immediates where sensible
authorIan Bolton <ian.bolton@arm.com>
Thu, 7 Aug 2014 13:42:22 +0000 (13:42 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Thu, 7 Aug 2014 13:42:22 +0000 (13:42 +0000)
* config/aarch64/aarch64.c (aarch64_expand_mov_immediate):
Use MOVN when one of the half-words is 0xffff.

Co-Authored-By: Kyrylo Tkachov <kyrylo.tkachov@arm.com>
From-SVN: r213711

gcc/ChangeLog
gcc/config/aarch64/aarch64.c

index be1e70389b021c6bd5fd035412c1f21c75afc82d..e121b9ead2be029a1e3aa12e2bd1705588c8cb7f 100644 (file)
@@ -1,3 +1,9 @@
+2014-08-07  Ian Bolton  <ian.bolton@arm.com>
+            Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * config/aarch64/aarch64.c (aarch64_expand_mov_immediate):
+       Use MOVN when one of the half-words is 0xffff.
+
 2014-08-07  Marat Zakirov  <m.zakirov@samsung.com>
 
        * config/arm/thumb1.md (*thumb1_movqi_insn): Copy of thumb1_movhi_insn.
index 11654283055996a59a17f721948d0f3cdbb8229b..832bcf36c635f7e124ccd40480b8ca5aa02480eb 100644 (file)
@@ -1006,7 +1006,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
   unsigned HOST_WIDE_INT val;
   bool subtargets;
   rtx subtarget;
-  int one_match, zero_match;
+  int one_match, zero_match, first_not_ffff_match;
 
   gcc_assert (mode == SImode || mode == DImode);
 
@@ -1107,29 +1107,48 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
   one_match = 0;
   zero_match = 0;
   mask = 0xffff;
+  first_not_ffff_match = -1;
 
   for (i = 0; i < 64; i += 16, mask <<= 16)
     {
-      if ((val & mask) == 0)
-       zero_match++;
-      else if ((val & mask) == mask)
+      if ((val & mask) == mask)
        one_match++;
+      else
+       {
+         if (first_not_ffff_match < 0)
+           first_not_ffff_match = i;
+         if ((val & mask) == 0)
+           zero_match++;
+       }
     }
 
   if (one_match == 2)
     {
-      mask = 0xffff;
-      for (i = 0; i < 64; i += 16, mask <<= 16)
+      /* Set one of the quarters and then insert back into result.  */
+      mask = 0xffffll << first_not_ffff_match;
+      emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_INT (val | mask)));
+      emit_insn (gen_insv_immdi (dest, GEN_INT (first_not_ffff_match),
+                                GEN_INT ((val >> first_not_ffff_match)
+                                         & 0xffff)));
+      return;
+    }
+
+  if (one_match > zero_match)
+    {
+      /* Set either first three quarters or all but the third.  */
+      mask = 0xffffll << (16 - first_not_ffff_match);
+      emit_insn (gen_rtx_SET (VOIDmode, dest,
+                             GEN_INT (val | mask | 0xffffffff00000000ull)));
+
+      /* Now insert other two quarters.         */
+      for (i = first_not_ffff_match + 16, mask <<= (first_not_ffff_match << 1);
+          i < 64; i += 16, mask <<= 16)
        {
          if ((val & mask) != mask)
-           {
-             emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_INT (val | mask)));
-             emit_insn (gen_insv_immdi (dest, GEN_INT (i),
-                                        GEN_INT ((val >> i) & 0xffff)));
-             return;
-           }
+           emit_insn (gen_insv_immdi (dest, GEN_INT (i),
+                                      GEN_INT ((val >> i) & 0xffff)));
        }
-      gcc_unreachable ();
+      return;
     }
 
   if (zero_match == 2)