This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH ARM] Improve neg[sd]f2 for vfp


This patch improves the code we generate when we have VFP and are using 
negation in some circumstances where the value has to go via integer 
registers.  For exmaple, if we are compiling -with -mfpu=vfp 
-mfloat-abi=softfp and have:

double f;

double a () { return -f; }

we would previously load f into a VFP register, negate it, transfer it to 
r0,r1 and return.   With this patch we can do all that in integer 
registers, generating

a:      ldr     r3, .L3
        ldmia   r3, {r0-r1}
        eor     r0, r0, #-2147483648
        bx      lr
.L3:
	.word	f

Similarly, if we have

double x(void);
void p (int, double);

void q()
{
  p(1, -x());
}

we would end up doing similar contortions.  With the patch we now generate:

q:
        str     lr, [sp, #-4]!
        bl      x
        mov     r2, r1
        eor     r1, r0, #-2147483648
        mov     r0, #1
        ldr     lr, [sp], #4
        b       p

However, if we are already using VFP registers (or if there's an equal 
choice for the register allocator) then we'll still use the VFP fneg[sd] 
instructions.
double a,c;
void z()
{
  c = -a;
}

z:
        ldr     r3, .L11
        fldd    d7, [r3, #0]
        ldr     r3, .L11+4
        fnegd   d7, d7
        fstd    d7, [r3, #0]
        bx      lr

Fully tested on arm-elf and by a series of inspections for VFP code.


Oh, finally I fixed a latent bug.  The constraints on these two patterns 
were using + on operand zero.  That was just bogus.

2005-05-12  Richard Earnshaw  <richard.earnshaw@arm.com>

	* arm/vfp.md (negsf2_vfp): Add alternative using integer registers.
	(negdf2_vfp): Likewise.  Convert to define_insn_and_split and split
	the alternatives using integer registers into the appropriate
	primitives.

Index: config/arm/vfp.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/vfp.md,v
retrieving revision 1.11
diff -p -p -r1.11 vfp.md
*** config/arm/vfp.md	27 Apr 2005 16:09:03 -0000	1.11
--- config/arm/vfp.md	12 May 2005 08:02:08 -0000
***************
*** 298,317 ****
  )
  
  (define_insn "*negsf2_vfp"
!   [(set (match_operand:SF	  0 "s_register_operand" "+w")
! 	(neg:SF (match_operand:SF 1 "s_register_operand" "w")))]
    "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
!   "fnegs%?\\t%0, %1"
    [(set_attr "predicable" "yes")
     (set_attr "type" "ffarith")]
  )
  
! (define_insn "*negdf2_vfp"
!   [(set (match_operand:DF	  0 "s_register_operand" "+w")
! 	(neg:DF (match_operand:DF 1 "s_register_operand" "w")))]
    "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
!   "fnegd%?\\t%P0, %P1"
    [(set_attr "predicable" "yes")
     (set_attr "type" "ffarith")]
  )
  
--- 298,356 ----
  )
  
  (define_insn "*negsf2_vfp"
!   [(set (match_operand:SF	  0 "s_register_operand" "=w,?r")
! 	(neg:SF (match_operand:SF 1 "s_register_operand" "w,r")))]
    "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
!   "@
!    fnegs%?\\t%0, %1
!    eor%?\\t%0, %1, #-2147483648"
    [(set_attr "predicable" "yes")
     (set_attr "type" "ffarith")]
  )
  
! (define_insn_and_split "*negdf2_vfp"
!   [(set (match_operand:DF	  0 "s_register_operand" "=w,?r,?r")
! 	(neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
    "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
!   "@
!    fnegd%?\\t%P0, %P1
!    #
!    #"
!   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP && reload_completed
!    && arm_general_register_operand (operands[0], DFmode)"
!   [(set (match_dup 0) (match_dup 1))]
!   "
!   if (REGNO (operands[0]) == REGNO (operands[1]))
!     {
!       operands[0] = gen_highpart (SImode, operands[0]);
!       operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
!     }
!   else
!     {
!       rtx in_hi, in_lo, out_hi, out_lo;
! 
!       in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
! 			   GEN_INT (0x80000000));
!       in_lo = gen_lowpart (SImode, operands[1]);
!       out_hi = gen_highpart (SImode, operands[0]);
!       out_lo = gen_lowpart (SImode, operands[0]);
! 
!       if (REGNO (in_lo) == REGNO (out_hi))
!         {
!           emit_insn (gen_rtx_SET (SImode, out_lo, in_lo));
! 	  operands[0] = out_hi;
!           operands[1] = in_hi;
!         }
!       else
!         {
!           emit_insn (gen_rtx_SET (SImode, out_hi, in_hi));
! 	  operands[0] = out_lo;
!           operands[1] = in_lo;
!         }
!     }
!   "
    [(set_attr "predicable" "yes")
+    (set_attr "length" "4,4,8")
     (set_attr "type" "ffarith")]
  )
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]