> I figured out what the root cause of this is. The SHL.L opcode (32 > bit shift) has a maximum shift count of 16:
This patch (committed) should fix it. I haven't addressed the "large variable shift count" part of the problem; this addresses the "large constant shift count" part which is needed for the floating point code. 2006-01-12 DJ Delorie <[EMAIL PROTECTED]> * config/m32c/shift.md: Rewrite: Allow arbitrary operands for shift counts, separate SI shifts for m32c vs m16c, pass shift type so that constant shifts can be split. * config/m32c/m32c.c (m32c_const_ok_for_constraint_p): Add In6. (m32c_valid_pointer_mode): Make static. (shift_gen_func_for): New. (m32c_prepare_shift): Use it. Split large const shifts into multiple shifts. * config/m32c/predicates.md (shiftcount_operand): Allow more general operands. (longshiftcount_operand): New. * doc/md.texi (Machine Constraints): Document In6. Index: config/m32c/predicates.md =================================================================== --- config/m32c/predicates.md (revision 109660) +++ config/m32c/predicates.md (working copy) @@ -146,7 +146,11 @@ ; limited range. (define_predicate "shiftcount_operand" - (ior (match_operand 0 "m32c_pseudo" "") + (ior (match_operand 0 "mra_operand" "") (and (match_operand 2 "const_int_operand" "") (match_test "-8 <= INTVAL (op) && INTVAL (op) && INTVAL (op) <= 8")))) +(define_predicate "longshiftcount_operand" + (ior (match_operand 0 "mra_operand" "") + (and (match_operand 2 "const_int_operand" "") + (match_test "-32 <= INTVAL (op) && INTVAL (op) && INTVAL (op) <= 32")))) ; TRUE for r0..r3, a0..a1, or sp. Index: config/m32c/m32c.c =================================================================== --- config/m32c/m32c.c (revision 109660) +++ config/m32c/m32c.c (working copy) @@ -902,4 +902,8 @@ m32c_const_ok_for_constraint_p (HOST_WID return (-16 <= value && value && value <= 16); } + if (memcmp (str, "In6", 3) == 0) + { + return (-32 <= value && value && value <= 32); + } if (memcmp (str, "IM2", 3) == 0) { @@ -1506,5 +1510,5 @@ m32c_function_arg_regno_p (int r) #undef TARGET_VALID_POINTER_MODE #define TARGET_VALID_POINTER_MODE m32c_valid_pointer_mode -bool +static bool m32c_valid_pointer_mode (enum machine_mode mode) { @@ -2835,25 +2839,61 @@ m32c_split_move (rtx * operands, enum ma } +typedef rtx (*shift_gen_func)(rtx, rtx, rtx); + +static shift_gen_func +shift_gen_func_for (int mode, int code) +{ +#define GFF(m,c,f) if (mode == m && code == c) return f + GFF(QImode, ASHIFT, gen_ashlqi3_i); + GFF(QImode, ASHIFTRT, gen_ashrqi3_i); + GFF(QImode, LSHIFTRT, gen_lshrqi3_i); + GFF(HImode, ASHIFT, gen_ashlhi3_i); + GFF(HImode, ASHIFTRT, gen_ashrhi3_i); + GFF(HImode, LSHIFTRT, gen_lshrhi3_i); + GFF(PSImode, ASHIFT, gen_ashlpsi3_i); + GFF(PSImode, ASHIFTRT, gen_ashrpsi3_i); + GFF(PSImode, LSHIFTRT, gen_lshrpsi3_i); + GFF(SImode, ASHIFT, TARGET_A16 ? gen_ashlsi3_16 : gen_ashlsi3_24); + GFF(SImode, ASHIFTRT, TARGET_A16 ? gen_ashrsi3_16 : gen_ashrsi3_24); + GFF(SImode, LSHIFTRT, TARGET_A16 ? gen_lshrsi3_16 : gen_lshrsi3_24); +#undef GFF +} + /* The m32c only has one shift, but it takes a signed count. GCC doesn't want this, so we fake it by negating any shift count when we're pretending to shift the other way. */ int -m32c_prepare_shift (rtx * operands, int scale, int bits) +m32c_prepare_shift (rtx * operands, int scale, int shift_code) { + enum machine_mode mode = GET_MODE (operands[0]); + shift_gen_func func = shift_gen_func_for (mode, shift_code); rtx temp; - if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) <= (1 << (bits - 1)) - && INTVAL (operands[2]) >= -(1 << (bits - 1))) + + if (GET_CODE (operands[2]) == CONST_INT) { - operands[2] = GEN_INT (scale * INTVAL (operands[2])); - return 0; + int maxc = TARGET_A24 && (mode == PSImode || mode == SImode) ? 32 : 8; + int count = INTVAL (operands[2]) * scale; + + while (count > maxc) + { + temp = gen_reg_rtx (mode); + emit_insn (func (temp, operands[1], GEN_INT (maxc))); + operands[1] = temp; + count -= maxc; + } + while (count < -maxc) + { + temp = gen_reg_rtx (mode); + emit_insn (func (temp, operands[1], GEN_INT (-maxc))); + operands[1] = temp; + count += maxc; + } + emit_insn (func (operands[0], operands[1], GEN_INT (count))); + return 1; } if (scale < 0) { temp = gen_reg_rtx (QImode); - if (GET_CODE (operands[2]) == CONST_INT) - temp = GEN_INT (-INTVAL (operands[2])); - else - emit_move_insn (temp, gen_rtx_NEG (QImode, operands[2])); + emit_move_insn (temp, gen_rtx_NEG (QImode, operands[2])); } else Index: config/m32c/shift.md =================================================================== --- config/m32c/shift.md (revision 109660) +++ config/m32c/shift.md (working copy) @@ -34,10 +34,10 @@ [(set (match_operand:QI 0 "mra_operand" "=RqiSd*Rmm,RqiSd*Rmm") (ashift:QI (match_operand:QI 1 "mra_operand" "0,0") - (match_operand:QI 2 "mrai_operand" "In4,R1w"))) + (match_operand:QI 2 "mrai_operand" "In4,RqiSd"))) (clobber (match_scratch:HI 3 "=X,R1w"))] "" "@ sha.b\t%2,%0 - mov.b\tr1l,r1h\n\tsha.b\tr1h,%0" + mov.b\t%2,r1h\n\tsha.b\tr1h,%0" ) @@ -45,21 +45,21 @@ [(set (match_operand:QI 0 "mra_operand" "=RqiSd*Rmm,RqiSd*Rmm") (ashiftrt:QI (match_operand:QI 1 "mra_operand" "0,0") - (neg:QI (match_operand:QI 2 "mrai_operand" "In4,R1w")))) + (neg:QI (match_operand:QI 2 "mrai_operand" "In4,RqiSd")))) (clobber (match_scratch:HI 3 "=X,R1w"))] "" "@ sha.b\t%2,%0 - mov.b\tr1l,r1h\n\tsha.b\tr1h,%0" + mov.b\t%2,r1h\n\tsha.b\tr1h,%0" ) -(define_insn "lshlqi3_i" +(define_insn "lshrqi3_i" [(set (match_operand:QI 0 "mra_operand" "=RqiSd*Rmm,RqiSd*Rmm") (lshiftrt:QI (match_operand:QI 1 "mra_operand" "0,0") - (neg:QI (match_operand:QI 2 "mrai_operand" "In4,R1w")))) + (neg:QI (match_operand:QI 2 "mrai_operand" "In4,RqiSd")))) (clobber (match_scratch:HI 3 "=X,R1w"))] "" "@ shl.b\t%2,%0 - mov.b\tr1l,r1h\n\tshl.b\tr1h,%0" + mov.b\t%2,r1h\n\tshl.b\tr1h,%0" ) @@ -71,5 +71,5 @@ (clobber (match_scratch:HI 3 ""))])] "" - "if (m32c_prepare_shift (operands, 1, 4)) + "if (m32c_prepare_shift (operands, 1, ASHIFT)) DONE;" ) @@ -81,5 +81,5 @@ (clobber (match_scratch:HI 3 ""))])] "" - "if (m32c_prepare_shift (operands, -1, 4)) + "if (m32c_prepare_shift (operands, -1, ASHIFTRT)) DONE;" ) @@ -91,5 +91,5 @@ (clobber (match_scratch:HI 3 ""))])] "" - "if (m32c_prepare_shift (operands, -1, 4)) + "if (m32c_prepare_shift (operands, -1, LSHIFTRT)) DONE;" ) @@ -100,10 +100,10 @@ [(set (match_operand:HI 0 "mra_operand" "=SdRhi*Rmm,SdRhi*Rmm") (ashift:HI (match_operand:HI 1 "mra_operand" "0,0") - (match_operand:QI 2 "mrai_operand" "In4,R1w"))) + (match_operand:QI 2 "mrai_operand" "In4,RqiSd"))) (clobber (match_scratch:HI 3 "=X,R1w"))] "" "@ sha.w\t%2,%0 - mov.b\tr1l,r1h\n\tsha.w\tr1h,%0" + mov.b\t%2,r1h\n\tsha.w\tr1h,%0" ) @@ -111,21 +111,21 @@ [(set (match_operand:HI 0 "mra_operand" "=SdRhi*Rmm,SdRhi*Rmm") (ashiftrt:HI (match_operand:HI 1 "mra_operand" "0,0") - (neg:QI (match_operand:QI 2 "mrai_operand" "In4,R1w")))) + (neg:QI (match_operand:QI 2 "mrai_operand" "In4,RqiSd")))) (clobber (match_scratch:HI 3 "=X,R1w"))] "" "@ sha.w\t%2,%0 - mov.b\tr1l,r1h\n\tsha.w\tr1h,%0" + mov.b\t%2,r1h\n\tsha.w\tr1h,%0" ) -(define_insn "lshlhi3_i" +(define_insn "lshrhi3_i" [(set (match_operand:HI 0 "mra_operand" "=RhiSd*Rmm,RhiSd*Rmm") (lshiftrt:HI (match_operand:HI 1 "mra_operand" "0,0") - (neg:QI (match_operand:QI 2 "mrai_operand" "In4,R1w")))) + (neg:QI (match_operand:QI 2 "mrai_operand" "In4,RqiSd")))) (clobber (match_scratch:HI 3 "=X,R1w"))] "" "@ shl.w\t%2,%0 - mov.b\tr1l,r1h\n\tshl.w\tr1h,%0" + mov.b\t%2,r1h\n\tshl.w\tr1h,%0" ) @@ -137,5 +137,5 @@ (clobber (match_scratch:HI 3 ""))])] "" - "if (m32c_prepare_shift (operands, 1, 4)) + "if (m32c_prepare_shift (operands, 1, ASHIFT)) DONE;" ) @@ -147,5 +147,5 @@ (clobber (match_scratch:HI 3 ""))])] "" - "if (m32c_prepare_shift (operands, -1, 4)) + "if (m32c_prepare_shift (operands, -1, ASHIFTRT)) DONE;" ) @@ -157,5 +157,5 @@ (clobber (match_scratch:HI 3 ""))])] "" - "if (m32c_prepare_shift (operands, -1, 4)) + "if (m32c_prepare_shift (operands, -1, LSHIFTRT)) DONE;" ) @@ -170,10 +170,10 @@ [(set (match_operand:PSI 0 "mra_operand" "=R02RaaSd*Rmm,R02RaaSd*Rmm") (ashift:PSI (match_operand:PSI 1 "mra_operand" "0,0") - (match_operand:QI 2 "mrai_operand" "In4,R1w"))) + (match_operand:QI 2 "mrai_operand" "In4,RqiSd"))) (clobber (match_scratch:HI 3 "=X,R1w"))] "TARGET_A24" "@ sha.l\t%2,%0 - mov.b\tr1l,r1h\n\tsha.l\tr1h,%0" + mov.b\t%2,r1h\n\tsha.l\tr1h,%0" ) @@ -181,21 +181,21 @@ [(set (match_operand:PSI 0 "mra_operand" "=R02RaaSd*Rmm,R02RaaSd*Rmm") (ashiftrt:PSI (match_operand:PSI 1 "mra_operand" "0,0") - (neg:QI (match_operand:QI 2 "mrai_operand" "In4,R1w")))) + (neg:QI (match_operand:QI 2 "mrai_operand" "In4,RqiSd")))) (clobber (match_scratch:HI 3 "=X,R1w"))] "TARGET_A24" "@ sha.l\t%2,%0 - mov.b\tr1l,r1h\n\tsha.l\tr1h,%0" + mov.b\t%2,r1h\n\tsha.l\tr1h,%0" ) -(define_insn "lshlpsi3_i" +(define_insn "lshrpsi3_i" [(set (match_operand:PSI 0 "mra_operand" "=R02RaaSd,??Rmm") (lshiftrt:PSI (match_operand:PSI 1 "mra_operand" "0,0") - (neg:QI (match_operand:QI 2 "shiftcount_operand" "In4,R1w")))) + (neg:QI (match_operand:QI 2 "shiftcount_operand" "In4,RqiSd")))) (clobber (match_scratch:HI 3 "=X,R1w"))] "TARGET_A24" "@ shl.l\t%2,%0 - mov.b\tr1l,r1h\n\tshl.l\tr1h,%0" + mov.b\t%2,r1h\n\tshl.l\tr1h,%0" ) @@ -207,5 +207,5 @@ (clobber (match_scratch:HI 3 ""))])] "TARGET_A24" - "if (m32c_prepare_shift (operands, 1, 4)) + "if (m32c_prepare_shift (operands, 1, ASHIFT)) DONE;" ) @@ -217,5 +217,5 @@ (clobber (match_scratch:HI 3 ""))])] "TARGET_A24" - "if (m32c_prepare_shift (operands, -1, 4)) + "if (m32c_prepare_shift (operands, -1, ASHIFTRT)) DONE;" ) @@ -227,5 +227,5 @@ (clobber (match_scratch:HI 3 ""))])] "TARGET_A24" - "if (m32c_prepare_shift (operands, -1, 4)) + "if (m32c_prepare_shift (operands, -1, LSHIFTRT)) DONE;" ) @@ -233,47 +233,90 @@ ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; The m16c has a maximum shift count of -16..16, even when in a +; register. It's optimal to use multiple shifts of -8..8 rather than +; loading larger constants into R1H multiple time. The m32c can shift +; -32..32 either via immediates or in registers. Hence, separate +; patterns. -(define_insn "ashlsi3_i" +(define_insn "ashlsi3_16" [(set (match_operand:SI 0 "r0123_operand" "=R03,R03") (ashift:SI (match_operand:SI 1 "r0123_operand" "0,0") - (match_operand:QI 2 "mrai_operand" "In4,R1w"))) + (match_operand:QI 2 "shiftcount_operand" "In4,RqiSd"))) (clobber (match_scratch:HI 3 "=X,R1w"))] - "" + "TARGET_A16" "@ sha.l\t%2,%0 - mov.b\tr1l,r1h\n\tsha.l\tr1h,%0" + mov.b\t%2,r1h\n\tsha.l\tr1h,%0" + [(set_attr "flags" "sz,sz")] ) -(define_insn "ashrsi3_i" +(define_insn "ashrsi3_16" [(set (match_operand:SI 0 "r0123_operand" "=R03,R03") (ashiftrt:SI (match_operand:SI 1 "r0123_operand" "0,0") - (neg:QI (match_operand:QI 2 "mrai_operand" "In4,R1w")))) + (neg:QI (match_operand:QI 2 "shiftcount_operand" "In4,RqiSd")))) (clobber (match_scratch:HI 3 "=X,R1w"))] - "" + "TARGET_A16" "@ sha.l\t%2,%0 - mov.b\tr1l,r1h\n\tsha.l\tr1h,%0" + mov.b\t%2,r1h\n\tsha.l\tr1h,%0" ) -(define_insn "lshlsi3_i" +(define_insn "lshrsi3_16" [(set (match_operand:SI 0 "r0123_operand" "=R03,R03") (lshiftrt:SI (match_operand:SI 1 "r0123_operand" "0,0") - (neg:QI (match_operand:QI 2 "mrai_operand" "In4,R1w")))) + (neg:QI (match_operand:QI 2 "shiftcount_operand" "In4,RqiSd")))) (clobber (match_scratch:HI 3 "=X,R1w"))] - "" + "TARGET_A16" "@ shl.l\t%2,%0 - mov.b\tr1l,r1h\n\tshl.l\tr1h,%0" + mov.b\t%2,r1h\n\tshl.l\tr1h,%0" + ) + + + +(define_insn "ashlsi3_24" + [(set (match_operand:SI 0 "r0123_operand" "=R03,R03") + (ashift:SI (match_operand:SI 1 "r0123_operand" "0,0") + (match_operand:QI 2 "longshiftcount_operand" "In6,RqiSd"))) + (clobber (match_scratch:HI 3 "=X,R1w"))] + "TARGET_A24" + "@ + sha.l\t%2,%0 + mov.b\t%2,r1h\n\tsha.l\tr1h,%0" ) +(define_insn "ashrsi3_24" + [(set (match_operand:SI 0 "r0123_operand" "=R03,R03") + (ashiftrt:SI (match_operand:SI 1 "r0123_operand" "0,0") + (neg:QI (match_operand:QI 2 "longshiftcount_operand" "In6,RqiSd")))) + (clobber (match_scratch:HI 3 "=X,R1w"))] + "TARGET_A24" + "@ + sha.l\t%2,%0 + mov.b\t%2,r1h\n\tsha.l\tr1h,%0" + ) + +(define_insn "lshrsi3_24" + [(set (match_operand:SI 0 "r0123_operand" "=R03,R03") + (lshiftrt:SI (match_operand:SI 1 "r0123_operand" "0,0") + (neg:QI (match_operand:QI 2 "longshiftcount_operand" "In6,RqiSd")))) + (clobber (match_scratch:HI 3 "=X,R1w"))] + "TARGET_A24" + "@ + shl.l\t%2,%0 + mov.b\t%2,r1h\n\tshl.l\tr1h,%0" + ) + + + (define_expand "ashlsi3" [(parallel [(set (match_operand:SI 0 "r0123_operand" "") - (ashift:SI (match_operand:SI 1 "r0123_operand" "") - (match_operand:QI 2 "mrai_operand" ""))) + (ashift:SI (match_operand:SI 1 "r0123_operand" "") + (match_operand:QI 2 "mrai_operand" ""))) (clobber (match_scratch:HI 3 ""))])] "" - "if (m32c_prepare_shift (operands, 1, 4)) + "if (m32c_prepare_shift (operands, 1, ASHIFT)) DONE;" ) @@ -285,5 +328,5 @@ (clobber (match_scratch:HI 3 ""))])] "" - "if (m32c_prepare_shift (operands, -1, 4)) + "if (m32c_prepare_shift (operands, -1, ASHIFTRT)) DONE;" ) @@ -295,5 +338,5 @@ (clobber (match_scratch:HI 3 ""))])] "" - "if (m32c_prepare_shift (operands, -1, 5)) + "if (m32c_prepare_shift (operands, -1, LSHIFTRT)) DONE;" ) Index: doc/md.texi =================================================================== --- doc/md.texi (revision 109660) +++ doc/md.texi (working copy) @@ -2324,6 +2324,6 @@ Used to match function return values. -16 @dots{} -1 or 1 @dots{} 16 [EMAIL PROTECTED] In4 --8 @dots{} -1 or 1 @dots{} 8 [EMAIL PROTECTED] In6 +-32 @dots{} -1 or 1 @dots{} 32 @item IM2