mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-22 16:10:36 +02:00
gallivm: obey clarified shift behavior
llvm shifts are undefined for shift counts exceeding (or matching) bit width, so need to apply a mask for the tgsi shift instructions. v2: only use mask for the tgsi shift instructions, not for the build shift helpers. None of the internal callers need this behavior, and while llvm can optimize away the masking for constants there are legitimate cases where it might not be able to do so even if we know that shift count must be smaller than type width (currently all such callers do not use the build shift helpers). Reviewed-by: Zack Rusin <zackr@vmware.com> Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
This commit is contained in:
parent
7a72bef47e
commit
e7ed70a52e
2 changed files with 24 additions and 8 deletions
|
|
@ -168,6 +168,7 @@ lp_build_not(struct lp_build_context *bld, LLVMValueRef a)
|
|||
|
||||
/**
|
||||
* Shift left.
|
||||
* Result is undefined if the shift count is not smaller than the type width.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_shl(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
|
||||
|
|
@ -189,6 +190,7 @@ lp_build_shl(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
|
|||
|
||||
/**
|
||||
* Shift right.
|
||||
* Result is undefined if the shift count is not smaller than the type width.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_shr(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
|
||||
|
|
@ -214,23 +216,25 @@ lp_build_shr(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
|
|||
|
||||
/**
|
||||
* Shift left with immediate.
|
||||
* The immediate shift count must be smaller than the type width.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_shl_imm(struct lp_build_context *bld, LLVMValueRef a, unsigned imm)
|
||||
{
|
||||
LLVMValueRef b = lp_build_const_int_vec(bld->gallivm, bld->type, imm);
|
||||
assert(imm <= bld->type.width);
|
||||
assert(imm < bld->type.width);
|
||||
return lp_build_shl(bld, a, b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shift right with immediate.
|
||||
* The immediate shift count must be smaller than the type width.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_shr_imm(struct lp_build_context *bld, LLVMValueRef a, unsigned imm)
|
||||
{
|
||||
LLVMValueRef b = lp_build_const_int_vec(bld->gallivm, bld->type, imm);
|
||||
assert(imm <= bld->type.width);
|
||||
assert(imm < bld->type.width);
|
||||
return lp_build_shr(bld, a, b);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1203,8 +1203,12 @@ ishr_emit_cpu(
|
|||
struct lp_build_tgsi_context * bld_base,
|
||||
struct lp_build_emit_data * emit_data)
|
||||
{
|
||||
emit_data->output[emit_data->chan] = lp_build_shr(&bld_base->int_bld,
|
||||
emit_data->args[0], emit_data->args[1]);
|
||||
struct lp_build_context *int_bld = &bld_base->int_bld;
|
||||
LLVMValueRef mask = lp_build_const_vec(int_bld->gallivm, int_bld->type,
|
||||
int_bld->type.width - 1);
|
||||
LLVMValueRef masked_count = lp_build_and(int_bld, emit_data->args[1], mask);
|
||||
emit_data->output[emit_data->chan] = lp_build_shr(int_bld, emit_data->args[0],
|
||||
masked_count);
|
||||
}
|
||||
|
||||
/* TGSI_OPCODE_ISLT (CPU Only) */
|
||||
|
|
@ -1439,8 +1443,12 @@ shl_emit_cpu(
|
|||
struct lp_build_tgsi_context * bld_base,
|
||||
struct lp_build_emit_data * emit_data)
|
||||
{
|
||||
emit_data->output[emit_data->chan] = lp_build_shl(&bld_base->uint_bld,
|
||||
emit_data->args[0], emit_data->args[1]);
|
||||
struct lp_build_context *uint_bld = &bld_base->uint_bld;
|
||||
LLVMValueRef mask = lp_build_const_vec(uint_bld->gallivm, uint_bld->type,
|
||||
uint_bld->type.width - 1);
|
||||
LLVMValueRef masked_count = lp_build_and(uint_bld, emit_data->args[1], mask);
|
||||
emit_data->output[emit_data->chan] = lp_build_shl(uint_bld, emit_data->args[0],
|
||||
masked_count);
|
||||
}
|
||||
|
||||
/* TGSI_OPCODE_SIN (CPU Only) */
|
||||
|
|
@ -1647,8 +1655,12 @@ ushr_emit_cpu(
|
|||
struct lp_build_tgsi_context * bld_base,
|
||||
struct lp_build_emit_data * emit_data)
|
||||
{
|
||||
emit_data->output[emit_data->chan] = lp_build_shr(&bld_base->uint_bld,
|
||||
emit_data->args[0], emit_data->args[1]);
|
||||
struct lp_build_context *uint_bld = &bld_base->uint_bld;
|
||||
LLVMValueRef mask = lp_build_const_vec(uint_bld->gallivm, uint_bld->type,
|
||||
uint_bld->type.width - 1);
|
||||
LLVMValueRef masked_count = lp_build_and(uint_bld, emit_data->args[1], mask);
|
||||
emit_data->output[emit_data->chan] = lp_build_shr(uint_bld, emit_data->args[0],
|
||||
masked_count);
|
||||
}
|
||||
|
||||
/* TGSI_OPCODE_ISLT (CPU Only) */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue