aboutsummaryrefslogtreecommitdiff
path: root/gcc/expmed.h
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2020-12-02 11:33:33 +0100
committerJakub Jelinek <jakub@redhat.com>2020-12-02 11:40:47 +0100
commite34153b0e230bc0a8b9a3f5db1d46a67cbb51788 (patch)
treee2df47d8da8ea8bae2100da5aed849fd05274c00 /gcc/expmed.h
parent037fe26ee1ac18581bf0ad646d48591c97d10bd3 (diff)
downloadgcc-e34153b0e230bc0a8b9a3f5db1d46a67cbb51788.zip
gcc-e34153b0e230bc0a8b9a3f5db1d46a67cbb51788.tar.gz
gcc-e34153b0e230bc0a8b9a3f5db1d46a67cbb51788.tar.bz2
expansion: Fix up infinite recursion due to double-word modulo optimization
Jeff has reported that my earlier patch broke rl78-elf, e.g. with unsigned short foo (unsigned short x) { return x % 7; } when compiled with -O2 -mg14. The problem is that rl78 is a BITS_PER_WORD == 8 target which doesn't have 8-bit modulo or divmod optab, but has instead 16-bit divmod, so my patch attempted to optimize it, then called expand_divmod to do 8-bit modulo and that in turn tried to do 16-bit modulo again. The following patch fixes it in two ways. One is to not perform the optimization when we have {u,s}divmod_optab handler for the double-word mode, in that case it is IMHO better to just do whatever we used to do before. This alone should fix the infinite recursion. But I'd be afraid some other target might have similar problem and might not have a divmod pattern, but only say a library call. So the patch also introduces a methods argument to expand_divmod such that normally we allow everything that was allowed before (using libcalls and widening), but when called from these expand_doubleword*mod routines we restrict it to no widening and no libcalls. 2020-12-02 Jakub Jelinek <jakub@redhat.com> * expmed.h (expand_divmod): Only declare if GCC_OPTABS_H is defined. Add enum optabs_method argument defaulted to OPTAB_LIB_WIDEN. * expmed.c: Include expmed.h after optabs.h. (expand_divmod): Add methods argument, if it is not OPTAB_{,LIB_}WIDEN, don't choose a wider mode, and pass it to other calls instead of hardcoded OPTAB_LIB_WIDEN. Avoid emitting libcalls if not OPTAB_LIB or OPTAB_LIB_WIDEN. * optabs.c: Include expmed.h after optabs.h. (expand_doubleword_mod, expand_doubleword_divmod): Pass OPTAB_DIRECT as last argument to expand_divmod. (expand_binop): Punt if {s,u}divmod_optab has handler for double-word int_mode. * expr.c: Include expmed.h after optabs.h. * explow.c: Include expmed.h after optabs.h.
Diffstat (limited to 'gcc/expmed.h')
-rw-r--r--gcc/expmed.h4
1 files changed, 3 insertions, 1 deletions
diff --git a/gcc/expmed.h b/gcc/expmed.h
index b719b94..6a9bab7 100644
--- a/gcc/expmed.h
+++ b/gcc/expmed.h
@@ -716,8 +716,10 @@ extern rtx expand_variable_shift (enum tree_code, machine_mode,
rtx, tree, rtx, int);
extern rtx expand_shift (enum tree_code, machine_mode, rtx, poly_int64, rtx,
int);
+#ifdef GCC_OPTABS_H
extern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx,
- rtx, int);
+ rtx, int, enum optab_methods = OPTAB_LIB_WIDEN);
+#endif
#endif
extern void store_bit_field (rtx, poly_uint64, poly_uint64,