Add specialist rules for signed integer comparisons; much better code.
This commit is contained in:
parent
ec0891469f
commit
fe177bd688
|
@ -468,6 +468,95 @@ PATTERNS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Conditional branches */
|
||||||
|
|
||||||
|
/* Normally COMPARE returns a condition code (in a flags register) which the CJUMP
|
||||||
|
* instructions can then operate on. But MIPS doesn't have a flags register, and
|
||||||
|
* requires you to know what condition you're testing for when you do the comparison.
|
||||||
|
* mcg doesn't like this much and we have to list every combination individually.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Signed integer comparisons against zero */
|
||||||
|
|
||||||
|
CJUMPEQ(COMPARESI.I(left:(int)reg, zero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||||
|
when specific_constant(%zero, 0)
|
||||||
|
emit "beq %left, zero, $true"
|
||||||
|
emit "nop"
|
||||||
|
emit "b $false"
|
||||||
|
emit "nop"
|
||||||
|
cost 16;
|
||||||
|
|
||||||
|
CJUMPLT(COMPARESI.I(left:(int)reg, zero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||||
|
when specific_constant(%zero, 0)
|
||||||
|
emit "bltz %left, $true"
|
||||||
|
emit "nop"
|
||||||
|
emit "b $false"
|
||||||
|
emit "nop"
|
||||||
|
cost 16;
|
||||||
|
|
||||||
|
CJUMPLE(COMPARESI.I(left:(int)reg, zero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||||
|
when specific_constant(%zero, 0)
|
||||||
|
emit "blez %left, $true"
|
||||||
|
emit "nop"
|
||||||
|
emit "b $false"
|
||||||
|
emit "nop"
|
||||||
|
cost 16;
|
||||||
|
|
||||||
|
/* Signed integer comparisons against a constant */
|
||||||
|
|
||||||
|
CJUMPEQ(COMPARESI.I(left:(int)reg, value:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||||
|
emit "li at, $value"
|
||||||
|
emit "beq %left, at, $true"
|
||||||
|
emit "nop"
|
||||||
|
emit "b $false"
|
||||||
|
emit "nop"
|
||||||
|
cost 20;
|
||||||
|
|
||||||
|
CJUMPLT(COMPARESI.I(left:(int)reg, value:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||||
|
when signed_constant(%value, 16)
|
||||||
|
emit "slti at, %left, $value"
|
||||||
|
emit "bne at, zero, $true"
|
||||||
|
emit "nop"
|
||||||
|
emit "b $false"
|
||||||
|
emit "nop"
|
||||||
|
cost 20;
|
||||||
|
|
||||||
|
CJUMPLE(COMPARESI.I(left:(int)reg, value:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||||
|
when constant_within_inclusive_range(%value, -0x8000, 0x7ffe)
|
||||||
|
emit "slti at, %left, 1+$value"
|
||||||
|
emit "bne at, zero, $true"
|
||||||
|
emit "nop"
|
||||||
|
emit "b $false"
|
||||||
|
emit "nop"
|
||||||
|
cost 20;
|
||||||
|
|
||||||
|
/* Signed integer comparisons against a register */
|
||||||
|
|
||||||
|
CJUMPEQ(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||||
|
emit "beq %left, %right, $true"
|
||||||
|
emit "nop"
|
||||||
|
emit "b $false"
|
||||||
|
emit "nop"
|
||||||
|
cost 20;
|
||||||
|
|
||||||
|
CJUMPLT(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||||
|
emit "slt at, %left, %right"
|
||||||
|
emit "bne at, zero, $true"
|
||||||
|
emit "nop"
|
||||||
|
emit "b $false"
|
||||||
|
emit "nop"
|
||||||
|
cost 20;
|
||||||
|
|
||||||
|
CJUMPLE(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||||
|
emit "slt at, %right, %left"
|
||||||
|
emit "beq at, zero, $true"
|
||||||
|
emit "nop"
|
||||||
|
emit "b $false"
|
||||||
|
emit "nop"
|
||||||
|
cost 20;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Comparisons */
|
/* Comparisons */
|
||||||
|
|
||||||
/* The COMPARE nodes return tristate integer values; -1, 0 or 1. */
|
/* The COMPARE nodes return tristate integer values; -1, 0 or 1. */
|
||||||
|
|
|
@ -27,6 +27,14 @@ bool burm_predicate_specific_constant(struct burm_node* node, arith val)
|
||||||
return ir->u.ivalue == val;
|
return ir->u.ivalue == val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool burm_predicate_constant_within_inclusive_range(struct burm_node* node, arith min, arith max)
|
||||||
|
{
|
||||||
|
struct ir* ir = node->ir;
|
||||||
|
assert(ir->opcode == IR_CONST);
|
||||||
|
|
||||||
|
return (ir->u.ivalue >= min) && (ir->u.ivalue <= max);
|
||||||
|
}
|
||||||
|
|
||||||
/* vim: set sw=4 ts=4 expandtab : */
|
/* vim: set sw=4 ts=4 expandtab : */
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue