Fix assertion on splat of groupshared scalar (#6930)

When splatting a groupshared scalar, we would trip an "Invalid
constantexpr cast!" assertion. This would happen while evaluating the
ImplicitCastExpr to turn the groupshared scalar into a vector because
the scalar expression was in a different address space (groupshared) vs
the target vector (local). The fix is to ensure that when looking up the
vector member expression, insert an lvalue-to-rvalue cast if necessary;
i.e. when a swizzle contains duplicate elements.
This commit is contained in:
Antonio Maiorano 2024-09-24 21:14:38 -04:00 коммит произвёл GitHub
Родитель d9a5e97d04
Коммит 0372fb792d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
4 изменённых файлов: 38 добавлений и 12 удалений

Просмотреть файл

@ -8444,8 +8444,19 @@ ExprResult HLSLExternalSource::LookupVectorMemberExprForHLSL(
ExprValueKind VK = positions.ContainsDuplicateElements()
? VK_RValue
: (IsArrow ? VK_LValue : BaseExpr.getValueKind());
HLSLVectorElementExpr *vectorExpr = new (m_context) HLSLVectorElementExpr(
resultType, VK, &BaseExpr, *member, MemberLoc, positions);
Expr *E = &BaseExpr;
// Insert an lvalue-to-rvalue cast if necessary
if (BaseExpr.getValueKind() == VK_LValue && VK == VK_RValue) {
// Remove qualifiers from result type and cast target type
resultType = resultType.getUnqualifiedType();
auto targetType = E->getType().getUnqualifiedType();
E = ImplicitCastExpr::Create(*m_context, targetType,
CastKind::CK_LValueToRValue, E, nullptr,
VK_RValue);
}
HLSLVectorElementExpr *vectorExpr = new (m_context)
HLSLVectorElementExpr(resultType, VK, E, *member, MemberLoc, positions);
return vectorExpr;
}

Просмотреть файл

@ -0,0 +1,15 @@
// RUN: %dxc -E main -T cs_6_0 -fcgl %s | FileCheck %s
// Validate that when swizzling requires an r-value (i.e. duplicate elements), that the result is stored to
// and loaded from a temporary.
// CHECK: store <1 x i32> %splat.splat, <1 x i32>* %tmp
// CHECK-NEXT: %1 = load <1 x i32>, <1 x i32>* %tmp
// CHECK-NEXT: %2 = shufflevector <1 x i32> %1, <1 x i32> undef, <4 x i32> zeroinitializer
// CHECK-NEXT: store <4 x i32> %2, <4 x i32>* %x
groupshared int a;
[numthreads(64, 1, 1)]
void main() {
a = 123;
int4 x = (a).xxxx;
}

Просмотреть файл

@ -118,18 +118,18 @@ void main() {
// Keep lhs.1
// So final selectors to write to lhs.(0, 1, 2, 3): 6, 1, 4, 5
// CHECK-NEXT: [[v22:%[0-9]+]] = OpLoad %v2float %v2f
// CHECK-NEXT: [[vs15:%[0-9]+]] = OpVectorShuffle %v3float [[v22]] [[v22]] 0 1 0
// CHECK-NEXT: [[vs15:%[0-9]+]] = OpVectorShuffle %v2float [[v22]] [[v22]] 1 0
// CHECK-NEXT: [[vs16:%[0-9]+]] = OpVectorShuffle %v3float [[vs15]] [[vs15]] 1 0 1
// CHECK-NEXT: [[v23:%[0-9]+]] = OpLoad %v4float %v4f2
// CHECK-NEXT: [[vs16:%[0-9]+]] = OpVectorShuffle %v4float [[v23]] [[vs15]] 6 1 4 5
// CHECK-NEXT: OpStore %v4f2 [[vs16]]
// CHECK-NEXT: [[vs17:%[0-9]+]] = OpVectorShuffle %v4float [[v23]] [[vs16]] 6 1 4 5
// CHECK-NEXT: OpStore %v4f2 [[vs17]]
v4f2.wzx.grb = v2f.gr.yxy; // select more than original, write to a part
// CHECK-NEXT: [[v24:%[0-9]+]] = OpLoad %v4float %v4f1
// CHECK-NEXT: OpStore %v4f2 [[v24]]
v4f2.wzyx.abgr.xywz.rgab = v4f1.xyzw.xyzw.rgab.rgab; // from original vector to original vector
// CHECK-NEXT: [[v24_0:%[0-9]+]] = OpAccessChain %_ptr_Function_float %v4f1 %int_2
// CHECK-NEXT: [[ce1:%[0-9]+]] = OpLoad %float [[v24_0]]
// CHECK-NEXT: [[v24_0:%[0-9]+]] = OpLoad %v4float %v4f1
// CHECK-NEXT: [[ce1:%[0-9]+]] = OpCompositeExtract %float [[v24_0]] 2
// CHECK-NEXT: [[ac4:%[0-9]+]] = OpAccessChain %_ptr_Function_float %v4f2 %int_1
// CHECK-NEXT: OpStore [[ac4]] [[ce1]]
v4f2.wzyx.zy.x = v4f1.xzyx.y.x; // from one element (rvalue) to one element (lvalue)

Просмотреть файл

@ -43,11 +43,11 @@ void main(float4 input: INPUT) {
// Selecting from resources
// CHECK: [[fptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_v4float %PerFrame %int_0 %uint_5 %int_0
// CHECK-NEXT: [[elem:%[0-9]+]] = OpAccessChain %_ptr_Uniform_float [[fptr]] %int_3
// CHECK-NEXT: {{%[0-9]+}} = OpLoad %float [[elem]]
// CHECK-NEXT: [[val:%[0-9]+]] = OpLoad %v4float [[fptr]]
// CHECK-NEXT: {{%[0-9]+}} = OpCompositeExtract %float [[val]] 3
v4f = input * PerFrame[5].f.www.r;
// CHECK: [[fptr_0:%[0-9]+]] = OpAccessChain %_ptr_Uniform_v4float %PerFrame %int_0 %uint_6 %int_0
// CHECK-NEXT: [[elem_0:%[0-9]+]] = OpAccessChain %_ptr_Uniform_float [[fptr_0]] %int_2
// CHECK-NEXT: {{%[0-9]+}} = OpLoad %float [[elem_0]]
// CHECK-NEXT: [[val_0:%[0-9]+]] = OpLoad %v4float [[fptr_0]]
// CHECK-NEXT: {{%[0-9]+}} = OpCompositeExtract %float [[val_0]] 2
sf = PerFrame[6].f.zzz.r * input.y;
}