mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-22 19:50:05 +00:00
ExtractInsert: Handle rudimentary CompositeConstruct and ConstantComposite
This optimizes a single index extract whose composite value terminates with a CompositeConstruct (or ConstantComposite) by evaluating to the correct component. This was needed for opaque legalization. This highlights the need/opportunity to improve this optimization to deal with more complex composite expressions including currently handled ops plus Null ops and special vector composition. A TODO has been added.
This commit is contained in:
parent
a91cecfefc
commit
7be791aaaa
@ -55,6 +55,11 @@ bool InsertExtractElimPass::ExtInsConflict(const ir::Instruction* extInst,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InsertExtractElimPass::IsVectorType(uint32_t typeId) {
|
||||
ir::Instruction* typeInst = def_use_mgr_->GetDef(typeId);
|
||||
return typeInst->opcode() == SpvOpTypeVector;
|
||||
}
|
||||
|
||||
bool InsertExtractElimPass::EliminateInsertExtract(ir::Function* func) {
|
||||
bool modified = false;
|
||||
for (auto bi = func->begin(); bi != func->end(); ++bi) {
|
||||
@ -74,6 +79,33 @@ bool InsertExtractElimPass::EliminateInsertExtract(ir::Function* func) {
|
||||
cid = cinst->GetSingleWordInOperand(kInsertCompositeIdInIdx);
|
||||
cinst = def_use_mgr_->GetDef(cid);
|
||||
}
|
||||
// If search ended with CompositeConstruct or ConstantComposite
|
||||
// and the extract has one index, return the appropriate component.
|
||||
// If a vector CompositeConstruct we make sure all preceding
|
||||
// components are of component type (not vector composition).
|
||||
// TODO(greg-lunarg): Handle multiple-indices, ConstantNull, special
|
||||
// vector composition, and additional CompositeInsert.
|
||||
if ((cinst->opcode() == SpvOpCompositeConstruct ||
|
||||
cinst->opcode() == SpvOpConstantComposite) &&
|
||||
(*ii).NumInOperands() == 2) {
|
||||
uint32_t compIdx = (*ii).GetSingleWordInOperand(1);
|
||||
if (IsVectorType(cinst->type_id())) {
|
||||
if (compIdx < cinst->NumInOperands()) {
|
||||
uint32_t i = 0;
|
||||
for (; i <= compIdx; i++) {
|
||||
uint32_t compId = cinst->GetSingleWordInOperand(i);
|
||||
ir::Instruction* compInst = def_use_mgr_->GetDef(compId);
|
||||
if (compInst->type_id() != (*ii).type_id())
|
||||
break;
|
||||
}
|
||||
if (i > compIdx)
|
||||
replId = cinst->GetSingleWordInOperand(compIdx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
replId = cinst->GetSingleWordInOperand(compIdx);
|
||||
}
|
||||
}
|
||||
if (replId != 0) {
|
||||
const uint32_t extId = ii->result_id();
|
||||
(void)def_use_mgr_->ReplaceAllUsesWith(extId, replId);
|
||||
|
@ -52,6 +52,9 @@ class InsertExtractElimPass : public Pass {
|
||||
bool ExtInsConflict(
|
||||
const ir::Instruction* extInst, const ir::Instruction* insInst) const;
|
||||
|
||||
// Return true if |typeId| is a vector type
|
||||
bool IsVectorType(uint32_t typeId);
|
||||
|
||||
// Look for OpExtract on sequence of OpInserts in |func|. If there is an
|
||||
// insert with identical indices, replace the extract with the value
|
||||
// that is inserted if possible. Specifically, replace if there is no
|
||||
|
Loading…
Reference in New Issue
Block a user