Ok, I fixed it using using pair of define_insn and define_expand below: (define_expand "addsi3" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "nonmemory_operand" "")))] "" { if (CONST_INT_P (operands [2])) { if (can_create_pseudo_p ()) { operands[2] = force_reg (SImode, operands[2]); emit_insn (gen_rtx_SET (SImode, operands[0], gen_rtx_PLUS (SImode, operands [1], operands [2]))); } } else { emit_insn (gen_rtx_SET (SImode, operands[0], gen_rtx_PLUS (SImode, operands [1], operands [2]))); } DONE; }) (define_insn "*addsi3_internal" [(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.radd \t%0,%1,%2" [(set_attr "type" "add") (set_attr "length" "1")]) I have to admit, that I don't understand why it works... I figured out possible explanation. When define_expand doesn't emit any insns, but it finishes with DONE, GCC tries other strategy to fir RTL instruction to machine description, right? I have also question about output assembly (compiled with -dP option). Sample C code: int b = 123; int a = b + 998; output: #(insn 8 7 19 simple_test.c:4 (set (reg:SI 3 r3 [44]) # (const_int 998 [0x3e6])) 8 {*movsi_insn} (nil)) l.addi r3,r0,998 # move immediate I # 8 *movsi_insn/1 [length = 1] #(insn 19 8 9 (set (reg:SI 3 r3 [44]) # (rto:SI (reg:SI 3 r3 [44]))) 72 {rto} (nil)) l.rto r3,r3 # 19 rto [length = 1] #(insn 9 19 10 simple_test.c:4 (set:SI (reg:SI 3 r3 [43]) # (plus:SI (reg:SI 4 r4 [42]) # (reg:SI 3 r3 [44]))) 49 {*addsi3_internal} (expr_list:REG_EQUAL (plus:SI (reg:SI 4 r4 [42]) # (const_int 998 [0x3e6])) # (nil))) l.radd r3,r4,r3 # 9 *addsi3_internal [length = 1] What "(expr_list:REG_EQUAL (..." stays for?