Skip to content
Snippets Groups Projects
  • Keith Randall's avatar
    2cb10d42
    cmd/compile: in prove, zero right shifts of positive int by #bits - 1 · 2cb10d42
    Keith Randall authored
    Taking over Zach's CL 212277. Just cleaned up and added a test.
    
    For a positive, signed integer, an arithmetic right shift of count
    (bit-width - 1) equals zero. e.g. int64(22) >> 63 -> 0. This CL makes
    prove replace these right shifts with a zero-valued constant.
    
    These shifts may arise in source code explicitly, but can also be
    created by the generic rewrite of signed division by a power of 2.
    // Signed divide by power of 2.
    // n / c =       n >> log(c) if n >= 0
    //       = (n+c-1) >> log(c) if n < 0
    // We conditionally add c-1 by adding n>>63>>(64-log(c))
    	(first shift signed, second shift unsigned).
    (Div64 <t> n (Const64 [c])) && isPowerOfTwo(c) ->
      (Rsh64x64
        (Add64 <t> n (Rsh64Ux64 <t>
        	(Rsh64x64 <t> n (Const64 <typ.UInt64> [63]))
    	(Const64 <typ.UInt64> [64-log2(c)])))
        (Const64 <typ.UInt64> [log2(c)]))
    
    If n is known to be positive, this rewrite includes an extra Add and 2
    extra Rsh. This CL will allow prove to replace one of the extra Rsh with
    a 0. That replacement then allows lateopt to remove all the unneccesary
    fixups from the generic rewrite.
    
    There is a rewrite rule to handle this case directly:
    (Div64 n (Const64 [c])) && isNonNegative(n) && isPowerOfTwo(c) ->
    	(Rsh64Ux64 n (Const64 <typ.UInt64> [log2(c)]))
    But this implementation of isNonNegative really only handles constants
    and a few special operations like len/cap. The division could be
    handled if the factsTable version of isNonNegative were available.
    Unfortunately, the first opt pass happens before prove even has a
    chance to deduce the numerator is non-negative, so the generic rewrite
    has already fired and created the extra Ops discussed above.
    
    Fixes #36159
    
    By Printf count, this zeroes 137 right shifts when building std and cmd.
    
    Change-Id: Iab486910ac9d7cfb86ace2835456002732b384a2
    Reviewed-on: https://go-review.googlesource.com/c/go/+/232857
    
    
    Run-TryBot: Keith Randall <khr@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
    2cb10d42
    History
    cmd/compile: in prove, zero right shifts of positive int by #bits - 1
    Keith Randall authored
    Taking over Zach's CL 212277. Just cleaned up and added a test.
    
    For a positive, signed integer, an arithmetic right shift of count
    (bit-width - 1) equals zero. e.g. int64(22) >> 63 -> 0. This CL makes
    prove replace these right shifts with a zero-valued constant.
    
    These shifts may arise in source code explicitly, but can also be
    created by the generic rewrite of signed division by a power of 2.
    // Signed divide by power of 2.
    // n / c =       n >> log(c) if n >= 0
    //       = (n+c-1) >> log(c) if n < 0
    // We conditionally add c-1 by adding n>>63>>(64-log(c))
    	(first shift signed, second shift unsigned).
    (Div64 <t> n (Const64 [c])) && isPowerOfTwo(c) ->
      (Rsh64x64
        (Add64 <t> n (Rsh64Ux64 <t>
        	(Rsh64x64 <t> n (Const64 <typ.UInt64> [63]))
    	(Const64 <typ.UInt64> [64-log2(c)])))
        (Const64 <typ.UInt64> [log2(c)]))
    
    If n is known to be positive, this rewrite includes an extra Add and 2
    extra Rsh. This CL will allow prove to replace one of the extra Rsh with
    a 0. That replacement then allows lateopt to remove all the unneccesary
    fixups from the generic rewrite.
    
    There is a rewrite rule to handle this case directly:
    (Div64 n (Const64 [c])) && isNonNegative(n) && isPowerOfTwo(c) ->
    	(Rsh64Ux64 n (Const64 <typ.UInt64> [log2(c)]))
    But this implementation of isNonNegative really only handles constants
    and a few special operations like len/cap. The division could be
    handled if the factsTable version of isNonNegative were available.
    Unfortunately, the first opt pass happens before prove even has a
    chance to deduce the numerator is non-negative, so the generic rewrite
    has already fired and created the extra Ops discussed above.
    
    Fixes #36159
    
    By Printf count, this zeroes 137 right shifts when building std and cmd.
    
    Change-Id: Iab486910ac9d7cfb86ace2835456002732b384a2
    Reviewed-on: https://go-review.googlesource.com/c/go/+/232857
    
    
    Run-TryBot: Keith Randall <khr@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
Code owners
Assign users and groups as approvers for specific file changes. Learn more.