An optimization worth doing.

Thomas Charles CONWAY conway at cs.mu.oz.au
Mon Feb 10 09:22:41 AEDT 1997


Hi

consider the following module:

%--------------------------------------------------------------------%
:- module foo.

:- interface.

:- type hufftree	--->
		node(frequency, item)
	;	tree(frequency, hufftree, hufftree)
	.

:- type frequency ==	int.

:- type item	==	int.

:- pred get_frequency(hufftree, frequency).
:- mode get_frequency(in, out) is det.

:- implementation.

get_frequency(node(Freq, _), Freq).
get_frequency(tree(Freq, _, _), Freq).
%--------------------------------------------------------------------%

for the predicate get_frequency we produce the following code:

BEGIN_MODULE(mercury__foo_module0)
	init_entry(mercury__foo__get_frequency_2_0);
	init_label(mercury__foo__get_frequency_2_0_i3);
BEGIN_CODE

/* code for predicate 'get_frequency'/2 in mode 0 */
Define_entry(mercury__foo__get_frequency_2_0);
	if ((tag(r1) != mktag((Integer) 0)))
		GOTO_LABEL(mercury__foo__get_frequency_2_0_i3);
	r1 = const_field(mktag(0), r1, (Integer) 0);
	proceed();
Define_label(mercury__foo__get_frequency_2_0_i3);
	r1 = const_field(mktag(1), r1, (Integer) 0);
	proceed();
END_MODULE

Now, because in both cases we want the first field (irrespective
of the tag), it would be cheaper to simply mask off the tag at
runtime (use an expression equivalent to (ptr & (!0x07))[0]) to
avoid the branch. The extra alu operations are cheap compared with
the cost of the conditional branch. It would mean that we could 
emit code something like the following:

BEGIN_MODULE(mercury__foo_module0)
	init_entry(mercury__foo__get_frequency_2_0);
BEGIN_CODE

/* code for predicate 'get_frequency'/2 in mode 0 */
Define_entry(mercury__foo__get_frequency_2_0);
	r1 = const_field_stripped_tag(r1, (Integer) 0);
	proceed();
END_MODULE

-- 
Thomas Conway               				      conway at cs.mu.oz.au
AD DEUM ET VINUM	  "Thomas Tallis is dead, and muic dies." - William Byrd



More information about the developers mailing list