RFA: Combine issue

Josh Conner jconner@apple.com
Thu Aug 4 23:38:00 GMT 2005


I'm seeing invalid code produced for a simple test case targeting arm- 
none-elf (attached), which I believe is caused by an invalid  
transformation in simplify_comparison.  It's transforming code of the  
form:

   (compare (subreg:QI (plus (reg:SI) (-1)))
            (-3))

into:

   (compare (plus (reg:SI) (-1))
            (-3))

But I don't believe this transformation (lifting the subreg) is valid  
for this particular instance.  Here are the more explicit rtl dumps -  
before:

(insn 14 12 15 0 (set (reg:SI 104)
         (plus:SI (reg:SI 103 [ <variable>.uc8 ])
             (const_int -1 [0xffffffff]))) 4 {*arm_addsi3}  
(insn_list:REG_DEP_TRUE 12 (nil))
     (expr_list:REG_DEAD (reg:SI 103 [ <variable>.uc8 ])
         (nil)))

(insn 15 14 16 0 (set (reg:SI 105)
         (and:SI (reg:SI 104)
             (const_int 255 [0xff]))) 53 {*arm_andsi3_insn}  
(insn_list:REG_DEP_TRUE 14 (nil))
     (expr_list:REG_DEAD (reg:SI 104)
         (nil)))

(insn 16 15 17 0 (set (reg:CC 24 cc)
         (compare:CC (reg:SI 105)
             (const_int 253 [0xfd]))) 194 {*arm_cmpsi_insn}  
(insn_list:REG_DEP_TRUE 15 (nil))
     (expr_list:REG_DEAD (reg:SI 105)
         (nil)))

After:

(note 14 12 15 0 NOTE_INSN_DELETED)

(insn 15 14 16 0 (set (reg:SI 105)
         (plus:SI (reg:SI 103 [ <variable>.uc8 ])
             (const_int -1 [0xffffffff]))) 4 {*arm_addsi3}  
(insn_list:REG_DEP_TRUE 12 (nil))
     (expr_list:REG_DEAD (reg:SI 103 [ <variable>.uc8 ])
         (nil)))

(insn 16 15 17 0 (set (reg:CC 24 cc)
         (compare:CC (reg:SI 105)
             (const_int -3 [0xfffffffd]))) 194 {*arm_cmpsi_insn}  
(insn_list:REG_DEP_TRUE 15 (nil))
     (expr_list:REG_DEAD (reg:SI 105)
         (nil)))

The conversion is being done at the "case SUBREG" code starting  
around line 10191 of combine.c.  The conversion is allowed because  
the following tests are met:

     ((unsigned HOST_WIDE_INT) c1
       < (unsigned HOST_WIDE_INT) 1 << (mode_width - 2)
      /* (A - C1) always sign-extends, like C2.  */
      && num_sign_bit_copies (a, inner_mode)
         > (unsigned int) (GET_MODE_BITSIZE (inner_mode)
                           - mode_width - 1))

In my case:
   c1 is 3, which is less than 1 << 6, and
   num_sign_bit_copies(a,SI) is 24 (because the SI register "a"  
contains a zero-extended QI value), and
   "GET_MODE_BITSIZE (inner_mode) - mode_width - 1" is 23

Now, as I understand things, we're trying to see if "compare (subreg  
(a - c1), c2)" is the same as "compare (a - c1, c2)".  And, this is  
considered acceptable if the result of "a - c1" is identical to a  
sign extended "subreg (a - c1)".  So far, so good.  However, as I  
apply the code to the SI/QI subreg case reads:

     if (INTVAL (c1) < 64) and there are at least 24 identical bits  
at the top of a

This logic, however, doesn't seem to match.  First, it would seem  
there should be at least 25 identical bits to verify that we do  
indeed have a sign-extended QI value.  But even with that addressed,  
consider another case (again with the QI/SI for concreteness).   
Suppose we have an expression like:

   lt (subreg (a - 1), -3)

And, suppose for this example that "a" is a SI sign-extended from a  
signed QI.  So, num_sign_bit_copies would be 25.  The transformation  
would be allowed (because c1 is less than 64 and num_sign_bit_copies  
is greater than 24).  However, if "a" contained a value of -128 at  
run-time:

   lt (subreg (a - 1), -3) becomes
     lt (subreg (-129), -3) becomes
       lt (127), -3 == FALSE

whereas after the transformation:

   lt (a - 1, -3) becomes
     lt (-129, -3) == TRUE

Am I misinterpreting the logic?  Am I missing something fundamental?   
I appreciate any feedback / pointers / clues / etc...

- Josh


-------------- next part --------------
A non-text attachment was scrubbed...
Name: test.c
Type: application/octet-stream
Size: 248 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc/attachments/20050804/91366902/attachment.obj>


More information about the Gcc mailing list