Hi gcc-patches mailing list, Christopher Bazley via Sourceware Forge <[email protected]> has requested that the following forgejo pull request be published on the mailing list.
Created on: 2026-06-12 15:12:52+00:00 Latest update: 2026-06-12 15:22:03+00:00 Changes: 2 changed files, 71 additions, 0 deletions Head revision: chris.bazley/gcc ref pr125767 commit c692b66804a7441fd5cdcda4921035724fc8ec16 Base revision: gcc/gcc-TEST ref trunk commit c6133f911ea5ae4a4df59079c6299593fdec8afc r17-1517-gc6133f911ea5ae Merge base: c6133f911ea5ae4a4df59079c6299593fdec8afc Full diff url: https://forge.sourceware.org/gcc/gcc-TEST/pulls/176.diff Discussion: https://forge.sourceware.org/gcc/gcc-TEST/pulls/176 Requested Reviewers: PR middle-end/125767 When the magnitude of the divisor is known to be bigger than that of the dividend, the output quotient should be 1 when divisor and dividend have the same sign or -1 when they have opposite signs. Previously, can_div_away_from_zero_p was overreliant on can_div_trunc_p: if can_div_trunc_p returned a failure indication then can_div_away_from_zero_p did likewise. This matters because can_div_away_from_zero_p is commonly used to answer questions such as "How many registers does this value occupy?" If the register has a scalable vector type, then the answer should be 1 if the number of bits occupied by the value is known to be not greater than the minimum number of bits in the vector type (as well as if the number of bits occupied by the value is known to be smaller). Previously, can_div_away_from_zero_p had to be used with care to avoid wrongly concluding that a value of type V16QI would not fit in a register of type VNx16QI. That could cause selection of inefficient instruction sequences or even an ICE in cases where V8QI in VNx16QI behaved as expected. Because polynomial division truncated toward zero can fail to produce a constant quotient in cases where polynomial division rounded away from zero can produce a constant quotient, it is not sufficient for the implementation of can_div_away_from_zero_p to simply adjust the quotient produced by can_div_trunc_p. can_div_trunc_p requires |b * Q| <= |a| whereas can_div_away_from_zero_p requires |b * Q| >= |a|. The latter can be proven in cases where the former cannot. For example, when a = 16 + 0i and b = 16 + 16i, |b * Q| cannot be smaller than |a| unless Q = 0, which would violate a common requirement that |a - b * Q| < |b| (because |a| >= 16 and |b| >= 16). In contrast, |b * Q| is bigger than |a| if Q > 1 or i > 0. Crucially, it's impossible to know the value of i at compile time, so can_div_trunc_p must conservatively return false. Another way of looking at it is: Q = (16 + 0i) / (16 + 16i) = 16 / (16 + 16i) = 1 / (1 + i) which is not "some constant Q" that these functions must find in order to return true; however, we can be sure that whatever the unknowable value of 1 / (1 + i) is, it lies within the range 0 < Q <= 1. We cannot know whether that answer should be truncated to zero, but we can know that it should be rounded to one. gcc/ChangeLog: * poly-int.h (can_div_away_from_zero_p): Exit early if |a| <= |b| instead of calling can_div_trunc_p and returning false if it returned false. gcc/testsuite/ChangeLog: * gcc.dg/plugin/poly-int-tests.h: New test cases. Changed files: - M: gcc/poly-int.h - M: gcc/testsuite/gcc.dg/plugin/poly-int-tests.h Christopher Bazley (1): Handle divisor bigger than dividend in can_div_away_from_zero_p gcc/poly-int.h | 39 ++++++++++++++++++++ gcc/testsuite/gcc.dg/plugin/poly-int-tests.h | 32 ++++++++++++++++ 2 files changed, 71 insertions(+) -- 2.54.0
