diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2018-11-19 16:51:57 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2018-11-19 16:51:57 +0000 |
commit | 2cad359c91f79322ca5f304abd9c99d4f3a94a75 (patch) | |
tree | 801ee456d2640e2487965c47824b154c6edaaa12 /llvm/test/Transforms | |
parent | 47066bd5f711b04328ffef45d9db38c51b0c9705 (diff) | |
download | bcm5719-llvm-2cad359c91f79322ca5f304abd9c99d4f3a94a75.tar.gz bcm5719-llvm-2cad359c91f79322ca5f304abd9c99d4f3a94a75.zip |
Revert "[LICM] Make LICM able to hoist phis"
This reverts commit r347190.
llvm-svn: 347225
Diffstat (limited to 'llvm/test/Transforms')
-rw-r--r-- | llvm/test/Transforms/LICM/hoist-phi.ll | 1164 | ||||
-rw-r--r-- | llvm/test/Transforms/LoopVectorize/invariant-store-vectorization.ll | 20 |
2 files changed, 9 insertions, 1175 deletions
diff --git a/llvm/test/Transforms/LICM/hoist-phi.ll b/llvm/test/Transforms/LICM/hoist-phi.ll deleted file mode 100644 index e7a191b836c..00000000000 --- a/llvm/test/Transforms/LICM/hoist-phi.ll +++ /dev/null @@ -1,1164 +0,0 @@ -; RUN: opt -S -licm < %s | FileCheck %s -; RUN: opt -passes='require<opt-remark-emit>,loop(licm)' -S < %s | FileCheck %s - -; CHECK-LABEL: @triangle_phi -define void @triangle_phi(i32 %x, i32* %p) { -; CHECK-LABEL: entry: -; CHECK: %cmp1 = icmp sgt i32 %x, 0 -; CHECK: br i1 %cmp1, label %[[IF_LICM:.*]], label %[[THEN_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: %add = add i32 %x, 1 -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]]: -; CHECK: phi i32 [ %add, %[[IF_LICM]] ], [ %x, %entry ] -; CHECK: store i32 %phi, i32* %p -; CHECK: %cmp2 = icmp ne i32 %phi, 0 -; CHECK: br label %loop - -loop: - %cmp1 = icmp sgt i32 %x, 0 - br i1 %cmp1, label %if, label %then - -if: - %add = add i32 %x, 1 - br label %then - -then: - %phi = phi i32 [ %add, %if ], [ %x, %loop ] - store i32 %phi, i32* %p - %cmp2 = icmp ne i32 %phi, 0 - br i1 %cmp2, label %loop, label %end - -end: - ret void -} - -; CHECK-LABEL: @diamond_phi -define void @diamond_phi(i32 %x, i32* %p) { -; CHECK-LABEL: entry: -; CHECK: %cmp1 = icmp sgt i32 %x, 0 -; CHECK: br i1 %cmp1, label %[[IF_LICM:.*]], label %[[ELSE_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: %add = add i32 %x, 1 -; CHECK: br label %[[THEN_LICM:.*]] - -; CHECK: [[ELSE_LICM]]: -; CHECK: %sub = sub i32 %x, 1 -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]] -; CHECK: %phi = phi i32 [ %add, %[[IF_LICM]] ], [ %sub, %[[ELSE_LICM]] ] -; CHECK: store i32 %phi, i32* %p -; CHECK: %cmp2 = icmp ne i32 %phi, 0 -; CHECK: br label %loop - -loop: - %cmp1 = icmp sgt i32 %x, 0 - br i1 %cmp1, label %if, label %else - -if: - %add = add i32 %x, 1 - br label %then - -else: - %sub = sub i32 %x, 1 - br label %then - -then: - %phi = phi i32 [ %add, %if ], [ %sub, %else ] - store i32 %phi, i32* %p - %cmp2 = icmp ne i32 %phi, 0 - br i1 %cmp2, label %loop, label %end - -end: - ret void -} - -; TODO: This is currently too complicated for us to be able to hoist the phi. -; CHECK-LABEL: @three_way_phi -define void @three_way_phi(i32 %x, i32* %p) { -; CHECK-LABEL: entry: -; CHECK-DAG: %cmp1 = icmp sgt i32 %x, 0 -; CHECK-DAG: %add = add i32 %x, 1 -; CHECK-DAG: %cmp2 = icmp sgt i32 %add, 0 -; CHECK: br i1 %cmp1, label %[[IF_LICM:.*]], label %[[ELSE_LICM:.*]] - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM:.*]] - -; CHECK: [[THEN_LICM]]: -; CHECK: %sub = sub i32 %x, 1 -; CHECK: br label %loop - -entry: - br label %loop - -loop: - %cmp1 = icmp sgt i32 %x, 0 - br i1 %cmp1, label %if, label %then - -if: - %add = add i32 %x, 1 - %cmp2 = icmp sgt i32 %add, 0 - br i1 %cmp2, label %if.if, label %then - -if.if: - %sub = sub i32 %x, 1 - br label %then - -then: - %phi = phi i32 [ 0, %loop ], [ %add, %if ], [ %sub, %if.if ] - store i32 %phi, i32* %p - %cmp3 = icmp ne i32 %phi, 0 - br i1 %cmp3, label %loop, label %end - -end: - ret void -} - -; TODO: This is currently too complicated for us to be able to hoist the phi. -; CHECK-LABEL: @tree_phi -define void @tree_phi(i32 %x, i32* %p) { -; CHECK-LABEL: entry: -; CHECK-DAG: %cmp1 = icmp sgt i32 %x, 0 -; CHECK-DAG: %add = add i32 %x, 1 -; CHECK-DAG: %cmp2 = icmp sgt i32 %add, 0 -; CHECK-DAG: %sub = sub i32 %x, 1 -; CHECK: br label %loop - -entry: - br label %loop - -loop: - %cmp1 = icmp sgt i32 %x, 0 - br i1 %cmp1, label %if, label %else - -if: - %add = add i32 %x, 1 - %cmp2 = icmp sgt i32 %add, 0 - br i1 %cmp2, label %if.if, label %if.else - -if.if: - br label %then - -if.else: - br label %then - -else: - %sub = sub i32 %x, 1 - br label %then - -then: - %phi = phi i32 [ %add, %if.if ], [ 0, %if.else ], [ %sub, %else ] - store i32 %phi, i32* %p - %cmp3 = icmp ne i32 %phi, 0 - br i1 %cmp3, label %loop, label %end - -end: - ret void -} - -; TODO: We can hoist the first phi, but not the second. -; CHECK-LABEL: @phi_phi -define void @phi_phi(i32 %x, i32* %p) { -; CHECK-LABEL: entry: -; CHECK-DAG: %cmp1 = icmp sgt i32 %x, 0 -; CHECK-DAG: %add = add i32 %x, 1 -; CHECK-DAG: %cmp2 = icmp sgt i32 %add, 0 -; CHECK-DAG: %sub = sub i32 %x, 1 -; CHECK: br i1 %cmp2, label %[[IF_IF_LICM:.*]], label %[[IF_ELSE_LICM:.*]] - -; CHECK: [[IF_IF_LICM]]: -; CHECK: br label %[[IF_THEN_LICM:.*]] - -; CHECK: [[IF_ELSE_LICM]]: -; CHECK: br label %[[IF_THEN_LICM]] - -; CHECK: [[IF_THEN_LICM]]: -; CHECK: %phi1 = phi i32 [ %add, %[[IF_IF_LICM]] ], [ 0, %[[IF_ELSE_LICM]] ] -; CHECK: br label %loop - -entry: - br label %loop - -loop: - %cmp1 = icmp sgt i32 %x, 0 - br i1 %cmp1, label %if, label %else - -if: - %add = add i32 %x, 1 - %cmp2 = icmp sgt i32 %add, 0 - br i1 %cmp2, label %if.if, label %if.else - -if.if: - br label %if.then - -if.else: - br label %if.then - -if.then: - %phi1 = phi i32 [ %add, %if.if ], [ 0, %if.else ] - br label %then - -else: - %sub = sub i32 %x, 1 - br label %then - -then: - %phi2 = phi i32 [ %phi1, %if.then ], [ %sub, %else ] - store i32 %phi2, i32* %p - %cmp3 = icmp ne i32 %phi2, 0 - br i1 %cmp3, label %loop, label %end - -end: - ret void -} - -; Check that we correctly duplicate empty control flow. -; CHECK-LABEL: @empty_triangle_phi -define i8 @empty_triangle_phi(i32 %x, i32 %y) { -; CHECK-LABEL: entry: -; CHECK: %cmp1 = icmp eq i32 %x, 0 -; CHECK: br i1 %cmp1, label %[[IF_LICM:.*]], label %[[THEN_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]]: -; CHECK: %phi = phi i8 [ 0, %[[IF_LICM]] ], [ 1, %entry ] -; CHECK: %cmp2 = icmp eq i32 %y, 0 -; CHECK: br label %loop - -loop: - %cmp1 = icmp eq i32 %x, 0 - br i1 %cmp1, label %if, label %then - -if: - br label %then - -then: - %phi = phi i8 [ 0, %if ], [ 1, %loop ] - %cmp2 = icmp eq i32 %y, 0 - br i1 %cmp2, label %end, label %loop - -end: - ret i8 %phi -} - -; CHECK-LABEL: @empty_diamond_phi -define i8 @empty_diamond_phi(i32 %x, i32 %y) { -; CHECK-LABEL: entry: -; CHECK: %cmp1 = icmp eq i32 %x, 0 -; CHECK: br i1 %cmp1, label %[[IF_LICM:.*]], label %[[ELSE_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM:.*]] - -; CHECK: [[ELSE_LICM]]: -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]]: -; CHECK: %phi = phi i8 [ 0, %[[IF_LICM]] ], [ 1, %[[ELSE_LICM]] ] -; CHECK: %cmp2 = icmp eq i32 %y, 0 -; CHECK: br label %loop - -loop: - %cmp1 = icmp eq i32 %x, 0 - br i1 %cmp1, label %if, label %else - -if: - br label %then - -else: - br label %then - -then: - %phi = phi i8 [ 0, %if ], [ 1, %else ] - %cmp2 = icmp eq i32 %y, 0 - br i1 %cmp2, label %end, label %loop - -end: - ret i8 %phi -} - -; Check that we correctly handle the case that the first thing we try to hoist is a phi. -; CHECK-LABEL: @empty_triangle_phi_first -define i8 @empty_triangle_phi_first(i32 %x, i1 %cond) { -; CHECK-LABEL: entry: -; CHECK: br i1 %cond, label %[[IF_LICM:.*]], label %[[THEN_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]]: -; CHECK: %phi = phi i8 [ 0, %[[IF_LICM]] ], [ 1, %entry ] -; CHECK: %cmp = icmp eq i32 %x, 0 -; CHECK: br label %loop - -loop: - br i1 %cond, label %if, label %then - -if: - br label %then - -then: - %phi = phi i8 [ 0, %if ], [ 1, %loop ] - %cmp = icmp eq i32 %x, 0 - br i1 %cmp, label %end, label %loop - -end: - ret i8 %phi -} - -; CHECK-LABEL: @empty_diamond_phi -define i8 @empty_diamond_phi_first(i32 %x, i1 %cond) { -; CHECK-LABEL: entry: -; CHECK: br i1 %cond, label %[[IF_LICM:.*]], label %[[ELSE_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM:.*]] - -; CHECK: [[ELSE_LICM]]: -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]]: -; CHECK: %phi = phi i8 [ 0, %[[IF_LICM]] ], [ 1, %[[ELSE_LICM]] ] -; CHECK: %cmp = icmp eq i32 %x, 0 -; CHECK: br label %loop - -loop: - br i1 %cond, label %if, label %else - -if: - br label %then - -else: - br label %then - -then: - %phi = phi i8 [ 0, %if ], [ 1, %else ] - %cmp = icmp eq i32 %x, 0 - br i1 %cmp, label %end, label %loop - -end: - ret i8 %phi -} - -; CHECK-LABEL: @empty_triangle_phi_first -define i8 @empty_triangle_phi_first_empty_loop_head(i32 %x, i1 %cond) { -; CHECK-LABEL: entry: -; CHECK: br i1 %cond, label %[[IF_LICM:.*]], label %[[THEN_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]]: -; CHECK: %phi = phi i8 [ 0, %[[IF_LICM]] ], [ 1, %entry ] -; CHECK: %cmp = icmp eq i32 %x, 0 -; CHECK: br label %loop - -loop: - br label %test - -test: - br i1 %cond, label %if, label %then - -if: - br label %then - -then: - %phi = phi i8 [ 0, %if ], [ 1, %test ] - %cmp = icmp eq i32 %x, 0 - br i1 %cmp, label %end, label %loop - -end: - ret i8 %phi -} - -; CHECK-LABEL: @empty_diamond_phi_first_empty_loop_head -define i8 @empty_diamond_phi_first_empty_loop_head(i32 %x, i1 %cond) { -; CHECK-LABEL: entry: -; CHECK: br i1 %cond, label %[[IF_LICM:.*]], label %[[ELSE_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM:.*]] - -; CHECK: [[ELSE_LICM]]: -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]]: -; CHECK: %phi = phi i8 [ 0, %[[IF_LICM]] ], [ 1, %[[ELSE_LICM]] ] -; CHECK: %cmp = icmp eq i32 %x, 0 -; CHECK: br label %loop - -loop: - br label %test - -test: - br i1 %cond, label %if, label %else - -if: - br label %then - -else: - br label %then - -then: - %phi = phi i8 [ 0, %if ], [ 1, %else ] - %cmp = icmp eq i32 %x, 0 - br i1 %cmp, label %end, label %loop - -end: - ret i8 %phi -} - -; The phi is on one branch of a diamond while simultaneously at the end of a -; triangle. Check that we duplicate the triangle and not the diamond. -; CHECK-LABEL: @triangle_diamond -define void @triangle_diamond(i32* %ptr, i32 %x, i32 %y) { -; CHECK-LABEL: entry: -; CHECK-DAG: %cmp1 = icmp ne i32 %x, 0 -; CHECK-DAG: %cmp2 = icmp ne i32 %y, 0 -; CHECK: br i1 %cmp1, label %[[IF_LICM:.*]], label %[[THEN_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]]: -; CHECK: %phi = phi i32 [ 0, %[[IF_LICM]] ], [ 127, %entry ] - -loop: - %cmp1 = icmp ne i32 %x, 0 - br i1 %cmp1, label %if, label %then - -if: - %cmp2 = icmp ne i32 %y, 0 - br i1 %cmp2, label %if.then, label %then - -then: - %phi = phi i32 [ 0, %if ], [ 127, %loop ] - store i32 %phi, i32* %ptr - br label %end - -if.then: - br label %end - -end: - br label %loop -} - -; As the previous, but the end of the diamond is the head of the loop. -; CHECK-LABEL: @triangle_diamond_backedge -define void @triangle_diamond_backedge(i32* %ptr, i32 %x, i32 %y) { -; CHECK-LABEL: entry: -; CHECK-DAG: %cmp1 = icmp ne i32 %x, 0 -; CHECK-DAG: %cmp2 = icmp ne i32 %y, 0 -; CHECK: br i1 %cmp1, label %[[IF_LICM:.*]], label %[[THEN_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]]: -; CHECK: %phi = phi i32 [ 0, %[[IF_LICM]] ], [ 127, %entry ] - -loop: - %cmp1 = icmp ne i32 %x, 0 - br i1 %cmp1, label %if, label %then - -if: - %cmp2 = icmp ne i32 %y, 0 - br i1 %cmp2, label %backedge, label %then - -then: - %phi = phi i32 [ 0, %if ], [ 127, %loop ] - store i32 %phi, i32* %ptr - br label %loop - -backedge: - br label %loop -} - -; TODO: The inner diamonds can be hoisted, but not currently the outer diamond -; CHECK-LABEL: @diamonds_inside_diamond -define void @diamonds_inside_diamond(i32 %x, i32* %p) { -; CHECK-LABEL: entry: -; CHECK-DAG: %cmp1 = icmp sgt i32 %x, 0 -; CHECK-DAG: %cmp3 = icmp slt i32 %x, -10 -; CHECK: br i1 %cmp3, label %[[ELSE_IF_LICM:.*]], label %[[ELSE_ELSE_LICM:.*]] -entry: - br label %loop - -; CHECK: [[ELSE_IF_LICM]]: -; CHECK: br label %[[ELSE_THEN_LICM:.*]] - -; CHECK: [[ELSE_ELSE_LICM]]: -; CHECK: br label %[[ELSE_THEN_LICM]] - -; CHECK: [[ELSE_THEN_LICM]]: -; CHECK: %phi2 = phi i32 [ 2, %[[ELSE_IF_LICM]] ], [ 3, %[[ELSE_ELSE_LICM]] ] -; CHECK: %cmp2 = icmp sgt i32 %x, 10 -; CHECK: br i1 %cmp2, label %[[IF_IF_LICM:.*]], label %[[IF_ELSE_LICM:.*]] - -; CHECK: [[IF_IF_LICM]]: -; CHECK: br label %[[IF_THEN_LICM:.*]] - -; CHECK: [[IF_ELSE_LICM]]: -; CHECK: br label %[[IF_THEN_LICM]] - -; CHECK: [[IF_THEN_LICM]]: -; CHECK: %phi1 = phi i32 [ 0, %[[IF_IF_LICM]] ], [ 1, %[[IF_ELSE_LICM]] ] -; CHECK: br label %loop - -loop: - %cmp1 = icmp sgt i32 %x, 0 - br i1 %cmp1, label %if, label %else - -if: - %cmp2 = icmp sgt i32 %x, 10 - br i1 %cmp2, label %if.if, label %if.else - -if.if: - br label %if.then - -if.else: - br label %if.then - -if.then: - %phi1 = phi i32 [ 0, %if.if ], [ 1, %if.else ] - br label %then - -else: - %cmp3 = icmp slt i32 %x, -10 - br i1 %cmp3, label %else.if, label %else.else - -else.if: - br label %else.then - -else.else: - br label %else.then - -else.then: - %phi2 = phi i32 [ 2, %else.if ], [ 3, %else.else ] - br label %then - -then: - %phi3 = phi i32 [ %phi1, %if.then ], [ %phi2, %else.then ] - store i32 %phi3, i32* %p - %cmp4 = icmp ne i32 %phi3, 0 - br i1 %cmp4, label %loop, label %end - -end: - ret void -} - -; We can hoist blocks that contain an edge that exits the loop by ignoring that -; edge in the hoisted block. -; CHECK-LABEL: @triangle_phi_loopexit -define void @triangle_phi_loopexit(i32 %x, i32* %p) { -; CHECK-LABEL: entry: -; CHECK-DAG: %add = add i32 %x, 1 -; CHECK-DAG: %cmp1 = icmp sgt i32 %x, 0 -; CHECK-DAG: %cmp2 = icmp sgt i32 10, %add -; CHECK: br i1 %cmp1, label %[[IF_LICM:.*]], label %[[THEN_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]]: -; CHECK: %phi = phi i32 [ %add, %[[IF_LICM]] ], [ %x, %entry ] - -loop: - %cmp1 = icmp sgt i32 %x, 0 - br i1 %cmp1, label %if, label %then - -if: - %add = add i32 %x, 1 - %cmp2 = icmp sgt i32 10, %add - br i1 %cmp2, label %then, label %end - -then: - %phi = phi i32 [ %add, %if ], [ %x, %loop ] - store i32 %phi, i32* %p - %cmp3 = icmp ne i32 %phi, 0 - br i1 %cmp3, label %loop, label %end - -end: - ret void -} - -; CHECK-LABEL: @diamond_phi_oneloopexit -define void @diamond_phi_oneloopexit(i32 %x, i32* %p) { -; CHECK-LABEL: entry: -; CHECK-DAG: %add = add i32 %x, 1 -; CHECK-DAG: %cmp1 = icmp sgt i32 %x, 0 -; CHECK-DAG: %cmp2 = icmp sgt i32 10, %add -; CHECK: br i1 %cmp1, label %[[IF_LICM:.*]], label %[[THEN_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM:.*]] - -; CHECK: [[ELSE_LICM]]: -; CHECK: %sub = sub i32 %x, 1 -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]] -; CHECK: %phi = phi i32 [ %add, %[[IF_LICM]] ], [ %sub, %[[ELSE_LICM]] ] -; CHECK: %cmp3 = icmp ne i32 %phi, 0 -; CHECK: br label %loop - -loop: - %cmp1 = icmp sgt i32 %x, 0 - br i1 %cmp1, label %if, label %else - -if: - %add = add i32 %x, 1 - %cmp2 = icmp sgt i32 10, %add - br i1 %cmp2, label %then, label %end - -else: - %sub = sub i32 %x, 1 - br label %then - -then: - %phi = phi i32 [ %add, %if ], [ %sub, %else ] - store i32 %phi, i32* %p - %cmp3 = icmp ne i32 %phi, 0 - br i1 %cmp3, label %loop, label %end - -end: - ret void -} - -; CHECK-LABEL: @diamond_phi_twoloopexit -define void @diamond_phi_twoloopexit(i32 %x, i32* %p) { -; CHECK-LABEL: entry: -; CHECK-DAG: %sub = sub i32 %x, 1 -; CHECK-DAG: %add = add i32 %x, 1 -; CHECK-DAG: %cmp1 = icmp sgt i32 %x, 0 -; CHECK-DAG: %cmp2 = icmp sgt i32 10, %add -; CHECK-DAG: %cmp3 = icmp sgt i32 10, %sub -; CHECK: br i1 %cmp1, label %[[IF_LICM:.*]], label %[[THEN_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM:.*]] - -; CHECK: [[ELSE_LICM]]: -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]] -; CHECK: %phi = phi i32 [ %add, %[[IF_LICM]] ], [ %sub, %[[ELSE_LICM]] ] -; CHECK: %cmp4 = icmp ne i32 %phi, 0 -; CHECK: br label %loop - -loop: - %cmp1 = icmp sgt i32 %x, 0 - br i1 %cmp1, label %if, label %else - -if: - %add = add i32 %x, 1 - %cmp2 = icmp sgt i32 10, %add - br i1 %cmp2, label %then, label %end - -else: - %sub = sub i32 %x, 1 - %cmp3 = icmp sgt i32 10, %sub - br i1 %cmp3, label %then, label %end - -then: - %phi = phi i32 [ %add, %if ], [ %sub, %else ] - store i32 %phi, i32* %p - %cmp4 = icmp ne i32 %phi, 0 - br i1 %cmp4, label %loop, label %end - -end: - ret void -} - -; The store cannot be hoisted, so add and shr cannot be hoisted into a -; conditional block. -; CHECK-LABEL: @conditional_use -define void @conditional_use(i32 %x, i32* %p) { -; CHECK-LABEL: entry: -; CHECK-DAG: %cond = icmp ugt i32 %x, 0 -; CHECK-DAG: %add = add i32 %x, 5 -; CHECK-DAG: %shr = ashr i32 %add, 1 -; CHECK: br label %loop -entry: - br label %loop - -loop: - %cond = icmp ugt i32 %x, 0 - br i1 %cond, label %if, label %else - -; CHECK-LABEL: if: -; CHECK: store i32 %shr, i32* %p, align 4 -if: - %add = add i32 %x, 5 - %shr = ashr i32 %add, 1 - store i32 %shr, i32* %p, align 4 - br label %then - -else: - br label %then - -then: - br label %loop -} - -; A diamond with two triangles on the left and one on the right. This test is -; to check that we have a unique loop preheader when we hoist the store (and so -; don't fail an assertion). -; CHECK-LABEL: @triangles_in_diamond -define void @triangles_in_diamond(i32* %ptr) { -; CHECK-LABEL: entry: -; CHECK: store i32 0, i32* %ptr, align 4 -; CHECK: br label %loop -entry: - br label %loop - -loop: - br i1 undef, label %left_triangle_1, label %right_triangle - -left_triangle_1: - br i1 undef, label %left_triangle_1_if, label %left_triangle_2 - -left_triangle_1_if: - br label %left_triangle_2 - -left_triangle_2: - br i1 undef, label %left_triangle_2_if, label %left_triangle_2_then - -left_triangle_2_if: - br label %left_triangle_2_then - -left_triangle_2_then: - br label %loop.end - -right_triangle: - br i1 undef, label %right_triangle.if, label %right_triangle.then - -right_triangle.if: - br label %right_triangle.then - -right_triangle.then: - br label %loop.end - -loop.end: - store i32 0, i32* %ptr, align 4 - br label %loop -} - -; %cmp dominates its used after being hoisted, but not after %brmerge is rehoisted -; CHECK-LABEL: @rehoist -define void @rehoist(i8* %this, i32 %x) { -; CHECK-LABEL: entry: -; CHECK-DAG: %sub = add nsw i32 %x, -1 -; CHECK-DAG: %fptr = bitcast i8* %this to void (i8*)* -; CHECK-DAG: %cmp = icmp eq i32 0, %sub -; CHECK-DAG: %brmerge = or i1 %cmp, true -entry: - %sub = add nsw i32 %x, -1 - br label %loop - -loop: - br i1 undef, label %if1, label %else1 - -if1: - %fptr = bitcast i8* %this to void (i8*)* - call void %fptr(i8* %this) - br label %then1 - -else1: - br label %then1 - -then1: - %cmp = icmp eq i32 0, %sub - br i1 %cmp, label %end, label %else2 - -else2: - %brmerge = or i1 %cmp, true - br i1 %brmerge, label %if3, label %end - -if3: - br label %end - -end: - br label %loop -} - -; A test case that uses empty blocks in a way that can cause control flow -; hoisting to get confused. -; CHECK-LABEL: @empty_blocks_multiple_conditional_branches -define void @empty_blocks_multiple_conditional_branches(float %arg, float* %ptr) { -; CHECK-LABEL: entry -; CHECK-DAG: %div1 = fmul float %arg, 4.000000e+00 -; CHECK-DAG: %div2 = fmul float %arg, 2.000000e+00 -entry: - br label %loop - -; The exact path to the phi isn't checked here, because it depends on whether -; cond2 or cond3 is hoisted first -; CHECK: %phi = phi float [ 0.000000e+00, %{{.*}} ], [ %div1, %{{.*}} ] -; CHECK: br label %loop - -loop: - br i1 undef, label %backedge2, label %cond1 - -cond1: - br i1 undef, label %cond1.if, label %cond1.else - -cond1.else: - br label %cond3 - -cond1.if: - br label %cond1.if.next - -cond1.if.next: - br label %cond2 - -cond2: - %div1 = fmul float %arg, 4.000000e+00 - br i1 undef, label %cond2.if, label %cond2.then - -cond2.if: - br label %cond2.then - -cond2.then: - %phi = phi float [ 0.000000e+00, %cond2 ], [ %div1, %cond2.if ] - store float %phi, float* %ptr - br label %backedge2 - -cond3: - br i1 undef, label %cond3.then, label %cond3.if - -cond3.if: - %div2 = fmul float %arg, 2.000000e+00 - store float %div2, float* %ptr - br label %cond3.then - -cond3.then: - br label %loop - -backedge2: - br label %loop -} - -; We can't do much here, so mainly just check that we don't crash. -; CHECK-LABEL: @many_path_phi -define void @many_path_phi(i32* %ptr1, i32* %ptr2) { -; CHECK-LABEL: entry: -; CHECK-DAG: %gep3 = getelementptr inbounds i32, i32* %ptr2, i32 2 -; CHECK-DAG: %gep2 = getelementptr inbounds i32, i32* %ptr2, i32 2 -; CHECK: br label %loop -entry: - br label %loop - -loop: - %phi1 = phi i32 [ 0, %entry ], [ %phi2, %end ] - %cmp1 = icmp ugt i32 %phi1, 3 - br i1 %cmp1, label %cond2, label %cond1 - -cond1: - br i1 undef, label %end, label %cond1.else - -cond1.else: - %gep2 = getelementptr inbounds i32, i32* %ptr2, i32 2 - %val2 = load i32, i32* %gep2, align 4 - %cmp2 = icmp eq i32 %val2, 13 - br i1 %cmp2, label %cond1.end, label %end - -cond1.end: - br label %end - -cond2: - br i1 undef, label %end, label %cond2.else - -cond2.else: - %gep3 = getelementptr inbounds i32, i32* %ptr2, i32 2 - %val3 = load i32, i32* %gep3, align 4 - %cmp3 = icmp eq i32 %val3, 13 - br i1 %cmp3, label %cond2.end, label %end - -cond2.end: - br label %end - -end: - %phi2 = phi i32 [ 1, %cond1 ], [ 2, %cond1.else ], [ 3, %cond1.end ], [ 4, %cond2 ], [ 5, %cond2.else ], [ 6, %cond2.end ] - br label %loop -} - -; Check that we correctly handle the hoisting of %gep when theres a critical -; edge that branches to the preheader. -; CHECK-LABEL: @crit_edge -define void @crit_edge(i32* %ptr, i32 %idx, i1 %cond1, i1 %cond2) { -; CHECK-LABEL: entry: -; CHECK: %gep = getelementptr inbounds i32, i32* %ptr, i32 %idx -; CHECK: br label %preheader -entry: - br label %preheader - -preheader: - br label %loop - -loop: - br i1 %cond1, label %then, label %if - -if: - %gep = getelementptr inbounds i32, i32* %ptr, i32 %idx - %val = load i32, i32* %gep - br label %then - -then: - %phi = phi i32 [ %val, %if ], [ 0, %loop ] - store i32 %phi, i32* %ptr - br i1 %cond2, label %loop, label %crit_edge - -crit_edge: - br label %preheader -} - -; Check that the conditional sub is correctly hoisted from the inner loop to the -; preheader of the outer loop. -; CHECK-LABEL: @hoist_from_innermost_loop -define void @hoist_from_innermost_loop(i32 %nx, i32* %ptr) { -; CHECK-LABEL: entry: -; CHECK-DAG: %sub = sub nsw i32 0, %nx -; CHECK: br label %outer_loop -entry: - br label %outer_loop - -outer_loop: - br label %middle_loop - -middle_loop: - br label %inner_loop - -inner_loop: - br i1 undef, label %inner_loop_end, label %if - -if: - %sub = sub nsw i32 0, %nx - store i32 %sub, i32* %ptr, align 4 - br label %inner_loop_end - -inner_loop_end: - br i1 undef, label %inner_loop, label %middle_loop_end - -middle_loop_end: - br i1 undef, label %middle_loop, label %outer_loop_end - -outer_loop_end: - br label %outer_loop -} - -; We have a diamond starting from %if, but %if.if is also reachable from %loop, -; so %gep should not be conditionally hoisted. -; CHECK-LABEL: @diamond_with_extra_in_edge -define void @diamond_with_extra_in_edge(i32* %ptr1, i32* %ptr2, i32 %arg) { -; CHECK-LABEL: entry: -; CHECK-DAG: %cmp2 = icmp ne i32 0, %arg -; CHECK-DAG: %gep = getelementptr i32, i32* %ptr1, i32 4 -; CHECK: br label %loop -entry: - br label %loop - -loop: - %phi1 = phi i32 [ 0, %entry ], [ %phi2, %then ] - %cmp1 = icmp ugt i32 16, %phi1 - br i1 %cmp1, label %if, label %if.if - -if: - %cmp2 = icmp ne i32 0, %arg - br i1 %cmp2, label %if.if, label %if.else - -if.if: - %gep = getelementptr i32, i32* %ptr1, i32 4 - %val = load i32, i32* %gep, align 4 - br label %then - -if.else: - br label %then - -then: - %phi2 = phi i32 [ %val, %if.if ], [ %phi1, %if.else ] - store i32 %phi2, i32* %ptr2, align 4 - br label %loop -} - -; %loop/%if/%then form a triangle, but %loop/%if/%then/%end also form a diamond. -; The triangle should be picked for conditional hoisting. -; CHECK-LABEL: @both_triangle_and_diamond -define void @both_triangle_and_diamond(i32* %ptr1, i32* %ptr2, i32 %arg) { -; CHECK-LABEL: entry: -; CHECK-DAG: %cmp1 = icmp ne i32 0, %arg -; CHECK-DAG: %gep = getelementptr i32, i32* %ptr1, i32 4 -; CHECK: br i1 %cmp1, label %[[IF_LICM:.*]], label %[[THEN_LICM:.*]] -entry: - br label %loop - -; CHECK: [[IF_LICM]]: -; CHECK: br label %[[THEN_LICM]] - -; CHECK: [[THEN_LICM]]: -; CHECK: %phi2 = phi i32 [ 0, %[[IF_LICM]] ], [ 1, %entry ] -; CHECK: br label %loop - -loop: - %phi1 = phi i32 [ 0, %entry ], [ %phi3, %end ] - %cmp1 = icmp ne i32 0, %arg - br i1 %cmp1, label %if, label %then - -if: - %gep = getelementptr i32, i32* %ptr1, i32 4 - %val = load i32, i32* %gep, align 4 - %cmp2 = icmp ugt i32 16, %phi1 - br i1 %cmp2, label %end, label %then - -then: - %phi2 = phi i32 [ 0, %if ], [ 1, %loop ] - br label %end - -end: - %phi3 = phi i32 [ %phi2, %then ], [ %val, %if ] - store i32 %phi3, i32* %ptr2, align 4 - br label %loop -} - -; We shouldn't duplicate the branch at the end of %loop and should instead hoist -; %val to %entry. -; CHECK-LABEL: @same_destination_branch -define i32 @same_destination_branch(i32 %arg1, i32 %arg2) { -; CHECK-LABEL: entry: -; CHECK-DAG: %cmp1 = icmp ne i32 %arg2, 0 -; CHECK-DAG: %val = add i32 %arg1, 1 -; CHECK: br label %loop -entry: - br label %loop - -loop: - %phi = phi i32 [ 0, %entry ], [ %add, %then ] - %add = add i32 %phi, 1 - %cmp1 = icmp ne i32 %arg2, 0 - br i1 %cmp1, label %if, label %if - -if: - %val = add i32 %arg1, 1 - br label %then - -then: - %cmp2 = icmp ne i32 %val, %phi - br i1 %cmp2, label %loop, label %end - -end: - ret i32 %val -} - -; Diamond-like control flow but the left/right blocks actually have the same -; destinations. -; TODO: We could potentially hoist all of phi2-4, but currently only hoist phi2. -; CHECK-LABEL: @diamond_like_same_destinations -define i32 @diamond_like_same_destinations(i32 %arg1, i32 %arg2) { -; CHECK-LABEL: entry: -; CHECK-DAG: %cmp1 = icmp ne i32 %arg1, 0 -; CHECK-DAG: %cmp2 = icmp ugt i32 %arg2, 1 -; CHECK-DAG: %cmp3 = icmp ugt i32 %arg2, 2 -; CHECK: br i1 %cmp1, label %[[LEFT1_LICM:.*]], label %[[RIGHT1_LICM:.*]] -entry: - br label %loop - -; CHECK: [[LEFT1_LICM]]: -; CHECK: br label %[[LEFT2_LICM:.*]] - -; CHECK: [[RIGHT1_LICM]]: -; CHECK: br label %[[LEFT2_LICM]] - -; CHECK: [[LEFT2_LICM]]: -; CHECK: %phi2 = phi i32 [ 0, %[[LEFT1_LICM]] ], [ 1, %[[RIGHT1_LICM]] ] -; CHECK: br label %loop - -loop: - %phi1 = phi i32 [ 0, %entry ], [ %add, %loopend ] - %add = add i32 %phi1, 1 - %cmp1 = icmp ne i32 %arg1, 0 - br i1 %cmp1, label %left1, label %right1 - -left1: - %cmp2 = icmp ugt i32 %arg2, 1 - br i1 %cmp2, label %left2, label %right2 - -right1: - %cmp3 = icmp ugt i32 %arg2, 2 - br i1 %cmp3, label %left2, label %right2 - -left2: - %phi2 = phi i32 [ 0, %left1 ], [ 1, %right1 ] - br label %loopend - -right2: - %phi3 = phi i32 [ 2, %left1 ], [ 3, %right1 ] - br label %loopend - -loopend: - %phi4 = phi i32 [ %phi2, %left2 ], [ %phi3, %right2 ] - %cmp4 = icmp ne i32 %phi1, 32 - br i1 %cmp4, label %loop, label %end - -end: - ret i32 %phi4 -} - -; A phi with multiple incoming values for the same block due to a branch with -; two destinations that are actually the same. We can't hoist this. -; TODO: This could be hoisted by erasing one of the incoming values. -; CHECK-LABEL: @phi_multiple_values_same_block -define i32 @phi_multiple_values_same_block(i32 %arg) { -; CHECK-LABEL: entry: -; CHECK: %cmp = icmp sgt i32 %arg, 4 -; CHECK-NOT: phi -; CHECK: br label %loop -entry: - br label %loop - -loop: - %cmp = icmp sgt i32 %arg, 4 - br i1 %cmp, label %if, label %then - -if: - br i1 undef, label %then, label %then - -then: - %phi = phi i32 [ %arg, %loop ], [ 1, %if ], [ 1, %if ] - br i1 undef, label %exit, label %loop - -exit: - ret i32 %phi -} diff --git a/llvm/test/Transforms/LoopVectorize/invariant-store-vectorization.ll b/llvm/test/Transforms/LoopVectorize/invariant-store-vectorization.ll index cf1257b8013..cc4c55c3f44 100644 --- a/llvm/test/Transforms/LoopVectorize/invariant-store-vectorization.ll +++ b/llvm/test/Transforms/LoopVectorize/invariant-store-vectorization.ll @@ -266,26 +266,19 @@ for.end: ; preds = %for.body ; variant/invariant values being stored to invariant address. ; test checks that the last element of the phi is extracted and scalar stored ; into the uniform address within the loop. -; Since the condition and the phi is loop invariant, they are LICM'ed before +; Since the condition and the phi is loop invariant, they are LICM'ed after ; vectorization. ; CHECK-LABEL: inv_val_store_to_inv_address_conditional_inv ; CHECK-NEXT: entry: -; CHECK-NEXT: [[B1:%.*]] = bitcast i32* [[B:%.*]] to i8* -; CHECK-NEXT: [[A4:%.*]] = bitcast i32* [[A:%.*]] to i8* ; CHECK-NEXT: [[NTRUNC:%.*]] = trunc i64 [[N:%.*]] to i32 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[NTRUNC]], [[K:%.*]] -; CHECK-NEXT: br i1 [[CMP]], label %[[COND_STORE_LICM:.*]], label %[[COND_STORE_K_LICM:.*]] -; CHECK: [[COND_STORE_LICM]]: -; CHECK-NEXT: br label %[[LATCH_LICM:.*]] -; CHECK: [[COND_STORE_K_LICM]]: -; CHECK-NEXT: br label %[[LATCH_LICM]] -; CHECK: [[LATCH_LICM]]: -; CHECK-NEXT: [[STOREVAL:%.*]] = phi i32 [ [[NTRUNC]], %[[COND_STORE_LICM]] ], [ [[K]], %[[COND_STORE_K_LICM]] ] ; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[N]], 1 ; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP0]], i64 [[N]], i64 1 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[SMAX]], 4 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_MEMCHECK:%.*]] ; CHECK: vector.memcheck: +; CHECK-NEXT: [[A4:%.*]] = bitcast i32* [[A:%.*]] to i8* +; CHECK-NEXT: [[B1:%.*]] = bitcast i32* [[B:%.*]] to i8* ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[N]], 1 ; CHECK-NEXT: [[SMAX2:%.*]] = select i1 [[TMP1]], i64 [[N]], i64 1 ; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i32, i32* [[B]], i64 [[SMAX2]] @@ -298,13 +291,17 @@ for.end: ; preds = %for.body ; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[SMAX]], 9223372036854775804 ; CHECK-NEXT: [[BROADCAST_SPLATINSERT5:%.*]] = insertelement <4 x i32> undef, i32 [[NTRUNC]], i32 0 ; CHECK-NEXT: [[BROADCAST_SPLAT6:%.*]] = shufflevector <4 x i32> [[BROADCAST_SPLATINSERT5]], <4 x i32> undef, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <4 x i1> undef, i1 [[CMP]], i32 3 +; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x i32> undef, i32 [[K]], i32 3 +; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[BROADCAST_SPLAT6]], <4 x i32> [[TMP3]] +; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i32> [[PREDPHI]], i32 3 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[INDEX]] ; CHECK-NEXT: [[TMP7:%.*]] = bitcast i32* [[TMP6]] to <4 x i32>* ; CHECK-NEXT: store <4 x i32> [[BROADCAST_SPLAT6]], <4 x i32>* [[TMP7]], align 4 -; CHECK-NEXT: store i32 [[STOREVAL]], i32* [[A]], align 4 +; CHECK-NEXT: store i32 [[TMP5]], i32* [[A]], align 4 ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] ; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]] @@ -324,6 +321,7 @@ for.end: ; preds = %for.body ; CHECK: cond_store_k: ; CHECK-NEXT: br label [[LATCH]] ; CHECK: latch: +; CHECK-NEXT: [[STOREVAL:%.*]] = phi i32 [ [[NTRUNC]], [[COND_STORE]] ], [ [[K]], [[COND_STORE_K]] ] ; CHECK-NEXT: store i32 [[STOREVAL]], i32* [[A]], align 4 ; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i64 [[I]], 1 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[I_NEXT]], [[N]] |