Tested with 8.00 RC6 and 7.00 (refresh).
With any of the optimization options, bad code is generated.
With optimization on, gcd returns 0. With optimization off it returns 1, which is the correct result.
int gcd(int a, int b)
{
if(b) return gcd(b,a%b);
else return a;
}
int main(void)
{
return gcd(1,1);
}
Using a temp variable removes the bug, when optimizations are present.
#include <stdio.h>
int gcd(int a, int b)
{
if( b != 0 )
{
const int c = a%b ;
return gcd( b , c ) ;
}
else
{
return a ;
}
}
int main(void)
{
printf("%d\n" , gcd(1,1) ) ;
return 0 ;
}
Both examples are with optimization, the problem is with the last two mov instructions, otherwise the code is the same.
(http://i.imgur.com/DlxoKVh.jpg)
Very nice the optimization that doesn't recall the sub sparing stack space and speeding-up execution! :)
The error is the same in the 32 and 64 bits version:
;;;;; 32 Bits version
_gcd:
push ebx
mov ebx,dword ptr [esp+8]
mov ecx,dword ptr [esp+C]
50: {
51: if(b)
L9:
test ecx,ecx
je L18
52: return gcd(b,a%b);
mov eax,ebx
cdq
idiv ecx
mov ecx,edx ;---\
mov ebx,ecx ;---+----------- WRONG! these instructions must be reversed
jmp L9
53: else
54: return a;
L18:
mov eax,ebx
pop ebx
ret
lea edi,[edi+0]
55: }
;;;;;;; 64 bits version
49: int gcd(int a, int b)
gcd:
mov r8d,ecx
mov ecx,edx
50: {
51: if(b)
L5:
test ecx,ecx
je L16
52: return gcd(b,a%b);
mov eax,r8d
cdq
idiv ecx
mov ecx,edx ;---\
mov r8d,ecx ;---+----------- WRONG! these instructions must be reversed
jmp L5
53: else
54: return a;
L16:
mov eax,r8d
ret
55: }
EDIT: I'm very tired today, my brain wan't cooperate! I posted two wrong answers in a row!!! >:(
The problem is the order of the move instructions that reloads the parameters ... :P
Maybe it's better to check if destination register is a result holding register to define the correct order of data assignement.
Not fixed in 8.00 RC7.
Fixed in 8.00 RC8.