[OpenCL][AMDGPU] Add support for -cl-denorms-are-zero

Adjust target features for amdgcn target when -cl-denorms-are-zero is set.

Denormal support is controlled by feature strings fp32-denormals fp64-denormals in amdgcn target. If -cl-denorms-are-zero is not set and the command line does not set fp32/64-denormals feature string, +fp32-denormals +fp64-denormals will be on for GPU's supporting them.

A new virtual function virtual void TargetInfo::adjustTargetOptions(const CodeGenOptions &CGOpts, TargetOptions &TargetOpts) const is introduced to allow adjusting target option by codegen option.

Differential Revision: https://reviews.llvm.org/D22815

llvm-svn: 278151
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index a5e1d6f..b280b1a 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -21,6 +21,7 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Basic/Version.h"
+#include "clang/Frontend/CodeGenOptions.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
@@ -1960,23 +1961,27 @@
   bool hasFP64:1;
   bool hasFMAF:1;
   bool hasLDEXPF:1;
+  bool hasDenormSupport:1;
 
   static bool isAMDGCN(const llvm::Triple &TT) {
     return TT.getArch() == llvm::Triple::amdgcn;
   }
 
 public:
-  AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+  AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
     : TargetInfo(Triple) ,
       GPU(isAMDGCN(Triple) ? GK_SOUTHERN_ISLANDS : GK_R600),
       hasFP64(false),
       hasFMAF(false),
-      hasLDEXPF(false) {
+      hasLDEXPF(false),
+      hasDenormSupport(false){
     if (getTriple().getArch() == llvm::Triple::amdgcn) {
       hasFP64 = true;
       hasFMAF = true;
       hasLDEXPF = true;
     }
+    if (Opts.CPU == "fiji")
+      hasDenormSupport = true;
 
     resetDataLayout(getTriple().getArch() == llvm::Triple::amdgcn ?
                     DataLayoutStringSI : DataLayoutStringR600);
@@ -2025,6 +2030,26 @@
                       DiagnosticsEngine &Diags, StringRef CPU,
                       const std::vector<std::string> &FeatureVec) const override;
 
+  void adjustTargetOptions(const CodeGenOptions &CGOpts,
+                           TargetOptions &TargetOpts) const override {
+    if (!hasDenormSupport)
+      return;
+    bool hasFP32Denormals = false;
+    bool hasFP64Denormals = false;
+    for (auto &I : TargetOpts.FeaturesAsWritten) {
+      if (I == "+fp32-denormals" || I == "-fp32-denormals")
+        hasFP32Denormals = true;
+      if (I == "+fp64-denormals" || I == "-fp64-denormals")
+        hasFP64Denormals = true;
+    }
+    if (!hasFP32Denormals)
+      TargetOpts.Features.push_back((Twine(CGOpts.FlushDenorm ? '-' : '+') +
+                                     Twine("fp32-denormals")).str());
+    if (!hasFP64Denormals && hasFP64)
+      TargetOpts.Features.push_back((Twine(CGOpts.FlushDenorm ? '-' : '+') +
+                                     Twine("fp64-denormals")).str());
+  }
+
   ArrayRef<Builtin::Info> getTargetBuiltins() const override {
     return llvm::makeArrayRef(BuiltinInfo,
                         clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin);