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]

purge_addressof flags badness


The purge_addressof code has a bad habit of not looking where it's
deciding to put new instructions.  The case that brought this to mind is

void *foo (int pred)
{
  void *x, *dummy;
  if (pred)
    x = &dummy;
  else
    x = 0;
  return x;
}

where the if has successfully been transformed to a cmove.  We enter
purge_addressof with rtl like

(insn 36 33 37 (set (reg:CCNO 17)
        (compare:CCNO (reg/v:SI 24)
            (const_int 0))) 4 {cmpsi_0} (nil)
    (nil))

(insn 37 36 24 (set (reg/v:SI 25)
        (if_then_else:SI (ne (reg:CCNO 17)
                (const_int 0))
            (addressof:SI (reg/v:SI 27) 26)
            (reg/v:SI 25))) 455 {movsicc+1} (nil)
    (nil))

As it is now, we'd quite happily put an addsi3(new, frame_pointer_rtx, ofs)
immediately before the cmove.  If this had been a cc0 host, we'd be dead
right there.  This target though has an explicit hard reg, which is
clobbered by addsi3.  We manage to survive until instruction scheduling
where we abort because the reg_dead notes didn't match up as expected.  

Some discussion with Jim yielded a potential solution.  The way reload
gets away with doing similar address fixups is by attempting to recognize
an explicit gen_rtx_PLUS then falling back on add_optab if that fails.

The same trick works in this instance. 

Since I don't expect fixup_var_refs to ever try to build an expression
containing anything but a plus, I don't do anything to verify that we're
not clobbering some potential flags register.

Ok?


r~

PS: Hmm.  Now that I think about it, the current x86 port represents
cmp+cmove as a unit until after reload for this very purpose.  Perhaps
the cc0 test I add isn't necessary?


	* function.c (fixup_var_refs_1): First try moving the expression
	directly into a register.  Don't separate cc0 setter and user.

Index: function.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/function.c,v
retrieving revision 1.194
diff -c -p -d -r1.194 function.c
*** function.c	1999/03/08 18:40:34	1.194
--- function.c	1999/03/10 23:10:17
*************** fixup_var_refs_1 (var, promoted_mode, lo
*** 1938,1955 ****
  	  /* Prevent sharing of rtl that might lose.  */
  	  rtx sub = copy_rtx (XEXP (var, 0));
  
- 	  start_sequence ();
- 
  	  if (! validate_change (insn, loc, sub, 0))
  	    {
! 	      rtx y = force_operand (sub, NULL_RTX);
  
  	      if (! validate_change (insn, loc, y, 0))
! 		*loc = copy_to_reg (y);
! 	    }
  
! 	  emit_insn_before (gen_sequence (), insn);
! 	  end_sequence ();
  	}
        return;
  
--- 1938,1981 ----
  	  /* Prevent sharing of rtl that might lose.  */
  	  rtx sub = copy_rtx (XEXP (var, 0));
  
  	  if (! validate_change (insn, loc, sub, 0))
  	    {
! 	      rtx y = gen_reg_rtx (GET_MODE (sub));
! 	      rtx seq, new_insn;
  
+ 	      /* We should be able to replace with a register or 
+ 		 all is lost.  */
  	      if (! validate_change (insn, loc, y, 0))
! 		abort ();
  
! 	      /* Careful!  First try to recognize a direct move of the
! 		 value, mimicking how things are done in gen_reload wrt
! 		 PLUS.  Consider what happens when insn is a conditional
! 		 move instruction and addsi3 clobbers flags.  */
! 
! 	      start_sequence ();
! 	      new_insn = emit_insn (gen_rtx_SET (VOIDmode, y, sub));
! 	      seq = gen_sequence ();
! 	      end_sequence ();
! 
! 	      if (recog_memoized (new_insn) < 0)
! 		{
! 		  /* That failed.  Fall back on force_operand and hope.  */
! 
! 		  start_sequence ();
! 		  force_operand (sub, y);
! 		  seq = gen_sequence ();
! 		  end_sequence ();
! 		}
! 
! #ifdef HAVE_cc0
! 	      /* Don't separate setter from user.  */
! 	      if (PREV_INSN (insn) && sets_cc0_p (PREV_INSN (insn)))
! 		insn = PREV_INSN (insn);
! #endif
! 
! 	      emit_insn_before (seq, insn);
! 	    }
  	}
        return;
  


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