Skip to content

Commit 8665e4e

Browse files
committed
[DXIL] Implement log intrinsic Lowering
Completes #86192 `DXIL.td` - add log2 to dxilop lowering `DXILIntrinsicExpansion.cpp` - add log and log10 to log2 expansions
1 parent cc3b6f9 commit 8665e4e

File tree

6 files changed

+117
-2
lines changed

6 files changed

+117
-2
lines changed

llvm/lib/Target/DirectX/DXIL.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ def Frac : DXILOpMapping<22, unary, int_dx_frac,
274274
"Returns a fraction from 0 to 1 that represents the "
275275
"decimal part of the input.",
276276
[llvm_halforfloat_ty, LLVMMatchType<0>]>;
277+
def Log2 : DXILOpMapping<23, unary, int_log2,
278+
"Returns the base-2 logarithm of the specified value.",
279+
[llvm_halforfloat_ty, LLVMMatchType<0>]>;
277280
def Sqrt : DXILOpMapping<24, unary, int_sqrt,
278281
"Returns the square root of the specified floating-point"
279282
"value, per component.",

llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ static bool isIntrinsicExpansion(Function &F) {
3535
switch (F.getIntrinsicID()) {
3636
case Intrinsic::abs:
3737
case Intrinsic::exp:
38+
case Intrinsic::log:
39+
case Intrinsic::log10:
3840
case Intrinsic::dx_any:
3941
case Intrinsic::dx_clamp:
4042
case Intrinsic::dx_uclamp:
@@ -108,8 +110,8 @@ static bool expandExpIntrinsic(CallInst *Orig) {
108110
Ty->isVectorTy() ? ConstantVector::getSplat(
109111
ElementCount::getFixed(
110112
cast<FixedVectorType>(Ty)->getNumElements()),
111-
ConstantFP::get(EltTy, numbers::log2e))
112-
: ConstantFP::get(EltTy, numbers::log2e);
113+
ConstantFP::get(EltTy, numbers::log2ef))
114+
: ConstantFP::get(EltTy, numbers::log2ef);
113115
Value *NewX = Builder.CreateFMul(Log2eConst, X);
114116
auto *Exp2Call =
115117
Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {NewX}, nullptr, "dx.exp2");
@@ -169,6 +171,32 @@ static bool expandLerpIntrinsic(CallInst *Orig) {
169171
return true;
170172
}
171173

174+
static bool expandLogIntrinsic(CallInst *Orig,
175+
float LogConstVal = numbers::ln2f) {
176+
Value *X = Orig->getOperand(0);
177+
IRBuilder<> Builder(Orig->getParent());
178+
Builder.SetInsertPoint(Orig);
179+
Type *Ty = X->getType();
180+
Type *EltTy = Ty->getScalarType();
181+
Constant *Ln2Const =
182+
Ty->isVectorTy() ? ConstantVector::getSplat(
183+
ElementCount::getFixed(
184+
cast<FixedVectorType>(Ty)->getNumElements()),
185+
ConstantFP::get(EltTy, LogConstVal))
186+
: ConstantFP::get(EltTy, LogConstVal);
187+
auto *Log2Call =
188+
Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
189+
Log2Call->setTailCall(Orig->isTailCall());
190+
Log2Call->setAttributes(Orig->getAttributes());
191+
auto *Result = Builder.CreateFMul(Ln2Const, Log2Call);
192+
Orig->replaceAllUsesWith(Result);
193+
Orig->eraseFromParent();
194+
return true;
195+
}
196+
static bool expandLog10Intrinsic(CallInst *Orig) {
197+
return expandLogIntrinsic(Orig, numbers::ln2f / numbers::ln10f);
198+
}
199+
172200
static bool expandRcpIntrinsic(CallInst *Orig) {
173201
Value *X = Orig->getOperand(0);
174202
IRBuilder<> Builder(Orig->getParent());
@@ -238,6 +266,10 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) {
238266
return expandAbs(Orig);
239267
case Intrinsic::exp:
240268
return expandExpIntrinsic(Orig);
269+
case Intrinsic::log:
270+
return expandLogIntrinsic(Orig);
271+
case Intrinsic::log10:
272+
return expandLog10Intrinsic(Orig);
241273
case Intrinsic::dx_any:
242274
return expandAnyIntrinsic(Orig);
243275
case Intrinsic::dx_uclamp:

llvm/test/CodeGen/DirectX/log.ll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
2+
; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
3+
4+
; Make sure dxil operation function calls for log are generated.
5+
6+
define noundef float @log_float(float noundef %a) #0 {
7+
entry:
8+
; DOPCHECK: call float @dx.op.unary.f32(i32 23, float %{{.*}})
9+
; EXPCHECK: call float @llvm.log2.f32(float %a)
10+
; CHECK: fmul float 0x3FE62E4300000000, %{{.*}}
11+
%elt.log = call float @llvm.log.f32(float %a)
12+
ret float %elt.log
13+
}
14+
15+
define noundef half @log_half(half noundef %a) #0 {
16+
entry:
17+
; DOPCHECK: call half @dx.op.unary.f16(i32 23, half %{{.*}})
18+
; EXPCHECK: call half @llvm.log2.f16(half %a)
19+
; CHECK: fmul half 0xH398C, %{{.*}}
20+
%elt.log = call half @llvm.log.f16(half %a)
21+
ret half %elt.log
22+
}
23+
24+
declare half @llvm.log.f16(half)
25+
declare float @llvm.log.f32(float)

llvm/test/CodeGen/DirectX/log10.ll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
2+
; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
3+
4+
; Make sure dxil operation function calls for log10 are generated.
5+
6+
define noundef float @log10_float(float noundef %a) #0 {
7+
entry:
8+
; DOPCHECK: call float @dx.op.unary.f32(i32 23, float %{{.*}})
9+
; EXPCHECK: call float @llvm.log2.f32(float %a)
10+
; CHECK: fmul float 0x3FD3441340000000, %{{.*}}
11+
%elt.log10 = call float @llvm.log10.f32(float %a)
12+
ret float %elt.log10
13+
}
14+
15+
define noundef half @log10_half(half noundef %a) #0 {
16+
entry:
17+
; DOPCHECK: call half @dx.op.unary.f16(i32 23, half %{{.*}})
18+
; EXPCHECK: call half @llvm.log2.f16(half %a)
19+
; CHECK: fmul half 0xH34D1, %{{.*}}
20+
%elt.log10 = call half @llvm.log10.f16(half %a)
21+
ret half %elt.log10
22+
}
23+
24+
declare half @llvm.log10.f16(half)
25+
declare float @llvm.log10.f32(float)

llvm/test/CodeGen/DirectX/log2.ll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
2+
3+
; Make sure dxil operation function calls for log2 are generated for float and half.
4+
5+
define noundef float @log2_float(float noundef %a) #0 {
6+
entry:
7+
; CHECK:call float @dx.op.unary.f32(i32 23, float %{{.*}})
8+
%elt.log2 = call float @llvm.log2.f32(float %a)
9+
ret float %elt.log2
10+
}
11+
12+
define noundef half @log2_half(half noundef %a) #0 {
13+
entry:
14+
; CHECK:call half @dx.op.unary.f16(i32 23, half %{{.*}})
15+
%elt.log2 = call half @llvm.log2.f16(half %a)
16+
ret half %elt.log2
17+
}
18+
19+
declare half @llvm.log2.f16(half)
20+
declare float @llvm.log2.f32(float)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
2+
3+
; DXIL operation log2 does not support double overload type
4+
; CHECK: LLVM ERROR: Invalid Overload Type
5+
6+
define noundef double @log2_double(double noundef %a) {
7+
entry:
8+
%elt.log2 = call double @llvm.log2.f64(double %a)
9+
ret double %elt.log2
10+
}

0 commit comments

Comments
 (0)