Bug 79121 - [6/7 Regression] invalid expansion of sign-extend unsigned plus left shift
Summary: [6/7 Regression] invalid expansion of sign-extend unsigned plus left shift
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 6.0
: P2 normal
Target Milestone: 6.4
Assignee: Richard Earnshaw
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2017-01-17 19:29 UTC by Richard Earnshaw
Modified: 2017-01-20 11:45 UTC (History)
3 users (show)

See Also:
Host:
Target: arm-* mips-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-01-17 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Earnshaw 2017-01-17 19:29:41 UTC
In the following, the conversion to long long requires a zero extend, however the expanders use an arithmetic right shift to generate the high-part word.

long long dohash(unsigned x) {
        return ((long long)x) << 4;
}

On ARM this generates 

        mov     r1, r0
        lsl     r0, r0, #4
        asr     r1, r1, #28   // Should be lsr
        bx      lr

Similarly on MIPS:

        sll     $3,$4,4
        .set    noreorder
        .set    nomacro
        jr      $31
        sra     $2,$4,28    // should be srl


Possibly introduced by this patch:
r227018 
Author: jiwang <jiwang@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Wed Aug 19 22:55:28 2015 +0000

    [Patch][expand] Check gimple statement to improve LSHIFT_EXP expand
    
    This patch improves LSHIFT_EXP expand if the shift operand comes from sign
    extension and the shift result across word_mode_size boundary. See code
    comments for details.
    
    2015-08-19  Jiong.Wang  <jiong.wang@arm.com>
    
    gcc/
      * expr.c (expand_expr_real_2): Check gimple statement during
      LSHIFT_EXPR expand.
Comment 1 Wilco 2017-01-17 19:51:13 UTC
Confirmed. This also fails on 64-bit targets, eg. on AArch64:

__int128 f2(unsigned long x) { return (__int128)x << 4; }

	mov	x1, x0
	lsl	x0, x0, 4
	asr	x1, x1, 60
	ret
Comment 2 Richard Earnshaw 2017-01-19 10:36:09 UTC
Author: rearnsha
Date: Thu Jan 19 10:35:38 2017
New Revision: 244613

URL: https://gcc.gnu.org/viewcvs?rev=244613&root=gcc&view=rev
Log:
    [expand] Fix for PR rtl-optimization/79121 incorrect expansion of extend plus left shift
    
    When generating a shift from an extended value moving from one to two
    machine registers, the type of the right shift is for the most
    significant word should be determined by the signedness of the inner
    type, not the signedness of the result type.
    
    gcc:
        PR rtl-optimization/79121
        * expr.c (expand_expr_real_2, case LSHIFT_EXPR): Look at the signedness
        of the inner type when shifting an extended value.
    
    gcc/testsuite:
        * gcc.c-torture/execute/pr79121.c: New test.

Added:
    trunk/gcc/testsuite/gcc.c-torture/execute/pr79121.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/expr.c
    trunk/gcc/testsuite/ChangeLog
Comment 3 Richard Earnshaw 2017-01-19 10:41:04 UTC
Fixed on trunk.  Backport to gcc-6 still needed.
Comment 4 Richard Earnshaw 2017-01-20 11:44:30 UTC
Author: rearnsha
Date: Fri Jan 20 11:43:58 2017
New Revision: 244702

URL: https://gcc.gnu.org/viewcvs?rev=244702&root=gcc&view=rev
Log:
    [expand] Fix for PR rtl-optimization/79121 incorrect expansion of extend plus left shift
    
    When generating a shift from an extended value moving from one to two
    machine registers, the type of the right shift is for the most
    significant word should be determined by the signedness of the inner
    type, not the signedness of the result type.
    
    gcc:
	PR rtl-optimization/79121
	* expr.c (expand_expr_real_2, case LSHIFT_EXPR): Look at the signedness
	of the inner type when shifting an extended value.
    
    gcc/testsuite:
	* gcc.c-torture/execute/pr79121.c: New test.


Added:
    branches/gcc-6-branch/gcc/testsuite/gcc.c-torture/execute/pr79121.c
Modified:
    branches/gcc-6-branch/gcc/ChangeLog
    branches/gcc-6-branch/gcc/expr.c
    branches/gcc-6-branch/gcc/testsuite/ChangeLog
Comment 5 Richard Earnshaw 2017-01-20 11:45:47 UTC
Fixed on gcc-6 and trunk.