From: Zhenqiang Chen Date: Mon, 17 Nov 2014 06:24:36 +0000 (+0000) Subject: aarch64.c (aarch64_code_to_ccmode, [...]): New functions. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7dd236702d11b60084560f56b0c3ffdd197c885a;p=gcc.git aarch64.c (aarch64_code_to_ccmode, [...]): New functions. 2014-11-17 Zhenqiang Chen * config/aarch64/aarch64.c (aarch64_code_to_ccmode, aarch64_convert_mode, aarch64_gen_ccmp_first, aarch64_gen_ccmp_next): New functions. (TARGET_GEN_CCMP_FIRST, TARGET_GEN_CCMP_NEXT): Define. From-SVN: r217645 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6af355b2e76..540784deb6c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2014-11-17 Zhenqiang Chen + + * config/aarch64/aarch64.c (aarch64_code_to_ccmode, + aarch64_convert_mode, aarch64_gen_ccmp_first, + aarch64_gen_ccmp_next): New functions. + (TARGET_GEN_CCMP_FIRST, TARGET_GEN_CCMP_NEXT): Define. + 2014-11-17 Zhenqiang Chen * config/aarch64/aarch64-protos.h (aarch64_ccmp_mode_to_code): New. diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index b9383a4e110..3548335385e 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -10211,6 +10211,144 @@ aarch64_use_by_pieces_infrastructure_p (unsigned int size, return default_use_by_pieces_infrastructure_p (size, align, op, speed_p); } +static enum machine_mode +aarch64_code_to_ccmode (enum rtx_code code) +{ + switch (code) + { + case NE: + return CC_DNEmode; + + case EQ: + return CC_DEQmode; + + case LE: + return CC_DLEmode; + + case LT: + return CC_DLTmode; + + case GE: + return CC_DGEmode; + + case GT: + return CC_DGTmode; + + case LEU: + return CC_DLEUmode; + + case LTU: + return CC_DLTUmode; + + case GEU: + return CC_DGEUmode; + + case GTU: + return CC_DGTUmode; + + default: + return CCmode; + } +} + +static bool +aarch64_convert_mode (rtx* op0, rtx* op1, int unsignedp) +{ + enum machine_mode mode; + + mode = GET_MODE (*op0); + if (mode == VOIDmode) + mode = GET_MODE (*op1); + + if (mode == QImode || mode == HImode) + { + *op0 = convert_modes (SImode, mode, *op0, unsignedp); + *op1 = convert_modes (SImode, mode, *op1, unsignedp); + } + else if (mode != SImode && mode != DImode) + return false; + + return true; +} + +static rtx +aarch64_gen_ccmp_first (int code, rtx op0, rtx op1) +{ + enum machine_mode mode; + rtx cmp, target; + int unsignedp = code == LTU || code == LEU || code == GTU || code == GEU; + + mode = GET_MODE (op0); + if (mode == VOIDmode) + mode = GET_MODE (op1); + + if (mode == VOIDmode) + return NULL_RTX; + + if (!register_operand (op0, GET_MODE (op0))) + op0 = force_reg (mode, op0); + if (!aarch64_plus_operand (op1, GET_MODE (op1))) + op1 = force_reg (mode, op1); + + if (!aarch64_convert_mode (&op0, &op1, unsignedp)) + return NULL_RTX; + + mode = aarch64_code_to_ccmode ((enum rtx_code) code); + if (mode == CCmode) + return NULL_RTX; + + cmp = gen_rtx_fmt_ee (COMPARE, CCmode, op0, op1); + target = gen_rtx_REG (mode, CC_REGNUM); + emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), cmp)); + return target; +} + +static rtx +aarch64_gen_ccmp_next (rtx prev, int cmp_code, rtx op0, rtx op1, int bit_code) +{ + rtx cmp0, cmp1, target, bit_op; + enum machine_mode mode; + int unsignedp = cmp_code == LTU || cmp_code == LEU + || cmp_code == GTU || cmp_code == GEU; + + mode = GET_MODE (op0); + if (mode == VOIDmode) + mode = GET_MODE (op1); + if (mode == VOIDmode) + return NULL_RTX; + + /* Give up if the operand is illegal since force_reg will introduce + additional overhead. */ + if (!register_operand (op0, GET_MODE (op0)) + || !aarch64_ccmp_operand (op1, GET_MODE (op1))) + return NULL_RTX; + + if (!aarch64_convert_mode (&op0, &op1, unsignedp)) + return NULL_RTX; + + mode = aarch64_code_to_ccmode ((enum rtx_code) cmp_code); + if (mode == CCmode) + return NULL_RTX; + + cmp1 = gen_rtx_fmt_ee ((enum rtx_code) cmp_code, SImode, op0, op1); + cmp0 = gen_rtx_fmt_ee (NE, SImode, prev, const0_rtx); + + bit_op = gen_rtx_fmt_ee ((enum rtx_code) bit_code, SImode, cmp0, cmp1); + + /* Generate insn to match ccmp_and/ccmp_ior. */ + target = gen_rtx_REG (mode, CC_REGNUM); + emit_insn (gen_rtx_SET (VOIDmode, target, + gen_rtx_fmt_ee (COMPARE, mode, + bit_op, const0_rtx))); + return target; +} + +#undef TARGET_GEN_CCMP_FIRST +#define TARGET_GEN_CCMP_FIRST aarch64_gen_ccmp_first + +#undef TARGET_GEN_CCMP_NEXT +#define TARGET_GEN_CCMP_NEXT aarch64_gen_ccmp_next + #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST aarch64_address_cost