> +(define_expand "zero_extendsidi2" > + [(set (match_operand:DI 0 "register_operand") > + (zero_extend:DI (match_operand:SI 1 "reg_or_indirect_memory_operand")))] > + "" > +{ > + if (register_operand (operands[1], SImode)) > + { > + operands[1] = gen_lowpart (DImode, operands[1]); > + emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (32))); > + emit_insn (gen_lshrdi3 (operands[0], operands[0], GEN_INT (32))); > + DONE; > + } > +}) > + > +(define_insn "*zero_extendsidi2" > + [(set (match_operand:DI 0 "register_operand" "=r,r") > + (zero_extend:DI (match_operand:SI 1 "reg_or_indirect_memory_operand" "0,m")))] > + "" > + "@ > + lsh\t%0,32\n\trsh\t%0,32 > + ldxw\t%0,%1" > + [(set_attr "type" "alu,ldx") > + (set_attr "length" "16,8")]) Sorry, should have noticed last time, but: you shouldn't need to handle register operands here given the expander above. It's OK if you find it improves code quality, but it'd be interesting to know why if so....
If I remove the 0,=r alternative from the insn above, and also adjust the predicate to indirect_memory_operand, then I get a segfault in one test, in update_costs_from_allocno (ira-color.c:1382), because: (gdb) print mode $1 = E_SImode (gdb) print default_target_ira_int->x_ira_register_move_cost[mode] $13 = (move_table *) 0x0 What I think is going on is: 1. The expand above is used, and 2. there is no insn in the program matched by a pattern that involves a SI operand, and therefore record_operand_costs is never called on SImode operand, and therefore the lazily-initialized x_ira_register_move_cost is never filled in for E_SImode, and then 3. ira() -> ira_color() -> color () -> do_coloring () -> ira_traverse_loop_tree () -> color_pass () -> color_allocnos () -> update_costs_from_prefs () -> update_costs_from_allocno () *CRASH* Is this a bug, or am I expected to somehow trigger the initialization of the SImode entry in the ira register move table in some other way? > + > +;;; Sign-extension > + > +;; Sign-extending a 32-bit value into a 64-bit value is achieved using > +;; shifting, with instructions generated by the expand below. > + > +(define_expand "extendsidi2" > + [(set (match_operand:DI 0 "register_operand") > + (sign_extend:DI (match_operand:SI 1 "register_operand")))] > + "" > +{ > + operands[1] = gen_lowpart (DImode, operands[1]); > + emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (32))); > + emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (32))); > + DONE; > +}) > + > +(define_insn "*extendsidi2" > + [(set (match_operand:DI 0 "register_operand" "=r") > + (sign_extend:DI (match_operand:SI 1 "register_operand" "0")))] > + "" > + "lsh\t%0,32\n\tarsh\t%0,32" > + [(set_attr "type" "alu") > + (set_attr "length" "16")]) Likewise this define_insn shouldn't be needed. The removal of this one doesn't trigger any problem that I can see running compile.exp. I'm glad to get rid of yet another insn! :)