[Mesa-dev] [PATCH v5 3/6] mesa/st: glsl_to_tgsi: add tests for the new temporary lifetime tracker

Nicolai Hähnle nhaehnle at gmail.com
Mon Jun 26 13:12:30 UTC 2017


On 25.06.2017 09:22, Gert Wollny wrote:
> This patch adds a set of unit tests for the new lifetime tracker.
> ---
>   configure.ac                                       |   1 +
>   src/mesa/Makefile.am                               |   2 +-
>   src/mesa/state_tracker/tests/Makefile.am           |  36 +
>   .../tests/test_glsl_to_tgsi_lifetime.cpp           | 976 +++++++++++++++++++++
>   4 files changed, 1014 insertions(+), 1 deletion(-)
>   create mode 100644 src/mesa/state_tracker/tests/Makefile.am
>   create mode 100644 src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp
> 
> diff --git a/configure.ac b/configure.ac
> index da7b2f8f81..5279b231ed 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -2839,6 +2839,7 @@ AC_CONFIG_FILES([Makefile
>   		src/mesa/drivers/osmesa/osmesa.pc
>   		src/mesa/drivers/x11/Makefile
>   		src/mesa/main/tests/Makefile
> +		src/mesa/state_tracker/tests/Makefile
>   		src/util/Makefile
>   		src/util/tests/hash_table/Makefile
>   		src/vulkan/Makefile])
> diff --git a/src/mesa/Makefile.am b/src/mesa/Makefile.am
> index 53f311d2a9..a88a94165d 100644
> --- a/src/mesa/Makefile.am
> +++ b/src/mesa/Makefile.am
> @@ -19,7 +19,7 @@
>   # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
>   # IN THE SOFTWARE.
>   
> -SUBDIRS = . main/tests
> +SUBDIRS = . main/tests state_tracker/tests
>   
>   if HAVE_XLIB_GLX
>   SUBDIRS += drivers/x11
> diff --git a/src/mesa/state_tracker/tests/Makefile.am b/src/mesa/state_tracker/tests/Makefile.am
> new file mode 100644
> index 0000000000..fb64cf9dc2
> --- /dev/null
> +++ b/src/mesa/state_tracker/tests/Makefile.am
> @@ -0,0 +1,36 @@
> +AM_CFLAGS = \
> +	$(PTHREAD_CFLAGS)
> +
> +AM_CXXFLAGS = \
> +	$(LLVM_CXXFLAGS)
> +
> +AM_CPPFLAGS = \
> +	-I$(top_srcdir)/src/gtest/include \
> +	-I$(top_srcdir)/src \
> +	-I$(top_srcdir)/src/mapi \
> +	-I$(top_builddir)/src/mesa \
> +	-I$(top_srcdir)/src/mesa \
> +	-I$(top_srcdir)/include \
> +	-I$(top_srcdir)/src/gallium/include \
> +	-I$(top_srcdir)/src/gallium/auxiliary \
> +	$(DEFINES)
> +
> +TESTS = st-renumerate-test
> +check_PROGRAMS = st-renumerate-test
> +
> +st_renumerate_test_SOURCES =			\
> +	test_glsl_to_tgsi_lifetime.cpp
> +
> +st_renumerate_test_LDFLAGS = \
> +	$(LLVM_LDFLAGS)
> +
> +st_renumerate_test_LDADD = \
> +	$(top_builddir)/src/mesa/libmesagallium.la \
> +	$(top_builddir)/src/mapi/shared-glapi/libglapi.la \
> +	$(top_builddir)/src/gallium/auxiliary/libgallium.la \
> +	$(top_builddir)/src/util/libmesautil.la \
> +	$(top_builddir)/src/gtest/libgtest.la \
> +	$(GALLIUM_COMMON_LIB_DEPS) \
> +	$(LLVM_LIBS) \
> +	$(PTHREAD_LIBS) \
> +	$(DLOPEN_LIBS)
> diff --git a/src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp b/src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp
> new file mode 100644
> index 0000000000..5f3378637a
> --- /dev/null
> +++ b/src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp
> @@ -0,0 +1,976 @@
> +/*
> + * Copyright © 2017 Gert Wollny
> + *
> + * 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 <state_tracker/st_glsl_to_tgsi_temprename.h>
> +#include <tgsi/tgsi_ureg.h>
> +#include <tgsi/tgsi_info.h>
> +#include <compiler/glsl/list.h>
> +#include <gtest/gtest.h>
> +
> +using std::vector;
> +using std::pair;
> +
> +/* A line to describe a TGSI instruction for building mock shaders */
> +struct MockCodeline {
> +   MockCodeline(unsigned  _op): op(_op) {}
> +   MockCodeline(unsigned _op, const vector<int>& _dst, const vector<int>& _src, const vector<int>&_to):
> +      op(_op), dst(_dst), src(_src), tex_offsets(_to){}
> +   unsigned op;
> +   vector<int> dst;
> +   vector<int> src;
> +   vector<int> tex_offsets;
> +};
> +
> +const int in0 = 0;
> +const int in1 = -1;
> +const int in2 = -2;
> +
> +const int out0 = 0;
> +const int out1 = -1;
> +
> +class MockShader {
> +public:
> +   MockShader(const vector<MockCodeline>& source);
> +   ~MockShader();
> +
> +   void free();
> +
> +   exec_list* get_program();
> +   int get_num_temps();

Empty line before private:


> +private:
> +   st_src_reg create_src_register(int src_idx);
> +   st_dst_reg create_dst_register(int dst_idx);
> +   exec_list* program;
> +   int num_temps;
> +   void *mem_ctx;
> +};
> +
> +using expectation = vector<vector<int>>;
> +
> +
> +class MesaTestWithMemCtx : public testing::Test {
> +   void SetUp();
> +   void TearDown();
> +protected:
> +   void *mem_ctx;
> +};
> +
> +class LifetimeEvaluatorTest : public MesaTestWithMemCtx {
> +protected:
> +   void run(const vector<MockCodeline>& code, const expectation& e);
> +private:
> +   virtual void check(const vector<lifetime>& result, const expectation& e) = 0;
> +};
> +
> +/* This is a test class to check the exact life times of
> + * registers. */
> +class LifetimeEvaluatorExactTest : public LifetimeEvaluatorTest {
> +protected:
> +   void check(const vector<lifetime>& result, const expectation& e);
> +};
> +
> +/* This test class checks that the life time covers at least
> + * in the expected range. It is used for cases where we know that
> + * a the implementation could be improved on estimating the minimal
> + * life time.
> + */
> +class LifetimeEvaluatorAtLeastTest : public LifetimeEvaluatorTest {
> +protected:
> +   void check(const vector<lifetime>& result, const expectation& e);
> +};
> +
> +TEST_F(LifetimeEvaluatorExactTest, SimpleMoveAdd)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_UADD, {out0}, {1, in0},  {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run(code, expectation({{-1, -1}, {0,1}}));
> +}
> +
> +TEST_F(LifetimeEvaluatorExactTest, SimpleMoveAddMove)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_UADD, {2}, {1, in0},  {}},
> +      { TGSI_OPCODE_MOV, {out0}, {2},  {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run(code, expectation({{-1, -1}, {0,1}, {1,2}}));
> +}
> +
> +TEST_F(LifetimeEvaluatorExactTest, SimpleMoveAddMoveTexoffset)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_MOV, {2}, {in1}, {}},
> +      { TGSI_OPCODE_UADD, {out0}, {},  {1,2}},

UADD doesn't have texoffsets.


> +      { TGSI_OPCODE_END}
> +   };
> +   run(code, expectation({{-1, -1}, {0,2}, {1,2}}));
> +}
> +
> +
> +TEST_F(LifetimeEvaluatorExactTest, SimpleMoveInLoop)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_BGNLOOP },
> +      { TGSI_OPCODE_UADD, {2}, {1, in0},  {}},
> +      { TGSI_OPCODE_UADD, {3}, {1, 2},  {}},
> +      { TGSI_OPCODE_UADD, {3}, {3, in1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_MOV, {out0}, {3},  {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 5}, {2,3}, {3, 6}}));
> +}
> +
> +
> +/* in loop if/else value written only in one path, and read later
> + *   - value must survive the whole loop */

Closing */ on its own line. Also, please capitalize the start of sentences.


> +TEST_F(LifetimeEvaluatorExactTest, MoveInIfInLoop)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_BGNLOOP },
> +      { TGSI_OPCODE_IF},
> +      { TGSI_OPCODE_UADD, {2}, {1, in0},  {}},
> +      { TGSI_OPCODE_ENDIF},
> +      { TGSI_OPCODE_UADD, {3}, {1, 2},  {}},
> +      { TGSI_OPCODE_UADD, {3}, {3, in1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_MOV, {out0}, {3},  {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 7}, {1,7}, {5, 8}}));

Space between , and {


> +}
> +
> +
> +/* in loop if/else value written in both path, and read later

Same comments as above, plus typo: *paths


> + * - value must survive from first write to last read in loop
> + * for now we only check that the minimum life time is correct */
> +TEST_F(LifetimeEvaluatorAtLeastTest, WriteInIfAndElseInLoop)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_BGNLOOP },
> +      { TGSI_OPCODE_IF},
> +      { TGSI_OPCODE_UADD, {2}, {1, in0},  {}},
> +      { TGSI_OPCODE_ELSE },
> +      { TGSI_OPCODE_MOV, {2}, {1},  {}},
> +      { TGSI_OPCODE_ENDIF},
> +      { TGSI_OPCODE_UADD, {3}, {1, 2},  {}},
> +      { TGSI_OPCODE_UADD, {3}, {3, in1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_MOV, {out0}, {3},  {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 9}, {3,7}, {7, 10}}));

Space (recurring problem also below)


> +}
> +
> +/* in loop if/else value written in both path, red in else path

As above, plus typo: *read


> + * before read and also read later
> + *  - value must survive from first write to last read in loop */
> +TEST_F(LifetimeEvaluatorExactTest, WriteInIfAndElseReadInElseInLoop)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_BGNLOOP },
> +      { TGSI_OPCODE_IF},
> +      { TGSI_OPCODE_UADD, {2}, {1, in0},  {}},
> +      { TGSI_OPCODE_ELSE },
> +      { TGSI_OPCODE_ADD, {2}, {1, 2},  {}},
> +      { TGSI_OPCODE_ENDIF},
> +      { TGSI_OPCODE_UADD, {3}, {1, 2},  {}},
> +      { TGSI_OPCODE_UADD, {3}, {3, in1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_MOV, {out0}, {3},  {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 9}, {1,9}, {7, 10}}));
> +}
> +
> +/* in loop if/else read in one path before written in the same loop
> + *   - value must survive the whole loop */
> +TEST_F(LifetimeEvaluatorExactTest, ReadInIfInLoopBeforeWrite)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_BGNLOOP },
> +      { TGSI_OPCODE_IF, {}, {in0},  {}},
> +      { TGSI_OPCODE_UADD, {2}, {1, 3},  {}},
> +      { TGSI_OPCODE_ENDIF},
> +      { TGSI_OPCODE_UADD, {3}, {1, 2},  {}},
> +      { TGSI_OPCODE_UADD, {3}, {3, in1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_MOV, {out0}, {3},  {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 7}, {1,7}, {1, 8}}));
> +}
> +
> +/* Write in nested ifs in loop, for now we do test whether the
> + * life time is atleast what is required, but we know that the
> + * implementation doesn't do a full check and sets larger boundaries */
> +TEST_F(LifetimeEvaluatorAtLeastTest, NestedIfInLoopAlwaysWriteButNotPropagated)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_IF, {}, {in0},  {}},
> +      {     TGSI_OPCODE_IF, {}, {in0},  {}},
> +      {       TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {     TGSI_OPCODE_ELSE},
> +      {       TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {     TGSI_OPCODE_ENDIF},
> +      {   TGSI_OPCODE_ELSE},
> +      {     TGSI_OPCODE_IF, {}, {in0},  {}},
> +      {       TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {     TGSI_OPCODE_ELSE},
> +      {       TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {     TGSI_OPCODE_ENDIF},
> +      {   TGSI_OPCODE_ENDIF},
> +      {   TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{3, 14}}));
> +}
> +
> +
> +

At most two consecutive empty lines at global scope.


> +TEST_F(LifetimeEvaluatorExactTest, NestedIfInLoopWriteNotAlways)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_IF, {}, {in0},  {}},
> +      {     TGSI_OPCODE_IF, {}, {in0},  {}},
> +      {       TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {     TGSI_OPCODE_ELSE},
> +      {       TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {     TGSI_OPCODE_ENDIF},
> +      {   TGSI_OPCODE_ELSE},
> +      {     TGSI_OPCODE_IF, {}, {in0},  {}},
> +      {       TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {     TGSI_OPCODE_ENDIF},
> +      {   TGSI_OPCODE_ENDIF},
> +      {   TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 13}}));
> +}
> +
> +/* if a continue is in the loop, all variables written after the
> + * continue and used outside the loop must be maintained for the
> + * whole loop */
> +TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteAfterContinue)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_IF, {}, {in0},  {}},
> +      {     TGSI_OPCODE_CONT},
> +      {   TGSI_OPCODE_ENDIF},
> +      {   TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 6}}));

Sorry to keep harping on this, but this is still incorrect.

TGSI loops don't have an implied loop condition, so the only way to exit 
a loop is via BRK. The CONT here doesn't matter, the lifetime should be 
{4, 6}.


> +}
> +
> +/* if a continue is in the loop, all variables written after the
> + * continue and used outside the loop must be maintained for the
> + * whole loop, but not further */
> +TEST_F(LifetimeEvaluatorExactTest, NestedLoopWithWriteAfterContinue)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_BGNLOOP },
> +      {     TGSI_OPCODE_IF, {}, {in0},  {}},
> +      {       TGSI_OPCODE_CONT},
> +      {     TGSI_OPCODE_ENDIF},
> +      {     TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {   TGSI_OPCODE_ENDLOOP },
> +      {   TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 8}}));

Should be {5, 7} for the same reason.


> +}
> +
> +/* if a continue is in the loop, all variables written after the
> + * continue and used outside the loop must be maintained for all
> + * loops up untto the read scope, but not further */

untto? :)


> +TEST_F(LifetimeEvaluatorExactTest, Nested2LoopWithWriteAfterContinue)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_BGNLOOP },
> +      {     TGSI_OPCODE_BGNLOOP },
> +      {       TGSI_OPCODE_IF, {}, {in0},  {}},
> +      {         TGSI_OPCODE_CONT},
> +      {       TGSI_OPCODE_ENDIF},
> +      {       TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {     TGSI_OPCODE_ENDLOOP },
> +      {   TGSI_OPCODE_ENDLOOP },
> +      {   TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 10}}));

{6, 9}


> +}
> +
> +/* Temporary used to switch must live through all case statememts */
> +TEST_F(LifetimeEvaluatorExactTest, UseSwitchCase)
> +{
> +   const vector<MockCodeline> code = {
> +      {TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      {TGSI_OPCODE_SWITCH, {}, {1}, {}},
> +      { TGSI_OPCODE_CASE, {}, {1}, {}},
> +      { TGSI_OPCODE_CASE, {}, {1}, {}},
> +      { TGSI_OPCODE_BRK},
> +      { TGSI_OPCODE_DEFAULT},
> +      {TGSI_OPCODE_ENDSWITCH},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 3}}));

So, SWITCH/CASE is a bit of an odd-ball, and I don't think we really use 
it, precisely because of how weird it is.

I think the correct interpretation would be that all the sources on both 
the SWITCH and the corresponding CASE lines have a read access on the 
line of the switch statement.

Please adjust the test accordingly (also, use different sources for the 
SWITCH and CASE statements!).


> +}
> +
> +TEST_F(LifetimeEvaluatorExactTest, WriteTwoOnlyUseOne)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_DFRACEXP , {1, 2}, {in0}, {}},
> +      { TGSI_OPCODE_ADD , {3}, {2, in0}, {}},

Remove space between ADD and ,


> +      { TGSI_OPCODE_MOV, {out1}, {3}, {}},
> +      { TGSI_OPCODE_END},
> +
> +   };
> +   run (code, expectation({{-1,-1},{0,1}, {0,1}, {1,2}}));
> +}
> +
> +/* if a break  is in the loop, all variables written after the

Remove extra space between break and is, and break and and below.


> + * break  and used outside the loop must be maintained for the
> + * whole loop */
> +TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteAfterBreak)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_IF, {}, {in0}, {}},
> +      {     TGSI_OPCODE_BRK},
> +      {   TGSI_OPCODE_ENDIF},
> +      {   TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_MOV, {out0}, {1}, {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 6}}));
> +
> +}
> +
> +/* if a break is in the loop, but inside a switch case, so it
> + * referes to that inner loop. The variable has to survive the loop */
> +TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteAfterBreakInSwitchInLoop)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_SWITCH, {}, {in1}, {}},
> +      {  TGSI_OPCODE_CASE, {}, {in1}, {}},
> +      {   TGSI_OPCODE_BGNLOOP },
> +      {    TGSI_OPCODE_IF, {}, {in0}, {}},
> +      {     TGSI_OPCODE_BRK},
> +      {    TGSI_OPCODE_ENDIF},
> +      {    TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      {   TGSI_OPCODE_ENDLOOP },
> +      {  TGSI_OPCODE_DEFAULT, {}, {}, {}},
> +      { TGSI_OPCODE_ENDSWITCH, {}, {}, {}},
> +      { TGSI_OPCODE_MOV, {out0}, {1}, {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{2, 10}}));
> +}
> +
> +/* value read/write in differnt loops, conditional */
> +TEST_F(LifetimeEvaluatorExactTest, LoopsWithDifferntScopesConditionalWrite)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {  TGSI_OPCODE_IF, {}, {in0}, {}},
> +      {     TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      {   TGSI_OPCODE_ENDIF},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_BGNLOOP },
> +      {     TGSI_OPCODE_MOV, {out0}, {1}, {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0,7}}));
> +}
> +
> +
> +TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteInSwitch)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_SWITCH, {}, {in0},  {} },
> +      {    TGSI_OPCODE_CASE, {}, {in0},  {} },
> +      {     TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {    TGSI_OPCODE_BRK },
> +      {   TGSI_OPCODE_DEFAULT },
> +      {   TGSI_OPCODE_BRK },
> +      {   TGSI_OPCODE_ENDSWITCH },
> +      {   TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 9}}));
> +}
> +
> +/* value written in one case, and read in other, in loop
> + * - must survive the loop */
> +TEST_F(LifetimeEvaluatorExactTest, LoopWithReadWriteInSwitchDifferentCase)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_SWITCH, {}, {in0},  {} },
> +      {    TGSI_OPCODE_CASE, {}, {in0},  {} },
> +      {     TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {    TGSI_OPCODE_BRK },
> +      {   TGSI_OPCODE_DEFAULT },
> +      {     TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      {   TGSI_OPCODE_BRK },
> +      {   TGSI_OPCODE_ENDSWITCH },
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 9}}));
> +}
> +
> +
> +TEST_F(LifetimeEvaluatorExactTest, LoopRWInSwitchCaseLastCaseWithoutBreak)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_SWITCH, {}, {in0},  {} },
> +      {    TGSI_OPCODE_CASE, {}, {in0},  {} },
> +      {     TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {    TGSI_OPCODE_BRK },
> +      {   TGSI_OPCODE_DEFAULT },
> +      {     TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      {   TGSI_OPCODE_ENDSWITCH },
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 8}}));
> +}
> +
> +/* value read/write in same case, stays there */
> +TEST_F(LifetimeEvaluatorExactTest, LoopWithReadWriteInSwitchSameCase)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_SWITCH, {}, {in0},  {} },
> +      {    TGSI_OPCODE_CASE, {}, {in0},  {} },
> +      {     TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {     TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      {    TGSI_OPCODE_BRK },
> +      {   TGSI_OPCODE_DEFAULT },
> +      {   TGSI_OPCODE_BRK },
> +      {   TGSI_OPCODE_ENDSWITCH },
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{3,4}}));
> +}
> +
> +/* value read/write in all cases, should only live from first
> + * write to last read, but currently the whole loop is used. */
> +TEST_F(LifetimeEvaluatorAtLeastTest, LoopWithReadWriteInSwitchSameCase)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_SWITCH, {}, {in0},  {}},
> +      {    TGSI_OPCODE_CASE, {}, {in0},  {} },
> +      {     TGSI_OPCODE_MOV, {}, {in0},  {}},
> +      {    TGSI_OPCODE_BRK },
> +      {   TGSI_OPCODE_DEFAULT },
> +      {     TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {   TGSI_OPCODE_BRK },
> +      {   TGSI_OPCODE_ENDSWITCH },
> +      {   TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{3,9}}));
> +}
> +
> +/* value read/write in differnt loops */
> +TEST_F(LifetimeEvaluatorExactTest, LoopsWithDifferntScopes)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {     TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_BGNLOOP },
> +      {     TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{1,5}}));
> +}
> +
> +/* first read before first write wiredness with nested loops */
> +TEST_F(LifetimeEvaluatorExactTest, LoopsWithDifferntScopesConditionalReadBeforeWrite)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_BGNLOOP },
> +      {    TGSI_OPCODE_IF, {}, {in0},  {}},
> +      {     TGSI_OPCODE_MOV, {out0}, {1},  {}},
> +      {    TGSI_OPCODE_ENDIF},
> +      {   TGSI_OPCODE_ENDLOOP },
> +      {   TGSI_OPCODE_BGNLOOP },
> +      {     TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      {   TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0,9}}));
> +}
> +
> +/* The variable is conditionally read before first written, so
> + * it has to surive all the loops. */
> +TEST_F(LifetimeEvaluatorExactTest, FRaWSameInstructionInLoopAndCondition)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_BGNLOOP },
> +      {     TGSI_OPCODE_IF },
> +      {       TGSI_OPCODE_ADD, {1}, {1,in0}, {}},
> +      {     TGSI_OPCODE_ENDIF},
> +      {     TGSI_OPCODE_MOV, {1}, {in1}, {}},
> +      {  TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END},
> +
> +   };
> +   run (code, expectation({{-1,-1},{0,7}}));
> +}
> +
> +/* If unconditionally first written and read in the same
> + * instruction, then the register must be kept for the
> + * one write, but not more (undefined behaviour) */
> +
> +TEST_F(LifetimeEvaluatorExactTest, FRaWSameInstruction)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_ADD, {1}, {1,in0}, {}},
> +      { TGSI_OPCODE_END},
> +
> +   };
> +   run (code, expectation({{-1,-1},{0,1}}));
> +}
> +
> +/* If unconditionally written and read in the same
> + * instruction, various times then the register must be
> + * kept for the one write, but not more (undefined behaviour) */
> +
> +TEST_F(LifetimeEvaluatorExactTest, FRaWSameInstructionMoreThenOnce)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_ADD, {1}, {1,in0}, {}},
> +      { TGSI_OPCODE_ADD, {1}, {1,in0}, {}},
> +      { TGSI_OPCODE_END},
> +
> +   };
> +   run (code, expectation({{-1,-1},{0,2}}));
> +}
> +
> +
> +/* register is only written. This should not happen,
> + * but to handle the case we want the register to life
> + * at least one instruction */
> +TEST_F(LifetimeEvaluatorExactTest, WriteOnly)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0,1}}));
> +}
> +
> +/* register read in if */
> +TEST_F(LifetimeEvaluatorExactTest, SimpleReadForIf)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      { TGSI_OPCODE_ADD, {out0}, {in0, in1},  {}},
> +      { TGSI_OPCODE_IF, {}, {1}, {}},
> +      { TGSI_OPCODE_ENDIF}
> +   };
> +   run (code, expectation({{-1,-1},{0,2}}));
> +}
> +
> +/* register read in switch and cases */
> +TEST_F(LifetimeEvaluatorExactTest, SimpleReadForSwitchAndCase)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      { TGSI_OPCODE_SWITCH, {}, {1}, {}},
> +      { TGSI_OPCODE_CASE, {}, {1}, {}},
> +      { TGSI_OPCODE_CASE, {}, {1}, {}},
> +      { TGSI_OPCODE_END, {}, {1}, {}},
> +   };
> +   run (code, expectation({{-1,-1},{0,3}}));
> +}
> +
> +/* first read before first write wiredness with nested loops */
> +TEST_F(LifetimeEvaluatorExactTest, LoopsWithDifferentScopesCondReadBeforeWrite)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_BGNLOOP },
> +      {    TGSI_OPCODE_IF, {}, {in0}, {}},
> +      {     TGSI_OPCODE_MOV, {out0}, {1}, {}},
> +      {    TGSI_OPCODE_ENDIF},
> +      {   TGSI_OPCODE_ENDLOOP },
> +      {   TGSI_OPCODE_BGNLOOP },
> +      {     TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      {   TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0,9}}));
> +}
> +
> +
> +TEST_F(LifetimeEvaluatorExactTest, WriteTwoReadOne)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_DFRACEXP , {1, 2}, {in0}, {}},
> +      { TGSI_OPCODE_ADD , {3}, {2, in0}, {}},
> +      { TGSI_OPCODE_MOV, {out1}, {3}, {}},
> +      { TGSI_OPCODE_END},
> +
> +   };
> +   run (code, expectation({{-1,-1},{0,1}, {0,1}, {1,2}}));
> +}
> +
> +
> +TEST_F(LifetimeEvaluatorExactTest, SomeScopesAndNoEndProgramId)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0},  {}},
> +      { TGSI_OPCODE_IF, {}, {1}, {}},
> +      { TGSI_OPCODE_MOV, {2}, {1}, {}},
> +      { TGSI_OPCODE_ENDIF},
> +      { TGSI_OPCODE_IF, {}, {1}, {}},
> +      { TGSI_OPCODE_MOV, {out0}, {2}, {}},
> +      { TGSI_OPCODE_ENDIF},
> +   };
> +   run (code, expectation({{-1,-1},{0,4}, {2,5}}));
> +}
> +
> +TEST_F(LifetimeEvaluatorExactTest, SerialReadWrite)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_MOV, {2}, {1}, {}},
> +      { TGSI_OPCODE_MOV, {3}, {2}, {}},
> +      { TGSI_OPCODE_MOV, {out0}, {3}, {}},
> +      { TGSI_OPCODE_END},
> +
> +   };
> +   run (code, expectation({{-1,-1},{0,1}, {1,2}, {2,3}}));
> +}
> +
> +
> +/* Check that two destination registers are used */
> +TEST_F(LifetimeEvaluatorExactTest, TwoDestRegisters)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_DFRACEXP , {1,2}, {in0},  {}},
> +      { TGSI_OPCODE_ADD, {out0}, {1,2}, {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0,1}, {0,1}}));
> +}
> +
> +/* Check that two destination registers are used */
> +TEST_F(LifetimeEvaluatorExactTest, WriteInLoopInConditionalReadOutside)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP},
> +      {   TGSI_OPCODE_IF, {}, {in0}, {}},
> +      {     TGSI_OPCODE_BGNLOOP},
> +      {       TGSI_OPCODE_MOV, {1}, {in1}, {}},
> +      {     TGSI_OPCODE_ENDLOOP},
> +      {   TGSI_OPCODE_ENDIF},
> +      {   TGSI_OPCODE_ADD, {2}, {1,in1}, {}},
> +      { TGSI_OPCODE_ENDLOOP},
> +      { TGSI_OPCODE_MOV, {out0}, {2}, {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0,7}, {6,8}}));
> +}
> +
> +
> +/*
> + * With two destinations if one value is thrown away, we must
> + * ensure that the two output registers don't merge.
> + * In this test case the last access for 2 and 3 is in line 4,
> + * but 4 can only be merged with 3 because it is read, 2 on the
> + * other hand is written to, and merging it with 4 would result in
> + * a bug. */
> +TEST_F(LifetimeEvaluatorExactTest, WritePastLastRead2)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_MOV, {2}, {in0}, {}},
> +      { TGSI_OPCODE_ADD, {3}, {1,2}, {}},
> +      { TGSI_OPCODE_DFRACEXP , {2,4}, {3}, {}},
> +      { TGSI_OPCODE_MOV, {out1}, {4}, {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0,2}, {1,4}, {2,3}, {3,4}}));
> +}
> +
> +/* Check that three destination registers are used */
> +TEST_F(LifetimeEvaluatorExactTest, ThreeSourceRegisters)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_DFRACEXP , {1,2}, {in0},  {}},
> +      { TGSI_OPCODE_ADD , {3}, {in0, in1},  {}},
> +      { TGSI_OPCODE_MAD, {out0}, {1,2, 3}, {}},

Be consistent about whitespace, please.

There are more issues like this throughout, please fix them.

Cheers,
Nicolai


> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0,2}, {0,2}, {1,2}}));
> +}
> +
> +/* Check minimal lifetime for registers only written to */
> +TEST_F(LifetimeEvaluatorExactTest, OverwriteWrittenOnlyTemps)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV , {1}, {in0},  {}},
> +      { TGSI_OPCODE_MOV , {2}, {in1},  {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0,1}, {1,2}}));
> +}
> +
> +/* same register is only written. This should not happen,
> + * but to handle the case we want the register to life
> + * at least past the last write instruction */
> +TEST_F(LifetimeEvaluatorExactTest, WriteOnlyTwiceSame)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0,2}}));
> +}
> +
> +
> +/* Dead code elimination should catch and remove the case
> + * when a variable is written after its last read, but
> + * we want the code to be aware of this case.
> + * The life time of this uselessly written variable is set
> + * to the instruction after the write, because
> + * otherwise it could be re-used too early. */
> +TEST_F(LifetimeEvaluatorExactTest, WritePastLastRead)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      { TGSI_OPCODE_MOV, {2}, {1}, {}},
> +      { TGSI_OPCODE_MOV, {1}, {2}, {}},
> +      { TGSI_OPCODE_END},
> +
> +   };
> +   run (code, expectation({{-1,-1},{0,3}, {1,2}}));
> +}
> +
> +/* if a break is in the loop, all variables written after the
> + * break and used outside the loop the variable must survive the
> + * outer loop
> + */
> +TEST_F(LifetimeEvaluatorExactTest, NestedLoopWithWriteAfterBreak)
> +{
> +   const vector<MockCodeline> code = {
> +      { TGSI_OPCODE_BGNLOOP },
> +      {   TGSI_OPCODE_BGNLOOP },
> +      {     TGSI_OPCODE_IF, {}, {in0}, {}},
> +      {       TGSI_OPCODE_BRK},
> +      {     TGSI_OPCODE_ENDIF},
> +      {     TGSI_OPCODE_MOV, {1}, {in0}, {}},
> +      {   TGSI_OPCODE_ENDLOOP },
> +      {   TGSI_OPCODE_MOV, {out0}, {1}, {}},
> +      { TGSI_OPCODE_ENDLOOP },
> +      { TGSI_OPCODE_END}
> +   };
> +   run (code, expectation({{-1,-1},{0, 8}}));
> +}
> +
> +/* Implementation of helper and test classes */
> +
> +MockShader::~MockShader()
> +{
> +   free();
> +   ralloc_free(mem_ctx);
> +}
> +
> +int MockShader::get_num_temps()
> +{
> +   return num_temps;
> +}
> +
> +
> +exec_list* MockShader::get_program()
> +{
> +   return program;
> +}
> +
> +MockShader::MockShader(const vector<MockCodeline>& source):
> +   num_temps(0)
> +{
> +   mem_ctx = ralloc_context(NULL);
> +
> +   program = new(mem_ctx) exec_list();
> +
> +   for (MockCodeline i: source) {
> +      glsl_to_tgsi_instruction *next_instr = new(mem_ctx) glsl_to_tgsi_instruction();
> +      next_instr->op = i.op;
> +      next_instr->info = tgsi_get_opcode_info(i.op);
> +
> +      assert(i.src.size() < 4);
> +      assert(i.dst.size() < 3);
> +      assert(i.tex_offsets.size() < 3);
> +
> +      for (unsigned  k = 0; k < i.src.size(); ++k) {
> +         next_instr->src[k] = create_src_register(i.src[k]);
> +      }
> +      for (unsigned k = 0; k < i.dst.size(); ++k) {
> +         next_instr->dst[k] = create_dst_register(i.dst[k]);
> +      }
> +      next_instr->tex_offset_num_offset = i.tex_offsets.size();
> +      next_instr->tex_offsets = new st_src_reg[i.tex_offsets.size()];
> +      for (unsigned k = 0; k < i.tex_offsets.size(); ++k) {
> +         next_instr->tex_offsets[k] = create_src_register(i.tex_offsets[k]);
> +      }
> +
> +      program->push_tail(next_instr);
> +   }
> +   ++num_temps;
> +}
> +
> +void MockShader::free()
> +{
> +   /* the list is not fully initialized, so
> +    * tearing it down also must be done manually. */
> +   exec_node *p;
> +   while ((p = program->pop_head())) {
> +      glsl_to_tgsi_instruction * instr = static_cast<glsl_to_tgsi_instruction *>(p);
> +      if (instr->tex_offset_num_offset > 0)
> +         delete[] instr->tex_offsets;
> +      delete p;
> +   }
> +   program = 0;
> +   num_temps = 0;
> +}
> +
> +st_src_reg MockShader::create_src_register(int src_idx)
> +{
> +   gl_register_file file;
> +   int idx = 0;
> +   if (src_idx > 0) {
> +      file = PROGRAM_TEMPORARY;
> +      idx = src_idx;
> +      if (num_temps < idx)
> +         num_temps = idx;
> +   } else {
> +      file = PROGRAM_INPUT;
> +      idx = -src_idx;
> +   }
> +   return st_src_reg(file, idx, GLSL_TYPE_INT);
> +
> +}
> +
> +st_dst_reg MockShader::create_dst_register(int dst_idx)
> +{
> +   gl_register_file file;
> +   int idx = 0;
> +   if (dst_idx > 0) {
> +      file = PROGRAM_TEMPORARY;
> +      idx = dst_idx;
> +      if (num_temps < idx)
> +         num_temps = idx;
> +   } else {
> +      file = PROGRAM_OUTPUT;
> +      idx = - dst_idx;
> +   }
> +   return st_dst_reg(file, 0xF, GLSL_TYPE_INT, idx);
> +}
> +
> +
> +void MesaTestWithMemCtx::SetUp()
> +{
> +   mem_ctx = ralloc_context(nullptr);
> +}
> +
> +void MesaTestWithMemCtx::TearDown()
> +{
> +   ralloc_free(mem_ctx);
> +   mem_ctx = nullptr;
> +}
> +
> +void LifetimeEvaluatorTest::run(const vector<MockCodeline>& code, const expectation& e)
> +{
> +   MockShader shader(code);
> +   std::vector<lifetime> result(shader.get_num_temps());
> +
> +   get_temp_registers_required_lifetimes(mem_ctx, shader.get_program(),
> +                                shader.get_num_temps(), &result[0]);
> +
> +   /* lifetimes[0] not used, but created for simpler processing */
> +   ASSERT_EQ(result.size(), e.size());
> +   check(result, e);
> +}
> +
> +
> +void LifetimeEvaluatorExactTest::check( const vector<lifetime>& lifetimes,
> +                                        const expectation& e)
> +{
> +   for (unsigned i = 1; i < lifetimes.size(); ++i) {
> +      EXPECT_EQ(lifetimes[i].begin, e[i][0]);
> +      EXPECT_EQ(lifetimes[i].end, e[i][1]);
> +   }
> +}
> +
> +void LifetimeEvaluatorAtLeastTest::check( const vector<lifetime>& lifetimes,
> +                                          const expectation& e)
> +{
> +   for (unsigned i = 1; i < lifetimes.size(); ++i) {
> +      EXPECT_LE(lifetimes[i].begin, e[i][0]);
> +      EXPECT_GE(lifetimes[i].end, e[i][1]);
> +   }
> +}
> 


-- 
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.


More information about the mesa-dev mailing list