[llvm] [DXIL] Implement log intrinsic Lowering (PR #86569)
Farzon Lotfi via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 25 12:57:47 PDT 2024
https://github.com/farzonl created https://github.com/llvm/llvm-project/pull/86569
Completes #86192
`DXIL.td` - add log2 to dxilop lowering
`DXILIntrinsicExpansion.cpp` - add log and log10 to log2 expansions
>From 824939e07bb60351bf52a887345c13799c9593c2 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Mon, 25 Mar 2024 15:48:55 -0400
Subject: [PATCH] [DXIL] Implement log intrinsic Lowering Completes #86192
`DXIL.td` - add log2 to dxilop lowering `DXILIntrinsicExpansion.cpp` - add
log and log10 to log2 expansions
---
llvm/lib/Target/DirectX/DXIL.td | 3 ++
.../Target/DirectX/DXILIntrinsicExpansion.cpp | 36 +++++++++++++++++--
llvm/test/CodeGen/DirectX/log.ll | 25 +++++++++++++
llvm/test/CodeGen/DirectX/log10.ll | 25 +++++++++++++
llvm/test/CodeGen/DirectX/log2.ll | 20 +++++++++++
llvm/test/CodeGen/DirectX/log2_error.ll | 10 ++++++
6 files changed, 117 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/DirectX/log.ll
create mode 100644 llvm/test/CodeGen/DirectX/log10.ll
create mode 100644 llvm/test/CodeGen/DirectX/log2.ll
create mode 100644 llvm/test/CodeGen/DirectX/log2_error.ll
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index f7e69ebae15b6c..fa26d82b9a2a42 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -274,6 +274,9 @@ def Frac : DXILOpMapping<22, unary, int_dx_frac,
"Returns a fraction from 0 to 1 that represents the "
"decimal part of the input.",
[llvm_halforfloat_ty, LLVMMatchType<0>]>;
+def Log2 : DXILOpMapping<23, unary, int_log2,
+ "Returns the base-2 logarithm of the specified value.",
+ [llvm_halforfloat_ty, LLVMMatchType<0>]>;
def RSqrt : DXILOpMapping<25, unary, int_dx_rsqrt,
"Returns the reciprocal of the square root of the specified value."
"rsqrt(x) = 1 / sqrt(x).",
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index b46564702c7aad..3cc375edabde92 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -35,6 +35,8 @@ static bool isIntrinsicExpansion(Function &F) {
switch (F.getIntrinsicID()) {
case Intrinsic::abs:
case Intrinsic::exp:
+ case Intrinsic::log:
+ case Intrinsic::log10:
case Intrinsic::dx_any:
case Intrinsic::dx_clamp:
case Intrinsic::dx_uclamp:
@@ -108,8 +110,8 @@ static bool expandExpIntrinsic(CallInst *Orig) {
Ty->isVectorTy() ? ConstantVector::getSplat(
ElementCount::getFixed(
cast<FixedVectorType>(Ty)->getNumElements()),
- ConstantFP::get(EltTy, numbers::log2e))
- : ConstantFP::get(EltTy, numbers::log2e);
+ ConstantFP::get(EltTy, numbers::log2ef))
+ : ConstantFP::get(EltTy, numbers::log2ef);
Value *NewX = Builder.CreateFMul(Log2eConst, X);
auto *Exp2Call =
Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {NewX}, nullptr, "dx.exp2");
@@ -169,6 +171,32 @@ static bool expandLerpIntrinsic(CallInst *Orig) {
return true;
}
+static bool expandLogIntrinsic(CallInst *Orig,
+ float LogConstVal = numbers::ln2f) {
+ Value *X = Orig->getOperand(0);
+ IRBuilder<> Builder(Orig->getParent());
+ Builder.SetInsertPoint(Orig);
+ Type *Ty = X->getType();
+ Type *EltTy = Ty->getScalarType();
+ Constant *Ln2Const =
+ Ty->isVectorTy() ? ConstantVector::getSplat(
+ ElementCount::getFixed(
+ cast<FixedVectorType>(Ty)->getNumElements()),
+ ConstantFP::get(EltTy, LogConstVal))
+ : ConstantFP::get(EltTy, LogConstVal);
+ auto *Log2Call =
+ Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
+ Log2Call->setTailCall(Orig->isTailCall());
+ Log2Call->setAttributes(Orig->getAttributes());
+ auto *Result = Builder.CreateFMul(Ln2Const, Log2Call);
+ Orig->replaceAllUsesWith(Result);
+ Orig->eraseFromParent();
+ return true;
+}
+static bool expandLog10Intrinsic(CallInst *Orig) {
+ return expandLogIntrinsic(Orig, numbers::ln2f / numbers::ln10f);
+}
+
static bool expandRcpIntrinsic(CallInst *Orig) {
Value *X = Orig->getOperand(0);
IRBuilder<> Builder(Orig->getParent());
@@ -238,6 +266,10 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) {
return expandAbs(Orig);
case Intrinsic::exp:
return expandExpIntrinsic(Orig);
+ case Intrinsic::log:
+ return expandLogIntrinsic(Orig);
+ case Intrinsic::log10:
+ return expandLog10Intrinsic(Orig);
case Intrinsic::dx_any:
return expandAnyIntrinsic(Orig);
case Intrinsic::dx_uclamp:
diff --git a/llvm/test/CodeGen/DirectX/log.ll b/llvm/test/CodeGen/DirectX/log.ll
new file mode 100644
index 00000000000000..172c3bfed3b770
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/log.ll
@@ -0,0 +1,25 @@
+; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
+; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
+
+; Make sure dxil operation function calls for log are generated.
+
+define noundef float @log_float(float noundef %a) #0 {
+entry:
+; DOPCHECK: call float @dx.op.unary.f32(i32 23, float %{{.*}})
+; EXPCHECK: call float @llvm.log2.f32(float %a)
+; CHECK: fmul float 0x3FE62E4300000000, %{{.*}}
+ %elt.log = call float @llvm.log.f32(float %a)
+ ret float %elt.log
+}
+
+define noundef half @log_half(half noundef %a) #0 {
+entry:
+; DOPCHECK: call half @dx.op.unary.f16(i32 23, half %{{.*}})
+; EXPCHECK: call half @llvm.log2.f16(half %a)
+; CHECK: fmul half 0xH398C, %{{.*}}
+ %elt.log = call half @llvm.log.f16(half %a)
+ ret half %elt.log
+}
+
+declare half @llvm.log.f16(half)
+declare float @llvm.log.f32(float)
diff --git a/llvm/test/CodeGen/DirectX/log10.ll b/llvm/test/CodeGen/DirectX/log10.ll
new file mode 100644
index 00000000000000..d4f827a0d1af83
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/log10.ll
@@ -0,0 +1,25 @@
+; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
+; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
+
+; Make sure dxil operation function calls for log10 are generated.
+
+define noundef float @log10_float(float noundef %a) #0 {
+entry:
+; DOPCHECK: call float @dx.op.unary.f32(i32 23, float %{{.*}})
+; EXPCHECK: call float @llvm.log2.f32(float %a)
+; CHECK: fmul float 0x3FD3441340000000, %{{.*}}
+ %elt.log10 = call float @llvm.log10.f32(float %a)
+ ret float %elt.log10
+}
+
+define noundef half @log10_half(half noundef %a) #0 {
+entry:
+; DOPCHECK: call half @dx.op.unary.f16(i32 23, half %{{.*}})
+; EXPCHECK: call half @llvm.log2.f16(half %a)
+; CHECK: fmul half 0xH34D1, %{{.*}}
+ %elt.log10 = call half @llvm.log10.f16(half %a)
+ ret half %elt.log10
+}
+
+declare half @llvm.log10.f16(half)
+declare float @llvm.log10.f32(float)
diff --git a/llvm/test/CodeGen/DirectX/log2.ll b/llvm/test/CodeGen/DirectX/log2.ll
new file mode 100644
index 00000000000000..2164d4db9396d1
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/log2.ll
@@ -0,0 +1,20 @@
+; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+
+; Make sure dxil operation function calls for log2 are generated for float and half.
+
+define noundef float @log2_float(float noundef %a) #0 {
+entry:
+; CHECK:call float @dx.op.unary.f32(i32 23, float %{{.*}})
+ %elt.log2 = call float @llvm.log2.f32(float %a)
+ ret float %elt.log2
+}
+
+define noundef half @log2_half(half noundef %a) #0 {
+entry:
+; CHECK:call half @dx.op.unary.f16(i32 23, half %{{.*}})
+ %elt.log2 = call half @llvm.log2.f16(half %a)
+ ret half %elt.log2
+}
+
+declare half @llvm.log2.f16(half)
+declare float @llvm.log2.f32(float)
diff --git a/llvm/test/CodeGen/DirectX/log2_error.ll b/llvm/test/CodeGen/DirectX/log2_error.ll
new file mode 100644
index 00000000000000..a26f6e8c3117f5
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/log2_error.ll
@@ -0,0 +1,10 @@
+; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+
+; DXIL operation log2 does not support double overload type
+; CHECK: LLVM ERROR: Invalid Overload Type
+
+define noundef double @log2_double(double noundef %a) {
+entry:
+ %elt.log2 = call double @llvm.log2.f64(double %a)
+ ret double %elt.log2
+}
More information about the llvm-commits
mailing list