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:
GregF 2017-09-12 18:15:09 -06:00 committed by David Neto
parent a91cecfefc
commit 7be791aaaa
2 changed files with 35 additions and 0 deletions

View File

@ -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);

View File

@ -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