diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2017-01-04 04:03:21 +0100 |
|---|---|---|
| committer | Christopher Li <sparse@chrisli.org> | 2017-02-13 09:34:45 +0800 |
| commit | 5636cd5cbf816f30ee57d580ec4debd8e0bd7581 (patch) | |
| tree | 1a600d68617996638e90486e72808412a64dc0ef | |
| parent | c8757aa484fbc45a33baa0b87fdb248f5f14d01d (diff) | |
| download | sparse-dev-5636cd5cbf816f30ee57d580ec4debd8e0bd7581.tar.gz | |
missing load simplification
In memops:find_dominating_parents(), the 'load-load optimization'
(see commit cf07903a "Don't bother finding dominating loads if ...")
cause some loads simplification to be missed.
For example, with the following code:
int foo(int *i, int *j)
{
*i = 6;
*j = 1;
do {
if (*i != 6)
(*i)++;
(*i)++;
} while (*i != *j);
return *j;
}
test-linearize returns something like:
foo:
.L0:
<entry-point>
store.32 $6 -> 0[%arg1]
store.32 $1 -> 0[%arg2]
br .L1
.L1:
load.32 %r4 <- 0[%arg1]
setne.32 %r5 <- %r4, $6
br %r5, .L4, .L5
.L4:
add.32 %r8 <- %r4, $1
store.32 %r8 -> 0[%arg1]
br .L5
.L5:
load.32 %r10 <- 0[%arg1]
add.32 %r11 <- %r10, $1
store.32 %r11 -> 0[%arg1]
load.32 %r15 <- 0[%arg2]
setne.32 %r16 <- %r11, %r15
br %r16, .L1, .L6
.L6:
ret.32 %r15
where we can notice that the first load in .L5 is not needed,
the value could be retrieved from %r4 and %r8, like:
@@ -8,15 +8,17 @@
.L1:
load.32 %r4 <- 0[%arg1]
setne.32 %r5 <- %r4, $6
+ phisrc.32 %phi4 <- %r4
br %r5, .L4, .L5
.L4:
add.32 %r8 <- %r4, $1
store.32 %r8 -> 0[%arg1]
+ phisrc.32 %phi5 <- %r8
br .L5
.L5:
- load.32 %r10 <- 0[%arg1]
+ phi.32 %r10 <- %phi4, %phi5
add.32 %r11 <- %r10, $1
store.32 %r11 -> 0[%arg1]
load.32 %r15 <- 0[%arg2]
The fix essentially consists in reverting commit cf07903a but on
memops.c's version of find_dominating_parents().
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
| -rw-r--r-- | memops.c | 10 |
1 files changed, 3 insertions, 7 deletions
@@ -18,12 +18,10 @@ static int find_dominating_parents(pseudo_t pseudo, struct instruction *insn, struct basic_block *bb, unsigned long generation, struct pseudo_list **dominators, - int local, int loads) + int local) { struct basic_block *parent; - if (bb_list_size(bb->parents) > 1) - loads = 0; FOR_EACH_PTR(bb->parents, parent) { struct instruction *one; struct instruction *br; @@ -41,8 +39,6 @@ static int find_dominating_parents(pseudo_t pseudo, struct instruction *insn, } if (!dominance) continue; - if (one->opcode == OP_LOAD && !loads) - continue; goto found_dominator; } END_FOR_EACH_PTR_REVERSE(one); no_dominance: @@ -50,7 +46,7 @@ no_dominance: continue; parent->generation = generation; - if (!find_dominating_parents(pseudo, insn, parent, generation, dominators, local, loads)) + if (!find_dominating_parents(pseudo, insn, parent, generation, dominators, local)) return 0; continue; @@ -124,7 +120,7 @@ static void simplify_loads(struct basic_block *bb) generation = ++bb_generation; bb->generation = generation; dominators = NULL; - if (find_dominating_parents(pseudo, insn, bb, generation, &dominators, local, 1)) { + if (find_dominating_parents(pseudo, insn, bb, generation, &dominators, local)) { /* This happens with initial assignments to structures etc.. */ if (!dominators) { if (local) { |
