[OpenMP][OMPIRBuilder] Move SIMD alignment calculation to LLVM Frontend
authorDominik Adamski <dominik.adamski@amd.com>
Tue, 22 Nov 2022 10:55:39 +0000 (04:55 -0600)
committerDominik Adamski <dominik.adamski@amd.com>
Fri, 13 Jan 2023 20:07:29 +0000 (14:07 -0600)
Currently default simd alignment is specified by Clang specific TargetInfo
class. This class cannot be reused for LLVM Flang. If we move the default
alignment field into TargetMachine class then we can create TargetMachine
objects and query them to find SIMD alignment.

Scope of changes:
  1) Added information about maximal allowed SIMD alignment to TargetMachine
     classes.
  2) Removed getSimdDefaultAlign function from Clang TargetInfo class.
  3) Refactored createTargetMachine function.

Reviewed By: jsjodin

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

13 files changed:
clang/include/clang/Basic/TargetInfo.h
clang/lib/AST/ASTContext.cpp
clang/lib/Basic/TargetInfo.cpp
clang/lib/Basic/Targets/PPC.h
clang/lib/Basic/Targets/WebAssembly.h
clang/lib/Basic/Targets/X86.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
llvm/include/llvm/Target/TargetMachine.h
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
llvm/lib/Target/X86/X86TargetMachine.cpp

index a5aea33..def708d 100644 (file)
@@ -226,7 +226,6 @@ protected:
   bool HasStrictFP;
 
   unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
-  unsigned short SimdDefaultAlign;
   std::string DataLayoutString;
   const char *UserLabelPrefix;
   const char *MCountName;
@@ -795,10 +794,6 @@ public:
 
   /// Return the maximum vector alignment supported for the given target.
   unsigned getMaxVectorAlign() const { return MaxVectorAlign; }
-  /// Return default simd alignment for the given target. Generally, this
-  /// value is type-specific, but this alignment can be used for most of the
-  /// types for the given target.
-  unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; }
 
   unsigned getMaxOpenCLWorkGroupSize() const { return MaxOpenCLWorkGroupSize; }
 
index 15a4380..6b97407 100644 (file)
@@ -79,6 +79,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
 #include "llvm/Support/Capacity.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
@@ -93,6 +94,7 @@
 #include <cstdlib>
 #include <map>
 #include <memory>
+#include <numeric>
 #include <optional>
 #include <string>
 #include <tuple>
@@ -2463,7 +2465,16 @@ unsigned ASTContext::getTypeUnadjustedAlign(const Type *T) const {
 }
 
 unsigned ASTContext::getOpenMPDefaultSimdAlign(QualType T) const {
-  unsigned SimdAlign = getTargetInfo().getSimdDefaultAlign();
+  const std::vector<std::string> &TargetFeatures =
+      Target->getTargetOpts().Features;
+  std::string TargetFeaturesString = std::accumulate(
+      TargetFeatures.cbegin(), TargetFeatures.cend(), std::string(),
+      [](const std::string &s1, const std::string &s2) {
+        return s1.empty() ? s2 : s1 + "," + s2;
+      });
+  unsigned SimdAlign = llvm::OpenMPIRBuilder ::getSimdDefaultAlignment(
+      getTargetInfo().getTriple().str(), Target->getTargetOpts().CPU,
+      TargetFeaturesString);
   return SimdAlign;
 }
 
index 8ee4326..fa5e568 100644 (file)
@@ -119,7 +119,6 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
   MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
   MaxVectorAlign = 0;
   MaxTLSAlign = 0;
-  SimdDefaultAlign = 0;
   SizeType = UnsignedLong;
   PtrDiffType = SignedLong;
   IntMaxType = SignedLongLong;
index cc185fd..4c02183 100644 (file)
@@ -87,7 +87,6 @@ public:
   PPCTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
       : TargetInfo(Triple) {
     SuitableAlign = 128;
-    SimdDefaultAlign = 128;
     LongDoubleWidth = LongDoubleAlign = 128;
     LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble();
     HasStrictFP = true;
index 1e73450..1f0bb08 100644 (file)
@@ -49,7 +49,6 @@ public:
     SuitableAlign = 128;
     LargeArrayMinWidth = 128;
     LargeArrayAlign = 128;
-    SimdDefaultAlign = 128;
     SigAtomicType = SignedLong;
     LongDoubleWidth = LongDoubleAlign = 128;
     LongDoubleFormat = &llvm::APFloat::IEEEquad();
index a6eea30..d700fb9 100644 (file)
@@ -399,9 +399,6 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
     return false;
   }
 
-  SimdDefaultAlign =
-      hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
-
   // FIXME: We should allow long double type on 32-bits to match with GCC.
   // This requires backend to be able to lower f80 without x87 first.
   if (!HasX87 && LongDoubleFormat == &llvm::APFloat::x87DoubleExtended())
index 58e81fb..c22d582 100644 (file)
@@ -500,8 +500,6 @@ ClangExpressionParser::ClangExpressionParser(
   auto target_info = TargetInfo::CreateTargetInfo(
       m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts);
   if (log) {
-    LLDB_LOGF(log, "Using SIMD alignment: %d",
-              target_info->getSimdDefaultAlign());
     LLDB_LOGF(log, "Target datalayout string: '%s'",
               target_info->getDataLayoutString());
     LLDB_LOGF(log, "Target ABI: '%s'", target_info->getABI().str().c_str());
index 2c1abe9..ce4a4f2 100644 (file)
@@ -502,6 +502,14 @@ public:
                                    ArrayRef<CanonicalLoopInfo *> Loops,
                                    InsertPointTy ComputeIP);
 
+  /// Get the alignment value for given target
+  ///
+  /// \param Triple         String which describes target triple
+  /// \param CPU            String which describes target CPU
+  /// \param Features       String which describes extra CPU features
+  static unsigned getSimdDefaultAlignment(const std::string &Triple,
+                                          StringRef CPU, StringRef Features);
+
 private:
   /// Modifies the canonical loop to be a statically-scheduled workshare loop.
   ///
index 6361373..c088052 100644 (file)
@@ -108,6 +108,9 @@ protected: // Can only create subclasses.
   std::unique_ptr<const MCInstrInfo> MII;
   std::unique_ptr<const MCSubtargetInfo> STI;
 
+  /// Simd target specific information
+  unsigned SimdDefaultAlignment = 0;
+
   unsigned RequireStructuredCFG : 1;
   unsigned O0WantsFastISel : 1;
 
@@ -204,6 +207,9 @@ public:
     return DL.getPointerSize(DL.getAllocaAddrSpace());
   }
 
+  /// Return default SIMD alignment
+  unsigned getSimdDefaultAlignment() const { return SimdDefaultAlignment; }
+
   /// Reset the target options based on the function's attributes.
   // FIXME: Remove TargetOptions that affect per-function code generation
   // from TargetMachine.
index ddbcef1..05bea28 100644 (file)
@@ -255,6 +255,50 @@ static void redirectTo(BasicBlock *Source, BasicBlock *Target, DebugLoc DL) {
   NewBr->setDebugLoc(DL);
 }
 
+/// Create the TargetMachine object to query the backend for optimization
+/// preferences.
+///
+/// Ideally, this would be passed from the front-end to the OpenMPBuilder, but
+/// e.g. Clang does not pass it to its CodeGen layer and creates it only when
+/// needed for the LLVM pass pipline. We use some default options to avoid
+/// having to pass too many settings from the frontend that probably do not
+/// matter.
+///
+/// Currently, TargetMachine is only used sometimes by the unrollLoopPartial
+/// and getVectorTypeAlignment methods. If we are going to use TargetMachine
+/// for more purposes, especially those that are sensitive to TargetOptions,
+/// RelocModel and CodeModel, it might become be worth requiring front-ends to
+/// pass on their TargetMachine, or at least cache it between methods.
+/// Note that while fontends such as Clang have just a single main
+/// TargetMachine per translation unit, "target-cpu" and "target-features"
+/// that determine the TargetMachine are per-function and can be overrided
+/// using __attribute__((target("OPTIONS"))).
+static std::unique_ptr<TargetMachine>
+createTargetMachine(const std::string &Triple, StringRef CPU,
+                    StringRef Features, CodeGenOpt::Level OptLevel) {
+  std::string Error;
+  const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
+  if (!TheTarget)
+    return {};
+
+  llvm::TargetOptions Options;
+  return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
+      Triple, CPU, Features, Options, /*RelocModel=*/std::nullopt,
+      /*CodeModel=*/std::nullopt, OptLevel));
+}
+
+/// Create the TargetMachine object to query the backend for optimization
+/// preferences.
+static std::unique_ptr<TargetMachine>
+createTargetMachine(Function *F, CodeGenOpt::Level OptLevel) {
+  Module *M = F->getParent();
+
+  StringRef CPU = F->getFnAttribute("target-cpu").getValueAsString();
+  StringRef Features = F->getFnAttribute("target-features").getValueAsString();
+  const std::string &Triple = M->getTargetTriple();
+  return createTargetMachine(Triple, CPU, Features, OptLevel);
+}
+
 void llvm::spliceBB(IRBuilderBase::InsertPoint IP, BasicBlock *New,
                     bool CreateBranch) {
   assert(New->getFirstInsertionPt() == New->begin() &&
@@ -3039,6 +3083,18 @@ void OpenMPIRBuilder::createIfVersion(CanonicalLoopInfo *CanonicalLoop,
   Builder.CreateBr(NewBlocks.front());
 }
 
+unsigned OpenMPIRBuilder::getSimdDefaultAlignment(const std::string &Triple,
+                                                  StringRef CPU,
+                                                  StringRef Features) {
+  std::unique_ptr<TargetMachine> TgtInfo(
+      createTargetMachine(Triple, CPU, Features, CodeGenOpt::Default));
+  if (!TgtInfo) {
+    return 0;
+  }
+
+  return TgtInfo->getSimdDefaultAlignment();
+}
+
 void OpenMPIRBuilder::applySimd(CanonicalLoopInfo *CanonicalLoop,
                                 MapVector<Value *, Value *> AlignedVars,
                                 Value *IfCond, OrderKind Order,
@@ -3141,42 +3197,6 @@ void OpenMPIRBuilder::applySimd(CanonicalLoopInfo *CanonicalLoop,
   addLoopMetadata(CanonicalLoop, LoopMDList);
 }
 
-/// Create the TargetMachine object to query the backend for optimization
-/// preferences.
-///
-/// Ideally, this would be passed from the front-end to the OpenMPBuilder, but
-/// e.g. Clang does not pass it to its CodeGen layer and creates it only when
-/// needed for the LLVM pass pipline. We use some default options to avoid
-/// having to pass too many settings from the frontend that probably do not
-/// matter.
-///
-/// Currently, TargetMachine is only used sometimes by the unrollLoopPartial
-/// method. If we are going to use TargetMachine for more purposes, especially
-/// those that are sensitive to TargetOptions, RelocModel and CodeModel, it
-/// might become be worth requiring front-ends to pass on their TargetMachine,
-/// or at least cache it between methods. Note that while fontends such as Clang
-/// have just a single main TargetMachine per translation unit, "target-cpu" and
-/// "target-features" that determine the TargetMachine are per-function and can
-/// be overrided using __attribute__((target("OPTIONS"))).
-static std::unique_ptr<TargetMachine>
-createTargetMachine(Function *F, CodeGenOpt::Level OptLevel) {
-  Module *M = F->getParent();
-
-  StringRef CPU = F->getFnAttribute("target-cpu").getValueAsString();
-  StringRef Features = F->getFnAttribute("target-features").getValueAsString();
-  const std::string &Triple = M->getTargetTriple();
-
-  std::string Error;
-  const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
-  if (!TheTarget)
-    return {};
-
-  llvm::TargetOptions Options;
-  return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
-      Triple, CPU, Features, Options, /*RelocModel=*/std::nullopt,
-      /*CodeModel=*/std::nullopt, OptLevel));
-}
-
 /// Heuristically determine the best-performant unroll factor for \p CLI. This
 /// depends on the target processor. We are re-using the same heuristics as the
 /// LoopUnrollPass.
index 9aea5af..df5d120 100644 (file)
@@ -333,6 +333,7 @@ PPCTargetMachine::PPCTargetMachine(const Target &T, const Triple &TT,
       TLOF(createTLOF(getTargetTriple())),
       TargetABI(computeTargetABI(TT, Options)),
       Endianness(isLittleEndianTriple(TT) ? Endian::LITTLE : Endian::BIG) {
+  SimdDefaultAlignment = 128;
   initAsmInfo();
 }
 
index 630c786..a76647f 100644 (file)
@@ -139,6 +139,7 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine(
   this->Options.FunctionSections = true;
   this->Options.DataSections = true;
   this->Options.UniqueSectionNames = true;
+  SimdDefaultAlignment = 128;
 
   initAsmInfo();
 
index 3e8e8af..d53554a 100644 (file)
@@ -245,6 +245,13 @@ X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT,
   setSupportsDebugEntryValues(true);
 
   initAsmInfo();
+
+  if (FS.contains("+avx512f"))
+    SimdDefaultAlignment = 512;
+  else if (FS.contains("+avx"))
+    SimdDefaultAlignment = 256;
+  else
+    SimdDefaultAlignment = 128;
 }
 
 X86TargetMachine::~X86TargetMachine() = default;