Index: cfe/trunk/lib/CodeGen/CGBuiltin.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp @@ -915,7 +915,11 @@ Overflow = CGF.Builder.CreateOr(Overflow, TruncOverflow); } - Result = CGF.Builder.CreateTrunc(UnsignedResult, ResTy); + // Negate the product if it would be negative in infinite precision. + Result = CGF.Builder.CreateSelect( + IsNegative, CGF.Builder.CreateNeg(UnsignedResult), UnsignedResult); + + Result = CGF.Builder.CreateTrunc(Result, ResTy); } assert(Overflow && Result && "Missing overflow or result"); Index: cfe/trunk/test/CodeGen/builtins-overflow.c =================================================================== --- cfe/trunk/test/CodeGen/builtins-overflow.c +++ cfe/trunk/test/CodeGen/builtins-overflow.c @@ -373,7 +373,9 @@ // 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 @@ // 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))