Commit e1578fd2 authored by Craig Topper's avatar Craig Topper
Browse files

[Sema][X86] Consider target attribute into the checks in validateOutputSize and validateInputSize.

The validateOutputSize and validateInputSize need to check whether
AVX or AVX512 are enabled. But this can be affected by the
target attribute so we need to factor that in.

This patch copies some of the code from CodeGen to create an
appropriate feature map that we can pass to the function. Probably
need some refactoring here to share more code with Codegen. Is
there a good place to do that? Also need to support the cpu_specific
attribute as well.

Differential Revision: https://reviews.llvm.org/D68627
parent 60573ae6
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ class CXXRecordDecl;
class DiagnosticsEngine;
class Expr;
class FixedPointSemantics;
class GlobalDecl;
class MangleContext;
class MangleNumberingContext;
class MaterializeTemporaryExpr;
@@ -2820,6 +2821,16 @@ public:
  /// PredefinedExpr to cache evaluated results.
  StringLiteral *getPredefinedStringLiteralFromCache(StringRef Key) const;

  /// Parses the target attributes passed in, and returns only the ones that are
  /// valid feature names.
  TargetAttr::ParsedTargetAttr
  filterFunctionTargetAttrs(const TargetAttr *TD) const;

  void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
                             const FunctionDecl *) const;
  void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
                             GlobalDecl GD) const;

  //===--------------------------------------------------------------------===//
  //                    Statistics
  //===--------------------------------------------------------------------===//
+4 −2
Original line number Diff line number Diff line
@@ -945,12 +945,14 @@ public:
  bool validateInputConstraint(MutableArrayRef<ConstraintInfo> OutputConstraints,
                               ConstraintInfo &info) const;

  virtual bool validateOutputSize(StringRef /*Constraint*/,
  virtual bool validateOutputSize(const llvm::StringMap<bool> &FeatureMap,
                                  StringRef /*Constraint*/,
                                  unsigned /*Size*/) const {
    return true;
  }

  virtual bool validateInputSize(StringRef /*Constraint*/,
  virtual bool validateInputSize(const llvm::StringMap<bool> &FeatureMap,
                                 StringRef /*Constraint*/,
                                 unsigned /*Size*/) const {
    return true;
  }
+63 −0
Original line number Diff line number Diff line
@@ -10779,3 +10779,66 @@ QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const {
    llvm_unreachable("Unexpected unsigned fixed point type");
  }
}

TargetAttr::ParsedTargetAttr
ASTContext::filterFunctionTargetAttrs(const TargetAttr *TD) const {
  assert(TD != nullptr);
  TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse();

  ParsedAttr.Features.erase(
      llvm::remove_if(ParsedAttr.Features,
                      [&](const std::string &Feat) {
                        return !Target->isValidFeatureName(
                            StringRef{Feat}.substr(1));
                      }),
      ParsedAttr.Features.end());
  return ParsedAttr;
}

void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
                                       const FunctionDecl *FD) const {
  if (FD)
    getFunctionFeatureMap(FeatureMap, GlobalDecl().getWithDecl(FD));
  else
    Target->initFeatureMap(FeatureMap, getDiagnostics(),
                           Target->getTargetOpts().CPU,
                           Target->getTargetOpts().Features);
}

// Fills in the supplied string map with the set of target features for the
// passed in function.
void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
                                       GlobalDecl GD) const {
  StringRef TargetCPU = Target->getTargetOpts().CPU;
  const FunctionDecl *FD = GD.getDecl()->getAsFunction();
  if (const auto *TD = FD->getAttr<TargetAttr>()) {
    TargetAttr::ParsedTargetAttr ParsedAttr = filterFunctionTargetAttrs(TD);

    // Make a copy of the features as passed on the command line into the
    // beginning of the additional features from the function to override.
    ParsedAttr.Features.insert(
        ParsedAttr.Features.begin(),
        Target->getTargetOpts().FeaturesAsWritten.begin(),
        Target->getTargetOpts().FeaturesAsWritten.end());

    if (ParsedAttr.Architecture != "" &&
        Target->isValidCPUName(ParsedAttr.Architecture))
      TargetCPU = ParsedAttr.Architecture;

    // Now populate the feature map, first with the TargetCPU which is either
    // the default or a new one from the target attribute string. Then we'll use
    // the passed in features (FeaturesAsWritten) along with the new ones from
    // the attribute.
    Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU,
                           ParsedAttr.Features);
  } else if (const auto *SD = FD->getAttr<CPUSpecificAttr>()) {
    llvm::SmallVector<StringRef, 32> FeaturesTmp;
    Target->getCPUSpecificCPUDispatchFeatures(
        SD->getCPUName(GD.getMultiVersionIndex())->getName(), FeaturesTmp);
    std::vector<std::string> Features(FeaturesTmp.begin(), FeaturesTmp.end());
    Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
  } else {
    Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU,
                           Target->getTargetOpts().Features);
  }
}
+11 −8
Original line number Diff line number Diff line
@@ -1731,21 +1731,24 @@ bool X86TargetInfo::validateAsmConstraint(
  }
}

bool X86TargetInfo::validateOutputSize(StringRef Constraint,
bool X86TargetInfo::validateOutputSize(const llvm::StringMap<bool> &FeatureMap,
                                       StringRef Constraint,
                                       unsigned Size) const {
  // Strip off constraint modifiers.
  while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
    Constraint = Constraint.substr(1);

  return validateOperandSize(Constraint, Size);
  return validateOperandSize(FeatureMap, Constraint, Size);
}

bool X86TargetInfo::validateInputSize(StringRef Constraint,
bool X86TargetInfo::validateInputSize(const llvm::StringMap<bool> &FeatureMap,
                                      StringRef Constraint,
                                      unsigned Size) const {
  return validateOperandSize(Constraint, Size);
  return validateOperandSize(FeatureMap, Constraint, Size);
}

bool X86TargetInfo::validateOperandSize(StringRef Constraint,
bool X86TargetInfo::validateOperandSize(const llvm::StringMap<bool> &FeatureMap,
                                        StringRef Constraint,
                                        unsigned Size) const {
  switch (Constraint[0]) {
  default:
@@ -1770,7 +1773,7 @@ bool X86TargetInfo::validateOperandSize(StringRef Constraint,
    case 'z':
    case '0':
      // XMM0
      if (SSELevel >= SSE1)
      if (FeatureMap.lookup("sse"))
        return Size <= 128U;
      return false;
    case 'i':
@@ -1784,10 +1787,10 @@ bool X86TargetInfo::validateOperandSize(StringRef Constraint,
    LLVM_FALLTHROUGH;
  case 'v':
  case 'x':
    if (SSELevel >= AVX512F)
    if (FeatureMap.lookup("avx512f"))
      // 512-bit zmm registers can be used if target supports AVX512F.
      return Size <= 512U;
    else if (SSELevel >= AVX)
    else if (FeatureMap.lookup("avx"))
      // 256-bit ymm registers can be used if target supports AVX.
      return Size <= 256U;
    return Size <= 128U;
+9 −6
Original line number Diff line number Diff line
@@ -177,9 +177,11 @@ public:
    return false;
  }

  bool validateOutputSize(StringRef Constraint, unsigned Size) const override;
  bool validateOutputSize(const llvm::StringMap<bool> &FeatureMap,
                          StringRef Constraint, unsigned Size) const override;

  bool validateInputSize(StringRef Constraint, unsigned Size) const override;
  bool validateInputSize(const llvm::StringMap<bool> &FeatureMap,
                         StringRef Constraint, unsigned Size) const override;

  virtual bool
  checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override {
@@ -191,8 +193,8 @@ public:
    return true;
  };


  virtual bool validateOperandSize(StringRef Constraint, unsigned Size) const;
  virtual bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap,
                                   StringRef Constraint, unsigned Size) const;

  std::string convertConstraint(const char *&Constraint) const override;
  const char *getClobbers() const override {
@@ -368,7 +370,8 @@ public:
    return -1;
  }

  bool validateOperandSize(StringRef Constraint, unsigned Size) const override {
  bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap,
                           StringRef Constraint, unsigned Size) const override {
    switch (Constraint[0]) {
    default:
      break;
@@ -386,7 +389,7 @@ public:
      return Size <= 64;
    }

    return X86TargetInfo::validateOperandSize(Constraint, Size);
    return X86TargetInfo::validateOperandSize(FeatureMap, Constraint, Size);
  }

  void setMaxAtomicWidth() override {
Loading