Actually I just tried it using GCC Explorer and they both optimise to the same assembly.
Confusing assembly that I can't find the > 0 test in at all.
#include <iostream>
int main()
{
int y;
for (int x = -1; x < 1000; x++)
{
if (x > 0 && x < 10)
{
y = x;
}
}
std::cout << y;
return 0;
}
main:
mov eax, -1 // x = -1
.L3:
lea edx, [rax-1] // edx = x - 1
cmp edx, 8 // compare edx to 8
cmovbe esi, eax // if (edx <= 8) y = x
add eax, 1 // x++
cmp eax, 1000 // compare x to 1000
jne .L3 // jump to L3 (loop start) if x != 1000
sub rsp, 8 // from here on deals with the cout call
mov edi, OFFSET FLAT:std::cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
xor eax, eax
add rsp, 8
ret
sub rsp, 8
mov edi, OFFSET FLAT:std::__ioinit
call std::ios_base::Init::Init()
mov edx, OFFSET FLAT:__dso_handle
mov esi, OFFSET FLAT:std::__ioinit
mov edi, OFFSET FLAT:std::ios_base::Init::~Init()
add rsp, 8
jmp __cxa_atexit
(note it still loops 1000 times even though there's no result from doing so apart from wasting time. Make sure you break loops as early as possible!)
EDIT: Figured it and it's really fecking clever. cmovbe is a conditional move based on an *unsigned* below-or-equal comparison. When x-1 is negative, it'll interpret it as a very large number, and therefore > 8 (>=10 in the original code). The signed version is cmovle (conditional-move-on-less-or-equal). Yes that's confusing.