r239579 - Add support for the the target attribute.

Eric Christopher echristo at gmail.com
Thu Jun 11 18:35:53 PDT 2015


Author: echristo
Date: Thu Jun 11 20:35:52 2015
New Revision: 239579

URL: http://llvm.org/viewvc/llvm-project?rev=239579&view=rev
Log:
Add support for the the target attribute.

Modeled after the gcc attribute of the same name, this feature
allows source level annotations to correspond to backend code
generation. In llvm particular parlance, this allows the adding
of subtarget features and changing the cpu for a particular function
based on source level hints.

This has been added into the existing support for function level
attributes without particular verification for any target outside
of whether or not the backend will support the features/cpu given
(similar to section, etc).

Added:
    cfe/trunk/test/CodeGen/attr-target.c
    cfe/trunk/test/Sema/attr-target.c
Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=239579&r1=239578&r2=239579&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Thu Jun 11 20:35:52 2015
@@ -1250,6 +1250,14 @@ def Pascal : InheritableAttr {
   let Documentation = [Undocumented];
 }
 
+def Target : InheritableAttr {
+  let Spellings = [GCC<"target">];
+  let Args = [StringArgument<"features">];
+  let Subjects =
+      SubjectList<[Function], ErrorDiag, "ExpectedFunctionMethodOrClass">;
+  let Documentation = [Undocumented];
+}
+
 def TransparentUnion : InheritableAttr {
   let Spellings = [GCC<"transparent_union">];
 //  let Subjects = SubjectList<[Record, TypedefName]>;

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=239579&r1=239578&r2=239579&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu Jun 11 20:35:52 2015
@@ -1483,24 +1483,52 @@ void CodeGenModule::ConstructAttributeLi
     if (!CodeGenOpts.StackRealignment)
       FuncAttrs.addAttribute("no-realign-stack");
 
-    // Add target-cpu and target-features work if they differ from the defaults.
-    std::string &CPU = getTarget().getTargetOpts().CPU;
-    if (CPU != "")
-      FuncAttrs.addAttribute("target-cpu", CPU);
+    // Add target-cpu and target-features attributes to functions. If
+    // we have a decl for the function and it has a target attribute then
+    // parse that and add it to the feature set.
+    StringRef TargetCPU = getTarget().getTargetOpts().CPU;
 
     // TODO: Features gets us the features on the command line including
     // feature dependencies. For canonicalization purposes we might want to
-    // avoid putting features in the target-features set if we know it'll be one
-    // of the default features in the backend, e.g. corei7-avx and +avx or figure
-    // out non-explicit dependencies.
-    std::vector<std::string> &Features = getTarget().getTargetOpts().Features;
+    // avoid putting features in the target-features set if we know it'll be
+    // one of the default features in the backend, e.g. corei7-avx and +avx or
+    // figure out non-explicit dependencies.
+    std::vector<std::string> Features(getTarget().getTargetOpts().Features);
+
+    // TODO: The target attribute complicates this further by allowing multiple
+    // additional features to be tacked on to the feature string for a
+    // particular function. For now we simply append to the set of features and
+    // let backend resolution fix them up.
+    const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl);
+    if (FD) {
+      if (const TargetAttr *TD = FD->getAttr<TargetAttr>()) {
+        StringRef FeaturesStr = TD->getFeatures();
+        SmallVector<StringRef, 1> AttrFeatures;
+        FeaturesStr.split(AttrFeatures, ",");
+
+        // Grab the various features and prepend a "+" to turn on the feature to
+        // the backend and add them to our existing set of Features.
+        for (auto &Feature : AttrFeatures) {
+          // While we're here iterating check for a different target cpu.
+          if (Feature.startswith("arch="))
+            TargetCPU = Feature.split("=").second;
+	  else
+	    Features.push_back("+" + Feature.str());
+	}
+      }
+    }
+
+    // Now add the target-cpu and target-features to the function.
+    if (TargetCPU != "")
+      FuncAttrs.addAttribute("target-cpu", TargetCPU);
     if (!Features.empty()) {
-      std::stringstream S;
+      std::stringstream TargetFeatures;
       std::copy(Features.begin(), Features.end(),
-                std::ostream_iterator<std::string>(S, ","));
+                std::ostream_iterator<std::string>(TargetFeatures, ","));
+
       // The drop_back gets rid of the trailing space.
       FuncAttrs.addAttribute("target-features",
-                             StringRef(S.str()).drop_back(1));
+                             StringRef(TargetFeatures.str()).drop_back(1));
     }
   }
 

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=239579&r1=239578&r2=239579&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Thu Jun 11 20:35:52 2015
@@ -2397,6 +2397,20 @@ static void handleSectionAttr(Sema &S, D
     D->addAttr(NewAttr);
 }
 
+static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // TODO: Validation should use a backend target library that specifies
+  // the allowable subtarget features and cpus. We could use something like a
+  // TargetCodeGenInfo hook here to do validation.
+  StringRef Str;
+  SourceLocation LiteralLoc;
+  if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc))
+    return;
+  unsigned Index = Attr.getAttributeSpellingListIndex();
+  TargetAttr *NewAttr =
+      ::new (S.Context) TargetAttr(Attr.getRange(), S.Context, Str, Index);
+  D->addAttr(NewAttr);
+}
+
 
 static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
   VarDecl *VD = cast<VarDecl>(D);
@@ -4716,6 +4730,9 @@ static void ProcessDeclAttribute(Sema &S
   case AttributeList::AT_Section:
     handleSectionAttr(S, D, Attr);
     break;
+  case AttributeList::AT_Target:
+    handleTargetAttr(S, D, Attr);
+    break;
   case AttributeList::AT_Unavailable:
     handleAttrWithMessage<UnavailableAttr>(S, D, Attr);
     break;

Added: cfe/trunk/test/CodeGen/attr-target.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attr-target.c?rev=239579&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/attr-target.c (added)
+++ cfe/trunk/test/CodeGen/attr-target.c Thu Jun 11 20:35:52 2015
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -target-cpu x86-64 -emit-llvm %s -o - | FileCheck %s
+
+int baz(int a) { return 4; }
+
+int __attribute__((target("avx,sse4.2,arch=ivybridge"))) foo(int a) { return 4; }
+
+int bar(int a) { return baz(a) + foo(a); }
+
+// Check that we emit the additional subtarget and cpu features for foo and not for baz or bar.
+// CHECK: baz{{.*}} #0
+// CHECK: foo{{.*}} #1
+// CHECK: bar{{.*}} #0
+// CHECK: #0 = {{.*}}"target-cpu"="x86-64" "target-features"="+sse,+sse2"
+// CHECK: #1 = {{.*}}"target-cpu"="ivybridge" "target-features"="+sse,+sse2,+avx,+sse4.2"

Added: cfe/trunk/test/Sema/attr-target.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-target.c?rev=239579&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-target.c (added)
+++ cfe/trunk/test/Sema/attr-target.c Thu Jun 11 20:35:52 2015
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu  -fsyntax-only -verify %s
+
+int __attribute__((target("avx,sse4.2,arch=ivybridge"))) foo() { return 4; }
+int __attribute__((target())) bar() { return 4; } //expected-error {{'target' attribute takes one argument}}
+
+





More information about the cfe-commits mailing list