I have a problem on the Altera Nios2 architecture (it is a bit like MIPS) with (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 "arith_operand" "r,I")))] "" "add%i2\\t%0, %1, %z2" [(set_attr "type" "alu")]) This is mostly old and stable and straightforward and in production use for half a decade; the main point of interest is that the 'I' argument represents a 16-bit signed immediate value on a 32-bit architecture. When compiling the simple stimulus program #define MAX 200 char a[MAX*256]; int main() { int i; for (i=0; i<MAX; i++) { a[i*256] = 0.0; a[i] = 0.0; } return 0; } at -O2 -fpic what happens is that the above define_insn matches fine originally but during pass "ivopts" induction variable elimination rewrites the immediate constant to be out of range, resulting in "unrecognizable insn". After peering at gcc.gnu.org/onlinedocs/gccint/* awhile my first thought was to add to my nios2.md ;; Split an add that we can't do in one insn into two insns, each of which ;; does one 16-bit part. This is used by combine. Note that the low-order ;; add should be last in case the result gets used in an address. (define_split [(set (match_operand:SI 0 "gpc_reg_operand" "") (plus:SI (match_operand:SI 1 "gpc_reg_operand" "") (match_operand:SI 2 "non_add_cint_operand" "")))] "" [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3))) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))] " { HOST_WIDE_INT val = INTVAL (operands[2]); HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000; HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode); operands[3] = GEN_INT (rest); operands[4] = GEN_INT (low); }") but (as I quickly discovered!) this will not take effect until pass "combine", whereas I'm crashing 14 passes earlier in "vregs", as soon as the volatile_ok global is set to 1, forcing all insns to have a valid match to a defined insn. My second thought was to add to my nios2.md (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "const_int_operand" "i"))) (clobber (match_scratch:SI 3 "=&r"))] "" "movhi\\t%3, %H2\;addi\\t%3, %3, %L2\;add%i2\\t%0, %1, %3" [(set_attr "type" "alu")]) so that when the ivopts transform converts the rtx into something the "addsi3" would no longer recognize, the above anonymous def would kick in and match, and at assembly time eventually substitute an instruction sequence capable of handling 32-bit immediate constants for the original single instruction with its 16-bit immediate constant limitation. Which might be roughly the right idea so far as it goes (?) but when I try adding the above to nios2.md and rebuilding the toolchain I get another "unrecognizable insn" off in a completely different file (libgcc2.c): ../../src/gcc-4.1/gcc/libgcc2.c: In function '__muldi3': ../../src/gcc-4.1/gcc/libgcc2.c:542: error: unrecognizable insn: (insn 112 48 50 1 ../../src/gcc-4.1/gcc/libgcc2.c:536 (set (reg:SI 2 r2) (scratch:SI)) -1 (nil) (nil)) ../../src/gcc-4.1/gcc/libgcc2.c:542: internal compiler error: in extract_insn, at recog.c:2093 Searching on the above I find a similar report back in 2009 to which Ian Lance Taylor suggested using a define_expand, but according to the manual define_expand is useful only when named, for generating rtx, whereas my (initial) problem is matching rtx, rather than generating it, if I understand correctly. Gcc is terra incognita to me and I seem to be in a bit over my head. I'm going to continue mucking around trying stuff and learning more about gcc internals, but I have a feeling this is one of those times where a little assistance from an experienced gcc hand could save a lot of time. :-) Thanks in advance for any help! -- Cynbe