[llvm] AMDGPU: Libcall expand fast pow/powr/pown/rootn for float case (PR #180553)

Steffen Larsen via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 9 23:00:01 PST 2026


================
@@ -1170,6 +1198,260 @@ bool AMDGPULibCalls::fold_rootn(FPMathOperator *FPOp, IRBuilder<> &B,
   return false;
 }
 
+// is_integer(y) => trunc(y) == y
+static Value *emitIsInteger(IRBuilder<> &B, Value *Y) {
+  Value *TruncY = B.CreateUnaryIntrinsic(Intrinsic::trunc, Y);
+  return B.CreateFCmpOEQ(TruncY, Y);
+}
+
+static Value *emitIsEvenInteger(IRBuilder<> &B, Value *Y) {
+  // Even integers are still integers after division by 2.
+  auto *HalfY = B.CreateFMul(Y, ConstantFP::get(Y->getType(), 0.5));
+  return emitIsInteger(B, HalfY);
+}
+
+// is_odd_integer(y) => is_integer(y) && !is_even_integer(y)
+static Value *emitIsOddInteger(IRBuilder<> &B, Value *Y) {
+  Value *IsIntY = emitIsInteger(B, Y);
+  Value *IsEvenY = emitIsEvenInteger(B, Y);
+  Value *NotEvenY = B.CreateNot(IsEvenY);
+  return B.CreateAnd(IsIntY, NotEvenY);
+}
----------------
steffenlarsen wrote:

Since `emitIsInteger` is doing a `trunc` already, we could avoid the fmul to begin with by doing `!((iN)trunc(y) & 1)` to check whether the value is even. Note that it recalculates the `trunc` operation. If you can think of a way to inline the functions and consolidate the truncations, feel free to do so, but the result should be integer for the result before doing the bitwise and.

```suggestion
// is_odd_integer(y) => is_integer(y) && !((iN)trunc(y) & 1)
static Value *emitIsOddInteger(IRBuilder<> &B, Value *Y) {
  LLVMContext &C = B.getContext();

  Value *IsIntY = emitIsInteger(B, Y);

  auto TruncIntTy = IntegerType::get(C, Y->getType()->getPrimitiveSizeInBits());
  Value *TruncY = B.CreateTrunc(TruncIntTy, Y);
  Value *IsEvenY = B.CreateAnd(TruncY, ConstantInt::get(TruncIntTy, 1));
  Value *NotEvenY = B.CreateNot(IsEvenY);

  return B.CreateAnd(IsIntY, NotEvenY);
}
```

If you're confident that the compiler is smart enough to transform the `is_integer(y * 0.5)` into something better, feel free to disregard this.

_NOTE:_ The suggestion inlines the `is_even_integer` implementation. I did this as I felt it would be misleading to call it "IsEvenInteger" as it no longer checks whether the floating point value is an integer to begin with.

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


More information about the llvm-commits mailing list