Commit 30c46053 by Michael Collison Committed by Michael Collison

aarch64.md (subv<GPI>4, [...]): New patterns.

2018-07-19  Michael Collison  <michael.collison@arm.com>
	    Richard Henderson <rth@redhat.com>

	* config/aarch64/aarch64.md (subv<GPI>4, usubv<GPI>4): New patterns.
	(subti): Handle op1 zero.
	(subvti4, usub4ti4): New.
	(*sub<GPI>3_compare1_imm): New.
	(sub<GPI>3_carryinCV): New.
	(*sub<GPI>3_carryinCV_z1_z2, *sub<GPI>3_carryinCV_z1): New.
	(*sub<GPI>3_carryinCV_z2, *sub<GPI>3_carryinCV): New.

2018-07-19  Michael Collison  <michael.collison@arm.com>
	    Richard Henderson <rth@redhat.com>

	* config/aarch64/aarch64.md: (addv<GPI>4, uaddv<GPI>4): New.
	(addti3): Create simpler code if low part is already known to be 0.
	(addvti4, uaddvti4): New.
	(*add<GPI>3_compareC_cconly_imm): New.
	(*add<GPI>3_compareC_cconly): New.
	(*add<GPI>3_compareC_imm): New.
	(*add<GPI>3_compareC): Rename from add<GPI>3_compare1; do not
	handle constants within this pattern..
	(*add<GPI>3_compareV_cconly_imm): New.
	(*add<GPI>3_compareV_cconly): New.
	(*add<GPI>3_compareV_imm): New.
	(add<GPI>3_compareV): New.
	(add<GPI>3_carryinC, add<GPI>3_carryinV): New.
	(*add<GPI>3_carryinC_zero, *add<GPI>3_carryinV_zero): New.
	(*add<GPI>3_carryinC, *add<GPI>3_carryinV): New.
	((*add<GPI>3_compareC_cconly_imm): Replace 'ne' operator
	with 'comparison' operator.
	(*add<GPI>3_compareV_cconly_imm): Ditto.
	(*add<GPI>3_compareV_cconly): Ditto.
	(*add<GPI>3_compareV_imm): Ditto.
	(add<GPI>3_compareV): Ditto.
	(add<mode>3_carryinC): Ditto.
	(*add<mode>3_carryinC_zero): Ditto.
	(*add<mode>3_carryinC): Ditto.
	(add<mode>3_carryinV): Ditto.
	(*add<mode>3_carryinV_zero): Ditto.
	(*add<mode>3_carryinV): Ditto.

2018-07-19  Michael Collison  <michael.collison@arm.com>
	    Richard Henderson <rth@redhat.com>

	* config/aarch64/aarch64-modes.def (CC_V): New.
	* config/aarch64/aarch64-protos.h
	(aarch64_addti_scratch_regs): Declare
	(aarch64_subvti_scratch_regs): Declare.
	(aarch64_expand_subvti): Declare.
	(aarch64_gen_unlikely_cbranch): Declare
	* config/aarch64/aarch64.c (aarch64_select_cc_mode): Test
	for signed overflow using CC_Vmode.
	(aarch64_get_condition_code_1): Handle CC_Vmode.
	(aarch64_gen_unlikely_cbranch): New function.
	(aarch64_addti_scratch_regs): New function.
	(aarch64_subvti_scratch_regs): New function.
	(aarch64_expand_subvti): New function.

2018-07-19  Michael Collison  <michael.collison@arm.com>
	    Richard Henderson <rth@redhat.com>

	* gcc.target/aarch64/builtin_sadd_128.c: New testcase.
	* gcc.target/aarch64/builtin_saddl.c: New testcase.
	* gcc.target/aarch64/builtin_saddll.c: New testcase.
	* gcc.target/aarch64/builtin_uadd_128.c: New testcase.
	* gcc.target/aarch64/builtin_uaddl.c: New testcase.
	* gcc.target/aarch64/builtin_uaddll.c: New testcase.
	* gcc.target/aarch64/builtin_ssub_128.c: New testcase.
	* gcc.target/aarch64/builtin_ssubl.c: New testcase.
	* gcc.target/aarch64/builtin_ssubll.c: New testcase.
	* gcc.target/aarch64/builtin_usub_128.c: New testcase.
	* gcc.target/aarch64/builtin_usubl.c: New testcase.
	* gcc.target/aarch64/builtin_usubll.c: New testcase.


Co-Authored-By: Richard Henderson <rth@redhat.com>

From-SVN: r262890
parent c01f9216
2018-07-19 Michael Collison <michael.collison@arm.com>
Richard Henderson <rth@redhat.com>
* config/aarch64/aarch64.md (subv<GPI>4, usubv<GPI>4): New patterns.
(subti): Handle op1 zero.
(subvti4, usub4ti4): New.
(*sub<GPI>3_compare1_imm): New.
(sub<GPI>3_carryinCV): New.
(*sub<GPI>3_carryinCV_z1_z2, *sub<GPI>3_carryinCV_z1): New.
(*sub<GPI>3_carryinCV_z2, *sub<GPI>3_carryinCV): New.
2018-07-19 Michael Collison <michael.collison@arm.com>
Richard Henderson <rth@redhat.com>
* config/aarch64/aarch64.md: (addv<GPI>4, uaddv<GPI>4): New.
(addti3): Create simpler code if low part is already known to be 0.
(addvti4, uaddvti4): New.
(*add<GPI>3_compareC_cconly_imm): New.
(*add<GPI>3_compareC_cconly): New.
(*add<GPI>3_compareC_imm): New.
(*add<GPI>3_compareC): Rename from add<GPI>3_compare1; do not
handle constants within this pattern..
(*add<GPI>3_compareV_cconly_imm): New.
(*add<GPI>3_compareV_cconly): New.
(*add<GPI>3_compareV_imm): New.
(add<GPI>3_compareV): New.
(add<GPI>3_carryinC, add<GPI>3_carryinV): New.
(*add<GPI>3_carryinC_zero, *add<GPI>3_carryinV_zero): New.
(*add<GPI>3_carryinC, *add<GPI>3_carryinV): New.
((*add<GPI>3_compareC_cconly_imm): Replace 'ne' operator
with 'comparison' operator.
(*add<GPI>3_compareV_cconly_imm): Ditto.
(*add<GPI>3_compareV_cconly): Ditto.
(*add<GPI>3_compareV_imm): Ditto.
(add<GPI>3_compareV): Ditto.
(add<mode>3_carryinC): Ditto.
(*add<mode>3_carryinC_zero): Ditto.
(*add<mode>3_carryinC): Ditto.
(add<mode>3_carryinV): Ditto.
(*add<mode>3_carryinV_zero): Ditto.
(*add<mode>3_carryinV): Ditto.
2018-07-19 Michael Collison <michael.collison@arm.com>
Richard Henderson <rth@redhat.com>
* config/aarch64/aarch64-modes.def (CC_V): New.
* config/aarch64/aarch64-protos.h
(aarch64_addti_scratch_regs): Declare
(aarch64_subvti_scratch_regs): Declare.
(aarch64_expand_subvti): Declare.
(aarch64_gen_unlikely_cbranch): Declare
* config/aarch64/aarch64.c (aarch64_select_cc_mode): Test
for signed overflow using CC_Vmode.
(aarch64_get_condition_code_1): Handle CC_Vmode.
(aarch64_gen_unlikely_cbranch): New function.
(aarch64_addti_scratch_regs): New function.
(aarch64_subvti_scratch_regs): New function.
(aarch64_expand_subvti): New function.
2018-07-19 Andre Vieira <andre.simoesdiasvieira@arm.com> 2018-07-19 Andre Vieira <andre.simoesdiasvieira@arm.com>
* config/aarch64/aarch64-option-extensions.def: New entry for profile * config/aarch64/aarch64-option-extensions.def: New entry for profile
......
...@@ -24,6 +24,7 @@ CC_MODE (CC_SWP); ...@@ -24,6 +24,7 @@ CC_MODE (CC_SWP);
CC_MODE (CC_NZ); /* Only N and Z bits of condition flags are valid. */ CC_MODE (CC_NZ); /* Only N and Z bits of condition flags are valid. */
CC_MODE (CC_Z); /* Only Z bit of condition flags is valid. */ CC_MODE (CC_Z); /* Only Z bit of condition flags is valid. */
CC_MODE (CC_C); /* Only C bit of condition flags is valid. */ CC_MODE (CC_C); /* Only C bit of condition flags is valid. */
CC_MODE (CC_V); /* Only V bit of condition flags is valid. */
/* Half-precision floating point for __fp16. */ /* Half-precision floating point for __fp16. */
FLOAT_MODE (HF, 2, 0); FLOAT_MODE (HF, 2, 0);
......
...@@ -472,6 +472,16 @@ void aarch64_relayout_simd_types (void); ...@@ -472,6 +472,16 @@ void aarch64_relayout_simd_types (void);
void aarch64_reset_previous_fndecl (void); void aarch64_reset_previous_fndecl (void);
bool aarch64_return_address_signing_enabled (void); bool aarch64_return_address_signing_enabled (void);
void aarch64_save_restore_target_globals (tree); void aarch64_save_restore_target_globals (tree);
void aarch64_addti_scratch_regs (rtx, rtx, rtx *,
rtx *, rtx *,
rtx *, rtx *,
rtx *);
void aarch64_subvti_scratch_regs (rtx, rtx, rtx *,
rtx *, rtx *,
rtx *, rtx *, rtx *);
void aarch64_expand_subvti (rtx, rtx, rtx,
rtx, rtx, rtx, rtx);
/* Initialize builtins for SIMD intrinsics. */ /* Initialize builtins for SIMD intrinsics. */
void init_aarch64_simd_builtins (void); void init_aarch64_simd_builtins (void);
...@@ -498,7 +508,8 @@ void aarch64_split_simd_move (rtx, rtx); ...@@ -498,7 +508,8 @@ void aarch64_split_simd_move (rtx, rtx);
bool aarch64_float_const_representable_p (rtx); bool aarch64_float_const_representable_p (rtx);
#if defined (RTX_CODE) #if defined (RTX_CODE)
void aarch64_gen_unlikely_cbranch (enum rtx_code, machine_mode cc_mode,
rtx label_ref);
bool aarch64_legitimate_address_p (machine_mode, rtx, bool, bool aarch64_legitimate_address_p (machine_mode, rtx, bool,
aarch64_addr_query_type = ADDR_QUERY_M); aarch64_addr_query_type = ADDR_QUERY_M);
machine_mode aarch64_select_cc_mode (RTX_CODE, rtx, rtx); machine_mode aarch64_select_cc_mode (RTX_CODE, rtx, rtx);
......
...@@ -6414,6 +6414,13 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y) ...@@ -6414,6 +6414,13 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
&& GET_CODE (y) == ZERO_EXTEND) && GET_CODE (y) == ZERO_EXTEND)
return CC_Cmode; return CC_Cmode;
/* A test for signed overflow. */
if ((GET_MODE (x) == DImode || GET_MODE (x) == TImode)
&& code == NE
&& GET_CODE (x) == PLUS
&& GET_CODE (y) == SIGN_EXTEND)
return CC_Vmode;
/* For everything else, return CCmode. */ /* For everything else, return CCmode. */
return CCmode; return CCmode;
} }
...@@ -6520,6 +6527,15 @@ aarch64_get_condition_code_1 (machine_mode mode, enum rtx_code comp_code) ...@@ -6520,6 +6527,15 @@ aarch64_get_condition_code_1 (machine_mode mode, enum rtx_code comp_code)
} }
break; break;
case E_CC_Vmode:
switch (comp_code)
{
case NE: return AARCH64_VS;
case EQ: return AARCH64_VC;
default: return -1;
}
break;
default: default:
return -1; return -1;
} }
...@@ -16274,6 +16290,131 @@ aarch64_split_dimode_const_store (rtx dst, rtx src) ...@@ -16274,6 +16290,131 @@ aarch64_split_dimode_const_store (rtx dst, rtx src)
return true; return true;
} }
/* Generate RTL for a conditional branch with rtx comparison CODE in
mode CC_MODE. The destination of the unlikely conditional branch
is LABEL_REF. */
void
aarch64_gen_unlikely_cbranch (enum rtx_code code, machine_mode cc_mode,
rtx label_ref)
{
rtx x;
x = gen_rtx_fmt_ee (code, VOIDmode,
gen_rtx_REG (cc_mode, CC_REGNUM),
const0_rtx);
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
gen_rtx_LABEL_REF (VOIDmode, label_ref),
pc_rtx);
aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x));
}
/* Generate DImode scratch registers for 128-bit (TImode) addition.
OP1 represents the TImode destination operand 1
OP2 represents the TImode destination operand 2
LOW_DEST represents the low half (DImode) of TImode operand 0
LOW_IN1 represents the low half (DImode) of TImode operand 1
LOW_IN2 represents the low half (DImode) of TImode operand 2
HIGH_DEST represents the high half (DImode) of TImode operand 0
HIGH_IN1 represents the high half (DImode) of TImode operand 1
HIGH_IN2 represents the high half (DImode) of TImode operand 2. */
void
aarch64_addti_scratch_regs (rtx op1, rtx op2, rtx *low_dest,
rtx *low_in1, rtx *low_in2,
rtx *high_dest, rtx *high_in1,
rtx *high_in2)
{
*low_dest = gen_reg_rtx (DImode);
*low_in1 = gen_lowpart (DImode, op1);
*low_in2 = simplify_gen_subreg (DImode, op2, TImode,
subreg_lowpart_offset (DImode, TImode));
*high_dest = gen_reg_rtx (DImode);
*high_in1 = gen_highpart (DImode, op1);
*high_in2 = simplify_gen_subreg (DImode, op2, TImode,
subreg_highpart_offset (DImode, TImode));
}
/* Generate DImode scratch registers for 128-bit (TImode) subtraction.
This function differs from 'arch64_addti_scratch_regs' in that
OP1 can be an immediate constant (zero). We must call
subreg_highpart_offset with DImode and TImode arguments, otherwise
VOIDmode will be used for the const_int which generates an internal
error from subreg_size_highpart_offset which does not expect a size of zero.
OP1 represents the TImode destination operand 1
OP2 represents the TImode destination operand 2
LOW_DEST represents the low half (DImode) of TImode operand 0
LOW_IN1 represents the low half (DImode) of TImode operand 1
LOW_IN2 represents the low half (DImode) of TImode operand 2
HIGH_DEST represents the high half (DImode) of TImode operand 0
HIGH_IN1 represents the high half (DImode) of TImode operand 1
HIGH_IN2 represents the high half (DImode) of TImode operand 2. */
void
aarch64_subvti_scratch_regs (rtx op1, rtx op2, rtx *low_dest,
rtx *low_in1, rtx *low_in2,
rtx *high_dest, rtx *high_in1,
rtx *high_in2)
{
*low_dest = gen_reg_rtx (DImode);
*low_in1 = simplify_gen_subreg (DImode, op1, TImode,
subreg_lowpart_offset (DImode, TImode));
*low_in2 = simplify_gen_subreg (DImode, op2, TImode,
subreg_lowpart_offset (DImode, TImode));
*high_dest = gen_reg_rtx (DImode);
*high_in1 = simplify_gen_subreg (DImode, op1, TImode,
subreg_highpart_offset (DImode, TImode));
*high_in2 = simplify_gen_subreg (DImode, op2, TImode,
subreg_highpart_offset (DImode, TImode));
}
/* Generate RTL for 128-bit (TImode) subtraction with overflow.
OP0 represents the TImode destination operand 0
LOW_DEST represents the low half (DImode) of TImode operand 0
LOW_IN1 represents the low half (DImode) of TImode operand 1
LOW_IN2 represents the low half (DImode) of TImode operand 2
HIGH_DEST represents the high half (DImode) of TImode operand 0
HIGH_IN1 represents the high half (DImode) of TImode operand 1
HIGH_IN2 represents the high half (DImode) of TImode operand 2. */
void
aarch64_expand_subvti (rtx op0, rtx low_dest, rtx low_in1,
rtx low_in2, rtx high_dest, rtx high_in1,
rtx high_in2)
{
if (low_in2 == const0_rtx)
{
low_dest = low_in1;
emit_insn (gen_subdi3_compare1 (high_dest, high_in1,
force_reg (DImode, high_in2)));
}
else
{
if (CONST_INT_P (low_in2))
{
low_in2 = force_reg (DImode, GEN_INT (-UINTVAL (low_in2)));
high_in2 = force_reg (DImode, high_in2);
emit_insn (gen_adddi3_compareC (low_dest, low_in1, low_in2));
}
else
emit_insn (gen_subdi3_compare1 (low_dest, low_in1, low_in2));
emit_insn (gen_subdi3_carryinCV (high_dest,
force_reg (DImode, high_in1),
high_in2));
}
emit_move_insn (gen_lowpart (DImode, op0), low_dest);
emit_move_insn (gen_highpart (DImode, op0), high_dest);
}
/* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */ /* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */
static unsigned HOST_WIDE_INT static unsigned HOST_WIDE_INT
......
2018-07-19 Michael Collison <michael.collison@arm.com>
Richard Henderson <rth@redhat.com>
* gcc.target/aarch64/builtin_sadd_128.c: New testcase.
* gcc.target/aarch64/builtin_saddl.c: New testcase.
* gcc.target/aarch64/builtin_saddll.c: New testcase.
* gcc.target/aarch64/builtin_uadd_128.c: New testcase.
* gcc.target/aarch64/builtin_uaddl.c: New testcase.
* gcc.target/aarch64/builtin_uaddll.c: New testcase.
* gcc.target/aarch64/builtin_ssub_128.c: New testcase.
* gcc.target/aarch64/builtin_ssubl.c: New testcase.
* gcc.target/aarch64/builtin_ssubll.c: New testcase.
* gcc.target/aarch64/builtin_usub_128.c: New testcase.
* gcc.target/aarch64/builtin_usubl.c: New testcase.
* gcc.target/aarch64/builtin_usubll.c: New testcase.
2018-07-19 Paolo Carlini <paolo.carlini@oracle.com> 2018-07-19 Paolo Carlini <paolo.carlini@oracle.com>
Revert fix for c++/59480 (and testsuite followup) Revert fix for c++/59480 (and testsuite followup)
......
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
__int128 overflow_add (__int128 x, __int128 y)
{
__int128 r;
int ovr = __builtin_add_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "adds" } } */
/* { dg-final { scan-assembler "adcs" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
long overflow_add (long x, long y)
{
long r;
int ovr = __builtin_saddl_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "adds" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
long long overflow_add (long long x, long long y)
{
long long r;
int ovr = __builtin_saddll_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "adds" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
__int128 overflow_sub (__int128 x, __int128 y)
{
__int128 r;
int ovr = __builtin_sub_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "subs" } } */
/* { dg-final { scan-assembler "sbcs" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
long overflow_sub (long x, long y)
{
long r;
int ovr = __builtin_ssubl_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "subs" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
long long overflow_sub (long long x, long long y)
{
long long r;
int ovr = __builtin_ssubll_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "subs" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
unsigned __int128 overflow_add (unsigned __int128 x, unsigned __int128 y)
{
unsigned __int128 r;
int ovr = __builtin_add_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "adds" } } */
/* { dg-final { scan-assembler "adcs" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
unsigned long overflow_add (unsigned long x, unsigned long y)
{
unsigned long r;
int ovr = __builtin_uaddl_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "adds" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
unsigned long long overflow_add (unsigned long long x, unsigned long long y)
{
unsigned long long r;
int ovr = __builtin_uaddll_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "adds" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
unsigned __int128 overflow_sub (unsigned __int128 x, unsigned __int128 y)
{
unsigned __int128 r;
int ovr = __builtin_sub_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "subs" } } */
/* { dg-final { scan-assembler "sbcs" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
unsigned long overflow_sub (unsigned long x, unsigned long y)
{
unsigned long r;
int ovr = __builtin_usubl_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "subs" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
extern void overflow_handler ();
unsigned long long overflow_sub (unsigned long long x, unsigned long long y)
{
unsigned long long r;
int ovr = __builtin_usubll_overflow (x, y, &r);
if (ovr)
overflow_handler ();
return r;
}
/* { dg-final { scan-assembler "subs" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment