Hi,

when working on removing avr's present monolithic SI-mode instruction patterns 
by splitters after reload and lowering to QI modes after expand, I have 
stepped over the following general issue:

The mid-end seems not to be able to simplify nested subreg expressions. I.e. 
it seems that there is no known transformation 

   (subreg:QI (subreg:HI (reg:SI xx) 0) 0) 
-> (subreg:QI (reg:SI xx) 0)

. I have stepped over the problem when replacing the avr-target's present 
xorsi3 define_insn by a corresponding define_expand explicitly using 4 
subregs, i.e. after replacing

(define_insn "xorhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
        (xor:SI (match_operand:HI 1 "register_operand" "%0")
                (match_operand:HI 2 "register_operand" "r")))]
  ""
  "eor %0,%2
        eor %B0,%B2"
  [(set_attr "length" "2")
   (set_attr "cc" "set_n")])

by

(define_expand "xorhi3"
 [(set (subreg:QI (match_operand:HI 0 "register_operand" "=r") 0)
       (xor:QI (subreg:QI (match_operand:HI 1 "register_operand" "%0") 0)
               (subreg:QI (match_operand:HI 2 "register_operand" "r")  0)))
  (set (subreg:QI (match_dup 0) 1)
       (xor:QI (subreg:QI (match_dup 1) 1)
               (subreg:QI (match_dup 2) 1)))]
  ""
  "")
 
So far I had seen no regressions on the testsuite, however after adapting the 
testcase gcc.c-torture/execute/200406029-1.c to compile also on int=16bits 
targets, I am now getting an ICE. The error message reads:

/home/bmh/gnucvs/head/gcc/gcc/testsuite/gcc.c-torture/execute/20040629-1.c:139: 
error: unrecognizable insn:
(insn 28 27 29 0 (set (subreg:QI (reg:HI 59) 0)
        (xor:QI (subreg:QI (reg:HI 42) 0)
            (subreg:QI (subreg:HI (reg/v:SI 41 [ x ]) 0) 0))) -1 
(insn_list:REG_DEP_TRUE 68 (insn_list:REG_DEP_TRUE 3 (insn_list:REG_DEP_TRUE 
27 (nil))))
    (nil))
/home/bmh/gnucvs/head/gcc/gcc/testsuite/gcc.c-torture/execute/20040629-1.c:139: 
internal compiler error: in extract_insn, at recog.c:2082
Please submit a full bug report,
with preprocessed source if appropriate.

The 20040629-1.c's bitfield operations generate HI mode subregs of SI mode 
registers and these HI mode subregs are themselves passed to the HI->QI mode 
expander. My question therefore is: 

It seems that the cleanest solution would be to teach gcc how to unnest 
subregs. Therefore my question: Is this possible and where would be the place 
for doing this?
 
Yours,

Björn


BTW. I have stepped over a similar issue when using the gen_highpart and 
gen_lowpart functions for splitters after reload. It sometimes happens that 
one of these functions also gets a subreg expression as input operand while 
not being able to handle it. Both functions seem to fail as well when they 
are working on a label reference immediate operand. It seems that in their 
present form gen_lowpart and gen_highpart should be used only in DI-SI-mode 
splitters since then there is no danger that the DI mode expression itself is 
a subreg of an even larger mode.

Reply via email to