RFA: Add Epiphany port

Richard Henderson rth@redhat.com
Fri Nov 4 18:20:00 GMT 2011


> (define_predicate "call_address_operand"
>   (match_code "symbol_ref,const,reg")
> {
>   return (symbolic_operand (op, mode) || (GET_CODE (op) == REG));
> })

Nit.

(define_predicate "call_address_operand"
  (ior (match_code "reg")
       (match_operand 0 "symbolic_operand")))

> (define_special_predicate "any_gpr_operand"
>   (match_code "subreg,reg")
> {
>   return gpr_operand (op, mode);
> })

(define_special_predicate "any_gpr_operand"
  (match_operand 0 "gpr_operand"))

though, I'm not sure what this achieves...  while any_gpr_operand
will ignore its mode, passing on that same mode to gpr_operand wont.

> (define_insn_and_split "move_frame"
>   [(set (match_operand:SI 0 "gpr_operand" "=r")
>         (match_operand:SI 1 "register_operand" "r"))
>    (clobber (reg:CC CC_REGNUM))]
>   "operands[1] == frame_pointer_rtx || operands[1] == arg_pointer_rtx"

It looks to me that there are several places that could be tidied up
if you have a frame_register_operand predicate to use here instead of
testing operands[] in the extra_constraints field.

> ;; If the frame pointer elimination offset is zero, we'll use this pattern.
> (define_insn_and_split "*move_frame_1"
>   [(set (match_operand:SI 0 "gpr_operand" "=r")
>         (match_operand:SI 1 "register_operand" "r"))
>    (clobber (reg:CC CC_REGNUM))]
>   "(reload_in_progress || reload_completed)
>    && (operands[1] == stack_pointer_rtx
>        || operands[1] == hard_frame_pointer_rtx)"
>   "#"
>   "&& 1"
>   [(set (match_dup 0) (match_dup 1))])

Duplicate of the above?  I really don't see how they differ...

> ;; reload uses gen_addsi2 because it doesn't understand the need for
> ;; the clobber.
> (define_peephole2
>   [(set (match_operand:SI 0 "gpr_operand" "")
>         (match_operand:SI 1 "const_int_operand" ""))
>    (parallel [(set (match_dup 0)
>                    (plus:SI (match_dup 0)
>                             (match_operand:SI 2 "gpr_operand")))
>               (clobber (reg:CC UNKNOWN_REGNUM))])]

I'd like to understand all of this a little more.

Given that reload *would* generate an add3 (with no clobber), and
add-without-clobber isn't ordinarily a valid insn, why not just go
ahead and use that as your reload pattern instead of this 
clobber placeholder?

Wouldn't a bare plus pattern with that same reload_in_progress || reload_completed
check work just as well for all the pattern matching you want to do
during peephole analysis?

>   int scratch = (0x17
>                  ^ (true_regnum (operands[0]) & 1)
>                  ^ (true_regnum (operands[1]) & 2)
>                  ^ (true_regnum (operands[2]) & 4));
>   asm_fprintf (asm_out_file, \"\tstr r%d,[sp,#0]\n\", scratch);
>   asm_fprintf (asm_out_file, \"\tmovfs r%d,status\n\", scratch);
>   output_asm_insn (\"add %0,%1,%2\", operands);
>   asm_fprintf (asm_out_file, \"\tmovts status,r%d\n\", scratch);
>   asm_fprintf (asm_out_file, \"\tldr r%d,[sp,#0]\n\", scratch);
>   return \"\";

It does seem like you'd do well to split this pattern.  If you do, then you'll
automatically get the right changes to debugging unwind info across this.

A test for epilogue_completed in the split condition should be sufficient to
wait until after peephole2 has finished, so that you don't interfere with the
transformations you want there.

I'm also interested in hearing about how well this whole scheme works in 
practice, as opposed to merely waiting until after reload to split and flags
users.  There are certainly lots of other ports that are in the same boat
with respect to only having a flags-clobbering add.

> (define_insn_and_split "*recipsf2_1"
>   [(match_parallel 4 "float_operation"
>      [(set (match_operand:SF 0 "gpr_operand" "=r,r")
>            (div:SF (match_operand:SF 1 "const_float_1_operand" "")
>                    (match_operand:SF 2 "move_src_operand" "rU16m,rU16mCal")))
>       (use (match_operand:SI 3 "move_src_operand" "rU16m,rU16mCal"))

How to you prevent a post-reload copy propagation pass from putting things
back just the way before you split them?  It seems to me that's the primary
reason to use specific register constraints here.

> (define_insn "fmadd"
>   [(match_parallel 4 "float_operation"
>      [(set (match_operand:SF 0 "gpr_operand" "=r")
>            (fma:SF (match_operand:SF 2 "gpr_operand" "%r")
>                    (match_operand:SF 3 "gpr_operand" "r")
>                    (match_operand:SF 1 "gpr_operand" "0")))
>       (clobber (reg:CC_FP CCFP_REGNUM))])]

Presumably the strange operand ordering is left over from your port-specific
builtins?  Also, the % is extraneous since the constraints are identical.

> ; combiner pattern, also used by vector combiner pattern
> (define_expand "maddsf"
>   [(parallel
>      [(set (match_operand:SF 0 "gpr_operand" "=r")
>            (plus:SF (mult:SF (match_operand:SF 1 "gpr_operand" "%r")
>                              (match_operand:SF 2 "gpr_operand" "r"))
>                     (match_operand:SF 3 "gpr_operand" "0")))
>       (clobber (reg:CC_FP CCFP_REGNUM))])]
>   "TARGET_FUSED_MADD")

I suspect these aren't needed anymore.  Anything the combiner could have
found should be able to be found by the SSA optimizers.

> ; leave to desaster.

lead to disaster

>         (and:SI (match_operand:SI 1 "gpr_operand" "%r")
>                 (match_operand:SI 2 "gpr_operand" "r")))

More useless %.  And more in the other logicals.

> (define_expand "one_cmplsi2"
>   [(set (match_operand:SI 0 "gpr_operand" "")
>         (xor:SI (match_operand:SI 1 "gpr_operand" "")
>                 (match_dup 2)))]
>   ""
>   "emit_insn (gen_xorsi3 (operands[0], operands[1],
>                           force_reg (SImode, GEN_INT (-1))));
>    DONE;")
> 
> (define_insn "*one_cmplsi2_i"
>   [(set (match_operand:SI 0 "gpr_operand" "=r")
>         (not:SI (match_operand:SI 1 "gpr_operand" "r")))
>    (clobber (reg:CC CC_REGNUM))]
>   "epiphany_m1reg >= 0"
>   "eor %0,%1,%-")

Why not combine these?  I'm pretty sure that expand_binop will try the xor
solution all on its own.  I'd think you'd only want to not use that when
m1reg is available.

Of course, if gpr_operand were to include -1 when m1reg is available, and
you swapped all the constraints to something other than "r", you get even
this for free.

>   "*
> {
>   rtx xop[3];
> 
>   xop[0] = operands[0];
>   xop[1] = operands[1];
>   xop[2] = GEN_INT (31-INTVAL (operands[2]));
>   output_asm_insn (\"lsl %0,%1,%2\", xop);
>   return \"\";
> }")

Please don't use "* in new code; { } is sufficient, and you get to remove
all of the gross \" bits.

> (define_insn "*mov<mode>cc_insn"
>   [(set (match_operand:WMODE 0 "gpr_operand" "=r")
>         (if_then_else:WMODE (match_operator 3 "proper_comparison_operator"
>                               [(match_operand 4 "cc_operand") (const_int 0)])
>                             (match_operand:WMODE 1 "nonmemory_operand" "r")
>                             (match_operand:WMODE 2 "gpr_operand" "0")))]

If there's a good reason for nonmemory_operand and not gpr_operand here,
you should add a big comment.  It looks like a mistake.

> static bool
> epiphany_frame_pointer_required (void)
> {
>   return cfun->calls_alloca;

Isn't this automatic?

> epiphany-load-combiner.o : $(srcdir)/config/epiphany/epiphany-load-combiner.c \

Missing file?

> #define IMM16(X)     ((unsigned)(X) <= 0xFFFF)
> #define IMM5(X)      ((unsigned)(X) <= 0x1F)

These need to be unsigned HOST_WIDE_INT, at minimum.
Preferably no cast at all and compare vs 0 as well.

> /* ??? This currently isn't used.  Waiting for PIC.  */
> #if 0
> #define EXTRA_CONSTRAINT(VALUE, C) \
> ((C) == 'R' ? (SYMBOL_REF_FUNCTION_P (VALUE) || GET_CODE (VALUE) == LABEL_REF) \

Just remove it.

There appear to be quite a number of macros in this file that have been
migrated to target hooks.  Please move them.

> /* For DWARF.  Marginally different than default so output is "prettier"
>    (and consistent with above).  */
> #define PUSHSECTION_ASM_OP "\t.section "

Unused?

> /* Tell crtstuff.c we're using ELF.  */
> #define OBJECT_FORMAT_ELF

Why wouldn't you get this from config/elfos.h?



r~



More information about the Gcc-patches mailing list