diff options
author | Zhenqiang Chen <zhenqiang.chen@linaro.org> | 2014-11-17 06:24:36 +0000 |
---|---|---|
committer | Zhenqiang Chen <zqchen@gcc.gnu.org> | 2014-11-17 06:24:36 +0000 |
commit | 7dd236702d11b60084560f56b0c3ffdd197c885a (patch) | |
tree | 5679e70771214678ce82802aa8d5770aac9cfc58 /gcc | |
parent | cf67050334d42b14a7eecf2d503a96c1d284fbfd (diff) | |
download | gcc-7dd236702d11b60084560f56b0c3ffdd197c885a.zip gcc-7dd236702d11b60084560f56b0c3ffdd197c885a.tar.gz gcc-7dd236702d11b60084560f56b0c3ffdd197c885a.tar.bz2 |
aarch64.c (aarch64_code_to_ccmode, [...]): New functions.
2014-11-17 Zhenqiang Chen <zhenqiang.chen@linaro.org>
* 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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 138 |
2 files changed, 145 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6af355b..540784d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2014-11-17 Zhenqiang Chen <zhenqiang.chen@linaro.org> + * 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 <zhenqiang.chen@linaro.org> + * config/aarch64/aarch64-protos.h (aarch64_ccmp_mode_to_code): New. * aarch64.c (aarch64_nzcv_codes): New data. (aarch64_ccmp_mode_to_code): New. diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index b9383a4..3548335 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 |