On Wed, Jul 19, 2006 at 07:52:32AM +0200, Wolfgang Mües wrote:
> Hello,
>
> after getting a "working" version of the gcc 4.0.2 with the Nintendo
> 8-bit-write problem, I was busy the last weeks trying to adapt the
> linux system (replacing I/O with writeb() macros, removing strb
> assembler calls).
It is good to hear from you again.
> However, it turned out that the sources of the linux kernel are a far
> more demanding test than every single small test case.
Such is life. Since the ARM backend has many arm_expand_fubar() functions,
it wouldn't too surpricing if one of them would now generate invalid insns.
> I have tried my very best to implement the last patch from Rask (thank
> you very much!). There was one place I was not shure I have coded the
> right solution:
> > + (match_code "reg" "0")))
>
> My patch (without the second operand for match_code):
>
> > (match_test "GET_CODE (XEXP (op, 0)) == REG")))
>
> Is this the right substitution?
I believe it is.
> If I compile the linux kernel with this patch, many files get compiled
> without problems, but in fs/vfat/namei.c I get:
>
> > fs/vfat/namei.c: In function 'vfat_add_entry':
> > fs/vfat/namei.c:694: error: unrecognizable insn:
> > (insn 2339 2338 2340 188 (set (mem/s/j:QI (reg:SI 14 lr) [0
> > <variable>.attr+0 S1 A8]) (reg:QI 12 ip)) -1 (nil)
> > (nil))
> > fs/vfat/namei.c:694: internal compiler error: in extract_insn, at
> > recog.c:2020 Please submit a full bug report,
>
> I can't see what is going on here...
The (clobber ...) part is missing. The first thing to do is to compile with
-fdump-rtl-all and see which pass creates this invalid insn. Grep is your
friend.
I've spotted a function named emit_set_insn() in arm.c. It might be the
problem, because it uses gen_rtx_SET() directly. Thus, if Y is a general
operand, the resulting insn should match one of the move patterns, but the
(clobber ...) expression needed for "_arm_movqi_insn_swp" will be missing.
For example, arm_split_constant() contains these potentially problematic
lines:
emit_set_insn (target, GEN_INT (val));
rtx temp = subtargets ? gen_reg_rtx (mode) : target;
emit_set_insn (temp, GEN_INT (val));
There are other functions which call emit_set_insn(). I have no idea which
one, if any, of these calls is causing the problem. It could also be one of
the RTL passes.
The function named emit_move_insn() ought to do the trick here, but
is perhaps a bit heavyweight for this purpose. Anyway, try this patch
(untested), which should plug this particular hole:
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c (revision 115021)
+++ gcc/config/arm/arm.c (working copy)
@@ -709,12 +709,15 @@
TLS_LE32
};
-/* Emit an insn that's a simple single-set. Both the operands must be known
- to be valid. */
+/* Emit an insn that's a simple single-set if Y isn't a general operand.
+ Both the operands must be known to be valid. */
inline static rtx
emit_set_insn (rtx x, rtx y)
{
- return emit_insn (gen_rtx_SET (VOIDmode, x, y));
+ if (general_operand (y, GET_MODE (x))
+ return emit_move_insn (x, y);
+ else
+ return emit_insn (gen_rtx_SET (VOIDmode, x, y));
}
/* Return the number of bits set in VALUE. */
--
Rask Ingemann Lambertsen