shift+test optimization error

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I have what looks to me like a flawed optimization by the
6.3.1 gcc.

This is the program:

/* bug24192 test case */
#include <stdio.h>

/* whatever the shift in badexample does,
 * the function should never return 1
 */
 
long
badexample(unsigned long iv)
{
  long ov = ((long)(1)) << ((iv & 0x3f) + 1);
  if (ov == 1)
    ov = 0;
  return ov;
}

int
main()
{
  int i;
  for(i=60;i<65;i++)
    printf("%d=>0x%lx\n",i&63,badexample(i&63));
}

/* end bug24192 test case */

The "if (ov==1)..."  test is failing when the compilation is optimized,
but not when compiled without optimization, as shown below.
The 63=>0x1 line should be 63=>0x0.

$ gcc -O -Wall -Wextra bug24192.c
$ ./a.out
60=>0x2000000000000000
61=>0x4000000000000000
62=>0x8000000000000000
63=>0x1
0=>0x2
$ gcc -Wall -Wextra bug24192.c
$ ./a.out
60=>0x2000000000000000
61=>0x4000000000000000
62=>0x8000000000000000
63=>0x0
0=>0x2

The reason is that the optimized code isn't looking at the value of
ov, but at the value of the shift argument, as seen in the assembly
code below. The shift argument is 64, which acts like an argument of
0 on the 64-bit x86, but the test is only looking for a shift
argument of 0. Shouldn't a programmer be able to expect that
whatever the shift operation puts into ov, the subsequent test
will ensure that the function cannot return 1?

$ gcc -S -O -o bug24192.s bug24192.c
$ cat bug24192.s
	.file	"bug24192.c"
	.text
	.globl	badexample
	.type	badexample, @function
badexample:
.LFB11:
	.cfi_startproc
	andl	$63, %edi
	movl	%edi, %ecx
	addl	$1, %ecx
	movl	$1, %eax
	salq	%cl, %rax
	testl	%ecx, %ecx
	movl	$0, %edx
	cmove	%rdx, %rax
	ret
	.cfi_endproc
.LFE11:
	.size	badexample, .-badexample
	.section	.rodata.str1.1,"aMS",@progbits,1
.LC0:
	.string	"%d=>0x%lx\n"
	.text
	.globl	main
	.type	main, @function
main:
.LFB12:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	pushq	%rbx
	.cfi_def_cfa_offset 24
	.cfi_offset 3, -24
	subq	$8, %rsp
	.cfi_def_cfa_offset 32
	movl	$60, %ebx
.L5:
	movl	%ebx, %ebp
	andl	$63, %ebp
	movslq	%ebp, %rdi
	call	badexample
	movq	%rax, %rdx
	movl	%ebp, %esi
	movl	$.LC0, %edi
	movl	$0, %eax
	call	printf
	addl	$1, %ebx
	cmpl	$65, %ebx
	jne	.L5
	movl	$0, %eax
	addq	$8, %rsp
	.cfi_def_cfa_offset 24
	popq	%rbx
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE12:
	.size	main, .-main
	.ident	"GCC: (GNU) 6.3.1 20161221 (Red Hat 6.3.1-1)"
	.section	.note.GNU-stack,"",@progbits

Here's the gcc info:

$ gcc -v
Using built-in specs.
COLLECT_GCC=/usr/bin/gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/6.3.1/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --disable-libgcj --with-isl --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 6.3.1 20161221 (Red Hat 6.3.1-1) (GCC)






[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux