Hi, The patches implements the two hooks for AARCH64 to generate ccmp instructions.
Bootstrap and no make check regression on qemu. OK for trunk? Thanks! -Zhenqiang ChangeLog: 2014-06-23 Zhenqiang Chen <zhenqiang.c...@linaro.org> * config/aarch64/aarch64.c (aarch64_code_to_ccmode): New function. (aarch64_convert_mode, aarch64_convert_mode): New functions. (aarch64_gen_ccmp_first, aarch64_gen_ccmp_next): New functions. (TARGET_GEN_CCMP_FIRST, TARGET_GEN_CCMP_NEXT): Define the two hooks. diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 4e8d55b..6f08e38 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -9601,6 +9601,137 @@ aarch64_uimm5 (HOST_WIDE_INT val) return (val & (HOST_WIDE_INT) 0x1f) == val; } +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; + + /* Make op0 and op1 are legal operands for cmp. */ + 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, VOIDmode, + 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