[PATCH] #pragma vectorize

Richard Smith richard at metafoo.co.uk
Mon Jun 2 13:31:57 PDT 2014

On Sun, Jun 1, 2014 at 7:39 PM, Tyler Nowicki <tnowicki at apple.com> wrote:

> Hi Richard,
> Thanks for the detailed review!
> I went with the last syntax you suggested. Seems simple to me and easily
> extendable: #pragma clang loop vectorize_width(2) interleave_count(4).
> Also it helped clean up a lot of the ambiguity you talked about in the
> LoopHintAttr. A single integer Value has replaced the Kind
> (Enable/Disable/Value) and a integer value there previously. Hopefully it
> won’t be too difficult to support constant expressions, and non-type
> template parameters. I’ll work on those patches next.
> I also improved the incompatibility testing as well. I realized there were
> several cases my previous test wasn’t identifying.
> Objective C is a proper superset of C, so yes. I don't know Objective C
> very well either, and it might be the case that it would never be possible
> to vectorize its for loop, because it's too dynamic.
> Ok, its on my list.
> I think you want (and what the approach I described above permits) is to
> callParseConstantExpression.
> I think I understand now what you are suggesting. Your thinking that the
> expression may include more than one token. I gave it a try, but I wasn’t
> able to get it to work. The expression returned by ParseConstantExpression
> was always invalid. Perhaps I didn’t implement it correctly. I’m capturing
> all of the tokens between the brackets and then when handling the annotated
> token I reinserted them into the stream and called ParseConstantExpression.
> I tried it with and without the brackets and with and without a trailing
> eof token. The LHS and Res expressions parsed in ParseConstantExpression
> were also always invalid <<NULL>>. Lets leave this and other constant
> expression work for a later patch.


Here is the updated patch.

I think this is very close to being ready.

+  let Args = [EnumArgument<"Option", "OptionType",
+                          ["vectorize", "vectorize_width", "interleave",
+                          ["Vectorize", "VectorizeWidth", "Interleave",
+              DefaultIntArgument<"Value", 1>];

Once you move to supporting arbitrary constant expressions as the argument,
I think you may want to split this into two separate Attrs (one for
vectorize and interleave, that have a BoolArgument, and one for
vectorize_width and interleave_count, that have an ExprArgument).

I also think we should have different spellings for these different enum
values, once we have proper pragma spelling support:

  let Spellings = [Pragma<"clang", "loop", "vectorize_width">,
                   Pragma<"clang", "loop", "interleave_count">];
  let Args = [ExprArgument<"Value">];

... but that can all be deferred for a later patch.

+    const char *MetadataNames[] = {
+        "llvm.vectorizer.width", "llvm.vectorizer.width",
+        "llvm.vectorizer.unroll", "llvm.vectorizer.unroll"};
+    if (ValueInt == 1 && (Option == LoopHintAttr::Vectorize ||
+                          Option == LoopHintAttr::Interleave)) {
+      Name = llvm::MDString::get(Context, "llvm.vectorizer.enable");
+      Value = Builder.getTrue();
+    } else {
+      if (ValueInt == 0)
+        ValueInt = 1; // Vectorization/interleaving is disabled.
+      Name = llvm::MDString::get(Context, MetadataNames[Option]);
+      Value = llvm::ConstantInt::get(Int32Ty, ValueInt);
+    }

Please change this to a 'switch' to make this code more robust against
enumerators being added later.

+///  loop-hint:
+///    'vectorize' '(' loop-hint-value ')'
+///    'interleave' '(' loop-hint-value ')'
+///  loop-hint-value:
+///    'enable'
+///    'disable'
+///    constant-expression

This needs to be updated.

+// CHECK: br i1 %cmp, label %while.body, label %while.end, !llvm.loop !1
+// CHECK: br i1 %cmp, label %do.body, label %do.end, !llvm.loop !5
+// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !7
+// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !8
+// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !11
+// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !13
+// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !14
+// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !16

I believe these tests will fail on a NDEBUG build, because we don't give
names to values and basic blocks there. What we'd usually do is something
like this:

+void while_test(int *List, int Length) {
+  // CHECK: define {{.*}} @_Z10while_test
+  int i = 0;
+#pragma clang loop vectorize(enable)
+#pragma clang loop interleave_count(4)
+#pragma clang loop vectorize_width(4)
+  while (i < Length) {
+    // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop
+    List[i] = i * 2;
+    i++;
+  }
[... at end of file ...]
+// CHECK: ![[LOOP_1]] = metadata !{metadata ![[LOOP_1]], metadata
![[WIDTH_4:.*]], metadata ![[UNROLL_4:.*]], metadata ![[ENABLE_1:.*]]}
+// CHECK: ![[WIDTH_4]] = metadata !{metadata !"llvm.vectorizer.width", i32
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140602/91fa32b0/attachment.html>

More information about the cfe-commits mailing list