summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2011-10-27 19:19:51 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2011-10-27 19:19:51 +0000
commit95fd2ca69f21f715d846d45178b1e57a76ee76ec (patch)
treeab7a79322e9947d7cfc773f730c155132a48ffb2 /clang/lib/CodeGen
parentf7d1e7be554530b28921a142ab83f97b4d80c4c9 (diff)
downloadbcm5719-llvm-95fd2ca69f21f715d846d45178b1e57a76ee76ec.tar.gz
bcm5719-llvm-95fd2ca69f21f715d846d45178b1e57a76ee76ec.zip
Annotate imprecise FP division with fpaccuracy metadata
The OpenCL single precision division operation is only required to be accurate to 2.5ulp. Annotate the fdiv instruction with metadata which signals to the backend that an imprecise divide instruction may be used. llvm-svn: 143136
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp16
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp14
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h5
3 files changed, 33 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index bd4e553991b..9ad3ae8352e 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -23,6 +23,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/Intrinsics.h"
+#include "llvm/LLVMContext.h"
#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
@@ -2752,3 +2753,18 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
return RValue::get(0);
return ConvertTempToRValue(*this, E->getType(), OrigDest);
}
+
+void CodeGenFunction::SetFPAccuracy(llvm::Value *Val, unsigned AccuracyN,
+ unsigned AccuracyD) {
+ assert(Val->getType()->isFPOrFPVectorTy());
+ if (!AccuracyN || !isa<llvm::Instruction>(Val))
+ return;
+
+ llvm::Value *Vals[2];
+ Vals[0] = llvm::ConstantInt::get(Int32Ty, AccuracyN);
+ Vals[1] = llvm::ConstantInt::get(Int32Ty, AccuracyD);
+ llvm::MDNode *Node = llvm::MDNode::get(getLLVMContext(), Vals);
+
+ cast<llvm::Instruction>(Val)->setMetadata(llvm::LLVMContext::MD_fpaccuracy,
+ Node);
+}
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 582d1c45722..25b4a0a0e77 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1772,8 +1772,18 @@ Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
Builder.SetInsertPoint(DivCont);
}
}
- if (Ops.LHS->getType()->isFPOrFPVectorTy())
- return Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div");
+ if (Ops.LHS->getType()->isFPOrFPVectorTy()) {
+ llvm::Value *Val = Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div");
+ if (CGF.getContext().getLangOptions().OpenCL) {
+ // OpenCL 1.1 7.4: minimum accuracy of single precision / is 2.5ulp
+ llvm::Type *ValTy = Val->getType();
+ if (ValTy->isFloatTy() ||
+ (isa<llvm::VectorType>(ValTy) &&
+ cast<llvm::VectorType>(ValTy)->getElementType()->isFloatTy()))
+ CGF.SetFPAccuracy(Val, 5, 2);
+ }
+ return Val;
+ }
else if (Ops.Ty->hasUnsignedIntegerRepresentation())
return Builder.CreateUDiv(Ops.LHS, Ops.RHS, "div");
else
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 858962d337b..4940e21c8be 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2382,6 +2382,11 @@ public:
/// a r-value suitable for passing the given parameter.
void EmitDelegateCallArg(CallArgList &args, const VarDecl *param);
+ /// SetFPAccuracy - Set the minimum required accuracy of the given floating
+ /// point operation, expressed as the maximum relative error in ulp.
+ void SetFPAccuracy(llvm::Value *Val, unsigned AccuracyN,
+ unsigned AccuracyD = 1);
+
private:
void EmitReturnOfRValue(RValue RV, QualType Ty);
OpenPOWER on IntegriCloud