glsl: Remove int64 div/mod lowering.

Most drivers that can expose GL4 were claiming the cap anyway (llvmpipe,
softpipe, zink, iris, nvc0, radeonsi, r600, freedreno, d3d12), and just
doing lowering in NIR if nessary.

crocus was only claiming the cap for gen8, but the backend compiler
enables NIR lowering regardless.

svga is the only other GL4 driver that didn't set it, and we can just set
the NIR lowering flag.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Acked-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25777>
This commit is contained in:
Eric Anholt 2023-10-18 08:18:46 +02:00 committed by Marge Bot
parent bd546f9e54
commit b1b0ebba1e
25 changed files with 1 additions and 2150 deletions

View file

@ -429,8 +429,6 @@ The integer capabilities:
* ``PIPE_CAP_DOUBLES``: Whether double precision floating-point operations
are supported.
* ``PIPE_CAP_INT64``: Whether 64-bit integer operations are supported.
* ``PIPE_CAP_INT64_DIVMOD``: Whether 64-bit integer division/modulo
operations are supported.
* ``PIPE_CAP_TGSI_TEX_TXF_LZ``: Whether TEX_LZ and TXF_LZ opcodes are
supported.
* ``PIPE_CAP_SHADER_CLOCK``: Whether the CLOCK opcode is supported.

View file

@ -827,12 +827,6 @@ vote_or_v460_desktop(const _mesa_glsl_parse_state *state)
return state->EXT_shader_group_vote_enable || state->ARB_shader_group_vote_enable || v460_desktop(state);
}
static bool
integer_functions_supported(const _mesa_glsl_parse_state *state)
{
return state->extensions->MESA_shader_integer_functions;
}
static bool
NV_shader_atomic_float_supported(const _mesa_glsl_parse_state *state)
{
@ -5193,22 +5187,6 @@ builtin_builder::create_builtins()
add_function("helperInvocationEXT", _helper_invocation(), NULL);
add_function("__builtin_idiv64",
generate_ir::idiv64(mem_ctx, integer_functions_supported),
NULL);
add_function("__builtin_imod64",
generate_ir::imod64(mem_ctx, integer_functions_supported),
NULL);
add_function("__builtin_udiv64",
generate_ir::udiv64(mem_ctx, integer_functions_supported),
NULL);
add_function("__builtin_umod64",
generate_ir::umod64(mem_ctx, integer_functions_supported),
NULL);
add_function("countLeadingZeros",
_countLeadingZeros(shader_integer_functions2,
glsl_type::uint_type),

File diff suppressed because it is too large Load diff

View file

@ -1,33 +0,0 @@
/*
* Copyright © 2016 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "ir_builder.h"
#include "builtin_functions.h"
#include "program/prog_instruction.h" /* for SWIZZLE_X, &c. */
using namespace ir_builder;
namespace generate_ir {
#include "builtin_int64.h"
}

View file

@ -1,99 +0,0 @@
/* Compile with:
*
* glsl_compiler --version 400 --dump-builder int64.glsl > builtin_int64.h
*
* Version 4.00+ is required for umulExtended.
*/
#version 400
#extension GL_ARB_gpu_shader_int64: require
#extension GL_ARB_shading_language_420pack: require
uvec4
udivmod64(uvec2 n, uvec2 d)
{
uvec2 quot = uvec2(0U, 0U);
int log2_denom = findMSB(d.y) + 32;
/* If the upper 32 bits of denom are non-zero, it is impossible for shifts
* greater than 32 bits to occur. If the upper 32 bits of the numerator
* are zero, it is impossible for (denom << [63, 32]) <= numer unless
* denom == 0.
*/
if (d.y == 0 && n.y >= d.x) {
log2_denom = findMSB(d.x);
/* Since the upper 32 bits of denom are zero, log2_denom <= 31 and we
* don't have to compare log2_denom inside the loop as is done in the
* general case (below).
*/
for (int i = 31; i >= 1; i--) {
if (log2_denom <= 31 - i && (d.x << i) <= n.y) {
n.y -= d.x << i;
quot.y |= 1U << i;
}
}
/* log2_denom is always <= 31, so manually peel the last loop
* iteration.
*/
if (d.x <= n.y) {
n.y -= d.x;
quot.y |= 1U;
}
}
uint64_t d64 = packUint2x32(d);
uint64_t n64 = packUint2x32(n);
for (int i = 31; i >= 1; i--) {
if (log2_denom <= 63 - i && (d64 << i) <= n64) {
n64 -= d64 << i;
quot.x |= 1U << i;
}
}
/* log2_denom is always <= 63, so manually peel the last loop
* iteration.
*/
if (d64 <= n64) {
n64 -= d64;
quot.x |= 1U;
}
return uvec4(quot, unpackUint2x32(n64));
}
uvec2
udiv64(uvec2 n, uvec2 d)
{
return udivmod64(n, d).xy;
}
ivec2
idiv64(ivec2 _n, ivec2 _d)
{
const bool negate = (_n.y < 0) != (_d.y < 0);
uvec2 n = unpackUint2x32(uint64_t(abs(packInt2x32(_n))));
uvec2 d = unpackUint2x32(uint64_t(abs(packInt2x32(_d))));
uvec2 quot = udivmod64(n, d).xy;
return negate ? unpackInt2x32(-int64_t(packUint2x32(quot))) : ivec2(quot);
}
uvec2
umod64(uvec2 n, uvec2 d)
{
return udivmod64(n, d).zw;
}
ivec2
imod64(ivec2 _n, ivec2 _d)
{
const bool negate = (_n.y < 0) != (_d.y < 0);
uvec2 n = unpackUint2x32(uint64_t(abs(packInt2x32(_n))));
uvec2 d = unpackUint2x32(uint64_t(abs(packInt2x32(_d))));
uvec2 rem = udivmod64(n, d).zw;
return negate ? unpackInt2x32(-int64_t(packUint2x32(rem))) : ivec2(rem);
}

View file

@ -33,10 +33,6 @@
struct gl_linked_shader;
struct gl_shader_program;
/* Operations for lower_64bit_integer_instructions() */
#define DIV64 (1U << 0)
#define MOD64 (1U << 1)
bool do_common_optimization(exec_list *ir, bool linked,
const struct gl_shader_compiler_options *options,
bool native_integers);
@ -78,9 +74,6 @@ bool propagate_invariance(exec_list *instructions);
namespace ir_builder { class ir_factory; };
bool lower_64bit_integer_instructions(exec_list *instructions,
unsigned what_to_lower);
void lower_precision(const struct gl_shader_compiler_options *options,
exec_list *instructions);

View file

@ -1,379 +0,0 @@
/*
* Copyright © 2016 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* \file lower_int64.cpp
*
* Lower 64-bit operations to 32-bit operations. Each 64-bit value is lowered
* to a uvec2. For each operation that can be lowered, there is a function
* called __builtin_foo with the same number of parameters that takes uvec2
* sources and produces uvec2 results. An operation like
*
* uint64_t(x) / uint64_t(y)
*
* becomes
*
* packUint2x32(__builtin_udiv64(unpackUint2x32(x), unpackUint2x32(y)));
*/
#include "main/macros.h"
#include "compiler/glsl_types.h"
#include "ir.h"
#include "ir_rvalue_visitor.h"
#include "ir_builder.h"
#include "ir_optimization.h"
#include "util/hash_table.h"
#include "builtin_functions.h"
typedef ir_function_signature *(*function_generator)(void *mem_ctx,
builtin_available_predicate avail);
using namespace ir_builder;
namespace lower_64bit {
void expand_source(ir_factory &, ir_rvalue *val, ir_variable **expanded_src);
ir_dereference_variable *compact_destination(ir_factory &,
const glsl_type *type,
ir_variable *result[4]);
ir_rvalue *lower_op_to_function_call(ir_instruction *base_ir,
ir_expression *ir,
ir_function_signature *callee);
};
using namespace lower_64bit;
namespace {
class lower_64bit_visitor : public ir_rvalue_visitor {
public:
lower_64bit_visitor(void *mem_ctx, exec_list *instructions, unsigned lower)
: progress(false), lower(lower),
function_list(), added_functions(&function_list, mem_ctx)
{
functions = _mesa_hash_table_create(mem_ctx,
_mesa_hash_string,
_mesa_key_string_equal);
foreach_in_list(ir_instruction, node, instructions) {
ir_function *const f = node->as_function();
if (f == NULL || strncmp(f->name, "__builtin_", 10) != 0)
continue;
add_function(f);
}
}
~lower_64bit_visitor()
{
_mesa_hash_table_destroy(functions, NULL);
}
void handle_rvalue(ir_rvalue **rvalue);
void add_function(ir_function *f)
{
_mesa_hash_table_insert(functions, f->name, f);
}
ir_function *find_function(const char *name)
{
struct hash_entry *const entry =
_mesa_hash_table_search(functions, name);
return entry != NULL ? (ir_function *) entry->data : NULL;
}
bool progress;
private:
unsigned lower; /** Bitfield of which operations to lower */
/** Hashtable containing all of the known functions in the IR */
struct hash_table *functions;
public:
exec_list function_list;
private:
ir_factory added_functions;
ir_rvalue *handle_op(ir_expression *ir, const char *function_name,
function_generator generator);
};
} /* anonymous namespace */
/**
* Determine if a particular type of lowering should occur
*/
#define lowering(x) (this->lower & x)
bool
lower_64bit_integer_instructions(exec_list *instructions,
unsigned what_to_lower)
{
if (instructions->is_empty())
return false;
ir_instruction *first_inst = (ir_instruction *) instructions->get_head_raw();
void *const mem_ctx = ralloc_parent(first_inst);
lower_64bit_visitor v(mem_ctx, instructions, what_to_lower);
visit_list_elements(&v, instructions);
if (v.progress && !v.function_list.is_empty()) {
/* Move all of the nodes from function_list to the head if the incoming
* instruction list.
*/
exec_node *const after = &instructions->head_sentinel;
exec_node *const before = instructions->head_sentinel.next;
exec_node *const head = v.function_list.head_sentinel.next;
exec_node *const tail = v.function_list.tail_sentinel.prev;
before->next = head;
head->prev = before;
after->prev = tail;
tail->next = after;
}
return v.progress;
}
/**
* Expand individual 64-bit values to uvec2 values
*
* Each operation is in one of a few forms.
*
* vector op vector
* vector op scalar
* scalar op vector
* scalar op scalar
*
* In the 'vector op vector' case, the two vectors must have the same size.
* In a way, the 'scalar op scalar' form is special case of the 'vector op
* vector' form.
*
* This method generates a new set of uvec2 values for each element of a
* single operand. If the operand is a scalar, the uvec2 is replicated
* multiple times. A value like
*
* u64vec3(a) + u64vec3(b)
*
* becomes
*
* u64vec3 tmp0 = u64vec3(a) + u64vec3(b);
* uvec2 tmp1 = unpackUint2x32(tmp0.x);
* uvec2 tmp2 = unpackUint2x32(tmp0.y);
* uvec2 tmp3 = unpackUint2x32(tmp0.z);
*
* and the returned operands array contains ir_variable pointers to
*
* { tmp1, tmp2, tmp3, tmp1 }
*/
void
lower_64bit::expand_source(ir_factory &body,
ir_rvalue *val,
ir_variable **expanded_src)
{
assert(val->type->is_integer_64());
ir_variable *const temp = body.make_temp(val->type, "tmp");
body.emit(assign(temp, val));
const ir_expression_operation unpack_opcode =
val->type->base_type == GLSL_TYPE_UINT64
? ir_unop_unpack_uint_2x32 : ir_unop_unpack_int_2x32;
const glsl_type *const type =
val->type->base_type == GLSL_TYPE_UINT64
? glsl_type::uvec2_type : glsl_type::ivec2_type;
unsigned i;
for (i = 0; i < val->type->vector_elements; i++) {
expanded_src[i] = body.make_temp(type, "expanded_64bit_source");
body.emit(assign(expanded_src[i],
expr(unpack_opcode, swizzle(temp, i, 1))));
}
for (/* empty */; i < 4; i++)
expanded_src[i] = expanded_src[0];
}
/**
* Convert a series of uvec2 results into a single 64-bit integer vector
*/
ir_dereference_variable *
lower_64bit::compact_destination(ir_factory &body,
const glsl_type *type,
ir_variable *result[4])
{
const ir_expression_operation pack_opcode =
type->base_type == GLSL_TYPE_UINT64
? ir_unop_pack_uint_2x32 : ir_unop_pack_int_2x32;
ir_variable *const compacted_result =
body.make_temp(type, "compacted_64bit_result");
for (unsigned i = 0; i < type->vector_elements; i++) {
body.emit(assign(compacted_result,
expr(pack_opcode, result[i]),
1U << i));
}
void *const mem_ctx = ralloc_parent(compacted_result);
return new(mem_ctx) ir_dereference_variable(compacted_result);
}
ir_rvalue *
lower_64bit::lower_op_to_function_call(ir_instruction *base_ir,
ir_expression *ir,
ir_function_signature *callee)
{
const unsigned num_operands = ir->num_operands;
ir_variable *src[4][4];
ir_variable *dst[4];
void *const mem_ctx = ralloc_parent(ir);
exec_list instructions;
unsigned source_components = 0;
const glsl_type *const result_type =
ir->type->base_type == GLSL_TYPE_UINT64
? glsl_type::uvec2_type : glsl_type::ivec2_type;
ir_factory body(&instructions, mem_ctx);
for (unsigned i = 0; i < num_operands; i++) {
expand_source(body, ir->operands[i], src[i]);
if (ir->operands[i]->type->vector_elements > source_components)
source_components = ir->operands[i]->type->vector_elements;
}
for (unsigned i = 0; i < source_components; i++) {
dst[i] = body.make_temp(result_type, "expanded_64bit_result");
exec_list parameters;
for (unsigned j = 0; j < num_operands; j++)
parameters.push_tail(new(mem_ctx) ir_dereference_variable(src[j][i]));
ir_dereference_variable *const return_deref =
new(mem_ctx) ir_dereference_variable(dst[i]);
ir_call *const c = new(mem_ctx) ir_call(callee,
return_deref,
&parameters);
body.emit(c);
}
ir_rvalue *const rv = compact_destination(body, ir->type, dst);
/* Move all of the nodes from instructions between base_ir and the
* instruction before it.
*/
exec_node *const after = base_ir;
exec_node *const before = after->prev;
exec_node *const head = instructions.head_sentinel.next;
exec_node *const tail = instructions.tail_sentinel.prev;
before->next = head;
head->prev = before;
after->prev = tail;
tail->next = after;
return rv;
}
ir_rvalue *
lower_64bit_visitor::handle_op(ir_expression *ir,
const char *function_name,
function_generator generator)
{
for (unsigned i = 0; i < ir->num_operands; i++)
if (!ir->operands[i]->type->is_integer_64())
return ir;
/* Get a handle to the correct ir_function_signature for the core
* operation.
*/
ir_function_signature *callee = NULL;
ir_function *f = find_function(function_name);
if (f != NULL) {
callee = (ir_function_signature *) f->signatures.get_head();
assert(callee != NULL && callee->ir_type == ir_type_function_signature);
} else {
f = new(base_ir) ir_function(function_name);
callee = generator(base_ir, NULL);
f->add_signature(callee);
add_function(f);
}
this->progress = true;
return lower_op_to_function_call(this->base_ir, ir, callee);
}
void
lower_64bit_visitor::handle_rvalue(ir_rvalue **rvalue)
{
if (*rvalue == NULL || (*rvalue)->ir_type != ir_type_expression)
return;
ir_expression *const ir = (*rvalue)->as_expression();
assert(ir != NULL);
switch (ir->operation) {
case ir_binop_div:
if (lowering(DIV64)) {
if (ir->type->base_type == GLSL_TYPE_UINT64) {
*rvalue = handle_op(ir, "__builtin_udiv64", generate_ir::udiv64);
} else {
*rvalue = handle_op(ir, "__builtin_idiv64", generate_ir::idiv64);
}
}
break;
case ir_binop_mod:
if (lowering(MOD64)) {
if (ir->type->base_type == GLSL_TYPE_UINT64) {
*rvalue = handle_op(ir, "__builtin_umod64", generate_ir::umod64);
} else {
*rvalue = handle_op(ir, "__builtin_imod64", generate_ir::imod64);
}
}
break;
default:
break;
}
}

View file

@ -123,10 +123,8 @@ files_libglsl = files(
'ast_type.cpp',
'builtin_functions.cpp',
'builtin_functions.h',
'builtin_int64.h',
'builtin_types.cpp',
'builtin_variables.cpp',
'generate_ir.cpp',
'gl_nir_lower_atomics.c',
'gl_nir_lower_images.c',
'gl_nir_lower_blend_equation_advanced.c',
@ -200,7 +198,6 @@ files_libglsl = files(
'lower_discard_flow.cpp',
'lower_distance.cpp',
'lower_instructions.cpp',
'lower_int64.cpp',
'lower_jumps.cpp',
'lower_mat_op_to_vec.cpp',
'lower_named_interface_blocks.cpp',

View file

@ -1,443 +0,0 @@
/*
* Copyright © 2013 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <gtest/gtest.h>
#include "util/compiler.h"
#include "main/macros.h"
#include "ir.h"
#include "ir_builder.h"
using namespace ir_builder;
namespace lower_64bit {
void expand_source(ir_factory &body,
ir_rvalue *val,
ir_variable **expanded_src);
ir_dereference_variable *compact_destination(ir_factory &body,
const glsl_type *type,
ir_variable *result[4]);
ir_rvalue *lower_op_to_function_call(ir_instruction *base_ir,
ir_expression *ir,
ir_function_signature *callee);
};
class expand_source : public ::testing::Test {
public:
virtual void SetUp();
virtual void TearDown();
exec_list instructions;
ir_factory *body;
ir_variable *expanded_src[4];
void *mem_ctx;
};
void
expand_source::SetUp()
{
glsl_type_singleton_init_or_ref();
mem_ctx = ralloc_context(NULL);
memset(expanded_src, 0, sizeof(expanded_src));
instructions.make_empty();
body = new ir_factory(&instructions, mem_ctx);
}
void
expand_source::TearDown()
{
delete body;
body = NULL;
ralloc_free(mem_ctx);
mem_ctx = NULL;
glsl_type_singleton_decref();
}
static ir_dereference_variable *
create_variable(void *mem_ctx, const glsl_type *type)
{
ir_variable *var = new(mem_ctx) ir_variable(type,
"variable",
ir_var_temporary);
return new(mem_ctx) ir_dereference_variable(var);
}
static ir_expression *
create_expression(void *mem_ctx, const glsl_type *type)
{
return new(mem_ctx) ir_expression(ir_unop_neg,
create_variable(mem_ctx, type));
}
static void
check_expanded_source(const glsl_type *type,
ir_variable *expanded_src[4])
{
const glsl_type *const expanded_type =
type->base_type == GLSL_TYPE_UINT64
? glsl_type::uvec2_type :glsl_type::ivec2_type;
for (int i = 0; i < type->vector_elements; i++) {
EXPECT_EQ(expanded_type, expanded_src[i]->type);
/* All elements that are part of the vector must be unique. */
for (int j = i - 1; j >= 0; j--) {
EXPECT_NE(expanded_src[i], expanded_src[j])
<< " Element " << i << " is the same as element " << j;
}
}
/* All elements that are not part of the vector must be the same as element
* 0. This is primarily for scalars (where every element is the same).
*/
for (int i = type->vector_elements; i < 4; i++) {
EXPECT_EQ(expanded_src[0], expanded_src[i])
<< " Element " << i << " should be the same as element 0";
}
}
static void
check_instructions(exec_list *instructions,
const glsl_type *type,
const ir_instruction *source)
{
const glsl_type *const expanded_type =
type->base_type == GLSL_TYPE_UINT64
? glsl_type::uvec2_type : glsl_type::ivec2_type;
const ir_expression_operation unpack_opcode =
type->base_type == GLSL_TYPE_UINT64
? ir_unop_unpack_uint_2x32 : ir_unop_unpack_int_2x32;
ir_instruction *ir;
/* The instruction list should contain IR to represent:
*
* type tmp1;
* tmp1 = source;
* uvec2 tmp2;
* tmp2 = unpackUint2x32(tmp1.x);
* uvec2 tmp3;
* tmp3 = unpackUint2x32(tmp1.y);
* uvec2 tmp4;
* tmp4 = unpackUint2x32(tmp1.z);
* uvec2 tmp5;
* tmp5 = unpackUint2x32(tmp1.w);
*/
ASSERT_FALSE(instructions->is_empty());
ir = (ir_instruction *) instructions->pop_head();
ir_variable *const tmp1 = ir->as_variable();
EXPECT_EQ(ir_type_variable, ir->ir_type);
EXPECT_EQ(type, tmp1->type) <<
" Got " <<
glsl_get_type_name(tmp1->type) <<
", expected " <<
glsl_get_type_name(type);
ASSERT_FALSE(instructions->is_empty());
ir = (ir_instruction *) instructions->pop_head();
ir_assignment *const assign1 = ir->as_assignment();
EXPECT_EQ(ir_type_assignment, ir->ir_type);
ASSERT_NE((void *)0, assign1);
EXPECT_EQ(tmp1, assign1->lhs->variable_referenced());
EXPECT_EQ(source, assign1->rhs);
for (unsigned i = 0; i < type->vector_elements; i++) {
ASSERT_FALSE(instructions->is_empty());
ir = (ir_instruction *) instructions->pop_head();
ir_variable *const tmp2 = ir->as_variable();
EXPECT_EQ(ir_type_variable, ir->ir_type);
EXPECT_EQ(expanded_type, tmp2->type);
ASSERT_FALSE(instructions->is_empty());
ir = (ir_instruction *) instructions->pop_head();
ir_assignment *const assign2 = ir->as_assignment();
EXPECT_EQ(ir_type_assignment, ir->ir_type);
ASSERT_NE((void *)0, assign2);
EXPECT_EQ(tmp2, assign2->lhs->variable_referenced());
ir_expression *unpack = assign2->rhs->as_expression();
ASSERT_NE((void *)0, unpack);
EXPECT_EQ(unpack_opcode, unpack->operation);
EXPECT_EQ(tmp1, unpack->operands[0]->variable_referenced());
}
EXPECT_TRUE(instructions->is_empty());
}
TEST_F(expand_source, uint64_variable)
{
const glsl_type *const type = glsl_type::uint64_t_type;
ir_dereference_variable *const deref = create_variable(mem_ctx, type);
lower_64bit::expand_source(*body, deref, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, deref);
}
TEST_F(expand_source, u64vec2_variable)
{
const glsl_type *const type = glsl_type::u64vec2_type;
ir_dereference_variable *const deref = create_variable(mem_ctx, type);
lower_64bit::expand_source(*body, deref, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, deref);
}
TEST_F(expand_source, u64vec3_variable)
{
const glsl_type *const type = glsl_type::u64vec3_type;
/* Generate an operand that is a scalar variable dereference. */
ir_variable *const var = new(mem_ctx) ir_variable(type,
"variable",
ir_var_temporary);
ir_dereference_variable *const deref =
new(mem_ctx) ir_dereference_variable(var);
lower_64bit::expand_source(*body, deref, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, deref);
}
TEST_F(expand_source, u64vec4_variable)
{
const glsl_type *const type = glsl_type::u64vec4_type;
ir_dereference_variable *const deref = create_variable(mem_ctx, type);
lower_64bit::expand_source(*body, deref, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, deref);
}
TEST_F(expand_source, int64_variable)
{
const glsl_type *const type = glsl_type::int64_t_type;
ir_dereference_variable *const deref = create_variable(mem_ctx, type);
lower_64bit::expand_source(*body, deref, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, deref);
}
TEST_F(expand_source, i64vec2_variable)
{
const glsl_type *const type = glsl_type::i64vec2_type;
ir_dereference_variable *const deref = create_variable(mem_ctx, type);
lower_64bit::expand_source(*body, deref, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, deref);
}
TEST_F(expand_source, i64vec3_variable)
{
const glsl_type *const type = glsl_type::i64vec3_type;
ir_dereference_variable *const deref = create_variable(mem_ctx, type);
lower_64bit::expand_source(*body, deref, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, deref);
}
TEST_F(expand_source, i64vec4_variable)
{
const glsl_type *const type = glsl_type::i64vec4_type;
ir_dereference_variable *const deref = create_variable(mem_ctx, type);
lower_64bit::expand_source(*body, deref, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, deref);
}
TEST_F(expand_source, uint64_expression)
{
const glsl_type *const type = glsl_type::uint64_t_type;
ir_expression *const expr = create_expression(mem_ctx, type);
lower_64bit::expand_source(*body, expr, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, expr);
}
TEST_F(expand_source, u64vec2_expression)
{
const glsl_type *const type = glsl_type::u64vec2_type;
ir_expression *const expr = create_expression(mem_ctx, type);
lower_64bit::expand_source(*body, expr, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, expr);
}
TEST_F(expand_source, u64vec3_expression)
{
const glsl_type *const type = glsl_type::u64vec3_type;
ir_expression *const expr = create_expression(mem_ctx, type);
lower_64bit::expand_source(*body, expr, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, expr);
}
TEST_F(expand_source, u64vec4_expression)
{
const glsl_type *const type = glsl_type::u64vec4_type;
ir_expression *const expr = create_expression(mem_ctx, type);
lower_64bit::expand_source(*body, expr, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, expr);
}
TEST_F(expand_source, int64_expression)
{
const glsl_type *const type = glsl_type::int64_t_type;
ir_expression *const expr = create_expression(mem_ctx, type);
lower_64bit::expand_source(*body, expr, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, expr);
}
TEST_F(expand_source, i64vec2_expression)
{
const glsl_type *const type = glsl_type::i64vec2_type;
ir_expression *const expr = create_expression(mem_ctx, type);
lower_64bit::expand_source(*body, expr, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, expr);
}
TEST_F(expand_source, i64vec3_expression)
{
const glsl_type *const type = glsl_type::i64vec3_type;
ir_expression *const expr = create_expression(mem_ctx, type);
lower_64bit::expand_source(*body, expr, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, expr);
}
TEST_F(expand_source, i64vec4_expression)
{
const glsl_type *const type = glsl_type::i64vec4_type;
ir_expression *const expr = create_expression(mem_ctx, type);
lower_64bit::expand_source(*body, expr, expanded_src);
check_expanded_source(type, expanded_src);
check_instructions(&instructions, type, expr);
}
class compact_destination : public ::testing::Test {
public:
virtual void SetUp();
virtual void TearDown();
exec_list instructions;
ir_factory *body;
ir_variable *expanded_src[4];
void *mem_ctx;
};
void
compact_destination::SetUp()
{
mem_ctx = ralloc_context(NULL);
memset(expanded_src, 0, sizeof(expanded_src));
instructions.make_empty();
body = new ir_factory(&instructions, mem_ctx);
}
void
compact_destination::TearDown()
{
delete body;
body = NULL;
ralloc_free(mem_ctx);
mem_ctx = NULL;
}
TEST_F(compact_destination, uint64)
{
const glsl_type *const type = glsl_type::uint64_t_type;
for (unsigned i = 0; i < type->vector_elements; i++) {
expanded_src[i] = new(mem_ctx) ir_variable(glsl_type::uvec2_type,
"result",
ir_var_temporary);
}
ir_dereference_variable *deref =
lower_64bit::compact_destination(*body,
type,
expanded_src);
ASSERT_EQ(ir_type_dereference_variable, deref->ir_type);
EXPECT_EQ(type, deref->var->type) <<
" Got " <<
glsl_get_type_name(deref->var->type) <<
", expected " <<
glsl_get_type_name(type);
ir_instruction *ir;
ASSERT_FALSE(instructions.is_empty());
ir = (ir_instruction *) instructions.pop_head();
ir_variable *const var = ir->as_variable();
ASSERT_NE((void *)0, var);
EXPECT_EQ(deref->var, var);
for (unsigned i = 0; i < type->vector_elements; i++) {
ASSERT_FALSE(instructions.is_empty());
ir = (ir_instruction *) instructions.pop_head();
ir_assignment *const assign = ir->as_assignment();
ASSERT_NE((void *)0, assign);
EXPECT_EQ(deref->var, assign->lhs->variable_referenced());
}
}

View file

@ -22,7 +22,6 @@ general_ir_test_files = files(
'array_refcount_test.cpp',
'builtin_variable_test.cpp',
'general_ir_test.cpp',
'lower_int64_test.cpp',
'opt_add_neg_to_sub_test.cpp',
)
general_ir_test_files += ir_expression_operation_h

View file

@ -334,7 +334,6 @@ u_pipe_screen_get_param_defaults(struct pipe_screen *pscreen,
case PIPE_CAP_LEGACY_MATH_RULES:
case PIPE_CAP_DOUBLES:
case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_TGSI_TEX_TXF_LZ:
case PIPE_CAP_SHADER_CLOCK:
case PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE:

View file

@ -194,7 +194,6 @@ crocus_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_NATIVE_FENCE_FD:
return true;
case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_SHADER_BALLOT:
case PIPE_CAP_PACKED_UNIFORMS:
return devinfo->ver == 8;

View file

@ -324,7 +324,6 @@ d3d12_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_DOUBLES:
case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR:

View file

@ -382,7 +382,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
return 64;
case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_DOUBLES:
return is_ir3(screen);

View file

@ -255,7 +255,6 @@ iris_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
case PIPE_CAP_DOUBLES:
case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_SAMPLER_VIEW_TARGET:
case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR:
case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:

View file

@ -258,7 +258,6 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_SHADER_ARRAY_COMPONENTS:
case PIPE_CAP_DOUBLES:
case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_QUERY_SO_OVERFLOW:
case PIPE_CAP_TGSI_DIV:
return 1;

View file

@ -220,7 +220,6 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_LEGACY_MATH_RULES:
case PIPE_CAP_DOUBLES:
case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_TGSI_TEX_TXF_LZ:
case PIPE_CAP_SHADER_CLOCK:
case PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE:

View file

@ -330,7 +330,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_GL_SPIRV:
case PIPE_CAP_GL_SPIRV_VARIABLE_POINTERS:
case PIPE_CAP_INT64_DIVMOD:
return 1;
/* nir related caps */

View file

@ -408,11 +408,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_TWO_SIDED_COLOR:
return 0;
case PIPE_CAP_INT64_DIVMOD:
/* it is actually not supported, but the nir lowering handles this correctly whereas
* the glsl lowering path seems to not initialize the buildins correctly.
*/
return 1;
case PIPE_CAP_CULL_DISTANCE:
return 1;

View file

@ -130,7 +130,6 @@ static int si_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_MEMOBJ:
case PIPE_CAP_LOAD_CONSTBUF:
case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_SHADER_CLOCK:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:

View file

@ -206,7 +206,6 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_VS_LAYER_VIEWPORT:
case PIPE_CAP_DOUBLES:
case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_TGSI_DIV:
return 1;
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:

View file

@ -740,7 +740,7 @@ vgpu10_get_shader_param(struct pipe_screen *screen,
.lower_extract_word = true, \
.lower_insert_byte = true, \
.lower_insert_word = true, \
.lower_int64_options = nir_lower_imul_2x32_64, \
.lower_int64_options = nir_lower_imul_2x32_64 | nir_lower_divmod64, \
.lower_fdph = true, \
.lower_flrp64 = true, \
.lower_ldexp = true, \

View file

@ -679,7 +679,6 @@ zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
return screen->info.have_NV_compute_shader_derivatives;
case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_DOUBLES:
return 1;

View file

@ -809,7 +809,6 @@ enum pipe_cap
PIPE_CAP_LEGACY_MATH_RULES,
PIPE_CAP_DOUBLES,
PIPE_CAP_INT64,
PIPE_CAP_INT64_DIVMOD,
PIPE_CAP_TGSI_TEX_TXF_LZ,
PIPE_CAP_SHADER_CLOCK,
PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE,

View file

@ -515,9 +515,6 @@ st_link_glsl_to_nir(struct gl_context *ctx,
bool have_dround = pscreen->get_shader_param(pscreen, ptarget,
PIPE_SHADER_CAP_DROUND_SUPPORTED);
if (!pscreen->get_param(pscreen, PIPE_CAP_INT64_DIVMOD))
lower_64bit_integer_instructions(ir, DIV64 | MOD64);
lower_packing_builtins(ir, ctx->Extensions.ARB_shading_language_packing,
ctx->Extensions.ARB_gpu_shader5,
ctx->st->has_half_float_packing);