[llvm] [DirectX] Make DXILOpLowering split vector coordinates, offsets, and gradient operands (PR #223091)
Deric C. via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 16 09:49:16 PDT 2026
https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/223091
>From 17eb826dc9bcad494b413a22db9ccd077f78b0f0 Mon Sep 17 00:00:00 2001
From: Deric Cheung <cheung.deric at gmail.com>
Date: Fri, 11 Sep 2026 11:27:29 -0700
Subject: [PATCH 1/2] Make DXILOpLowering split vector coordinates, offsets,
and gradient operands
---
llvm/lib/Target/DirectX/DXILOpLowering.cpp | 115 +++++++++-----
llvm/test/CodeGen/DirectX/Sample.ll | 73 ++++++---
llvm/test/CodeGen/DirectX/SampleBias.ll | 74 ++++++---
llvm/test/CodeGen/DirectX/SampleGrad.ll | 149 +++++++++++-------
llvm/test/CodeGen/DirectX/SampleLevel.ll | 65 ++++++--
.../DirectX/Texture2DArray-SampleBias.ll | 50 +++++-
.../DirectX/Texture2DArray-SampleGrad.ll | 59 ++++++-
llvm/test/CodeGen/DirectX/TextureLoad.ll | 86 ++++++----
llvm/test/CodeGen/DirectX/TextureStore.ll | 99 +++++++++---
9 files changed, 561 insertions(+), 209 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index a98c115bcd62e..aa73629eee232 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -26,6 +26,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Use.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/ErrorHandling.h"
@@ -639,22 +640,56 @@ class OpLowerer {
});
}
+ /// Recover the scalar components of `Vec` from the `insertelement` chain that
+ /// built it. Since we run after the scalarizer, such a chain is usually just
+ /// a temporary gathered to pass the vector to a call.
+ static void collectInsertedElements(Value *Vec,
+ MutableArrayRef<Value *> Elements) {
+ unsigned NumElts = cast<FixedVectorType>(Vec->getType())->getNumElements();
+ assert(NumElts <= Elements.size() && "Not enough room for the components");
+
+ SmallVector<InsertElementInst *, 4> Chain;
+ for (auto *IEI = dyn_cast<InsertElementInst>(Vec); IEI;
+ IEI = dyn_cast<InsertElementInst>(IEI->getOperand(0))) {
+ if (!isa<ConstantInt>(IEI->getOperand(2)))
+ break; // This break should never happen below SM6.9.
+ Chain.push_back(IEI);
+ }
+
+ // Replay element insertion from the innermost first, so that a repeated
+ // index ends up holding the live value.
+ while (!Chain.empty()) {
+ InsertElementInst *IEI = Chain.pop_back_val();
+ uint64_t IndexVal = cast<ConstantInt>(IEI->getOperand(2))->getZExtValue();
+ if (IndexVal < NumElts)
+ Elements[IndexVal] = IEI->getOperand(1);
+ }
+ }
+
// Copies `Src` into `Args` starting at `ArgIdx`. If `Src` is a vector, its
- // elements are extracted and stored in consecutive slots; otherwise `Src`
- // is stored directly. At most `MaxElements` elements are expected.
+ // elements are placed in consecutive slots; otherwise `Src` is stored
+ // directly. At most `MaxElements` elements are expected.
static void extractElementsIntoArgs(IRBuilder<> &IRB,
MutableArrayRef<Value *> Args,
unsigned ArgIdx, Value *Src,
unsigned MaxElements) {
- Type *Ty = Src->getType();
- if (auto *VecTy = dyn_cast<FixedVectorType>(Ty)) {
- unsigned Count = VecTy->getNumElements();
- assert(Count <= MaxElements && "Expected at most 3 elements in vector");
- for (unsigned I = 0; I < Count; ++I)
- Args[ArgIdx + I] = IRB.CreateExtractElement(Src, uint64_t(I));
- } else {
+ auto *VecTy = dyn_cast<FixedVectorType>(Src->getType());
+ if (!VecTy) {
Args[ArgIdx] = Src;
+ return;
}
+
+ unsigned Count = VecTy->getNumElements();
+ assert(Count <= MaxElements && "Too many elements for the arg list");
+
+ SmallVector<Value *, 4> Elements(Count, nullptr);
+ collectInsertedElements(Src, Elements);
+
+ for (unsigned I = 0; I < Count; ++I)
+ Args[ArgIdx + I] = Elements[I]
+ ? Elements[I]
+ : IRB.CreateExtractElement(
+ Src, ConstantInt::get(IRB.getInt32Ty(), I));
}
/// Copy offsets into the argument list at the given index, unless
@@ -676,6 +711,7 @@ class OpLowerer {
return replaceFunction(F, [&](CallInst *CI) -> Error {
IRB.SetInsertPoint(CI);
+ SmallVector<WeakTrackingVH, 4> VectorArgs = collectVectorArgs(CI);
Value *Handle =
createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());
Value *Coords = CI->getArgOperand(1);
@@ -710,6 +746,8 @@ class OpLowerer {
if (Error E = replaceResRetUses(CI, *OpCall, /*HasCheckBit=*/false))
return E;
+ eraseDeadInsertElementChains(VectorArgs);
+
return Error::success();
});
}
@@ -725,6 +763,7 @@ class OpLowerer {
return replaceFunction(F, [&](CallInst *CI) -> Error {
IRB.SetInsertPoint(CI);
+ SmallVector<WeakTrackingVH, 4> VectorArgs = collectVectorArgs(CI);
Value *Handle =
createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());
Value *Sampler =
@@ -755,6 +794,8 @@ class OpLowerer {
if (Error E = replaceResRetUses(CI, *OpCall, /*HasCheckBit=*/false))
return E;
+ eraseDeadInsertElementChains(VectorArgs);
+
return Error::success();
});
}
@@ -946,35 +987,8 @@ class OpLowerer {
static std::array<Value *, 4> splitStoreData(IRBuilder<> &IRB, Value *Data,
uint64_t NumElements,
bool FillWithUndef) {
- Type *DataTy = Data->getType();
- Type *ScalarTy = DataTy->getScalarType();
-
std::array<Value *, 4> DataElements{nullptr, nullptr, nullptr, nullptr};
- if (DataTy == ScalarTy)
- DataElements[0] = Data;
- else {
- // Since we're post-scalarizer, if we see a vector here it's likely
- // constructed solely for the argument of the store. Just use the scalar
- // values from before they're inserted into the temporary.
- auto *IEI = dyn_cast<InsertElementInst>(Data);
- while (IEI) {
- auto *IndexOp = dyn_cast<ConstantInt>(IEI->getOperand(2));
- if (!IndexOp)
- break;
- size_t IndexVal = IndexOp->getZExtValue();
- assert(IndexVal < 4 && "Too many elements for resource store");
- DataElements[IndexVal] = IEI->getOperand(1);
- IEI = dyn_cast<InsertElementInst>(IEI->getOperand(0));
- }
- }
-
- // If for some reason we weren't able to forward the arguments from the
- // scalarizer artifact, then we may need to actually extract elements from
- // the vector.
- for (uint64_t I = 0, E = NumElements; I < E; ++I)
- if (DataElements[I] == nullptr)
- DataElements[I] = IRB.CreateExtractElement(
- Data, ConstantInt::get(IRB.getInt32Ty(), I));
+ extractElementsIntoArgs(IRB, DataElements, 0, Data, 4);
// For any elements beyond the length of the vector, we should fill it up
// with undef - however, for typed UAVs we repeat the first element to
@@ -982,13 +996,14 @@ class OpLowerer {
for (uint64_t I = NumElements, E = 4; I < E; ++I)
if (DataElements[I] == nullptr)
DataElements[I] =
- FillWithUndef ? UndefValue::get(ScalarTy) : DataElements[0];
+ FillWithUndef ? UndefValue::get(Data->getType()->getScalarType())
+ : DataElements[0];
return DataElements;
}
- /// Erase the chain of `insertelement`s that only existed to build up the
- /// value operand of a store we've just replaced.
+ /// Erase the chain of `insertelement`s that only existed to build up a vector
+ /// operand of an intrinsic we've just replaced.
static void eraseDeadInsertElementChain(Value *Data) {
auto *IEI = dyn_cast<InsertElementInst>(Data);
while (IEI && IEI->use_empty()) {
@@ -1059,6 +1074,23 @@ class OpLowerer {
});
}
+ /// Snapshot the vector-typed arguments of `CI` so their `insertelement`
+ /// chains can be cleaned up once `CI` has been replaced. The handles are weak
+ /// because two arguments can share an `insertelement` chain.
+ static SmallVector<WeakTrackingVH, 4> collectVectorArgs(CallInst *CI) {
+ SmallVector<WeakTrackingVH, 4> Vectors;
+ for (Value *Arg : CI->args())
+ if (isa<FixedVectorType>(Arg->getType()))
+ Vectors.emplace_back(Arg);
+ return Vectors;
+ }
+
+ static void eraseDeadInsertElementChains(ArrayRef<WeakTrackingVH> Vectors) {
+ for (const WeakTrackingVH &VH : Vectors)
+ if (Value *V = VH)
+ eraseDeadInsertElementChain(V);
+ }
+
[[nodiscard]] bool lowerTextureStore(Function &F) {
const DataLayout &DL = F.getDataLayout();
IRBuilder<> &IRB = OpBuilder.getIRB();
@@ -1068,6 +1100,7 @@ class OpLowerer {
return replaceFunction(F, [&](CallInst *CI) -> Error {
IRB.SetInsertPoint(CI);
+ SmallVector<WeakTrackingVH, 4> VectorArgs = collectVectorArgs(CI);
Value *Handle =
createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());
Value *Coords = CI->getArgOperand(1);
@@ -1101,7 +1134,7 @@ class OpLowerer {
return E;
CI->eraseFromParent();
- eraseDeadInsertElementChain(Data);
+ eraseDeadInsertElementChains(VectorArgs);
return Error::success();
});
diff --git a/llvm/test/CodeGen/DirectX/Sample.ll b/llvm/test/CodeGen/DirectX/Sample.ll
index 779df2beb347d..f9a6fcc868b14 100644
--- a/llvm/test/CodeGen/DirectX/Sample.ll
+++ b/llvm/test/CodeGen/DirectX/Sample.ll
@@ -16,8 +16,8 @@ define void @sample_texture2d_float4(<2 x float> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sample.f32(i32 60,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -46,8 +46,8 @@ define void @sample_texture2d_with_clamp(<2 x float> %coords, float %clamp) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sample.f32(i32 60,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -76,8 +76,8 @@ define void @sample_texture2d_with_offset(<2 x float> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sample.f32(i32 60,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -106,10 +106,10 @@ define void @sample_texture2d_with_dynamic_offset(<2 x float> %coords, <2 x i32>
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
- ; CHECK: %[[OFF0:.*]] = extractelement <2 x i32> %offsets, i64 0
- ; CHECK: %[[OFF1:.*]] = extractelement <2 x i32> %offsets, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
+ ; CHECK: %[[OFF0:.*]] = extractelement <2 x i32> %offsets, i32 0
+ ; CHECK: %[[OFF1:.*]] = extractelement <2 x i32> %offsets, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sample.f32(i32 60,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -138,8 +138,8 @@ define void @sample_texture2d_with_offset_and_clamp(<2 x float> %coords, float %
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sample.f32(i32 60,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -196,9 +196,9 @@ define void @sample_texture3d_float4(<3 x float> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i32 2
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sample.f32(i32 60,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -227,8 +227,8 @@ define void @sample_texture2d_scalar(<2 x float> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sample.f32(i32 60,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -257,8 +257,8 @@ define void @sample_texture2d_half4(<2 x float> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f16
; CHECK-SAME: @dx.op.sample.f16(i32 60,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -276,3 +276,38 @@ define void @sample_texture2d_half4(<2 x float> %coords) {
call void @use_half4(<4 x half> %data)
ret void
}
+
+; The scalarizer re-gathers the coordinates just to pass them to the intrinsic.
+; DXIL has no vector instructions, so the scalars the vector was built from are
+; forwarded into the sample rather than extracted again.
+; CHECK-LABEL: define void @sample_texture2d_scalarized(
+define void @sample_texture2d_scalarized(float %u, float %v) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 2)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_2t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ %coords.0 = insertelement <2 x float> poison, float %u, i32 0
+ %coords.1 = insertelement <2 x float> %coords.0, float %v, i32 1
+
+ ; CHECK-NOT: insertelement
+ ; CHECK-NOT: extractelement
+ ; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
+ ; CHECK-SAME: @dx.op.sample.f32(i32 60,
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: float %u, float %v, float undef, float undef,
+ ; CHECK-SAME: i32 undef, i32 undef, i32 undef,
+ ; CHECK-SAME: float undef)
+ %data = call <4 x float>
+ @llvm.dx.resource.sample.v4f32.tdx.Texture_v4f32_0_0_0_2t.tdx.Sampler_0t.v2f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 2) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <2 x float> %coords.1, <2 x i32> zeroinitializer)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[SAMPLE]], 0
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
diff --git a/llvm/test/CodeGen/DirectX/SampleBias.ll b/llvm/test/CodeGen/DirectX/SampleBias.ll
index 47cded9a65275..dfca61b61ab85 100644
--- a/llvm/test/CodeGen/DirectX/SampleBias.ll
+++ b/llvm/test/CodeGen/DirectX/SampleBias.ll
@@ -16,8 +16,8 @@ define void @samplebias_texture2d_float4(<2 x float> %coords, float %bias) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -47,8 +47,8 @@ define void @samplebias_texture2d_with_clamp(<2 x float> %coords, float %bias, f
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -78,8 +78,8 @@ define void @samplebias_texture2d_with_offset(<2 x float> %coords, float %bias)
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -109,10 +109,10 @@ define void @samplebias_texture2d_with_dynamic_offset(<2 x float> %coords, float
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
- ; CHECK: %[[OFF0:.*]] = extractelement <2 x i32> %offsets, i64 0
- ; CHECK: %[[OFF1:.*]] = extractelement <2 x i32> %offsets, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
+ ; CHECK: %[[OFF0:.*]] = extractelement <2 x i32> %offsets, i32 0
+ ; CHECK: %[[OFF1:.*]] = extractelement <2 x i32> %offsets, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -142,8 +142,8 @@ define void @samplebias_texture2d_with_offset_and_clamp(<2 x float> %coords, flo
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -202,9 +202,9 @@ define void @samplebias_texture3d_float4(<3 x float> %coords, float %bias) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i32 2
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -234,8 +234,8 @@ define void @samplebias_texture2d_scalar(<2 x float> %coords, float %bias) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -265,8 +265,8 @@ define void @samplebias_texture2d_half4(<2 x float> %coords, float %bias) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f16
; CHECK-SAME: @dx.op.sampleBias.f16(i32 61,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -285,3 +285,39 @@ define void @samplebias_texture2d_half4(<2 x float> %coords, float %bias) {
call void @use_half4(<4 x half> %data)
ret void
}
+
+; The scalarizer re-gathers the coordinates just to pass them to the intrinsic.
+; DXIL has no vector instructions, so the scalars the vector was built from are
+; forwarded into the sample rather than extracted again.
+; CHECK-LABEL: define void @samplebias_texture2d_scalarized(
+define void @samplebias_texture2d_scalarized(float %u, float %v, float %bias) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 2)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_2t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ %coords.0 = insertelement <2 x float> poison, float %u, i32 0
+ %coords.1 = insertelement <2 x float> %coords.0, float %v, i32 1
+
+ ; CHECK-NOT: insertelement
+ ; CHECK-NOT: extractelement
+ ; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
+ ; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: float %u, float %v, float undef, float undef,
+ ; CHECK-SAME: i32 undef, i32 undef, i32 undef,
+ ; CHECK-SAME: float %bias,
+ ; CHECK-SAME: float undef)
+ %data = call <4 x float>
+ @llvm.dx.resource.samplebias.v4f32.tdx.Texture_v4f32_0_0_0_2t.tdx.Sampler_0t.v2f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 2) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <2 x float> %coords.1, float %bias, <2 x i32> zeroinitializer)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[SAMPLE]], 0
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
diff --git a/llvm/test/CodeGen/DirectX/SampleGrad.ll b/llvm/test/CodeGen/DirectX/SampleGrad.ll
index 0371079c9f29d..37ec29d03a570 100644
--- a/llvm/test/CodeGen/DirectX/SampleGrad.ll
+++ b/llvm/test/CodeGen/DirectX/SampleGrad.ll
@@ -16,12 +16,12 @@ define void @samplegrad_texture2d_float4(<2 x float> %coords, <2 x float> %ddx,
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
- ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i64 0
- ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i64 1
- ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i64 0
- ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
+ ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i32 0
+ ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i32 1
+ ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i32 0
+ ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -53,12 +53,12 @@ define void @samplegrad_texture2d_with_clamp(<2 x float> %coords, <2 x float> %d
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
- ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i64 0
- ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i64 1
- ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i64 0
- ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
+ ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i32 0
+ ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i32 1
+ ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i32 0
+ ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -90,12 +90,12 @@ define void @samplegrad_texture2d_with_offset(<2 x float> %coords, <2 x float> %
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
- ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i64 0
- ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i64 1
- ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i64 0
- ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
+ ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i32 0
+ ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i32 1
+ ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i32 0
+ ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -127,14 +127,14 @@ define void @samplegrad_texture2d_with_dynamic_offset(<2 x float> %coords, <2 x
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
- ; CHECK: %[[OFF0:.*]] = extractelement <2 x i32> %offsets, i64 0
- ; CHECK: %[[OFF1:.*]] = extractelement <2 x i32> %offsets, i64 1
- ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i64 0
- ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i64 1
- ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i64 0
- ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
+ ; CHECK: %[[OFF0:.*]] = extractelement <2 x i32> %offsets, i32 0
+ ; CHECK: %[[OFF1:.*]] = extractelement <2 x i32> %offsets, i32 1
+ ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i32 0
+ ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i32 1
+ ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i32 0
+ ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -166,12 +166,12 @@ define void @samplegrad_texture2d_with_offset_and_clamp(<2 x float> %coords, <2
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
- ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i64 0
- ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i64 1
- ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i64 0
- ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
+ ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i32 0
+ ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i32 1
+ ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i32 0
+ ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -233,15 +233,15 @@ define void @samplegrad_texture3d_float4(<3 x float> %coords, <3 x float> %ddx,
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i64 2
- ; CHECK: %[[DDX0:.*]] = extractelement <3 x float> %ddx, i64 0
- ; CHECK: %[[DDX1:.*]] = extractelement <3 x float> %ddx, i64 1
- ; CHECK: %[[DDX2:.*]] = extractelement <3 x float> %ddx, i64 2
- ; CHECK: %[[DDY0:.*]] = extractelement <3 x float> %ddy, i64 0
- ; CHECK: %[[DDY1:.*]] = extractelement <3 x float> %ddy, i64 1
- ; CHECK: %[[DDY2:.*]] = extractelement <3 x float> %ddy, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i32 2
+ ; CHECK: %[[DDX0:.*]] = extractelement <3 x float> %ddx, i32 0
+ ; CHECK: %[[DDX1:.*]] = extractelement <3 x float> %ddx, i32 1
+ ; CHECK: %[[DDX2:.*]] = extractelement <3 x float> %ddx, i32 2
+ ; CHECK: %[[DDY0:.*]] = extractelement <3 x float> %ddy, i32 0
+ ; CHECK: %[[DDY1:.*]] = extractelement <3 x float> %ddy, i32 1
+ ; CHECK: %[[DDY2:.*]] = extractelement <3 x float> %ddy, i32 2
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -273,12 +273,12 @@ define void @samplegrad_texture2d_scalar(<2 x float> %coords, <2 x float> %ddx,
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
- ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i64 0
- ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i64 1
- ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i64 0
- ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
+ ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i32 0
+ ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i32 1
+ ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i32 0
+ ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -310,12 +310,12 @@ define void @samplegrad_texture2d_half4(<2 x float> %coords, <2 x float> %ddx, <
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
- ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i64 0
- ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i64 1
- ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i64 0
- ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
+ ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i32 0
+ ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i32 1
+ ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i32 0
+ ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f16
; CHECK-SAME: @dx.op.sampleGrad.f16(i32 63,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -336,3 +336,46 @@ define void @samplegrad_texture2d_half4(<2 x float> %coords, <2 x float> %ddx, <
call void @use_half4(<4 x half> %data)
ret void
}
+
+; DXIL has no vector instructions, so the scalars the vector operands were
+; built from are forwarded into the sample rather than extracted again.
+; CHECK-LABEL: define void @sample_grad_texture2d_scalarized(
+define void @sample_grad_texture2d_scalarized(float %u, float %v, float %ddxu,
+ float %ddxv, float %ddyu,
+ float %ddyv) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 2)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_2t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ %coords.0 = insertelement <2 x float> poison, float %u, i32 0
+ %coords.1 = insertelement <2 x float> %coords.0, float %v, i32 1
+ %ddx.0 = insertelement <2 x float> poison, float %ddxu, i32 0
+ %ddx.1 = insertelement <2 x float> %ddx.0, float %ddxv, i32 1
+ %ddy.0 = insertelement <2 x float> poison, float %ddyu, i32 0
+ %ddy.1 = insertelement <2 x float> %ddy.0, float %ddyv, i32 1
+
+ ; CHECK-NOT: insertelement
+ ; CHECK-NOT: extractelement <2 x float>
+ ; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
+ ; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: float %u, float %v, float undef, float undef,
+ ; CHECK-SAME: i32 undef, i32 undef, i32 undef,
+ ; CHECK-SAME: float %ddxu, float %ddxv, float undef,
+ ; CHECK-SAME: float %ddyu, float %ddyv, float undef,
+ ; CHECK-SAME: float undef)
+ %data = call <4 x float>
+ @llvm.dx.resource.samplegrad.v4f32.tdx.Texture_v4f32_0_0_0_2t.tdx.Sampler_0t.v2f32.v2f32.v2f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 2) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <2 x float> %coords.1, <2 x float> %ddx.1, <2 x float> %ddy.1,
+ <2 x i32> zeroinitializer)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[SAMPLE]], 0
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
diff --git a/llvm/test/CodeGen/DirectX/SampleLevel.ll b/llvm/test/CodeGen/DirectX/SampleLevel.ll
index 3cfbc544418d9..f902e646c90c1 100644
--- a/llvm/test/CodeGen/DirectX/SampleLevel.ll
+++ b/llvm/test/CodeGen/DirectX/SampleLevel.ll
@@ -16,8 +16,8 @@ define void @samplelevel_texture2d_float4(<2 x float> %coords, float %lod) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleLevel.f32(i32 62,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -46,8 +46,8 @@ define void @samplelevel_texture2d_with_offset(<2 x float> %coords, float %lod)
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleLevel.f32(i32 62,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -76,10 +76,10 @@ define void @samplelevel_texture2d_with_dynamic_offset(<2 x float> %coords, floa
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
- ; CHECK: %[[OFF0:.*]] = extractelement <2 x i32> %offsets, i64 0
- ; CHECK: %[[OFF1:.*]] = extractelement <2 x i32> %offsets, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
+ ; CHECK: %[[OFF0:.*]] = extractelement <2 x i32> %offsets, i32 0
+ ; CHECK: %[[OFF1:.*]] = extractelement <2 x i32> %offsets, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleLevel.f32(i32 62,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -136,9 +136,9 @@ define void @samplelevel_texture3d_float4(<3 x float> %coords, float %lod) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i32 2
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleLevel.f32(i32 62,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -167,8 +167,8 @@ define void @samplelevel_texture2d_scalar(<2 x float> %coords, float %lod) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleLevel.f32(i32 62,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -197,8 +197,8 @@ define void @samplelevel_texture2d_half4(<2 x float> %coords, float %lod) {
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x float> %coords, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f16
; CHECK-SAME: @dx.op.sampleLevel.f16(i32 62,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -216,3 +216,38 @@ define void @samplelevel_texture2d_half4(<2 x float> %coords, float %lod) {
call void @use_half4(<4 x half> %data)
ret void
}
+
+; The scalarizer re-gathers the coordinates just to pass them to the intrinsic.
+; DXIL has no vector instructions, so the scalars the vector was built from are
+; forwarded into the sample rather than extracted again.
+; CHECK-LABEL: define void @samplelevel_texture2d_scalarized(
+define void @samplelevel_texture2d_scalarized(float %u, float %v, float %lod) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 2)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_2t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ %coords.0 = insertelement <2 x float> poison, float %u, i32 0
+ %coords.1 = insertelement <2 x float> %coords.0, float %v, i32 1
+
+ ; CHECK-NOT: insertelement
+ ; CHECK-NOT: extractelement
+ ; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
+ ; CHECK-SAME: @dx.op.sampleLevel.f32(i32 62,
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: float %u, float %v, float undef, float undef,
+ ; CHECK-SAME: i32 undef, i32 undef, i32 undef,
+ ; CHECK-SAME: float %lod)
+ %data = call <4 x float>
+ @llvm.dx.resource.samplelevel.v4f32.tdx.Texture_v4f32_0_0_0_2t.tdx.Sampler_0t.v2f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 2) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <2 x float> %coords.1, float %lod, <2 x i32> zeroinitializer)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[SAMPLE]], 0
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
diff --git a/llvm/test/CodeGen/DirectX/Texture2DArray-SampleBias.ll b/llvm/test/CodeGen/DirectX/Texture2DArray-SampleBias.ll
index 84a77920bcbed..76ceecb9ec6c2 100644
--- a/llvm/test/CodeGen/DirectX/Texture2DArray-SampleBias.ll
+++ b/llvm/test/CodeGen/DirectX/Texture2DArray-SampleBias.ll
@@ -14,9 +14,9 @@ define void @samplebias_texture2darray_float4(<3 x float> %coords, float %bias)
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i32 2
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -46,9 +46,9 @@ define void @samplebias_texture2darray_with_offset(<3 x float> %coords, float %b
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i32 2
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -94,3 +94,41 @@ define void @samplebias_texture2darray_with_clamp(<3 x float> %coords, float %bi
call void @use_float4(<4 x float> %data)
ret void
}
+
+; The scalarizer re-gathers the coordinates just to pass them to the intrinsic.
+; DXIL has no vector instructions, so the scalars the vector was built from are
+; forwarded into the sample rather than extracted again.
+; CHECK-LABEL: define void @samplebias_texture2darray_scalarized(
+define void @samplebias_texture2darray_scalarized(float %u, float %v, float %w,
+ float %bias) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 7)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_7t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ %coords.0 = insertelement <3 x float> poison, float %u, i32 0
+ %coords.1 = insertelement <3 x float> %coords.0, float %v, i32 1
+ %coords.2 = insertelement <3 x float> %coords.1, float %w, i32 2
+
+ ; CHECK-NOT: insertelement
+ ; CHECK-NOT: extractelement
+ ; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
+ ; CHECK-SAME: @dx.op.sampleBias.f32(i32 61,
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: float %u, float %v, float %w, float undef,
+ ; CHECK-SAME: i32 undef, i32 undef, i32 undef,
+ ; CHECK-SAME: float %bias,
+ ; CHECK-SAME: float undef)
+ %data = call <4 x float>
+ @llvm.dx.resource.samplebias.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 7) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <3 x float> %coords.2, float %bias, <2 x i32> zeroinitializer)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[SAMPLE]], 0
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
diff --git a/llvm/test/CodeGen/DirectX/Texture2DArray-SampleGrad.ll b/llvm/test/CodeGen/DirectX/Texture2DArray-SampleGrad.ll
index 214906036542a..fa06b4cbe5f03 100644
--- a/llvm/test/CodeGen/DirectX/Texture2DArray-SampleGrad.ll
+++ b/llvm/test/CodeGen/DirectX/Texture2DArray-SampleGrad.ll
@@ -14,13 +14,13 @@ define void @samplegrad_texture2darray_float4(<3 x float> %coords, <2 x float> %
@llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i64 2
- ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i64 0
- ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i64 1
- ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i64 0
- ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x float> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x float> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x float> %coords, i32 2
+ ; CHECK: %[[DDX0:.*]] = extractelement <2 x float> %ddx, i32 0
+ ; CHECK: %[[DDX1:.*]] = extractelement <2 x float> %ddx, i32 1
+ ; CHECK: %[[DDY0:.*]] = extractelement <2 x float> %ddy, i32 0
+ ; CHECK: %[[DDY1:.*]] = extractelement <2 x float> %ddy, i32 1
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
@@ -70,3 +70,48 @@ define void @samplegrad_texture2darray_with_offset(<3 x float> %coords, <2 x flo
call void @use_float4(<4 x float> %data)
ret void
}
+
+; The scalarizer re-gathers the vector operands just to pass them to the
+; intrinsic. DXIL has no vector instructions, so the scalars they were built
+; from are forwarded into the sample rather than extracted again.
+; CHECK-LABEL: define void @samplegrad_texture2darray_scalarized(
+define void @samplegrad_texture2darray_scalarized(float %u, float %v, float %w,
+ float %ddxu, float %ddxv,
+ float %ddyu, float %ddyv) {
+ %texture = call target("dx.Texture", <4 x float>, 0, 0, 0, 7)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_7t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+ %sampler = call target("dx.Sampler", 0)
+ @llvm.dx.resource.handlefrombinding.tdx.Sampler_0t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ %coords.0 = insertelement <3 x float> poison, float %u, i32 0
+ %coords.1 = insertelement <3 x float> %coords.0, float %v, i32 1
+ %coords.2 = insertelement <3 x float> %coords.1, float %w, i32 2
+ %ddx.0 = insertelement <2 x float> poison, float %ddxu, i32 0
+ %ddx.1 = insertelement <2 x float> %ddx.0, float %ddxv, i32 1
+ %ddy.0 = insertelement <2 x float> poison, float %ddyu, i32 0
+ %ddy.1 = insertelement <2 x float> %ddy.0, float %ddyv, i32 1
+
+ ; CHECK-NOT: insertelement
+ ; CHECK-NOT: extractelement
+ ; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
+ ; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
+ ; CHECK-SAME: float %u, float %v, float %w, float undef,
+ ; CHECK-SAME: i32 undef, i32 undef, i32 undef,
+ ; CHECK-SAME: float %ddxu, float %ddxv, float undef,
+ ; CHECK-SAME: float %ddyu, float %ddyv, float undef,
+ ; CHECK-SAME: float undef)
+ %data = call <4 x float>
+ @llvm.dx.resource.samplegrad.v4f32.tdx.Texture_v4f32_0_0_0_7t.tdx.Sampler_0t.v3f32.v2f32.v2f32.v2i32(
+ target("dx.Texture", <4 x float>, 0, 0, 0, 7) %texture,
+ target("dx.Sampler", 0) %sampler,
+ <3 x float> %coords.2, <2 x float> %ddx.1, <2 x float> %ddy.1,
+ <2 x i32> zeroinitializer)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[SAMPLE]], 0
+ call void @use_float4(<4 x float> %data)
+ ret void
+}
diff --git a/llvm/test/CodeGen/DirectX/TextureLoad.ll b/llvm/test/CodeGen/DirectX/TextureLoad.ll
index cf6c460ac2105..29329f4bf9896 100644
--- a/llvm/test/CodeGen/DirectX/TextureLoad.ll
+++ b/llvm/test/CodeGen/DirectX/TextureLoad.ll
@@ -13,8 +13,8 @@ define void @load_texture2d_float4(<2 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_2t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 0, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, i32 undef, i32 undef, i32 undef)
%data = call <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_0_0_0_2t.v2i32.i32.v2i32(
target("dx.Texture", <4 x float>, 0, 0, 0, 2) %texture,
@@ -31,8 +31,8 @@ define void @load_texture2d_float(<2 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_f32_0_0_0_2t(
i32 0, i32 1, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 0, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, i32 undef, i32 undef, i32 undef)
%data = call float @llvm.dx.resource.load.level.f32.tdx.Texture_f32_0_0_0_2t.v2i32.i32.v2i32(
target("dx.Texture", float, 0, 0, 0, 2) %texture,
@@ -49,8 +49,8 @@ define void @load_texture2d_int3(<2 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_v3i32_0_0_1_2t(
i32 0, i32 2, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.i32 @dx.op.textureLoad.i32(i32 66, %dx.types.Handle %{{.*}}, i32 0, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, i32 undef, i32 undef, i32 undef)
%data = call <3 x i32> @llvm.dx.resource.load.level.v3i32.tdx.Texture_v3i32_0_0_1_2t.v2i32.i32.v2i32(
target("dx.Texture", <3 x i32>, 0, 0, 1, 2) %texture,
@@ -66,8 +66,8 @@ define void @load_texture2d_float4_with_level(<2 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_2t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 2, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, i32 undef, i32 undef, i32 undef)
%data = call <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_0_0_0_2t.v2i32.i32.v2i32(
target("dx.Texture", <4 x float>, 0, 0, 0, 2) %texture,
@@ -84,8 +84,8 @@ define void @load_texture2d_float4_with_offset(<2 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_2t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 0, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, i32 1, i32 -2, i32 undef)
%data = call <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_0_0_0_2t.v2i32.i32.v2i32(
target("dx.Texture", <4 x float>, 0, 0, 0, 2) %texture,
@@ -102,8 +102,8 @@ define void @load_texture2d_float4_with_level_and_offset(<2 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_2t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 3, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, i32 -1, i32 2, i32 undef)
%data = call <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_0_0_0_2t.v2i32.i32.v2i32(
target("dx.Texture", <4 x float>, 0, 0, 0, 2) %texture,
@@ -152,9 +152,9 @@ define void @load_texture3d_float3(<3 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_v3f32_0_0_0_4t(
i32 0, i32 4, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i32 2
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 0, i32 %[[COORD0]], i32 %[[COORD1]], i32 %[[COORD2]], i32 undef, i32 undef, i32 undef)
%data = call <3 x float> @llvm.dx.resource.load.level.v3f32.tdx.Texture_v3f32_0_0_0_4t.v3i32.i32.v3i32(
target("dx.Texture", <3 x float>, 0, 0, 0, 4) %texture,
@@ -171,9 +171,9 @@ define void @load_texture3d_float3_with_level_and_offset(<3 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_v3f32_0_0_0_4t(
i32 0, i32 4, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i32 2
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 2, i32 %[[COORD0]], i32 %[[COORD1]], i32 %[[COORD2]], i32 1, i32 -2, i32 3)
%data = call <3 x float> @llvm.dx.resource.load.level.v3f32.tdx.Texture_v3f32_0_0_0_4t.v3i32.i32.v3i32(
target("dx.Texture", <3 x float>, 0, 0, 0, 4) %texture,
@@ -190,9 +190,9 @@ define void @load_texture2darray_float4(<3 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_7t(
i32 0, i32 5, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i32 2
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 0, i32 %[[COORD0]], i32 %[[COORD1]], i32 %[[COORD2]], i32 undef, i32 undef, i32 undef)
%data = call <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_0_0_0_7t.v3i32.i32.v2i32(
target("dx.Texture", <4 x float>, 0, 0, 0, 7) %texture,
@@ -209,9 +209,9 @@ define void @load_texture2darray_float4_with_level_and_offset(<3 x i32> %coords)
@llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_0_0_0_7t(
i32 0, i32 5, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i32 2
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 1, i32 %[[COORD0]], i32 %[[COORD1]], i32 %[[COORD2]], i32 -1, i32 2, i32 undef)
%data = call <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_0_0_0_7t.v3i32.i32.v2i32(
target("dx.Texture", <4 x float>, 0, 0, 0, 7) %texture,
@@ -232,8 +232,8 @@ define void @load_rwtexture2d_float4_implicit_mip(<2 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_1_0_0_2t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 undef, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, i32 undef, i32 undef, i32 undef)
%data = call <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_1_0_0_2t.v2i32.i32.v2i32(
target("dx.Texture", <4 x float>, 1, 0, 0, 2) %texture,
@@ -250,8 +250,8 @@ define void @load_rwtexture2d_float4_explicit_lod(<2 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_1_0_0_2t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 undef, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, i32 undef, i32 undef, i32 undef)
%data = call <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_1_0_0_2t.v2i32.i32.v2i32(
target("dx.Texture", <4 x float>, 1, 0, 0, 2) %texture,
@@ -268,9 +268,9 @@ define void @load_rwtexture2darray_float4(<3 x i32> %coords) {
@llvm.dx.resource.handlefrombinding.tdx.Texture_v4f32_1_0_0_7t(
i32 0, i32 0, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i32 2
; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 undef, i32 %[[COORD0]], i32 %[[COORD1]], i32 %[[COORD2]], i32 undef, i32 undef, i32 undef)
%data = call <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_1_0_0_7t.v3i32.i32.v2i32(
target("dx.Texture", <4 x float>, 1, 0, 0, 7) %texture,
@@ -280,3 +280,27 @@ define void @load_rwtexture2darray_float4(<3 x i32> %coords) {
call void @use_float4(<4 x float> %data)
ret void
}
+
+; DXIL has no vector instructions, so the scalars the coordinate vector was
+; built from are forwarded into the load rather than extracted again.
+; CHECK-LABEL: define void @load_rwtexture2darray_scalarized_coords(
+define void @load_rwtexture2darray_scalarized_coords(i32 %x, i32 %y, i32 %z) {
+ %texture = call target("dx.Texture", float, 1, 0, 0, 7)
+ @llvm.dx.resource.handlefrombinding.tdx.Texture_f32_1_0_0_7t(
+ i32 0, i32 0, i32 1, i32 0, ptr null)
+
+ %coords.0 = insertelement <3 x i32> poison, i32 %x, i32 0
+ %coords.1 = insertelement <3 x i32> %coords.0, i32 %y, i32 1
+ %coords.2 = insertelement <3 x i32> %coords.1, i32 %z, i32 2
+
+ ; CHECK-NOT: insertelement
+ ; CHECK-NOT: extractelement
+ ; CHECK: %[[LOAD:.*]] = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %{{.*}}, i32 undef, i32 %x, i32 %y, i32 %z, i32 undef, i32 undef, i32 undef)
+ %data = call float @llvm.dx.resource.load.level.f32.tdx.Texture_f32_1_0_0_7t.v3i32.i32.v2i32(
+ target("dx.Texture", float, 1, 0, 0, 7) %texture,
+ <3 x i32> %coords.2, i32 0, <2 x i32> zeroinitializer)
+
+ ; CHECK: extractvalue %dx.types.ResRet.f32 %[[LOAD]], 0
+ call void @use_float(float %data)
+ ret void
+}
diff --git a/llvm/test/CodeGen/DirectX/TextureStore.ll b/llvm/test/CodeGen/DirectX/TextureStore.ll
index c37b3f2baccd9..efaeb11620746 100644
--- a/llvm/test/CodeGen/DirectX/TextureStore.ll
+++ b/llvm/test/CodeGen/DirectX/TextureStore.ll
@@ -28,8 +28,8 @@ define void @store_texture2d_float4(<4 x float> %data, <2 x i32> %coords) {
; CHECK: %[[DATA1:.*]] = extractelement <4 x float> %data, i32 1
; CHECK: %[[DATA2:.*]] = extractelement <4 x float> %data, i32 2
; CHECK: %[[DATA3:.*]] = extractelement <4 x float> %data, i32 3
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: call void @dx.op.textureStore.f32(i32 67, %dx.types.Handle %{{.*}}, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, float %[[DATA0]], float %[[DATA1]], float %[[DATA2]], float %[[DATA3]], i8 15)
call void @llvm.dx.resource.store.texture(
target("dx.Texture", <4 x float>, 1, 0, 0, 2) %texture,
@@ -47,9 +47,9 @@ define void @store_texture3d_float4(<4 x float> %data, <3 x i32> %coords) {
; CHECK: %[[DATA1:.*]] = extractelement <4 x float> %data, i32 1
; CHECK: %[[DATA2:.*]] = extractelement <4 x float> %data, i32 2
; CHECK: %[[DATA3:.*]] = extractelement <4 x float> %data, i32 3
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i32 2
; CHECK: call void @dx.op.textureStore.f32(i32 67, %dx.types.Handle %{{.*}}, i32 %[[COORD0]], i32 %[[COORD1]], i32 %[[COORD2]], float %[[DATA0]], float %[[DATA1]], float %[[DATA2]], float %[[DATA3]], i8 15)
call void @llvm.dx.resource.store.texture(
target("dx.Texture", <4 x float>, 1, 0, 0, 4) %texture,
@@ -67,8 +67,8 @@ define void @store_texture1darray_float4(<4 x float> %data, <2 x i32> %coords) {
; CHECK: %[[DATA1:.*]] = extractelement <4 x float> %data, i32 1
; CHECK: %[[DATA2:.*]] = extractelement <4 x float> %data, i32 2
; CHECK: %[[DATA3:.*]] = extractelement <4 x float> %data, i32 3
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: call void @dx.op.textureStore.f32(i32 67, %dx.types.Handle %{{.*}}, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, float %[[DATA0]], float %[[DATA1]], float %[[DATA2]], float %[[DATA3]], i8 15)
call void @llvm.dx.resource.store.texture(
target("dx.Texture", <4 x float>, 1, 0, 0, 6) %texture,
@@ -86,9 +86,9 @@ define void @store_texture2darray_float4(<4 x float> %data, <3 x i32> %coords) {
; CHECK: %[[DATA1:.*]] = extractelement <4 x float> %data, i32 1
; CHECK: %[[DATA2:.*]] = extractelement <4 x float> %data, i32 2
; CHECK: %[[DATA3:.*]] = extractelement <4 x float> %data, i32 3
- ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i64 1
- ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i64 2
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords, i32 1
+ ; CHECK: %[[COORD2:.*]] = extractelement <3 x i32> %coords, i32 2
; CHECK: call void @dx.op.textureStore.f32(i32 67, %dx.types.Handle %{{.*}}, i32 %[[COORD0]], i32 %[[COORD1]], i32 %[[COORD2]], float %[[DATA0]], float %[[DATA1]], float %[[DATA2]], float %[[DATA3]], i8 15)
call void @llvm.dx.resource.store.texture(
target("dx.Texture", <4 x float>, 1, 0, 0, 7) %texture,
@@ -104,8 +104,8 @@ define void @store_texture2d_float(float %data, <2 x i32> %coords) {
%texture = call target("dx.Texture", float, 1, 0, 0, 2)
@llvm.dx.resource.handlefrombinding(i32 0, i32 5, i32 1, i32 0, ptr null)
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: call void @dx.op.textureStore.f32(i32 67, %dx.types.Handle %{{.*}}, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, float %data, float %data, float %data, float %data, i8 15)
call void @llvm.dx.resource.store.texture(
target("dx.Texture", float, 1, 0, 0, 2) %texture,
@@ -123,8 +123,8 @@ define void @store_texture2d_int3(<3 x i32> %data, <2 x i32> %coords) {
; CHECK: %[[DATA0:.*]] = extractelement <3 x i32> %data, i32 0
; CHECK: %[[DATA1:.*]] = extractelement <3 x i32> %data, i32 1
; CHECK: %[[DATA2:.*]] = extractelement <3 x i32> %data, i32 2
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: call void @dx.op.textureStore.i32(i32 67, %dx.types.Handle %{{.*}}, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, i32 %[[DATA0]], i32 %[[DATA1]], i32 %[[DATA2]], i32 %[[DATA0]], i8 15)
call void @llvm.dx.resource.store.texture(
target("dx.Texture", <3 x i32>, 1, 0, 1, 2) %texture,
@@ -142,8 +142,8 @@ define void @store_texture2d_half4(<4 x half> %data, <2 x i32> %coords) {
; CHECK: %[[DATA1:.*]] = extractelement <4 x half> %data, i32 1
; CHECK: %[[DATA2:.*]] = extractelement <4 x half> %data, i32 2
; CHECK: %[[DATA3:.*]] = extractelement <4 x half> %data, i32 3
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: call void @dx.op.textureStore.f16(i32 67, %dx.types.Handle %{{.*}}, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, half %[[DATA0]], half %[[DATA1]], half %[[DATA2]], half %[[DATA3]], i8 15)
call void @llvm.dx.resource.store.texture(
target("dx.Texture", <4 x half>, 1, 0, 0, 2) %texture,
@@ -165,8 +165,8 @@ define void @store_texture2d_scalarized(float %x, float %y, float %z, float %w,
%vec.3 = insertelement <4 x float> %vec.2, float %w, i32 3
; CHECK-NOT: insertelement
- ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i64 0
- ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i64 1
+ ; CHECK: %[[COORD0:.*]] = extractelement <2 x i32> %coords, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <2 x i32> %coords, i32 1
; CHECK: call void @dx.op.textureStore.f32(i32 67, %dx.types.Handle %{{.*}}, i32 %[[COORD0]], i32 %[[COORD1]], i32 undef, float %x, float %y, float %z, float %w, i8 15)
call void @llvm.dx.resource.store.texture(
target("dx.Texture", <4 x float>, 1, 0, 0, 2) %texture,
@@ -174,3 +174,66 @@ define void @store_texture2d_scalarized(float %x, float %y, float %z, float %w,
ret void
}
+
+; DXIL has no vector instructions, so the scalars the coordinate vector was
+; built from are forwarded into the store rather than extracted again.
+; CHECK-LABEL: define void @store_texture2darray_scalarized_coords(
+define void @store_texture2darray_scalarized_coords(float %data, i32 %x, i32 %y, i32 %z) {
+ %texture = call target("dx.Texture", float, 1, 0, 0, 7)
+ @llvm.dx.resource.handlefrombinding(i32 0, i32 9, i32 1, i32 0, ptr null)
+
+ %coords.0 = insertelement <3 x i32> poison, i32 %x, i32 0
+ %coords.1 = insertelement <3 x i32> %coords.0, i32 %y, i32 1
+ %coords.2 = insertelement <3 x i32> %coords.1, i32 %z, i32 2
+
+ ; CHECK-NOT: insertelement
+ ; CHECK-NOT: extractelement
+ ; CHECK: call void @dx.op.textureStore.f32(i32 67, %dx.types.Handle %{{.*}}, i32 %x, i32 %y, i32 %z, float %data, float %data, float %data, float %data, i8 15)
+ call void @llvm.dx.resource.store.texture(
+ target("dx.Texture", float, 1, 0, 0, 7) %texture,
+ <3 x i32> %coords.2, float %data)
+
+ ; CHECK-NOT: insertelement
+ ; CHECK: ret void
+ ret void
+}
+
+; Coordinates that don't come from an insertelement still have to be extracted.
+; CHECK-LABEL: define void @store_texture2darray_partial_coords(
+define void @store_texture2darray_partial_coords(float %data, <3 x i32> %coords, i32 %z) {
+ %texture = call target("dx.Texture", float, 1, 0, 0, 7)
+ @llvm.dx.resource.handlefrombinding(i32 0, i32 10, i32 1, i32 0, ptr null)
+
+ %coords.z = insertelement <3 x i32> %coords, i32 %z, i32 2
+
+ ; CHECK: %[[COORD0:.*]] = extractelement <3 x i32> %coords.z, i32 0
+ ; CHECK: %[[COORD1:.*]] = extractelement <3 x i32> %coords.z, i32 1
+ ; CHECK: call void @dx.op.textureStore.f32(i32 67, %dx.types.Handle %{{.*}}, i32 %[[COORD0]], i32 %[[COORD1]], i32 %z, float %data, float %data, float %data, float %data, i8 15)
+ call void @llvm.dx.resource.store.texture(
+ target("dx.Texture", float, 1, 0, 0, 7) %texture,
+ <3 x i32> %coords.z, float %data)
+
+ ret void
+}
+
+; An index can be inserted more than once; the outermost insert is the live
+; value for that component.
+; CHECK-LABEL: define void @store_texture2d_repeated_index(
+define void @store_texture2d_repeated_index(float %x, float %y, float %z, float %w,
+ float %live, <2 x i32> %coords) {
+ %texture = call target("dx.Texture", <4 x float>, 1, 0, 0, 2)
+ @llvm.dx.resource.handlefrombinding(i32 0, i32 11, i32 1, i32 0, ptr null)
+
+ %vec.0 = insertelement <4 x float> poison, float %x, i32 0
+ %vec.1 = insertelement <4 x float> %vec.0, float %y, i32 1
+ %vec.2 = insertelement <4 x float> %vec.1, float %z, i32 2
+ %vec.3 = insertelement <4 x float> %vec.2, float %w, i32 3
+ %vec.4 = insertelement <4 x float> %vec.3, float %live, i32 0
+
+ ; CHECK: call void @dx.op.textureStore.f32(i32 67, %dx.types.Handle %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 undef, float %live, float %y, float %z, float %w, i8 15)
+ call void @llvm.dx.resource.store.texture(
+ target("dx.Texture", <4 x float>, 1, 0, 0, 2) %texture,
+ <2 x i32> %coords, <4 x float> %vec.4)
+
+ ret void
+}
>From 33ec9468566429d18b69f3cf202d5b0dafac0263 Mon Sep 17 00:00:00 2001
From: Deric Cheung <cheung.deric at gmail.com>
Date: Fri, 11 Sep 2026 15:57:10 -0700
Subject: [PATCH 2/2] touch-up tests
---
llvm/test/CodeGen/DirectX/SampleGrad.ll | 2 +-
llvm/test/CodeGen/DirectX/TextureStore.ll | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/test/CodeGen/DirectX/SampleGrad.ll b/llvm/test/CodeGen/DirectX/SampleGrad.ll
index 37ec29d03a570..f1fd44cbbd0b7 100644
--- a/llvm/test/CodeGen/DirectX/SampleGrad.ll
+++ b/llvm/test/CodeGen/DirectX/SampleGrad.ll
@@ -358,7 +358,7 @@ define void @sample_grad_texture2d_scalarized(float %u, float %v, float %ddxu,
%ddy.1 = insertelement <2 x float> %ddy.0, float %ddyv, i32 1
; CHECK-NOT: insertelement
- ; CHECK-NOT: extractelement <2 x float>
+ ; CHECK-NOT: extractelement
; CHECK: %[[SAMPLE:.*]] = call %dx.types.ResRet.f32
; CHECK-SAME: @dx.op.sampleGrad.f32(i32 63,
; CHECK-SAME: %dx.types.Handle %{{[^,]*}},
diff --git a/llvm/test/CodeGen/DirectX/TextureStore.ll b/llvm/test/CodeGen/DirectX/TextureStore.ll
index efaeb11620746..7e52ea3f61c47 100644
--- a/llvm/test/CodeGen/DirectX/TextureStore.ll
+++ b/llvm/test/CodeGen/DirectX/TextureStore.ll
@@ -193,7 +193,6 @@ define void @store_texture2darray_scalarized_coords(float %data, i32 %x, i32 %y,
target("dx.Texture", float, 1, 0, 0, 7) %texture,
<3 x i32> %coords.2, float %data)
- ; CHECK-NOT: insertelement
; CHECK: ret void
ret void
}
More information about the llvm-commits
mailing list