From 3809ab9a2ef9816f5d42b434df65207fe04a0e44 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 16 Jan 2018 14:49:22 +0000 Subject: Merging r321771: ------------------------------------------------------------------------ r321771 | vedantk | 2018-01-03 15:11:32 -0800 (Wed, 03 Jan 2018) | 21 lines [CGBuiltin] Handle unsigned mul overflow properly (PR35750) r320902 fixed the IRGen for some types of checked multiplications. It did not handle unsigned overflow correctly in the case where the signed operand is negative (PR35750). Eli pointed out that on overflow, the result must be equal to the unique value that is equivalent to the mathematically-correct result modulo two raised to the k power, where k is the number of bits in the result type. This patch fixes the specialized IRGen from r320902 accordingly. Testing: Apart from check-clang, I modified the test harness from r320902 to validate the results of all multiplications -- not just the ones which don't overflow: https://gist.github.com/vedantk/3eb9c88f82e5c32f2e590555b4af5081 llvm.org/PR35750, rdar://34963321 Differential Revision: https://reviews.llvm.org/D41717 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_60@322555 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/builtins-overflow.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/CodeGen/builtins-overflow.c b/test/CodeGen/builtins-overflow.c index 7a30cfbd46..f83bbfb967 100644 --- a/test/CodeGen/builtins-overflow.c +++ b/test/CodeGen/builtins-overflow.c @@ -373,7 +373,9 @@ int test_mixed_sign_mull_overflow_unsigned(int x, unsigned y) { // CHECK-NEXT: [[NotNull:%.*]] = icmp ne i32 [[UnsignedResult]], 0 // CHECK-NEXT: [[Underflow:%.*]] = and i1 [[IsNeg]], [[NotNull]] // CHECK-NEXT: [[OFlow:%.*]] = or i1 [[UnsignedOFlow]], [[Underflow]] -// CHECK-NEXT: store i32 [[UnsignedResult]], i32* %{{.*}}, align 4 +// CHECK-NEXT: [[NegatedResult:%.*]] = sub i32 0, [[UnsignedResult]] +// CHECK-NEXT: [[Result:%.*]] = select i1 [[IsNeg]], i32 [[NegatedResult]], i32 [[UnsignedResult]] +// CHECK-NEXT: store i32 [[Result]], i32* %{{.*}}, align 4 // CHECK: br i1 [[OFlow]] unsigned result; @@ -432,7 +434,9 @@ long long test_mixed_sign_mulll_overflow_trunc_unsigned(long long x, unsigned lo // CHECK-NEXT: [[OVERFLOW_PRE_TRUNC:%.*]] = or i1 {{.*}}, [[UNDERFLOW]] // CHECK-NEXT: [[TRUNC_OVERFLOW:%.*]] = icmp ugt i64 [[UNSIGNED_RESULT]], 4294967295 // CHECK-NEXT: [[OVERFLOW:%.*]] = or i1 [[OVERFLOW_PRE_TRUNC]], [[TRUNC_OVERFLOW]] -// CHECK-NEXT: trunc i64 [[UNSIGNED_RESULT]] to i32 +// CHECK-NEXT: [[NEGATED:%.*]] = sub i64 0, [[UNSIGNED_RESULT]] +// CHECK-NEXT: [[RESULT:%.*]] = select i1 {{.*}}, i64 [[NEGATED]], i64 [[UNSIGNED_RESULT]] +// CHECK-NEXT: trunc i64 [[RESULT]] to i32 // CHECK-NEXT: store unsigned result; if (__builtin_mul_overflow(y, x, &result)) -- cgit v1.2.3