Я пытаюсь реализовать анализ жизнеспособности, чтобы удалить мертвые инструкции. я знаю это isInstructionTriviallyDead()
существует, однако, я хочу узнать, как удалить код, используя цепочки def-use (или use-def).
То, как я сейчас это делаю, я перебираю все инструкции в блоке (используя inst_iterator
), и для каждой инструкции, циклически просматривая все ее применения. В конечном счете, если инструкция бесполезна, я считаю ее мертвой и поэтому могу удалить ее, используя eraseFromParent()
Это выглядит примерно так:
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
bool deadInst = true;
Instruction *inst = &*I;for (User* pUser : inst->users()) {
// If we enter this loop, we have at least one use, so instruction isn't dead
deadInst = false;
}
// deadInst is true if we didn't enter the loop, so has no uses
if (deadInst) {
inst->eraseFromParent();
}
}
Проблема в том, что в инструкции возврата нет связанных с ней применений (и я уверен, что есть и другие определения без использования). Однако инструкцию возврата не следует удалять, так как это приведет к семантически неверному коду.
Мой общий подход к удалению инструкций через анализ жизнеспособности в порядке? Что я могу сделать, чтобы гарантировать, что инструкции, такие как возврат, не будут удалены?
Любые указатели очень ценятся 🙂
также проверьте, является ли инструкция терминатором (inst->isTerminator()
)
Ты упомянул llvm::isInstructionTriviallyDead
и это хорошее начало, чтобы получить представление о том, что можно удалить, а что нельзя.
Вы уже заметили, что не можете удалить инструкцию терминатора.
Кроме того, вы не хотите удалять инструкции без использования, но с побочными эффектами. Учти это:
define void @bar()() {
call void @foo()()
ret void
}
Вы не хотите удалять call
инструкции, даже если она не имеет смысла, потому что она может, например, записать в стандартный вывод или изменить некоторую глобальную переменную. То же самое касается store
«S. Проверьте Instruction::mayHaveSideEffects
для полного списка.
Ваш анализ живучести слишком агрессивен: бесполезен необходимо, но не достаточно условие, чтобы инструкция считалась мертвой.
Если вы не хотите использовать isInstructionTriviallyDead
в учебных целях я рекомендую вам начать с другого пути: подумайте, когда инструкции наверняка не работают (например, alloca
мертв, когда нет пользы, так же add
инструкция …) а потом обобщать.
Кроме того, просто пройтись по всем инструкциям, и удаление мертвых недостаточно. Например:
%2 = add i32 3, %1
%3 = add i32 3, %2
Когда вы впервые сталкиваетесь %2
это имеет применение в %3
так что не мертвый. Но после устранения %3
как мертвый, %2
тоже становится мертвым Вы можете решить эту проблему, выполняя итерации до тех пор, пока не будет найдена новая мертвая инструкция (неэффективная, но простая), или с помощью некоторой рекурсивной процедуры.