This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [target.md]: Backend passes cause code bloat of +140%.


Weddington, Eric schrieb:

> Anatoly Sokolov and I already have a patch to add builtin function capabilities for the AVR. Could you send us your patches?


The patch is contained in my top post


http://gcc.gnu.org/ml/gcc/2009-01/msg00309.html

Here a verbatim copy, so it is easier to discuss what goes wrong and how things could have been implemented better.

It's nice to learn about gcc no matter if the stuff below will end in gcc or not.

Georg-Johann

Index: gcc/config/avr/avr.md
===================================================================
--- gcc/config/avr/avr.md    (revision 143546)
+++ gcc/config/avr/avr.md    (working copy)
@@ -59,7 +59,10 @@
    (UNSPECV_EPILOGUE_RESTORES    1)
    (UNSPECV_WRITE_SP_IRQ_ON    2)
    (UNSPECV_WRITE_SP_IRQ_OFF    3)
-   (UNSPECV_GOTO_RECEIVER    4)])
+   (UNSPECV_GOTO_RECEIVER    4)
+
+   (UNSPEC_LPM 10)
+   ])

(include "predicates.md")
(include "constraints.md")
@@ -3262,3 +3265,102 @@
expand_epilogue ();
DONE;
}")
+
+
+(define_expand "pgm_read_byte"
+ [(parallel[(match_operand:QI 0 "register_operand" "")
+ (match_operand:HI 1 "register_operand" "")])]
+ ""
+ {
+ rtx Z = gen_rtx_REG (HImode, REG_Z);
+ rtx reg_z = gen_reg_rtx (HImode);
+ rtx reg_z1 = gen_reg_rtx (HImode);
+
+ switch (avr_test)
+ {
+ case 0:
+ emit_move_insn (Z, operands[1]);
+ emit_insn (gen_lpmZ_postinc (operands[0]));
+ break;
+
+ case 1:
+ emit_move_insn (Z, operands[1]);
+ emit_insn (gen_lpmZ_postinc_1 (operands[0]));
+ break;
+
+ case 2:
+ /* Allow modified Z to have other pseudo number than Z */
+ emit_move_insn (Z, operands[1]);
+ emit_insn (gen_lpmZ_postinc_2 (operands[0], reg_z1));
+ break;
+
+ case 3:
+ /* Allow modified Z to have other pseudo number than Z */
+ emit_move_insn (reg_z, operands[1]);
+ emit_insn (gen_lpmZ_postinc_3 (operands[0], reg_z1, reg_z));
+ break;
+
+ default: abort();
+ }
+
+ DONE;
+ })
+
+;; %0 = *Z
+(define_insn "lpmZ"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (unspec:QI [(mem:QI (reg:HI REG_Z))
+ ] UNSPEC_LPM))]
+ ""
+ "lpm %0, Z"
+ [(set_attr "cc" "none")
+ (set_attr "length" "1")])
+
+;; %0 = *Z++
+(define_insn "lpmZ_postinc"
+ [(set (reg:HI REG_Z)
+ (plus:HI (reg:HI REG_Z)
+ (const_int 1)))
+ (set (match_operand:QI 0 "register_operand" "=r")
+ (unspec:QI [(mem:QI (reg:HI REG_Z))
+ ] UNSPEC_LPM))]
+ ""
+ "lpm %0, Z+"
+ [(set_attr "cc" "none")
+ (set_attr "length" "1")])
+
+
+(define_insn "lpmZ_postinc_1"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (unspec:QI [(mem:QI (post_inc (reg:HI REG_Z)))
+ ] UNSPEC_LPM))]
+ ""
+ "lpm %0, Z+"
+ [(set_attr "cc" "none")
+ (set_attr "length" "1")])
+
+(define_insn "lpmZ_postinc_2"
+ [(set (match_operand:HI 1 "register_operand" "+z")
+ (plus:HI (reg:HI REG_Z)
+ (const_int 1)))
+
+ (set (match_operand:QI 0 "register_operand" "=r")
+ (unspec:QI [(mem:QI (reg:HI REG_Z))
+ ] UNSPEC_LPM))]
+ ""
+ "lpm %0, Z+"
+ [(set_attr "cc" "none")
+ (set_attr "length" "1")])
+
+(define_insn "lpmZ_postinc_3"
+ [(set (match_operand:HI 1 "register_operand" "=z")
+ (plus:HI (match_operand:HI 2 "register_operand" "z")
+ (const_int 1)))
+
+ (set (match_operand:QI 0 "register_operand" "=r")
+ (unspec:QI [(mem:QI (match_dup 2))
+ ] UNSPEC_LPM))]
+ ""
+ "lpm %0, Z+"
+ [(set_attr "cc" "none")
+ (set_attr "length" "1")])
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c (revision 143546)
+++ gcc/config/avr/avr.c (working copy)
@@ -29,6 +29,7 @@
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
+#include "insn-codes.h"
#include "insn-attr.h"
#include "flags.h"
#include "reload.h"
@@ -45,6 +46,8 @@
#include "target-def.h"
#include "params.h"
#include "df.h"
+#include "langhooks.h"
+#include "optabs.h" /* For GEN_FCN */


 /* Maximal allowed offset for an address in the LD command */
 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
@@ -88,6 +91,9 @@ static struct machine_function * avr_ini
 static rtx avr_builtin_setjmp_frame_value (void);
 static bool avr_hard_regno_scratch_ok (unsigned int);

+static void avr_init_builtins_hook (void);
+static rtx avr_expand_builtin_hook (tree, rtx, rtx, enum machine_mode mode, int);
+
/* Allocate registers from r25 to r8 for parameters for function calls. */
#define FIRST_CUM_REG 26


@@ -357,6 +363,12 @@ int avr_case_values_threshold = 30000;
 #undef TARGET_HARD_REGNO_SCRATCH_OK
 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok

+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS avr_init_builtins_hook
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN avr_expand_builtin_hook
+
+
 struct gcc_target targetm = TARGET_INITIALIZER;

 void
@@ -6103,4 +6115,112 @@ avr_return_in_memory (const_tree type, c
     return false;
 }

+
+enum avr_builtin_id
+{
+ AVR_BUILTIN_PGM_READ_BYTE,
+
+ AVR_BUILTIN_MAX
+};
+
+enum avr_ftype_id
+{
+ AVR__UNSIGNED_CHAR__FTYPE__CONST_UNSIGNED_CHAR_PTR,
+
+ AVR_FTYPE_MAX
+};
+
+static GTY(()) tree avr_builtin_decls[(int) AVR_BUILTIN_MAX];
+static GTY(()) tree avr_ftypes[(int) AVR_FTYPE_MAX];
+
+static struct avr_builtin_description
+{
+ const enum insn_code icode;
+ const enum avr_ftype_id ftype;
+ const char * const name;
+}
+avr_builtins [AVR_BUILTIN_MAX] =
+{
+ [AVR_BUILTIN_PGM_READ_BYTE] =
+ {
+ .icode = CODE_FOR_pgm_read_byte,
+ .ftype = AVR__UNSIGNED_CHAR__FTYPE__CONST_UNSIGNED_CHAR_PTR,
+ .name = "__builtin_pgm_read_byte"
+ }
+};
+
+static void
+avr_init_ftypes (void)
+{
+ /* const unsigned char * */
+ tree const_unsigned_char_ptr_type_node
+ = build_pointer_type (build_type_variant (unsigned_char_type_node, 1, 0));
+
+ /* unsigned char (*) (const unsigned char*) */
+ avr_ftypes[(int) AVR__UNSIGNED_CHAR__FTYPE__CONST_UNSIGNED_CHAR_PTR]
+ = build_function_type_list (unsigned_char_type_node, const_unsigned_char_ptr_type_node, NULL_TREE);
+}
+
+static void
+avr_init_builtins_hook (void)
+{
+ int id;
+ struct avr_builtin_description * d = avr_builtins;
+
+ avr_init_ftypes ();
+
+ for (id = 0; id < (int) AVR_BUILTIN_MAX; id++, d++)
+ {
+ avr_builtin_decls[id]
+ = add_builtin_function (d->name, avr_ftypes[d->ftype], id,
+ BUILT_IN_MD, NULL, NULL_TREE);
+ }
+}
+
+/* Expand an expression EXP that calls a built-in function, with result going
+ to TARGET if that's convenient (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored. */
+static rtx
+avr_expand_builtin_hook (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ enum insn_code icode;
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ tree arg1;
+ rtx op1, pat;
+ enum machine_mode mode1;
+ unsigned int id = DECL_FUNCTION_CODE (fndecl);
+
+ icode = avr_builtins[id].icode;
+
+ switch (id)
+ {
+ case AVR_BUILTIN_PGM_READ_BYTE:
+
+ arg1 = CALL_EXPR_ARG (exp, 0);
+ mode1 = insn_data[icode].operand[1].mode;
+
+ op1 = expand_normal (arg1);
+ op1 = force_reg (Pmode, op1);
+
+ if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+
+ pat = GEN_FCN (icode) (target, op1);
+ break;
+
+ default:
+ abort();
+ }
+
+ if (!pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+
+ return target;
+}
+
#include "gt-avr.h"
Index: gcc/config/avr/avr.opt
===================================================================
--- gcc/config/avr/avr.opt (revision 143546)
+++ gcc/config/avr/avr.opt (working copy)
@@ -66,3 +66,6 @@ Relax branches
mpmem-wrap-around
Target Report
Make the linker relaxation machine assume that a program counter wrap-around occures.
+
+mtest=
+Target RejectNegative Report Joined Undocumented UInteger Var(avr_test) Init(0)




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]