2014-08-26 Yvan Roux <yvan.roux@linaro.org>
authoryroux <yroux@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 26 Aug 2014 12:53:08 +0000 (12:53 +0000)
committeryroux <yroux@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 26 Aug 2014 12:53:08 +0000 (12:53 +0000)
Backport from trunk r213711.
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.

git-svn-id: svn://gcc.gnu.org/svn/gcc/branches/linaro/gcc-4_9-branch@214514 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 2caabdf..e1fc0ee 100644 (file)
@@ -1,5 +1,14 @@
 2014-08-26  Yvan Roux  <yvan.roux@linaro.org>
 
+       Backport from trunk r213711.
+       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-26  Yvan Roux  <yvan.roux@linaro.org>
+
        Backport from trunk r213632.
        2014-08-05  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
index 3833654..75b8406 100644 (file)
@@ -1005,7 +1005,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);
 
@@ -1106,29 +1106,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)