Add specialist rules for signed integer comparisons; much better code.
authorDavid Given <dg@cowlark.com>
Mon, 17 Sep 2018 21:53:18 +0000 (23:53 +0200)
committerDavid Given <dg@cowlark.com>
Mon, 17 Sep 2018 21:53:18 +0000 (23:53 +0200)
mach/mips/mcg/table
mach/proto/mcg/predicates.c

index 0703b15..de7b9b2 100644 (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 */
 
        /* The COMPARE nodes return tristate integer values; -1, 0 or 1. */
index 427a598..2142385 100644 (file)
@@ -27,6 +27,14 @@ bool burm_predicate_specific_constant(struct burm_node* node, arith 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 : */