aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/example.c
diff options
authorLinus Torvalds <torvalds@ppc970.osdl.org>2004-12-09 18:43:25 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:05:49 -0700
commitedfdf5d1bddd0be6b675c2e624a844adc67bbcb8 (patch)
tree919ddc47ee1298e53acf2e5ad0321ab167702631 /example.c
parent86bf4942ef5fb846903fcb046dbdbd1548e2febb (diff)
downloadsparse-dev-edfdf5d1bddd0be6b675c2e624a844adc67bbcb8.tar.gz
Be smarter about when we need to flush a pseudo.
We can often just re-generate it (from its source, or from an earlier flush).
Diffstat (limited to 'example.c')
-rw-r--r--example.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/example.c b/example.c
index 5b3c7aff..78f362b9 100644
--- a/example.c
+++ b/example.c
@@ -94,12 +94,38 @@ static void alloc_stack(struct bb_state *state, struct storage *storage)
state->stack_offset += 4;
}
+/*
+ * Can we re-generate the pseudo, so that we don't need to
+ * flush it to memory? We can regenerate:
+ * - immediates and symbol addresses
+ * - pseudos we got as input in non-registers
+ * - pseudos we've already saved off earlier..
+ */
+static int can_regenerate(struct bb_state *state, pseudo_t pseudo)
+{
+ struct storage_hash *in;
+
+ switch (pseudo->type) {
+ case PSEUDO_VAL:
+ case PSEUDO_SYM:
+ return 1;
+
+ default:
+ in = find_storage_hash(pseudo, state->inputs);
+ if (in && in->storage->type != REG_REG)
+ return 1;
+ in = find_storage_hash(pseudo, state->internal);
+ return 1;
+ }
+ return 0;
+}
+
static void flush_one_pseudo(struct bb_state *state, struct hardreg *hardreg, pseudo_t pseudo)
{
struct storage_hash *out;
struct storage *storage;
- if (pseudo->type != PSEUDO_REG && pseudo->type != PSEUDO_ARG)
+ if (can_regenerate(state, pseudo))
return;
out = find_storage_hash(pseudo, state->internal);