@@ -133,37 +133,59 @@ static int if_convert_phi(struct instruction *insn)
return REPEAT_CSE;
}
-static int clean_up_phi(struct instruction *insn)
+static int trivial_phi(pseudo_t *same, struct instruction *insn, struct pseudo_list **list)
{
+ pseudo_t target = insn->target;
pseudo_t phi;
- struct instruction *last;
- int same;
- last = NULL;
- same = 1;
+ assert(insn->opcode == OP_PHI);
+
+ if (pseudo_in_list(*list, target))
+ return 1;
+ add_pseudo(list, target);
+
FOR_EACH_PTR(insn->phi_list, phi) {
struct instruction *def;
+ pseudo_t src;
+
if (phi == VOID)
continue;
def = phi->def;
- if (def->src1 == VOID || !def->bb)
+ assert(def->bb);
+ if (!def->bb)
continue;
- if (last) {
- if (last->src1 != def->src1)
- same = 0;
+
+ src = def->src; // bypass OP_PHISRC & get the real source
+
+ if (src == VOID || src == target || src == *same)
+ continue;
+ if (!*same) {
+ *same = src;
continue;
}
- last = def;
+ if (src->type == PSEUDO_REG && src->def->opcode == OP_PHI) {
+ if (trivial_phi(same, src->def, list))
+ continue;
+ }
+ return 0;
} END_FOR_EACH_PTR(phi);
- if (same) {
- pseudo_t pseudo = last ? last->src1 : VOID;
- convert_instruction_target(insn, pseudo);
- kill_instruction(insn);
- return REPEAT_CSE;
- }
+ return 1;
+}
+
+static int clean_up_phi(struct instruction *insn)
+{
+ struct pseudo_list *list = NULL;
+ pseudo_t same = NULL;
+
+ if (!trivial_phi(&same, insn, &list))
+ return if_convert_phi(insn);
- return if_convert_phi(insn);
+ if (!same)
+ same = VOID;
+ convert_instruction_target(insn, same);
+ kill_instruction(insn);
+ return REPEAT_CSE;
}
static int delete_pseudo_user_list_entry(struct pseudo_user_list **list, pseudo_t *entry, int count)
new file mode 100644
@@ -0,0 +1,15 @@
+void foo(int *p)
+{
+ int a = *p;
+ while (1)
+ a ^= 0;
+}
+
+/*
+ * check-name: trivial phis
+ * check-command: test-linearize -Wno-decl $file
+ * check-output-ignore
+ * check-output-excludes: phi\\.
+ * check-output-excludes: phisrc\\.
+ * check-output-end
+ */
In a set of related phi-nodes and phi-sources if all phi-sources but one correspond to the target of one of the phi-sources, then no phi-nodes is needed and all %phis can be replaced by the unique source. For example, if we have something like: foo: phisrc.32 %phi1 <- %arg1 br .L1 .L1: phi.32 %r2 <- %phi1, %phi2 phisrc.32 %phi2 <- %r2 ... we can see that %phi2 is the target of the phi-node that use it thus neither %phi2 nor %r2 are completly inter-dependent and the only true soure is %arg1. In this case %r2 can be replaced by %arg1 and the phi-node can be removed as well as its phi-sources. There are also more complex cases with several inter-related phi-nodes, the source of a phi-node being defined by another phi-node. Like for the simple case, if there is only a single independent source, all the related phi-nodes can be replaced by this unique true source and the the phi-sources can be removed. Removing these trivial phi-nodes will usually trigger other simplifications, especially those concerning the CFG. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> --- simplify.c | 56 ++++++++++++++++++++++++++++------------- validation/optim/trivial-phis.c | 15 +++++++++++ 2 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 validation/optim/trivial-phis.c