Rewrite how PowerPC ncg does conditional branches and tests.

The rewritten code rules bring 3 new features:

  1.  The new rules compare a small constant with a register by
      reversing the comparison and using `cmpwi` or `cmplwi`.  The old
      rules put the constant in a register.

  2.  The new rules emit shorter code to yield the test results,
      without referencing the tables in mach/powerpc/ncg/tge.s.

  3.  The new rules use the extended `beq` and relatives, not the
      basic `bc`, in the assembly output.

I delete the old tristate tokens and the old moves, because they
confused me.  Some of the old moves weren't really moves.  For
example, `move R3, C0` and then `move C0, R0` did not move r3 to r0.

I rename C0 to CR0.
This commit is contained in:
George Koehler 2017-01-25 19:08:55 -05:00
parent a348853ece
commit f64b7d8ea0

View file

@ -27,15 +27,6 @@ PC_OFFSET = 4 /* Offset of saved PC relative to our FP */
#define los(n) (lo(n) | (((0-(lo(n)>>15)) & ~0xFFFF))) #define los(n) (lo(n) | (((0-(lo(n)>>15)) & ~0xFFFF)))
#define his(n) ((hi(n) + (lo(n)>>15)) & 0xFFFF) #define his(n) ((hi(n) + (lo(n)>>15)) & 0xFFFF)
#define IFFALSE {CONST, 4}
#define IFTRUE {CONST, 12}
#define ALWAYS {CONST, 20}
#define DCTRZ {CONST, 34}
#define LT {CONST, 0}
#define GT {CONST, 1}
#define EQ {CONST, 2}
PROPERTIES PROPERTIES
@ -54,8 +45,6 @@ PROPERTIES
GPR16 GPR17 GPR18 GPR19 GPR20 GPR21 GPR22 GPR23 GPR16 GPR17 GPR18 GPR19 GPR20 GPR21 GPR22 GPR23
GPR24 GPR25 GPR26 GPR27 GPR28 GPR29 GPR30 GPR31 GPR24 GPR25 GPR26 GPR27 GPR28 GPR29 GPR30 GPR31
CR0 CR1
FPR0(8) FPR1(8) FPR2(8) FPR3(8) FPR4(8) FPR5(8) FPR6(8) FPR7(8) FPR0(8) FPR1(8) FPR2(8) FPR3(8) FPR4(8) FPR5(8) FPR6(8) FPR7(8)
FPR8(8) FPR9(8) FPR10(8) FPR11(8) FPR12(8) FPR13(8) FPR14(8) FPR15(8) FPR8(8) FPR9(8) FPR10(8) FPR11(8) FPR12(8) FPR13(8) FPR14(8) FPR15(8)
FPR16(8) FPR17(8) FPR18(8) FPR19(8) FPR20(8) FPR21(8) FPR22(8) FPR23(8) FPR16(8) FPR17(8) FPR18(8) FPR19(8) FPR20(8) FPR21(8) FPR22(8) FPR23(8)
@ -158,7 +147,7 @@ REGISTERS
LR("lr") : SPR. LR("lr") : SPR.
CTR("ctr") : SPR. CTR("ctr") : SPR.
C0("cr0") : CR, CR0. CR0("cr0") : CR.
#define RSCRATCH R11 #define RSCRATCH R11
#define FSCRATCH F0 #define FSCRATCH F0
@ -200,13 +189,6 @@ TOKENS
SUM_RC = { GPR reg; INT off; } 4. SUM_RC = { GPR reg; INT off; } 4.
SUM_RR = { GPR reg1; GPR reg2; } 4. SUM_RR = { GPR reg1; GPR reg2; } 4.
TRISTATE_RC_S = { GPR reg; INT val; } 4.
TRISTATE_RC_U = { GPR reg; INT val; } 4.
TRISTATE_RR_S = { GPR reg1; GPR reg2; } 4.
TRISTATE_RR_U = { GPR reg1; GPR reg2; } 4.
TRISTATE_FF = { FPR reg1; FPR reg2; } 4.
SEX_B = { GPR reg; } 4. SEX_B = { GPR reg; } 4.
SEX_H = { GPR reg; } 4. SEX_H = { GPR reg; } 4.
@ -231,6 +213,20 @@ TOKENS
XOR_RIS = { GPR reg; INT valhi; } 4. XOR_RIS = { GPR reg; INT valhi; } 4.
XOR_RC = { GPR reg; INT val; } 4. XOR_RC = { GPR reg; INT val; } 4.
COND_RC = { GPR reg; INT val; } 4.
COND_RR = { GPR reg1; GPR reg2; } 4.
CONDL_RC = { GPR reg; INT val; } 4.
CONDL_RR = { GPR reg1; GPR reg2; } 4.
COND_FS = { FSREG reg1; FSREG reg2; } 4.
COND_FD = { FREG reg1; FREG reg2; } 4.
XEQ = { GPR reg; } 4.
XNE = { GPR reg; } 4.
XGT = { GPR reg; } 4.
XGE = { GPR reg; } 4.
XLT = { GPR reg; } 4.
XLE = { GPR reg; } 4.
SETS SETS
@ -246,9 +242,6 @@ SETS
SUM_ALL = SUM_RC + SUM_RR. SUM_ALL = SUM_RC + SUM_RR.
TRISTATE_ALL = TRISTATE_RC_S + TRISTATE_RC_U + TRISTATE_RR_S +
TRISTATE_RR_U + TRISTATE_FF.
SEX_ALL = SEX_B + SEX_H. SEX_ALL = SEX_B + SEX_H.
LOGICAL_ALL = NOT_R + AND_RR + OR_RR + OR_RC + XOR_RR + LOGICAL_ALL = NOT_R + AND_RR + OR_RR + OR_RC + XOR_RR +
@ -265,8 +258,7 @@ SETS
/* anything killed by sti (store indirect) */ /* anything killed by sti (store indirect) */
MEMORY = IND_ALL_BHW + IND_ALL_D. MEMORY = IND_ALL_BHW + IND_ALL_D.
OP_ALL_W = SUM_ALL + TRISTATE_ALL + SEX_ALL + LOGICAL_ALL + OP_ALL_W = SUM_ALL + SEX_ALL + LOGICAL_ALL + IND_ALL_W.
IND_ALL_W.
INSTRUCTIONS INSTRUCTIONS
@ -293,14 +285,27 @@ INSTRUCTIONS
andisX "andis." GPR:wo:cc, GPR:ro, CONST:ro. andisX "andis." GPR:wo:cc, GPR:ro, CONST:ro.
b LABEL:ro. b LABEL:ro.
bc CONST:ro, CONST:ro, LABEL:ro. bc CONST:ro, CONST:ro, LABEL:ro.
beq LABEL:ro.
bne LABEL:ro.
bgt LABEL:ro.
bge LABEL:ro.
blt LABEL:ro.
ble LABEL:ro.
bxx LABEL:ro. /* dummy */
bcctr CONST:ro, CONST:ro, CONST:ro. bcctr CONST:ro, CONST:ro, CONST:ro.
bctr.
bcctrl CONST:ro, CONST:ro, CONST:ro. bcctrl CONST:ro, CONST:ro, CONST:ro.
bctrl.
bclr CONST:ro, CONST:ro, CONST:ro. bclr CONST:ro, CONST:ro, CONST:ro.
bl LABEL:ro. bl LABEL:ro.
cmp CR:ro, CONST:ro, GPR:ro, GPR:ro kills :cc. cmp CR:ro, CONST:ro, GPR:ro, GPR:ro kills :cc.
cmpw GPR:ro, GPR:ro kills :cc.
cmpi CR:ro, CONST:ro, GPR:ro, CONST:ro kills :cc. cmpi CR:ro, CONST:ro, GPR:ro, CONST:ro kills :cc.
cmpwi GPR:ro, CONST:ro kills :cc.
cmpl CR:ro, CONST:ro, GPR:ro, GPR:ro kills :cc. cmpl CR:ro, CONST:ro, GPR:ro, GPR:ro kills :cc.
cmplw GPR:ro, GPR:ro kills :cc.
cmpli CR:ro, CONST:ro, GPR:ro, CONST:ro kills :cc. cmpli CR:ro, CONST:ro, GPR:ro, CONST:ro kills :cc.
cmplwi GPR:ro, CONST:ro kills :cc.
divw GPR:wo, GPR:ro, GPR:ro cost(4, 23). divw GPR:wo, GPR:ro, GPR:ro cost(4, 23).
divwu GPR:wo, GPR:ro, GPR:ro cost(4, 23). divwu GPR:wo, GPR:ro, GPR:ro cost(4, 23).
eqv GPR:wo, GPR:ro, GPR:ro. eqv GPR:wo, GPR:ro, GPR:ro.
@ -308,7 +313,8 @@ INSTRUCTIONS
extsh GPR:wo, GPR:ro. extsh GPR:wo, GPR:ro.
fadd FREG:wo, FREG:ro, FREG:ro cost(4, 5). fadd FREG:wo, FREG:ro, FREG:ro cost(4, 5).
fadds FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5). fadds FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5).
fcmpo CR:wo, FPR:ro, FPR:ro cost(4, 5). fcmpo CR:wo, FREG:ro, FREG:ro cost(4, 5).
fcmpo CR:wo, FSREG:ro, FSREG:ro cost(4, 5).
fdiv FREG:wo, FREG:ro, FREG:ro cost(4, 35). fdiv FREG:wo, FREG:ro, FREG:ro cost(4, 35).
fdivs FSREG:wo, FSREG:ro, FSREG:ro cost(4, 21). fdivs FSREG:wo, FSREG:ro, FSREG:ro cost(4, 21).
fmr FPR:wo, FPR:ro cost(4, 5). fmr FPR:wo, FPR:ro cost(4, 5).
@ -349,6 +355,8 @@ INSTRUCTIONS
oris GPR:wo, GPR:ro, CONST:ro. oris GPR:wo, GPR:ro, CONST:ro.
orX "or." GPR:wo:cc, GPR:ro, GPR:ro. orX "or." GPR:wo:cc, GPR:ro, GPR:ro.
rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro. rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro.
extlwi GPR:wo, GPR:ro, CONST:ro, CONST:ro.
extrwi GPR:wo, GPR:ro, CONST:ro, CONST:ro.
slw GPR:wo, GPR:ro, GPR:ro. slw GPR:wo, GPR:ro, GPR:ro.
subf GPR:wo, GPR:ro, GPR:ro. subf GPR:wo, GPR:ro, GPR:ro.
sraw GPR:wo, GPR:ro, GPR:ro cost(4, 2). sraw GPR:wo, GPR:ro, GPR:ro cost(4, 2).
@ -566,67 +574,6 @@ MOVES
COMMENT("move FPR->IND_RR_W") COMMENT("move FPR->IND_RR_W")
stfdx %1, %2.reg1, %2.reg2 stfdx %1, %2.reg1, %2.reg2
/* Extract condition code field (actually produces (CC&3)<<2) */
from CR0 to GPR
gen
COMMENT("move CR0->GPR")
mfcr %2
rlwinm %2, %2, {CONST, 4}, {CONST, 32-4}, {CONST, 31-2}
/* Comparisons */
from TRISTATE_RR_S to CR0
gen
cmp %2, {CONST, 0}, %1.reg1, %1.reg2
from TRISTATE_RR_U to CR0
gen
cmpl %2, {CONST, 0}, %1.reg1, %1.reg2
from TRISTATE_RC_S to CR0
gen
COMMENT("move TRISTATE_RC_S->CR0 large")
move {CONST, %1.val}, RSCRATCH
cmp %2, {CONST, 0}, %1.reg, RSCRATCH
from TRISTATE_RC_U smallu(%val) to CR0
gen
COMMENT("move TRISTATE_RC_U->CR0 small")
cmpli %2, {CONST, 0}, %1.reg, {CONST, %1.val}
from TRISTATE_RC_U to CR0
gen
COMMENT("move TRISTATE_RC_U->CR0")
move {CONST, %1.val}, RSCRATCH
cmpl %2, {CONST, 0}, %1.reg, RSCRATCH
from TRISTATE_FF to CR0
gen
COMMENT("move TRISTATE_FF->CR0")
fcmpo %2, %1.reg1, %1.reg2
from GPR to CR0
gen
COMMENT("move GPR->CR0")
orX RSCRATCH, %1, %1 /* alas, can't call test */
from TRISTATE_RR_S + TRISTATE_RC_S + TRISTATE_FF to GPR
gen
COMMENT("move TRISTATE_R*_S->GPR")
move %1, C0
move C0, RSCRATCH
move {LABEL, ".tristate_s_table"}, %2
lwzx %2, %2, RSCRATCH
from TRISTATE_RR_U + TRISTATE_RC_U to GPR
gen
COMMENT("move TRISTATE_R*_U->GPR")
move %1, C0
move C0, RSCRATCH
move {LABEL, ".tristate_u_table"}, %2
lwzx %2, %2, RSCRATCH
/* Logicals */ /* Logicals */
from NOT_R to GPR from NOT_R to GPR
@ -669,6 +616,71 @@ MOVES
COMMENT("move XOR_RC->GPR") COMMENT("move XOR_RC->GPR")
xori %2, %1.reg, {CONST, %1.val} xori %2, %1.reg, {CONST, %1.val}
/* Conditions */
/* Compare values, then copy cr0 to GPR. */
from COND_RC to GPR
gen
cmpwi %1.reg, {CONST, %1.val}
mfcr %2
from COND_RR to GPR
gen
cmpw %1.reg1, %1.reg2
mfcr %2
from CONDL_RC to GPR
gen
cmplwi %1.reg, {CONST, %1.val}
mfcr %2
from CONDL_RR to GPR
gen
cmplw %1.reg1, %1.reg2
mfcr %2
from COND_FS to GPR
gen
fcmpo CR0, %1.reg1, %1.reg2
mfcr %2
from COND_FD to GPR
gen
fcmpo CR0, %1.reg1, %1.reg2
mfcr %2
/* Given a copy of cr0 in %1.reg, extract a condition bit
* (lt, gt, eq) and perhaps flip it.
*/
from XEQ to GPR
gen
extrwi %2, %1.reg, {CONST, 1}, {CONST, 2}
from XNE to GPR
gen
extrwi %2, %1.reg, {CONST, 1}, {CONST, 2}
xori %2, %2, {CONST, 1}
from XGT to GPR
gen
extrwi %2, %1.reg, {CONST, 1}, {CONST, 1}
from XGE to GPR
gen
extrwi %2, %1.reg, {CONST, 1}, {CONST, 0}
xori %2, %2, {CONST, 1}
from XLT to GPR
gen
extrwi %2, %1.reg, {CONST, 1}, {CONST, 0}
from XLE to GPR
gen
extrwi %2, %1.reg, {CONST, 1}, {CONST, 1}
xori %2, %2, {CONST, 1}
/* Miscellaneous */ /* Miscellaneous */
from OP_ALL_W + LABEL + CONST_ALL to GPRE from OP_ALL_W + LABEL + CONST_ALL to GPRE
@ -720,9 +732,9 @@ STACKINGRULES
extsh RSCRATCH, %1.reg extsh RSCRATCH, %1.reg
stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL to STACK from SUM_ALL + LOGICAL_ALL to STACK
gen gen
COMMENT("stack SUM_ALL + TRISTATE_ALL + LOGICAL_ALL") COMMENT("stack SUM_ALL + LOGICAL_ALL")
move %1, RSCRATCH move %1, RSCRATCH
stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
@ -804,7 +816,7 @@ COERCIONS
extsh %a, %1.reg extsh %a, %1.reg
yields %a yields %a
from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL from SUM_ALL + LOGICAL_ALL
uses REG uses REG
gen gen
move %1, %a move %1, %a
@ -1683,153 +1695,337 @@ PATTERNS
cal ".inn" cal ".inn"
/* Boolean resolutions */ /* Boolean resolutions */
pat teq /* top = (top == 0) */ pat teq /* top = (top == 0) */
with TRISTATE_ALL + GPR with REG
uses reusing %1, REG uses reusing %1, REG
gen gen
move %1, C0 test %1
move C0, RSCRATCH mfcr %a
move {LABEL, ".teq_table"}, %a move {XEQ, %a}, %a
lwzx %a, %a, RSCRATCH
yields %a yields %a
pat tne /* top = (top != 0) */ pat tne /* top = (top != 0) */
with TRISTATE_ALL + GPR with REG
uses reusing %1, REG uses reusing %1, REG
gen gen
move %1, C0 test %1
move C0, RSCRATCH mfcr %a
move {LABEL, ".tne_table"}, %a move {XNE, %a}, %a
lwzx %a, %a, RSCRATCH
yields %a yields %a
pat tlt /* top = (top < 0) */ pat tlt /* top = (top < 0) */
with TRISTATE_ALL + GPR with REG
uses reusing %1, REG uses reusing %1, REG
gen gen
move %1, C0 test %1
move C0, RSCRATCH mfcr %a
move {LABEL, ".tlt_table"}, %a move {XLT, %a}, %a
lwzx %a, %a, RSCRATCH
yields %a yields %a
pat tle /* top = (top <= 0) */ pat tle /* top = (top <= 0) */
with TRISTATE_ALL + GPR with REG
uses reusing %1, REG uses reusing %1, REG
gen gen
move %1, C0 test %1
move C0, RSCRATCH mfcr %a
move {LABEL, ".tle_table"}, %a move {XLE, %a}, %a
lwzx %a, %a, RSCRATCH
yields %a yields %a
pat tgt /* top = (top > 0) */ pat tgt /* top = (top > 0) */
with TRISTATE_ALL + GPR with REG
uses reusing %1, REG uses reusing %1, REG
gen gen
move %1, C0 test %1
move C0, RSCRATCH mfcr %a
move {LABEL, ".tgt_table"}, %a move {XGT, %a}, %a
lwzx %a, %a, RSCRATCH
yields %a yields %a
pat tge /* top = (top >= 0) */ pat tge /* top = (top >= 0) */
with TRISTATE_ALL + GPR with REG
uses reusing %1, REG uses reusing %1, REG
gen gen
move %1, C0 test %1
move C0, RSCRATCH mfcr %a
move {LABEL, ".tge_table"}, %a move {XGE, %a}, %a
lwzx %a, %a, RSCRATCH
yields %a yields %a
pat cmi teq $1==4 /* Signed second == top */
with REG CONST2
uses reusing %1, REG={COND_RC, %1, %2.val}
gen move {XEQ, %a}, %a
yields %a
with CONST2 REG
uses reusing %1, REG={COND_RC, %2, %1.val}
gen move {XEQ, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={COND_RR, %2, %1}
gen move {XEQ, %a}, %a
yields %a
pat cmi tne $1==4 /* Signed second != top */
with REG CONST2
uses reusing %1, REG={COND_RC, %1, %2.val}
gen move {XNE, %a}, %a
yields %a
with CONST2 REG
uses reusing %1, REG={COND_RC, %2, %1.val}
gen move {XNE, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={COND_RR, %2, %1}
gen move {XNE, %a}, %a
yields %a
pat cmi tgt $1==4 /* Signed second > top */
with REG CONST2
uses reusing %1, REG={COND_RC, %1, %2.val}
gen move {XLT, %a}, %a
yields %a
with CONST2 REG
uses reusing %1, REG={COND_RC, %2, %1.val}
gen move {XGT, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={COND_RR, %2, %1}
gen move {XGT, %a}, %a
yields %a
pat cmi tge $1==4 /* Signed second >= top */
with REG CONST2
uses reusing %1, REG={COND_RC, %1, %2.val}
gen move {XLE, %a}, %a
yields %a
with CONST2 REG
uses reusing %1, REG={COND_RC, %2, %1.val}
gen move {XGE, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={COND_RR, %2, %1}
gen move {XGE, %a}, %a
yields %a
pat cmi tlt $1==4 /* Signed second < top */
with REG CONST2
uses reusing %1, REG={COND_RC, %1, %2.val}
gen move {XGT, %a}, %a
yields %a
with CONST2 REG
uses reusing %1, REG={COND_RC, %2, %1.val}
gen move {XLT, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={COND_RR, %2, %1}
gen move {XLT, %a}, %a
yields %a
pat cmi tle $1==4 /* Signed second <= top */
with REG CONST2
uses reusing %1, REG={COND_RC, %1, %2.val}
gen move {XGE, %a}, %a
yields %a
with CONST2 REG
uses reusing %1, REG={COND_RC, %2, %1.val}
gen move {XLE, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={COND_RR, %2, %1}
gen move {XLE, %a}, %a
yields %a
pat cmu teq $1==4 /* Unsigned second == top */
with REG UCONST2
uses reusing %1, REG={CONDL_RC, %1, %2.val}
gen move {XEQ, %a}, %a
yields %a
with UCONST2 REG
uses reusing %1, REG={CONDL_RC, %2, %1.val}
gen move {XEQ, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={CONDL_RR, %2, %1}
gen move {XEQ, %a}, %a
yields %a
pat cmu tne $1==4 /* Unsigned second != top */
with REG UCONST2
uses reusing %1, REG={CONDL_RC, %1, %2.val}
gen move {XNE, %a}, %a
yields %a
with UCONST2 REG
uses reusing %1, REG={CONDL_RC, %2, %1.val}
gen move {XNE, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={CONDL_RR, %2, %1}
gen move {XNE, %a}, %a
yields %a
pat cmu tgt $1==4 /* Unsigned second > top */
with REG UCONST2
uses reusing %1, REG={CONDL_RC, %1, %2.val}
gen move {XLT, %a}, %a
yields %a
with UCONST2 REG
uses reusing %1, REG={CONDL_RC, %2, %1.val}
gen move {XGT, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={CONDL_RR, %2, %1}
gen move {XGT, %a}, %a
yields %a
pat cmu tge $1==4 /* Unsigned second >= top */
with REG UCONST2
uses reusing %1, REG={CONDL_RC, %1, %2.val}
gen move {XLE, %a}, %a
yields %a
with UCONST2 REG
uses reusing %1, REG={CONDL_RC, %2, %1.val}
gen move {XGE, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={CONDL_RR, %2, %1}
gen move {XGE, %a}, %a
yields %a
pat cmu tlt $1==4 /* Unsigned second < top */
with REG UCONST2
uses reusing %1, REG={CONDL_RC, %1, %2.val}
gen move {XGT, %a}, %a
yields %a
with UCONST2 REG
uses reusing %1, REG={CONDL_RC, %2, %1.val}
gen move {XLT, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={CONDL_RR, %2, %1}
gen move {XLT, %a}, %a
yields %a
pat cmu tle $1==4 /* Unsigned second <= top */
with REG UCONST2
uses reusing %1, REG={CONDL_RC, %1, %2.val}
gen move {XGE, %a}, %a
yields %a
with UCONST2 REG
uses reusing %1, REG={CONDL_RC, %2, %1.val}
gen move {XLE, %a}, %a
yields %a
with REG REG
uses reusing %1, REG={CONDL_RR, %2, %1}
gen move {XLE, %a}, %a
yields %a
/* Simple branches */ /* Simple branches */
pat zeq /* Branch if signed top == 0 */ proc zxx example zeq
with TRISTATE_ALL+GPR STACK with REG STACK
gen gen
move %1, C0 test %1
bc IFTRUE, EQ, {LABEL, $1} bxx* {LABEL, $1}
pat beq /* Pop signed int, branch if... */
leaving pat zeq call zxx("beq") /* top == 0 */
cmi INT32 pat zne call zxx("bne") /* top != 0 */
zeq $1 pat zgt call zxx("bgt") /* top > 0 */
pat zge call zxx("bge") /* top >= 0 */
pat zlt call zxx("blt") /* top < 0 */
pat zle call zxx("ble") /* top >= 0 */
pat zne /* Branch if signed top != 0 */ /* The peephole optimizer rewrites
with TRISTATE_ALL+GPR STACK * cmi 4 zeq
* as beq, and does same for bne, bgt, and so on.
*/
proc bxx example beq
with REG CONST2 STACK
gen gen
move %1, C0 cmpwi %1, {CONST, %2.val}
bc IFFALSE, EQ, {LABEL, $1} bxx[2] {LABEL, $1}
with CONST2 REG STACK
pat bne
leaving
cmi INT32
zne $1
pat zgt /* Branch if signed top > 0 */
with TRISTATE_ALL+GPR STACK
gen gen
move %1, C0 cmpwi %2, {CONST, %1.val}
bc IFTRUE, GT, {LABEL, $1} bxx[1] {LABEL, $1}
with REG REG STACK
pat bgt
leaving
cmi INT32
zgt $1
pat zge /* Branch if signed top >= 0 */
with TRISTATE_ALL+GPR STACK
gen gen
move %1, C0 cmpw %2, %1
bc IFFALSE, LT, {LABEL, $1} bxx[1] {LABEL, $1}
pat bge /* Pop two signed ints, branch if... */
leaving pat beq call bxx("beq", "beq") /* second == top */
cmi INT32 pat bne call bxx("bne", "bne") /* second != top */
zge $1 pat bgt call bxx("bgt", "blt") /* second > top */
pat bge call bxx("bge", "ble") /* second >= top */
pat blt call bxx("blt", "bgt") /* second < top */
pat ble call bxx("ble", "bge") /* second >= top */
pat zlt /* Branch if signed top < 0 */ proc cmu4zxx example cmu zeq
with TRISTATE_ALL+GPR STACK with REG CONST2 STACK
gen gen
move %1, C0 cmplwi %1, {CONST, %2.val}
bc IFTRUE, LT, {LABEL, $1} bxx[2] {LABEL, $2}
with CONST2 REG STACK
pat blt
leaving
cmi INT32
zlt $1
pat zle /* Branch if signed top >= 0 */
with TRISTATE_ALL+GPR STACK
gen gen
move %1, C0 cmplwi %2, {CONST, %1.val}
bc IFFALSE, GT, {LABEL, $1} bxx[1] {LABEL, $2}
with REG REG STACK
gen
cmplw %2, %1
bxx[1] {LABEL, $2}
pat ble /* Pop two unsigned ints, branch if... */
leaving pat cmu zeq $1==4 call cmu4zxx("beq", "beq")
cmi INT32 pat cmu zne $1==4 call cmu4zxx("bne", "bne")
zle $1 pat cmu zgt $1==4 call cmu4zxx("bgt", "blt")
pat cmu zge $1==4 call cmu4zxx("bge", "ble")
pat cmu zlt $1==4 call cmu4zxx("blt", "bgt")
pat cmu zle $1==4 call cmu4zxx("ble", "bge")
/* Compare and jump */
/* Comparisons */
/* Each comparison extracts the lt and gt bits from cr0.
* extlwi %a, %a, 2, 0
* puts lt in the sign bit, so lt yields a negative result,
* gt yields positive.
* rlwinm %a, %a, 1, 31, 0
* puts gt in the sign bit, to reverse the comparison.
*/
pat cmi $1==INT32 /* Signed tristate compare */ pat cmi $1==INT32 /* Signed tristate compare */
with CONST_ALL GPR with REG CONST2
yields {TRISTATE_RC_S, %2, %1.val} uses reusing %1, REG={COND_RC, %1, %2.val}
with GPR GPR gen rlwinm %a, %a, {CONST, 1}, {CONST, 31}, {CONST, 0}
yields {TRISTATE_RR_S, %2, %1} yields %a
with CONST2 REG
uses reusing %2, REG={COND_RC, %2, %1.val}
gen extlwi %a, %a, {CONST, 2}, {CONST, 0}
yields %a
with REG REG
uses reusing %1, REG={COND_RR, %2, %1}
gen extlwi %a, %a, {CONST, 2}, {CONST, 0}
yields %a
pat cmu $1==INT32 /* Unsigned tristate compare */ pat cmu $1==INT32 /* Unsigned tristate compare */
with CONST_ALL GPR with REG UCONST2
yields {TRISTATE_RC_U, %2, %1.val} uses reusing %1, REG={CONDL_RC, %1, %2.val}
with GPR GPR gen rlwinm %a, %a, {CONST, 1}, {CONST, 31}, {CONST, 0}
yields {TRISTATE_RR_U, %2, %1} yields %a
with UCONST2 REG
uses reusing %2, REG={CONDL_RC, %2, %1.val}
gen extlwi %a, %a, {CONST, 2}, {CONST, 0}
yields %a
with REG REG
uses reusing %1, REG={CONDL_RR, %2, %1}
gen extlwi %a, %a, {CONST, 2}, {CONST, 0}
yields %a
pat cmp /* Compare pointers */ pat cmp /* Compare pointers */
leaving leaving
@ -1895,7 +2091,7 @@ PATTERNS
kills ALL kills ALL
gen gen
mtspr CTR, %1 mtspr CTR, %1
bcctrl ALWAYS, {CONST, 0}, {CONST, 0} bctrl.
pat lfr $1==INT32 /* Load function result, word */ pat lfr $1==INT32 /* Load function result, word */
yields R3 yields R3
@ -2022,7 +2218,7 @@ PATTERNS
move {IND_RC_W, %a, 4}, SP move {IND_RC_W, %a, 4}, SP
move {IND_RC_W, %a, 0}, %a move {IND_RC_W, %a, 0}, %a
mtspr CTR, %a mtspr CTR, %a
bcctr ALWAYS, {CONST, 0}, {CONST, 0} bctr.
pat lor $1==0 /* Load FP */ pat lor $1==0 /* Load FP */
uses REG uses REG
@ -2075,12 +2271,11 @@ PATTERNS
pat lae rck $2==4 /* Range check */ pat lae rck $2==4 /* Range check */
with REG with REG
uses CR0
gen gen
cmpli %a, {CONST, 0}, %1, {CONST, rom($1, 1)} cmpwi %1, {CONST, rom($1, 1)}
bc IFTRUE, LT, {LABEL, ".trap_erange"} blt {LABEL, ".trap_erange"}
cmpli %a, {CONST, 0}, %1, {CONST, rom($1, 2)} cmpwi %1, {CONST, rom($1, 2)}
bc IFTRUE, GT, {LABEL, ".trap_erange"} bgt {LABEL, ".trap_erange"}
yields %1 yields %1
@ -2134,7 +2329,60 @@ PATTERNS
pat cmf $1==INT32 /* Compare single */ pat cmf $1==INT32 /* Compare single */
with FSREG FSREG with FSREG FSREG
yields {TRISTATE_FF, %2.1, %1.1} uses REG={COND_FS, %2, %1}
gen extlwi %a, %a, {CONST, 2}, {CONST, 0}
yields %a
pat cmf teq $1==4 /* Single second == top */
with FSREG FSREG
uses REG={COND_FS, %2, %1}
gen move {XEQ, %a}, %a
yields %a
pat cmf tne $1==4 /* Single second == top */
with FSREG FSREG
uses REG={COND_FS, %2, %1}
gen move {XNE, %a}, %a
yields %a
pat cmf tgt $1==4 /* Single second > top */
with FSREG FSREG
uses REG={COND_FS, %2, %1}
gen move {XGT, %a}, %a
yields %a
pat cmf tge $1==4 /* Single second >= top */
with FSREG FSREG
uses REG={COND_FS, %2, %1}
gen move {XGE, %a}, %a
yields %a
pat cmf tlt $1==4 /* Single second < top */
with FSREG FSREG
uses REG={COND_FS, %2, %1}
gen move {XLT, %a}, %a
yields %a
pat cmf tle $1==4 /* Single second <= top */
with FSREG FSREG
uses REG={COND_FS, %2, %1}
gen move {XLE, %a}, %a
yields %a
proc cmf4zxx example cmf zeq
with FREG FREG STACK
uses REG
gen
fcmpo CR0, %2, %1
bxx* {LABEL, $2}
/* Pop 2 singles, branch if... */
pat cmf zeq $1==4 call cmf4zxx("beq")
pat cmf zne $1==4 call cmf4zxx("bne")
pat cmf zgt $1==4 call cmf4zxx("bgt")
pat cmf zge $1==4 call cmf4zxx("bge")
pat cmf zlt $1==4 call cmf4zxx("blt")
pat cmf zle $1==4 call cmf4zxx("ble")
pat loc loc cff $1==INT32 && $2==INT64 /* Convert single to double */ pat loc loc cff $1==INT32 && $2==INT64 /* Convert single to double */
with FSREG with FSREG
@ -2208,7 +2456,60 @@ PATTERNS
pat cmf $1==INT64 /* Compare double */ pat cmf $1==INT64 /* Compare double */
with FREG FREG with FREG FREG
yields {TRISTATE_FF, %2, %1} uses REG={COND_FD, %2, %1}
gen extlwi %a, %a, {CONST, 2}, {CONST, 0}
yields %a
pat cmf teq $1==8 /* Double second == top */
with FREG FREG
uses REG={COND_FD, %2, %1}
gen move {XEQ, %a}, %a
yields %a
pat cmf tne $1==8 /* Single second == top */
with FREG FREG
uses REG={COND_FD, %2, %1}
gen move {XNE, %a}, %a
yields %a
pat cmf tgt $1==8 /* Double second > top */
with FREG FREG
uses REG={COND_FD, %2, %1}
gen move {XGT, %a}, %a
yields %a
pat cmf tge $1==8 /* Double second >= top */
with FREG FREG
uses REG={COND_FD, %2, %1}
gen move {XGE, %a}, %a
yields %a
pat cmf tlt $1==8 /* Double second < top */
with FREG FREG
uses REG={COND_FD, %2, %1}
gen move {XLT, %a}, %a
yields %a
pat cmf tle $1==8 /* Double second <= top */
with FREG FREG
uses REG={COND_FD, %2, %1}
gen move {XLE, %a}, %a
yields %a
proc cmf8zxx example cmf zeq
with FREG FREG STACK
uses REG
gen
fcmpo CR0, %2, %1
bxx* {LABEL, $2}
/* Pop 2 doubles, branch if... */
pat cmf zeq $1==8 call cmf8zxx("beq")
pat cmf zne $1==8 call cmf8zxx("bne")
pat cmf zgt $1==8 call cmf8zxx("bgt")
pat cmf zge $1==8 call cmf8zxx("bge")
pat cmf zlt $1==8 call cmf8zxx("blt")
pat cmf zle $1==8 call cmf8zxx("ble")
pat loc loc cff $1==INT64 && $2==INT32 /* Convert double to single */ pat loc loc cff $1==INT64 && $2==INT32 /* Convert double to single */
with FREG with FREG