Bug 80341

Summary: [5 Regression] gcc miscompiles division of signed char
Product: gcc Reporter: Vsevolod Livinskii <vsevolod.livinskiy>
Component: middle-endAssignee: Richard Biener <rguenth>
Status: RESOLVED FIXED    
Severity: normal CC: jakub
Priority: P2 Keywords: wrong-code
Version: 7.0.1   
Target Milestone: 6.4   
Host: Target:
Build: Known to work: 6.3.1, 7.0.1
Known to fail: 5.4.0, 6.3.0 Last reconfirmed: 2017-04-06 00:00:00
Bug Depends on:    
Bug Blocks: 103035    
Attachments: Reproducer.

Description Vsevolod Livinskii 2017-04-06 10:48:39 UTC
Created attachment 41140 [details]
Reproducer.

GCC generates incorrect code. Correct result is 90.

Reproducer:
>$ cat foo.c
extern const signed char var_25;
extern signed char var_465;

void foo() { 
    var_465 = (unsigned short) var_25 / -55; 
} 
>$ cat main.c
#include <stdio.h>

extern void foo ();

const signed char var_25 = -84;
signed char var_465 = 0;

int main () {
    foo ();
    printf("%d\n", (int) var_465);
    return 0;
}

Run:
>$ gcc main.c foo.c ; ./a.out 
1

GCC version:
Rev. 246681
>$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/home/vsevolod/workspace/gcc-dev/bin-trunk/libexec/gcc/x86_64-pc-linux-gnu/7.0.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /home/vsevolod/workspace/gcc-dev/trunk/configure --prefix=/home/vsevolod/workspace/gcc-dev/bin-trunk --disable-bootstrap
Thread model: posix
gcc version 7.0.1 20170404 (experimental) (GCC)
Comment 1 Marek Polacek 2017-04-06 11:07:26 UTC
GCC 4.4 gives 90 but GCC 4.5 gives 1.
Comment 2 Marek Polacek 2017-04-06 12:24:19 UTC
Better testcase:

const signed char c = -84;
signed char s;

void
foo ()
{
  s = (unsigned short) c / -55;
}

int
main ()
{
  foo ();
  if (s != 90)
    __builtin_abort ();
}
Comment 3 Marek Polacek 2017-04-06 12:25:54 UTC
Likely started with

commit 4d307e1ff39d0c2f90123ef789d611e2323be76d
Author: rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Wed Feb 10 11:54:14 2010 +0000

    2010-02-10  Richard Guenther  <rguenther@suse.de>
    
            PR c/43007
            * tree.c (get_unwidened): Handle constants.
            * convert.c (convert_to_integer): Handle TRUNC_DIV_EXPR.
    
            * gcc.c-torture/execute/20100209-1.c: New testcase.
            * gcc.dg/fold-div-3.c: Likewise.
    
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@156653 138bc75d-0d04-0410-961f-82ee72b054a4
Comment 4 Marek Polacek 2017-04-06 12:38:13 UTC
With -O I get
x.c: In function ‘foo’:
x.c:7:7: warning: overflow in implicit constant conversion [-Woverflow]
   s = (unsigned short) c / -55;
       ^
Comment 5 Richard Biener 2017-04-06 12:51:15 UTC
hmm, get_unwidened ((int) (short unsigned int) c) returns c?!  I wonder if that's by design...
Comment 6 Richard Biener 2017-04-06 12:54:25 UTC
Ah, it is as we pass it signed char as 2nd arg...
Comment 7 Richard Biener 2017-04-06 14:01:38 UTC
Testing patch.
Comment 8 Richard Biener 2017-04-07 08:20:56 UTC
Author: rguenth
Date: Fri Apr  7 08:20:24 2017
New Revision: 246756

URL: https://gcc.gnu.org/viewcvs?rev=246756&root=gcc&view=rev
Log:
2017-04-07  Richard Biener  <rguenther@suse.de>

	PR middle-end/80341
	* tree.c (get_unwidened): Also handle ! for_type case for
	INTEGER_CSTs.
	* convert.c (do_narrow): Split out from ...
	(convert_to_integer_1): ... here.  Do not pass final truncation
	type to get_unwidened for TRUNC_DIV_EXPR.

	* gcc.dg/torture/pr80341.c: New testcase.

Added:
    trunk/gcc/testsuite/gcc.dg/torture/pr80341.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/convert.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree.c
Comment 9 Richard Biener 2017-04-07 08:38:30 UTC
Fixed on trunk sofar.
Comment 10 Richard Biener 2017-06-22 07:31:07 UTC
Author: rguenth
Date: Thu Jun 22 07:30:03 2017
New Revision: 249499

URL: https://gcc.gnu.org/viewcvs?rev=249499&root=gcc&view=rev
Log:
2017-06-22  Richard Biener  <rguenther@suse.de>

	Backport from mainline
	2017-04-20  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/80453
	* tree-ssa-sccvn.h (struct vn_phi_s): Add cclhs and ccrhs members.
	* tree-ssa-sccvn.c (cond_stmts_equal_p): Use recorded lhs and rhs
	from the conditions.
	(vn_phi_eq): Pass them down.
	(vn_phi_lookup): Record them.
	(vn_phi_insert): Likewise.

	2017-04-07  Richard Biener  <rguenther@suse.de>

	PR middle-end/80341
	* tree.c (get_unwidened): Also handle ! for_type case for
	INTEGER_CSTs.
	* convert.c (do_narrow): Split out from ...
	(convert_to_integer_1): ... here.  Do not pass final truncation
	type to get_unwidened for TRUNC_DIV_EXPR.

	* gcc.dg/torture/pr80341.c: New testcase.

	2017-04-04  Richard Biener  <rguenther@suse.de>

	PR middle-end/80281
	* match.pd (A + (-B) -> A - B): Make sure to preserve unsigned
	arithmetic done for the negate or the plus.  Simplify.
	(A - (-B) -> A + B): Likewise.
	* fold-const.c (split_tree): Make sure to not negate pointers.

	* gcc.dg/torture/pr80281.c: New testcase.

Modified:
    branches/gcc-6-branch/gcc/ChangeLog
    branches/gcc-6-branch/gcc/convert.c
    branches/gcc-6-branch/gcc/fold-const.c
    branches/gcc-6-branch/gcc/match.pd
    branches/gcc-6-branch/gcc/testsuite/ChangeLog
    branches/gcc-6-branch/gcc/tree-ssa-sccvn.c
    branches/gcc-6-branch/gcc/tree-ssa-sccvn.h
    branches/gcc-6-branch/gcc/tree.c
Comment 11 Richard Biener 2017-09-18 11:10:37 UTC
Author: rguenth
Date: Mon Sep 18 11:10:06 2017
New Revision: 252920

URL: https://gcc.gnu.org/viewcvs?rev=252920&root=gcc&view=rev
Log:
2017-09-18  Richard Biener  <rguenther@suse.de>
 
	Backport from mainline
	2017-04-07  Richard Biener  <rguenther@suse.de>

	PR middle-end/80341
	* gcc.dg/torture/pr80341.c: New testcase.

	2017-04-04  Richard Biener  <rguenther@suse.de>

	PR middle-end/80281
	* gcc.dg/torture/pr80281.c: New testcase.

Added:
    branches/gcc-6-branch/gcc/testsuite/gcc.dg/torture/pr80281.c
    branches/gcc-6-branch/gcc/testsuite/gcc.dg/torture/pr80341.c
Modified:
    branches/gcc-6-branch/gcc/testsuite/ChangeLog
Comment 12 Jakub Jelinek 2017-10-11 09:28:55 UTC
GCC 5 branch has been closed, should be fixed in GCC 6.4 and later.