This is the mail archive of the 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]

Old patch: combine.c/ tweaks to improve strcmp() builtin

This is an old patch which we never finished discussing.  Its purpose
is to improve the code generated by the x86 back end for strcmp.
Under the right conditions this is compiled to a repz cmpsb
instruction, but then we generate three unnecessary instructions right
afterward.  For instance, the somewhat silly example

  if (!strcmp ("foo", "bar"))

compiles to

        movl    $.LC1, %edi
        movl    $.LC0, %esi
*       seta    %dl
*       setb    %al
*       cmpb    %al, %dl
        jne     .L5
	call	a

without the patch.  The three starred instructions are unnecessary,
and the patch removes them.  [Pretend for the moment that we didn't
know what the strings were at compile time.]

The patch works by (a) fixing a bug in combine.c that causes it not to
recognize the seta/setb/cmp sequence, and (b) adding a dummy 
(set (reg cc) (reg cc)) pattern to so combine thinks it can
make the simplification.  The dummy insn goes away in the next pass
that deletes no-op moves.

It would be better to teach combine to delete no-op moves it
generates; we can get things like (set (pc) (pc)) out of combine as
well as this.  At the moment, however, combine is emphatically not
prepared to do that, and I don't have time to do the legwork.  This
patch is safe, simple, and solves a real problem.

One of the deltas in combine.c just removes a redundant test.  I
generated the combine.c diff with -b so this would be obvious; in my
tree, I corrected the indentation as well.


	* combine.c (try_combine): Remove redundant test.
	(use_crosses_set_p): If the last set has been deleted, it
	doesn't count.
	* (*cc_noop_move, *pc_noop_move): Dummy insns to help

Index: combine.c
--- combine.c	2000/09/19 04:49:44	1.156
+++ combine.c	2000/10/01 01:21:32
@@ -2517,8 +2517,6 @@ try_combine (i3, i2, i1, new_direct_jump
     if (i3_subst_into_i2 && GET_CODE (PATTERN (i2)) == PARALLEL)
-	  {
 	    for (i = 0; i < XVECLEN (PATTERN (i2), 0); i++)
 	      if (GET_CODE (SET_DEST (XVECEXP (PATTERN (i2), 0, i))) == REG
 		  && SET_DEST (XVECEXP (PATTERN (i2), 0, i)) != i2dest
@@ -2532,7 +2530,6 @@ try_combine (i3, i2, i1, new_direct_jump
 		    for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
 		      if (XEXP (link, 0) == i2)
 			XEXP (link, 0) = i3;
-	  }
 	if (i3notes)
@@ -11596,7 +11593,10 @@ use_crosses_set_p (x, from_cuid)
       for (; regno < endreg; regno++)
 	if (reg_last_set[regno]
-	    && INSN_CUID (reg_last_set[regno]) > from_cuid)
+	    /* If the last set has been deleted, it doesn't count.  */
+	    && INSN_CUID (reg_last_set[regno]) > from_cuid
+	    && ! INSN_DELETED_P (reg_last_set [regno])
+	    && GET_CODE (reg_last_set [regno]) != NOTE)
 	  return 1;
       return 0;
Index: config/i386/
--- config/i386/	2000/09/29 11:24:13	1.183
+++ config/i386/	2000/10/01 01:21:33
@@ -1237,6 +1237,19 @@
   [(set_attr "type" "icmp")
    (set_attr "mode" "QI")])
+;; Dummy insns to help combine.
+(define_insn "*cc_nop_move"
+  [(set (reg 17) (reg 17))]
+  ""
+  "* abort ();"
+  [(set_attr "type" "other")])
+(define_insn "*pc_nop_move"
+  [(set (pc) (pc))]
+  ""
+  "* abort ();"
+  [(set_attr "type" "other")])
 ;; These implement float point compares.
 ;; %%% See if we can get away with VOIDmode operands on the actual insns,
 ;; which would allow mix and match FP modes on the compares.  Which is what

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