loongarch: use -mno-check-zero-division as the default for optimized code

Integer division by zero is undefined behavior anyway, and there are
already many platforms where neither the GCC port and the hardware do
anything to trap on division by zero.  So any portable program shall not
rely on SIGFPE on division by zero, in both theory and practice.  As the
result, there is no real reason to cost two additional instructions just
for the trap on division by zero with a new ISA.

One remaining reason to trap on division by zero may be debugging,
especially while -fsanitize=integer-divide-by-zero is not implemented
for LoongArch yet.  To make debugging easier, keep -mcheck-zero-division
as the default for -O0 and -Og, but use -mno-check-zero-division as the
default for all other optimization levels.

Co-authored-by: Lulu Cheng <chenglulu@loongson.cn>

gcc/ChangeLog:

	* config/loongarch/loongarch.cc (loongarch_check_zero_div_p):
	New static function.
	(loongarch_idiv_insns): Use loongarch_check_zero_div_p instead
	of TARGET_CHECK_ZERO_DIV.
	(loongarch_output_division): Likewise.
	* common/config/loongarch/loongarch-common.cc
	(TARGET_DEFAULT_TARGET_FLAGS): Remove unneeded hook.
	* doc/invoke.texi: Update to match the new behavior.

gcc/testsuite/ChangeLog:

	* gcc.c-torture/execute/20101011-1.c (dg-additional-options):
	add -mcheck-zero-division for LoongArch targets.
This commit is contained in:
Xi Ruoyao 2022-07-02 16:16:44 +08:00
parent b5c3dd3df3
commit f150dc1bd1
No known key found for this signature in database
GPG Key ID: ACAAD20E19E710E3
4 changed files with 18 additions and 7 deletions

View File

@ -37,7 +37,4 @@ static const struct default_options loongarch_option_optimization_table[] =
{ OPT_LEVELS_NONE, 0, NULL, 0 }
};
#undef TARGET_DEFAULT_TARGET_FLAGS
#define TARGET_DEFAULT_TARGET_FLAGS MASK_CHECK_ZERO_DIV
struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;

View File

@ -2102,6 +2102,19 @@ loongarch_load_store_insns (rtx mem, rtx_insn *insn)
return loongarch_address_insns (XEXP (mem, 0), mode, might_split_p);
}
/* Return true if we need to trap on division by zero. */
static bool
loongarch_check_zero_div_p (void)
{
/* if -m[no-]check-zero-division is given explicitly. */
if (target_flags_explicit & MASK_CHECK_ZERO_DIV)
return TARGET_CHECK_ZERO_DIV;
/* if not, don't trap for optimized code except -Og. */
return !optimize || optimize_debug;
}
/* Return the number of instructions needed for an integer division. */
int
@ -2110,7 +2123,7 @@ loongarch_idiv_insns (machine_mode mode ATTRIBUTE_UNUSED)
int count;
count = 1;
if (TARGET_CHECK_ZERO_DIV)
if (loongarch_check_zero_div_p ())
count += 2;
return count;
@ -4051,7 +4064,6 @@ loongarch_do_optimize_block_move_p (void)
return !optimize_size;
}
/* Expand a QI or HI mode atomic memory operation.
GENERATOR contains a pointer to the gen_* function that generates
@ -5263,7 +5275,7 @@ loongarch_output_division (const char *division, rtx *operands)
const char *s;
s = division;
if (TARGET_CHECK_ZERO_DIV)
if (loongarch_check_zero_div_p ())
{
output_asm_insn (s, operands);
s = "bne\t%2,%.,1f\n\tbreak\t7\n1:";

View File

@ -24806,7 +24806,8 @@ Set the cost of branches to roughly @var{n} instructions.
@itemx -mno-check-zero-divison
@opindex -mcheck-zero-division
Trap (do not trap) on integer division by zero. The default is
@option{-mcheck-zero-division}.
@option{-mcheck-zero-division} for @option{-O0} or @option{-Og}, and
@option{-mno-check-zero-division} for other optimization levels.
@item -mcond-move-int
@itemx -mno-cond-move-int

View File

@ -1,6 +1,7 @@
/* { dg-options "-fnon-call-exceptions" } */
/* With -fnon-call-exceptions 0 / 0 should not be eliminated. */
/* { dg-additional-options "-DSIGNAL_SUPPRESS" { target { ! signal } } } */
/* { dg-additional-options "-mcheck-zero-division" { target { loongarch*-*-* } } } */
#ifdef SIGNAL_SUPPRESS
# define DO_TEST 0