cmov patch

Richard Henderson rth@cygnus.com
Sun Jun 27 02:49:00 GMT 1999


An object lesson not to take anything for granted:

The new ia32 compiler models `testb $imm,%ah' as

  (set (reg:CCNO 17)
        (compare:CCNO
          (and:SI
            (zero_extract:SI
              (reg:SI 0 eax)
              (const_int 8)
              (const_int 8))
            (const_int imm))
          (const_int 0)))

Jump assumed that it could always copy arg0 of the compare (`(and:SI ...)')
to a temporary.  Oops, there is no instruction that does 

  (set (reg:QI tmp)
       (and:QI
	 (subreg:QI
	   (zero_extract:SI
	     (reg:SI 0 eax)
	     (const_int 8)
	     (const_int 8)) 0)
	 (const_int imm)))

Obviously we must validate the copy before commiting to the cmov.

Applied to mainline.


r~


        * jump.c (jump_optimize_1): Validate the cmov copy to a temporary.

Index: jump.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/jump.c,v
retrieving revision 1.147.10.1
retrieving revision 1.147.10.2
diff -c -p -d -r1.147.10.1 -r1.147.10.2
*** jump.c	1999/04/08 02:41:58	1.147.10.1
--- jump.c	1999/06/26 16:59:23	1.147.10.2
*************** jump_optimize_1 (f, cross_jump, noop_mov
*** 1076,1082 ****
  
  		if (target)
  		  {
! 		    rtx seq1,seq2,last;
  
  		    /* Save the conditional move sequence but don't emit it
  		       yet.  On some machines, like the alpha, it is possible
--- 1076,1083 ----
  
  		if (target)
  		  {
! 		    rtx seq1, seq2, last;
! 		    int copy_ok;
  
  		    /* Save the conditional move sequence but don't emit it
  		       yet.  On some machines, like the alpha, it is possible
*************** jump_optimize_1 (f, cross_jump, noop_mov
*** 1086,1093 ****
  		    seq2 = get_insns ();
  		    end_sequence ();
  
! 		    /* Now that we can't fail, generate the copy insns that
! 		       preserve the compared values.  */
  		    start_sequence ();
  		    emit_move_insn (cond0, XEXP (temp4, 0));
  		    if (cond1 != XEXP (temp4, 1))
--- 1087,1095 ----
  		    seq2 = get_insns ();
  		    end_sequence ();
  
! 		    /* "Now that we can't fail..."  Famous last words.
! 		       Generate the copy insns that preserve the compared
! 		       values.  */
  		    start_sequence ();
  		    emit_move_insn (cond0, XEXP (temp4, 0));
  		    if (cond1 != XEXP (temp4, 1))
*************** jump_optimize_1 (f, cross_jump, noop_mov
*** 1095,1119 ****
  		    seq1 = get_insns ();
  		    end_sequence ();
  
! 		    emit_insns_before (seq1, temp5);
! 		    /* Insert conditional move after insn, to be sure that
! 		       the jump and a possible compare won't be separated */
! 		    last = emit_insns_after (seq2, insn);
! 
! 		    /* ??? We can also delete the insn that sets X to A.
! 		       Flow will do it too though.  */
! 		    delete_insn (temp);
! 		    next = NEXT_INSN (insn);
! 		    delete_jump (insn);
  
! 		    if (after_regscan)
  		      {
! 			reg_scan_update (seq1, NEXT_INSN (last), old_max_reg);
! 			old_max_reg = max_reg_num ();
! 		      }
  
! 		    changed = 1;
! 		    continue;
  		  }
  		else
  		  end_sequence ();
--- 1097,1138 ----
  		    seq1 = get_insns ();
  		    end_sequence ();
  
! 		    /* Validate the sequence -- this may be some weird
! 		       bit-extract-and-test instruction for which there
! 		       exists no complimentary bit-extract insn.  */
! 		    copy_ok = 1;
! 		    for (last = seq1; last ; last = NEXT_INSN (last))
! 		      if (recog_memoized (last) < 0)
! 			{
! 			  copy_ok = 0;
! 			  break;
! 			}
  
! 		    if (copy_ok)
  		      {
! 		        emit_insns_before (seq1, temp5);
  
! 		        /* Insert conditional move after insn, to be sure
! 			   that the jump and a possible compare won't be
! 			   separated.  */
! 		        last = emit_insns_after (seq2, insn);
! 
! 		        /* ??? We can also delete the insn that sets X to A.
! 		           Flow will do it too though.  */
! 		        delete_insn (temp);
! 		        next = NEXT_INSN (insn);
! 		        delete_jump (insn);
! 
! 		        if (after_regscan)
! 		          {
! 			    reg_scan_update (seq1, NEXT_INSN (last),
! 					     old_max_reg);
! 			    old_max_reg = max_reg_num ();
! 		          }
! 
! 		        changed = 1;
! 		        continue;
! 		      }
  		  }
  		else
  		  end_sequence ();


More information about the Gcc-patches mailing list