00001
#include "ShOptimizations.hpp"
00002
#include <map>
00003
#include <set>
00004
#include <utility>
00005
#include <iostream>
00006
#include "ShBitSet.hpp"
00007
#include "ShCtrlGraph.hpp"
00008
#include "ShDebug.hpp"
00009
#include "ShEvaluate.hpp"
00010
#include "ShContext.hpp"
00011
#include "ShSyntax.hpp"
00012
#include <sstream>
00013
#include <fstream>
00014
00015
00016
00017
00018
#ifdef SH_DEBUG_OPTIMIZER
00019
#ifndef SH_DEBUG_CONSTPROP
00020
#define SH_DEBUG_CONSTPROP
00021
#endif
00022
#endif
00023
00024
namespace {
00025
00026
using namespace SH;
00027
00028
typedef std::queue<ValueTracking::Def> ConstWorkList;
00029
00030
struct ConstProp :
public ShStatementInfo {
00031 ConstProp(ShStatement* stmt,
00032 ConstWorkList& worklist)
00033 : stmt(stmt)
00034 {
00035
for (
int i = 0; i <
opInfo[stmt->op].
arity ; i++) {
00036
for (
int j = 0; j < stmt->src[i].size(); j++) {
00037
switch(stmt->src[i].node()->kind()) {
00038
case SH_INPUT:
00039
case SH_OUTPUT:
00040
case SH_INOUT:
00041
case SH_TEXTURE:
00042
case SH_STREAM:
00043
case SH_PALETTE:
00044 src[i].push_back(Cell(Cell::BOTTOM));
00045
break;
00046
case SH_TEMP:
00047
if (stmt->src[i].uniform()) {
00048
00049
00050
if (stmt->src[i].meta(
"opt:lifting") !=
"never") {
00051 src[i].push_back(Cell(Cell::UNIFORM, stmt->src[i], j));
00052 }
else {
00053 src[i].push_back(Cell(Cell::BOTTOM));
00054 }
00055 }
else {
00056 src[i].push_back(Cell(Cell::TOP));
00057 }
00058
break;
00059
case SH_CONST:
00060 src[i].push_back(Cell(Cell::CONSTANT, stmt->src[i].getValue(j)));
00061
break;
00062 }
00063 }
00064 }
00065 updateDest(worklist);
00066 }
00067
00068
ShStatementInfo* clone() const;
00069
00070
int idx(
int destindex,
int source)
00071 {
00072
return (stmt->src[source].size() == 1 ? 0 : destindex);
00073 }
00074
00075
void updateDest(ConstWorkList& worklist)
00076 {
00077 dest.clear();
00078
00079
00080
if (
opInfo[stmt->op].
result_source == ShOperationInfo::IGNORE)
return;
00081
00082
if (stmt->op ==
SH_OP_ASN) {
00083
for (
int i = 0; i < stmt->dest.size(); i++) {
00084 dest.push_back(src[0][i]);
00085
if (src[0][i].state == Cell::UNIFORM ||
00086 src[0][i].state == Cell::CONSTANT) {
00087 worklist.push(ValueTracking::Def(stmt, i));
00088 }
00089 }
00090 }
else if (
opInfo[stmt->op].
result_source == ShOperationInfo::EXTERNAL) {
00091
00092
00093
for (
int i = 0; i < stmt->dest.size(); i++) {
00094 dest.push_back(Cell(Cell::BOTTOM));
00095 }
00096 }
else if (
opInfo[stmt->op].
result_source == ShOperationInfo::LINEAR) {
00097
00098
00099
00100
bool all_fields_uniform =
true;
00101
for (
int i = 0; i < stmt->dest.size(); i++) {
00102
bool alluniform =
true;
00103
bool allconst =
true;
00104
for (
int s = 0; s <
opInfo[stmt->op].
arity; s++) {
00105
if (src[s][idx(i,s)].state != Cell::CONSTANT) {
00106 allconst =
false;
00107
if (src[s][idx(i,s)].state != Cell::UNIFORM) {
00108 alluniform =
false;
00109 }
00110 }
00111 }
00112
if (!alluniform) all_fields_uniform =
false;
00113
if (allconst) {
00114 ShVariable tmpdest(
new ShVariableNode(SH_CONST, 1));
00115 ShStatement eval(*stmt);
00116 eval.dest = tmpdest;
00117
for (
int k = 0; k <
opInfo[stmt->op].
arity; k++) {
00118 ShVariable tmpsrc(
new ShVariableNode(SH_CONST, 1));
00119 tmpsrc.setValue(0, src[k][idx(i,k)].value);
00120 eval.src[k] = tmpsrc;
00121 }
00122 evaluate(eval);
00123 dest.push_back(Cell(Cell::CONSTANT, tmpdest.getValue(0)));
00124 worklist.push(ValueTracking::Def(stmt, i));
00125 }
else {
00126 dest.push_back(Cell(Cell::BOTTOM));
00127 }
00128 }
00129
00130
00131
00132
00133
00134
if (all_fields_uniform) {
00135 dest.clear();
00136
for (
int i = 0; i < stmt->dest.size(); i++) {
00137 dest.push_back(Cell(Cell::UNIFORM,
this, i));
00138 worklist.push(ValueTracking::Def(stmt, i));
00139 }
00140 }
00141 }
else if (
opInfo[stmt->op].
result_source == ShOperationInfo::ALL) {
00142
00143
bool allconst =
true;
00144
bool alluniform =
true;
00145
for (
int s = 0; s <
opInfo[stmt->op].
arity; s++) {
00146
for (
unsigned int k = 0; k < src[s].size(); k++) {
00147
if (src[s][k].state != Cell::CONSTANT) {
00148 allconst =
false;
00149
if (src[s][k].state != Cell::UNIFORM) {
00150 alluniform =
false;
00151 }
00152 }
00153 }
00154 }
00155
if (allconst) {
00156 ShVariable tmpdest(
new ShVariableNode(SH_CONST, stmt->dest.size()));
00157 ShStatement eval(*stmt);
00158 eval.dest = tmpdest;
00159
for (
int i = 0; i <
opInfo[stmt->op].
arity; i++) {
00160 ShVariable tmpsrc(
new ShVariableNode(SH_CONST, stmt->src[i].size()));
00161
for (
int j = 0; j < stmt->src[i].size(); j++) {
00162 tmpsrc.setValue(j, src[i][j].value);
00163 }
00164 eval.src[i] = tmpsrc;
00165 }
00166 evaluate(eval);
00167
for (
int i = 0; i < stmt->dest.size(); i++) {
00168 dest.push_back(Cell(Cell::CONSTANT, tmpdest.getValue(i)));
00169 worklist.push(ValueTracking::Def(stmt, i));
00170 }
00171 }
else if (alluniform) {
00172
for (
int i = 0; i < stmt->dest.size(); i++) {
00173 dest.push_back(Cell(Cell::UNIFORM,
this, i));
00174 worklist.push(ValueTracking::Def(stmt, i));
00175 }
00176 }
else {
00177
for (
int i = 0; i < stmt->dest.size(); i++) {
00178 dest.push_back(Cell(Cell::BOTTOM));
00179 worklist.push(ValueTracking::Def(stmt, i));
00180 }
00181 }
00182 }
else {
00183 SH_DEBUG_ASSERT(0 &&
"Invalid result source type");
00184 }
00185 }
00186
00187
typedef int ValueNum;
00188
00189
struct Uniform {
00190 Uniform()
00191 : constant(false),
00192 valuenum(-1)
00193 {
00194 }
00195
00196 Uniform(
float constval)
00197 : constant(true),
00198 constval(constval)
00199 {
00200 }
00201
00202 Uniform(
int valuenum,
int index,
bool neg)
00203 : constant(false),
00204 valuenum(valuenum), index(index), neg(neg)
00205 {
00206 }
00207
00208
bool operator==(
const Uniform& other)
const
00209
{
00210
if (constant != other.constant)
return false;
00211
00212
if (constant) {
00213
return constval == other.constval;
00214 }
else {
00215
if (valuenum != other.valuenum)
return false;
00216
if (index != other.index)
return false;
00217
if (neg != other.neg)
return false;
00218
return true;
00219 }
00220 }
00221
00222
bool operator!=(
const Uniform& other)
const
00223
{
00224
return !(*
this == other);
00225 }
00226
00227
bool constant;
00228
00229 ValueNum valuenum;
00230
int index;
00231
bool neg;
00232
00233
float constval;
00234 };
00235
00236
class Value {
00237
public:
00238
enum Type {
00239 NODE,
00240 STMT
00241 };
00242
00243 Type type;
00244
00245
00246 ShVariableNodePtr node;
00247
00248
00249
ShOperation op;
00250
int destsize;
00251 std::vector<Uniform> src[3];
00252
00253
static void clear()
00254 {
00255 m_values.clear();
00256 }
00257
00258
static ValueNum lookup(
const ShVariableNodePtr& node)
00259 {
00260
for (std::size_t i = 0; i < m_values.size(); i++) {
00261
if (m_values[i]->type == NODE && m_values[i]->node == node)
return i;
00262 }
00263 m_values.push_back(
new Value(node));
00264
return m_values.size() - 1;
00265 }
00266
00267
bool operator==(
const Value& other)
const
00268
{
00269
if (type != other.type)
return false;
00270
if (type == NODE) {
00271
return node == other.node;
00272 }
else if (type == STMT) {
00273
if (op != other.op || destsize != other.destsize)
return false;
00274
for (
int i = 0; i <
opInfo[op].
arity; i++) {
00275
if (src[i].size() != other.src[i].size())
return false;
00276
for (std::size_t j = 0; j < src[i].size(); j++) {
00277
if (src[i][j] != other.src[i][j])
return false;
00278 }
00279 }
00280
return true;
00281 }
00282
return false;
00283 }
00284
00285
bool operator!=(
const Value& other)
const
00286
{
00287
return !(*
this == other);
00288 }
00289
00290
static ValueNum lookup(ConstProp* cp)
00291 {
00292 Value* val =
new Value(cp);
00293
00294
for (std::size_t i = 0; i < m_values.size(); i++) {
00295
if (m_values[i]->type != STMT)
continue;
00296
if (m_values[i]->op != cp->stmt->op)
continue;
00297
00298
if (*val == *m_values[i]) {
00299
delete val;
00300
return i;
00301 }
00302 }
00303 m_values.push_back(val);
00304
return m_values.size() - 1;
00305 }
00306
00307
static Value* get(ValueNum n)
00308 {
00309
return m_values[n];
00310 }
00311
00312
static void dump(std::ostream& out);
00313
00314
private:
00315 Value(
const ShVariableNodePtr& node)
00316 : type(NODE), node(node)
00317 {
00318 }
00319
00320 Value(ConstProp* cp)
00321 : type(STMT), node(0), op(cp->stmt->op), destsize(cp->stmt->dest.size())
00322 {
00323
for (
int i = 0; i <
opInfo[cp->stmt->op].
arity; i++) {
00324
for (std::size_t j = 0; j < cp->src[i].size(); j++) {
00325
if (cp->src[i][j].state == Cell::UNIFORM) {
00326 src[i].push_back(cp->src[i][j].uniform);
00327 }
else {
00328 src[i].push_back(Uniform(cp->src[i][j].value));
00329 }
00330 }
00331 }
00332 }
00333
00334
static std::vector<Value*> m_values;
00335 };
00336
00337
struct Cell {
00338
enum State {
00339 BOTTOM,
00340 CONSTANT,
00341 UNIFORM,
00342 TOP
00343 };
00344
00345 Cell(State state,
float value = 0.0)
00346 : state(state), value(value)
00347 {
00348 }
00349
00350 Cell(State state,
const ShVariable& var,
int index)
00351 : state(state), value(0.0),
00352 uniform(Value::lookup(var.node()), var.swizzle()[index], var.neg())
00353 {
00354 }
00355
00356 Cell(State state, ConstProp* cp,
int index)
00357 : state(state), value(0.0),
00358 uniform(Value::lookup(cp), index, false)
00359 {
00360 }
00361
00362
bool operator==(
const Cell& other)
const
00363
{
00364
return state == other.state && value == other.value;
00365 }
00366
bool operator!=(
const Cell& other)
const
00367
{
00368
return !(*
this == other);
00369 }
00370
00371 State state;
00372
float value;
00373
00374 Uniform uniform;
00375 };
00376
00377 ShStatement* stmt;
00378 std::vector<Cell> dest;
00379 std::vector<Cell> src[3];
00380 };
00381
00382
ShStatementInfo* ConstProp::clone()
const
00383
{
00384
return new ConstProp(*
this);
00385 }
00386
00387 ConstProp::Cell meet(
const ConstProp::Cell& a,
const ConstProp::Cell& b)
00388 {
00389
if (a.state == ConstProp::Cell::BOTTOM || b.state == ConstProp::Cell::BOTTOM) {
00390
return ConstProp::Cell(ConstProp::Cell::BOTTOM);
00391 }
00392
if (a.state != b.state
00393 && (a.state != ConstProp::Cell::TOP && b.state != ConstProp::Cell::TOP)) {
00394
return ConstProp::Cell(ConstProp::Cell::BOTTOM);
00395 }
00396
00397
00398
if (a.state == b.state) {
00399
if (a.state == ConstProp::Cell::CONSTANT) {
00400
if (a.value == b.value) {
00401
return a;
00402 }
else {
00403
return ConstProp::Cell(ConstProp::Cell::BOTTOM);
00404 }
00405 }
00406
if (a.state == ConstProp::Cell::UNIFORM) {
00407
if (a.uniform == b.uniform)
return a;
00408
return ConstProp::Cell(ConstProp::Cell::BOTTOM);
00409 }
00410 }
00411
00412
if (a.state != ConstProp::Cell::TOP)
return a;
00413
if (b.state != ConstProp::Cell::TOP)
return b;
00414
00415
return ConstProp::Cell(ConstProp::Cell::TOP);
00416 }
00417
00418 std::vector<ConstProp::Value*> ConstProp::Value::m_values = std::vector<ConstProp::Value*>();
00419
00420 std::ostream&
operator<<(std::ostream& out,
const ConstProp::Uniform& uniform)
00421 {
00422
if (uniform.constant) {
00423 out << uniform.constval;
00424 }
else {
00425
if (uniform.neg) out <<
'-';
00426 out <<
"v" << uniform.valuenum <<
"[" << uniform.index <<
"]";
00427 }
00428
return out;
00429 }
00430
00431
void ConstProp::Value::dump(std::ostream& out)
00432 {
00433 out <<
"--- uniform values ---" << std::endl;
00434
for (std::size_t i = 0; i < m_values.size(); i++) {
00435 out << i <<
": ";
00436
if (m_values[i]->type == NODE) {
00437 out <<
"node " << m_values[i]->node->name() << std::endl;
00438 }
else if (m_values[i]->type == STMT) {
00439 out <<
"stmt [" << m_values[i]->destsize <<
"] " <<
opInfo[m_values[i]->op].
name <<
" ";
00440
for (
int j = 0; j <
opInfo[m_values[i]->op].
arity; j++) {
00441
if (j) out <<
", ";
00442
for (std::vector<Uniform>::iterator U = m_values[i]->src[j].begin();
00443 U != m_values[i]->src[j].end(); ++U) {
00444 out << *U;
00445 }
00446 }
00447 out <<
";" << std::endl;
00448 }
00449 }
00450 }
00451
00452 std::ostream&
operator<<(std::ostream& out,
const ConstProp::Cell& cell)
00453 {
00454
switch(cell.state) {
00455
case ConstProp::Cell::BOTTOM:
00456 out <<
"[bot]";
00457
break;
00458
case ConstProp::Cell::CONSTANT:
00459 out <<
"[" << cell.value <<
"]";
00460
break;
00461
case ConstProp::Cell::TOP:
00462 out <<
"[top]";
00463
break;
00464
case ConstProp::Cell::UNIFORM:
00465 out <<
"<" << cell.uniform <<
">";
00466
break;
00467 }
00468
return out;
00469 }
00470
00471
struct InitConstProp {
00472 InitConstProp(ConstWorkList& worklist)
00473 : worklist(worklist)
00474 {
00475 }
00476
00477
void operator()(
const ShCtrlGraphNodePtr& node)
00478 {
00479
if (!node)
return;
00480 ShBasicBlockPtr block = node->block;
00481
if (!block)
return;
00482
for (ShBasicBlock::ShStmtList::iterator I = block->begin(); I != block->end(); ++I) {
00483 I->destroy_info<ConstProp>();
00484 ConstProp* cp =
new ConstProp(&(*I), worklist);
00485 I->add_info(cp);
00486 }
00487 }
00488
00489 ConstWorkList& worklist;
00490 };
00491
00492
struct DumpConstProp {
00493
void operator()(
const ShCtrlGraphNodePtr& node)
00494 {
00495
if (!node)
return;
00496 ShBasicBlockPtr block = node->block;
00497
if (!block)
return;
00498
for (ShBasicBlock::ShStmtList::iterator I = block->begin(); I != block->end(); ++I) {
00499 std::cerr <<
"{" << *I <<
"} --- ";
00500 ConstProp* cp = I->get_info<ConstProp>();
00501
00502
if (!cp) {
00503 std::cerr <<
"NO CP INFORMATION" << std::endl;
00504
continue;
00505 }
00506
00507 std::cerr <<
"dest = {";
00508
for (std::size_t i = 0; i < cp->dest.size(); i++) {
00509 std::cerr << cp->dest[i];
00510 }
00511 std::cerr <<
"}; ";
00512
for (
int s = 0; s <
opInfo[I->op].
arity; s++) {
00513
if (s) std::cerr <<
", ";
00514 std::cerr <<
"src" << s <<
" = {";
00515
for (std::size_t i = 0; i < cp->src[s].size(); i++) {
00516 std::cerr << cp->src[s][i];
00517 }
00518 std::cerr <<
"}";
00519 }
00520 std::cerr << std::endl;
00521 }
00522
00523 }
00524 };
00525
00526
struct FinishConstProp
00527 {
00528 FinishConstProp(
bool lift_uniforms)
00529 : lift_uniforms(lift_uniforms)
00530 {
00531 }
00532
00533
void operator()(
const ShCtrlGraphNodePtr& node) {
00534
if (!node)
return;
00535 ShBasicBlockPtr block = node->block;
00536
if (!block)
return;
00537
for (ShBasicBlock::ShStmtList::iterator I = block->begin(); I != block->end(); ++I) {
00538 ConstProp* cp = I->get_info<ConstProp>();
00539
00540
if (!cp)
continue;
00541
00542
if (!cp->dest.empty()) {
00543
00544
00545
00546
if (I->op !=
SH_OP_ASN || I->src[0].node()->kind() != SH_CONST) {
00547 ShVariable newconst(
new ShVariableNode(SH_CONST, I->dest.size()));
00548
bool allconst =
true;
00549
for (
int i = 0; i < I->dest.size(); i++) {
00550
if (cp->dest[i].state != ConstProp::Cell::CONSTANT) {
00551 allconst =
false;
00552
break;
00553 }
00554 newconst.setValue(i, cp->dest[i].value);
00555 }
00556
if (allconst) {
00557
#ifdef SH_DEBUG_CONSTPROP
00558
SH_DEBUG_PRINT(
"Replaced {" << *I <<
"} with " << newconst);
00559
#endif
00560
*I = ShStatement(I->dest, SH_OP_ASN, newconst);
00561 }
else {
00562
00563
for (
int s = 0; s <
opInfo[I->op].
arity; s++) {
00564
if (I->src[s].node()->kind() == SH_CONST)
continue;
00565
00566 ShVariable newconst(
new ShVariableNode(SH_CONST, I->src[s].size()));
00567
bool allconst =
true;
00568
for (
int i = 0; i < I->src[s].size(); i++) {
00569
if (cp->src[s][i].state != ConstProp::Cell::CONSTANT) {
00570 allconst =
false;
00571
break;
00572 }
00573 newconst.setValue(i, cp->src[s][i].value);
00574 }
00575
if (allconst) {
00576
#ifdef SH_DEBUG_CONSTPROP
00577
SH_DEBUG_PRINT(
"Replaced {" << *I <<
"}.src[" << s <<
"] with " << newconst);
00578
#endif
00579
I->src[s] = newconst;
00580 }
00581 }
00582 }
00583
00584
if (!lift_uniforms || allconst) {
00585
00586
continue;
00587 }
00588
00589
bool alluniform =
true;
00590
for (
int s = 0; s <
opInfo[I->op].
arity; s++) {
00591
for (
int i = 0; i < I->src[s].size(); i++) {
00592
if (cp->src[s][i].state != ConstProp::Cell::UNIFORM
00593 && cp->src[s][i].state != ConstProp::Cell::CONSTANT) {
00594 alluniform =
false;
00595
break;
00596 }
00597 }
00598
if (!alluniform)
break;
00599 }
00600
if (!alluniform || I->dest.node()->kind() == SH_OUTPUT
00601 || I->dest.node()->kind() == SH_INOUT) {
00602
#ifdef SH_DEBUG_CONSTPROP
00603
SH_DEBUG_PRINT(
"Considering " << *I <<
" for uniform lifting");
00604
#endif
00605
for (
int s = 0; s <
opInfo[I->op].
arity; s++) {
00606
if (I->src[s].uniform()) {
00607
#ifdef SH_DEBUG_CONSTPROP
00608
SH_DEBUG_PRINT(*I <<
".src[" << s <<
"] is already a uniform");
00609
#endif
00610
continue;
00611 }
00612
00613
bool mixed =
false;
00614
bool neg =
false;
00615 ConstProp::ValueNum uniform = -1;
00616 std::vector<int> indices;
00617
00618
for (
int i = 0; i < I->src[s].size(); i++) {
00619
if (cp->src[s][i].state == ConstProp::Cell::UNIFORM) {
00620
if (uniform < 0) {
00621 uniform = cp->src[s][i].uniform.valuenum;
00622 neg = cp->src[s][i].uniform.neg;
00623 indices.push_back(cp->src[s][i].uniform.index);
00624 }
else {
00625
if (uniform != cp->src[s][i].uniform.valuenum
00626 || neg != cp->src[s][i].uniform.neg) {
00627 mixed =
true;
00628
break;
00629 }
00630 indices.push_back(cp->src[s][i].uniform.index);
00631 }
00632 }
else {
00633
00634 mixed =
true;
00635 }
00636 }
00637
00638
00639
if (mixed) {
00640
#ifdef SH_DEBUG_CONSTPROP
00641
SH_DEBUG_PRINT(*I <<
".src[" << s <<
"] is mixed");
00642
#endif
00643
continue;
00644 }
00645
if (uniform < 0) {
00646
#ifdef SH_DEBUG_CONSTPROP
00647
SH_DEBUG_PRINT(*I <<
".src[" << s <<
"] is not uniform");
00648
#endif
00649
continue;
00650 }
00651 ConstProp::Value* value = ConstProp::Value::get(uniform);
00652
00653
00654
#ifdef SH_DEBUG_CONSTPROP
00655
SH_DEBUG_PRINT(
"Lifting {" << *I <<
"}.src[" << s <<
"]: " << uniform);
00656
#endif
00657
int srcsize;
00658
if (value->type == ConstProp::Value::NODE) {
00659 srcsize = value->node->size();
00660 }
else {
00661 srcsize = value->destsize;
00662 }
00663 ShSwizzle swizzle(srcsize, indices.size(), &(*indices.begin()));
00664
00665 ShVariableNodePtr node = build_uniform(value, uniform);
00666
if (node) {
00667 I->src[s] = ShVariable(node, swizzle, neg);
00668 }
else {
00669
#ifdef SH_DEBUG_CONSTPROP
00670
SH_DEBUG_PRINT(
"Could not lift " << *I <<
".src[" << s <<
"] for some reason");
00671
#endif
00672
}
00673 }
00674 }
00675 }
00676 }
00677 }
00678
00679
00680
for (ShBasicBlock::ShStmtList::iterator I = block->begin(); I != block->end(); ++I) {
00681
00682 I->destroy_info<ConstProp>();
00683 }
00684 }
00685
00686 ShVariableNodePtr build_uniform(ConstProp::Value* value,
00687 ConstProp::ValueNum valuenum)
00688 {
00689
if (value->type == ConstProp::Value::NODE) {
00690
return value->node;
00691 }
00692
00693 ShContext::current()->enter(0);
00694 ShVariableNodePtr node =
new ShVariableNode(SH_TEMP, value->destsize);
00695 {
00696 std::ostringstream s;
00697 s <<
"dep_" << valuenum;
00698 node->name(s.str());
00699 }
00700 ShContext::current()->exit();
00701
00702
#ifdef SH_DEBUG_CONSTPROP
00703
SH_DEBUG_PRINT(
"Lifting value #" << valuenum);
00704
#endif
00705
00706
bool broken =
false;
00707
00708 ShProgram prg =
SH_BEGIN_PROGRAM(
"uniform") {
00709 ShStatement stmt(node, value->op);
00710
00711
for (
int i = 0; i <
opInfo[value->op].
arity; i++) {
00712 stmt.src[i] = compute(value->src[i]);
00713
if (stmt.src[i].null()) broken =
true;
00714 }
00715
00716 ShContext::current()->parsing()->tokenizer.blockList()->addStatement(stmt);
00717 } SH_END;
00718
00719
#ifdef SH_DEBUG_CONSTPROP
00720
{
00721 std::ostringstream s;
00722 s <<
"lifted_" << valuenum;
00723 std::string dotfilename(s.str() +
".dot");
00724 std::ofstream
dot(dotfilename.c_str());
00725 prg.node()->ctrlGraph->graphvizDump(dot);
00726
dot.close();
00727 std::string cmdline = std::string(
"dot -Tps -o ") + s.str() +
".ps " + s.str() +
".dot";
00728 system(cmdline.c_str());
00729 }
00730
#endif
00731
00732
if (broken)
return 0;
00733 node->attach(prg.node());
00734
00735 value->type = ConstProp::Value::NODE;
00736 value->node = node;
00737
00738
return node;
00739 }
00740
00741 ShVariable compute(
const std::vector<ConstProp::Uniform>& src)
00742 {
00743 ConstProp::ValueNum v = -1;
00744
00745
bool allsame =
true;
00746
bool neg =
false;
00747 std::vector<int> indices;
00748 std::vector<float> constvals;
00749
for (std::size_t i = 0; i < src.size(); i++) {
00750
if (src[i].constant) {
00751
if (v >= 0) {
00752 allsame =
false;
00753
break;
00754 }
00755 constvals.push_back(src[i].constval);
00756 }
else {
00757
if (v < 0 && constvals.empty()) {
00758 v = src[i].valuenum;
00759 neg = src[i].neg;
00760 }
else {
00761
if (v != src[i].valuenum || neg != src[i].neg || !constvals.empty()) {
00762 allsame =
false;
00763 }
00764 }
00765 indices.push_back(src[i].index);
00766 }
00767 }
00768
if (!allsame) {
00769
00770 ShVariable r = ShVariable(
new ShVariableNode(SH_TEMP, src.size()));
00771
00772
for (std::size_t i = 0; i < src.size(); i++) {
00773 std::vector<ConstProp::Uniform> v;
00774 v.push_back(src[i]);
00775 ShVariable scalar = compute(v);
00776 ShStatement stmt(r(i), SH_OP_ASN, scalar);
00777 ShContext::current()->parsing()->tokenizer.blockList()->addStatement(stmt);
00778 }
00779
return r;
00780 }
00781
00782
if (!constvals.empty()) {
00783 ShVariable var(
new ShVariableNode(SH_CONST, constvals.size()));
00784 var.setValues(&*constvals.begin());
00785
return var;
00786 }
00787
00788 ConstProp::Value* value = ConstProp::Value::get(v);
00789
00790
if (value->type == ConstProp::Value::NODE) {
00791 ShSwizzle swizzle(value->node->size(), indices.size(), &*indices.begin());
00792
return ShVariable(value->node, swizzle, neg);
00793 }
00794
if (value->type == ConstProp::Value::STMT) {
00795 ShVariableNodePtr node =
new ShVariableNode(SH_TEMP, value->destsize);
00796 ShStatement stmt(node, value->op);
00797
00798
for (
int i = 0; i <
opInfo[value->op].
arity; i++) {
00799 stmt.src[i] = compute(value->src[i]);
00800
if (stmt.src[i].null())
return ShVariable();
00801 }
00802
00803 ShContext::current()->parsing()->tokenizer.blockList()->addStatement(stmt);
00804 ShSwizzle swizzle(node->size(), indices.size(), &*indices.begin());
00805
return ShVariable(node, swizzle, neg);
00806 }
00807
00808
#ifdef SH_DEBUG_CONSTPROP
00809
SH_DEBUG_PRINT(
"Reached invalid point");
00810
#endif
00811
00812
00813
return ShVariable();
00814 }
00815
00816
bool lift_uniforms;
00817 };
00818
00819 }
00820
00821
namespace SH {
00822
00823
00824 void propagate_constants(
ShProgram& p)
00825 {
00826
ShCtrlGraphPtr graph = p.
node()->ctrlGraph;
00827
00828 ConstWorkList worklist;
00829
00830
00831
00832 InitConstProp init(worklist);
00833 graph->dfs(init);
00834
00835
#ifdef SH_DEBUG_CONSTPROP
00836
SH_DEBUG_PRINT(
"Const Prop Initial Values:");
00837 DumpConstProp dump_pre;
00838 graph->dfs(dump_pre);
00839
#endif
00840
00841
00842
while (!worklist.empty()) {
00843 ValueTracking::Def def = worklist.front(); worklist.pop();
00844 ValueTracking* vt = def.stmt->get_info<ValueTracking>();
00845
if (!vt) {
00846
#ifdef SH_DEBUG_CONSTPROP
00847
SH_DEBUG_PRINT(*def.stmt <<
" on worklist does not have VT information?");
00848
#endif
00849
continue;
00850 }
00851
00852
00853
for (ValueTracking::DefUseChain::iterator use = vt->uses[def.index].begin();
00854 use != vt->uses[def.index].end(); ++use) {
00855 ConstProp* cp = use->stmt->get_info<ConstProp>();
00856
if (!cp) {
00857
#ifdef SH_DEBUG_CONSTPROP
00858
SH_DEBUG_PRINT(
"Use " << *use->stmt <<
" does not have const prop information!");
00859
#endif
00860
continue;
00861 }
00862
00863 ConstProp::Cell cell = cp->src[use->source][use->index];
00864
00865 ValueTracking* ut = use->stmt->get_info<ValueTracking>();
00866
if (!ut) {
00867
00868
#ifdef SH_DEBUG_CONSTPROP
00869
SH_DEBUG_PRINT(
"Use " << *use->stmt <<
" on worklist does not have VT information?");
00870
#endif
00871
continue;
00872 }
00873
00874
#ifdef SH_DEBUG_CONSTPROP
00875
SH_DEBUG_PRINT(
"Meeting cell for {" << *use->stmt
00876 <<
"}.src" << use->source <<
"[" << use->index <<
"]");
00877
#endif
00878
00879 ConstProp::Cell new_cell(ConstProp::Cell::TOP);
00880
00881
for (ValueTracking::UseDefChain::iterator possdef
00882 = ut->defs[use->source][use->index].begin();
00883 possdef != ut->defs[use->source][use->index].end(); ++possdef) {
00884 ConstProp* dcp = possdef->stmt->get_info<ConstProp>();
00885
if (!dcp) {
00886
#ifdef SH_DEBUG_CONSTPROP
00887
SH_DEBUG_PRINT(
"Possible def " << *dcp->stmt <<
" on worklist does not have CP information?");
00888
#endif
00889
continue;
00890 }
00891
00892 ConstProp::Cell destcell = dcp->dest[possdef->index];
00893
00894
00895
if (use->stmt->src[use->source].neg()) {
00896
if (destcell.state == ConstProp::Cell::CONSTANT) {
00897 destcell.value = -destcell.value;
00898 }
else if (destcell.state == ConstProp::Cell::UNIFORM) {
00899 destcell.uniform.neg = !destcell.uniform.neg;
00900 }
00901 }
00902
#ifdef SH_DEBUG_CONSTPROP
00903
SH_DEBUG_PRINT(
" meet(" << new_cell <<
", " << destcell <<
") = " <<
00904 meet(new_cell, destcell));
00905
#endif
00906
new_cell = meet(new_cell, destcell);
00907 }
00908
00909
if (cell != new_cell) {
00910
#ifdef SH_DEBUG_CONSTPROP
00911
SH_DEBUG_PRINT(
" ...replacing cell");
00912
#endif
00913
cp->src[use->source][use->index] = new_cell;
00914 cp->updateDest(worklist);
00915 }
00916 }
00917 }
00918
00919
00920
00921
#ifdef SH_DEBUG_CONSTPROP
00922
ConstProp::Value::dump(std::cerr);
00923
00924 DumpConstProp dump;
00925 graph->dfs(dump);
00926
#endif
00927
00928 FinishConstProp finish(p.
node()->target().find(
"gpu:") == 0
00929 && !ShContext::current()->optimization_disabled(
"uniform lifting"));
00930 graph->dfs(finish);
00931
00932 }
00933
00934 }