diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-03 20:26:23 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-03 20:26:23 +0000 |
commit | f0c0337bbfb63d1f9edf145aab535bdf82c20454 (patch) | |
tree | de30bd60d1dbee4bf7ef487139b3ceb8781c82db /lib/CodeGen | |
parent | 570918821a8492048e6ab54955c9864bd6c3e952 (diff) |
Notes
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 86 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCGNU.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 13 | ||||
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 10 |
5 files changed, 85 insertions, 30 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index a5c43fba6d051..c677d9887accc 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -1756,9 +1756,7 @@ void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) { ConstructDefaultFnAttrList(F.getName(), F.hasFnAttribute(llvm::Attribute::OptimizeNone), /* AttrOnCallsite = */ false, FuncAttrs); - llvm::AttributeList AS = llvm::AttributeList::get( - getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs); - F.addAttributes(llvm::AttributeList::FunctionIndex, AS); + F.addAttributes(llvm::AttributeList::FunctionIndex, FuncAttrs); } void CodeGenModule::ConstructAttributeList( diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index a64303831171d..70b741651fd11 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -51,6 +51,64 @@ struct BinOpInfo { BinaryOperator::Opcode Opcode; // Opcode of BinOp to perform FPOptions FPFeatures; const Expr *E; // Entire expr, for error unsupported. May not be binop. + + /// Check if the binop can result in integer overflow. + bool mayHaveIntegerOverflow() const { + // Without constant input, we can't rule out overflow. + const auto *LHSCI = dyn_cast<llvm::ConstantInt>(LHS); + const auto *RHSCI = dyn_cast<llvm::ConstantInt>(RHS); + if (!LHSCI || !RHSCI) + return true; + + // Assume overflow is possible, unless we can prove otherwise. + bool Overflow = true; + const auto &LHSAP = LHSCI->getValue(); + const auto &RHSAP = RHSCI->getValue(); + if (Opcode == BO_Add) { + if (Ty->hasSignedIntegerRepresentation()) + (void)LHSAP.sadd_ov(RHSAP, Overflow); + else + (void)LHSAP.uadd_ov(RHSAP, Overflow); + } else if (Opcode == BO_Sub) { + if (Ty->hasSignedIntegerRepresentation()) + (void)LHSAP.ssub_ov(RHSAP, Overflow); + else + (void)LHSAP.usub_ov(RHSAP, Overflow); + } else if (Opcode == BO_Mul) { + if (Ty->hasSignedIntegerRepresentation()) + (void)LHSAP.smul_ov(RHSAP, Overflow); + else + (void)LHSAP.umul_ov(RHSAP, Overflow); + } else if (Opcode == BO_Div || Opcode == BO_Rem) { + if (Ty->hasSignedIntegerRepresentation() && !RHSCI->isZero()) + (void)LHSAP.sdiv_ov(RHSAP, Overflow); + else + return false; + } + return Overflow; + } + + /// Check if the binop computes a division or a remainder. + bool isDivisionLikeOperation() const { + return Opcode == BO_Div || Opcode == BO_Rem || Opcode == BO_DivAssign || + Opcode == BO_RemAssign; + } + + /// Check if the binop can result in an integer division by zero. + bool mayHaveIntegerDivisionByZero() const { + if (isDivisionLikeOperation()) + if (auto *CI = dyn_cast<llvm::ConstantInt>(RHS)) + return CI->isZero(); + return true; + } + + /// Check if the binop can result in a float division by zero. + bool mayHaveFloatDivisionByZero() const { + if (isDivisionLikeOperation()) + if (auto *CFP = dyn_cast<llvm::ConstantFP>(RHS)) + return CFP->isZero(); + return true; + } }; static bool MustVisitNullValue(const Expr *E) { @@ -85,9 +143,17 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) { assert((isa<UnaryOperator>(Op.E) || isa<BinaryOperator>(Op.E)) && "Expected a unary or binary operator"); + // If the binop has constant inputs and we can prove there is no overflow, + // we can elide the overflow check. + if (!Op.mayHaveIntegerOverflow()) + return true; + + // If a unary op has a widened operand, the op cannot overflow. if (const auto *UO = dyn_cast<UnaryOperator>(Op.E)) return IsWidenedIntegerOp(Ctx, UO->getSubExpr()); + // We usually don't need overflow checks for binops with widened operands. + // Multiplication with promoted unsigned operands is a special case. const auto *BO = cast<BinaryOperator>(Op.E); auto OptionalLHSTy = getUnwidenedIntegerType(Ctx, BO->getLHS()); if (!OptionalLHSTy) @@ -100,14 +166,14 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) { QualType LHSTy = *OptionalLHSTy; QualType RHSTy = *OptionalRHSTy; - // We usually don't need overflow checks for binary operations with widened - // operands. Multiplication with promoted unsigned operands is a special case. + // This is the simple case: binops without unsigned multiplication, and with + // widened operands. No overflow check is needed here. if ((Op.Opcode != BO_Mul && Op.Opcode != BO_MulAssign) || !LHSTy->isUnsignedIntegerType() || !RHSTy->isUnsignedIntegerType()) return true; - // The overflow check can be skipped if either one of the unpromoted types - // are less than half the size of the promoted type. + // For unsigned multiplication the overflow check can be elided if either one + // of the unpromoted types are less than half the size of the promoted type. unsigned PromotedSize = Ctx.getTypeSize(Op.E->getType()); return (2 * Ctx.getTypeSize(LHSTy)) < PromotedSize || (2 * Ctx.getTypeSize(RHSTy)) < PromotedSize; @@ -2377,7 +2443,8 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( const auto *BO = cast<BinaryOperator>(Ops.E); if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) && Ops.Ty->hasSignedIntegerRepresentation() && - !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS())) { + !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) && + Ops.mayHaveIntegerOverflow()) { llvm::IntegerType *Ty = cast<llvm::IntegerType>(Zero->getType()); llvm::Value *IntMin = @@ -2400,11 +2467,13 @@ Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { CodeGenFunction::SanitizerScope SanScope(&CGF); if ((CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero) || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) && - Ops.Ty->isIntegerType()) { + Ops.Ty->isIntegerType() && + (Ops.mayHaveIntegerDivisionByZero() || Ops.mayHaveIntegerOverflow())) { llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true); } else if (CGF.SanOpts.has(SanitizerKind::FloatDivideByZero) && - Ops.Ty->isRealFloatingType()) { + Ops.Ty->isRealFloatingType() && + Ops.mayHaveFloatDivisionByZero()) { llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); llvm::Value *NonZero = Builder.CreateFCmpUNE(Ops.RHS, Zero); EmitBinOpCheck(std::make_pair(NonZero, SanitizerKind::FloatDivideByZero), @@ -2439,7 +2508,8 @@ Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) { // Rem in C can't be a floating point type: C99 6.5.5p2. if ((CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero) || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) && - Ops.Ty->isIntegerType()) { + Ops.Ty->isIntegerType() && + (Ops.mayHaveIntegerDivisionByZero() || Ops.mayHaveIntegerOverflow())) { CodeGenFunction::SanitizerScope SanScope(&CGF); llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, false); diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 9f6ccb4b5d266..821629c50d4a1 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -663,7 +663,7 @@ class CGObjCGNUstep : public CGObjCGNU { } // The lookup function is guaranteed not to capture the receiver pointer. - LookupFn->setDoesNotCapture(1); + LookupFn->addParamAttr(0, llvm::Attribute::NoCapture); llvm::Value *args[] = { EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 10f1673214546..ff26d80fe2b68 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -892,10 +892,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) B.addAttribute(llvm::Attribute::NoInline); - F->addAttributes( - llvm::AttributeList::FunctionIndex, - llvm::AttributeList::get(F->getContext(), - llvm::AttributeList::FunctionIndex, B)); + F->addAttributes(llvm::AttributeList::FunctionIndex, B); return; } @@ -961,9 +958,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, B.addAttribute(llvm::Attribute::MinSize); } - F->addAttributes(llvm::AttributeList::FunctionIndex, - llvm::AttributeList::get( - F->getContext(), llvm::AttributeList::FunctionIndex, B)); + F->addAttributes(llvm::AttributeList::FunctionIndex, B); unsigned alignment = D->getMaxAlignment() / Context.getCharWidth(); if (alignment) @@ -2029,9 +2024,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk); if (ExtraAttrs.hasAttributes(llvm::AttributeList::FunctionIndex)) { llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeList::FunctionIndex); - F->addAttributes(llvm::AttributeList::FunctionIndex, - llvm::AttributeList::get( - VMContext, llvm::AttributeList::FunctionIndex, B)); + F->addAttributes(llvm::AttributeList::FunctionIndex, B); } if (!DontDefer) { diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 94c3880ea26ec..ecd81d84b1fa2 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -1901,10 +1901,7 @@ void X86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D, // Now add the 'alignstack' attribute with a value of 16. llvm::AttrBuilder B; B.addStackAlignmentAttr(16); - Fn->addAttributes( - llvm::AttributeList::FunctionIndex, - llvm::AttributeList::get(CGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, B)); + Fn->addAttributes(llvm::AttributeList::FunctionIndex, B); } if (FD->hasAttr<AnyX86InterruptAttr>()) { llvm::Function *Fn = cast<llvm::Function>(GV); @@ -5449,10 +5446,7 @@ public: // the backend to perform a realignment as part of the function prologue. llvm::AttrBuilder B; B.addStackAlignmentAttr(8); - Fn->addAttributes( - llvm::AttributeList::FunctionIndex, - llvm::AttributeList::get(CGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, B)); + Fn->addAttributes(llvm::AttributeList::FunctionIndex, B); } }; |