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.