1/*
2 * Copyright (C) 2021 Collabora, Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#include "agx_test.h"
25
26#include <gtest/gtest.h>
27
28static void
29agx_optimize_and_dce(agx_context *ctx)
30{
31   agx_optimizer(ctx);
32   agx_dce(ctx);
33}
34
35#define CASE(instr, expected) INSTRUCTION_CASE(instr, expected, agx_optimize_and_dce)
36#define NEGCASE(instr) CASE(instr, instr)
37
38static inline agx_index
39agx_fmov(agx_builder *b, agx_index s0)
40{
41    agx_index tmp = agx_temp(b->shader, s0.size);
42    agx_fmov_to(b, tmp, s0);
43    return tmp;
44}
45
46class Optimizer : public testing::Test {
47protected:
48   Optimizer() {
49      mem_ctx = ralloc_context(NULL);
50
51      wx     = agx_register(0, AGX_SIZE_32);
52      wy     = agx_register(2, AGX_SIZE_32);
53      wz     = agx_register(4, AGX_SIZE_32);
54
55      hx     = agx_register(0, AGX_SIZE_16);
56   }
57
58   ~Optimizer() {
59      ralloc_free(mem_ctx);
60   }
61
62   void *mem_ctx;
63
64   agx_index wx, wy, wz, hx;
65};
66
67TEST_F(Optimizer, FusedFABSNEG)
68{
69   CASE(agx_fadd_to(b, wz, agx_fmov(b, agx_abs(wx)), wy),
70        agx_fadd_to(b, wz, agx_abs(wx), wy));
71
72   CASE(agx_fmul_to(b, wz, wx, agx_fmov(b, agx_neg(agx_abs(wx)))),
73        agx_fmul_to(b, wz, wx, agx_neg(agx_abs(wx))));
74}
75
76TEST_F(Optimizer, Copyprop)
77{
78   CASE(agx_fmul_to(b, wz, wx, agx_mov(b, wy)), agx_fmul_to(b, wz, wx, wy));
79   CASE(agx_fmul_to(b, wz, agx_mov(b, wx), agx_mov(b, wy)), agx_fmul_to(b, wz, wx, wy));
80}
81
82TEST_F(Optimizer, InlineHazards)
83{
84   NEGCASE(agx_p_combine_to(b, wx, agx_mov_imm(b, AGX_SIZE_32, 0), wy, wz, wz));
85}
86
87TEST_F(Optimizer, CopypropRespectsAbsNeg)
88{
89   CASE(agx_fadd_to(b, wz, agx_abs(agx_mov(b, wx)), wy),
90        agx_fadd_to(b, wz, agx_abs(wx), wy));
91
92   CASE(agx_fadd_to(b, wz, agx_neg(agx_mov(b, wx)), wy),
93        agx_fadd_to(b, wz, agx_neg(wx), wy));
94
95   CASE(agx_fadd_to(b, wz, agx_neg(agx_abs(agx_mov(b, wx))), wy),
96        agx_fadd_to(b, wz, agx_neg(agx_abs(wx)), wy));
97}
98
99TEST_F(Optimizer, IntCopyprop)
100{
101   CASE(agx_xor_to(b, wz, agx_mov(b, wx), wy),
102        agx_xor_to(b, wz, wx, wy));
103}
104
105TEST_F(Optimizer, IntCopypropDoesntConvert)
106{
107   NEGCASE({
108         agx_index cvt = agx_temp(b->shader, AGX_SIZE_32);
109         agx_mov_to(b, cvt, hx);
110         agx_xor_to(b, wz, cvt, wy);
111   });
112}
113