[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