[m-rev.] for post-commit review: optimize more computed_gotos
Peter Wang
novalazy at gmail.com
Fri Jul 12 15:36:25 AEST 2024
On Fri, 12 Jul 2024 04:48:50 +1000 "Zoltan Somogyi" <zoltan.somogyi at runbox.com> wrote:
> Optimize computed gotos in more situations.
>
> compiler/peephole.m:
> Allow the optimization of computed_goto instructions even when
> some of the values that the switched-on rval can take don't have
> an associated label. This works, because the absence of a label
> for a value indicates that the switched-on rval cannot have that value
> at runtime (usually because it represents the tag of a function symbol
> that the switched-on variable cannot be bound to at that program point,
> according to its inst there).
>
> We have long optimized computed gotos that can go to one of only two labels
> into an if-then-else, but only if one of those labels was associated
> with only one value. Extend this to work even if it has more than one
> value, using indexing into a single-word bitmap to make the test fast,
> with the time taken being effectively independent of the number of values
> represented in that bitmap.
> diff --git a/compiler/peephole.m b/compiler/peephole.m
> index 6382951a9..03971eeb3 100644
> --- a/compiler/peephole.m
> +++ b/compiler/peephole.m
...
> + (
> + LaterVals = [],
> + CondRval = binop(eq(int_type_int), SelectorRval,
> + const(llconst_int(FirstVal)))
> + ;
> + LaterVals = [_ | _],
> + build_offset_mask([FirstVal | LaterVals], 0u, Mask),
> + SelectorRvalUint = cast(lt_int(int_type_uint), SelectorRval),
> + QueryRval = binop(
> + unchecked_left_shift(int_type_uint, shift_by_uint),
> + const(llconst_uint(1u)), SelectorRvalUint),
I believe you'll need to test SelectorRval < bits_per_uint to avoid
undefined behaviour. x86(-64) mask the shift count to 5 or 6 bits.
> + SelectedBitUintRval = binop(bitwise_and(int_type_uint),
> + const(llconst_uint(Mask)), QueryRval),
> + CondRval = binop(ne(int_type_uint),
> + SelectedBitUintRval, const(llconst_uint(0u)))
> + ),
> CommentInstr = llds_instr(comment(Comment0), ""),
> - BranchInstr = llds_instr(if_val(CondRval, code_label(OneValLabel)),
> - ""),
> - GotoInstr = llds_instr(goto(code_label(OtherLabel)), Comment0),
> + BranchUinstr = if_val(CondRval, code_label(FewerValsLabel)),
> + BranchInstr = llds_instr(BranchUinstr, Comment0 ++ " part 1"),
> + GotoUinstr = goto(code_label(OtherLabel)),
> + GotoInstr = llds_instr(GotoUinstr, Comment0 ++ " part 2"),
> Instrs = [CommentInstr, BranchInstr, GotoInstr | Instrs0]
> else
> fail
> ).
> % Build a map that associates each label in a computed goto with the
> - % values of the switch rval that cause a jump to it.
> + % values of the switch rval that cause a jump to it. Fail if any of the
> + % targets is not there.
> %
> :- pred build_computed_goto_target_map(list(maybe(label))::in, int::in,
> - map(label, list(int))::in, map(label, list(int))::out) is semidet.
> + one_or_more_map(label, int)::in,
> + one_or_more_map(label, int)::out) is det.
>
The comment says it fails, but the predicate is det.
Peter
More information about the reviews
mailing list