ac/llvm: add missing optimization barrier for 64-bit readlanes

Otherwise, LLVM optimizes it but it's actually incorrect.

Fixes: 0f45d4dc2b ("ac: add ac_build_readlane without optimization barrier")
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3585>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3585>
(cherry picked from commit cc320ef9af)
This commit is contained in:
Samuel Pitoiset 2020-01-27 13:42:11 +01:00 committed by Dylan Baker
parent 1b2c982166
commit b35d45f21a
2 changed files with 47 additions and 34 deletions

View file

@ -607,7 +607,7 @@
"description": "ac/llvm: add missing optimization barrier for 64-bit readlanes",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"master_sha": null,
"because_sha": "0f45d4dc2b15e137346e1e3f064a24302e1c9048"
},

View file

@ -3611,11 +3611,15 @@ void ac_apply_fmask_to_sample(struct ac_llvm_context *ac, LLVMValueRef fmask,
}
static LLVMValueRef
_ac_build_readlane(struct ac_llvm_context *ctx, LLVMValueRef src, LLVMValueRef lane)
_ac_build_readlane(struct ac_llvm_context *ctx, LLVMValueRef src,
LLVMValueRef lane, bool with_opt_barrier)
{
LLVMTypeRef type = LLVMTypeOf(src);
LLVMValueRef result;
if (with_opt_barrier)
ac_build_optimization_barrier(ctx, &src);
src = LLVMBuildZExt(ctx->builder, src, ctx->i32, "");
if (lane)
lane = LLVMBuildZExt(ctx->builder, lane, ctx->i32, "");
@ -3630,6 +3634,43 @@ _ac_build_readlane(struct ac_llvm_context *ctx, LLVMValueRef src, LLVMValueRef l
return LLVMBuildTrunc(ctx->builder, result, type, "");
}
static LLVMValueRef
ac_build_readlane_common(struct ac_llvm_context *ctx,
LLVMValueRef src, LLVMValueRef lane,
bool with_opt_barrier)
{
LLVMTypeRef src_type = LLVMTypeOf(src);
src = ac_to_integer(ctx, src);
unsigned bits = LLVMGetIntTypeWidth(LLVMTypeOf(src));
LLVMValueRef ret;
if (bits > 32) {
assert(bits % 32 == 0);
LLVMTypeRef vec_type = LLVMVectorType(ctx->i32, bits / 32);
LLVMValueRef src_vector =
LLVMBuildBitCast(ctx->builder, src, vec_type, "");
ret = LLVMGetUndef(vec_type);
for (unsigned i = 0; i < bits / 32; i++) {
LLVMValueRef ret_comp;
src = LLVMBuildExtractElement(ctx->builder, src_vector,
LLVMConstInt(ctx->i32, i, 0), "");
ret_comp = _ac_build_readlane(ctx, src, lane,
with_opt_barrier);
ret = LLVMBuildInsertElement(ctx->builder, ret, ret_comp,
LLVMConstInt(ctx->i32, i, 0), "");
}
} else {
ret = _ac_build_readlane(ctx, src, lane, with_opt_barrier);
}
if (LLVMGetTypeKind(src_type) == LLVMPointerTypeKind)
return LLVMBuildIntToPtr(ctx->builder, ret, src_type, "");
return LLVMBuildBitCast(ctx->builder, ret, src_type, "");
}
/**
* Builds the "llvm.amdgcn.readlane" or "llvm.amdgcn.readfirstlane" intrinsic.
*
@ -3642,44 +3683,16 @@ _ac_build_readlane(struct ac_llvm_context *ctx, LLVMValueRef src, LLVMValueRef l
* @return value of the lane
*/
LLVMValueRef ac_build_readlane_no_opt_barrier(struct ac_llvm_context *ctx,
LLVMValueRef src, LLVMValueRef lane)
LLVMValueRef src, LLVMValueRef lane)
{
unsigned bits = LLVMGetIntTypeWidth(LLVMTypeOf(src));
LLVMValueRef ret;
if (bits > 32) {
assert(bits % 32 == 0);
LLVMTypeRef vec_type = LLVMVectorType(ctx->i32, bits / 32);
LLVMValueRef src_vector =
LLVMBuildBitCast(ctx->builder, src, vec_type, "");
ret = LLVMGetUndef(vec_type);
for (unsigned i = 0; i < bits / 32; i++) {
src = LLVMBuildExtractElement(ctx->builder, src_vector,
LLVMConstInt(ctx->i32, i, 0), "");
LLVMValueRef ret_comp = _ac_build_readlane(ctx, src, lane);
ret = LLVMBuildInsertElement(ctx->builder, ret, ret_comp,
LLVMConstInt(ctx->i32, i, 0), "");
}
} else {
ret = _ac_build_readlane(ctx, src, lane);
}
return ret;
return ac_build_readlane_common(ctx, src, lane, false);
}
LLVMValueRef
ac_build_readlane(struct ac_llvm_context *ctx, LLVMValueRef src, LLVMValueRef lane)
{
LLVMTypeRef src_type = LLVMTypeOf(src);
src = ac_to_integer(ctx, src);
LLVMValueRef ret;
ac_build_optimization_barrier(ctx, &src);
ret = ac_build_readlane_no_opt_barrier(ctx, src, lane);
if (LLVMGetTypeKind(src_type) == LLVMPointerTypeKind)
return LLVMBuildIntToPtr(ctx->builder, ret, src_type, "");
return LLVMBuildBitCast(ctx->builder, ret, src_type, "");
return ac_build_readlane_common(ctx, src, lane, true);
}
LLVMValueRef