The new opcode is used to generate a new vector with a single field from
the source vector replaced. This will eventually replace
ir_dereference_array of vectors in the LHS of assignments.
v2: Convert tabs to spaces. Suggested by Eric.
v3: Add constant expression handling for ir_triop_vector_insert. This
prevents the constant matrix inversion tests from regressing. Duh.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
The new opcode is used to get a single field from a vector. The field
index may not be constant. This will eventually replace
ir_dereference_array of vectors. This is similar to the extractelement
instruction in LLVM IR.
http://llvm.org/docs/LangRef.html#extractelement-instruction
v2: Convert tabs to spaces. Suggested by Eric.
v3: Add array index range checking to ir_binop_vector_extract constant
expression handling. Suggested by Ken.
v4: Use CLAMP instead of MIN2(MAX2()). Suggested by Ken.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
v2: Order bits from LSB end (31 - count) for ir_unop_find_msb.
v3: Add ir_triop_bitfield_extract as an exception to the op[0]->type ==
op[1]->type assertion in ir_constant_expression.cpp.
Reviewed-by: Chris Forbes <chrisf@ijw.co.nz> [v2]
Mesa constant-folds built-in functions by using a miniature GLSL
interpreter (see
ir_function_signature::constant_expression_evaluate_expression_list()).
This interpreter had a bug in its handling of array indexing, which
caused expressions like "m[i][j]" (where m is a matrix) to be handled
incorrectly. Specifically, it incorrectly treated j as indexing into
the whole matrix (rather than indexing just into the vector m[i]); as
a result the offset computed for m[i] was lost and m[i][j] was treated
as m[j][0].
Fixes piglit tests inverse-mat[234].{vert,frag}.
NOTE: This is a candidate for the 9.1 and 9.0 branches.
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=57436
Many GPUs have an instruction to do linear interpolation which is more
efficient than simply performing the algebra necessary (two multiplies,
an add, and a subtract).
Pattern matching or peepholing this is more desirable, but can be
tricky. By using an opcode, we can at least make shaders which use the
mix() built-in get the more efficient behavior.
Currently, all consumers lower ir_triop_lrp. Subsequent patches will
actually generate different code.
v2 [mattst88]:
- Add LRP_TO_ARITH flag to ir_to_mesa.cpp. Will be removed in a
subsequent patch and ir_triop_lrp translated directly.
v3 [mattst88]:
- Move changes from the next patch to opt_algebraic.cpp to accept
3-src operations.
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
That is, evaluate constant expressions for the following functions:
packSnorm4x8, unpackSnorm4x8
packUnorm4x8, unpackUnorm4x8
Reviewed-by: Chad Versace <chad.versace@linux.intel.com>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
That is, evaluate constant expressions of the following functions:
packSnorm2x16 unpackSnorm2x16
packUnorm2x16 unpackUnorm2x16
packHalf2x16 unpackHalf2x16
v2: Reuse _mesa_pack_float_to_half and its inverse to evaluate
pack/unpackHalf2x16. [for idr]
v3: Whitespace fixes. [for mattst88]
Don't cast neg floats directly to uint16; use an intermediate cast to
int16. [for paul]
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> (v2)
Reviewed-by: Paul Berry <stereotype441@gmail.com>
Reviewed-by: Matt Tuner <mattst88@gmail.com>
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
Move round_to_even's definition to mesa/main so that _mesa_float_to_half()
can use it in order to eliminate rounding bias.
In additon to moving the fuction definition, prefix its name with "_mesa",
just as all other functions in mesa/main are prefixed.
v2: Fix Android build.
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
The method is used to get a reference to an ir_constant * within the
context of evaluating an assignment when calculating a
constant_expression_value.
Signed-off-by: Olivier Galibert <galibert@pobox.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net> [v1]
We were looping over all the vector components, but only dealing with
the first one. This was masked by the fact that constant expression
handling on built-ins went through custom code for the lessThan()
/function/ rather than the ir_binop_less expression operator.
NOTE: This is a candidate for all release branches.
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Signed-off-by: Olivier Galibert <galibert@pobox.com>
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Aside from ir_call, our IR is cleanly split into two classes:
- Statements (typeless; used for side effects, control flow)
- Values (deeply nestable, pure, typed expression trees)
Unfortunately, ir_call confused all this:
- For void functions, we placed ir_call directly in the instruction
stream, treating it as an untyped statement. Yet, it was a subclass
of ir_rvalue, and no other ir_rvalue could be used in this way.
- For functions with a return value, ir_call could be placed in
arbitrary expression trees. While this fit naturally with the source
language, it meant that expressions might not be pure, making it
difficult to transform and optimize them. To combat this, we always
emitted ir_call directly in the RHS of an ir_assignment, only using
a temporary variable in expression trees. Many passes relied on this
assumption; the acos and atan built-ins violated it.
This patch makes ir_call a statement (ir_instruction) rather than a
value (ir_rvalue). Non-void calls now take a ir_dereference of a
variable, and store the return value there---effectively a call and
assignment rolled into one. They cannot be embedded in expressions.
All expression trees are now pure, without exception.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
When translating a call from AST to HIR, we need to decide whether it
can be evaluated to a constant before emitting any code (namely, the
temporary declaration, assignment, and call.)
Soon, ir_call will become a statement taking a dereference of where to
store the return value, rather than an rvalue to be used on the RHS of
an assignment. It will be more convenient to try evaluation before
creating a call. ir_function_signature seems like a reasonable place.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Currently, ir_call can be used as either a statement (for void
functions) or a value (for non-void functions). This is rather awkward,
as it's the only class that can be used in both forms.
A number of places use ir_call::get_error_instruction() to construct a
generic value of error_type. If ir_call is to become a statement, it
can no longer serve this purpose.
Unfortunately, none of our classes are particularly well suited for
this, and creating a new one would be rather aggrandizing. So, this
patch introduces ir_rvalue::error_value(), a static method that creates
an instance of the base class, ir_rvalue. This has the nice property
that you can't accidentally try and access uninitialized fields (as it
doesn't have any). The downside is that the base class is no longer
abstract.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Constant expressions which called GLSL's equal() and notEqual()
built-ins on bvecs would hit an assertion failure; we simply forgot to
implement them for booleans.
NOTE: This is a candidate for stable release branches.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Chad Versace <chad.versace@linux.intel.com>
The implementation of ir_binop_nequal in constant_expression_value()
appears to have been copy-and-pasted from the implementation of
ir_binop_equal, but with all instances of '==' changed to '!='. This
is correct except for one minor flaw: one of those '==' operators was
in an assertion checking that the types of the two arguments were
equal. That one needs to stay an '=='.
Fixes piglit tests {fs,vs}-inline-notequal.
v2: Avoid the C99 rounding functions, because I don't trust
get/setting the C99 rounding mode from inside our library not having
other side effects. Instead, open-code roundEven() behavior around
Mesa's IROUND, which we're already testing for C99 rounding mode
safety.
Fixes glsl-1.30/compiler/built-in-functions/round*
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Fixes the glsl-1.30/compiler/built-in-functions/trunc-* tests under 1.30.
Reviewed-by: Chad Versace <chad@chad-versace.us>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Bitshifts are one of the rare places that GLSL allows mixed base types
without an implicit conversion occurring.
Reviewed-by: Chad Versace <chad@chad-versace.us>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
These are necessary to handle int/uint constructor conversions. For
example, the following code currently results in a type mismatch:
int x = 7;
uint y = uint(x);
In particular, uint(x) still has type int.
This commit simply adds the new operations; it does not generate them,
nor does it add backend support for them.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Fixes regression: https://bugs.freedesktop.org/show_bug.cgi?id=34160
Commit e7c1f058d1 disabled constant-folding
when division-by-zero occured. This was a mistake, because the spec does
allow division by zero. (From section 5.9 of the GLSL 1.20 spec: Dividing
by zero does not cause an exception but does result in an unspecified
value.)
For floating-point division, the original pre-e7c1f05 behavior is
reinstated.
For integer division, constant-fold 1/0 to 0.
This reverts commit b3cf92aa91.
The reverted commit prevented constant-folding of reciprocal expressions
when the reciprocated expression was 0. However, since the spec allows
division by zero, constant-folding *is* permissible in this case.
From Section 5.9 of the GLSL 1.20 spec:
Dividing by zero does not cause an exception but does result in an
unspecified value.
Avoid division-by-zero when constant-folding the following expression
types:
ir_unop_rsq
ir_binop_div
ir_binop_mod
Fixes bugs:
https://bugs.freedesktop.org//show_bug.cgi?id=33306https://bugs.freedesktop.org//show_bug.cgi?id=33508
Fixes Piglit tests:
glslparsertest/glsl2/div-by-zero-01.frag
glslparsertest/glsl2/div-by-zero-02.frag
glslparsertest/glsl2/div-by-zero-03.frag
glslparsertest/glsl2/modulus-zero-01.frag
glslparsertest/glsl2/modulus-zero-02.frag
NOTE: This is a candidate for the 7.9 and 7.10 branches.
Do not constant-fold a reciprocal if any component of the reciprocated
expression is 0. For example, do not constant-fold `1 / vec4(0, 1, 2, 3)`.
Incorrect, previous behavior
----------------------------
Reciprocals were constant-folded even when some component of the
reciprocated expression was 0. The incorrectly applied arithmetic was:
1 / 0 := 0
For example,
1 / vec4(0, 1, 2, 3) = vec4(0, 1, 1/2, 1/3)
NOTE: This is a candidate for the 7.9 and 7.10 branches.
The vector operator collects 2, 3, or 4 scalar components into a
vector. Doing this has several advantages. First, it will make
ud-chain tracking for components of vectors much easier. Second, a
later optimization pass could collect scalars into vectors to allow
generation of SWZ instructions (or similar as operands to other
instructions on R200 and i915). It also enables an easy way to
generate IR for SWZ instructions in the ARB_vertex_program assembler.
The operate just like ir_unop_sin and ir_unop_cos except that they
expect their inputs to be limited to the range [-pi, pi]. Several
GPUs require this limited range for their sine and cosine
instructions, so having these as operations (along with a to-be-written
lowering pass) helps this architectures.
These new operations also matche the semantics of the
GL_ARB_fragment_program SCS instruction. Having these as operations
helps in generating GLSL IR directly from assembly fragment programs.
ir_binop_less, ir_binop_greater, ir_binop_lequal, and ir_binop_gequal
are defined to work on vectors as well as scalars, as long as the two
operands have the same type.
This is evident from both ir_validate.cpp and our use of these opcodes
in the GLSL lessThan, greaterThan, lessThanEqual, greaterThanEqual
built-in functions.
Found by code inspection. Not known to fix any bugs. Presumably, our
tests for the built-in comparison functions must pass because C.E.
handling is done on the ir_call of "greaterThan" rather than the inlined
opcode. The C.E. handling of the built-in function calls is correct.
NOTE: This is a candidate for the 7.9 branch.
When ir_binop_all_equal and ir_binop_any_nequal were introduced, the
meaning of these two opcodes changed to return vectors rather than a
single scalar, but the constant expression handling code was incorrectly
written and only worked for scalars. As a result, only the first
component of the returned vector would be properly initialized.
Currently GLSL IR forbids any vector comparisons, and defines "ir_binop_equal"
and "ir_binop_nequal" to compare all elements and give a single bool.
This is highly unintuitive and prevents generation of optimal Mesa IR.
Hence, first rename "ir_binop_equal" to "ir_binop_all_equal" and
"ir_binop_nequal" to "ir_binop_any_nequal".
Second, readd "ir_binop_equal" and "ir_binop_nequal" with the same semantics
as less, lequal, etc.
Third, allow all comparisons to acts on vectors.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
This effectively reverts b6f15869b3.
In desktop GLSL, defining a function with the same name as a built-in
hides that built-in function completely, so there would never be
built-in and user function signatures in the same ir_function.
However, in GLSL ES, overloading built-ins is allowed, and does not
hide the built-in signatures - so we're back to needing this.
Complete initialize data passed to ir_constant constructor.
Fixes piglit glsl-mat-from-int-ctor-02 valgrind unintialized variable
error with softpipe and llvmpipe.
The previous any() implementation would generate arg0.x || arg0.y ||
arg0.z. Having an expression operation for this makes it easy for the
backend to generate something easier (DPn + SNE for 915 FS, .any
predication on 965 VS)
Calls to equal(bvec, bvec) or notEqual(bvec, bvec) previously caused an
assertion. Fixes piglit tests glsl-const-builtin-equal-bool and
glsl-const-builtin-notEqual-bool.