Commit 6e7d6b25 authored by Michael Kruse's avatar Michael Kruse
Browse files

Merge branch 'pragma-clang-loop' into HEAD

parents 676d091c fe0d2e34
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -16,11 +16,12 @@
#include "clang/AST/ASTFwd.h"
#include "clang/AST/AttrIterator.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/AttributeCommonInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
+444 −0
Original line number Diff line number Diff line
@@ -552,6 +552,8 @@ class Attr {
  // attribute may be documented under multiple categories, more than one
  // Documentation entry may be listed.
  list<Documentation> Documentation;

  bit PrettyPrintSpelling = 1;
}

/// Used to define a set of mutually exclusive attributes.
@@ -3495,6 +3497,447 @@ def InitSeg : Attr {
  }];
}

def LoopId : Attr {
  // #pragma clang loop id(loopname)

  // This exists only to make ClangAttrEmitter emit a printPretty(OS, Policy) function which prints "#pragma" and then calls printPrettyPragma(OS, Policy)
  let Spellings = [Pragma<"", "id">];
  let PrettyPrintSpelling = 0;

  let Args = [StringArgument<"LoopName">];

  let AdditionalMembers = [{
    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
      OS << "clang loop id(" << getLoopName() << ")";
    }
  }];

  let Documentation = [Undocumented];
}

def LoopReversal : Attr {
  // #pragma clang loop           reverse [reversed_id(loopname)]
  // #pragma clang loop(loopname) reverse [reversed_id(loopname)]

  // This exists only to make ClangAttrEmitter emit a printPretty(OS, Policy) function which prints "#pragma" and then calls printPrettyPragma(OS, Policy)
  let Spellings = [Pragma<"", "reverse">];
  let PrettyPrintSpelling = 0;

  let Args = [StringArgument<"ApplyOn">, StringArgument<"ReversedId">];

  let AdditionalMembers = [{
    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
      OS << "clang loop";
      if (!getApplyOn().empty()) {
        OS << "(" << getApplyOn() << ")";
      }

      OS << " reverse";

      if (!getReversedId().empty())
        OS << " reversed_id(" << getReversedId() << ")";
    }
  }];

  let Documentation = [Undocumented];
}

def LoopTiling : Attr {
  // #pragma clang loop tile
  // #pragma clang loop(depth) tile
  // #pragma clang loop(loopname1, loopname2, ...) tile

  let Spellings = [Pragma<"", "tile">];
  let PrettyPrintSpelling = 0;

  let Args = [VariadicStringArgument<"ApplyOn">, ExprArgument<"ApplyOnDepth">, VariadicExprArgument<"TileSizes">, VariadicStringArgument<"FloorIds">, VariadicStringArgument<"TileIds">, StringArgument<"Peel">];

  let AdditionalMembers = [{
    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
      OS << "clang loop";
      if (applyOn_size()) {
        OS << "(";
        bool First = true;
        for (auto Piece : applyOn()) {
        if (!First) {
          OS << ", ";
            }
            OS << Piece;
            First = false;
          }
        OS << ")";
      } else if (getApplyOnDepth()) {
        OS << "(" ;
        getApplyOnDepth()->printPretty(OS, nullptr, Policy);
        OS << ")";
      }

      OS << " tile";

      if (tileSizes_size()) {
        OS << " sizes(";
        bool First = true;
        for (auto Size : tileSizes()) {
          if (!First) {
            OS << ", ";
          }
          Size->printPretty(OS, nullptr, Policy);
          First = false;
        }
        OS << ")";
      }

      if (floorIds_size()) {
        OS << " floor_ids(";
        bool First = true;
        for (auto Id : floorIds()) {
          if (!First) {
            OS << ", ";
          }
          OS<<Id;
          First = false;
        }
        OS << ")";
      }

      if (tileIds_size()) {
        OS << " tile_ids(";
        bool First = true;
        for (auto Id : tileIds()) {
          if (!First) {
            OS << ", ";
          }
          OS<<Id;
          First = false;
        }
        OS << ")";
      }

      if (getPeelLength()) {
        OS << " peel(" << getPeel() << ")";
      }
    }
  }];

  let Documentation = [Undocumented];
}

def LoopInterchange : Attr {
  // #pragma clang loop interchange
  // #pragma clang loop(loopname1, loopname2, ...) interchange
  // #pragma clang loop(depth) interchange

  let Spellings = [Pragma<"", "interchange">];
  let PrettyPrintSpelling = 0;

  let Args = [VariadicStringArgument<"ApplyOn">, ExprArgument<"ApplyOnDepth">, VariadicStringArgument<"Permutation">, VariadicStringArgument<"PermutedIds">];

  let AdditionalMembers = [{
    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
      OS << "clang loop";
      if (applyOn_size()) {
        OS << "(";
        bool First = true;
          for (auto Piece : applyOn()) {
            if (!First) {
              OS << ", ";
            }
            OS << Piece;
            First = false;
          }
        OS << ")";
      } else if (getApplyOnDepth() ) {
        OS << "(" ;
        getApplyOnDepth()->printPretty(OS, nullptr, Policy);
        OS << ")";
      }

      OS << " interchange";

      if (permutation_size()) {
        OS << " permutation(";
        bool First = true;
        for (auto PermId : permutation()) {
          if (!First) {
            OS << ", ";
          }
          OS << PermId;
          First = false;
        }
        OS << ")";
      }

      if (permutedIds_size()) {
        OS << " permuted_ids(";
        bool First = true;
        for (auto PermId : permutedIds()) {
          if (!First) {
            OS << ", ";
          }
          OS << PermId;
          First = false;
        }
        OS << ")";
      }
    }
  }];

  let Documentation = [Undocumented];
}


def LoopFission : Attr {
  // #pragma clang loop fission
  // #pragma clang loop(loopname) fission

  let Spellings = [Pragma<"", "fission">];
  let PrettyPrintSpelling = 0;

  let Args = [StringArgument<"ApplyOn">, VariadicExprArgument<"SplitAt">, BoolArgument<"AutoFission">,  VariadicStringArgument<"FissionedIds">];

  let AdditionalMembers = [{
    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
      OS << "clang loop";
      if (!getApplyOn().empty()) {
        OS << "(" << getApplyOn() << ")";
      }

      OS << " fission";

      if (splitAt_size()) {
        OS << " split_at(";
        bool First = true;
        for (auto SplitPos : splitAt()) {
          if (!First) {
            OS << ", ";
          }
          SplitPos->printPretty(OS, nullptr, Policy);
          First = false;
        }
        OS << ")";
      }

      if (getAutoFission()) {
        OS << " autofission";
      }

      if (fissionedIds_size()) {
        OS << " fissioned_ids(";
        bool First = true;
        for (auto FissionId : fissionedIds()) {
          if (!First) {
            OS << ", ";
          }
          OS << FissionId;
          First = false;
        }
        OS << ")";
      }
    }
  }];

  let Documentation = [Undocumented];
}


def LoopFusion : Attr {
  // #pragma clang loop fuse
  // #pragma clang loop(loopname,loopname,...) fuse

  let Spellings = [Pragma<"", "fuse">];
  let PrettyPrintSpelling = 0;

  let Args = [VariadicStringArgument<"ApplyOn">, StringArgument<"FusedId">];

  let AdditionalMembers = [{
    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
      OS << "clang loop";
      if (applyOn_size()) {
        OS << "(";
        bool First = true;
        for (auto On : applyOn()) {
          if (!First) {
            OS << ", ";
          }
          OS << On;
          First = false;
        }
        OS << ")";
      }

      OS << " fuse";

      if (!getFusedId().empty()) {
        OS << " fused_id(" << getFusedId() << ")";
      }
    }
  }];

  let Documentation = [Undocumented];
}


def Pack : Attr {
  // #pragma clang loop           pack array(arrayname) [allocate(malloc)] [isl_size("isl map")] [isl_redirect("isl map")]
  // #pragma clang loop(loopname) pack array(arrayname) [allocate(malloc)] [isl_size("isl map")] [isl_redirect("isl map")]

  let Spellings = [Pragma<"", "pack">];
  let PrettyPrintSpelling = 0;

  let Args = [StringArgument<"ApplyOn">, ExprArgument<"Array">, BoolArgument<"OnHeap">, StringArgument<"IslSize">, StringArgument<"IslRedirect">];

  let AdditionalMembers = [{
    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
      OS << "clang loop";

      if (!getApplyOn().empty()) {
        OS << "(" << getApplyOn() << ")";
      }

      OS << " pack";

      if (getArray()) {
          OS << " array(";
          getArray()->printPretty(OS, nullptr, Policy);
          OS << ")";
      }

      if (getOnHeap()) {
        OS << " allocate(malloc)";
      }

      if (!getIslSize().empty()) {
        OS << " isl_size(\"" << getIslSize() << "\")";
      }

      if (!getIslRedirect().empty()) {
        OS << " isl_redirect(\"" << getIslRedirect() << "\")";
      }
    }
  }];

  let Documentation = [Undocumented];
}


def LoopUnrolling : Attr {
  // FIXME: Replace by #pragma clang loop unroll, which current emits different metadata
  // #pragma clang loop unrolling [factor(n)] [full]
  // #pragma clang loop(loopname) unrolling [factor(n)] [full]

  // This exists only to make ClangAttrEmitter emit a printPretty(OS, Policy) function which prints "#pragma" and then calls printPrettyPragma(OS, Policy)
  let Spellings = [Pragma<"", "unrolling">];
  let PrettyPrintSpelling = 0;

  let Args = [StringArgument<"ApplyOn">, ExprArgument<"Factor">, BoolArgument<"Full">];

  let AdditionalMembers = [{
    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
      OS << "clang loop";
      if (!getApplyOn().empty()) {
        OS << "(" << getApplyOn() << ")";
      }

      OS << " unrolling";

      if (getFactor()) {
        OS << " factor(";
        getFactor()->printPretty(OS, nullptr, Policy);
        OS << ")";
      }

      if (getFull()) {
        OS << " full";
      }
    }
  }];

  let Documentation = [Undocumented];
}


// TODO: 'interleave' would also be defined with arbitrary loop nests.
def LoopUnrollingAndJam : Attr {
  // #pragma clang loop unrollingandjam [factor(n)] [full]
  // #pragma clang loop(loopname,loopname) unrollingandjam [factor(n)] [full]

  // This exists only to make ClangAttrEmitter emit a printPretty(OS, Policy) function which prints "#pragma" and then calls printPrettyPragma(OS, Policy)
  let Spellings = [Pragma<"", "unrollingandjam">];
  let PrettyPrintSpelling = 0;

  let Args = [VariadicStringArgument<"ApplyOn">, ExprArgument<"Factor">, BoolArgument<"Full">, VariadicStringArgument<"UnrolledIds">, ];

  let AdditionalMembers = [{
    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
      OS << "clang loop";
      if (applyOn_size()) {
        OS << "(";
        bool First = true;
          for (auto Piece : applyOn()) {
            if (!First) {
              OS << ", ";
            }
            OS << Piece;
            First = false;
          }
        OS << ")";
      }

      OS << " unrollingandjam";

      if (getFactor()) {
        OS << " factor(";
        getFactor()->printPretty(OS, nullptr, Policy);
        OS << ")";
      }

      if (getFull()) {
        OS << " full";
      }

      if (unrolledIds_size()) {
        OS << " unrolled_ids(";
        bool First = true;
        for (auto Piece : unrolledIds()) {
            if (!First) {
              OS << ", ";
            }
            OS << Piece;
            First = false;
          }
        OS << ")";
      }
    }
  }];

  let Documentation = [Undocumented];
}


def LoopParallelizeThread : Attr {
  // #pragma clang loop thread_parallel
  // #pragma clang loop(loopname) thread_parallel

  // This exists only to make ClangAttrEmitter emit a printPretty(OS, Policy) function which prints "#pragma" and then calls printPrettyPragma(OS, Policy)
  let Spellings = [Pragma<"", "parallelize_thread">];
  let PrettyPrintSpelling = 0;

  let Args = [StringArgument<"ApplyOn">];

  let AdditionalMembers = [{
    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
      OS << "clang loop";
      if (!getApplyOn().empty()) {
        OS << "(" << getApplyOn() << ")";
      }
      OS << " parallelize_thread";
    }
  }];

  let Documentation = [Undocumented];
}


def LoopHint : Attr {
  /// #pragma clang loop <option> directive
  /// vectorize: vectorizes loop operations if State == Enable.
@@ -3517,6 +3960,7 @@ def LoopHint : Attr {
  let Spellings = [Pragma<"clang", "loop">, Pragma<"", "unroll">,
                   Pragma<"", "nounroll">, Pragma<"", "unroll_and_jam">,
                   Pragma<"", "nounroll_and_jam">];
  let PrettyPrintSpelling = 0;

  /// State of the loop optimization specified by the spelling.
  let Args = [EnumArgument<"Option", "OptionType",
+7 −0
Original line number Diff line number Diff line
@@ -447,6 +447,13 @@ CODEGENOPT(AAPCSBitfieldWidth, 1, 1)
/// propagate signaling NaN inputs per IEEE 754-2008 (AMDGPU Only)
CODEGENOPT(EmitIEEENaNCompliantInsts, 1, 1)

/// Disable the LLVM passes:
/// - LoopUnroll
///
/// Legacy pass manager only
/// See NoLegacyLoopTransformsPassGate in BackendUtil.cpp
CODEGENOPT(DisableLegacyLoopTransformation, 1, 0)

// Whether to emit Swift Async function extended frame information: auto,
// never, always.
ENUM_CODEGENOPT(SwiftAsyncFramePointer, SwiftAsyncFramePointerKind, 2,
+10 −0
Original line number Diff line number Diff line
@@ -1473,6 +1473,16 @@ def note_pragma_loop_invalid_vectorize_option : Note<
  "vectorize_width loop hint malformed; use vectorize_width(X, fixed) or "
  "vectorize_width(X, scalable) where X is an integer, or vectorize_width('fixed' or 'scalable')">;

// Pragma transform support.
def err_pragma_transform : Error<
  "transform directive parse error">;
def warn_pragma_transform : Warning<
  "transform directive parse warning">;
def err_pragma_transform_unknown_directive : Error<
  "expected a transformation">;
def err_pragma_transform_unexpected_directive : Error<
  "unexpected transform directive %select{|'#pragma clang transform %1'}0">;

def err_pragma_fp_invalid_option : Error<
  "%select{invalid|missing}0 option%select{ %1|}0; expected 'contract', 'reassociate' or 'exceptions'">;
def err_pragma_fp_invalid_argument : Error<
+1 −0
Original line number Diff line number Diff line
@@ -881,6 +881,7 @@ PRAGMA_ANNOTATION(pragma_openmp_end)
// The lexer produces these so that they only take effect when the parser
// handles #pragma loop ... directives.
PRAGMA_ANNOTATION(pragma_loop_hint)
ANNOTATION(pragma_loop_transform)

PRAGMA_ANNOTATION(pragma_fp)

Loading