[Info-vax] Anyone still around ? :-)

Louis Krupp lkrupp at nospam.pssw.com.invalid
Thu Oct 10 01:57:30 EDT 2019


On Wed, 09 Oct 2019 20:29:16 -0600, Louis Krupp
<lkrupp at nospam.pssw.com.invalid> wrote:

>On Thu, 10 Oct 2019 00:40:35 +0200, hb <end.of at inter.net> wrote:
>
>>On 10/9/19 11:55 PM, Louis Krupp wrote:
>>> On Tue, 8 Oct 2019 07:19:39 -0700 (PDT), osuvman50 at gmail.com wrote:
>>> 
>>>> I was considering making a post about the failure of the C compiler's optimizer
>>>> to recognize and optimize the pattern:
>>>>
>>>>     choice = permutation % (CARDS_IN_DECK-i);
>>>>     permutation = permutation / (CARDS_IN_DECK-i);
>>>>
>>>> but didn't think I'd get any constructive responses. (refactoring to eliminate a
>>>> divide makes the whole program run 18% faster on both alpha and IA64).
>>> 
>>> For what it's worth, GNU C++ on Linux doesn't optimize it either, but
>>> GNU Fortran does at optimization level 1. If you have a FORTRAN
>>> compiler, you'll probably have to tweak this code a bit (getting rid
>>> of the colons, for example) to try it:
>>> 
>>> subroutine s(permutation, choice, i)
>>>     implicit none
>>>     integer :: permutation, choice, i
>>>     integer, parameter :: CARDS_IN_DECK = 52
>>>     choice = mod(permutation, (CARDS_IN_DECK-i))
>>>     permutation = permutation / (CARDS_IN_DECK-i)
>>> end subroutine
>>> 
>>> Louis
>>> 
>>
>>What kind of optimization do you expect?
>>
>>#define CARDS_IN_DECK 52
>>extern int permutation,  choice;
>>void foo (int i) {
>>        choice = permutation % (CARDS_IN_DECK-i);
>>        permutation = permutation / (CARDS_IN_DECK-i);
>>}
>>$
>>$ gcc -m64 -S -O3 foo.c
<snip>
>>$
>
>I expected what you got. My test case, which I should have posted, was
>a bit different:
>
>const int CARDS_IN_DECK = 52;
>
>void s(int& permutation, int& choice, int i)
>{
>    choice = permutation % (CARDS_IN_DECK-i);
>    permutation = permutation / (CARDS_IN_DECK-i);
>}
>
>and the results were:
>
>    movl    (%rdi), %eax
>    movl    $52, %ecx
>    subl    %edx, %ecx
>    cltd
>    idivl   %ecx
>    movl    %edx, (%rsi)
>    movl    (%rdi), %eax
>    cltd
>    idivl   %ecx
>    movl    %eax, (%rdi)
>    ret
>
>Changing permutation and choice to externals make all the difference,
>for whatever reason...
>

My guess -- in case anyone is wondering -- is that Fortran has
stricter anti-aliasing rules than C++. When the input permutation
argument is passed by value instead of by reference:

const int CARDS_IN_DECK = 52;

void s(int perm_in, int& perm_out, int& choice_out, int i)
{
    choice_out = perm_in % (CARDS_IN_DECK-i);
    perm_out = perm_in / (CARDS_IN_DECK-i);
}

GNU C++ does the expected optimization at -O1:

	movq	%rdx, %r8
	movl	%ecx, %eax
	movl	$52, %ecx
	subl	%eax, %ecx
	movl	%edi, %eax
	cltd
	idivl	%ecx
	movl	%edx, (%r8)
	movl	%eax, (%rsi)
	ret

Louis



More information about the Info-vax mailing list