ack/util/ego/cs/cs.h
George Koehler b1b737ed6c Optimize procedures that do both a / b and a % b.
Enable this in CS for PowerPC; disable it for all other machines.
PowerPC has no remainder instruction; the back end uses division to
compute remainder.  If CS finds both a / b and a % b, then CS now
rewrites a % b as a - b * (a / b) and computes a / b only once.  This
removes an extra division in the PowerPC code, so it saves both time
and space.

I have not considered whether to enable this optimization for other
machines.  It might be less useful in machines with a remainder
instruction.  Also, if a % b occurs before a / b, the EM code gets a
DUP.  PowerPC ncg handles this DUP well; other back ends might not.
2018-03-05 13:32:06 -05:00

130 lines
3.3 KiB
C

/* $Id$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
typedef short valnum;
typedef struct entity *entity_p;
typedef struct avail *avail_p;
typedef struct token *token_p;
typedef struct occur *occur_p;
struct token {
valnum tk_vn;
offset tk_size;
line_p tk_lfirst; /* Textually first instruction, involved
* in pushing this token.
*/
};
/* We distinguish these entities. */
#define ENCONST 0
#define ENLOCAL 1
#define ENEXTERNAL 2
#define ENINDIR 3
#define ENOFFSETTED 4
#define ENALOCAL 5
#define ENAEXTERNAL 6
#define ENAOFFSETTED 7
#define ENALOCBASE 8
#define ENAARGBASE 9
#define ENPROC 10
#define ENFZER 11
#define ENARRELEM 12
#define ENLOCBASE 13
#define ENHEAPPTR 14
#define ENIGNMASK 15
struct entity {
valnum en_vn;
bool en_static;
byte en_kind; /* ENLOCAL, ENEXTERNAL, etc. */
offset en_size;
union {
offset en__val; /* ENCONST. */
offset en__loc; /* ENLOCAL, ENALOCAL. */
obj_p en__ext; /* ENEXTERNAL, ENAEXTERNAL. */
valnum en__ind; /* ENINDIR. */
struct {
valnum en__base;
offset en__off;
} en_offs; /* ENOFFSETTED, ENAOFFSETTED. */
offset en__levels; /* ENALOCBASE, ENAARGBASE. */
proc_p en__pro; /* ENPROC. */
struct {
valnum en__arbase;
valnum en__index;
valnum en__adesc;
} en_arr; /* ENARRELEM. */
} en_inf;
};
/* Macros to increase ease of use. */
#define en_val en_inf.en__val
#define en_loc en_inf.en__loc
#define en_ext en_inf.en__ext
#define en_ind en_inf.en__ind
#define en_base en_inf.en_offs.en__base
#define en_off en_inf.en_offs.en__off
#define en_levels en_inf.en__levels
#define en_pro en_inf.en__pro
#define en_arbase en_inf.en_arr.en__arbase
#define en_index en_inf.en_arr.en__index
#define en_adesc en_inf.en_arr.en__adesc
struct occur {
line_p oc_lfirst; /* First instruction of expression. */
line_p oc_llast; /* Last one. */
bblock_p oc_belongs; /* Basic block it belongs to. */
};
/* We distinguish these groups of instructions. */
#define SIMPLE_LOAD 0
#define EXPENSIVE_LOAD 1
#define LOAD_ARRAY 2
#define STORE_DIRECT 3
#define STORE_INDIR 4
#define STORE_ARRAY 5
#define UNAIR_OP 6
#define BINAIR_OP 7
#define TERNAIR_OP 8
#define REMAINDER 9
#define KILL_ENTITY 10
#define SIDE_EFFECTS 11
#define FIDDLE_STACK 12
#define IGNORE 13
#define HOPELESS 14
#define BBLOCK_END 15
struct avail {
avail_p av_before; /* Ptr to earlier discovered expressions. */
byte av_instr; /* Operator instruction. */
offset av_size;
line_p av_found; /* Line where expression is first found. */
lset av_occurs; /* Set of recurrences of expression. */
entity_p av_saveloc; /* Local where result is put in. */
valnum av_result;
union {
valnum av__operand; /* EXPENSIVE_LOAD, UNAIR_OP. */
struct {
valnum av__oleft;
valnum av__oright;
} av_2; /* BINAIR_OP. */
struct {
valnum av__ofirst;
valnum av__osecond;
valnum av__othird;
} av_3; /* TERNAIR_OP. */
} av_o;
};
/* Macros to increase ease of use. */
#define av_operand av_o.av__operand
#define av_oleft av_o.av_2.av__oleft
#define av_oright av_o.av_2.av__oright
#define av_ofirst av_o.av_3.av__ofirst
#define av_osecond av_o.av_3.av__osecond
#define av_othird av_o.av_3.av__othird
extern int Scs; /* Number of optimizations found. */