xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r600/sfn/sfn_conditionaljumptracker.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* -*- mesa-c++  -*-
2  * Copyright 2019 Collabora LTD
3  * Author: Gert Wollny <[email protected]>
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "sfn_conditionaljumptracker.h"
8 
9 #include "sfn_debug.h"
10 
11 #include <iostream>
12 #include <memory>
13 #include <stack>
14 #include <vector>
15 
16 namespace r600 {
17 
18 using std::shared_ptr;
19 using std::stack;
20 using std::vector;
21 
22 struct StackFrame {
23 
StackFramer600::StackFrame24    StackFrame(r600_bytecode_cf *s, JumpType t):
25        type(t),
26        start(s)
27    {
28    }
29 
30    virtual ~StackFrame();
31 
32    JumpType type;
33    r600_bytecode_cf *start;
34    vector<r600_bytecode_cf *> mid;
35 
36    virtual void fixup_mid(r600_bytecode_cf *cf) = 0;
37    virtual void fixup_pop(r600_bytecode_cf *final) = 0;
38 };
39 
40 using PStackFrame = shared_ptr<StackFrame>;
41 
42 struct IfFrame : public StackFrame {
43    IfFrame(r600_bytecode_cf *s);
44    void fixup_mid(r600_bytecode_cf *cf) override;
45    void fixup_pop(r600_bytecode_cf *final) override;
46 };
47 
48 struct LoopFrame : public StackFrame {
49    LoopFrame(r600_bytecode_cf *s);
50    void fixup_mid(r600_bytecode_cf *cf) override;
51    void fixup_pop(r600_bytecode_cf *final) override;
52 };
53 
54 struct ConditionalJumpTrackerImpl {
55    ConditionalJumpTrackerImpl();
56    stack<PStackFrame> m_jump_stack;
57    stack<PStackFrame> m_loop_stack;
58    int m_current_loop_stack_pos;
59 };
60 
ConditionalJumpTrackerImpl()61 ConditionalJumpTrackerImpl::ConditionalJumpTrackerImpl():
62     m_current_loop_stack_pos(0)
63 {
64 }
65 
~ConditionalJumpTracker()66 ConditionalJumpTracker::~ConditionalJumpTracker() { delete impl; }
67 
ConditionalJumpTracker()68 ConditionalJumpTracker::ConditionalJumpTracker()
69 {
70    impl = new ConditionalJumpTrackerImpl();
71 }
72 
73 void
push(r600_bytecode_cf * start,JumpType type)74 ConditionalJumpTracker::push(r600_bytecode_cf *start, JumpType type)
75 {
76    PStackFrame f;
77    switch (type) {
78    case jt_if:
79       f.reset(new IfFrame(start));
80       break;
81    case jt_loop:
82       f.reset(new LoopFrame(start));
83       impl->m_loop_stack.push(f);
84       break;
85    }
86    impl->m_jump_stack.push(f);
87 }
88 
89 bool
pop(r600_bytecode_cf * final,JumpType type)90 ConditionalJumpTracker::pop(r600_bytecode_cf *final, JumpType type)
91 {
92    if (impl->m_jump_stack.empty())
93       return false;
94 
95    auto& frame = *impl->m_jump_stack.top();
96    if (frame.type != type)
97       return false;
98 
99    frame.fixup_pop(final);
100    if (frame.type == jt_loop)
101       impl->m_loop_stack.pop();
102    impl->m_jump_stack.pop();
103    return true;
104 }
105 
106 bool
add_mid(r600_bytecode_cf * source,JumpType type)107 ConditionalJumpTracker::add_mid(r600_bytecode_cf *source, JumpType type)
108 {
109    if (impl->m_jump_stack.empty()) {
110       sfn_log << "Jump stack empty\n";
111       return false;
112    }
113 
114    PStackFrame pframe;
115    if (type == jt_loop) {
116       if (impl->m_loop_stack.empty()) {
117          sfn_log << "Loop jump stack empty\n";
118          return false;
119       }
120       pframe = impl->m_loop_stack.top();
121    } else {
122       pframe = impl->m_jump_stack.top();
123    }
124 
125    pframe->mid.push_back(source);
126    pframe->fixup_mid(source);
127    return true;
128 }
129 
IfFrame(r600_bytecode_cf * s)130 IfFrame::IfFrame(r600_bytecode_cf *s):
131     StackFrame(s, jt_if)
132 {
133 }
134 
~StackFrame()135 StackFrame::~StackFrame() {}
136 
137 void
fixup_mid(r600_bytecode_cf * source)138 IfFrame::fixup_mid(r600_bytecode_cf *source)
139 {
140    /* JUMP target is ELSE */
141    start->cf_addr = source->id;
142 }
143 
144 void
fixup_pop(r600_bytecode_cf * final)145 IfFrame::fixup_pop(r600_bytecode_cf *final)
146 {
147    /* JUMP or ELSE target is one past last CF instruction */
148    unsigned offset = final->eg_alu_extended ? 4 : 2;
149    auto src = mid.empty() ? start : mid[0];
150    src->cf_addr = final->id + offset;
151    src->pop_count = 1;
152 }
153 
LoopFrame(r600_bytecode_cf * s)154 LoopFrame::LoopFrame(r600_bytecode_cf *s):
155     StackFrame(s, jt_loop)
156 {
157 }
158 
159 void
fixup_mid(UNUSED r600_bytecode_cf * mid)160 LoopFrame::fixup_mid(UNUSED r600_bytecode_cf *mid)
161 {
162 }
163 
164 void
fixup_pop(r600_bytecode_cf * final)165 LoopFrame::fixup_pop(r600_bytecode_cf *final)
166 {
167    /* LOOP END address is past LOOP START */
168    final->cf_addr = start->id + 2;
169 
170    /* LOOP START address is past LOOP END*/
171    start->cf_addr = final->id + 2;
172 
173    /* BREAK and CONTINUE point at LOOP END*/
174    for (auto m : mid)
175       m->cf_addr = final->id;
176 }
177 
178 } // namespace r600
179