https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69984
Bug ID: 69984 Summary: [4.9/5/6] Signed comparison instruction emitted for unsigned variable comparison Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: edmar at freescale dot com Target Milestone: --- This test case has only unsigned variables and constants: extern void bar1 (void); extern void bar2 (void); void foo (unsigned short int A, unsigned short int B, unsigned long D) { unsigned long C; unsigned long E = 0x0FFFEFFEUL; C = A * B; if (C <= D) bar1 (); if (C <= E) bar2 (); } Yet, gcc generates signed comparison instruction (jle) for test C<=E: .file "ucmp.c" .text .p2align 4,,15 .globl foo .type foo, @function foo: .LFB0: .cfi_startproc pushq %rbx .cfi_def_cfa_offset 16 .cfi_offset 3, -16 movzwl %si, %esi movzwl %di, %ebx imull %esi, %ebx movslq %ebx, %rax cmpq %rdx, %rax jbe .L6 .L2: cmpl $268431358, %ebx jle .L7 popq %rbx .cfi_remember_state .cfi_def_cfa_offset 8 ret .p2align 4,,10 .p2align 3 .L7: .cfi_restore_state popq %rbx .cfi_remember_state .cfi_def_cfa_offset 8 jmp bar2 .p2align 4,,10 .p2align 3 .L6: .cfi_restore_state call bar1 jmp .L2 .cfi_endproc .LFE0: .size foo, .-foo .ident "GCC: (GNU) 6.0.0 20160226 (Fri Feb 26 14:08:27 CST 2016 build.sh rev=1286 s=FCtrunk Nx86_64)" .section .note.GNU-stack,"",@progbits -fsanitize=<sub-options> silently corrects the code: (I tried with *each of*: undefined, signed-integer-overflow, bounds, unreachable, return, address. Any one will correct the code) ex: ... imull %esi, %ebx jo .L8 .L2: movslq %ebx, %rbx cmpq %rbp, %rbx jbe .L9 .L4: cmpq $268431358, %rbx jbe .L10 ... and also -fno-tree-vrp: ... imull %ebx, %edi movslq %edi, %rbx cmpq %rdx, %rbx jbe .L6 .L2: cmpq $268431358, %rbx jbe .L7 ... With PowerPC target I can trace this all the way back to 4.9.2 (Did not try 4.9.[01]). 4.8.3 generates correct code. Test compiled with: gcc -O3 -S ucmp.c gcc configured with: gcc -v Using built-in specs. COLLECT_GCC=/local/edmar/bug_area/opt/freescale/gcc-6.0.x-Nx86_64-linux/x86_64-linux/bin/gcc COLLECT_LTO_WRAPPER=/local/edmar/bug_area/opt/freescale/gcc-6.0.x-Nx86_64-linux/x86_64-linux/bin/../libexec/gcc/x86_64-pc-linux/6.0.0/lto-wrapper Target: x86_64-pc-linux Configured with: ../src_gcc/configure --prefix=/local/edmar/bug_area//opt/freescale/gcc-6.0.x-Nx86_64-linux/x86_64-linux --target=x86_64-pc-linux --build=x86_64-pc-linux --enable-checking --disable-decimal-float --enable-interfaces=c,c++ --with-cpu=generic --enable-tls --enable-build-with-cxx --enable-languages=c,c++ --with-gmp=/local/edmar/bug_area//opt/freescale/Nx86_64/linux_host_libs/usr/64 --with-target-gmp=/local/edmar/bug_area//opt/freescale/Nx86_64/linux_host_libs/tgmp/64 --disable-target-multilib --with-mpfr=/local/edmar/bug_area//opt/freescale/Nx86_64/linux_host_libs/usr/64 --with-mpc=/local/edmar/bug_area//opt/freescale/Nx86_64/linux_host_libs/usr/64 --with-ppl=/local/edmar/bug_area//opt/freescale/Nx86_64/linux_host_libs/usr/64 --with-isl=/local/edmar/bug_area//opt/freescale/Nx86_64/linux_host_libs/usr/64 --with-cloog=/local/edmar/bug_area//opt/freescale/Nx86_64/linux_host_libs/usr/64 --enable-cloog-backend=isl Thread model: posix gcc version 6.0.0 20160226 (Fri Feb 26 14:08:27 CST 2016 build.sh rev=1286 s=FCtrunk Nx86_64) (GCC) ucmp.c.084t.oaccdevlow: ;; Function foo (foo, funcdef_no=0, decl_uid=1760, cgraph_uid=0, symbol_order=1) foo (short unsigned int A, short unsigned int B, long unsigned int D) { long unsigned int C; int _4; int _6; int _7; long unsigned int E.0_12; <bb 2>: _4 = (int) A_3(D); _6 = (int) B_5(D); _7 = _4 * _6; C_8 = (long unsigned int) _7; if (C_8 <= D_9(D)) goto <bb 3>; else goto <bb 4>; <bb 3>: bar1 (); <bb 4>: E.0_12 = E; if (C_8 <= E.0_12) goto <bb 5>; else goto <bb 6>; <bb 5>: bar2 (); <bb 6>: return; } ucmp.c.086t.ccp2: ;; Function foo (foo, funcdef_no=0, decl_uid=1760, cgraph_uid=0, symbol_order=1) foo (short unsigned int A, short unsigned int B, long unsigned int D) { long unsigned int C; int _4; int _6; int _7; <bb 2>: _4 = (int) A_3(D); _6 = (int) B_5(D); _7 = _4 * _6; C_8 = (long unsigned int) _7; if (C_8 <= D_9(D)) goto <bb 3>; else goto <bb 4>; <bb 3>: bar1 (); <bb 4>: if (C_8 <= 268431358) goto <bb 5>; else goto <bb 6>; <bb 5>: bar2 (); <bb 6>: return; } ucmp.c.096t.vrp1: ;; Function foo (foo, funcdef_no=0, decl_uid=1760, cgraph_uid=0, symbol_order=1) ;; 1 loops found ;; ;; Loop 0 ;; header 0, latch 1 ;; depth 0, outer -1 ;; nodes: 0 1 2 3 4 5 6 ;; 2 succs { 3 4 } ;; 3 succs { 4 } ;; 4 succs { 5 6 } ;; 5 succs { 6 } ;; 6 succs { 1 } SSA replacement table N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j C_12 -> { C_8 } C_14 -> { C_8 } Incremental SSA update started at block: 2 Number of blocks in CFG: 8 Number of blocks to update: 4 ( 50%) Value ranges after VRP: .MEM_1: VARYING .MEM_2: VARYING A_3(D): VARYING _4: [0, 65535] B_5(D): VARYING _6: [0, 65535] _7: [0, +INF(OVF)] C_8: [0, +INF] D_9(D): VARYING C_12: [0, D_9(D)] EQUIVALENCES: { C_8 } (1 elements) C_14: [D_9(D) + 1, +INF] EQUIVALENCES: { C_8 } (1 elements) Removing basic block 7 foo (short unsigned int A, short unsigned int B, long unsigned int D) { long unsigned int C; int _4; int _6; int _7; <bb 2>: _4 = (int) A_3(D); _6 = (int) B_5(D); _7 = _4 * _6; C_8 = (long unsigned int) _7; if (C_8 <= D_9(D)) goto <bb 3>; else goto <bb 4>; <bb 3>: bar1 (); <bb 4>: if (_7 <= 268431358) goto <bb 5>; else goto <bb 6>; <bb 5>: bar2 (); <bb 6>: return; }