Add FRAME_V tokens for local variables.

When storing to a local, stop killing the tokens of other locals,
unless they might overlap with the stored local.  This helps some
procedures that juggle locals when the locals aren't in registers.

Also use FRAME_V tokens for locals in statically enclosing procedures.
Rewrite _lxa_ as _lxl_, to skip the `addi ?,?,8` if we can add 8 to
the next constant.  The PowerPC code from _lxl_ is now sometimes
better, sometimes worse than before.

The i386 table provided the idea to use %size to find overlapping
locals.
This commit is contained in:
George Koehler 2017-12-22 17:04:16 -05:00
parent 4bb31c296d
commit 2eeee36f78

View file

@ -9,7 +9,6 @@ INT64 = 8
FP_OFFSET = 0 /* Offset of saved FP relative to our FP */ FP_OFFSET = 0 /* Offset of saved FP relative to our FP */
PC_OFFSET = 4 /* Offset of saved PC relative to our FP */ PC_OFFSET = 4 /* Offset of saved PC relative to our FP */
SL_OFFSET = 8 /* Offset of static link */
#define COMMENT(n) /* comment {LABEL, n} */ #define COMMENT(n) /* comment {LABEL, n} */
@ -19,6 +18,12 @@ SL_OFFSET = 8 /* Offset of static link */
#define smalls(n) sfit(n, 16) #define smalls(n) sfit(n, 16)
#define smallu(n) ufit(n, 16) #define smallu(n) ufit(n, 16)
/* Finds FRAME_V tokens that overlap myoff, mysize. */
#define fover(myoff, mysize) (%off+%size>(myoff) && %off<((myoff)+(mysize)))
/* Checks if we can use {LXFRAME, x}. */
#define nicelx(x) ((x)>=1 && (x)<=0x8000)
#define lo(n) ((n) & 0xFFFF) #define lo(n) ((n) & 0xFFFF)
#define hi(n) (((n)>>16) & 0xFFFF) #define hi(n) (((n)>>16) & 0xFFFF)
@ -138,6 +143,8 @@ TOKENS
DIV_RR = { GPR reg1; GPR reg2; } 4. /* reg1 / reg2 signed */ DIV_RR = { GPR reg1; GPR reg2; } 4. /* reg1 / reg2 signed */
DIV_RR_U = { GPR reg1; GPR reg2; } 4. /* reg1 / reg2 unsigned */ DIV_RR_U = { GPR reg1; GPR reg2; } 4. /* reg1 / reg2 unsigned */
/* Indirect loads and stores */
IND_RC_B = { GPR reg; INT off; } 4 off "(" reg ")". IND_RC_B = { GPR reg; INT off; } 4 off "(" reg ")".
IND_RL_B = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". IND_RL_B = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")".
IND_RR_B = { GPR reg1; GPR reg2; } 4. IND_RR_B = { GPR reg1; GPR reg2; } 4.
@ -154,6 +161,23 @@ TOKENS
IND_RL_D = { GPR reg; ADDR adr; } 8 "lo16[" adr "](" reg ")". IND_RL_D = { GPR reg; ADDR adr; } 8 "lo16[" adr "](" reg ")".
IND_RR_D = { GPR reg1; GPR reg2; } 8. IND_RR_D = { GPR reg1; GPR reg2; } 8.
/* Local variables in frame */
FRAME_B = { INT level; GPR reg; INT off; INT size; }
4 off "(" reg ")".
FRAME_H = { INT level; GPR reg; INT off; INT size; }
4 off "(" reg ")".
FRAME_H_S = { INT level; GPR reg; INT off; INT size; }
4 off "(" reg ")".
FRAME_W = { INT level; GPR reg; INT off; INT size; }
4 off "(" reg ")".
FRAME_D = { INT level; GPR reg; INT off; INT size; }
8 off "(" reg ")".
LXFRAME = { INT level; } 4.
/* Bitwise logic */
NOT_R = { GPR reg; } 4. /* ~reg */ NOT_R = { GPR reg; } 4. /* ~reg */
AND_RIS = { GPR reg; INT valhi; } 4. AND_RIS = { GPR reg; INT valhi; } 4.
AND_RC = { GPR reg; INT val; } 4. AND_RC = { GPR reg; INT val; } 4.
@ -170,6 +194,8 @@ TOKENS
NOR_RR = { GPR reg1; GPR reg2; } 4. /* ~(reg1 | reg2) */ NOR_RR = { GPR reg1; GPR reg2; } 4. /* ~(reg1 | reg2) */
EQV_RR = { GPR reg1; GPR reg2; } 4. /* ~(reg1 ^ reg2) */ EQV_RR = { GPR reg1; GPR reg2; } 4. /* ~(reg1 ^ reg2) */
/* Comparisons */
COND_RC = { GPR reg; INT val; } 4. COND_RC = { GPR reg; INT val; } 4.
COND_RR = { GPR reg1; GPR reg2; } 4. COND_RR = { GPR reg1; GPR reg2; } 4.
CONDL_RC = { GPR reg; INT val; } 4. CONDL_RC = { GPR reg; INT val; } 4.
@ -200,27 +226,37 @@ SETS
CONST = C + CONST_STACK. CONST = C + CONST_STACK.
IND_ALL_B = IND_RC_B + IND_RL_B + IND_RR_B. SET_RC_B = IND_RC_B + IND_RL_B + FRAME_B.
IND_ALL_H = IND_RC_H + IND_RL_H + IND_RR_H + SET_RC_H = IND_RC_H + IND_RL_H + FRAME_H.
IND_RC_H_S + IND_RL_H_S + IND_RR_H_S. SET_RC_H_S = IND_RC_H_S + IND_RL_H_S + FRAME_H_S.
IND_ALL_W = IND_RC_W + IND_RL_W + IND_RR_W. SET_RC_W = IND_RC_W + IND_RL_W + FRAME_W.
IND_ALL_D = IND_RC_D + IND_RL_D + IND_RR_D. SET_RC_D = IND_RC_D + IND_RL_D + FRAME_D.
IND_ALL_B = IND_RC_B + IND_RL_B + IND_RR_B.
IND_ALL_H = IND_RC_H + IND_RL_H + IND_RR_H +
IND_RC_H_S + IND_RL_H_S + IND_RR_H_S.
IND_ALL_W = IND_RC_W + IND_RL_W + IND_RR_W.
IND_ALL_D = IND_RC_D + IND_RL_D + IND_RR_D.
IND_V = IND_ALL_B + IND_ALL_H + IND_ALL_W + IND_ALL_D.
FRAME_V = FRAME_B + FRAME_H + FRAME_H_S + FRAME_W + FRAME_D.
/* anything killed by sti (store indirect) */ /* anything killed by sti (store indirect) */
MEMORY = IND_ALL_B + IND_ALL_H + IND_ALL_W + IND_ALL_D. MEMORY = IND_V + FRAME_V.
/* any integer from stack that we can easily move to GPR */ /* any integer from stack that we can easily move to GPR */
INT_W = REG + CONST_STACK + SEX_B + SEX_H + INT_W = REG + CONST_STACK + SEX_B + SEX_H +
SUM_RIS + SUM_RC + SUM_RL + SUM_RR + SUM_RIS + SUM_RC + SUM_RL + SUM_RR +
SUB_RR + NEG_R + MUL_RR + DIV_RR + DIV_RR_U + SUB_RR + NEG_R + MUL_RR + DIV_RR + DIV_RR_U +
IND_ALL_B + IND_ALL_H + IND_ALL_W + IND_ALL_B + IND_ALL_H + IND_ALL_W +
FRAME_B + FRAME_H + FRAME_H_S + FRAME_W +
NOT_R + AND_RIS + AND_RC + AND_RR + ANDC_RR + NOT_R + AND_RIS + AND_RC + AND_RR + ANDC_RR +
OR_RIS + OR_RC + OR_RR + ORC_RR + OR_RIS + OR_RC + OR_RR + ORC_RR +
XOR_RIS + XOR_RC + XOR_RR + NAND_RR + NOR_RR + EQV_RR + XOR_RIS + XOR_RC + XOR_RR + NAND_RR + NOR_RR + EQV_RR +
XEQ + XNE + XGT + XGE + XLT + XLE. XEQ + XNE + XGT + XGE + XLT + XLE.
FLOAT_D = FREG + IND_ALL_D. FLOAT_D = FREG + IND_ALL_D + FRAME_D.
FLOAT_W = FSREG + IND_ALL_W. FLOAT_W = FSREG + IND_ALL_W + FRAME_W.
INSTRUCTIONS INSTRUCTIONS
@ -293,21 +329,21 @@ INSTRUCTIONS
frsp FSREG+LOCAL:wo, FREG:ro cost(4, 5). frsp FSREG+LOCAL:wo, FREG:ro cost(4, 5).
fsub FREG+DLOCAL:wo, FREG:ro, FREG:ro cost(4, 5). fsub FREG+DLOCAL:wo, FREG:ro, FREG:ro cost(4, 5).
fsubs FSREG+LOCAL:wo, FSREG:ro, FSREG:ro cost(4, 5). fsubs FSREG+LOCAL:wo, FSREG:ro, FSREG:ro cost(4, 5).
lbz GPR:wo, IND_RC_B+IND_RL_B:ro cost(4, 3). lbz GPR:wo, SET_RC_B:ro cost(4, 3).
lbzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). lbzx GPR:wo, GPR:ro, GPR:ro cost(4, 3).
lfd FPR+DLOCAL:wo, IND_RC_D+IND_RL_D:ro cost(4, 5). lfd FPR+DLOCAL:wo, SET_RC_D:ro cost(4, 5).
lfdu FPR:wo, IND_RC_D:ro cost(4, 5). lfdu FPR:wo, IND_RC_D:ro cost(4, 5).
lfdx FPR:wo, GPR:ro, GPR:ro cost(4, 5). lfdx FPR:wo, GPR:ro, GPR:ro cost(4, 5).
lfs FSREG+LOCAL:wo, IND_RC_W+IND_RL_W:ro cost(4, 4). lfs FSREG+LOCAL:wo, SET_RC_W:ro cost(4, 4).
lfsu FSREG:wo, IND_RC_W:rw cost(4, 4). lfsu FSREG:wo, IND_RC_W:rw cost(4, 4).
lfsx FSREG:wo, GPR:ro, GPR:ro cost(4, 4). lfsx FSREG:wo, GPR:ro, GPR:ro cost(4, 4).
lha GPR:wo, IND_RC_H_S+IND_RL_H_S:ro cost(4, 3). lha GPR:wo, SET_RC_H_S:ro cost(4, 3).
lhax GPR:wo, GPR:ro, GPR:ro cost(4, 3). lhax GPR:wo, GPR:ro, GPR:ro cost(4, 3).
lhz GPR:wo, IND_RC_H+IND_RL_H:ro cost(4, 3). lhz GPR:wo, SET_RC_H:ro cost(4, 3).
lhzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). lhzx GPR:wo, GPR:ro, GPR:ro cost(4, 3).
lwzu GPR:wo, IND_RC_W:rw cost(4, 3). lwzu GPR:wo, IND_RC_W:rw cost(4, 3).
lwzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). lwzx GPR:wo, GPR:ro, GPR:ro cost(4, 3).
lwz GPR+LOCAL:wo, IND_RC_W+IND_RL_W:ro cost(4, 3). lwz GPR+LOCAL:wo, SET_RC_W:ro cost(4, 3).
mfcr GPR:wo cost(4,2). mfcr GPR:wo cost(4,2).
mfspr GPR:wo, SPR:ro cost(4, 3). mfspr GPR:wo, SPR:ro cost(4, 3).
mtspr SPR:wo, GPR:ro cost(4, 2). mtspr SPR:wo, GPR:ro cost(4, 2).
@ -336,17 +372,17 @@ INSTRUCTIONS
sraw GPR+LOCAL:wo, GPR:ro, GPR:ro cost(4, 2). sraw GPR+LOCAL:wo, GPR:ro, GPR:ro cost(4, 2).
srawi GPR+LOCAL:wo, GPR:ro, CONST:ro cost(4, 2). srawi GPR+LOCAL:wo, GPR:ro, CONST:ro cost(4, 2).
srw GPR+LOCAL:wo, GPR:ro, GPR:ro. srw GPR+LOCAL:wo, GPR:ro, GPR:ro.
stb GPR:ro, IND_RC_B+IND_RL_B:rw cost(4, 3). stb GPR:ro, SET_RC_B:rw cost(4, 3).
stbx GPR:ro, GPR:ro, GPR:ro cost(4, 3). stbx GPR:ro, GPR:ro, GPR:ro cost(4, 3).
stfd FPR:ro, IND_RC_D+IND_RL_D:rw cost(4, 4). stfd FPR:ro, SET_RC_D:rw cost(4, 4).
stfdu FPR:ro, IND_RC_D:rw cost(4, 4). stfdu FPR:ro, IND_RC_D:rw cost(4, 4).
stfdx FPR:ro, GPR:ro, GPR:ro cost(4, 4). stfdx FPR:ro, GPR:ro, GPR:ro cost(4, 4).
stfs FSREG:ro, IND_RC_W+IND_RL_W:rw cost(4, 3). stfs FSREG:ro, SET_RC_W:rw cost(4, 3).
stfsu FSREG:ro, IND_RC_W:rw cost(4, 3). stfsu FSREG:ro, IND_RC_W:rw cost(4, 3).
stfsx FSREG:ro, GPR:ro, GPR:ro cost(4, 3). stfsx FSREG:ro, GPR:ro, GPR:ro cost(4, 3).
sth GPR:ro, IND_RC_H+IND_RL_H:rw cost(4, 3). sth GPR:ro, SET_RC_H:rw cost(4, 3).
sthx GPR:ro, GPR:ro, GPR:ro cost(4, 3). sthx GPR:ro, GPR:ro, GPR:ro cost(4, 3).
stw GPR:ro, IND_RC_W+IND_RL_W:rw cost(4, 3). stw GPR:ro, SET_RC_W:rw cost(4, 3).
stwx GPR:ro, GPR:ro, GPR:ro cost(4, 3). stwx GPR:ro, GPR:ro, GPR:ro cost(4, 3).
stwu GPR:ro, IND_RC_W:rw cost(4, 3). stwu GPR:ro, IND_RC_W:rw cost(4, 3).
xor GPR:wo, GPR:ro, GPR:ro. xor GPR:wo, GPR:ro, GPR:ro.
@ -439,7 +475,7 @@ MOVES
/* Read byte */ /* Read byte */
from IND_RC_B+IND_RL_B to GPR from SET_RC_B to GPR
gen lbz %2, %1 gen lbz %2, %1
from IND_RR_B to GPR from IND_RR_B to GPR
@ -447,7 +483,7 @@ MOVES
/* Write byte */ /* Write byte */
from GPR to IND_RC_B+IND_RL_B from GPR to SET_RC_B
gen stb %1, %2 gen stb %1, %2
from GPR to IND_RR_B from GPR to IND_RR_B
@ -455,13 +491,13 @@ MOVES
/* Read halfword (short) */ /* Read halfword (short) */
from IND_RC_H+IND_RL_H to GPR from SET_RC_H to GPR
gen lhz %2, %1 gen lhz %2, %1
from IND_RR_H to GPR from IND_RR_H to GPR
gen lhzx %2, %1.reg1, %1.reg2 gen lhzx %2, %1.reg1, %1.reg2
from IND_RC_H_S+IND_RL_H_S to GPR from SET_RC_H_S to GPR
gen lha %2, %1 gen lha %2, %1
from IND_RR_H_S to GPR from IND_RR_H_S to GPR
@ -469,7 +505,7 @@ MOVES
/* Write halfword */ /* Write halfword */
from GPR to IND_RC_H+IND_RL_H from GPR to SET_RC_H
gen sth %1, %2 gen sth %1, %2
from GPR to IND_RR_H from GPR to IND_RR_H
@ -477,13 +513,13 @@ MOVES
/* Read word */ /* Read word */
from IND_RC_W+IND_RL_W to GPR from SET_RC_W to GPR
gen lwz %2, %1 gen lwz %2, %1
from IND_RR_W to GPR from IND_RR_W to GPR
gen lwzx %2, %1.reg1, %1.reg2 gen lwzx %2, %1.reg1, %1.reg2
from IND_RC_W+IND_RL_W to FSREG from SET_RC_W to FSREG
gen lfs %2, %1 gen lfs %2, %1
from IND_RR_W to FSREG from IND_RR_W to FSREG
@ -491,13 +527,13 @@ MOVES
/* Write word */ /* Write word */
from GPR to IND_RC_W+IND_RL_W from GPR to SET_RC_W
gen stw %1, %2 gen stw %1, %2
from GPR to IND_RR_W from GPR to IND_RR_W
gen stwx %1, %2.reg1, %2.reg2 gen stwx %1, %2.reg1, %2.reg2
from FSREG to IND_RC_W+IND_RL_W from FSREG to SET_RC_W
gen stfs %1, %2 gen stfs %1, %2
from FSREG to IND_RR_W from FSREG to IND_RR_W
@ -505,7 +541,7 @@ MOVES
/* Read double */ /* Read double */
from IND_RC_D+IND_RL_D to FPR from SET_RC_D to FPR
gen lfd %2, %1 gen lfd %2, %1
from IND_RR_D to FPR from IND_RR_D to FPR
@ -513,12 +549,41 @@ MOVES
/* Write double */ /* Write double */
from FPR to IND_RC_D+IND_RL_D from FPR to SET_RC_D
gen stfd %1, %2 gen stfd %1, %2
from FPR to IND_RR_D from FPR to IND_RR_D
gen stfdx %1, %2.reg1, %2.reg2 gen stfdx %1, %2.reg1, %2.reg2
/* LXFRAME is a lexical frame from the static chain. We define a move
so "uses REG={LXFRAME, $1}" may find a register with the same
frame, and not repeat the move. This move can't search for a REG
with {LXFRAME, $1-1}, but must always start from fp. The static
chain, if it exists, is the argument at fp + EM_BSIZE. */
from LXFRAME %level==1 to REG
gen lwz %2, {IND_RC_W, fp, EM_BSIZE}
from LXFRAME %level==2 to REG
gen lwz %2, {IND_RC_W, fp, EM_BSIZE}
/* PowerPC can't add r0 + EM_BSIZE,
* so %2 must not be r0. */
lwz %2, {IND_RC_W, %2, EM_BSIZE}
from LXFRAME %level==3 to REG
gen lwz %2, {IND_RC_W, fp, EM_BSIZE}
lwz %2, {IND_RC_W, %2, EM_BSIZE}
lwz %2, {IND_RC_W, %2, EM_BSIZE}
from LXFRAME %level==4 to REG
gen lwz %2, {IND_RC_W, fp, EM_BSIZE}
lwz %2, {IND_RC_W, %2, EM_BSIZE}
lwz %2, {IND_RC_W, %2, EM_BSIZE}
lwz %2, {IND_RC_W, %2, EM_BSIZE}
from LXFRAME to REG /* assuming %level in 2 to 0x8000 */
gen li %2, {C, %1.level-1}
mtspr ctr, %2
lwz %2, {IND_RC_W, fp, EM_BSIZE}
1: lwz %2, {IND_RC_W, %2, EM_BSIZE}
bdnz {LABEL, "1b"}
/* Logicals */ /* Logicals */
from NOT_R to GPR from NOT_R to GPR
@ -661,6 +726,11 @@ TESTS
STACKINGRULES STACKINGRULES
/* We don't allow GPR-REG on the stack. The intent is to ban
* r0 from the stack, but this also bans fp from the stack.
* This is odd because most other tables for ncg allow the
* frame pointer on the stack.
*/
from REG to STACK from REG to STACK
gen gen
COMMENT("stack REG") COMMENT("stack REG")
@ -760,6 +830,11 @@ COERCIONS
gen move {SUM_RR, %1.reg1, %1.reg2}, r12 gen move {SUM_RR, %1.reg1, %1.reg2}, r12
yields {IND_RC_W, r12, 4} {IND_RC_W, r12, 0} yields {IND_RC_W, r12, 4} {IND_RC_W, r12, 0}
from FRAME_D %off<=0x7FFA
yields
{FRAME_W, %1.level, %1.reg, %1.off+4, 4}
{FRAME_W, %1.level, %1.reg, %1.off, 4}
PATTERNS PATTERNS
@ -897,24 +972,47 @@ PATTERNS
uses REG={SUM_RIS, fp, his($1)} uses REG={SUM_RIS, fp, his($1)}
yields {SUM_RC, %a, los($1)} yields {SUM_RC, %a, los($1)}
pat lal loi smalls($1) && $2==1 /* Load byte from local */
yields {FRAME_B, 0, fp, $1, 1}
/* Load half-word from local and sign-extend */
pat lal loi loc loc cii smalls($1) && $2==2 && $3==2 && $4==4
yields {FRAME_H_S, 0, fp, $1, 1}
pat lal loi smalls($1) && $2==2 /* Load half-word from local */
yields {FRAME_H, 0, fp, $1, 1}
/* Load word from local */ /* Load word from local */
pat lol inreg($1)==reg_any || inreg($1)==reg_float pat lol inreg($1)==reg_any || inreg($1)==reg_float
yields {LOCAL, $1} yields {LOCAL, $1}
pat lol smalls($1)
yields {FRAME_W, 0, fp, $1, 4}
pat lol pat lol
leaving leaving
lal $1 lal $1
loi 4 loi 4
/* Load double-word from local */ pat ldl inreg($1)==reg_float /* Load double-word from local */
pat ldl inreg($1)==reg_float
yields {DLOCAL, $1} yields {DLOCAL, $1}
pat ldl smalls($1) && smalls($1+4)
/* smalls($1+4) implies FRAME_D %off<=0xFFFA */
yields {FRAME_D, 0, fp, $1, 8}
pat ldl pat ldl
leaving leaving
lal $1 lal $1
loi 8 loi 8
/* Store word to local */ pat lal sti smalls($1) && $2==1 /* Store byte to local */
pat stl inreg($1)==reg_any with REG
kills IND_V, FRAME_V %level==0 && fover($1, 1)
gen move %1, {FRAME_B, 0, fp, $1, 1}
pat lal sti smalls($1) && $2==2 /* Store half-word to local */
with REG
kills IND_V, FRAME_V %level==0 && fover($1, 2)
gen move %1, {FRAME_H, 0, fp, $1, 2}
pat stl inreg($1)==reg_any /* Store word to local */
with exact INT_W with exact INT_W
/* ncg fails to infer that regvar($1) is dead! */ /* ncg fails to infer that regvar($1) is dead! */
kills regvar($1) kills regvar($1)
@ -924,58 +1022,69 @@ PATTERNS
lwz {LOCAL, $1}, {IND_RC_W, sp, 0} lwz {LOCAL, $1}, {IND_RC_W, sp, 0}
addi sp, sp, {C, 4} addi sp, sp, {C, 4}
pat stl inreg($1)==reg_float pat stl inreg($1)==reg_float
with exact FSREG+IND_ALL_W with exact FLOAT_W
kills regvar_w($1, reg_float) kills regvar_w($1, reg_float)
gen move %1, {FSREG_EXPR, regvar_w($1, reg_float)} gen move %1, {FSREG_EXPR, regvar_w($1, reg_float)}
with STACK with STACK
gen gen
lfs {LOCAL, $1}, {IND_RC_W, sp, 0} lfs {LOCAL, $1}, {IND_RC_W, sp, 0}
addi sp, sp, {C, 4} addi sp, sp, {C, 4}
pat stl smalls($1)
with REG+FSREG
kills IND_V, FRAME_V %level==0 && fover($1, 4)
gen move %1, {FRAME_W, 0, fp, $1, 4}
pat stl pat stl
leaving leaving
lal $1 lal $1
sti 4 sti 4
/* Store double-word to local */ pat sdl inreg($1)==reg_float /* Store double-word to local */
pat sdl inreg($1)==reg_float with exact FLOAT_D
with exact FREG+IND_ALL_D
kills regvar_d($1, reg_float) kills regvar_d($1, reg_float)
gen move %1, {FPR_EXPR, regvar_d($1, reg_float)} gen move %1, {FPR_EXPR, regvar_d($1, reg_float)}
with STACK with STACK
gen gen
lfd {DLOCAL, $1}, {IND_RC_D, sp, 0} lfd {DLOCAL, $1}, {IND_RC_D, sp, 0}
addi sp, sp, {C, 8} addi sp, sp, {C, 8}
pat sdl smalls($1) && smalls($1+4)
with REG REG
kills IND_V, FRAME_V %level==0 && fover($1, 8)
gen
move %1, {FRAME_W, 0, fp, $1, 4}
move %2, {FRAME_W, 0, fp, $1+4, 4}
with FREG
kills IND_V, FRAME_V %level==0 && fover($1, 4)
gen move %1, {FRAME_D, 0, fp, $1, 8}
pat sdl pat sdl
leaving leaving
lal $1 lal $1
sti 8 sti 8
/* Load indirect from local */ pat lil inreg($1)==reg_any /* Load indirect from local */
pat lil inreg($1)==reg_any
yields {IND_RC_W, regvar($1), 0} yields {IND_RC_W, regvar($1), 0}
pat lil pat lil
leaving leaving
lol $1 lol $1
loi 4 loi 4
pat sil /* Save to indirected local */ pat sil /* Store indirect to local */
leaving leaving
lol $1 lol $1
sti 4 sti 4
pat zrl /* Zero local */ pat zrl /* Zero local */
leaving leaving
loc 0 loc 0
stl $1 stl $1
pat inl /* Increment local */ pat inl /* Increment local */
leaving leaving
lol $1 lol $1
loc 1 loc 1
adi 4 adi 4
stl $1 stl $1
pat del /* Decrement local */ pat del /* Decrement local */
leaving leaving
lol $1 lol $1
loc 1 loc 1
@ -983,9 +1092,87 @@ PATTERNS
stl $1 stl $1
/* Local variables of procedures on static chain */
/* lxa (lexical argument base) -> lxl (lexical local base) */
pat lxa adp nicelx($1)
leaving lxl $1 adp $2+EM_BSIZE
pat lxa lof nicelx($1)
leaving lxl $1 lof $2+EM_BSIZE
pat lxa ldf nicelx($1)
leaving lxl $1 ldf $2+EM_BSIZE
pat lxa stf nicelx($1)
leaving lxl $1 stf $2+EM_BSIZE
pat lxa sdf nicelx($1)
leaving lxl $1 stf $2+EM_BSIZE
pat lxa $1==0 || nicelx($1)
leaving lxl $1 adp EM_BSIZE
/* Load locals in statically enclosing procedures */
pat lxl adp loi nicelx($1) && smalls($2) && $3==1
uses REG={LXFRAME, $1}
yields {FRAME_B, $1, %a, $2, 1}
pat lxl adp loi loc loc cii nicelx($1) && smalls($2) &&
$3==2 && $4==2 && $5==4
uses REG={LXFRAME, $1}
yields {FRAME_H_S, $1, %a, $2, 2}
pat lxl adp loi nicelx($1) && smalls($2) && $3==2
uses REG={LXFRAME, $1}
yields {FRAME_H, $1, %a, $2, 2}
pat lxl lof nicelx($1) && smalls($2)
uses REG={LXFRAME, $1}
yields {FRAME_W, $1, %a, $2, 4}
pat lxl ldf nicelx($1) && smalls($2) && smalls($2+4)
uses REG={LXFRAME, $1}
/* smalls($2+4) implies FRAME_D %off<=0xFFFA */
yields {FRAME_D, $1, %a, $2, 8}
/* Store locals in statically enclosing procedures */
pat lxl adp sti nicelx($1) && smalls($2) && $3==1
with REG
kills IND_V, FRAME_V %level==$1 && fover($2, 1)
uses REG={LXFRAME, $1}
gen move %1, {FRAME_B, $1, %a, $2, 1}
pat lxl adp sti nicelx($1) && smalls($2) && $3==2
with REG
kills IND_V, FRAME_V %level==$1 && fover($2, 2)
uses REG={LXFRAME, $1}
gen move %1, {FRAME_H, $1, %a, $2, 2}
pat lxl stf nicelx($1) && smalls($2)
with REG+FSREG
kills IND_V, FRAME_V %level==$1 && fover($2, 4)
uses REG={LXFRAME, $1}
gen move %1, {FRAME_W, $1, %a, $2, 4}
pat lxl sdf nicelx($1) && smalls($2) && smalls($2+4)
with REG REG
kills IND_V, FRAME_V %level==$1 && fover($2, 8)
uses REG={LXFRAME, $1}
gen
move %1, {FRAME_W, $1, %a, $2, 4}
move %2, {FRAME_W, $1, %a, $2+4, 4}
with FREG
kills IND_V, FRAME_V %level==$1 && fover($2, 8)
uses REG={LXFRAME, $1}
gen move %1, {FRAME_D, $1, %a, $2, 8}
/* Programs use "lxl cal" to pass the static chain and call a
* nested procedure. This must push a token LXFRAME or the
* register fp to the real stack. */
/* Local base of procedure on static chain */
pat lxl nicelx($1)
uses REG={LXFRAME, $1}
yields %a /* Can't yield LXFRAME. */
pat lxl $1==0 /* Our local base */
with STACK
gen stwu fp, {IND_RC_W, sp, 0-4}
/* Can't yield fp. */
/* Global variables */ /* Global variables */
pat lpi /* Load address of external function */ pat lpi /* Load address of function */
leaving leaving
lae $1 lae $1
@ -2008,30 +2195,11 @@ PATTERNS
leaving leaving
ret 0 ret 0
/* /* Our caller's local base, "lxl 0 dch", appears in
* Lexical local base: lxl 0 yields our fp, lxl n yields the * lang/cem/libcc.ansi/setjmp/setjmp.e, lang/m2/libm2/par_misc.e
* fp of the nth statically enclosing procedure.
*/ */
pat lxl $1==0 pat lxl dch $1==0
leaving yields {IND_RC_W, fp, FP_OFFSET}
lor 0
pat lxl $1==1
yields {IND_RC_W, fp, SL_OFFSET}
pat lxl $1==2
uses REG={IND_RC_W, fp, SL_OFFSET}
yields {IND_RC_W, %a, SL_OFFSET}
pat lxl $1==3
uses REG={IND_RC_W, fp, SL_OFFSET}, reusing %a, REG
gen move {IND_RC_W, %a, SL_OFFSET}, %b
yields {IND_RC_W, %b, SL_OFFSET}
pat lxl $1>=4 && $1<=0x8000
uses REG={IND_RC_W, fp, SL_OFFSET},
REG={CONST_0000_7FFF, $1-1}
gen
mtspr ctr, %b
1: lwz %a, {IND_RC_W, %a, SL_OFFSET}
bdnz {LABEL, "1b"}
yields %a
pat dch /* Dynamic chain: LB -> caller's LB */ pat dch /* Dynamic chain: LB -> caller's LB */
with REG with REG
@ -2041,11 +2209,6 @@ PATTERNS
leaving leaving
adp EM_BSIZE adp EM_BSIZE
pat lxa /* Lexical argument base */
leaving
lxl $1
lpb
pat gto /* longjmp */ pat gto /* longjmp */
with STACK with STACK
uses REG uses REG
@ -2058,26 +2221,20 @@ PATTERNS
bctr. bctr.
pat lor $1==0 /* Load local base */ pat lor $1==0 /* Load local base */
uses REG leaving lxl 0
gen
move fp, %a
yields %a
pat lor $1==1 /* Load stack pointer */ pat lor $1==1 /* Load stack pointer */
uses REG with STACK
gen uses REG=sp
move sp, %a yields %a /* Can't yield sp. */
yields %a
pat str $1==0 /* Store local base */ pat str $1==0 /* Store local base */
with REG with REG
gen gen move %1, fp
move %1, fp
pat str $1==1 /* Store stack pointer */ pat str $1==1 /* Store stack pointer */
with REG with REG
gen gen move %1, sp
move %1, sp
pat lae rck $2==4 /* Range check */ pat lae rck $2==4 /* Range check */
with REG with REG