Skip to contentSkip to conversation

Add instruction to pseudo user tracking.

PATCH In review Christopher Li 2 participants 2 messages Jan 17, 2007 Sparse checker

lore
Share & tools
lore

Christopher Li

author maintainer
#0 lore raw

PATCH 1/1 Add instruction to pseudo user tracking.

The current way of tracking pseudo register user is by keeping a list of the address of the pseudo_t member. This address can be in part of the instruction member, the worse case is in the argument list of the call instruction.

As the comment for address_taken() said, using the container to get instruction pointer is wrong. It use to work with instruction that relate to symbol address. But that is not true any more. Even worse, it is very hard to track the pseudo usage other than symbol address. The only reason symbol address used to works for call instruction is because call instruction did not directly use the symbol address.

I bit the bullet and just add the instruction pointer to pair with the pseudo user pointer. So it will work with the case that the user instruction is call as well.

Testing:

I compare the linearize result with/without the patch on a few sparse source file it self. The linearize generate exactly the same result except the symbol address changes. Which is predictable different because the pseudo user structure allocate memory.

flow.c +26 -25
Index: sparse/flow.c
===================================================================
@@ -229,27 +229,27 @@ int simplify_flow(struct entrypoint *ep)
 	return simplify_branch_nodes(ep);
 }
 
-static inline void concat_user_list(struct pseudo_ptr_list *src, struct pseudo_ptr_list **dst)
+static inline void concat_user_list(struct pseudo_user_list *src, struct pseudo_user_list **dst)
 {
 	concat_ptr_list((struct ptr_list *)src, (struct ptr_list **)dst);
 }
 
 void convert_instruction_target(struct instruction *insn, pseudo_t src)
 {
-	pseudo_t target, *usep;
-
+	pseudo_t target;
+	struct pseudo_user *pu;
 	/*
 	 * Go through the "insn->users" list and replace them all..
 	 */
 	target = insn->target;
 	if (target == src)
 		return;
-	FOR_EACH_PTR(target->users, usep) {
-		if (*usep != VOID) {
-			assert(*usep == target);
-			*usep = src;
+	FOR_EACH_PTR(target->users, pu) {
+		if (*pu->userp != VOID) {
+			assert(*pu->userp == target);
+			*pu->userp = src;
 		}
-	} END_FOR_EACH_PTR(usep);
+	} END_FOR_EACH_PTR(pu);
 	concat_user_list(target->users, &src->users);
 	target->users = NULL;
 }
@@ -360,7 +360,7 @@ found_dominator:
 		phi = alloc_phi(parent, one->target, one->size);
 		phi->ident = phi->ident ? : pseudo->ident;
 		add_instruction(&parent->insns, br);
-		use_pseudo(phi, add_pseudo(dominators, phi));
+		use_pseudo(insn, phi, add_pseudo(dominators, phi));
 	} END_FOR_EACH_PTR(parent);
 	return 1;
 }		
@@ -592,7 +592,8 @@ void check_access(struct instruction *in
 
 static void simplify_one_symbol(struct entrypoint *ep, struct symbol *sym)
 {
-	pseudo_t pseudo, src, *pp;
+	pseudo_t pseudo, src;
+	struct pseudo_user *pu;
 	struct instruction *def;
 	unsigned long mod;
 	int all, stores, complex;
@@ -614,9 +615,9 @@ static void simplify_one_symbol(struct e
 	def = NULL;
 	stores = 0;
 	complex = 0;
-	FOR_EACH_PTR(pseudo->users, pp) {
+	FOR_EACH_PTR(pseudo->users, pu) {
 		/* We know that the symbol-pseudo use is the "src" in the instruction */
-		struct instruction *insn = container(pp, struct instruction, src);
+		struct instruction *insn = pu->insn;
 
 		switch (insn->opcode) {
 		case OP_STORE:
@@ -639,7 +640,7 @@ static void simplify_one_symbol(struct e
 			warning(sym->pos, "symbol '%s' pseudo used in unexpected way", show_ident(sym->ident));
 		}
 		complex |= insn->offset;
-	} END_FOR_EACH_PTR(pp);
+	} END_FOR_EACH_PTR(pu);
 
 	if (complex)
 		goto complex_def;
@@ -655,13 +656,13 @@ static void simplify_one_symbol(struct e
 	if (def)
 		src = def->target;
 
-	FOR_EACH_PTR(pseudo->users, pp) {
-		struct instruction *insn = container(pp, struct instruction, src);
+	FOR_EACH_PTR(pseudo->users, pu) {
+		struct instruction *insn = pu->insn;
 		if (insn->opcode == OP_LOAD) {
 			check_access(insn);
 			convert_load_instruction(insn, src);
 		}
-	} END_FOR_EACH_PTR(pp);
+	} END_FOR_EACH_PTR(pu);
 
 	/* Turn the store into a no-op */
 	kill_store(def);
@@ -671,29 +672,29 @@ multi_def:
 complex_def:
 external_visibility:
 	all = 1;
-	FOR_EACH_PTR_REVERSE(pseudo->users, pp) {
-		struct instruction *insn = container(pp, struct instruction, src);
+	FOR_EACH_PTR_REVERSE(pseudo->users, pu) {
+		struct instruction *insn = pu->insn;
 		if (insn->opcode == OP_LOAD)
 			all &= find_dominating_stores(pseudo, insn, ++bb_generation, !mod);
-	} END_FOR_EACH_PTR_REVERSE(pp);
+	} END_FOR_EACH_PTR_REVERSE(pu);
 
 	/* If we converted all the loads, remove the stores. They are dead */
 	if (all && !mod) {
-		FOR_EACH_PTR(pseudo->users, pp) {
-			struct instruction *insn = container(pp, struct instruction, src);
+		FOR_EACH_PTR(pseudo->users, pu) {
+			struct instruction *insn = pu->insn;
 			if (insn->opcode == OP_STORE)
 				kill_store(insn);
-		} END_FOR_EACH_PTR(pp);
+		} END_FOR_EACH_PTR(pu);
 	} else {
 		/*
 		 * If we couldn't take the shortcut, see if we can at least kill some
 		 * of them..
 		 */
-		FOR_EACH_PTR(pseudo->users, pp) {
-			struct instruction *insn = container(pp, struct instruction, src);
+		FOR_EACH_PTR(pseudo->users, pu) {
+			struct instruction *insn = pu->insn;
 			if (insn->opcode == OP_STORE)
 				kill_dominated_stores(pseudo, insn, ++bb_generation, insn->bb, !mod, 0);
-		} END_FOR_EACH_PTR(pp);
+		} END_FOR_EACH_PTR(pu);
 
 		if (!(mod & (MOD_NONLOCAL | MOD_STATIC))) {
 			struct basic_block *bb;
simplify.c +32 -15

114 lines not on this page · raw message

memops.c +5 -17
Index: sparse/memops.c
===================================================================
@@ -59,31 +59,19 @@ found_dominator:
 		phi = alloc_phi(parent, one->target, one->size);
 		phi->ident = phi->ident ? : one->target->ident;
 		add_instruction(&parent->insns, br);
-		use_pseudo(phi, add_pseudo(dominators, phi));
+		use_pseudo(insn, phi, add_pseudo(dominators, phi));
 	} END_FOR_EACH_PTR(parent);
 	return 1;
 }		
 
-/*
- * FIXME! This is wrong. Since we now distribute out the OP_SYMADDR,
- * we can no longer really use "container()" to get from a user to
- * the instruction that uses it.
- *
- * This happens to work, simply because the likelihood of the
- * (possibly non-instruction) containing the right bitpattern
- * in the right place is pretty low. But this is still wrong.
- *
- * We should make symbol-pseudos count non-load/store usage,
- * or something.
- */
 static int address_taken(pseudo_t pseudo)
 {
-	pseudo_t *usep;
-	FOR_EACH_PTR(pseudo->users, usep) {
-		struct instruction *insn = container(usep, struct instruction, src);
+	struct pseudo_user *pu;
+	FOR_EACH_PTR(pseudo->users, pu) {
+		struct instruction *insn = pu->insn;
 		if (insn->bb && (insn->opcode != OP_LOAD || insn->opcode != OP_STORE))
 			return 1;
-	} END_FOR_EACH_PTR(usep);
+	} END_FOR_EACH_PTR(pu);
 	return 0;
 }
 
linearize.h +25 -3
Index: sparse/linearize.h
===================================================================
@@ -9,6 +9,15 @@
 struct instruction;
 DECLARE_PTR_LIST(pseudo_ptr_list, pseudo_t);
 
+struct pseudo_user {
+	struct instruction *insn;
+	pseudo_t *userp;
+};
+
+DECLARE_ALLOCATOR(pseudo_user);
+DECLARE_PTR_LIST(pseudo_user_list, struct pseudo_user);
+
+
 enum pseudo_type {
 	PSEUDO_VOID,
 	PSEUDO_REG,
@@ -21,7 +30,7 @@ enum pseudo_type {
 struct pseudo {
 	int nr;
 	enum pseudo_type type;
-	struct pseudo_ptr_list *users;
+	struct pseudo_user_list *users;
 	struct ident *ident;
 	union {
 		struct symbol *sym;
@@ -268,16 +277,29 @@ static inline void add_pseudo_ptr(pseudo
 	add_ptr_list(list, ptr);
 }
 
+static inline void add_pseudo_user_ptr(struct pseudo_user *user, struct pseudo_user_list **list)
+{
+	add_ptr_list(list, user);
+}
+
 static inline int has_use_list(pseudo_t p)
 {
 	return (p && p->type != PSEUDO_VOID && p->type != PSEUDO_VAL);
 }
 
-static inline void use_pseudo(pseudo_t p, pseudo_t *pp)
+static inline struct pseudo_user* alloc_pseudo_user(struct instruction *insn, pseudo_t *pp)
+{
+	struct pseudo_user *user = __alloc_pseudo_user(0);
+	user->userp = pp;
+	user->insn = insn;
+	return user;
+}
+
+static inline void use_pseudo(struct instruction *insn, pseudo_t p, pseudo_t *pp)
 {
 	*pp = p;
 	if (has_use_list(p))
-		add_pseudo_ptr(pp, &p->users);
+		add_pseudo_user_ptr(alloc_pseudo_user(insn, pp), &p->users);
 }
 
 static inline void remove_bb_from_list(struct basic_block_list **list, struct basic_block *entry, int count)
linearize.c +37 -35

217 lines not on this page · raw message

#1 lore raw
Quoted 12 lines · Christopher Li

The current way of tracking pseudo register user is by keeping a list of the address of the pseudo_t member. This address can be in part of the instruction member, the worse case is in the argument list of the call instruction.

As the comment for address_taken() said, using the container to get instruction pointer is wrong. It use to work with instruction that relate to symbol address. But that is not true any more. Even worse, it is very hard to track the pseudo usage other than symbol address. The only reason symbol address used to works for call instruction is because call instruction did not directly use the symbol address.

Quoted 3 lines

I bit the bullet and just add the instruction pointer to pair with the pseudo user pointer. So it will work with the case that the user instruction is call as well.

Good call; merged. Thanks.

- Josh Triplett