aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/icode/hipe_icode_fp.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe/icode/hipe_icode_fp.erl')
-rw-r--r--lib/hipe/icode/hipe_icode_fp.erl43
1 files changed, 23 insertions, 20 deletions
diff --git a/lib/hipe/icode/hipe_icode_fp.erl b/lib/hipe/icode/hipe_icode_fp.erl
index 5ae0395b72..3e4a2f039a 100644
--- a/lib/hipe/icode/hipe_icode_fp.erl
+++ b/lib/hipe/icode/hipe_icode_fp.erl
@@ -738,8 +738,16 @@ filter_map([{Var, Bindings}|Left], NofPreds, Map) ->
true ->
case all_args_equal(Bindings) of
true ->
- {_, FVar} = hd(Bindings),
- filter_map(Left, NofPreds, gb_trees:update(Var, FVar, Map));
+ NewBinding =
+ case hd(Bindings) of
+ {Pred, {assigned, FVar0}} when is_integer(Pred) ->
+ case bindings_all_assigned(Bindings) of
+ true -> {assigned, FVar0};
+ false -> FVar0
+ end;
+ {Pred, FVar0} when is_integer(Pred) -> FVar0
+ end,
+ filter_map(Left, NofPreds, gb_trees:update(Var, NewBinding, Map));
false ->
PhiDst = hipe_icode:mk_new_fvar(),
PhiArgs = strip_of_assigned(Bindings),
@@ -751,7 +759,7 @@ filter_map([{Var, Bindings}|Left], NofPreds, Map) ->
gb_trees:update(phi, [{PhiDst, PhiArgs}|Val], Map)
end,
NewBinding =
- case bindings_are_assigned(Bindings) of
+ case bindings_all_assigned(Bindings) of
true -> {assigned, PhiDst};
false -> PhiDst
end,
@@ -763,30 +771,25 @@ filter_map([{Var, Bindings}|Left], NofPreds, Map) ->
filter_map([], _NofPreds, Map) ->
Map.
-bindings_are_assigned([{_, {assigned, _}}|Left]) ->
- assert_assigned(Left),
- true;
-bindings_are_assigned(Bindings) ->
- assert_not_assigned(Bindings),
- false.
-
-assert_assigned([{_, {assigned, _}}|Left]) ->
- assert_assigned(Left);
-assert_assigned([]) ->
- ok.
-
-assert_not_assigned([{_, FVar}|Left]) ->
- true = hipe_icode:is_fvar(FVar),
- assert_not_assigned(Left);
-assert_not_assigned([]) ->
- ok.
+bindings_all_assigned([]) -> true;
+bindings_all_assigned([{_, {assigned, _}}|Left]) ->
+ bindings_all_assigned(Left);
+bindings_all_assigned(_) -> false.
%% all_args_equal returns true if the mapping for a variable is the
%% same from all predecessors, i.e., we do not need a phi-node.
+%% During the fixpoint loop, a mapping might become assigned, without that
+%% information having propagated into all predecessors. We take care to answer
+%% true even if FVar is only assigned in some predecessors.
+
+all_args_equal([{_, {assigned, FVar}}|Left]) ->
+ all_args_equal(Left, FVar);
all_args_equal([{_, FVar}|Left]) ->
all_args_equal(Left, FVar).
+all_args_equal([{_, {assigned, FVar1}}|Left], FVar1) ->
+ all_args_equal(Left, FVar1);
all_args_equal([{_, FVar1}|Left], FVar1) ->
all_args_equal(Left, FVar1);
all_args_equal([], _) ->