From fe177bd68880db90b29c227507cf3f3602442cf3 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Sep 2018 23:53:18 +0200 Subject: [PATCH] Add specialist rules for signed integer comparisons; much better code. --- mach/mips/mcg/table | 89 +++++++++++++++++++++++++++++++++++++ mach/proto/mcg/predicates.c | 8 ++++ 2 files changed, 97 insertions(+) diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table index 0703b156f..de7b9b248 100644 --- a/mach/mips/mcg/table +++ b/mach/mips/mcg/table @@ -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. */ diff --git a/mach/proto/mcg/predicates.c b/mach/proto/mcg/predicates.c index 427a59836..21423852e 100644 --- a/mach/proto/mcg/predicates.c +++ b/mach/proto/mcg/predicates.c @@ -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 : */