summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorGregF <greg@LunarG.com>2017-11-17 16:47:11 -0700
committerDavid Neto <dneto@google.com>2017-11-21 17:56:03 -0500
commite28edd458b729da7bbfd51e375feb33103709e6f (patch)
tree376f392f61fa143866229226173684832835bcdb /source
parentb14291581fb2a515c3e195f0b6f44dd1a0307996 (diff)
Optimize loads/stores on nested structs
Also fix LocalAccessChainConvert test: nested structs now convert Add InsertExtractElim test for nested struct
Diffstat (limited to 'source')
-rw-r--r--source/opt/insert_extract_elim.cpp49
-rw-r--r--source/opt/insert_extract_elim.h27
-rw-r--r--source/opt/mem_pass.cpp2
3 files changed, 52 insertions, 26 deletions
diff --git a/source/opt/insert_extract_elim.cpp b/source/opt/insert_extract_elim.cpp
index d3c64854..b506d9eb 100644
--- a/source/opt/insert_extract_elim.cpp
+++ b/source/opt/insert_extract_elim.cpp
@@ -31,24 +31,28 @@ const uint32_t kInsertCompositeIdInIdx = 1;
} // anonymous namespace
bool InsertExtractElimPass::ExtInsMatch(const ir::Instruction* extInst,
- const ir::Instruction* insInst) const {
- if (extInst->NumInOperands() != insInst->NumInOperands() - 1) return false;
- uint32_t numIdx = extInst->NumInOperands() - 1;
+ const ir::Instruction* insInst,
+ const uint32_t extOffset) const {
+ if (extInst->NumInOperands() - extOffset != insInst->NumInOperands() - 1)
+ return false;
+ uint32_t numIdx = extInst->NumInOperands() - 1 - extOffset;
for (uint32_t i = 0; i < numIdx; ++i)
- if (extInst->GetSingleWordInOperand(i + 1) !=
+ if (extInst->GetSingleWordInOperand(i + 1 + extOffset) !=
insInst->GetSingleWordInOperand(i + 2))
return false;
return true;
}
bool InsertExtractElimPass::ExtInsConflict(
- const ir::Instruction* extInst, const ir::Instruction* insInst) const {
- if (extInst->NumInOperands() == insInst->NumInOperands() - 1) return false;
- uint32_t extNumIdx = extInst->NumInOperands() - 1;
+ const ir::Instruction* extInst, const ir::Instruction* insInst,
+ const uint32_t extOffset) const {
+ if (extInst->NumInOperands() - extOffset == insInst->NumInOperands() - 1)
+ return false;
+ uint32_t extNumIdx = extInst->NumInOperands() - 1 - extOffset;
uint32_t insNumIdx = insInst->NumInOperands() - 2;
uint32_t numIdx = std::min(extNumIdx, insNumIdx);
for (uint32_t i = 0; i < numIdx; ++i)
- if (extInst->GetSingleWordInOperand(i + 1) !=
+ if (extInst->GetSingleWordInOperand(i + 1 + extOffset) !=
insInst->GetSingleWordInOperand(i + 2))
return false;
return true;
@@ -68,13 +72,32 @@ bool InsertExtractElimPass::EliminateInsertExtract(ir::Function* func) {
uint32_t cid = ii->GetSingleWordInOperand(kExtractCompositeIdInIdx);
ir::Instruction* cinst = get_def_use_mgr()->GetDef(cid);
uint32_t replId = 0;
+ // Offset of extract indices being compared to insert indices.
+ // Offset increases as indices are matched.
+ uint32_t extOffset = 0;
while (cinst->opcode() == SpvOpCompositeInsert) {
- if (ExtInsConflict(&*ii, cinst)) break;
- if (ExtInsMatch(&*ii, cinst)) {
+ if (ExtInsMatch(&*ii, cinst, extOffset)) {
+ // Match! Use inserted value as replacement
replId = cinst->GetSingleWordInOperand(kInsertObjectIdInIdx);
break;
}
- cid = cinst->GetSingleWordInOperand(kInsertCompositeIdInIdx);
+ else if (ExtInsConflict(&*ii, cinst, extOffset)) {
+ // If extract has fewer indices than the insert, stop searching.
+ // Otherwise increment offset of extract indices considered and
+ // continue searching through the inserted value
+ if (ii->NumInOperands() - extOffset <
+ cinst->NumInOperands() - 1) {
+ break;
+ }
+ else {
+ extOffset += cinst->NumInOperands() - 2;
+ cid = cinst->GetSingleWordInOperand(kInsertObjectIdInIdx);
+ }
+ }
+ else {
+ // Consider next composite in insert chain
+ cid = cinst->GetSingleWordInOperand(kInsertCompositeIdInIdx);
+ }
cinst = get_def_use_mgr()->GetDef(cid);
}
// If search ended with CompositeConstruct or ConstantComposite
@@ -85,8 +108,8 @@ bool InsertExtractElimPass::EliminateInsertExtract(ir::Function* func) {
// vector composition, and additional CompositeInsert.
if ((cinst->opcode() == SpvOpCompositeConstruct ||
cinst->opcode() == SpvOpConstantComposite) &&
- (*ii).NumInOperands() == 2) {
- uint32_t compIdx = (*ii).GetSingleWordInOperand(1);
+ (*ii).NumInOperands() - extOffset == 2) {
+ uint32_t compIdx = (*ii).GetSingleWordInOperand(extOffset + 1);
if (IsVectorType(cinst->type_id())) {
if (compIdx < cinst->NumInOperands()) {
uint32_t i = 0;
diff --git a/source/opt/insert_extract_elim.h b/source/opt/insert_extract_elim.h
index d5dba00f..cb0f4f3f 100644
--- a/source/opt/insert_extract_elim.h
+++ b/source/opt/insert_extract_elim.h
@@ -40,25 +40,28 @@ class InsertExtractElimPass : public Pass {
Status Process(ir::IRContext*) override;
private:
- // Return true if indices of extract |extInst| and insert |insInst| match
+ // Return true if indices of extract |extInst| starting at |extOffset|
+ // match indices of insert |insInst|.
bool ExtInsMatch(const ir::Instruction* extInst,
- const ir::Instruction* insInst) const;
+ const ir::Instruction* insInst,
+ const uint32_t extOffset) const;
- // Return true if indices of extract |extInst| and insert |insInst| conflict,
- // specifically, if the insert changes bits specified by the extract, but
- // changes either more bits or less bits than the extract specifies,
- // meaning the exact value being inserted cannot be used to replace
- // the extract.
+ // Return true if indices of extract |extInst| starting at |extOffset| and
+ // indices of insert |insInst| conflict, specifically, if the insert
+ // changes bits specified by the extract, but changes either more bits
+ // or less bits than the extract specifies, meaning the exact value being
+ // inserted cannot be used to replace the extract.
bool ExtInsConflict(const ir::Instruction* extInst,
- const ir::Instruction* insInst) const;
+ const ir::Instruction* insInst,
+ const uint32_t extOffset) 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
- // intervening insert which conflicts.
+ // Look for OpExtract on sequence of OpInserts in |func|. If there is a
+ // reaching insert which corresponds to the indices of the extract, replace
+ // the extract with the value that is inserted. Also resolve extracts from
+ // CompositeConstruct or ConstantComposite.
bool EliminateInsertExtract(ir::Function* func);
// Initialize extensions whitelist
diff --git a/source/opt/mem_pass.cpp b/source/opt/mem_pass.cpp
index ae5baa81..1292804a 100644
--- a/source/opt/mem_pass.cpp
+++ b/source/opt/mem_pass.cpp
@@ -64,7 +64,7 @@ bool MemPass::IsTargetType(const ir::Instruction* typeInst) const {
int nonMathComp = 0;
typeInst->ForEachInId([&nonMathComp, this](const uint32_t* tid) {
ir::Instruction* compTypeInst = get_def_use_mgr()->GetDef(*tid);
- if (!IsBaseTargetType(compTypeInst)) ++nonMathComp;
+ if (!IsTargetType(compTypeInst)) ++nonMathComp;
});
return nonMathComp == 0;
}