-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[CIR] Upstream overflow builtins #166643
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CIR] Upstream overflow builtins #166643
Changes from 11 commits
7abb216
d032089
7d73c08
848fbe7
d42d928
e2b3629
f77a61d
781e7bb
3b01b5a
05600b8
5c00c3d
afa0bda
28d8de4
1767a97
8e7c9a4
03f4133
7efb03f
1c61733
b18aedf
ebcb509
27a3db7
6fd2afa
2fe28dd
dd9f7f1
052ffdb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -58,6 +58,45 @@ static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const CallExpr *e, | |||||
| return RValue::get(result); | ||||||
| } | ||||||
|
|
||||||
| namespace { | ||||||
| struct WidthAndSignedness { | ||||||
| unsigned width; | ||||||
| bool isSigned; | ||||||
| }; | ||||||
| } // namespace | ||||||
|
|
||||||
| static WidthAndSignedness | ||||||
| getIntegerWidthAndSignedness(const clang::ASTContext &astContext, | ||||||
| const clang::QualType type) { | ||||||
| assert(type->isIntegerType() && "Given type is not an integer."); | ||||||
| unsigned width = type->isBooleanType() ? 1 | ||||||
| : type->isBitIntType() ? astContext.getIntWidth(type) | ||||||
| : astContext.getTypeInfo(type).Width; | ||||||
| bool isSigned = type->isSignedIntegerType(); | ||||||
| return {width, isSigned}; | ||||||
| } | ||||||
|
|
||||||
| // Given one or more integer types, this function produces an integer type that | ||||||
| // encompasses them: any value in one of the given types could be expressed in | ||||||
| // the encompassing type. | ||||||
| static struct WidthAndSignedness | ||||||
| EncompassingIntegerType(ArrayRef<struct WidthAndSignedness> types) { | ||||||
| assert(types.size() > 0 && "Empty list of types."); | ||||||
|
|
||||||
| // If any of the given types is signed, we must return a signed type. | ||||||
| bool isSigned = llvm::any_of(types, [](const auto &t) { return t.isSigned; }); | ||||||
|
|
||||||
| // The encompassing type must have a width greater than or equal to the width | ||||||
| // of the specified types. Additionally, if the encompassing type is signed, | ||||||
| // its width must be strictly greater than the width of any unsigned types | ||||||
| // given. | ||||||
| unsigned width = 0; | ||||||
| for (const auto &type : types) | ||||||
| width = std::max(width, type.width + (isSigned && !type.isSigned)); | ||||||
|
|
||||||
| return {width, isSigned}; | ||||||
| } | ||||||
|
|
||||||
| RValue CIRGenFunction::emitRotate(const CallExpr *e, bool isRotateLeft) { | ||||||
| mlir::Value input = emitScalarExpr(e->getArg(0)); | ||||||
| mlir::Value amount = emitScalarExpr(e->getArg(1)); | ||||||
|
|
@@ -491,6 +530,154 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, | |||||
| cir::PrefetchOp::create(builder, loc, address, locality, isWrite); | ||||||
| return RValue::get(nullptr); | ||||||
| } | ||||||
| case Builtin::BI__builtin_add_overflow: | ||||||
| case Builtin::BI__builtin_sub_overflow: | ||||||
| case Builtin::BI__builtin_mul_overflow: { | ||||||
| const clang::Expr *LeftArg = e->getArg(0); | ||||||
adams381 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| const clang::Expr *RightArg = e->getArg(1); | ||||||
| const clang::Expr *ResultArg = e->getArg(2); | ||||||
|
|
||||||
| clang::QualType ResultQTy = | ||||||
| ResultArg->getType()->castAs<clang::PointerType>()->getPointeeType(); | ||||||
|
|
||||||
| WidthAndSignedness LeftInfo = | ||||||
| getIntegerWidthAndSignedness(cgm.getASTContext(), LeftArg->getType()); | ||||||
| WidthAndSignedness RightInfo = | ||||||
| getIntegerWidthAndSignedness(cgm.getASTContext(), RightArg->getType()); | ||||||
| WidthAndSignedness ResultInfo = | ||||||
| getIntegerWidthAndSignedness(cgm.getASTContext(), ResultQTy); | ||||||
|
|
||||||
| // Note we compute the encompassing type with the consideration to the | ||||||
| // result type, so later in LLVM lowering we don't get redundant integral | ||||||
| // extension casts. | ||||||
| WidthAndSignedness EncompassingInfo = | ||||||
| EncompassingIntegerType({LeftInfo, RightInfo, ResultInfo}); | ||||||
|
|
||||||
| auto EncompassingCIRTy = cir::IntType::get( | ||||||
| &getMLIRContext(), EncompassingInfo.width, EncompassingInfo.isSigned); | ||||||
| auto ResultCIRTy = mlir::cast<cir::IntType>(cgm.convertType(ResultQTy)); | ||||||
|
|
||||||
| mlir::Value Left = emitScalarExpr(LeftArg); | ||||||
| mlir::Value Right = emitScalarExpr(RightArg); | ||||||
| Address ResultPtr = emitPointerWithAlignment(ResultArg); | ||||||
|
|
||||||
| // Extend each operand to the encompassing type, if necessary. | ||||||
| if (Left.getType() != EncompassingCIRTy) | ||||||
| Left = | ||||||
| builder.createCast(cir::CastKind::integral, Left, EncompassingCIRTy); | ||||||
| if (Right.getType() != EncompassingCIRTy) | ||||||
| Right = | ||||||
| builder.createCast(cir::CastKind::integral, Right, EncompassingCIRTy); | ||||||
|
|
||||||
| // Perform the operation on the extended values. | ||||||
| cir::BinOpOverflowKind OpKind; | ||||||
| switch (builtinID) { | ||||||
| default: | ||||||
| llvm_unreachable("Unknown overflow builtin id."); | ||||||
| case Builtin::BI__builtin_add_overflow: | ||||||
| OpKind = cir::BinOpOverflowKind::Add; | ||||||
| break; | ||||||
| case Builtin::BI__builtin_sub_overflow: | ||||||
| OpKind = cir::BinOpOverflowKind::Sub; | ||||||
| break; | ||||||
| case Builtin::BI__builtin_mul_overflow: | ||||||
| OpKind = cir::BinOpOverflowKind::Mul; | ||||||
| break; | ||||||
| } | ||||||
|
|
||||||
| auto Loc = getLoc(e->getSourceRange()); | ||||||
|
||||||
| auto Loc = getLoc(e->getSourceRange()); | |
| mlir::Location loc = getLoc(e->getSourceRange()); |
We don't use auto unless the type is obvious from the code (such as the result of mlir::cast or T::get) or unhelpfully verbose (such as iterators).
https://llvm.org/docs/CodingStandards.html#use-auto-type-deduction-to-make-code-more-readable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still needs to be addressed.
adams381 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No auto here
Uh oh!
There was an error while loading. Please reload this page.