Add specialist rules for signed integer comparisons; much better code.

This commit is contained in:
David Given 2018-09-17 23:53:18 +02:00
parent ec0891469f
commit fe177bd688
2 changed files with 97 additions and 0 deletions

View file

@ -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. */

View file

@ -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 : */