[PATCH] [IR] Fix the definition of 'shl nsw'

Sanjoy Das sanjoy at playingwithpointers.com
Wed Apr 8 02:39:04 PDT 2015


One way to phrase the overflow behavior in terms of bits shifted out
is:

T << S as N-bit integers sign-overflows if and only if

  a. S != N and the bits shifted out are not all equal to the sign bit
     of (T << S).

  b. S == N and the bits shifted out are not all zero.

[(a) is the definition of sign-overflow as in the LangRef today.  (b)
is LangRef's definition for unsigned-wrap.]

(b) is equivalent to "S == N and T != 1".

We can now prove that "T << S" sign-overflows iff "T * (1 << S)"
sign-overflows:

If S != N:
     Sext(T * (1 << S)) == Sext(T) * Sext(1 << S)
<=>  Sext(T * (1 << S)) == Sext(T) * Zext(1 << S)
<=>  Sext(T * (1 << S)) == Sext(T) << S  -- (A)
<=>  Sext(T << S) == Sext(T) << S
<=>  (a)


if S == N:
     Sext(T * (1 << S)) == Sext(T) * Sext(1 << S)
<=>  Sext(T * (1 << N)) == Sext(T) * Sext(1 << N)
<=>  T == 1
<=>  (b)

For (A) we use the identity "Sext(T) << S == Sext(T) * Zext(1 << S)".
This really is the interesting difference between shifting and
multiplication -- roughly speaking, shifting always treats its second
argument as unsigned.  More precisely, if we define a "half-nsw
multiplication", one where "sext(A *hnsw B) == sext(A) * zext(B)" then
the current definition of an "shl nsw A B" in the LangRef is
equivalent to "A *hnsw B".

-- Sanjoy



More information about the llvm-commits mailing list