Skip to content

Conversation

@farzonl
Copy link
Member

@farzonl farzonl commented Apr 10, 2025

fixes #135221

  • have powi use the same legalization path as pow
  • use CreateSIToFP to cast the int back to a float type
  • add tests for powi

fixes llvm#135221
- have powi use the same legalization path as pow
- use CreateSIToFP to cast the int back to a float type
- add tests for powi
@llvmbot
Copy link
Member

llvmbot commented Apr 10, 2025

@llvm/pr-subscribers-backend-directx

Author: Farzon Lotfi (farzonl)

Changes

fixes #135221

  • have powi use the same legalization path as pow
  • use CreateSIToFP to cast the int back to a float type
  • add tests for powi

Full diff: https://github.com/llvm/llvm-project/pull/135228.diff

2 Files Affected:

  • (modified) llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp (+9-4)
  • (modified) llvm/test/CodeGen/DirectX/pow.ll (+26)
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index e44d3b70eb657..84acf4d536d0c 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -49,6 +49,7 @@ static bool isIntrinsicExpansion(Function &F) {
   case Intrinsic::log:
   case Intrinsic::log10:
   case Intrinsic::pow:
+  case Intrinsic::powi:
   case Intrinsic::dx_all:
   case Intrinsic::dx_any:
   case Intrinsic::dx_cross:
@@ -251,7 +252,7 @@ static Value *expandExpIntrinsic(CallInst *Orig) {
 }
 
 static Value *expandAnyOrAllIntrinsic(CallInst *Orig,
-                                      Intrinsic::ID intrinsicId) {
+                                      Intrinsic::ID IntrinsicId) {
   Value *X = Orig->getOperand(0);
   IRBuilder<> Builder(Orig);
   Type *Ty = X->getType();
@@ -285,7 +286,7 @@ static Value *expandAnyOrAllIntrinsic(CallInst *Orig,
     Result = Builder.CreateExtractElement(Cond, (uint64_t)0);
     for (unsigned I = 1; I < XVec->getNumElements(); I++) {
       Value *Elt = Builder.CreateExtractElement(Cond, I);
-      Result = ApplyOp(intrinsicId, Result, Elt);
+      Result = ApplyOp(IntrinsicId, Result, Elt);
     }
   }
   return Result;
@@ -410,13 +411,16 @@ static Value *expandAtan2Intrinsic(CallInst *Orig) {
   return Result;
 }
 
-static Value *expandPowIntrinsic(CallInst *Orig) {
+static Value *expandPowIntrinsic(CallInst *Orig, Intrinsic::ID IntrinsicId) {
 
   Value *X = Orig->getOperand(0);
   Value *Y = Orig->getOperand(1);
   Type *Ty = X->getType();
   IRBuilder<> Builder(Orig);
 
+  if (IntrinsicId == Intrinsic::powi)
+    Y = Builder.CreateSIToFP(Y, Ty);
+
   auto *Log2Call =
       Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
   auto *Mul = Builder.CreateFMul(Log2Call, Y);
@@ -542,7 +546,8 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) {
     Result = expandLog10Intrinsic(Orig);
     break;
   case Intrinsic::pow:
-    Result = expandPowIntrinsic(Orig);
+  case Intrinsic::powi:
+    Result = expandPowIntrinsic(Orig, IntrinsicId);
     break;
   case Intrinsic::dx_all:
   case Intrinsic::dx_any:
diff --git a/llvm/test/CodeGen/DirectX/pow.ll b/llvm/test/CodeGen/DirectX/pow.ll
index 378649ec119d5..ebc0382415801 100644
--- a/llvm/test/CodeGen/DirectX/pow.ll
+++ b/llvm/test/CodeGen/DirectX/pow.ll
@@ -25,5 +25,31 @@ entry:
   ret half %elt.pow
 }
 
+define noundef float @powi_float(float noundef %a, i32 noundef %b) {
+entry:
+; CHECK: [[CAST:%.*]] = sitofp i32 %b to float
+; DOPCHECK: call float @dx.op.unary.f32(i32 23, float %a)
+; EXPCHECK: call float @llvm.log2.f32(float %a)
+; CHECK: fmul float %{{.*}}, [[CAST]]
+; DOPCHECK: call float @dx.op.unary.f32(i32 21, float %{{.*}})
+; EXPCHECK: call float @llvm.exp2.f32(float %{{.*}})
+  %elt.powi = call float @llvm.powi.f32.i32(float %a, i32 %b)
+  ret float %elt.powi
+}
+
+define noundef half @powi_half(half noundef %a, i32 noundef %b) {
+entry:
+; CHECK: [[CAST:%.*]] = sitofp i32 %b to half
+; DOPCHECK: call half @dx.op.unary.f16(i32 23, half %a)
+; EXPCHECK: call half @llvm.log2.f16(half %a)
+; CHECK: fmul half %{{.*}}, [[CAST]]
+; DOPCHECK: call half @dx.op.unary.f16(i32 21, half %{{.*}})
+; EXPCHECK: call half @llvm.exp2.f16(half %{{.*}})
+  %elt.powi = call half @llvm.powi.f16.i32(half %a, i32 %b)
+  ret half %elt.powi
+}
+
 declare half @llvm.pow.f16(half,half)
 declare float @llvm.pow.f32(float,float)
+declare half @llvm.powi.f16.i32(half,i32)
+declare float @llvm.powi.f32.i32(float,i32)

@farzonl farzonl merged commit 641de84 into llvm:main Apr 10, 2025
13 of 14 checks passed
@farzonl farzonl self-assigned this Apr 11, 2025
@damyanp damyanp moved this to Closed in HLSL Support Apr 25, 2025
@damyanp damyanp removed this from HLSL Support Jun 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DirectX] Pow optomized to Powi in frotend causes the backend to have an intrinsic it can't lower

4 participants