Patchwork [ARM] Fix PR50022

login
register
mail settings
Submitter Ramana Radhakrishnan
Date Aug. 12, 2011, 2:16 p.m.
Message ID <CACUk7=UKi2QgYtDpEeQKw7q2ThLAoXLr+hN-VsvPVF01h-T6jw@mail.gmail.com>
Download mbox | patch
Permalink /patch/109844/
State New
Headers show

Comments

Ramana Radhakrishnan - Aug. 12, 2011, 2:16 p.m.
>
> Use a bool for "emit".  Otherwise OK.

Fixed this and a small thinko in the minor modification from my first
stab at this. Revised patch attached. I'll commit this if there are no
regressions.

Ramana

>
> R.
>
>>
>> final-pr50022-patch.txt
>>
>>
>> diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
>> index 2f7c508..d99d1ce 100644
>> --- a/gcc/config/arm/arm-protos.h
>> +++ b/gcc/config/arm/arm-protos.h
>> @@ -131,8 +131,9 @@ extern const char *output_mov_long_double_arm_from_fpa (rtx *);
>>  extern const char *output_mov_long_double_arm_from_arm (rtx *);
>>  extern const char *output_mov_double_fpa_from_arm (rtx *);
>>  extern const char *output_mov_double_arm_from_fpa (rtx *);
>> -extern const char *output_move_double (rtx *);
>> +extern const char *output_move_double (rtx *, int, int *count);
>>  extern const char *output_move_quad (rtx *);
>> +extern int arm_count_output_move_double_insns (rtx *);
>>  extern const char *output_move_vfp (rtx *operands);
>>  extern const char *output_move_neon (rtx *operands);
>>  extern int arm_attr_length_move_neon (rtx);
>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>> index 6cd80f8..446be81 100644
>> --- a/gcc/config/arm/arm.c
>> +++ b/gcc/config/arm/arm.c
>> @@ -13262,11 +13262,24 @@ output_mov_double_arm_from_fpa (rtx *operands)
>>  /* Output a move between double words.  It must be REG<-MEM
>>     or MEM<-REG.  */
>>  const char *
>> -output_move_double (rtx *operands)
>> +output_move_double (rtx *operands, int emit, int *count)
>>  {
>>    enum rtx_code code0 = GET_CODE (operands[0]);
>>    enum rtx_code code1 = GET_CODE (operands[1]);
>>    rtx otherops[3];
>> +  if (count)
>> +    *count = 1;
>> +
>> +  /* The only case when this might happen is when
>> +     you are looking at the length of a DImode instruction
>> +     that has an invalid constant in it.  */
>> +  if (code0 == REG && code1 != MEM)
>> +    {
>> +      gcc_assert (!emit);
>> +      *count = 2;
>> +      return "";
>> +    }
>> +
>>
>>    if (code0 == REG)
>>      {
>> @@ -13279,35 +13292,49 @@ output_move_double (rtx *operands)
>>        switch (GET_CODE (XEXP (operands[1], 0)))
>>       {
>>       case REG:
>> -       if (TARGET_LDRD
>> -           && !(fix_cm3_ldrd && reg0 == REGNO(XEXP (operands[1], 0))))
>> -         output_asm_insn ("ldr%(d%)\t%0, [%m1]", operands);
>> -       else
>> -         output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands);
>> +
>> +       if (emit)
>> +         {
>> +           if (TARGET_LDRD
>> +               && !(fix_cm3_ldrd && reg0 == REGNO(XEXP (operands[1], 0))))
>> +             output_asm_insn ("ldr%(d%)\t%0, [%m1]", operands);
>> +           else
>> +             output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands);
>> +         }
>>         break;
>>
>>       case PRE_INC:
>>         gcc_assert (TARGET_LDRD);
>> -       output_asm_insn ("ldr%(d%)\t%0, [%m1, #8]!", operands);
>> +       if (emit)
>> +         output_asm_insn ("ldr%(d%)\t%0, [%m1, #8]!", operands);
>> +
>>         break;
>>
>>       case PRE_DEC:
>> -       if (TARGET_LDRD)
>> -         output_asm_insn ("ldr%(d%)\t%0, [%m1, #-8]!", operands);
>> -       else
>> -         output_asm_insn ("ldm%(db%)\t%m1!, %M0", operands);
>> +       if (emit)
>> +         {
>> +           if (TARGET_LDRD)
>> +             output_asm_insn ("ldr%(d%)\t%0, [%m1, #-8]!", operands);
>> +           else
>> +             output_asm_insn ("ldm%(db%)\t%m1!, %M0", operands);
>> +         }
>>         break;
>>
>>       case POST_INC:
>> -       if (TARGET_LDRD)
>> -         output_asm_insn ("ldr%(d%)\t%0, [%m1], #8", operands);
>> -       else
>> -         output_asm_insn ("ldm%(ia%)\t%m1!, %M0", operands);
>> +
>> +       if (emit)
>> +         {
>> +           if (TARGET_LDRD)
>> +             output_asm_insn ("ldr%(d%)\t%0, [%m1], #8", operands);
>> +           else
>> +             output_asm_insn ("ldm%(ia%)\t%m1!, %M0", operands);
>> +         }
>>         break;
>>
>>       case POST_DEC:
>>         gcc_assert (TARGET_LDRD);
>> -       output_asm_insn ("ldr%(d%)\t%0, [%m1], #-8", operands);
>> +       if (emit)
>> +         output_asm_insn ("ldr%(d%)\t%0, [%m1], #-8", operands);
>>         break;
>>
>>       case PRE_MODIFY:
>> @@ -13325,8 +13352,13 @@ output_move_double (rtx *operands)
>>             if (reg_overlap_mentioned_p (otherops[0], otherops[2]))
>>               {
>>                 /* Registers overlap so split out the increment.  */
>> -               output_asm_insn ("add%?\t%1, %1, %2", otherops);
>> -               output_asm_insn ("ldr%(d%)\t%0, [%1] @split", otherops);
>> +               if (emit)
>> +                 {
>> +                   output_asm_insn ("add%?\t%1, %1, %2", otherops);
>> +                   output_asm_insn ("ldr%(d%)\t%0, [%1] @split", otherops);
>> +                 }
>> +               if (count)
>> +                 *count = 2;
>>               }
>>             else
>>               {
>> @@ -13337,11 +13369,20 @@ output_move_double (rtx *operands)
>>                     || GET_CODE (otherops[2]) != CONST_INT
>>                     || (INTVAL (otherops[2]) > -256
>>                         && INTVAL (otherops[2]) < 256))
>> -                 output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops);
>> +                 {
>> +                   if (emit)
>> +                     output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops);
>> +                 }
>>                 else
>>                   {
>> -                   output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
>> -                   output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
>> +                   if (emit)
>> +                     {
>> +                       output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
>> +                       output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
>> +                     }
>> +                   if (count)
>> +                     *count = 2;
>> +
>>                   }
>>               }
>>           }
>> @@ -13354,11 +13395,19 @@ output_move_double (rtx *operands)
>>                 || GET_CODE (otherops[2]) != CONST_INT
>>                 || (INTVAL (otherops[2]) > -256
>>                     && INTVAL (otherops[2]) < 256))
>> -             output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops);
>> +             {
>> +               if (emit)
>> +                 output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops);
>> +             }
>>             else
>>               {
>> -               output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
>> -               output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
>> +               if (emit)
>> +                 {
>> +                   output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
>> +                   output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
>> +                 }
>> +               if (count)
>> +                 *count = 2;
>>               }
>>           }
>>         break;
>> @@ -13371,12 +13420,19 @@ output_move_double (rtx *operands)
>>         /* Use the second register of the pair to avoid problematic
>>            overlap.  */
>>         otherops[1] = operands[1];
>> -       output_asm_insn ("adr%?\t%0, %1", otherops);
>> +       if (emit)
>> +         output_asm_insn ("adr%?\t%0, %1", otherops);
>>         operands[1] = otherops[0];
>> -       if (TARGET_LDRD)
>> -         output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
>> -       else
>> -         output_asm_insn ("ldm%(ia%)\t%1, %M0", operands);
>> +       if (emit)
>> +         {
>> +           if (TARGET_LDRD)
>> +             output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
>> +           else
>> +             output_asm_insn ("ldm%(ia%)\t%1, %M0", operands);
>> +         }
>> +
>> +       if (count)
>> +         *count = 2;
>>         break;
>>
>>         /* ??? This needs checking for thumb2.  */
>> @@ -13395,17 +13451,20 @@ output_move_double (rtx *operands)
>>                     switch ((int) INTVAL (otherops[2]))
>>                       {
>>                       case -8:
>> -                       output_asm_insn ("ldm%(db%)\t%1, %M0", otherops);
>> +                       if (emit)
>> +                         output_asm_insn ("ldm%(db%)\t%1, %M0", otherops);
>>                         return "";
>>                       case -4:
>>                         if (TARGET_THUMB2)
>>                           break;
>> -                       output_asm_insn ("ldm%(da%)\t%1, %M0", otherops);
>> +                       if (emit)
>> +                         output_asm_insn ("ldm%(da%)\t%1, %M0", otherops);
>>                         return "";
>>                       case 4:
>>                         if (TARGET_THUMB2)
>>                           break;
>> -                       output_asm_insn ("ldm%(ib%)\t%1, %M0", otherops);
>> +                       if (emit)
>> +                         output_asm_insn ("ldm%(ib%)\t%1, %M0", otherops);
>>                         return "";
>>                       }
>>                   }
>> @@ -13433,34 +13492,50 @@ output_move_double (rtx *operands)
>>                     if (reg_overlap_mentioned_p (operands[0], otherops[2])
>>                         || (fix_cm3_ldrd && reg0 == REGNO (otherops[1])))
>>                       {
>> -                       output_asm_insn ("add%?\t%0, %1, %2", otherops);
>> -                       output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
>> +                       if (emit)
>> +                         {
>> +                           output_asm_insn ("add%?\t%0, %1, %2", otherops);
>> +                           output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
>> +                         }
>> +                       if (count)
>> +                         *count = 2;
>>                       }
>>                     else
>>                       {
>>                         otherops[0] = operands[0];
>> -                       output_asm_insn ("ldr%(d%)\t%0, [%1, %2]", otherops);
>> +                       if (emit)
>> +                         output_asm_insn ("ldr%(d%)\t%0, [%1, %2]", otherops);
>>                       }
>>                     return "";
>>                   }
>>
>>                 if (GET_CODE (otherops[2]) == CONST_INT)
>> +                 {
>> +                   if (emit)
>> +                     {
>> +                       if (!(const_ok_for_arm (INTVAL (otherops[2]))))
>> +                         output_asm_insn ("sub%?\t%0, %1, #%n2", otherops);
>> +                       else
>> +                         output_asm_insn ("add%?\t%0, %1, %2", otherops);
>> +                     }
>> +
>> +                 }
>> +               else
>>                   {
>> -                   if (!(const_ok_for_arm (INTVAL (otherops[2]))))
>> -                     output_asm_insn ("sub%?\t%0, %1, #%n2", otherops);
>> -                   else
>> +                   if (emit)
>>                       output_asm_insn ("add%?\t%0, %1, %2", otherops);
>>                   }
>> -               else
>> -                 output_asm_insn ("add%?\t%0, %1, %2", otherops);
>>               }
>>             else
>> -             output_asm_insn ("sub%?\t%0, %1, %2", otherops);
>> +             {
>> +               if (emit)
>> +                 output_asm_insn ("sub%?\t%0, %1, %2", otherops);
>> +             }
>>
>>             if (TARGET_LDRD)
>>               return "ldr%(d%)\t%0, [%1]";
>> -
>> -           return "ldm%(ia%)\t%1, %M0";
>> +
>> +             return "ldm%(ia%)\t%1, %M0";
>>           }
>>         else
>>           {
>> @@ -13468,13 +13543,24 @@ output_move_double (rtx *operands)
>>             /* Take care of overlapping base/data reg.  */
>>             if (reg_mentioned_p (operands[0], operands[1]))
>>               {
>> -               output_asm_insn ("ldr%?\t%0, %1", otherops);
>> -               output_asm_insn ("ldr%?\t%0, %1", operands);
>> +               if (emit)
>> +                 {
>> +                   output_asm_insn ("ldr%?\t%0, %1", otherops);
>> +                   output_asm_insn ("ldr%?\t%0, %1", operands);
>> +                 }
>> +               if (count)
>> +                 *count = 2;
>> +
>>               }
>>             else
>>               {
>> -               output_asm_insn ("ldr%?\t%0, %1", operands);
>> -               output_asm_insn ("ldr%?\t%0, %1", otherops);
>> +               if (emit)
>> +                 {
>> +                   output_asm_insn ("ldr%?\t%0, %1", operands);
>> +                   output_asm_insn ("ldr%?\t%0, %1", otherops);
>> +                 }
>> +               if (count)
>> +                 *count = 2;
>>               }
>>           }
>>       }
>> @@ -13488,34 +13574,45 @@ output_move_double (rtx *operands)
>>        switch (GET_CODE (XEXP (operands[0], 0)))
>>          {
>>       case REG:
>> -       if (TARGET_LDRD)
>> -         output_asm_insn ("str%(d%)\t%1, [%m0]", operands);
>> -       else
>> -         output_asm_insn ("stm%(ia%)\t%m0, %M1", operands);
>> +       if (emit)
>> +         {
>> +           if (TARGET_LDRD)
>> +             output_asm_insn ("str%(d%)\t%1, [%m0]", operands);
>> +           else
>> +             output_asm_insn ("stm%(ia%)\t%m0, %M1", operands);
>> +         }
>>         break;
>>
>>          case PRE_INC:
>>         gcc_assert (TARGET_LDRD);
>> -       output_asm_insn ("str%(d%)\t%1, [%m0, #8]!", operands);
>> +       if (emit)
>> +         output_asm_insn ("str%(d%)\t%1, [%m0, #8]!", operands);
>>         break;
>>
>>          case PRE_DEC:
>> -       if (TARGET_LDRD)
>> -         output_asm_insn ("str%(d%)\t%1, [%m0, #-8]!", operands);
>> -       else
>> -         output_asm_insn ("stm%(db%)\t%m0!, %M1", operands);
>> +       if (emit)
>> +         {
>> +           if (TARGET_LDRD)
>> +             output_asm_insn ("str%(d%)\t%1, [%m0, #-8]!", operands);
>> +           else
>> +             output_asm_insn ("stm%(db%)\t%m0!, %M1", operands);
>> +         }
>>         break;
>>
>>          case POST_INC:
>> -       if (TARGET_LDRD)
>> -         output_asm_insn ("str%(d%)\t%1, [%m0], #8", operands);
>> -       else
>> -         output_asm_insn ("stm%(ia%)\t%m0!, %M1", operands);
>> +       if (emit)
>> +         {
>> +           if (TARGET_LDRD)
>> +             output_asm_insn ("str%(d%)\t%1, [%m0], #8", operands);
>> +           else
>> +             output_asm_insn ("stm%(ia%)\t%m0!, %M1", operands);
>> +         }
>>         break;
>>
>>          case POST_DEC:
>>         gcc_assert (TARGET_LDRD);
>> -       output_asm_insn ("str%(d%)\t%1, [%m0], #-8", operands);
>> +       if (emit)
>> +         output_asm_insn ("str%(d%)\t%1, [%m0], #-8", operands);
>>         break;
>>
>>       case PRE_MODIFY:
>> @@ -13533,19 +13630,35 @@ output_move_double (rtx *operands)
>>           {
>>             if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
>>               {
>> -               output_asm_insn ("str%?\t%0, [%1, %2]!", otherops);
>> -               output_asm_insn ("str%?\t%H0, [%1, #4]", otherops);
>> +               if (emit)
>> +                 {
>> +                   output_asm_insn ("str%?\t%0, [%1, %2]!", otherops);
>> +                   output_asm_insn ("str%?\t%H0, [%1, #4]", otherops);
>> +                 }
>> +               if (count)
>> +                 *count = 2;
>>               }
>>             else
>>               {
>> -               output_asm_insn ("str%?\t%H0, [%1, #4]", otherops);
>> -               output_asm_insn ("str%?\t%0, [%1], %2", otherops);
>> +               if (emit)
>> +                 {
>> +                   output_asm_insn ("str%?\t%H0, [%1, #4]", otherops);
>> +                   output_asm_insn ("str%?\t%0, [%1], %2", otherops);
>> +                 }
>> +               if (count)
>> +                 *count = 2;
>>               }
>>           }
>>         else if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
>> -         output_asm_insn ("str%(d%)\t%0, [%1, %2]!", otherops);
>> +         {
>> +           if (emit)
>> +             output_asm_insn ("str%(d%)\t%0, [%1, %2]!", otherops);
>> +         }
>>         else
>> -         output_asm_insn ("str%(d%)\t%0, [%1], %2", otherops);
>> +         {
>> +           if (emit)
>> +             output_asm_insn ("str%(d%)\t%0, [%1], %2", otherops);
>> +         }
>>         break;
>>
>>       case PLUS:
>> @@ -13555,19 +13668,22 @@ output_move_double (rtx *operands)
>>             switch ((int) INTVAL (XEXP (XEXP (operands[0], 0), 1)))
>>               {
>>               case -8:
>> -               output_asm_insn ("stm%(db%)\t%m0, %M1", operands);
>> +               if (emit)
>> +                 output_asm_insn ("stm%(db%)\t%m0, %M1", operands);
>>                 return "";
>>
>>               case -4:
>>                 if (TARGET_THUMB2)
>>                   break;
>> -               output_asm_insn ("stm%(da%)\t%m0, %M1", operands);
>> +               if (emit)
>> +                 output_asm_insn ("stm%(da%)\t%m0, %M1", operands);
>>                 return "";
>>
>>               case 4:
>>                 if (TARGET_THUMB2)
>>                   break;
>> -               output_asm_insn ("stm%(ib%)\t%m0, %M1", operands);
>> +               if (emit)
>> +                 output_asm_insn ("stm%(ib%)\t%m0, %M1", operands);
>>                 return "";
>>               }
>>           }
>> @@ -13580,7 +13696,8 @@ output_move_double (rtx *operands)
>>           {
>>             otherops[0] = operands[1];
>>             otherops[1] = XEXP (XEXP (operands[0], 0), 0);
>> -           output_asm_insn ("str%(d%)\t%0, [%1, %2]", otherops);
>> +           if (emit)
>> +             output_asm_insn ("str%(d%)\t%0, [%1, %2]", otherops);
>>             return "";
>>           }
>>         /* Fall through */
>> @@ -13588,8 +13705,14 @@ output_move_double (rtx *operands)
>>          default:
>>         otherops[0] = adjust_address (operands[0], SImode, 4);
>>         otherops[1] = operands[1];
>> -       output_asm_insn ("str%?\t%1, %0", operands);
>> -       output_asm_insn ("str%?\t%H1, %0", otherops);
>> +       if (emit)
>> +         {
>> +           output_asm_insn ("str%?\t%1, %0", operands);
>> +           output_asm_insn ("str%?\t%H1, %0", otherops);
>> +         }
>> +       if (count)
>> +         *count = 2;
>> +
>>       }
>>      }
>>
>> @@ -24183,4 +24306,13 @@ arm_attr_length_push_multi(rtx parallel_op, rtx first_op)
>>    return 4;
>>  }
>>
>> +/* Compute the number of instructions emitted by output_move_double.  */
>> +int
>> +arm_count_output_move_double_insns (rtx *operands)
>> +{
>> +  int count;
>> +  output_move_double (operands, 0, &count);
>> +  return count;
>> +}
>> +
>>  #include "gt-arm.h"
>> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
>> index 3d4dcfa..082ded4 100644
>> --- a/gcc/config/arm/arm.md
>> +++ b/gcc/config/arm/arm.md
>> @@ -4981,7 +4981,7 @@
>>      case 2:
>>        return \"#\";
>>      default:
>> -      return output_move_double (operands);
>> +      return output_move_double (operands, 1, NULL);
>>      }
>>    "
>>    [(set_attr "length" "8,12,16,8,8")
>> @@ -6341,7 +6341,7 @@
>>      case 2:
>>        return \"#\";
>>      default:
>> -      return output_move_double (operands);
>> +      return output_move_double (operands, 1, NULL);
>>      }
>>    "
>>    [(set_attr "length" "8,12,16,8,8")
>> @@ -10315,6 +10315,7 @@
>>    [(set (match_operand:SI 0 "s_register_operand" "=r,r")
>>       (if_then_else:SI (match_operator 4 "arm_comparison_operator"
>>                         [(match_operand 3 "cc_register" "") (const_int 0)])
>> +
>>                        (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
>>                        (not:SI
>>                         (match_operand:SI 2 "s_register_operand" "r,r"))))]
>> diff --git a/gcc/config/arm/cirrus.md b/gcc/config/arm/cirrus.md
>> index f08da0b..e3fe687 100644
>> --- a/gcc/config/arm/cirrus.md
>> +++ b/gcc/config/arm/cirrus.md
>> @@ -1,4 +1,4 @@
>> -;; Cirrus EP9312 "Maverick" ARM floating point co-processor description.
>> +;; CIRRUS EP9312 "Maverick" ARM floating point co-processor description.
>>  ;; Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
>>  ;; Contributed by Red Hat.
>>  ;; Written by Aldy Hernandez (aldyh@redhat.com)
>> @@ -379,7 +379,7 @@
>>        return \"#\";
>>      case 1:
>>      case 2:
>> -      return output_move_double (operands);
>> +      return output_move_double (operands, 1, NULL);
>>
>>      case 3: return \"cfmv64lr%?\\t%V0, %Q1\;cfmv64hr%?\\t%V0, %R1\";
>>      case 4: return \"cfmvr64l%?\\t%Q0, %V1\;cfmvr64h%?\\t%R0, %V1\";
>> @@ -439,7 +439,7 @@
>>      case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
>>      case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
>>      case 2: return \"#\";
>> -    case 3: case 4: return output_move_double (operands);
>> +    case 3: case 4: return output_move_double (operands, 1, NULL);
>>      case 5: return \"cfcpyd%?\\t%V0, %V1\";
>>      case 6: return \"cfldrd%?\\t%V0, %1\";
>>      case 7: return \"cfmvdlr\\t%V0, %Q1\;cfmvdhr%?\\t%V0, %R1\";
>> @@ -466,7 +466,7 @@
>>      case 0:
>>      case 1:
>>      case 2:
>> -      return (output_move_double (operands));
>> +      return (output_move_double (operands, 1, NULL));
>>
>>      case 3: return \"cfmv64lr%?\\t%V0, %Q1\;cfmv64hr%?\\t%V0, %R1\";
>>      case 4: return \"cfmvr64l%?\\t%Q0, %V1\;cfmvr64h%?\\t%R0, %V1\";
>> @@ -522,7 +522,7 @@
>>      {
>>      case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
>>      case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
>> -    case 2: case 3: case 4: return output_move_double (operands);
>> +    case 2: case 3: case 4: return output_move_double (operands, 1, NULL);
>>      case 5: return \"cfcpyd%?\\t%V0, %V1\";
>>      case 6: return \"cfldrd%?\\t%V0, %1\";
>>      case 7: return \"cfmvdlr\\t%V0, %Q1\;cfmvdhr%?\\t%V0, %R1\";
>> diff --git a/gcc/config/arm/fpa.md b/gcc/config/arm/fpa.md
>> index 6e6dd8d..3d41950 100644
>> --- a/gcc/config/arm/fpa.md
>> +++ b/gcc/config/arm/fpa.md
>> @@ -567,7 +567,7 @@
>>      case 0: return \"ldm%(ia%)\\t%m1, %M0\\t%@ double\";
>>      case 1: return \"stm%(ia%)\\t%m0, %M1\\t%@ double\";
>>      case 2: return \"#\";
>> -    case 3: case 4: return output_move_double (operands);
>> +    case 3: case 4: return output_move_double (operands, 1, NULL);
>>      case 5: return \"mvf%?d\\t%0, %1\";
>>      case 6: return \"mnf%?d\\t%0, #%N1\";
>>      case 7: return \"ldf%?d\\t%0, %1\";
>> @@ -657,7 +657,7 @@
>>      default:
>>      case 0: return \"ldm%(ia%)\\t%m1, %M0\\t%@ double\";
>>      case 1: return \"stm%(ia%)\\t%m0, %M1\\t%@ double\";
>> -    case 2: case 3: case 4: return output_move_double (operands);
>> +    case 2: case 3: case 4: return output_move_double (operands, 1, NULL);
>>      case 5: return \"mvf%?d\\t%0, %1\";
>>      case 6: return \"mnf%?d\\t%0, #%N1\";
>>      case 7: return \"ldf%?d\\t%0, %1\";
>> diff --git a/gcc/config/arm/iwmmxt.md b/gcc/config/arm/iwmmxt.md
>> index 7f13ae4..b066157 100644
>> --- a/gcc/config/arm/iwmmxt.md
>> +++ b/gcc/config/arm/iwmmxt.md
>> @@ -76,7 +76,7 @@
>>    switch (which_alternative)
>>      {
>>      default:
>> -      return output_move_double (operands);
>> +      return output_move_double (operands, 1, NULL);
>>      case 0:
>>        return \"#\";
>>      case 3:
>> @@ -173,7 +173,7 @@
>>     case 3: return \"tmrrc%?\\t%Q0, %R0, %1\";
>>     case 4: return \"tmcrr%?\\t%0, %Q1, %R1\";
>>     case 5: return \"#\";
>> -   default: return output_move_double (operands);
>> +   default: return output_move_double (operands, 1, NULL);
>>     }"
>>    [(set_attr "predicable" "yes")
>>     (set_attr "length"         "4,     4,   4,4,4,8,   8,8")
>> diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
>> index 1f9ea67..6d61233 100644
>> --- a/gcc/config/arm/neon.md
>> +++ b/gcc/config/arm/neon.md
>> @@ -190,7 +190,7 @@
>>      case 2: gcc_unreachable ();
>>      case 4: return "vmov\t%Q0, %R0, %P1  @ <mode>";
>>      case 5: return "vmov\t%P0, %Q1, %R1  @ <mode>";
>> -    default: return output_move_double (operands);
>> +    default: return output_move_double (operands, 1, NULL);
>>      }
>>  }
>>   [(set_attr "neon_type" "neon_int_1,*,neon_vmov,*,neon_mrrc,neon_mcr_2_mcrr,*,*,*")
>> diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
>> index 3311ae0..82f96f0 100644
>> --- a/gcc/config/arm/vfp.md
>> +++ b/gcc/config/arm/vfp.md
>> @@ -150,7 +150,7 @@
>>      case 4:
>>      case 5:
>>      case 6:
>> -      return output_move_double (operands);
>> +      return output_move_double (operands, 1, NULL);
>>      case 7:
>>        return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\";
>>      case 8:
>> @@ -199,7 +199,7 @@
>>      case 4:
>>      case 5:
>>      case 6:
>> -      return output_move_double (operands);
>> +      return output_move_double (operands, 1, NULL);
>>      case 7:
>>        return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\";
>>      case 8:
>> @@ -213,10 +213,19 @@
>>      }
>>    "
>>    [(set_attr "type" "*,*,*,*,load2,load2,store2,r_2_f,f_2_r,ffarithd,f_loadd,f_stored")
>> -   (set_attr "length" "4,8,12,16,8,8,8,4,4,4,4,4")
>> +   (set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 8)
>> +                               (eq_attr "alternative" "2") (const_int 12)
>> +                               (eq_attr "alternative" "3") (const_int 16)
>> +                               (eq_attr "alternative" "4,5,6")
>> +                            (symbol_ref
>> +                             "arm_count_output_move_double_insns (operands) \
>> +                                 * 4")]
>> +                              (const_int 4)))
>>     (set_attr "predicable"    "yes")
>>     (set_attr "pool_range"     "*,*,*,*,1020,4096,*,*,*,*,1020,*")
>>     (set_attr "neg_pool_range" "*,*,*,*,1008,0,*,*,*,*,1008,*")
>> +   (set (attr "ce_count")
>> +     (symbol_ref "arm_count_output_move_double_insns (operands)"))
>>     (set_attr "arch"           "t2,any,any,any,a,t2,any,any,any,any,any,any")]
>>   )
>>
>> @@ -427,7 +436,7 @@
>>        case 3: case 4:
>>       return output_move_vfp (operands);
>>        case 5: case 6:
>> -     return output_move_double (operands);
>> +     return output_move_double (operands, 1, NULL);
>>        case 7:
>>       if (TARGET_VFP_SINGLE)
>>         return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";
>> @@ -473,7 +482,7 @@
>>        case 3: case 4:
>>       return output_move_vfp (operands);
>>        case 5: case 6: case 8:
>> -     return output_move_double (operands);
>> +     return output_move_double (operands, 1, NULL);
>>        case 7:
>>       if (TARGET_VFP_SINGLE)
>>         return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";
>
>
>
Matthias Klose - Aug. 14, 2011, 6:12 a.m.
On 08/12/2011 04:16 PM, Ramana Radhakrishnan wrote:
>>> @@ -24183,4 +24306,13 @@ arm_attr_length_push_multi(rtx parallel_op, rtx first_op)
>>>    return 4;
>>>  }
>>>
>>> +/* Compute the number of instructions emitted by output_move_double.  */
>>> +int
>>> +arm_count_output_move_double_insns (rtx *operands)
>>> +{
>>> +  int count;
>>> +  output_move_double (operands, 0, &count);
>>> +  return count;
>>> +}

@@ -24205,4 +24328,13 @@ arm_attr_length_push_multi(rtx parallel_op, rtx first_op)
   return 4;
 }

+/* Compute the number of instructions emitted by output_move_double.  */
+int
+arm_length_output_move_double_insns (rtx *operands)
+{
+  int count;
+  output_move_double (operands, false, &count);
+  return count;
+}
+

fails to build, rename it everywhere if needed.

Patch

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 2f7c508..2353704 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -131,8 +131,9 @@  extern const char *output_mov_long_double_arm_from_fpa (rtx *);
 extern const char *output_mov_long_double_arm_from_arm (rtx *);
 extern const char *output_mov_double_fpa_from_arm (rtx *);
 extern const char *output_mov_double_arm_from_fpa (rtx *);
-extern const char *output_move_double (rtx *);
+extern const char *output_move_double (rtx *, bool, int *count);
 extern const char *output_move_quad (rtx *);
+extern int arm_count_output_move_double_insns (rtx *);
 extern const char *output_move_vfp (rtx *operands);
 extern const char *output_move_neon (rtx *operands);
 extern int arm_attr_length_move_neon (rtx);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index afa989e..4457704 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -13284,11 +13284,24 @@  output_mov_double_arm_from_fpa (rtx *operands)
 /* Output a move between double words.  It must be REG<-MEM
    or MEM<-REG.  */
 const char *
-output_move_double (rtx *operands)
+output_move_double (rtx *operands, bool emit, int *count)
 {
   enum rtx_code code0 = GET_CODE (operands[0]);
   enum rtx_code code1 = GET_CODE (operands[1]);
   rtx otherops[3];
+  if (count)
+    *count = 1;
+
+  /* The only case when this might happen is when 
+     you are looking at the length of a DImode instruction
+     that has an invalid constant in it.  */
+  if (code0 == REG && code1 != MEM)
+    {
+      gcc_assert (!emit);
+      *count = 2;
+      return "";
+    }
+      
 
   if (code0 == REG)
     {
@@ -13301,35 +13314,49 @@  output_move_double (rtx *operands)
       switch (GET_CODE (XEXP (operands[1], 0)))
 	{
 	case REG:
-	  if (TARGET_LDRD
-	      && !(fix_cm3_ldrd && reg0 == REGNO(XEXP (operands[1], 0))))
-	    output_asm_insn ("ldr%(d%)\t%0, [%m1]", operands);
-	  else
-	    output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands);
+
+	  if (emit)
+	    {
+	      if (TARGET_LDRD
+		  && !(fix_cm3_ldrd && reg0 == REGNO(XEXP (operands[1], 0))))
+		output_asm_insn ("ldr%(d%)\t%0, [%m1]", operands);
+	      else
+		output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands);
+	    }
 	  break;
 
 	case PRE_INC:
 	  gcc_assert (TARGET_LDRD);
-	  output_asm_insn ("ldr%(d%)\t%0, [%m1, #8]!", operands);
+	  if (emit)
+	    output_asm_insn ("ldr%(d%)\t%0, [%m1, #8]!", operands);
+	  
 	  break;
 
 	case PRE_DEC:
-	  if (TARGET_LDRD)
-	    output_asm_insn ("ldr%(d%)\t%0, [%m1, #-8]!", operands);
-	  else
-	    output_asm_insn ("ldm%(db%)\t%m1!, %M0", operands);
+	  if (emit)
+	    {
+	      if (TARGET_LDRD)
+		output_asm_insn ("ldr%(d%)\t%0, [%m1, #-8]!", operands);
+	      else
+		output_asm_insn ("ldm%(db%)\t%m1!, %M0", operands);
+	    }
 	  break;
 
 	case POST_INC:
-	  if (TARGET_LDRD)
-	    output_asm_insn ("ldr%(d%)\t%0, [%m1], #8", operands);
-	  else
-	    output_asm_insn ("ldm%(ia%)\t%m1!, %M0", operands);
+	  
+	  if (emit)
+	    {
+	      if (TARGET_LDRD)
+		output_asm_insn ("ldr%(d%)\t%0, [%m1], #8", operands);
+	      else
+		output_asm_insn ("ldm%(ia%)\t%m1!, %M0", operands);
+	    }
 	  break;
 
 	case POST_DEC:
 	  gcc_assert (TARGET_LDRD);
-	  output_asm_insn ("ldr%(d%)\t%0, [%m1], #-8", operands);
+	  if (emit)
+	    output_asm_insn ("ldr%(d%)\t%0, [%m1], #-8", operands);
 	  break;
 
 	case PRE_MODIFY:
@@ -13347,8 +13374,13 @@  output_move_double (rtx *operands)
 	      if (reg_overlap_mentioned_p (otherops[0], otherops[2]))
 		{
 		  /* Registers overlap so split out the increment.  */
-		  output_asm_insn ("add%?\t%1, %1, %2", otherops);
-		  output_asm_insn ("ldr%(d%)\t%0, [%1] @split", otherops);
+		  if (emit)
+		    {
+		      output_asm_insn ("add%?\t%1, %1, %2", otherops);
+		      output_asm_insn ("ldr%(d%)\t%0, [%1] @split", otherops);
+		    }
+		  if (count)
+		    *count = 2;
 		}
 	      else
 		{
@@ -13359,11 +13391,20 @@  output_move_double (rtx *operands)
 		      || GET_CODE (otherops[2]) != CONST_INT
 		      || (INTVAL (otherops[2]) > -256
 			  && INTVAL (otherops[2]) < 256))
-		    output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops);
+		    {
+		      if (emit)
+			output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops);
+		    }
 		  else
 		    {
-		      output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
-		      output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
+		      if (emit)
+			{
+			  output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
+			  output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
+			}
+		      if (count)
+			*count = 2;
+
 		    }
 		}
 	    }
@@ -13376,11 +13417,19 @@  output_move_double (rtx *operands)
 		  || GET_CODE (otherops[2]) != CONST_INT
 		  || (INTVAL (otherops[2]) > -256
 		      && INTVAL (otherops[2]) < 256))
-		output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops);
+		{
+		  if (emit)
+		    output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops);
+		}
 	      else
 		{
-		  output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
-		  output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
+		  if (emit)
+		    {
+		      output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
+		      output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
+		    }
+		  if (count)
+		    *count = 2;
 		}
 	    }
 	  break;
@@ -13393,12 +13442,19 @@  output_move_double (rtx *operands)
 	  /* Use the second register of the pair to avoid problematic
 	     overlap.  */
 	  otherops[1] = operands[1];
-	  output_asm_insn ("adr%?\t%0, %1", otherops);
+	  if (emit)
+	    output_asm_insn ("adr%?\t%0, %1", otherops);
 	  operands[1] = otherops[0];
-	  if (TARGET_LDRD)
-	    output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
-	  else
-	    output_asm_insn ("ldm%(ia%)\t%1, %M0", operands);
+	  if (emit)
+	    {
+	      if (TARGET_LDRD)
+		output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
+	      else
+		output_asm_insn ("ldm%(ia%)\t%1, %M0", operands);
+	    }
+
+	  if (count)
+	    *count = 2;
 	  break;
 
 	  /* ??? This needs checking for thumb2.  */
@@ -13417,17 +13473,20 @@  output_move_double (rtx *operands)
 		      switch ((int) INTVAL (otherops[2]))
 			{
 			case -8:
-			  output_asm_insn ("ldm%(db%)\t%1, %M0", otherops);
+			  if (emit)
+			    output_asm_insn ("ldm%(db%)\t%1, %M0", otherops);
 			  return "";
 			case -4:
 			  if (TARGET_THUMB2)
 			    break;
-			  output_asm_insn ("ldm%(da%)\t%1, %M0", otherops);
+			  if (emit)
+			    output_asm_insn ("ldm%(da%)\t%1, %M0", otherops);
 			  return "";
 			case 4:
 			  if (TARGET_THUMB2)
 			    break;
-			  output_asm_insn ("ldm%(ib%)\t%1, %M0", otherops);
+			  if (emit)
+			    output_asm_insn ("ldm%(ib%)\t%1, %M0", otherops);
 			  return "";
 			}
 		    }
@@ -13455,34 +13514,50 @@  output_move_double (rtx *operands)
 		      if (reg_overlap_mentioned_p (operands[0], otherops[2])
 			  || (fix_cm3_ldrd && reg0 == REGNO (otherops[1])))
 			{
-			  output_asm_insn ("add%?\t%0, %1, %2", otherops);
-			  output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
+			  if (emit)
+			    {
+			      output_asm_insn ("add%?\t%0, %1, %2", otherops);
+			      output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
+			    }
+			  if (count)
+			    *count = 2;
 			}
 		      else
 			{
 			  otherops[0] = operands[0];
-			  output_asm_insn ("ldr%(d%)\t%0, [%1, %2]", otherops);
+			  if (emit)
+			    output_asm_insn ("ldr%(d%)\t%0, [%1, %2]", otherops);
 			}
 		      return "";
 		    }
 
 		  if (GET_CODE (otherops[2]) == CONST_INT)
+		    {							
+		      if (emit)
+			{
+			  if (!(const_ok_for_arm (INTVAL (otherops[2]))))
+			    output_asm_insn ("sub%?\t%0, %1, #%n2", otherops);
+			  else
+			    output_asm_insn ("add%?\t%0, %1, %2", otherops);
+			}
+			
+		    }
+		  else
 		    {
-		      if (!(const_ok_for_arm (INTVAL (otherops[2]))))
-			output_asm_insn ("sub%?\t%0, %1, #%n2", otherops);
-		      else
+		      if (emit)
 			output_asm_insn ("add%?\t%0, %1, %2", otherops);
 		    }
-		  else
-		    output_asm_insn ("add%?\t%0, %1, %2", otherops);
 		}
 	      else
-		output_asm_insn ("sub%?\t%0, %1, %2", otherops);
+		{
+		  if (emit)
+		    output_asm_insn ("sub%?\t%0, %1, %2", otherops);
+		}
 
 	      if (TARGET_LDRD)
 		return "ldr%(d%)\t%0, [%1]";
-
-	      return "ldm%(ia%)\t%1, %M0";
+	      
+		return "ldm%(ia%)\t%1, %M0";
 	    }
 	  else
 	    {
@@ -13490,13 +13565,24 @@  output_move_double (rtx *operands)
 	      /* Take care of overlapping base/data reg.  */
 	      if (reg_mentioned_p (operands[0], operands[1]))
 		{
-		  output_asm_insn ("ldr%?\t%0, %1", otherops);
-		  output_asm_insn ("ldr%?\t%0, %1", operands);
+		  if (emit)
+		    {
+		      output_asm_insn ("ldr%?\t%0, %1", otherops);
+		      output_asm_insn ("ldr%?\t%0, %1", operands);
+		    }
+		  if (count)
+		    *count = 2;
+
 		}
 	      else
 		{
-		  output_asm_insn ("ldr%?\t%0, %1", operands);
-		  output_asm_insn ("ldr%?\t%0, %1", otherops);
+		  if (emit)
+		    {
+		      output_asm_insn ("ldr%?\t%0, %1", operands);
+		      output_asm_insn ("ldr%?\t%0, %1", otherops);
+		    }
+		  if (count)
+		    *count = 2;
 		}
 	    }
 	}
@@ -13510,34 +13596,45 @@  output_move_double (rtx *operands)
       switch (GET_CODE (XEXP (operands[0], 0)))
         {
 	case REG:
-	  if (TARGET_LDRD)
-	    output_asm_insn ("str%(d%)\t%1, [%m0]", operands);
-	  else
-	    output_asm_insn ("stm%(ia%)\t%m0, %M1", operands);
+	  if (emit)
+	    {
+	      if (TARGET_LDRD)
+		output_asm_insn ("str%(d%)\t%1, [%m0]", operands);
+	      else
+		output_asm_insn ("stm%(ia%)\t%m0, %M1", operands);
+	    }
 	  break;
 
         case PRE_INC:
 	  gcc_assert (TARGET_LDRD);
-	  output_asm_insn ("str%(d%)\t%1, [%m0, #8]!", operands);
+	  if (emit)
+	    output_asm_insn ("str%(d%)\t%1, [%m0, #8]!", operands);
 	  break;
 
         case PRE_DEC:
-	  if (TARGET_LDRD)
-	    output_asm_insn ("str%(d%)\t%1, [%m0, #-8]!", operands);
-	  else
-	    output_asm_insn ("stm%(db%)\t%m0!, %M1", operands);
+	  if (emit)
+	    {
+	      if (TARGET_LDRD)
+		output_asm_insn ("str%(d%)\t%1, [%m0, #-8]!", operands);
+	      else
+		output_asm_insn ("stm%(db%)\t%m0!, %M1", operands);
+	    }
 	  break;
 
         case POST_INC:
-	  if (TARGET_LDRD)
-	    output_asm_insn ("str%(d%)\t%1, [%m0], #8", operands);
-	  else
-	    output_asm_insn ("stm%(ia%)\t%m0!, %M1", operands);
+	  if (emit)
+	    {
+	      if (TARGET_LDRD)
+		output_asm_insn ("str%(d%)\t%1, [%m0], #8", operands);
+	      else
+		output_asm_insn ("stm%(ia%)\t%m0!, %M1", operands);
+	    }
 	  break;
 
         case POST_DEC:
 	  gcc_assert (TARGET_LDRD);
-	  output_asm_insn ("str%(d%)\t%1, [%m0], #-8", operands);
+	  if (emit)
+	    output_asm_insn ("str%(d%)\t%1, [%m0], #-8", operands);
 	  break;
 
 	case PRE_MODIFY:
@@ -13555,19 +13652,35 @@  output_move_double (rtx *operands)
 	    {
 	      if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
 		{
-		  output_asm_insn ("str%?\t%0, [%1, %2]!", otherops);
-		  output_asm_insn ("str%?\t%H0, [%1, #4]", otherops);
+		  if (emit)
+		    {
+		      output_asm_insn ("str%?\t%0, [%1, %2]!", otherops);
+		      output_asm_insn ("str%?\t%H0, [%1, #4]", otherops);
+		    }
+		  if (count)
+		    *count = 2;
 		}
 	      else
 		{
-		  output_asm_insn ("str%?\t%H0, [%1, #4]", otherops);
-		  output_asm_insn ("str%?\t%0, [%1], %2", otherops);
+		  if (emit)
+		    {
+		      output_asm_insn ("str%?\t%H0, [%1, #4]", otherops);
+		      output_asm_insn ("str%?\t%0, [%1], %2", otherops);
+		    }
+		  if (count)
+		    *count = 2;
 		}
 	    }
 	  else if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
-	    output_asm_insn ("str%(d%)\t%0, [%1, %2]!", otherops);
+	    {
+	      if (emit)
+		output_asm_insn ("str%(d%)\t%0, [%1, %2]!", otherops);
+	    }
 	  else
-	    output_asm_insn ("str%(d%)\t%0, [%1], %2", otherops);
+	    {
+	      if (emit)
+		output_asm_insn ("str%(d%)\t%0, [%1], %2", otherops);
+	    }
 	  break;
 
 	case PLUS:
@@ -13577,19 +13690,22 @@  output_move_double (rtx *operands)
 	      switch ((int) INTVAL (XEXP (XEXP (operands[0], 0), 1)))
 		{
 		case -8:
-		  output_asm_insn ("stm%(db%)\t%m0, %M1", operands);
+		  if (emit)
+		    output_asm_insn ("stm%(db%)\t%m0, %M1", operands);
 		  return "";
 
 		case -4:
 		  if (TARGET_THUMB2)
 		    break;
-		  output_asm_insn ("stm%(da%)\t%m0, %M1", operands);
+		  if (emit)
+		    output_asm_insn ("stm%(da%)\t%m0, %M1", operands);
 		  return "";
 
 		case 4:
 		  if (TARGET_THUMB2)
 		    break;
-		  output_asm_insn ("stm%(ib%)\t%m0, %M1", operands);
+		  if (emit)
+		    output_asm_insn ("stm%(ib%)\t%m0, %M1", operands);
 		  return "";
 		}
 	    }
@@ -13602,7 +13718,8 @@  output_move_double (rtx *operands)
 	    {
 	      otherops[0] = operands[1];
 	      otherops[1] = XEXP (XEXP (operands[0], 0), 0);
-	      output_asm_insn ("str%(d%)\t%0, [%1, %2]", otherops);
+	      if (emit)
+		output_asm_insn ("str%(d%)\t%0, [%1, %2]", otherops);
 	      return "";
 	    }
 	  /* Fall through */
@@ -13610,8 +13727,14 @@  output_move_double (rtx *operands)
         default:
 	  otherops[0] = adjust_address (operands[0], SImode, 4);
 	  otherops[1] = operands[1];
-	  output_asm_insn ("str%?\t%1, %0", operands);
-	  output_asm_insn ("str%?\t%H1, %0", otherops);
+	  if (emit)
+	    {
+	      output_asm_insn ("str%?\t%1, %0", operands);
+	      output_asm_insn ("str%?\t%H1, %0", otherops);
+	    }
+	  if (count)
+	    *count = 2;
+
 	}
     }
 
@@ -24205,4 +24328,13 @@  arm_attr_length_push_multi(rtx parallel_op, rtx first_op)
   return 4;
 }
 
+/* Compute the number of instructions emitted by output_move_double.  */
+int
+arm_length_output_move_double_insns (rtx *operands)
+{
+  int count;
+  output_move_double (operands, false, &count);
+  return count;
+}
+
 #include "gt-arm.h"
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 3d4dcfa..473bc7c 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -4981,7 +4981,7 @@ 
     case 2:
       return \"#\";
     default:
-      return output_move_double (operands);
+      return output_move_double (operands, true, NULL);
     }
   "
   [(set_attr "length" "8,12,16,8,8")
@@ -6341,7 +6341,7 @@ 
     case 2:
       return \"#\";
     default:
-      return output_move_double (operands);
+      return output_move_double (operands, true, NULL);
     }
   "
   [(set_attr "length" "8,12,16,8,8")
@@ -10315,6 +10315,7 @@ 
   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
 	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
 			  [(match_operand 3 "cc_register" "") (const_int 0)])
+
 			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
 			 (not:SI
 			  (match_operand:SI 2 "s_register_operand" "r,r"))))]
diff --git a/gcc/config/arm/cirrus.md b/gcc/config/arm/cirrus.md
index f08da0b..bfd2bb8 100644
--- a/gcc/config/arm/cirrus.md
+++ b/gcc/config/arm/cirrus.md
@@ -1,4 +1,4 @@ 
-;; Cirrus EP9312 "Maverick" ARM floating point co-processor description.
+;; CIRRUS EP9312 "Maverick" ARM floating point co-processor description.
 ;; Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
 ;; Contributed by Red Hat.
 ;; Written by Aldy Hernandez (aldyh@redhat.com)
@@ -379,7 +379,7 @@ 
       return \"#\";
     case 1:
     case 2:
-      return output_move_double (operands);
+      return output_move_double (operands, true, NULL);
 
     case 3: return \"cfmv64lr%?\\t%V0, %Q1\;cfmv64hr%?\\t%V0, %R1\";
     case 4: return \"cfmvr64l%?\\t%Q0, %V1\;cfmvr64h%?\\t%R0, %V1\";
@@ -439,7 +439,7 @@ 
     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
     case 2: return \"#\";
-    case 3: case 4: return output_move_double (operands);
+    case 3: case 4: return output_move_double (operands, true, NULL);
     case 5: return \"cfcpyd%?\\t%V0, %V1\";
     case 6: return \"cfldrd%?\\t%V0, %1\";
     case 7: return \"cfmvdlr\\t%V0, %Q1\;cfmvdhr%?\\t%V0, %R1\";
@@ -466,7 +466,7 @@ 
     case 0:
     case 1:
     case 2:
-      return (output_move_double (operands));
+      return (output_move_double (operands, true, NULL));
 
     case 3: return \"cfmv64lr%?\\t%V0, %Q1\;cfmv64hr%?\\t%V0, %R1\";
     case 4: return \"cfmvr64l%?\\t%Q0, %V1\;cfmvr64h%?\\t%R0, %V1\";
@@ -522,7 +522,7 @@ 
     {
     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
-    case 2: case 3: case 4: return output_move_double (operands);
+    case 2: case 3: case 4: return output_move_double (operands, true, NULL);
     case 5: return \"cfcpyd%?\\t%V0, %V1\";
     case 6: return \"cfldrd%?\\t%V0, %1\";
     case 7: return \"cfmvdlr\\t%V0, %Q1\;cfmvdhr%?\\t%V0, %R1\";
diff --git a/gcc/config/arm/fpa.md b/gcc/config/arm/fpa.md
index 6e6dd8d..f2113a9 100644
--- a/gcc/config/arm/fpa.md
+++ b/gcc/config/arm/fpa.md
@@ -567,7 +567,7 @@ 
     case 0: return \"ldm%(ia%)\\t%m1, %M0\\t%@ double\";
     case 1: return \"stm%(ia%)\\t%m0, %M1\\t%@ double\";
     case 2: return \"#\";
-    case 3: case 4: return output_move_double (operands);
+    case 3: case 4: return output_move_double (operands, true, NULL);
     case 5: return \"mvf%?d\\t%0, %1\";
     case 6: return \"mnf%?d\\t%0, #%N1\";
     case 7: return \"ldf%?d\\t%0, %1\";
@@ -657,7 +657,7 @@ 
     default:
     case 0: return \"ldm%(ia%)\\t%m1, %M0\\t%@ double\";
     case 1: return \"stm%(ia%)\\t%m0, %M1\\t%@ double\";
-    case 2: case 3: case 4: return output_move_double (operands);
+    case 2: case 3: case 4: return output_move_double (operands, true, NULL);
     case 5: return \"mvf%?d\\t%0, %1\";
     case 6: return \"mnf%?d\\t%0, #%N1\";
     case 7: return \"ldf%?d\\t%0, %1\";
diff --git a/gcc/config/arm/iwmmxt.md b/gcc/config/arm/iwmmxt.md
index 7f13ae4..bc0b80d 100644
--- a/gcc/config/arm/iwmmxt.md
+++ b/gcc/config/arm/iwmmxt.md
@@ -76,7 +76,7 @@ 
   switch (which_alternative)
     {
     default:
-      return output_move_double (operands);
+      return output_move_double (operands, true, NULL);
     case 0:
       return \"#\";
     case 3:
@@ -173,7 +173,7 @@ 
    case 3: return \"tmrrc%?\\t%Q0, %R0, %1\";
    case 4: return \"tmcrr%?\\t%0, %Q1, %R1\";
    case 5: return \"#\";
-   default: return output_move_double (operands);
+   default: return output_move_double (operands, true, NULL);
    }"
   [(set_attr "predicable" "yes")
    (set_attr "length"         "4,     4,   4,4,4,8,   8,8")
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 1f9ea67..24dd941 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -190,7 +190,7 @@ 
     case 2: gcc_unreachable ();
     case 4: return "vmov\t%Q0, %R0, %P1  @ <mode>";
     case 5: return "vmov\t%P0, %Q1, %R1  @ <mode>";
-    default: return output_move_double (operands);
+    default: return output_move_double (operands, true, NULL);
     }
 }
  [(set_attr "neon_type" "neon_int_1,*,neon_vmov,*,neon_mrrc,neon_mcr_2_mcrr,*,*,*")
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index 3311ae0..991b517 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -150,7 +150,7 @@ 
     case 4:
     case 5:
     case 6:
-      return output_move_double (operands);
+      return output_move_double (operands, true, NULL);
     case 7:
       return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\";
     case 8:
@@ -199,7 +199,7 @@ 
     case 4:
     case 5:
     case 6:
-      return output_move_double (operands);
+      return output_move_double (operands, true, NULL);
     case 7:
       return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\";
     case 8:
@@ -213,10 +213,19 @@ 
     }
   "
   [(set_attr "type" "*,*,*,*,load2,load2,store2,r_2_f,f_2_r,ffarithd,f_loadd,f_stored")
-   (set_attr "length" "4,8,12,16,8,8,8,4,4,4,4,4")
+   (set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 8)
+                               (eq_attr "alternative" "2") (const_int 12)
+                               (eq_attr "alternative" "3") (const_int 16)
+                               (eq_attr "alternative" "4,5,6") 
+			       (symbol_ref 
+				"arm_count_output_move_double_insns (operands) \
+                                 * 4")]
+                              (const_int 4)))
    (set_attr "predicable"    "yes")
    (set_attr "pool_range"     "*,*,*,*,1020,4096,*,*,*,*,1020,*")
    (set_attr "neg_pool_range" "*,*,*,*,1008,0,*,*,*,*,1008,*")
+   (set (attr "ce_count") 
+	(symbol_ref "get_attr_length (insn) / 4"))
    (set_attr "arch"           "t2,any,any,any,a,t2,any,any,any,any,any,any")]
  )
 
@@ -427,7 +436,7 @@ 
       case 3: case 4:
 	return output_move_vfp (operands);
       case 5: case 6:
-	return output_move_double (operands);
+	return output_move_double (operands, true, NULL);
       case 7:
 	if (TARGET_VFP_SINGLE)
 	  return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";
@@ -473,7 +482,7 @@ 
       case 3: case 4:
 	return output_move_vfp (operands);
       case 5: case 6: case 8:
-	return output_move_double (operands);
+	return output_move_double (operands, true, NULL);
       case 7:
 	if (TARGET_VFP_SINGLE)
 	  return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";