Author: vedantk Date: Tue Dec 18 13:05:03 2018 New Revision: 349542 URL: http://llvm.org/viewvc/llvm-project?rev=349542&view=rev Log: [CodeGen] Handle mixed-width ops in mixed-sign mul-with-overflow lowering
The special lowering for __builtin_mul_overflow introduced in r320902 fixed an ICE seen when passing mixed-sign operands to the builtin. This patch extends the special lowering to cover mixed-width, mixed-sign operands. In a few common scenarios, calls to muloti4 will no longer be emitted. This should address the latest comments in PR34920 and work around the link failure seen in: https://bugzilla.redhat.com/show_bug.cgi?id=1657544 Testing: - check-clang - A/B output comparison with: https://gist.github.com/vedantk/3eb9c88f82e5c32f2e590555b4af5081 Differential Revision: https://reviews.llvm.org/D55843 Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp cfe/trunk/test/CodeGen/builtins-overflow.c Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=349542&r1=349541&r2=349542&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original) +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Tue Dec 18 13:05:03 2018 @@ -1235,7 +1235,7 @@ static bool isSpecialMixedSignMultiply(u WidthAndSignedness Op2Info, WidthAndSignedness ResultInfo) { return BuiltinID == Builtin::BI__builtin_mul_overflow && - Op1Info.Width == Op2Info.Width && Op1Info.Width >= ResultInfo.Width && + std::max(Op1Info.Width, Op2Info.Width) >= ResultInfo.Width && Op1Info.Signed != Op2Info.Signed; } @@ -1256,11 +1256,20 @@ EmitCheckedMixedSignMultiply(CodeGenFunc const clang::Expr *UnsignedOp = Op1Info.Signed ? Op2 : Op1; llvm::Value *Signed = CGF.EmitScalarExpr(SignedOp); llvm::Value *Unsigned = CGF.EmitScalarExpr(UnsignedOp); + unsigned SignedOpWidth = Op1Info.Signed ? Op1Info.Width : Op2Info.Width; + unsigned UnsignedOpWidth = Op1Info.Signed ? Op2Info.Width : Op1Info.Width; + + // One of the operands may be smaller than the other. If so, [s|z]ext it. + if (SignedOpWidth < UnsignedOpWidth) + Signed = CGF.Builder.CreateSExt(Signed, Unsigned->getType(), "op.sext"); + if (UnsignedOpWidth < SignedOpWidth) + Unsigned = CGF.Builder.CreateZExt(Unsigned, Signed->getType(), "op.zext"); llvm::Type *OpTy = Signed->getType(); llvm::Value *Zero = llvm::Constant::getNullValue(OpTy); Address ResultPtr = CGF.EmitPointerWithAlignment(ResultArg); llvm::Type *ResTy = ResultPtr.getElementType(); + unsigned OpWidth = std::max(Op1Info.Width, Op2Info.Width); // Take the absolute value of the signed operand. llvm::Value *IsNegative = CGF.Builder.CreateICmpSLT(Signed, Zero); @@ -1278,8 +1287,8 @@ EmitCheckedMixedSignMultiply(CodeGenFunc if (ResultInfo.Signed) { // Signed overflow occurs if the result is greater than INT_MAX or lesser // than INT_MIN, i.e when |Result| > (INT_MAX + IsNegative). - auto IntMax = llvm::APInt::getSignedMaxValue(ResultInfo.Width) - .zextOrSelf(Op1Info.Width); + auto IntMax = + llvm::APInt::getSignedMaxValue(ResultInfo.Width).zextOrSelf(OpWidth); llvm::Value *MaxResult = CGF.Builder.CreateAdd(llvm::ConstantInt::get(OpTy, IntMax), CGF.Builder.CreateZExt(IsNegative, OpTy)); @@ -1297,9 +1306,9 @@ EmitCheckedMixedSignMultiply(CodeGenFunc llvm::Value *Underflow = CGF.Builder.CreateAnd( IsNegative, CGF.Builder.CreateIsNotNull(UnsignedResult)); Overflow = CGF.Builder.CreateOr(UnsignedOverflow, Underflow); - if (ResultInfo.Width < Op1Info.Width) { + if (ResultInfo.Width < OpWidth) { auto IntMax = - llvm::APInt::getMaxValue(ResultInfo.Width).zext(Op1Info.Width); + llvm::APInt::getMaxValue(ResultInfo.Width).zext(OpWidth); llvm::Value *TruncOverflow = CGF.Builder.CreateICmpUGT( UnsignedResult, llvm::ConstantInt::get(OpTy, IntMax)); Overflow = CGF.Builder.CreateOr(Overflow, TruncOverflow); Modified: cfe/trunk/test/CodeGen/builtins-overflow.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtins-overflow.c?rev=349542&r1=349541&r2=349542&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/builtins-overflow.c (original) +++ cfe/trunk/test/CodeGen/builtins-overflow.c Tue Dec 18 13:05:03 2018 @@ -339,6 +339,27 @@ long long test_smulll_overflow(long long return result; } +int test_mixed_sign_mul_overflow_sext_signed_op(int x, unsigned long long y) { +// CHECK: @test_mixed_sign_mul_overflow_sext_signed_op +// CHECK: [[SignedOp:%.*]] = sext i32 %0 to i64 +// CHECK: [[IsNeg:%.*]] = icmp slt i64 [[SignedOp]], 0 + int result; + if (__builtin_mul_overflow(x, y, &result)) + return LongErrorCode; + return result; +} + +int test_mixed_sign_mul_overflow_zext_unsigned_op(long long x, unsigned y) { +// CHECK: @test_mixed_sign_mul_overflow_zext_unsigned_op +// CHECK: [[UnsignedOp:%.*]] = zext i32 %1 to i64 +// CHECK: [[IsNeg:%.*]] = icmp slt i64 %0, 0 +// CHECK: @llvm.umul.with.overflow.i64({{.*}}, i64 [[UnsignedOp]]) + int result; + if (__builtin_mul_overflow(x, y, &result)) + return LongErrorCode; + return result; +} + int test_mixed_sign_mull_overflow(int x, unsigned y) { // CHECK: @test_mixed_sign_mull_overflow // CHECK: [[IsNeg:%.*]] = icmp slt i32 [[Op1:%.*]], 0 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits