combiner bug and fix

Denis Chertykov denisc@overta.ru
Thu Jun 19 16:07:00 GMT 2003


I have analyzed the bug# 11181 and founded that it's a combiner bug.

Combiner tries to combine the foolowing insns:

(insn 13 11 14 1 (set (reg:QI 42)
        (xor:QI (reg:QI 24 r24)
            (reg:QI 43))) 54 {xorqi3} (insn_list 10 (nil))
    (expr_list:REG_DEAD (reg:QI 24 r24)
        (nil)))

(note 14 13 15 1 NOTE_INSN_DELETED)

(note 15 14 16 1 NOTE_INSN_DELETED)

(note 16 15 17 1 NOTE_INSN_DELETED)

(jump_insn 17 16 22 1 (set (pc)
        (if_then_else (eq (zero_extract:HI (reg:QI 42)
                    (const_int 1 [0x1])
                    (const_int 0 [0x0]))
                (const_int 0 [0x0]))
            (label_ref 9)
            (pc))) 97 {*sbrx_branch} (insn_list 13 (nil))
    (expr_list:REG_DEAD (reg:QI 42)
        (expr_list:REG_BR_PROB (const_int 8900 [0x22c4])
            (nil))))


In process of combining it builds the following rtl:

(zero_extract:HI (xor:QI (reg:QI 24 r24)
        (reg:QI 43))
    (const_int 1 [0x1])
    (const_int 0 [0x0]))

And tries to simplify it by combine_simplify_rtx -> simplify_shift_const.
simplify_shift_const have the following fragment:

	  /* If we can't do that, try to simplify the shift in each arm of the
	     logical expression, make a new logical expression, and apply
	     the inverse distributive law.  */
	  {
	    rtx lhs = simplify_shift_const (NULL_RTX, code, shift_mode,
					    XEXP (varop, 0), count);
	    rtx rhs = simplify_shift_const (NULL_RTX, code, shift_mode,
					    XEXP (varop, 1), count);

	    varop = gen_binary (GET_CODE (varop), shift_mode, lhs, rhs);
	    varop = apply_distributive_law (varop);

	    count = 0;
	  }
	  break;
----------------------------------------------------
IMHO: it's buggy because lhs and/or rhs can be (clobber (const_int 0))
and building of varop are wrong because builded rtl seems like:
(xor:HI (clobber:QI (const_int 0 [0x0]))
    (clobber:QI (const_int 0 [0x0])))

It's a wrong rtl which must be rejected by combiner, but it have a
code XOR which is valid and this rtl will be processed. It is a
problem because the new rtl
(zero_extract:HI (xor:HI (clobber:QI (const_int 0 [0x0]))
    (clobber:QI (const_int 0 [0x0])))
    (const_int 1 [0x1])
    (const_int 0 [0x0]))

will be simplified to (const_int 1).


The fix.

2003-6-19  Denis Chertykov  <denisc@overta.ru>

	* combine.c (simplify_shift_const): Handle the CLOBBER rtx and
	don't build a binary operation with it.



Index: combine.c
===================================================================
RCS file: /cvsroot/gcc/egcs/gcc/combine.c,v
retrieving revision 1.363
diff -c -3 -p -r1.363 combine.c
*** combine.c	13 Jun 2003 22:13:07 -0000	1.363
--- combine.c	19 Jun 2003 07:13:44 -0000
*************** simplify_shift_const (rtx x, enum rtx_co
*** 9670,9683 ****
  	     logical expression, make a new logical expression, and apply
  	     the inverse distributive law.  */
  	  {
  	    rtx lhs = simplify_shift_const (NULL_RTX, code, shift_mode,
  					    XEXP (varop, 0), count);
! 	    rtx rhs = simplify_shift_const (NULL_RTX, code, shift_mode,
  					    XEXP (varop, 1), count);
! 
! 	    varop = gen_binary (GET_CODE (varop), shift_mode, lhs, rhs);
! 	    varop = apply_distributive_law (varop);
! 
  	    count = 0;
  	  }
  	  break;
--- 9670,9693 ----
  	     logical expression, make a new logical expression, and apply
  	     the inverse distributive law.  */
  	  {
+ 	    rtx rhs;
  	    rtx lhs = simplify_shift_const (NULL_RTX, code, shift_mode,
  					    XEXP (varop, 0), count);
! 	    if (GET_CODE (lhs) != CLOBBER)
! 	      {
! 		rhs = simplify_shift_const (NULL_RTX, code, shift_mode,
  					    XEXP (varop, 1), count);
! 		if (GET_CODE (rhs) != CLOBBER)
! 		  {
! 		    varop = gen_binary (GET_CODE (varop), shift_mode,
! 					lhs, rhs);
! 		    varop = apply_distributive_law (varop);
! 		  }
! 		else
! 		  varop = rhs;
! 	      }
! 	    else
! 	      varop = lhs;
  	    count = 0;
  	  }
  	  break;




More information about the Gcc-patches mailing list