Hello Nicolai,
Am Sonntag, den 18.06.2017, 12:05 +0200 schrieb Nicolai Hähnle: > > > if HAVE_XLIB_GLX > > SUBDIRS += drivers/x11 > > @@ -101,7 +101,7 @@ AM_CFLAGS = \ > > $(VISIBILITY_CFLAGS) \ > > $(MSVC2013_COMPAT_CFLAGS) > > AM_CXXFLAGS = \ > > - $(LLVM_CFLAGS) \ > > + $(LLVM_CXXFLAGS) \ > > I kind of suspect that this might be a no-no. On the one hand it > makes sense, because it makes the use of CXXFLAGS consistent, but > it's a pretty significant build system change. I understand that, but c++11 is just such an improvement. > > At least separate it out into its own patch. Okay, > > > > > $(VISIBILITY_CXXFLAGS) \ > > $(MSVC2013_COMPAT_CXXFLAGS) > > > > diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources > > index 21f9167bda..a68e9d2afe 100644 > > --- a/src/mesa/Makefile.sources > > +++ b/src/mesa/Makefile.sources > > @@ -509,6 +509,8 @@ STATETRACKER_FILES = \ > > state_tracker/st_glsl_to_tgsi.h \ > > state_tracker/st_glsl_to_tgsi_private.cpp \ > > state_tracker/st_glsl_to_tgsi_private.h \ > > + state_tracker/st_glsl_to_tgsi_temprename.cpp \ > > + state_tracker/st_glsl_to_tgsi_temprename.h \ > > Inconsistent use of whitespace. > > Then the whole patch needs to be re-arranged, i.e. the > st_glsl_to_tgsi_private stuff, This was a mistake when I was re-basing the patch. > and I agree with Emil that the tests > should be separated out into their own patch. I'm currently working on this. > > BTW, you can and should use > > git rebase -x "cd $builddir && make" $basecommit > > to verify that you don't break the build in an intermediate patch. Nice trick, thanks. > > +typedef int scope_idx; > > Please remove this, it's an unnecessary and distracting abstraction > that doesn't gain you anything. Actually, with the refactoring it did the last two days it helped a lot. > I consider the scopes back-reference here and in temp_access to be > bad style. I already got rid of them. > Think less object- and more data-oriented, then you won't need them. > Most of those helper functions should be members of > tgsi_temp_lifetime -- and the getters/setters can be removed > entirely. YAGNI. I think with the new design that uses pointers into a pre-allocated array the methods must stay where they are. > To first approximation, you should never use mutable. Those methods > should not be const to begin with. This is something else I actually didn't like and corrected already. > > +scope_idx > > +tgsi_temp_lifetime::make_scope(e_scope_type type, int id, int lvl, > > + int s_begin)const > > +{ > > + int idx = scopes.size(); > > + scopes.push_back(prog_scope(type, idx, id, lvl, s_begin, > > scopes)); > > + return idx; > > +} > > AFAICS this overload is only used once. Please remove it. Okay. > Use C-style comments. Okay, > Also, this should probably have an assert, or can this really happen? I don't think it can happen, an assert it is. > + case TGSI_OPCODE_IF: > > + case TGSI_OPCODE_UIF:{ > > + if (inst->src[0].file == PROGRAM_TEMPORARY) { > > + acc[inst->src[0].index].append(line, acc_read, > > current); > > + } > > + scope_idx scope = make_scope(current, sct_if, if_id, > > nesting_lvl, line); > > It's probably a good idea to have scopes start at line + 1. > Otherwise, > it may be tempting to think that the read access of the IF condition > happens inside the IF scope, at least based on the line numbers. I don't think that's a problem. At least I can't think of a test case that would trigger a problem with that. > > > + case TGSI_OPCODE_DEFAULT: { > > + auto scope_type = (inst->op == TGSI_OPCODE_CASE) ? > > + sct_switch_case : > > sct_switch_default; > > + if ( scopes[current].type() == sct_switch ) { > > No spaces inside parenthesis (also elsewhere). Okay. > > + scope_stack.push(current); > > + current = make_scope(current, scope_type, > > scopes[current].id(), > > + nesting_lvl, line); > > + }else{ > > Spaces around else (also elsewhere). Okay. > > No comment between if- and else-block. Okay. > > > > + scopes[current].set_continue(current, line); > > You do need to distinguish between break and continue (at least for > accuracy), because break allows you to skip over a piece of code > indefinitely while continue doesn't. I.e.: I risk to differ, in the worst case a CONT can act like it would be a BRK, and because I have to handle the worst case it doesn't make sense to distinguish between the two. > > BGNLOOP > ... > BRK/CONT > ... > MOV TEMP[i], ... > ... > ENDLOOP > > If it's a CONT, then i is written unconditionally inside the loop. While one would normally expect this, it is not guarantied. Think of a shader like this: ... varying int a; varying float b; int f(int a, float b) {...} for (int i = 0; i< n; ++i ) { if (a && f(i, b)) continue; ... x = } It may not be the best style. but it is possible. > + > > + for (unsigned j = 0; j < inst->tex_offset_num_offset; > > j++) { > > + if (inst->tex_offsets[j].file == PROGRAM_TEMPORARY) { > > + acc[inst->tex_offsets[j].index].append(line, > > acc_read, current); > > + } > > + } > > You need to handle the reads before the writes. After all, you might > have a > > ADD TEMP[i], TEMP[i], ... > > which may have to register as an undefined read. I will add a test case, and correct the code accordingly. > > > > + > > + } // end default > > + } // end switch (op) > > No end-of-scope comments. okay, > > > > +scope_idx > > +prog_scope::get_parent_loop() const > > Based on what it does, this should be renamed to something like > get_innermost_loop. Okay. > > > +void temp_access::append(int line, e_acc_type acc, scope_idx idx) > > +{ > > + last_write = line; > > Looks like last_write should be called last_access. Initially I thought the same, but a last read is also (most of the time) the last access, and it is handled differently then a write past the last read, so i think that last_write catches it better. > > + if (acc == acc_read) { > > + last_read = line; > > + last_read_scope = idx; > > + if (undefined_read > line) { > > + undefined_read = line; > > + undefined_read_scope = idx; > > + } > > The way you're using it this is effectively just first_read, not > undefined_read. Indeed. > > > > + } else { > > + if (first_write == -1) { > > + first_write = line; > > + first_write_scope = idx; > > + > > + // we write in an if-branch > > + auto fw_ifthen_scope = scopes[idx].in_ifelse(); > > + if ((fw_ifthen_scope >= 0) && > > scopes[fw_ifthen_scope].in_loop()) { > > + // value not always written, in loops we must keep it > > + keep_for_full_loop = true; > > + } else { > > + // same thing for switch-case > > + auto fw_switch_scope = scopes[idx].in_switchcase(); > > + if (fw_switch_scope >= 0 && > > scopes[fw_switch_scope].in_loop()) { > > + keep_for_full_loop = true; > > + } > > + } > > Simplify this by using an in_conditional() instead of in_ifelse + > in_switchcase(). I was thinking about this, but I also thought that when I want to track all code path later then I will have to distinguish the two again, but, on the other hand, adding a method that combines the two is a no- brainer. > > > + > > + /* Only written to, just make sure that renaming > > + * doesn't reuse this register too early (corner > > + * case is the one opcode with two destinations) */ > > + if (last_read_scope < 0) { > > + return make_pair(first_write, first_write + 1); > > What if there are multiple writes to the temporary? Good catch! Next text case :) > > + /* propagate lifetime also if there was a continue/break > > + * in a loop and the write was after it (so it constitutes > > + * a conditional write */ > > It's only conditional if there was a break. Continue doesn't make it > conditional. I think I made my argument. > + /* propagate lifetimes before moving to upper scopes */ > > + if ((scopes[first_write_scope].type() == sct_loop) && > > + (keep_for_full_loop || (undefined_read < first_write))) { > > + first_write = scopes[first_write_scope].begin(); > > + int lr = scopes[first_write_scope].end(); > > + if (last_read < lr) > > + last_read = lr; > > + } > > What about: > > BGNLOOP > ... > BGNLOOP > IF ... > read TEMP[i] > ENDIF > write TEMP[i] > ENDLOOP > ... > ENDLOOP > > In this case, you don't set keep_for_full_loop, yet the lifetime > must extend for the entire _outer_ loop. Another test case that needs to be added :) > > I see two related problems in the code: > > 1. In this case, keep_for_full_loop needs to be set to true (because > overwriting first_write in the code above means that the related > check below won't fire). > > 2. target_level is set to the inner loop even though it really needs > to be set to the outer loop. Indeed. Thanks a lot, Gert _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev