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
This commit is contained in:
Zhenqiang Chen 2014-11-17 06:24:36 +00:00 committed by Zhenqiang Chen
parent cf67050334
commit 7dd236702d
2 changed files with 145 additions and 0 deletions

View File

@ -1,3 +1,10 @@
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.

View File

@ -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