transform preprocess: remove unused instructions & aggregates
MODIFY
ir/function.cpp
ir/function.cpp
@@ -207,10 +207,27 @@ multimap<Value*, Value*> Function::getUsers() const {
users.emplace(op, const_cast<Instr*>(&i));
}
}
- // TODO: missing, e.g., global var users
+ for (auto &agg : aggregates) {
+ for (auto val : agg->getVals()) {
+ users.emplace(val, agg.get());
+ }
+ }
return users;
}
+bool Function::removeUnusedAggs(const multimap<Value*, Value*> &users) {
+ bool changed = false;
+ for (auto I = aggregates.begin(); I != aggregates.end(); ) {
+ if (users.count(I->get())) {
+ ++I;
+ } else {
+ I = aggregates.erase(I);
+ changed = true;
+ }
+ }
+ return changed;
+}
+
void Function::print(ostream &os, bool print_header) const {
{
const auto &gvars = getGlobalVars();

MODIFY
ir/function.h
ir/function.h
@@ -153,6 +153,7 @@ public:
instr_helper instrs() const { return *this; }
std::multimap<Value*, Value*> getUsers() const;
+ bool removeUnusedAggs(const std::multimap<Value*, Value*> &users);
void print(std::ostream &os, bool print_header = true) const;
friend std::ostream &operator<<(std::ostream &os, const Function &f);

MODIFY
ir/instr.cpp
ir/instr.cpp
@@ -3001,6 +3001,12 @@ const ConversionOp* isCast(ConversionOp::Op op, const Value &v) {
return (c && c->getOp() == op) ? c : nullptr;
}
+bool hasNoSideEffects(const Instr &i) {
+ return isNoOp(i) ||
+ dynamic_cast<const GEP*>(&i) ||
+ dynamic_cast<const ShuffleVector*>(&i);
+}
+
Value* isNoOp(const Value &v) {
if (isCast(ConversionOp::BitCast, v))
return &static_cast<const ConversionOp*>(&v)->getValue();

MODIFY
ir/instr.h
ir/instr.h
@@ -814,5 +814,6 @@ public:
const ConversionOp *isCast(ConversionOp::Op op, const Value &v);
+bool hasNoSideEffects(const Instr &i);
Value *isNoOp(const Value &v);
}

MODIFY
tools/transform.cpp
tools/transform.cpp
@@ -901,6 +901,7 @@ void Transform::preprocess() {
// remove store of initializers to global variables that aren't needed to
// verify the transformation
vector<Value*> worklist;
+ vector<Instr*> to_remove;
set<const Value*> seen;
for (auto fn : { &src, &tgt }) {
@@ -908,7 +909,6 @@ void Transform::preprocess() {
if (bb.getName() != "#init")
continue;
- vector<Instr*> to_remove;
auto users = fn->getUsers();
for (auto &i : bb.instrs()) {
@@ -930,13 +930,13 @@ void Transform::preprocess() {
if (user == gvar ||
isNoOp(*user) ||
dynamic_cast<Phi*>(user) ||
- dynamic_cast<Return*>(user) ||
dynamic_cast<Select*>(user)) {
for (auto p = users.equal_range(user); p.first != p.second;
++p.first)
worklist.emplace_back(p.first->second);
}
- else if (dynamic_cast<FnCall*>(user)) {
+ else if (dynamic_cast<FnCall*>(user) ||
+ dynamic_cast<Return*>(user)) {
// OK
} else {
needed = true;
@@ -957,6 +957,29 @@ void Transform::preprocess() {
for (auto i : to_remove) {
bb.delInstr(i);
}
+ to_remove.clear();
+
+ bool changed;
+ do {
+ users = fn->getUsers();
+ changed = false;
+
+ for (auto bb : fn->getBBs()) {
+ for (auto &i : bb->instrs()) {
+ auto i_ptr = const_cast<Instr*>(&i);
+ if (hasNoSideEffects(i) && !users.count(i_ptr))
+ to_remove.emplace_back(i_ptr);
+ }
+
+ for (auto i : to_remove) {
+ bb->delInstr(i);
+ changed = true;
+ }
+ to_remove.clear();
+ }
+
+ changed |= fn->removeUnusedAggs(users);
+ } while (changed);
}
}

transform preprocess: remove unused instructions & aggregates