@@ -147,6 +147,15 @@ struct BinOpInfo {
147147 return UnOp->getSubExpr ()->getType ()->isFixedPointType ();
148148 return false ;
149149 }
150+
151+ // / Does the BinaryOperator have the wraps attribute?
152+ // / If so, we can ellide overflow sanitizer checks.
153+ bool oneOfWraps () const {
154+ const Type *TyPtr = E->getType ().getTypePtrOrNull ();
155+ if (TyPtr)
156+ return TyPtr->hasAttr (attr::Wraps);
157+ return false ;
158+ }
150159};
151160
152161static bool MustVisitNullValue (const Expr *E) {
@@ -726,6 +735,11 @@ class ScalarExprEmitter
726735
727736 // Binary Operators.
728737 Value *EmitMul (const BinOpInfo &Ops) {
738+ if ((Ops.Ty ->isSignedIntegerOrEnumerationType () ||
739+ Ops.Ty ->isUnsignedIntegerType ()) &&
740+ Ops.oneOfWraps ())
741+ return Builder.CreateMul (Ops.LHS , Ops.RHS , " mul" );
742+
729743 if (Ops.Ty ->isSignedIntegerOrEnumerationType ()) {
730744 switch (CGF.getLangOpts ().getSignedOverflowBehavior ()) {
731745 case LangOptions::SOB_Defined:
@@ -2822,6 +2836,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
28222836 } else if (type->isIntegerType ()) {
28232837 QualType promotedType;
28242838 bool canPerformLossyDemotionCheck = false ;
2839+ BinOpInfo Ops = (createBinOpInfoFromIncDec (
2840+ E, value, isInc, E->getFPFeaturesInEffect (CGF.getLangOpts ())));
2841+
28252842 if (CGF.getContext ().isPromotableIntegerType (type)) {
28262843 promotedType = CGF.getContext ().getPromotedIntegerType (type);
28272844 assert (promotedType != type && " Shouldn't promote to the same type." );
@@ -2878,10 +2895,12 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
28782895 // Note that signed integer inc/dec with width less than int can't
28792896 // overflow because of promotion rules; we're just eliding a few steps
28802897 // here.
2881- } else if (E->canOverflow () && type->isSignedIntegerOrEnumerationType ()) {
2898+ } else if (E->canOverflow () && type->isSignedIntegerOrEnumerationType () &&
2899+ !Ops.oneOfWraps ()) {
28822900 value = EmitIncDecConsiderOverflowBehavior (E, value, isInc);
28832901 } else if (E->canOverflow () && type->isUnsignedIntegerType () &&
2884- CGF.SanOpts .has (SanitizerKind::UnsignedIntegerOverflow)) {
2902+ CGF.SanOpts .has (SanitizerKind::UnsignedIntegerOverflow) &&
2903+ !Ops.oneOfWraps ()) {
28852904 value = EmitOverflowCheckedBinOp (createBinOpInfoFromIncDec (
28862905 E, value, isInc, E->getFPFeaturesInEffect (CGF.getLangOpts ())));
28872906 } else {
@@ -3670,7 +3689,8 @@ Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
36703689 if ((CGF.SanOpts .has (SanitizerKind::IntegerDivideByZero) ||
36713690 CGF.SanOpts .has (SanitizerKind::SignedIntegerOverflow)) &&
36723691 Ops.Ty ->isIntegerType () &&
3673- (Ops.mayHaveIntegerDivisionByZero () || Ops.mayHaveIntegerOverflow ())) {
3692+ (Ops.mayHaveIntegerDivisionByZero () || Ops.mayHaveIntegerOverflow ()) &&
3693+ !Ops.oneOfWraps ()) {
36743694 llvm::Value *Zero = llvm::Constant::getNullValue (ConvertType (Ops.Ty ));
36753695 EmitUndefinedBehaviorIntegerDivAndRemCheck (Ops, Zero, true );
36763696 } else if (CGF.SanOpts .has (SanitizerKind::FloatDivideByZero) &&
@@ -3719,7 +3739,8 @@ Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) {
37193739 if ((CGF.SanOpts .has (SanitizerKind::IntegerDivideByZero) ||
37203740 CGF.SanOpts .has (SanitizerKind::SignedIntegerOverflow)) &&
37213741 Ops.Ty ->isIntegerType () &&
3722- (Ops.mayHaveIntegerDivisionByZero () || Ops.mayHaveIntegerOverflow ())) {
3742+ (Ops.mayHaveIntegerDivisionByZero () || Ops.mayHaveIntegerOverflow ()) &&
3743+ !Ops.oneOfWraps ()) {
37233744 CodeGenFunction::SanitizerScope SanScope (&CGF);
37243745 llvm::Value *Zero = llvm::Constant::getNullValue (ConvertType (Ops.Ty ));
37253746 EmitUndefinedBehaviorIntegerDivAndRemCheck (Ops, Zero, false );
@@ -4084,6 +4105,11 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {
40844105 op.RHS ->getType ()->isPointerTy ())
40854106 return emitPointerArithmetic (CGF, op, CodeGenFunction::NotSubtraction);
40864107
4108+ if ((op.Ty ->isSignedIntegerOrEnumerationType () ||
4109+ op.Ty ->isUnsignedIntegerType ()) &&
4110+ op.oneOfWraps ())
4111+ return Builder.CreateAdd (op.LHS , op.RHS , " add" );
4112+
40874113 if (op.Ty ->isSignedIntegerOrEnumerationType ()) {
40884114 switch (CGF.getLangOpts ().getSignedOverflowBehavior ()) {
40894115 case LangOptions::SOB_Defined:
@@ -4240,6 +4266,10 @@ Value *ScalarExprEmitter::EmitFixedPointBinOp(const BinOpInfo &op) {
42404266Value *ScalarExprEmitter::EmitSub (const BinOpInfo &op) {
42414267 // The LHS is always a pointer if either side is.
42424268 if (!op.LHS ->getType ()->isPointerTy ()) {
4269+ if ((op.Ty ->isSignedIntegerOrEnumerationType () ||
4270+ op.Ty ->isUnsignedIntegerType ()) &&
4271+ op.oneOfWraps ())
4272+ return Builder.CreateSub (op.LHS , op.RHS , " sub" );
42434273 if (op.Ty ->isSignedIntegerOrEnumerationType ()) {
42444274 switch (CGF.getLangOpts ().getSignedOverflowBehavior ()) {
42454275 case LangOptions::SOB_Defined:
@@ -4390,7 +4420,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
43904420 bool SanitizeSignedBase = CGF.SanOpts .has (SanitizerKind::ShiftBase) &&
43914421 Ops.Ty ->hasSignedIntegerRepresentation () &&
43924422 !CGF.getLangOpts ().isSignedOverflowDefined () &&
4393- !CGF.getLangOpts ().CPlusPlus20 ;
4423+ !CGF.getLangOpts ().CPlusPlus20 && !Ops. oneOfWraps () ;
43944424 bool SanitizeUnsignedBase =
43954425 CGF.SanOpts .has (SanitizerKind::UnsignedShiftBase) &&
43964426 Ops.Ty ->hasUnsignedIntegerRepresentation ();
0 commit comments