[llvm] [AMDGPU] Avoid errors with 23-bit division and remainder. (PR #202753)

Jay Foad via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 11 07:21:56 PDT 2026


================
@@ -1055,32 +1056,39 @@ unsigned AMDGPUCodeGenPrepareImpl::getDivNumBits(BinaryOperator &I, Value *Num,
   return DivBits;
 }
 
-// The fractional part of a float is enough to accurately represent up to
-// a 24-bit signed integer.
-Value *AMDGPUCodeGenPrepareImpl::expandDivRem24(IRBuilder<> &Builder,
-                                                BinaryOperator &I, Value *Num,
-                                                Value *Den, bool IsDiv,
-                                                bool IsSigned) const {
-  unsigned DivBits = getDivNumBits(I, Num, Den, 24, IsSigned);
+Value *AMDGPUCodeGenPrepareImpl::expandDivRemToFloat(IRBuilder<> &Builder,
+                                                     BinaryOperator &I,
+                                                     Value *Num, Value *Den,
+                                                     bool IsDiv,
+                                                     bool IsSigned) const {
+  unsigned DivBits = getDivNumBits(I, Num, Den, 23, IsSigned);
 
-  // v_rcp_f32(float(X)) can have an error of 1 ulp.
-  // This can cause expandDivRem24Impl to sometimes calculate Y/X incorrectly
-  // when abs(Y)>0x800000.
-  // For example,
-  // (0xbf2758/0xbf2759) erroneously produces 1 instead of 0.
-  // (0xe3170d/0x000c32) erroneously produces 4767 instead of 4766.
-  //
-  // Note that for DivBits==24 && IsSigned, Y is in the range
-  // [-0x800000:0x7FFFFF]. abs(Y) is at most
-  // 0x800000 so it cannot hit this issue.
-  if (DivBits > (IsSigned ? 24 : 23))
+  if (DivBits > (IsSigned ? 23 : 22))
     return nullptr;
-  return expandDivRem24Impl(Builder, I, Num, Den, DivBits, IsDiv, IsSigned);
+  return expandDivRemToFloatImpl(Builder, I, Num, Den, DivBits, IsDiv,
+                                 IsSigned);
 }
 
-Value *AMDGPUCodeGenPrepareImpl::expandDivRem24Impl(
+Value *AMDGPUCodeGenPrepareImpl::expandDivRemToFloatImpl(
     IRBuilder<> &Builder, BinaryOperator &I, Value *Num, Value *Den,
     unsigned DivBits, bool IsDiv, bool IsSigned) const {
+
+  // v_rcp_f32(float(X)) can have an error of 1 ulp.
+  // This would cause incorrect calculation of Y/X if:
+  //   Y = (0x7FFFFF/X)*(X-0)-1
----------------
jayfoad wrote:

```suggestion
  //   Y = (0x7FFFFF/X)*X-1
```

https://github.com/llvm/llvm-project/pull/202753


More information about the llvm-commits mailing list