| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: opt -S < %s -passes=slp-vectorizer -mtriple=riscv64 -mattr=+v | FileCheck %s |
| |
| declare void @g() |
| |
| ; Shouldn't be vectorized |
| define void @f0(i1 %c, ptr %p, ptr %q) { |
| ; CHECK-LABEL: define void @f0( |
| ; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]]) #[[ATTR0:[0-9]+]] { |
| ; CHECK-NEXT: [[X0:%.*]] = load i64, ptr [[P]], align 8 |
| ; CHECK-NEXT: [[P1:%.*]] = getelementptr i64, ptr [[P]], i64 1 |
| ; CHECK-NEXT: [[X1:%.*]] = load i64, ptr [[P1]], align 8 |
| ; CHECK-NEXT: br i1 [[C]], label %[[FOO:.*]], label %[[BAR:.*]] |
| ; CHECK: [[FOO]]: |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: br label %[[BAZ:.*]] |
| ; CHECK: [[BAR]]: |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: br label %[[BAZ]] |
| ; CHECK: [[BAZ]]: |
| ; CHECK-NEXT: store i64 [[X0]], ptr [[Q]], align 8 |
| ; CHECK-NEXT: [[Q1:%.*]] = getelementptr i64, ptr [[Q]], i64 1 |
| ; CHECK-NEXT: store i64 [[X1]], ptr [[Q1]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| %x0 = load i64, ptr %p |
| %p1 = getelementptr i64, ptr %p, i64 1 |
| %x1 = load i64, ptr %p1 |
| br i1 %c, label %foo, label %bar |
| foo: |
| call void @g() |
| call void @g() |
| call void @g() |
| br label %baz |
| bar: |
| call void @g() |
| call void @g() |
| call void @g() |
| br label %baz |
| baz: |
| store i64 %x0, ptr %q |
| %q1 = getelementptr i64, ptr %q, i64 1 |
| store i64 %x1, ptr %q1 |
| |
| ret void |
| } |
| |
| ; Should be vectorized - just one spill of TMP0 |
| define void @f1(i1 %c, ptr %p, ptr %q, ptr %r) { |
| ; CHECK-LABEL: define void @f1( |
| ; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]], ptr [[R:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[ENTRY:.*:]] |
| ; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[P]], align 8 |
| ; CHECK-NEXT: br i1 [[C]], label %[[FOO:.*]], label %[[BAR:.*]] |
| ; CHECK: [[FOO]]: |
| ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i64> [[TMP0]], splat (i64 1) |
| ; CHECK-NEXT: br label %[[BAZ:.*]] |
| ; CHECK: [[BAR]]: |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: br label %[[BAZ]] |
| ; CHECK: [[BAZ]]: |
| ; CHECK-NEXT: [[TMP2:%.*]] = phi <2 x i64> [ [[TMP1]], %[[FOO]] ], [ [[TMP0]], %[[BAR]] ] |
| ; CHECK-NEXT: store <2 x i64> [[TMP2]], ptr [[Q]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %x0 = load i64, ptr %p |
| %p1 = getelementptr i64, ptr %p, i64 1 |
| %x1 = load i64, ptr %p1 |
| br i1 %c, label %foo, label %bar |
| foo: |
| %y0 = add i64 %x0, 1 |
| %y1 = add i64 %x1, 1 |
| br label %baz |
| bar: |
| call void @g() |
| call void @g() |
| call void @g() |
| br label %baz |
| baz: |
| %phi0 = phi i64 [%y0, %foo], [%x0, %bar] |
| %phi1 = phi i64 [%y1, %foo], [%x1, %bar] |
| store i64 %phi0, ptr %q |
| %q1 = getelementptr i64, ptr %q, i64 1 |
| store i64 %phi1, ptr %q1 |
| |
| ret void |
| } |
| |
| ; Shouldn't be vectorized |
| define void @f11(i1 %c, ptr %p, ptr %q, ptr %r) { |
| ; CHECK-LABEL: define void @f11( |
| ; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]], ptr [[R:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[ENTRY:.*:]] |
| ; CHECK-NEXT: [[X0:%.*]] = load i64, ptr [[P]], align 8 |
| ; CHECK-NEXT: [[P1:%.*]] = getelementptr i64, ptr [[P]], i64 1 |
| ; CHECK-NEXT: [[X1:%.*]] = load i64, ptr [[P1]], align 8 |
| ; CHECK-NEXT: br i1 [[C]], label %[[FOO:.*]], label %[[BAR:.*]] |
| ; CHECK: [[FOO]]: |
| ; CHECK-NEXT: br label %[[BAZ:.*]] |
| ; CHECK: [[BAR]]: |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: br label %[[BAZ]] |
| ; CHECK: [[BAZ]]: |
| ; CHECK-NEXT: [[PHI0:%.*]] = phi i64 [ 0, %[[FOO]] ], [ [[X0]], %[[BAR]] ] |
| ; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ 1, %[[FOO]] ], [ [[X1]], %[[BAR]] ] |
| ; CHECK-NEXT: store i64 [[PHI0]], ptr [[Q]], align 8 |
| ; CHECK-NEXT: [[Q1:%.*]] = getelementptr i64, ptr [[Q]], i64 1 |
| ; CHECK-NEXT: store i64 [[PHI1]], ptr [[Q1]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %x0 = load i64, ptr %p |
| %p1 = getelementptr i64, ptr %p, i64 1 |
| %x1 = load i64, ptr %p1 |
| br i1 %c, label %foo, label %bar |
| foo: |
| br label %baz |
| bar: |
| call void @g() |
| call void @g() |
| call void @g() |
| br label %baz |
| baz: |
| %phi0 = phi i64 [0, %foo], [%x0, %bar] |
| %phi1 = phi i64 [1, %foo], [%x1, %bar] |
| store i64 %phi0, ptr %q |
| %q1 = getelementptr i64, ptr %q, i64 1 |
| store i64 %phi1, ptr %q1 |
| |
| ret void |
| } |
| |
| ; Should be vectorized |
| define void @f2(i1 %c, ptr %p, ptr %q, ptr %r) { |
| ; CHECK-LABEL: define void @f2( |
| ; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]], ptr [[R:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[ENTRY:.*]]: |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: br i1 [[C]], label %[[FOO:.*]], label %[[BAR:.*]] |
| ; CHECK: [[FOO]]: |
| ; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[P]], align 8 |
| ; CHECK-NEXT: br label %[[BAR]] |
| ; CHECK: [[BAR]]: |
| ; CHECK-NEXT: [[TMP1:%.*]] = phi <2 x i64> [ zeroinitializer, %[[ENTRY]] ], [ [[TMP0]], %[[FOO]] ] |
| ; CHECK-NEXT: store <2 x i64> [[TMP1]], ptr [[Q]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| call void @g() |
| call void @g() |
| call void @g() |
| br i1 %c, label %foo, label %bar |
| foo: |
| %x0 = load i64, ptr %p |
| %p1 = getelementptr i64, ptr %p, i64 1 |
| %x1 = load i64, ptr %p1 |
| br label %bar |
| bar: |
| %phi0 = phi i64 [0, %entry], [%x0, %foo] |
| %phi1 = phi i64 [0, %entry], [%x1, %foo] |
| store i64 %phi0, ptr %q |
| %q1 = getelementptr i64, ptr %q, i64 1 |
| store i64 %phi1, ptr %q1 |
| |
| ret void |
| } |
| |
| |
| ; Shouldn't be vectorized |
| define void @f3(i64 %n, double %f0, double %f1, ptr %q) { |
| ; CHECK-LABEL: define void @f3( |
| ; CHECK-SAME: i64 [[N:%.*]], double [[F0:%.*]], double [[F1:%.*]], ptr [[Q:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[ENTRY:.*]]: |
| ; CHECK-NEXT: br label %[[LOOP:.*]] |
| ; CHECK: [[LOOP]]: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LATCH:.*]] ] |
| ; CHECK-NEXT: [[PHI0:%.*]] = phi double [ [[F0]], %[[ENTRY]] ], [ [[X0:%.*]], %[[LATCH]] ] |
| ; CHECK-NEXT: [[PHI1:%.*]] = phi double [ [[F1]], %[[ENTRY]] ], [ [[X1:%.*]], %[[LATCH]] ] |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: br label %[[LATCH]] |
| ; CHECK: [[LATCH]]: |
| ; CHECK-NEXT: [[X0]] = fadd double [[PHI0]], 1.000000e+00 |
| ; CHECK-NEXT: [[X1]] = fadd double [[PHI1]], 1.000000e+00 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 |
| ; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] |
| ; CHECK-NEXT: br i1 [[DONE]], label %[[EXIT:.*]], label %[[LOOP]] |
| ; CHECK: [[EXIT]]: |
| ; CHECK-NEXT: [[Q_GEP0:%.*]] = getelementptr i64, ptr [[Q]], i64 [[IV]] |
| ; CHECK-NEXT: store double [[X0]], ptr [[Q_GEP0]], align 8 |
| ; CHECK-NEXT: [[Q_GEP1:%.*]] = getelementptr i64, ptr [[Q_GEP0]], i64 1 |
| ; CHECK-NEXT: store double [[X1]], ptr [[Q_GEP1]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop |
| loop: |
| %iv = phi i64 [0, %entry], [%iv.next, %latch] |
| %phi0 = phi double [%f0, %entry], [%x0, %latch] |
| %phi1 = phi double [%f1, %entry], [%x1, %latch] |
| call void @g() |
| call void @g() |
| call void @g() |
| br label %latch |
| latch: |
| %x0 = fadd double %phi0, 1.0 |
| %x1 = fadd double %phi1, 1.0 |
| |
| %iv.next = add i64 %iv, 1 |
| %done = icmp eq i64 %iv.next, %n |
| br i1 %done, label %exit, label %loop |
| exit: |
| %q.gep0 = getelementptr i64, ptr %q, i64 %iv |
| store double %x0, ptr %q.gep0 |
| %q.gep1 = getelementptr i64, ptr %q.gep0, i64 1 |
| store double %x1, ptr %q.gep1 |
| ret void |
| } |
| |
| ; Should be vectorized |
| define void @f4(ptr %p, ptr %q, i1 %c0, i1 %c1) { |
| ; CHECK-LABEL: define void @f4( |
| ; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i1 [[C0:%.*]], i1 [[C1:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[ENTRY:.*:]] |
| ; CHECK-NEXT: br label %[[FOO:.*]] |
| ; CHECK: [[FOO]]: |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: br label %[[BAR:.*]] |
| ; CHECK: [[BAR]]: |
| ; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[P]], align 8 |
| ; CHECK-NEXT: br i1 [[C0]], label %[[BAZ:.*]], label %[[QUX:.*]] |
| ; CHECK: [[BAZ]]: |
| ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i64> [[TMP0]], splat (i64 1) |
| ; CHECK-NEXT: br label %[[QUX]] |
| ; CHECK: [[QUX]]: |
| ; CHECK-NEXT: [[TMP2:%.*]] = phi <2 x i64> [ [[TMP0]], %[[BAR]] ], [ [[TMP1]], %[[BAZ]] ] |
| ; CHECK-NEXT: store <2 x i64> [[TMP2]], ptr [[Q]], align 8 |
| ; CHECK-NEXT: br i1 [[C1]], label %[[FOO]], label %[[BAR]] |
| ; |
| entry: |
| br label %foo |
| foo: |
| call void @g() |
| call void @g() |
| call void @g() |
| br label %bar |
| bar: |
| %x0 = load i64, ptr %p |
| %p1 = getelementptr i64, ptr %p, i64 1 |
| %x1 = load i64, ptr %p1 |
| br i1 %c0, label %baz, label %qux |
| baz: |
| %y0 = add i64 %x0, 1 |
| %y1 = add i64 %x1, 1 |
| br label %qux |
| qux: |
| %z0 = phi i64 [%x0, %bar], [%y0, %baz] |
| %z1 = phi i64 [%x1, %bar], [%y1, %baz] |
| store i64 %z0, ptr %q |
| %q1 = getelementptr i64, ptr %q, i64 1 |
| store i64 %z1, ptr %q1 |
| br i1 %c1, label %foo, label %bar |
| } |
| |
| |
| ; Should be vectorized |
| define void @f5(i1 %c0, ptr %p, ptr %q) { |
| ; CHECK-LABEL: define void @f5( |
| ; CHECK-SAME: i1 [[C0:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[ENTRY:.*:]] |
| ; CHECK-NEXT: br label %[[FOO:.*]] |
| ; CHECK: [[FOO]]: |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[P]], align 8 |
| ; CHECK-NEXT: br i1 [[C0]], label %[[BAR:.*]], label %[[FOOBAR:.*]] |
| ; CHECK: [[BAR]]: |
| ; CHECK-NEXT: br label %[[BAZ:.*]] |
| ; CHECK: [[BAZ]]: |
| ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i64> [[TMP0]], splat (i64 1) |
| ; CHECK-NEXT: br label %[[BARFOO:.*]] |
| ; CHECK: [[FOOBAR]]: |
| ; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i64> [[TMP0]], splat (i64 2) |
| ; CHECK-NEXT: br label %[[BARFOO]] |
| ; CHECK: [[BARFOO]]: |
| ; CHECK-NEXT: [[TMP3:%.*]] = phi <2 x i64> [ [[TMP2]], %[[FOOBAR]] ], [ [[TMP1]], %[[BAZ]] ] |
| ; CHECK-NEXT: store <2 x i64> [[TMP3]], ptr [[Q]], align 8 |
| ; CHECK-NEXT: br label %[[FOO]] |
| ; |
| entry: |
| br label %foo |
| foo: |
| call void @g() |
| call void @g() |
| call void @g() |
| %x0 = load i64, ptr %p |
| %p1 = getelementptr i64, ptr %p, i64 1 |
| %x1 = load i64, ptr %p1 |
| br i1 %c0, label %bar, label %foobar |
| bar: |
| br label %baz |
| baz: |
| %y0 = add i64 %x0, 1 |
| %y1 = add i64 %x1, 1 |
| br label %barfoo |
| foobar: |
| %z0 = add i64 %x0, 2 |
| %z1 = add i64 %x1, 2 |
| br label %barfoo |
| barfoo: |
| %phi0 = phi i64 [%z0, %foobar], [%y0, %baz] |
| %phi1 = phi i64 [%z1, %foobar], [%y1, %baz] |
| store i64 %phi0, ptr %q |
| %q1 = getelementptr i64, ptr %q, i64 1 |
| store i64 %phi1, ptr %q1 |
| br label %foo |
| } |
| |
| ; Shouldn't be vectorized |
| define void @f6(i1 %c, ptr %p, ptr %q, ptr %r) { |
| ; CHECK-LABEL: define void @f6( |
| ; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]], ptr [[R:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[ENTRY:.*]]: |
| ; CHECK-NEXT: br i1 [[C]], label %[[FOO:.*]], label %[[BAR:.*]] |
| ; CHECK: [[FOO]]: |
| ; CHECK-NEXT: [[X0:%.*]] = load i64, ptr [[P]], align 8 |
| ; CHECK-NEXT: [[P1:%.*]] = getelementptr i64, ptr [[P]], i64 1 |
| ; CHECK-NEXT: [[X1:%.*]] = load i64, ptr [[P1]], align 8 |
| ; CHECK-NEXT: br label %[[BAR]] |
| ; CHECK: [[BAR]]: |
| ; CHECK-NEXT: [[PHI0:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[X0]], %[[FOO]] ] |
| ; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[X1]], %[[FOO]] ] |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: call void @g() |
| ; CHECK-NEXT: br label %[[BAZ:.*]] |
| ; CHECK: [[BAZ]]: |
| ; CHECK-NEXT: store i64 [[PHI0]], ptr [[Q]], align 8 |
| ; CHECK-NEXT: [[Q1:%.*]] = getelementptr i64, ptr [[Q]], i64 1 |
| ; CHECK-NEXT: store i64 [[PHI1]], ptr [[Q1]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br i1 %c, label %foo, label %bar |
| foo: |
| %x0 = load i64, ptr %p |
| %p1 = getelementptr i64, ptr %p, i64 1 |
| %x1 = load i64, ptr %p1 |
| br label %bar |
| bar: |
| %phi0 = phi i64 [0, %entry], [%x0, %foo] |
| %phi1 = phi i64 [0, %entry], [%x1, %foo] |
| call void @g() |
| call void @g() |
| call void @g() |
| br label %baz |
| baz: |
| store i64 %phi0, ptr %q |
| %q1 = getelementptr i64, ptr %q, i64 1 |
| store i64 %phi1, ptr %q1 |
| |
| ret void |
| } |
| |