b1b737ed6c
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.
130 lines
3.3 KiB
C
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. */
|