ppc regression

David Edelsohn dje@watson.ibm.com
Sat Jun 19 00:15:00 GMT 1999


	The following patch seems to handle the non-offsettable memory
operands.  I have applied it to the mainline trunk.  You can slide it
over to the gcc-2.95 release branch whenever you think it is appropriate.

David

	* rs6000.c (find_addr_reg): New function.
	* rs6000.h (find_addr_reg): Declare.
	(offsettable_addr_operand): Delete.
	* rs6000.md (movdf_hardfloat32): Handle non-offsettable loads
	from and stores to GPRs.

Index: rs6000.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.74
diff -c -p -r1.74 rs6000.c
*** rs6000.c	1999/06/14 14:33:46	1.74
--- rs6000.c	1999/06/19 06:54:46
*************** rs6000_encode_section_info (decl)
*** 5681,5687 ****
--- 5681,5713 ----
  }
  
  #endif /* USING_SVR4_H */
+ 
  
+ /* Return a REG that occurs in ADDR with coefficient 1.
+    ADDR can be effectively incremented by incrementing REG.  */
+ 
+ struct rtx_def *
+ find_addr_reg (addr)
+      rtx addr;
+ {
+   while (GET_CODE (addr) == PLUS)
+     {
+       if (GET_CODE (XEXP (addr, 0)) == REG)
+ 	addr = XEXP (addr, 0);
+       else if (GET_CODE (XEXP (addr, 1)) == REG)
+ 	addr = XEXP (addr, 1);
+       else if (CONSTANT_P (XEXP (addr, 0)))
+ 	addr = XEXP (addr, 1);
+       else if (CONSTANT_P (XEXP (addr, 1)))
+ 	addr = XEXP (addr, 0);
+       else
+ 	abort ();
+     }
+   if (GET_CODE (addr) == REG)
+     return addr;
+   abort ();
+ }
+ 
  void
  rs6000_fatal_bad_address (op)
    rtx op;
Index: rs6000.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.51
diff -c -p -r1.51 rs6000.h
*** rs6000.h	1999/06/09 16:01:49	1.51
--- rs6000.h	1999/06/19 06:54:47
*************** extern int flag_expensive_optimizations;
*** 3224,3236 ****
  extern int frame_pointer_needed;
  
  /* Declare functions in rs6000.c */
- extern int offsettable_mem_operand ();
  extern void optimization_options ();
  extern void output_options ();
  extern void rs6000_override_options ();
  extern void rs6000_file_start ();
  extern struct rtx_def *rs6000_float_const ();
  extern struct rtx_def *rs6000_got_register ();
  extern int direct_return ();
  extern int get_issue_rate ();
  extern int any_operand ();
--- 3224,3236 ----
  extern int frame_pointer_needed;
  
  /* Declare functions in rs6000.c */
  extern void optimization_options ();
  extern void output_options ();
  extern void rs6000_override_options ();
  extern void rs6000_file_start ();
  extern struct rtx_def *rs6000_float_const ();
  extern struct rtx_def *rs6000_got_register ();
+ extern struct rtx_def *find_addr_reg();
  extern int direct_return ();
  extern int get_issue_rate ();
  extern int any_operand ();
*************** extern int got_no_const_operand ();
*** 3249,3255 ****
  extern int num_insns_constant ();
  extern int easy_fp_constant ();
  extern int volatile_mem_operand ();
! extern int offsettable_addr_operand ();
  extern int mem_or_easy_const_operand ();
  extern int add_operand ();
  extern int non_add_cint_operand ();
--- 3249,3255 ----
  extern int num_insns_constant ();
  extern int easy_fp_constant ();
  extern int volatile_mem_operand ();
! extern int offsettable_mem_operand ();
  extern int mem_or_easy_const_operand ();
  extern int add_operand ();
  extern int non_add_cint_operand ();
Index: rs6000.md
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.56
diff -c -p -r1.56 rs6000.md
*** rs6000.md	1999/06/09 16:01:51	1.56
--- rs6000.md	1999/06/19 06:54:47
***************
*** 6307,6314 ****
  ;; The "??" is a kludge until we can figure out a more reasonable way
  ;; of handling these non-offsettable values.
  (define_insn "*movdf_hardfloat32"
!   [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,o,!r,!r,!r,f,f,m")
! 	(match_operand:DF 1 "input_operand" "r,o,r,G,H,F,f,m,f"))]
    "! TARGET_POWERPC64 && TARGET_HARD_FLOAT
     && (gpc_reg_operand (operands[0], DFmode)
         || gpc_reg_operand (operands[1], DFmode))"
--- 6307,6314 ----
  ;; The "??" is a kludge until we can figure out a more reasonable way
  ;; of handling these non-offsettable values.
  (define_insn "*movdf_hardfloat32"
!   [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,!r,!r,!r,f,f,m")
! 	(match_operand:DF 1 "input_operand" "r,m,r,G,H,F,f,m,f"))]
    "! TARGET_POWERPC64 && TARGET_HARD_FLOAT
     && (gpc_reg_operand (operands[0], DFmode)
         || gpc_reg_operand (operands[1], DFmode))"
***************
*** 6320,6343 ****
        abort ();
      case 0:
        /* We normally copy the low-numbered register first.  However, if
! 	 the first register operand 0 is the same as the second register of
! 	 operand 1, we must copy in the opposite order.  */
        if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
  	return \"mr %L0,%L1\;mr %0,%1\";
        else
  	return \"mr %0,%1\;mr %L0,%L1\";
      case 1:
!       /* If the low-address word is used in the address, we must load it
! 	 last.  Otherwise, load it first.  Note that we cannot have
! 	 auto-increment in that case since the address register is known to be
! 	 dead.  */
!       if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
! 			     operands [1], 0))
! 	return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
        else
! 	return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
      case 2:
!       return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
      case 3:
      case 4:
      case 5:
--- 6320,6389 ----
        abort ();
      case 0:
        /* We normally copy the low-numbered register first.  However, if
! 	 the first register operand 0 is the same as the second register
! 	 of operand 1, we must copy in the opposite order.  */
        if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
  	return \"mr %L0,%L1\;mr %0,%1\";
        else
  	return \"mr %0,%1\;mr %L0,%L1\";
      case 1:
!       if (offsettable_memref_p (operands[1]))
! 	{
! 	  /* If the low-address word is used in the address, we must load
! 	     it last.  Otherwise, load it first.  Note that we cannot have
! 	     auto-increment in that case since the address register is
! 	     known to be dead.  */
! 	  if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
! 				 operands[1], 0))
! 	    return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
! 	  else
! 	    return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
! 	}
        else
! 	{
! 	  rtx addreg;
! 
! 	  if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC
! 	      || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
! 	    abort ();
! 
! 	  addreg = find_addr_reg (XEXP (operands[1], 0));
! 	  if (refers_to_regno_p (REGNO (operands[0]),
! 				 REGNO (operands[0]) + 1,
! 				 operands[1], 0))
! 	    {
! 	      output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
! 	      output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
! 	      output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
! 	      return \"{lx|lwzx} %0,%1\";
! 	    }
! 	  else
! 	    {
! 	      output_asm_insn (\"{lx|lwzx} %0,%1\", operands);
! 	      output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
! 	      output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
! 	      output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
! 	      return \"\";
! 	    }
! 	}
      case 2:
!       if (offsettable_memref_p (operands[0]))
! 	return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
!       else
! 	{
! 	  rtx addreg;
! 
! 	  if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC
! 	      || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
! 	    abort ();
! 
! 	  addreg = find_addr_reg (XEXP (operands[0], 0));
! 	  output_asm_insn (\"{stx|stwx} %1,%0\", operands);
! 	  output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
! 	  output_asm_insn (\"{stx|stwx} %L1,%0\", operands);
! 	  output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
! 	  return \"\";
! 	}
      case 3:
      case 4:
      case 5:


More information about the Gcc-patches mailing list