X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbearch.h;h=bf222581c7af0fff967fc05029b80bf862b9c499;hb=5d6cfd12693c34b702aab148038ebb562f2695f9;hp=cdc14f3a37bacd29638963a74677c29e419ec1f2;hpb=d2c1b0191844c3c23731158a153838d570dcd65a;p=libfirm diff --git a/ir/be/bearch.h b/ir/be/bearch.h index cdc14f3a3..bf222581c 100644 --- a/ir/be/bearch.h +++ b/ir/be/bearch.h @@ -32,6 +32,7 @@ #include "bitset.h" #include "obst.h" #include "raw_bitset.h" +#include "irop_t.h" #include "be_types.h" #include "beinfo.h" @@ -77,24 +78,25 @@ typedef enum arch_register_req_type_t { extern const arch_register_req_t *arch_no_register_req; /** - * Format a register requirements information into a string. - * @param buf The string where to put it to. - * @param len The size of @p buf. + * Print information about a register requirement in human readable form + * @param F output stream/file * @param req The requirements structure to format. - * @return A pointer to buf. */ -extern char *arch_register_req_format(char *buf, size_t len, const arch_register_req_t *req, const ir_node *node); +void arch_dump_register_req(FILE *F, const arch_register_req_t *req, + const ir_node *node); + +void arch_dump_register_reqs(FILE *F, const ir_node *node); +void arch_dump_reqs_and_registers(FILE *F, const ir_node *node); /** - * Certain node classes which are relevant for the register allocator. + * Node classification. Mainly used for statistics. */ typedef enum arch_irn_class_t { - arch_irn_class_spill = 1 << 0, - arch_irn_class_reload = 1 << 1, - arch_irn_class_remat = 1 << 2, - arch_irn_class_copy = 1 << 3, - arch_irn_class_perm = 1 << 4, - arch_irn_class_branch = 1 << 5 + arch_irn_class_spill = 1 << 0, + arch_irn_class_reload = 1 << 1, + arch_irn_class_remat = 1 << 2, + arch_irn_class_copy = 1 << 3, + arch_irn_class_perm = 1 << 4 } arch_irn_class_t; void arch_set_frame_offset(ir_node *irn, int bias); @@ -110,6 +112,10 @@ void arch_perform_memory_operand(ir_node *irn, ir_node *spill, unsign /** * Get the register requirements for a node. + * @note Deprecated API! Preferably use + * arch_get_in_register_req and + * arch_get_out_register_req. + * * @param irn The node. * @param pos The position of the operand you're interested in. * @return A pointer to the register requirements. If NULL is returned, the @@ -117,8 +123,6 @@ void arch_perform_memory_operand(ir_node *irn, ir_node *spill, unsign */ const arch_register_req_t *arch_get_register_req(const ir_node *irn, int pos); -#define arch_get_register_req_out(irn) arch_get_register_req(irn, -1) - /** * Put all registers which shall not be ignored by the register * allocator in a bit set. @@ -214,8 +218,9 @@ void be_register_isa_if(const char *name, const arch_isa_if_t *isa); struct arch_register_t { const char *name; /**< The name of the register. */ const arch_register_class_t *reg_class; /**< The class the register belongs to. */ - unsigned index; /**< The index of the register in the class. */ - arch_register_type_t type; /**< The type of the register. */ + unsigned index; /**< The index of the register in the class. */ + arch_register_type_t type; /**< The type of the register. */ + const arch_register_req_t *single_req; }; static inline const arch_register_class_t * @@ -236,9 +241,9 @@ const char *_arch_register_get_name(const arch_register_t *reg) return reg->name; } -#define arch_register_get_class(reg) _arch_register_get_class(reg) -#define arch_register_get_index(reg) _arch_register_get_index(reg) -#define arch_register_get_name(reg) _arch_register_get_name(reg) +#define arch_register_get_class(reg) _arch_register_get_class(reg) +#define arch_register_get_index(reg) _arch_register_get_index(reg) +#define arch_register_get_name(reg) _arch_register_get_name(reg) /** * Convenience macro to check for register type. @@ -254,13 +259,14 @@ const char *_arch_register_get_name(const arch_register_t *reg) * Like general purpose or floating point. */ struct arch_register_class_t { - unsigned index; /**< index of this register class */ - const char *name; /**< The name of the register class.*/ - unsigned n_regs; /**< Number of registers in this - class. */ - ir_mode *mode; /**< The mode of the register class.*/ - const arch_register_t *regs; /**< The array of registers. */ - arch_register_class_flags_t flags; /**< register class flags. */ + unsigned index; /**< index of this register class */ + const char *name; /**< The name of the register class.*/ + unsigned n_regs; /**< Number of registers in this + class. */ + ir_mode *mode; /**< The mode of the register class.*/ + const arch_register_t *regs; /**< The array of registers. */ + arch_register_class_flags_t flags; /**< register class flags. */ + const arch_register_req_t *class_req; }; /** return the number of registers in this register class */ @@ -300,7 +306,7 @@ _arch_register_for_index(const arch_register_class_t *cls, unsigned idx) * Expresses requirements to register allocation for an operand. */ struct arch_register_req_t { - arch_register_req_type_t type; /**< The type of the constraint. */ + arch_register_req_type_t type; /**< The type of the constraint. */ const arch_register_class_t *cls; /**< The register class this constraint belongs to. */ const unsigned *limited; /**< allowed register bitset */ @@ -355,13 +361,12 @@ struct arch_irn_ops_t { /** * Get the register requirements for a given operand. - * @param self The self pointer. * @param irn The node. - * @param pos The operand's position (0..n for the input operands). + * @param pos The operand's position * @return The register requirements for the selected operand. * The pointer returned is never NULL. */ - const arch_register_req_t *(*get_irn_reg_req)(const ir_node *irn, int pos); + const arch_register_req_t *(*get_irn_reg_req_in)(const ir_node *irn, int pos); /** * Classify the node. @@ -372,7 +377,6 @@ struct arch_irn_ops_t { /** * Get the entity on the stack frame this node depends on. - * @param self The this pointer. * @param irn The node in question. * @return The entity on the stack frame or NULL, if the node does not have a * stack frame entity. @@ -381,7 +385,6 @@ struct arch_irn_ops_t { /** * Set the entity on the stack frame this node depends on. - * @param self The this pointer. * @param irn The node in question. * @param ent The entity to set */ @@ -389,7 +392,6 @@ struct arch_irn_ops_t { /** * Set the offset of a node carrying an entity on the stack frame. - * @param self The this pointer. * @param irn The node. * @param offset The offset of the node's stack frame entity. */ @@ -402,7 +404,6 @@ struct arch_irn_ops_t { * A positive value stands for an expanding stack area, a negative value for * a shrinking one. * - * @param self The this pointer * @param irn The node * @return 0 if the stackpointer is not modified with a constant * value, otherwise the increment/decrement value @@ -413,7 +414,6 @@ struct arch_irn_ops_t { * Returns an inverse operation which yields the i-th argument * of the given node as result. * - * @param self The this pointer. * @param irn The original operation * @param i Index of the argument we want the inverse operation to yield * @param inverse struct to be filled with the resulting inverse op @@ -425,7 +425,6 @@ struct arch_irn_ops_t { /** * Get the estimated cycle count for @p irn. * - * @param self The this pointer. * @param irn The node. * * @return The estimated cycle count for this operation @@ -435,7 +434,6 @@ struct arch_irn_ops_t { /** * Asks the backend whether operand @p i of @p irn can be loaded form memory internally * - * @param self The this pointer. * @param irn The node. * @param i Index of the argument we would like to know whether @p irn can load it form memory internally * @@ -446,7 +444,6 @@ struct arch_irn_ops_t { /** * Ask the backend to assimilate @p reload of operand @p i into @p irn. * - * @param self The this pointer. * @param irn The node. * @param spill The spill. * @param i The position of the reload. @@ -570,14 +567,14 @@ struct arch_isa_if_t { * Get the the number of register classes in the isa. * @return The number of register classes. */ - unsigned (*get_n_reg_class)(const void *self); + unsigned (*get_n_reg_class)(void); /** * Get the i-th register class. * @param i The number of the register class. * @return The register class. */ - const arch_register_class_t *(*get_reg_class)(const void *self, unsigned i); + const arch_register_class_t *(*get_reg_class)(unsigned i); /** * Get the register class which shall be used to store a value of a given mode. @@ -585,7 +582,7 @@ struct arch_isa_if_t { * @param mode The mode in question. * @return A register class which can hold values of the given mode. */ - const arch_register_class_t *(*get_reg_class_for_mode)(const void *self, const ir_mode *mode); + const arch_register_class_t *(*get_reg_class_for_mode)(const ir_mode *mode); /** * Get the ABI restrictions for procedure calls. @@ -625,7 +622,7 @@ struct arch_isa_if_t { * @param cls The register class. * @return The alignment in bytes. */ - int (*get_reg_class_alignment)(const void *self, const arch_register_class_t *cls); + int (*get_reg_class_alignment)(const arch_register_class_t *cls); /** * A "static" function, returns the frontend settings @@ -648,7 +645,7 @@ struct arch_isa_if_t { * NULL * }; */ - const be_execution_unit_t ***(*get_allowed_execution_units)(const void *self, const ir_node *irn); + const be_execution_unit_t ***(*get_allowed_execution_units)(const ir_node *irn); /** * Return the abstract machine for this isa. @@ -669,41 +666,41 @@ struct arch_isa_if_t { /** * mark node as rematerialized */ - void (*mark_remat)(const void *self, ir_node *node); + void (*mark_remat)(ir_node *node); /** * parse an assembler constraint part and set flags according to its nature * advances the *c pointer to point to the last parsed character (so if you * parse a single character don't advance c) */ - asm_constraint_flags_t (*parse_asm_constraint)(const void *self, const char **c); + asm_constraint_flags_t (*parse_asm_constraint)(const char **c); /** * returns true if the string is a valid clobbered (register) in this * backend */ - int (*is_valid_clobber)(const void *self, const char *clobber); + int (*is_valid_clobber)(const char *clobber); }; #define arch_env_done(env) ((env)->impl->done(env)) #define arch_env_handle_intrinsics(env) \ do { if((env)->impl->handle_intrinsics != NULL) (env)->impl->handle_intrinsics(); } while(0) -#define arch_env_get_n_reg_class(env) ((env)->impl->get_n_reg_class(env)) -#define arch_env_get_reg_class(env,i) ((env)->impl->get_reg_class(env, i)) -#define arch_env_get_reg_class_for_mode(env,mode) ((env)->impl->get_reg_class_for_mode((env), (mode))) +#define arch_env_get_n_reg_class(env) ((env)->impl->get_n_reg_class()) +#define arch_env_get_reg_class(env,i) ((env)->impl->get_reg_class(i)) +#define arch_env_get_reg_class_for_mode(env,mode) ((env)->impl->get_reg_class_for_mode((mode))) #define arch_env_get_call_abi(env,tp,abi) ((env)->impl->get_call_abi((env), (tp), (abi))) #define arch_env_get_code_generator_if(env) ((env)->impl->get_code_generator_if((env))) #define arch_env_get_list_sched_selector(env,selector) ((env)->impl->get_list_sched_selector((env), (selector))) #define arch_env_get_ilp_sched_selector(env) ((env)->impl->get_ilp_sched_selector(env)) -#define arch_env_get_reg_class_alignment(env,cls) ((env)->impl->get_reg_class_alignment((env), (cls))) +#define arch_env_get_reg_class_alignment(env,cls) ((env)->impl->get_reg_class_alignment((cls))) #define arch_env_get_params(env) ((env)->impl->get_params()) -#define arch_env_get_allowed_execution_units(env,irn) ((env)->impl->get_allowed_execution_units((env), (irn))) +#define arch_env_get_allowed_execution_units(env,irn) ((env)->impl->get_allowed_execution_units((irn))) #define arch_env_get_machine(env) ((env)->impl->get_machine(env)) #define arch_env_get_backend_irg_list(env,irgs) ((env)->impl->get_backend_irg_list((env), (irgs))) -#define arch_env_parse_asm_constraint(env,c) ((env)->impl->parse_asm_constraint((env), (c)) -#define arch_env_is_valid_clobber(env,clobber) ((env)->impl->is_valid_clobber((env), (clobber)) +#define arch_env_parse_asm_constraint(env,c) ((env)->impl->parse_asm_constraint((c)) +#define arch_env_is_valid_clobber(env,clobber) ((env)->impl->is_valid_clobber((clobber)) #define arch_env_mark_remat(env,node) \ - do { if ((env)->impl->mark_remat != NULL) (env)->impl->mark_remat((env), (node)); } while(0) + do { if ((env)->impl->mark_remat != NULL) (env)->impl->mark_remat((node)); } while(0) /** * ISA base class. @@ -723,9 +720,46 @@ struct arch_env_t { static inline unsigned arch_irn_get_n_outs(const ir_node *node) { backend_info_t *info = be_get_info(node); + if (info->out_infos == NULL) + return 0; + return ARR_LEN(info->out_infos); } +static inline const arch_irn_ops_t *get_irn_ops_simple(const ir_node *node) +{ + const ir_op *ops = get_irn_op(node); + const arch_irn_ops_t *be_ops = get_op_ops(ops)->be_ops; + assert(!is_Proj(node)); + return be_ops; +} + +static inline const arch_register_req_t *arch_get_register_req_out( + const ir_node *irn) +{ + int pos = 0; + backend_info_t *info; + + if (is_Proj(irn)) { + pos = get_Proj_proj(irn); + irn = get_Proj_pred(irn); + } else if (get_irn_mode(irn) == mode_T) { + /* TODO: find out who does this and fix the caller! */ + return arch_no_register_req; + } + info = be_get_info(irn); + if (info->out_infos == NULL) + return arch_no_register_req; + + return info->out_infos[pos].req; +} + +static inline bool arch_irn_is_ignore(const ir_node *irn) +{ + const arch_register_req_t *req = arch_get_register_req_out(irn); + return !!(req->type & arch_register_req_type_ignore); +} + static inline bool arch_irn_consider_in_reg_alloc( const arch_register_class_t *cls, const ir_node *node) { @@ -735,10 +769,34 @@ static inline bool arch_irn_consider_in_reg_alloc( !(req->type & arch_register_req_type_ignore); } -static inline bool arch_irn_is_ignore(const ir_node *irn) +/** + * Get register constraints for an operand at position @p + */ +static inline const arch_register_req_t *arch_get_in_register_req( + const ir_node *node, int pos) { - const arch_register_req_t *req = arch_get_register_req_out(irn); - return !!(req->type & arch_register_req_type_ignore); + const arch_irn_ops_t *ops = get_irn_ops_simple(node); + return ops->get_irn_reg_req_in(node, pos); +} + +/** + * Get register constraint for a produced result (the @p pos result) + */ +static inline const arch_register_req_t *arch_get_out_register_req( + const ir_node *node, int pos) +{ + const backend_info_t *info = be_get_info(node); + if (info->out_infos == NULL) + return arch_no_register_req; + return info->out_infos[pos].req; +} + +static inline void arch_set_out_register_req(ir_node *node, int pos, + const arch_register_req_t *req) +{ + backend_info_t *info = be_get_info(node); + assert(pos < (int) arch_irn_get_n_outs(node)); + info->out_infos[pos].req = req; } -#endif /* FIRM_BE_BEARCH_H */ +#endif