SPIRV: allow 64 bit literals in OperandVariableLiteralId class iteration.
This commit is contained in:
parent
28660bb580
commit
b249f2fc24
@ -127,6 +127,37 @@ namespace spv {
|
||||
}
|
||||
}
|
||||
|
||||
// Return the size of a type in 32-bit words. This currently only
|
||||
// handles ints and floats, and is only invoked by queries which must be
|
||||
// integer types. If ever needed, it can be generalized.
|
||||
unsigned spirvbin_t::typeSizeInWords(spv::Id id) const
|
||||
{
|
||||
const unsigned typeStart = idPos(id);
|
||||
const spv::Op opCode = asOpCode(typeStart);
|
||||
|
||||
switch (opCode) {
|
||||
case spv::OpTypeInt: // fall through...
|
||||
case spv::OpTypeFloat: return (spv[typeStart+2]+31)/32;
|
||||
default:
|
||||
error("unimplemented type size request");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Looks up the type of a given const or variable ID, and
|
||||
// returns its size in 32-bit words.
|
||||
unsigned spirvbin_t::idTypeSizeInWords(spv::Id id) const
|
||||
{
|
||||
const unsigned idStart = idPos(id);
|
||||
const spv::Op opCode = asOpCode(idStart);
|
||||
|
||||
if (spv::InstructionDesc[opCode].hasType())
|
||||
return typeSizeInWords(asId(idStart+1));
|
||||
|
||||
error("asked for type of typeless ID");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is this an opcode we should remove when using --strip?
|
||||
bool spirvbin_t::isStripOp(spv::Op opCode) const
|
||||
{
|
||||
@ -140,6 +171,7 @@ namespace spv {
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if this opcode is flow control
|
||||
bool spirvbin_t::isFlowCtrl(spv::Op opCode) const
|
||||
{
|
||||
switch (opCode) {
|
||||
@ -155,6 +187,7 @@ namespace spv {
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if this opcode defines a type
|
||||
bool spirvbin_t::isTypeOp(spv::Op opCode) const
|
||||
{
|
||||
switch (opCode) {
|
||||
@ -182,6 +215,7 @@ namespace spv {
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if this opcode defines a constant
|
||||
bool spirvbin_t::isConstOp(spv::Op opCode) const
|
||||
{
|
||||
switch (opCode) {
|
||||
@ -324,7 +358,7 @@ namespace spv {
|
||||
fnPosDCE.clear();
|
||||
fnCalls.clear();
|
||||
typeConstPos.clear();
|
||||
typeConstPosR.clear();
|
||||
idPosR.clear();
|
||||
entryPoint = spv::NoResult;
|
||||
largestNewId = 0;
|
||||
|
||||
@ -340,6 +374,14 @@ namespace spv {
|
||||
if ((options & STRIP) && isStripOp(opCode))
|
||||
stripInst(start);
|
||||
|
||||
unsigned word = start+1;
|
||||
|
||||
if (spv::InstructionDesc[opCode].hasType())
|
||||
word++;
|
||||
|
||||
if (spv::InstructionDesc[opCode].hasResult())
|
||||
idPosR[asId(word++)] = start;
|
||||
|
||||
if (opCode == spv::Op::OpName) {
|
||||
const spv::Id target = asId(start+1);
|
||||
const std::string name = literalString(start+2);
|
||||
@ -363,11 +405,9 @@ namespace spv {
|
||||
} else if (isConstOp(opCode)) {
|
||||
assert(asId(start + 2) != spv::NoResult);
|
||||
typeConstPos.insert(start);
|
||||
typeConstPosR[asId(start + 2)] = start;
|
||||
} else if (isTypeOp(opCode)) {
|
||||
assert(asId(start + 1) != spv::NoResult);
|
||||
typeConstPos.insert(start);
|
||||
typeConstPosR[asId(start + 1)] = start;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -459,13 +499,22 @@ namespace spv {
|
||||
// word += numOperands;
|
||||
return nextInst;
|
||||
|
||||
case spv::OperandVariableLiteralId:
|
||||
while (numOperands > 0) {
|
||||
++word; // immediate
|
||||
idFn(asId(word++)); // ID
|
||||
numOperands -= 2;
|
||||
case spv::OperandVariableLiteralId: {
|
||||
if (opCode == OpSwitch) {
|
||||
// word-2 is the position of the selector ID. Literals match its type.
|
||||
const unsigned literalSize = idTypeSizeInWords(asId(word-2));
|
||||
unsigned numLiteralIdPairs = (nextInst-word) / (1+literalSize);
|
||||
|
||||
for (unsigned arg=0; arg<numLiteralIdPairs; ++arg) {
|
||||
word += literalSize; // literal
|
||||
idFn(asId(word++)); // label
|
||||
}
|
||||
} else {
|
||||
assert(0); // currentely, only OpSwitch uses OperandVariableLiteralId
|
||||
}
|
||||
|
||||
return nextInst;
|
||||
}
|
||||
|
||||
case spv::OperandLiteralString: {
|
||||
const int stringWordCount = literalStringWords(literalString(word));
|
||||
@ -966,23 +1015,27 @@ namespace spv {
|
||||
|
||||
std::unordered_map<spv::Id, int> typeUseCount;
|
||||
|
||||
// Count total type usage
|
||||
process(inst_fn_nop,
|
||||
[&](spv::Id& id) { if (isType[id]) ++typeUseCount[id]; }
|
||||
);
|
||||
// This is not the most efficient algorithm, but this is an offline tool, and
|
||||
// it's easy to write this way. Can be improved opportunistically if needed.
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
strip();
|
||||
typeUseCount.clear();
|
||||
|
||||
// Remove types from deleted code
|
||||
for (const auto& fn : fnPosDCE)
|
||||
// Count total type usage
|
||||
process(inst_fn_nop,
|
||||
[&](spv::Id& id) { if (isType[id]) --typeUseCount[id]; },
|
||||
fn.second.first, fn.second.second);
|
||||
[&](spv::Id& id) { if (isType[id]) ++typeUseCount[id]; }
|
||||
);
|
||||
|
||||
// Remove single reference types
|
||||
for (const auto typeStart : typeConstPos) {
|
||||
const spv::Id typeId = asTypeConstId(typeStart);
|
||||
if (typeUseCount[typeId] == 1) {
|
||||
--typeUseCount[typeId];
|
||||
stripInst(typeStart);
|
||||
// Remove single reference types
|
||||
for (const auto typeStart : typeConstPos) {
|
||||
const spv::Id typeId = asTypeConstId(typeStart);
|
||||
if (typeUseCount[typeId] == 1) {
|
||||
changed = true;
|
||||
--typeUseCount[typeId];
|
||||
stripInst(typeStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1060,12 +1113,12 @@ namespace spv {
|
||||
}
|
||||
#endif // NOTDEF
|
||||
|
||||
// Return start position in SPV of given type. error if not found.
|
||||
unsigned spirvbin_t::typePos(spv::Id id) const
|
||||
// Return start position in SPV of given Id. error if not found.
|
||||
unsigned spirvbin_t::idPos(spv::Id id) const
|
||||
{
|
||||
const auto tid_it = typeConstPosR.find(id);
|
||||
if (tid_it == typeConstPosR.end())
|
||||
error("type ID not found");
|
||||
const auto tid_it = idPosR.find(id);
|
||||
if (tid_it == idPosR.end())
|
||||
error("ID not found");
|
||||
|
||||
return tid_it->second;
|
||||
}
|
||||
@ -1083,11 +1136,11 @@ namespace spv {
|
||||
case spv::OpTypeInt: return 3 + (spv[typeStart+3]);
|
||||
case spv::OpTypeFloat: return 5;
|
||||
case spv::OpTypeVector:
|
||||
return 6 + hashType(typePos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
|
||||
return 6 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
|
||||
case spv::OpTypeMatrix:
|
||||
return 30 + hashType(typePos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
|
||||
return 30 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
|
||||
case spv::OpTypeImage:
|
||||
return 120 + hashType(typePos(spv[typeStart+2])) +
|
||||
return 120 + hashType(idPos(spv[typeStart+2])) +
|
||||
spv[typeStart+3] + // dimensionality
|
||||
spv[typeStart+4] * 8 * 16 + // depth
|
||||
spv[typeStart+5] * 4 * 16 + // arrayed
|
||||
@ -1098,24 +1151,24 @@ namespace spv {
|
||||
case spv::OpTypeSampledImage:
|
||||
return 502;
|
||||
case spv::OpTypeArray:
|
||||
return 501 + hashType(typePos(spv[typeStart+2])) * spv[typeStart+3];
|
||||
return 501 + hashType(idPos(spv[typeStart+2])) * spv[typeStart+3];
|
||||
case spv::OpTypeRuntimeArray:
|
||||
return 5000 + hashType(typePos(spv[typeStart+2]));
|
||||
return 5000 + hashType(idPos(spv[typeStart+2]));
|
||||
case spv::OpTypeStruct:
|
||||
{
|
||||
std::uint32_t hash = 10000;
|
||||
for (unsigned w=2; w < wordCount; ++w)
|
||||
hash += w * hashType(typePos(spv[typeStart+w]));
|
||||
hash += w * hashType(idPos(spv[typeStart+w]));
|
||||
return hash;
|
||||
}
|
||||
|
||||
case spv::OpTypeOpaque: return 6000 + spv[typeStart+2];
|
||||
case spv::OpTypePointer: return 100000 + hashType(typePos(spv[typeStart+3]));
|
||||
case spv::OpTypePointer: return 100000 + hashType(idPos(spv[typeStart+3]));
|
||||
case spv::OpTypeFunction:
|
||||
{
|
||||
std::uint32_t hash = 200000;
|
||||
for (unsigned w=2; w < wordCount; ++w)
|
||||
hash += w * hashType(typePos(spv[typeStart+w]));
|
||||
hash += w * hashType(idPos(spv[typeStart+w]));
|
||||
return hash;
|
||||
}
|
||||
|
||||
@ -1132,14 +1185,14 @@ namespace spv {
|
||||
case spv::OpConstantFalse: return 300008;
|
||||
case spv::OpConstantComposite:
|
||||
{
|
||||
std::uint32_t hash = 300011 + hashType(typePos(spv[typeStart+1]));
|
||||
std::uint32_t hash = 300011 + hashType(idPos(spv[typeStart+1]));
|
||||
for (unsigned w=3; w < wordCount; ++w)
|
||||
hash += w * hashType(typePos(spv[typeStart+w]));
|
||||
hash += w * hashType(idPos(spv[typeStart+w]));
|
||||
return hash;
|
||||
}
|
||||
case spv::OpConstant:
|
||||
{
|
||||
std::uint32_t hash = 400011 + hashType(typePos(spv[typeStart+1]));
|
||||
std::uint32_t hash = 400011 + hashType(idPos(spv[typeStart+1]));
|
||||
for (unsigned w=3; w < wordCount; ++w)
|
||||
hash += w * spv[typeStart+w];
|
||||
return hash;
|
||||
@ -1212,19 +1265,19 @@ namespace spv {
|
||||
msg(3, 4, std::string("ID bound: ") + std::to_string(bound()));
|
||||
|
||||
strip(); // strip out data we decided to eliminate
|
||||
|
||||
if (options & OPT_LOADSTORE) optLoadStore();
|
||||
if (options & OPT_FWD_LS) forwardLoadStores();
|
||||
if (options & DCE_FUNCS) dceFuncs();
|
||||
if (options & DCE_VARS) dceVars();
|
||||
if (options & DCE_TYPES) dceTypes();
|
||||
strip(); // strip out data we decided to eliminate
|
||||
|
||||
if (options & MAP_TYPES) mapTypeConst();
|
||||
if (options & MAP_NAMES) mapNames();
|
||||
if (options & MAP_FUNCS) mapFnBodies();
|
||||
|
||||
mapRemainder(); // map any unmapped IDs
|
||||
applyMap(); // Now remap each shader to the new IDs we've come up with
|
||||
strip(); // strip out data we decided to eliminate
|
||||
}
|
||||
|
||||
// remap from a memory image
|
||||
|
@ -162,13 +162,15 @@ private:
|
||||
// handle error
|
||||
void error(const std::string& txt) const { errorHandler(txt); }
|
||||
|
||||
bool isConstOp(spv::Op opCode) const;
|
||||
bool isTypeOp(spv::Op opCode) const;
|
||||
bool isStripOp(spv::Op opCode) const;
|
||||
bool isFlowCtrl(spv::Op opCode) const;
|
||||
range_t literalRange(spv::Op opCode) const;
|
||||
range_t typeRange(spv::Op opCode) const;
|
||||
range_t constRange(spv::Op opCode) const;
|
||||
bool isConstOp(spv::Op opCode) const;
|
||||
bool isTypeOp(spv::Op opCode) const;
|
||||
bool isStripOp(spv::Op opCode) const;
|
||||
bool isFlowCtrl(spv::Op opCode) const;
|
||||
range_t literalRange(spv::Op opCode) const;
|
||||
range_t typeRange(spv::Op opCode) const;
|
||||
range_t constRange(spv::Op opCode) const;
|
||||
unsigned typeSizeInWords(spv::Id id) const;
|
||||
unsigned idTypeSizeInWords(spv::Id id) const;
|
||||
|
||||
spv::Id& asId(unsigned word) { return spv[word]; }
|
||||
const spv::Id& asId(unsigned word) const { return spv[word]; }
|
||||
@ -177,10 +179,10 @@ private:
|
||||
spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); }
|
||||
unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); }
|
||||
spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); }
|
||||
unsigned typePos(spv::Id id) const;
|
||||
unsigned idPos(spv::Id id) const;
|
||||
|
||||
static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; }
|
||||
static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); }
|
||||
static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; }
|
||||
static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); }
|
||||
|
||||
// Header access & set methods
|
||||
spirword_t magic() const { return spv[0]; } // return magic number
|
||||
@ -263,8 +265,8 @@ private:
|
||||
// Which functions are called, anywhere in the module, with a call count
|
||||
std::unordered_map<spv::Id, int> fnCalls;
|
||||
|
||||
posmap_t typeConstPos; // word positions that define types & consts (ordered)
|
||||
posmap_rev_t typeConstPosR; // reverse map from IDs to positions
|
||||
posmap_t typeConstPos; // word positions that define types & consts (ordered)
|
||||
posmap_rev_t idPosR; // reverse map from IDs to positions
|
||||
|
||||
std::vector<spv::Id> idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user