| 1148 | } |
| 1149 | |
| 1150 | GcnToken* GcnGotoEliminator::moveOutwardLoop(GcnToken* gotoToken, const Scope& scope) |
| 1151 | { |
| 1152 | // first, replace the original goto with a value set and insert a break. |
| 1153 | |
| 1154 | // create a flag variable, initialize to false |
| 1155 | // all variables are global so no need to worry about redefinition. |
| 1156 | auto var = m_factory.createVariable({ 0, GcnScalarType::Bool }); |
| 1157 | // set the variable to true, marking the goto happened |
| 1158 | auto setValue = m_factory.createSetValue({ 1, GcnScalarType::Bool }, var); |
| 1159 | // create the break |
| 1160 | auto branch = m_factory.createBranch(scope.end); |
| 1161 | // replace the old goto |
| 1162 | auto ptr = m_tokens->insert(gotoToken->getIterator(), var); |
| 1163 | ptr = m_tokens->insertAfter(ptr, setValue); |
| 1164 | ptr = m_tokens->insertAfter(ptr, branch); |
| 1165 | m_tokens->erase(gotoToken); |
| 1166 | |
| 1167 | // second, move the original conditional goto to the scope end |
| 1168 | auto tokenIf = m_factory.createIf(GcnConditionOp::EqBool, 1, var); |
| 1169 | auto tokenIfEnd = m_factory.createIfEnd(tokenIf, nullptr); |
| 1170 | auto newGoto = m_factory.createBranch(gotoToken->getMatch()); |
| 1171 | auto resetVar = m_factory.createSetValue({ 0, GcnScalarType::Bool }, var); |
| 1172 | |
| 1173 | ptr = m_tokens->insertAfter(scope.end->getIterator(), tokenIf); |
| 1174 | ptr = m_tokens->insertAfter(ptr, resetVar); // deactive the goto condition |
| 1175 | ptr = m_tokens->insertAfter(ptr, newGoto); |
| 1176 | m_tokens->insertAfter(ptr, tokenIfEnd); |
| 1177 | |
| 1178 | return newGoto; |
| 1179 | } |
| 1180 | |
| 1181 | bool GcnGotoEliminator::isBackGoto(GcnToken* gotoToken) |
| 1182 | { |
nothing calls this directly
no test coverage detected