Thank you for answering your email. I actually cannot use you suggestion, because source register and destination register are almost always the same register. Now I'm found something weird. Original template "addsi3" for OpenRISC is: (define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") (plus:SI (match_operand:SI 1 "register_operand" "%r,r") (match_operand:SI 2 "nonmemory_operand" "r,I")))] "" "@ l.add \t%0,%1,%2 l.addi \t%0,%1,%2" [(set_attr "type" "add,add") (set_attr "length" "1,1")]) and "mulsi3" is: (define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r")))] "TARGET_HARD_MUL" "l.mul \t%0,%1,%2" [(set_attr "type" "mul") (set_attr "length" "1")]) Now, when I write in C such code: int b = 100; b *= 101; GCC properly moves immediate to temporary register and then call "l.mul" instruction. I tried to do the same trick and modified "addsi3" template to: (define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "register_operand" "r")))] "" "l.add \t%0,%1,%2" [(set_attr "type" "add") (set_attr "length" "1")]) The problem is that, GCC fails to compile with this modified template with error: ../../gcc-4.5.1/gcc/crtstuff.c: In function ‘__do_global_dtors_aux’: ../../gcc-4.5.1/gcc/crtstuff.c:332:1: internal compiler error: in gen_add2_insn, at optabs.c:4764 As I remember documentation for RTL says, that it's able to make operands fit instruction template, so it's able to move immediate to register as it's done for "multsi3". So why it doesn't work for "addsi3"?