On Mon, 2012-09-03 at 19:37 +0900, Kaz Kojima wrote: > Oleg Endo <oleg.e...@t-online.de> wrote: > > In any case, I have no problem with changing the multi line comments > > to /* ... */. Just let me know. > > Other than that, the patch is OK.
I've committed the attached version of the patch as rev 190909. Cheers, Oleg
Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 190865) +++ gcc/config/sh/sh.md (working copy) @@ -881,10 +881,9 @@ if (TARGET_SHMEDIA) emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1], operands[2], operands[3])); - else if (TARGET_CBRANCHDI4) - expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1); else - sh_emit_compare_and_branch (operands, SImode); + expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1); + DONE; }) Index: gcc/config/sh/sh-protos.h =================================================================== --- gcc/config/sh/sh-protos.h (revision 190865) +++ gcc/config/sh/sh-protos.h (working copy) @@ -106,6 +106,9 @@ extern rtx sh_gen_truncate (enum machine_mode, rtx, int); extern bool sh_vector_mode_supported_p (enum machine_mode); extern bool sh_cfun_trap_exit_p (void); +extern void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&, + enum machine_mode mode = VOIDmode); + #endif /* RTX_CODE */ extern const char *output_jump_label_table (void); Index: gcc/config/sh/sh.c =================================================================== --- gcc/config/sh/sh.c (revision 190865) +++ gcc/config/sh/sh.c (working copy) @@ -21,6 +21,12 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +/* FIXME: This is a temporary hack, so that we can include <algorithm> + below. <algorithm> will try to include <cstdlib> which will reference + malloc & co, which are poisoned by "system.h". The proper solution is + to include <cstdlib> in "system.h" instead of <stdlib.h>. */ +#include <cstdlib> + #include "config.h" #include "system.h" #include "coretypes.h" @@ -56,6 +62,7 @@ #include "tm-constrs.h" #include "opts.h" +#include <algorithm> int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch; @@ -1791,65 +1798,124 @@ } } -enum rtx_code -prepare_cbranch_operands (rtx *operands, enum machine_mode mode, - enum rtx_code comparison) +/* Implement the CANONICALIZE_COMPARISON macro for the combine pass. + This function is also re-used to canonicalize comparisons in cbranch + pattern expanders. */ +void +sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1, + enum machine_mode mode) { - rtx op1; - rtx scratch = NULL_RTX; + /* When invoked from within the combine pass the mode is not specified, + so try to get it from one of the operands. */ + if (mode == VOIDmode) + mode = GET_MODE (op0); + if (mode == VOIDmode) + mode = GET_MODE (op1); - if (comparison == LAST_AND_UNUSED_RTX_CODE) - comparison = GET_CODE (operands[0]); - else - scratch = operands[4]; - if (CONST_INT_P (operands[1]) - && !CONST_INT_P (operands[2])) + // We need to have a mode to do something useful here. + if (mode == VOIDmode) + return; + + // Currently, we don't deal with floats here. + if (GET_MODE_CLASS (mode) == MODE_FLOAT) + return; + + // Make sure that the constant operand is the second operand. + if (CONST_INT_P (op0) && !CONST_INT_P (op1)) { - rtx tmp = operands[1]; + std::swap (op0, op1); + cmp = swap_condition (cmp); + } - operands[1] = operands[2]; - operands[2] = tmp; - comparison = swap_condition (comparison); - } - if (CONST_INT_P (operands[2])) + if (CONST_INT_P (op1)) { - HOST_WIDE_INT val = INTVAL (operands[2]); - if ((val == -1 || val == -0x81) - && (comparison == GT || comparison == LE)) + /* Try to adjust the constant operand in such a way that available + comparison insns can be utilized better and the constant can be + loaded with a 'mov #imm,Rm' insn. This avoids a load from the + constant pool. */ + const HOST_WIDE_INT val = INTVAL (op1); + + /* x > -1 --> x >= 0 + x > 0xFFFFFF7F --> x >= 0xFFFFFF80 + x <= -1 --> x < 0 + x <= 0xFFFFFF7F --> x < 0xFFFFFF80 */ + if ((val == -1 || val == -0x81) && (cmp == GT || cmp == LE)) { - comparison = (comparison == GT) ? GE : LT; - operands[2] = gen_int_mode (val + 1, mode); + cmp = cmp == GT ? GE : LT; + op1 = gen_int_mode (val + 1, mode); + } + + /* x >= 1 --> x > 0 + x >= 0x80 --> x > 0x7F + x < 1 --> x <= 0 + x < 0x80 --> x <= 0x7F */ + else if ((val == 1 || val == 0x80) && (cmp == GE || cmp == LT)) + { + cmp = cmp == GE ? GT : LE; + op1 = gen_int_mode (val - 1, mode); } - else if ((val == 1 || val == 0x80) - && (comparison == GE || comparison == LT)) + + /* unsigned x >= 1 --> x != 0 + unsigned x < 1 --> x == 0 */ + else if (val == 1 && (cmp == GEU || cmp == LTU)) { - comparison = (comparison == GE) ? GT : LE; - operands[2] = gen_int_mode (val - 1, mode); + cmp = cmp == GEU ? NE : EQ; + op1 = CONST0_RTX (mode); } - else if (val == 1 && (comparison == GEU || comparison == LTU)) + + /* unsigned x >= 0x80 --> unsigned x > 0x7F + unsigned x < 0x80 --> unsigned x < 0x7F */ + else if (val == 0x80 && (cmp == GEU || cmp == LTU)) { - comparison = (comparison == GEU) ? NE : EQ; - operands[2] = CONST0_RTX (mode); + cmp = cmp == GEU ? GTU : LEU; + op1 = gen_int_mode (val - 1, mode); } - else if (val == 0x80 && (comparison == GEU || comparison == LTU)) + + /* unsigned x > 0 --> x != 0 + unsigned x <= 0 --> x == 0 */ + else if (val == 0 && (cmp == GTU || cmp == LEU)) + cmp = cmp == GTU ? NE : EQ; + + /* unsigned x > 0x7FFFFFFF --> signed x < 0 + unsigned x <= 0x7FFFFFFF --> signed x >= 0 */ + else if (mode == SImode && (cmp == GTU || cmp == LEU) + && val == 0x7FFFFFFF) { - comparison = (comparison == GEU) ? GTU : LEU; - operands[2] = gen_int_mode (val - 1, mode); + cmp = cmp == GTU ? LT : GE; + op1 = const0_rtx; } - else if (val == 0 && (comparison == GTU || comparison == LEU)) - comparison = (comparison == GTU) ? NE : EQ; - else if (mode == SImode - && ((val == 0x7fffffff - && (comparison == GTU || comparison == LEU)) - || ((unsigned HOST_WIDE_INT) val - == (unsigned HOST_WIDE_INT) 0x7fffffff + 1 - && (comparison == GEU || comparison == LTU)))) + + /* unsigned x >= 0x80000000 --> signed x < 0 + unsigned x < 0x80000000 --> signed x >= 0 */ + else if (mode == SImode && (cmp == GEU || cmp == LTU) + && (unsigned HOST_WIDE_INT)val + == ((unsigned HOST_WIDE_INT)0x7FFFFFFF + 1)) { - comparison = (comparison == GTU || comparison == GEU) ? LT : GE; - operands[2] = CONST0_RTX (mode); + cmp = cmp == GEU ? LT : GE; + op1 = const0_rtx; } } - op1 = operands[1]; +} + +enum rtx_code +prepare_cbranch_operands (rtx *operands, enum machine_mode mode, + enum rtx_code comparison) +{ + /* The scratch reg is only available when this is invoked from within + the cbranchdi4_i splitter, through expand_cbranchdi4. */ + rtx scratch = NULL_RTX; + + if (comparison == LAST_AND_UNUSED_RTX_CODE) + comparison = GET_CODE (operands[0]); + else + scratch = operands[4]; + + sh_canonicalize_comparison (comparison, operands[1], operands[2], mode); + + /* Notice that this function is also invoked after reload by + the cbranchdi4_i pattern, through expand_cbranchdi4. */ + rtx op1 = operands[1]; + if (can_create_pseudo_p ()) operands[1] = force_reg (mode, op1); /* When we are handling DImode comparisons, we want to keep constants so @@ -1883,8 +1949,6 @@ expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability) { rtx (*branch_expander) (rtx, rtx) = gen_branch_true; - rtx jump; - comparison = prepare_cbranch_operands (operands, SImode, comparison); switch (comparison) { @@ -1896,10 +1960,9 @@ emit_insn (gen_rtx_SET (VOIDmode, get_t_reg_rtx (), gen_rtx_fmt_ee (comparison, SImode, operands[1], operands[2]))); - jump = emit_jump_insn (branch_expander (operands[3], get_t_reg_rtx ())); + rtx jump = emit_jump_insn (branch_expander (operands[3], get_t_reg_rtx ())); if (probability >= 0) add_reg_note (jump, REG_BR_PROB, GEN_INT (probability)); - } /* ??? How should we distribute probabilities when more than one branch @@ -1956,8 +2019,7 @@ lsw_taken = EQ; if (prob >= 0) { - /* If we had more precision, we'd use rev_prob - (rev_prob >> 32) . - */ + // If we had more precision, we'd use rev_prob - (rev_prob >> 32) . msw_skip_prob = rev_prob; if (REG_BR_PROB_BASE <= 65535) lsw_taken_prob = prob ? REG_BR_PROB_BASE : 0; Index: gcc/config/sh/sh.h =================================================================== --- gcc/config/sh/sh.h (revision 190865) +++ gcc/config/sh/sh.h (working copy) @@ -1946,6 +1946,10 @@ leave this zero for correct SH3 code. */ #define SHIFT_COUNT_TRUNCATED (! TARGET_SH3 && ! TARGET_SH2A) +/* CANONICALIZE_COMPARISON macro for the combine pass. */ +#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \ + sh_canonicalize_comparison ((CODE), (OP0), (OP1)) + /* All integers have the same format so truncation is easy. */ /* But SHmedia must sign-extend DImode when truncating to SImode. */ #define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) \