On 6/29/2026 3:22 AM, Christopher Bazley wrote: > Ping! > > Please could someone take over this code review from Richard > Sandiford? He wrote (in a comment on the Forge) that he cannot > complete the review because he is now a co-author. The relevant > comment is > https://forge.sourceware.org/gcc/gcc-TEST/pulls/180#issuecomment-6403 I would have been comfortable with Richard S. self-approving, even under these conditions. His knowledge in this space far exceeds my own.
> > Thanks, > Chris > > On 19/06/2026 14:08, Christopher Bazley via Sourceware Forge wrote: >> From: Christopher Bazley <[email protected]> >> >> 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. Thanks for the detailed cover & comments. It really does help someone not intimately familiar with what's going on here. OK for the trunk. jeff
