diff options
Diffstat (limited to 'lib/compiler/src')
| -rw-r--r-- | lib/compiler/src/Makefile | 2 | ||||
| -rw-r--r-- | lib/compiler/src/beam_bounds.erl | 23 | ||||
| -rw-r--r-- | lib/compiler/src/beam_ssa_pre_codegen.erl | 2 | ||||
| -rw-r--r-- | lib/compiler/src/beam_validator.erl | 8 |
4 files changed, 31 insertions, 4 deletions
diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile index 82b0a12a7d..e0625337b5 100644 --- a/lib/compiler/src/Makefile +++ b/lib/compiler/src/Makefile @@ -157,7 +157,7 @@ docs: clean: rm -f $(TARGET_FILES) - rm -f $(EGEN)/beam_opcodes.erl $(EGEN)/beam_opcodes.hrl + rm -f $(EGEN)/beam_opcodes.erl $(EGEN)/beam_opcodes.hrl $(EGEN)/OPCODES-GENERATED rm -f $(EGEN)/core_parse.erl rm -f core diff --git a/lib/compiler/src/beam_bounds.erl b/lib/compiler/src/beam_bounds.erl index 6f3902596e..6ac5141821 100644 --- a/lib/compiler/src/beam_bounds.erl +++ b/lib/compiler/src/beam_bounds.erl @@ -46,7 +46,28 @@ bounds('bnot', R0) -> case R0 of - {A,B} -> + {A, B} when is_integer(A), is_integer(B), A =/= B -> + %% While it's easy to get an exact range, doing so can make certain + %% chains of operations slow to converge, e.g. + %% + %% f(0) -> -1; f(N) -> abs(bnot f(N)). + %% + %% Where the range increases by 1 every time we pass through, + %% making it more or less impossible to reach a fixpoint. + %% + %% We therefore widen the range a bit quicker to ensure that we + %% converge on 'any' within a reasonable time frame, hoping that + %% the range will still be tight enough in the cases where we + %% don't feed the result into itself. + case {abs(A) bsr ?NUM_BITS, abs(B) bsr ?NUM_BITS} of + {0, 0} -> + Min = min(-B - 1, -(B bsl 1) - 1), + Max = max(-A - 1, -(A bsl 1) - 1), + normalize({Min, Max}); + {_, _} -> + any + end; + {A, B} -> R = {inf_add(inf_neg(B), -1), inf_add(inf_neg(A), -1)}, normalize(R); _ -> diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl index e3406f12de..dc76755aad 100644 --- a/lib/compiler/src/beam_ssa_pre_codegen.erl +++ b/lib/compiler/src/beam_ssa_pre_codegen.erl @@ -680,7 +680,7 @@ sanitize([L|Ls], InBlocks, Count0, Values0, Blocks0) -> no_change -> Blk = sanitize_last(Blk0, Values0), Blocks1 = Blocks0#{L := Blk}, - Blocks = sanitize_reachable(Blk0, Blocks1), + Blocks = sanitize_reachable(Blk, Blocks1), sanitize(Ls, InBlocks, Count0, Values0, Blocks); {Is,Last,Count,Values} -> Blk1 = Blk0#b_blk{is=Is,last=Last}, diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index f19ea897fe..285db8a26a 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -2830,7 +2830,13 @@ unpack_typed_arg(#tr{r=Reg,t=Type}, Vst) -> %% The validator is not yet clever enough to do proper range analysis like %% the main type pass, so our types will be a bit cruder here, but they %% should at the very least not be in direct conflict. - true = none =/= beam_types:meet(get_movable_term_type(Reg, Vst), Type), + Current = get_movable_term_type(Reg, Vst), + case beam_types:meet(Current, Type) of + none -> + throw({bad_typed_register, Current, Type}); + _ -> + ok + end, Reg; unpack_typed_arg(Arg, _Vst) -> Arg. |
