[llvm-commits] [llvm] r126964 - in /llvm/trunk: lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp lib/CodeGen/SelectionDAG/LegalizeTypes.h test/CodeGen/X86/umulo-64.ll

Eli Friedman eli.friedman at gmail.com
Thu Mar 3 15:12:32 PST 2011


On Thu, Mar 3, 2011 at 2:57 PM, Eric Christopher <echristo at apple.com> wrote:
>
> On Mar 3, 2011, at 2:52 PM, Eli Friedman wrote:
>
>> On Thu, Mar 3, 2011 at 2:39 PM, Eric Christopher <echristo at apple.com> wrote:
>>>
>>> On Mar 3, 2011, at 2:33 PM, Eli Friedman wrote:
>>>
>>>> Author: efriedma
>>>> Date: Thu Mar  3 16:33:23 2011
>>>> New Revision: 126964
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=126964&view=rev
>>>> Log:
>>>> Revert r123908; the code in question is completely untested and wrong.
>>>
>>> How very anti-social of you.
>>>
>>> Don't do that again without sending email first or filing a bug.
>>
>> Sorry, I agree that was inappropriate.
>>
>>> What's up?
>>
>> On x86-64, trying to compile an i128 umulo crashes.  As for smulo,
>> it's returning completely wrong results because it's trying to use the
>> bottom 128 bits of an i128-bit multiply to determine whether it
>> overflowed, which is impossible to do.  For example, compiling the
>> following at -O0 with -ftrapv traps, while it is trivial to conclude
>> it shouldn't because a 64x64->128 multiply can't overflow.
>>
>> #include <stdio.h>
>> __int128_t x(__int128_t a, __int128_t b) {
>>  return a*b;
>> }
>>
>> int main() {
>>  __int128_t r = x((long long)0x8000000000000001, (long
>> long)0x8000000000000000);
>>  printf("%llx %llx\n", (long long)(r >> 64), (long long)r);
>>  return 0;
>> }
>
> Aha. I'd only been testing 64-bit on arm, not 128-bit on x86-64. Though, what happens on x86-64 without the patch applied? It can't possibly succeed and be correct?
>
> I'll take a look at it, but I'm pretty sure the code works for 64-bit. Probably could hack it to turn off if there's no multiply instruction for the target at the width.

Err, I'm reasonably sure the code has precisely the same issues for
64-bit... narrow my previous example and compile on x86-32, and you
end up with the following, which has the exact same issue:

#include <stdio.h>
long long x(long long a, long long b) {
  return a*b;
}
int main() {
  long long r = x((int)0x80000001, (int)0x80000000);
  printf("%llx\n", r);
  return 0;
}

-Eli




More information about the llvm-commits mailing list