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]

i386 string operations fix 3



Hi
Jakub asked me to take a look at the testcase:

/* { dg-do compile { target i?86-*-* } } */
/* { dg-options "-Os -fpic" } */

#include <string.h>

typedef struct
{
  char *a;
  char *b;
} *foo;

void
bar (foo x)
{
  char *c = x->b;
  char *d = (void *)0;
  unsigned int e = 0, f = 0, g;
  while (*c != ':')
    if (*c == '%')
      {
        ++c;
        switch (*c++)
          {
          case 'N':
            g = strlen (x->a);
            if (e + g >= f) {
		char *h = d;
		f += 256 + g;
		d = (char *) __builtin_alloca (f);
		memcpy (d, h, e);
	    };
            memcpy (&d[e], x->a, g);
            e += g;
            break;
	  }
      }
}

That produces crash in reload.  The purpose is rep_movsi pattern that
accept destination with an address_operand predicate, but only the "D"
constraint. The comment says that it is to allow strength reduction to
offset the reference and that reload should load the address into edi
when needed.  This worked (more by an accident) for old backend, where
move expander got an address operand and resulted into lea or plus pattern.
On the current backend it fails, since plus pattern requires flags clobber
and lea won't match when the destination gets reloaded to memory.

I don't think we want reload to handle such case and it seems to me
cleanest solution to change that predicate back to register_operand.  This
fixes the bug and strength reduction should know how to handle backends w/o
addressable references now anyway.

To avoid large rejects, I've boundled it together with my previous fix
to same area not reviewed yet.  The problem fixed was:

1) the strset patterns was modeling destination register to double
   (not to be increased by the size of block)
2) use address_operand for memory expressions so loop.c and integrate
   is happy
3) Don't use match_dup of input operands for outputs, so SSA form of
   patterns is possible
4) canonicalizes the ashift inside the plus, so my checker is happy
5) Puts uses last - some parts of gcc seems to assume this.

Note that I didn't had chance to bootstrap this patch yet, but I've
bootstrapped and tested equivalent in my local tree.  I will let you know in
case of troubles.

Honza

Thu Aug  3 18:21:24 MET DST 2000  Jan Hubicka  <jh@suse.cz>
	* i386.md (strmovsi_1, strmovhi_1 strmovqi_1):
	Do not use match_dup of input operands at outputs.
	Use register_operand for memory expression.
	(rep_movsi): Put use last, canonicalize.
	Use register_operand for memory expression.
	(rep_movqi): Put use last.
	Use register_operand for memory expression.
	(strsetsi_1, strset_hi_1, strsetqi_1): Do not use match_dup
	of input operands at outputs.  Use register_operand for memory
	expression.
	(rep_stossi): Put use last; canonicalize; fix match_dup in
	the address expression
	(rep_stosqi): Likewise.
	(memcmp expander): Update calls.
	(cmpstrsi_nz_1, cmpstrsi_1, strlensi_1): Avoid match_dups in
	the clobbers.
Index: egcs/gcc/config/i386//i386.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.172
diff -c -3 -p -r1.172 i386.md
*** i386.md	2000/08/21 15:10:42	1.172
--- i386.md	2000/08/22 22:21:45
***************
*** 9595,9604 ****
    [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
  	(mem:SI (match_operand:SI 3 "register_operand" "1")))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 0)
  		 (const_int 4)))
     (set (match_operand:SI 1 "register_operand" "=S")
! 	(plus:SI (match_dup 1)
  		 (const_int 4)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
--- 9595,9604 ----
    [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
  	(mem:SI (match_operand:SI 3 "register_operand" "1")))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 2)
  		 (const_int 4)))
     (set (match_operand:SI 1 "register_operand" "=S")
! 	(plus:SI (match_dup 3)
  		 (const_int 4)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
***************
*** 9611,9620 ****
    [(set (mem:HI (match_operand:SI 2 "register_operand" "0"))
  	(mem:HI (match_operand:SI 3 "register_operand" "1")))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 0)
  		 (const_int 2)))
     (set (match_operand:SI 1 "register_operand" "=S")
! 	(plus:SI (match_dup 1)
  		 (const_int 2)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
--- 9611,9620 ----
    [(set (mem:HI (match_operand:SI 2 "register_operand" "0"))
  	(mem:HI (match_operand:SI 3 "register_operand" "1")))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 2)
  		 (const_int 2)))
     (set (match_operand:SI 1 "register_operand" "=S")
! 	(plus:SI (match_dup 3)
  		 (const_int 2)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
***************
*** 9627,9636 ****
    [(set (mem:QI (match_operand:SI 2 "register_operand" "0"))
  	(mem:QI (match_operand:SI 3 "register_operand" "1")))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 0)
  		 (const_int 1)))
     (set (match_operand:SI 1 "register_operand" "=S")
! 	(plus:SI (match_dup 1)
  		 (const_int 1)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
--- 9627,9636 ----
    [(set (mem:QI (match_operand:SI 2 "register_operand" "0"))
  	(mem:QI (match_operand:SI 3 "register_operand" "1")))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 2)
  		 (const_int 1)))
     (set (match_operand:SI 1 "register_operand" "=S")
! 	(plus:SI (match_dup 3)
  		 (const_int 1)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
***************
*** 9639,9659 ****
     (set_attr "memory" "both")
     (set_attr "mode" "QI")])
  
- ;; It might seem that operands 3 & 4 could use predicate register_operand.
- ;; But strength reduction might offset the MEM expression.  So we let
- ;; reload put the address into %edi & %esi.
- 
  (define_insn "rep_movsi"
    [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
-    (use (match_operand:SI 5 "register_operand" "2"))
     (set (match_operand:SI 0 "register_operand" "=D") 
!         (plus:SI (match_operand:SI 3 "address_operand" "0")
! 	         (ashift:SI (match_dup 5) (const_int 2))))
     (set (match_operand:SI 1 "register_operand" "=S") 
!         (plus:SI (match_operand:SI 4 "address_operand" "1")
! 	         (ashift:SI (match_dup 5) (const_int 2))))
     (set (mem:BLK (match_dup 3))
  	(mem:BLK (match_dup 4)))
     (use (reg:SI 19))]
    ""
    "rep\;movsl|rep movsd"
--- 9639,9656 ----
     (set_attr "memory" "both")
     (set_attr "mode" "QI")])
  
  (define_insn "rep_movsi"
    [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
     (set (match_operand:SI 0 "register_operand" "=D") 
!         (plus:SI (ashift:SI (match_operand:SI 5 "register_operand" "2")
! 			    (const_int 2))
! 		 (match_operand:SI 3 "register_operand" "0")))
     (set (match_operand:SI 1 "register_operand" "=S") 
!         (plus:SI (ashift:SI (match_dup 5) (const_int 2))
! 		 (match_operand:SI 4 "register_operand" "1")))
     (set (mem:BLK (match_dup 3))
  	(mem:BLK (match_dup 4)))
+    (use (match_dup 5))
     (use (reg:SI 19))]
    ""
    "rep\;movsl|rep movsd"
***************
*** 9664,9676 ****
  
  (define_insn "rep_movqi"
    [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
-    (use (match_operand:SI 5 "register_operand" "2"))
     (set (match_operand:SI 0 "register_operand" "=D") 
!         (plus:SI (match_operand:SI 3 "address_operand" "0") (match_dup 5)))
     (set (match_operand:SI 1 "register_operand" "=S") 
!         (plus:SI (match_operand:SI 4 "address_operand" "1") (match_dup 5)))
     (set (mem:BLK (match_dup 3))
  	(mem:BLK (match_dup 4)))
     (use (reg:SI 19))]
    ""
    "rep\;movsb|rep movsb"
--- 9661,9674 ----
  
  (define_insn "rep_movqi"
    [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
     (set (match_operand:SI 0 "register_operand" "=D") 
!         (plus:SI (match_operand:SI 3 "register_operand" "0")
! 		 (match_operand:SI 5 "register_operand" "2")))
     (set (match_operand:SI 1 "register_operand" "=S") 
!         (plus:SI (match_operand:SI 4 "register_operand" "1") (match_dup 5)))
     (set (mem:BLK (match_dup 3))
  	(mem:BLK (match_dup 4)))
+    (use (match_dup 5))
     (use (reg:SI 19))]
    ""
    "rep\;movsb|rep movsb"
***************
*** 9899,9905 ****
    [(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
  	(match_operand:SI 2 "register_operand" "a"))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 0)
  		 (const_int 4)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
--- 9897,9903 ----
    [(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
  	(match_operand:SI 2 "register_operand" "a"))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 1)
  		 (const_int 4)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
***************
*** 9912,9918 ****
    [(set (mem:HI (match_operand:SI 1 "register_operand" "0"))
  	(match_operand:HI 2 "register_operand" "a"))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 0)
  		 (const_int 2)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
--- 9910,9916 ----
    [(set (mem:HI (match_operand:SI 1 "register_operand" "0"))
  	(match_operand:HI 2 "register_operand" "a"))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 1)
  		 (const_int 2)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
***************
*** 9925,9931 ****
    [(set (mem:QI (match_operand:SI 1 "register_operand" "0"))
  	(match_operand:QI 2 "register_operand" "a"))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 0)
  		 (const_int 1)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
--- 9923,9929 ----
    [(set (mem:QI (match_operand:SI 1 "register_operand" "0"))
  	(match_operand:QI 2 "register_operand" "a"))
     (set (match_operand:SI 0 "register_operand" "=D")
! 	(plus:SI (match_dup 1)
  		 (const_int 1)))
     (use (reg:SI 19))]
    "TARGET_SINGLE_STRINGOP || optimize_size"
***************
*** 9934,9952 ****
     (set_attr "memory" "store")
     (set_attr "mode" "QI")])
  
- ;; It might seem that operand 0 could use predicate register_operand.
- ;; But strength reduction might offset the MEM expression.  So we let
- ;; reload put the address into %edi.
- 
  (define_insn "rep_stossi"
    [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
-    (use (match_operand:SI 2 "register_operand" "a"))
-    (use (match_operand:SI 4 "register_operand" "1"))
     (set (match_operand:SI 0 "register_operand" "=D") 
!         (plus:SI (match_operand:SI 3 "address_operand" "0")
! 	         (ashift:SI (match_dup 3) (const_int 2))))
     (set (mem:BLK (match_dup 3))
  	(const_int 0))
     (use (reg:SI 19))]
    ""
    "rep\;stosl|rep stosd"
--- 9932,9947 ----
     (set_attr "memory" "store")
     (set_attr "mode" "QI")])
  
  (define_insn "rep_stossi"
    [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
     (set (match_operand:SI 0 "register_operand" "=D") 
!         (plus:SI (ashift:SI (match_operand:SI 4 "register_operand" "1")
! 			    (const_int 2))
! 		 (match_operand:SI 3 "register_operand" "0")))
     (set (mem:BLK (match_dup 3))
  	(const_int 0))
+    (use (match_operand:SI 2 "register_operand" "a"))
+    (use (match_dup 4))
     (use (reg:SI 19))]
    ""
    "rep\;stosl|rep stosd"
***************
*** 9957,9968 ****
  
  (define_insn "rep_stosqi"
    [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
-    (use (match_operand:QI 2 "register_operand" "a"))
-    (use (match_operand:SI 4 "register_operand" "1"))
     (set (match_operand:SI 0 "register_operand" "=D") 
!         (plus:SI (match_operand:SI 3 "address_operand" "0") (match_dup 3)))
     (set (mem:BLK (match_dup 3))
  	(const_int 0))
     (use (reg:SI 19))]
    ""
    "rep\;stosb|rep stosb"
--- 9952,9964 ----
  
  (define_insn "rep_stosqi"
    [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
     (set (match_operand:SI 0 "register_operand" "=D") 
!         (plus:SI (match_operand:SI 3 "register_operand" "0")
! 		 (match_operand:SI 4 "register_operand" "1")))
     (set (mem:BLK (match_dup 3))
  	(const_int 0))
+    (use (match_operand:QI 2 "register_operand" "a"))
+    (use (match_dup 4))
     (use (reg:SI 19))]
    ""
    "rep\;stosb|rep stosb"
***************
*** 10005,10016 ****
  	  emit_move_insn (operands[0], const0_rtx);
  	  DONE;
  	}
!       emit_insn (gen_cmpstrsi_nz_1 (addr1, addr2, countreg, align));
      }
    else
      {
        emit_insn (gen_cmpsi_1 (countreg, countreg));
!       emit_insn (gen_cmpstrsi_1 (addr1, addr2, countreg, align));
      }
  
    outlow = gen_lowpart (QImode, out);
--- 10001,10014 ----
  	  emit_move_insn (operands[0], const0_rtx);
  	  DONE;
  	}
!       emit_insn (gen_cmpstrsi_nz_1 (addr1, addr2, countreg, align,
! 				    addr1, addr2, countreg));
      }
    else
      {
        emit_insn (gen_cmpsi_1 (countreg, countreg));
!       emit_insn (gen_cmpstrsi_1 (addr1, addr2, countreg, align,
! 				 addr1, addr2, countreg));
      }
  
    outlow = gen_lowpart (QImode, out);
***************
*** 10040,10060 ****
  
  ;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
  ;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
- ;;
- ;; It might seem that operands 0 & 1 could use predicate register_operand.
- ;; But strength reduction might offset the MEM expression.  So we let
- ;; reload put the address into %edi & %esi.
  
  (define_insn "cmpstrsi_nz_1"
    [(set (reg:CC 17)
! 	(compare:CC (mem:BLK (match_operand:SI 0 "address_operand" "S"))
! 		    (mem:BLK (match_operand:SI 1 "address_operand" "D"))))
!    (use (match_operand:SI 2 "register_operand" "c"))
     (use (match_operand:SI 3 "immediate_operand" "i"))
     (use (reg:SI 19))
!    (clobber (match_dup 0))
!    (clobber (match_dup 1))
!    (clobber (match_dup 2))]
    ""
    "repz{\;| }cmpsb"
    [(set_attr "type" "str")
--- 10038,10054 ----
  
  ;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
  ;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
  
  (define_insn "cmpstrsi_nz_1"
    [(set (reg:CC 17)
! 	(compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
! 		    (mem:BLK (match_operand:SI 5 "register_operand" "1"))))
!    (use (match_operand:SI 6 "register_operand" "2"))
     (use (match_operand:SI 3 "immediate_operand" "i"))
     (use (reg:SI 19))
!    (clobber (match_operand:SI 0 "register_operand" "=S"))
!    (clobber (match_operand:SI 1 "register_operand" "=D"))
!    (clobber (match_operand:SI 2 "register_operand" "=c"))]
    ""
    "repz{\;| }cmpsb"
    [(set_attr "type" "str")
***************
*** 10065,10081 ****
  
  (define_insn "cmpstrsi_1"
    [(set (reg:CC 17)
! 	(if_then_else:CC (ne (match_operand:SI 2 "register_operand" "c")
  			     (const_int 0))
! 	  (compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S"))
! 		      (mem:BLK (match_operand:SI 1 "address_operand" "D")))
  	  (const_int 0)))
     (use (match_operand:SI 3 "immediate_operand" "i"))
     (use (reg:CC 17))
     (use (reg:SI 19))
!    (clobber (match_dup 0))
!    (clobber (match_dup 1))
!    (clobber (match_dup 2))]
    ""
    "repz{\;| }cmpsb"
    [(set_attr "type" "str")
--- 10059,10075 ----
  
  (define_insn "cmpstrsi_1"
    [(set (reg:CC 17)
! 	(if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2")
  			     (const_int 0))
! 	  (compare:SI (mem:BLK (match_operand:SI 4 "register_operand" "0"))
! 		      (mem:BLK (match_operand:SI 5 "register_operand" "1")))
  	  (const_int 0)))
     (use (match_operand:SI 3 "immediate_operand" "i"))
     (use (reg:CC 17))
     (use (reg:SI 19))
!    (clobber (match_operand:SI 0 "register_operand" "=S"))
!    (clobber (match_operand:SI 1 "register_operand" "=D"))
!    (clobber (match_operand:SI 2 "register_operand" "=c"))]
    ""
    "repz{\;| }cmpsb"
    [(set_attr "type" "str")
***************
*** 10139,10163 ****
  
        emit_insn (gen_cld ());
        emit_insn (gen_strlensi_1 (scratch1, scratch3, eoschar,
! 				 align, constm1_rtx));
        emit_insn (gen_one_cmplsi2 (scratch2, scratch1));
        emit_insn (gen_addsi3 (out, scratch2, constm1_rtx));
      }
    DONE;
  }")
  
- ;; It might seem that operands 0 & 1 could use predicate register_operand.
- ;; But strength reduction might offset the MEM expression.  So we let
- ;; reload put the address into %edi.
- 
  (define_insn "strlensi_1"
    [(set (match_operand:SI 0 "register_operand" "=&c")
! 	(unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D"))
  		    (match_operand:QI 2 "general_operand" "a")
  		    (match_operand:SI 3 "immediate_operand" "i")
  		    (match_operand:SI 4 "immediate_operand" "0")] 0))
     (use (reg:SI 19))
!    (clobber (match_dup 1))
     (clobber (reg:CC 17))]
    ""
    "repnz{\;| }scasb"
--- 10133,10153 ----
  
        emit_insn (gen_cld ());
        emit_insn (gen_strlensi_1 (scratch1, scratch3, eoschar,
! 				 align, constm1_rtx, scratch3));
        emit_insn (gen_one_cmplsi2 (scratch2, scratch1));
        emit_insn (gen_addsi3 (out, scratch2, constm1_rtx));
      }
    DONE;
  }")
  
  (define_insn "strlensi_1"
    [(set (match_operand:SI 0 "register_operand" "=&c")
! 	(unspec:SI [(mem:BLK (match_operand:SI 5 "register_operand" "1"))
  		    (match_operand:QI 2 "general_operand" "a")
  		    (match_operand:SI 3 "immediate_operand" "i")
  		    (match_operand:SI 4 "immediate_operand" "0")] 0))
     (use (reg:SI 19))
!    (clobber (match_operand:SI 1 "register_operand" "=D"))
     (clobber (reg:CC 17))]
    ""
    "repnz{\;| }scasb"

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