summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/GuardWidening/basic-loop.ll
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test/Transforms/GuardWidening/basic-loop.ll')
-rw-r--r--llvm/test/Transforms/GuardWidening/basic-loop.ll138
1 files changed, 138 insertions, 0 deletions
diff --git a/llvm/test/Transforms/GuardWidening/basic-loop.ll b/llvm/test/Transforms/GuardWidening/basic-loop.ll
new file mode 100644
index 00000000000..8129a789f33
--- /dev/null
+++ b/llvm/test/Transforms/GuardWidening/basic-loop.ll
@@ -0,0 +1,138 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -loop-guard-widening < %s | FileCheck %s
+; RUN: opt -S -passes="loop(guard-widening)" < %s | FileCheck %s
+
+declare void @llvm.experimental.guard(i1,...)
+
+@G = external global i32
+
+; Show that we can widen into early checks within a loop, and in the process
+; expose optimization oppurtunities.
+define void @widen_within_loop(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
+; CHECK-LABEL: @widen_within_loop(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: store i32 0, i32* @G
+; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2:%.*]]
+; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ]
+; CHECK-NEXT: store i32 1, i32* @G
+; CHECK-NEXT: store i32 2, i32* @G
+; CHECK-NEXT: store i32 3, i32* @G
+; CHECK-NEXT: br label [[LOOP]]
+;
+entry:
+ br label %loop
+
+loop:
+ store i32 0, i32* @G
+ call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
+ store i32 1, i32* @G
+ call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"(i32 1) ]
+ store i32 2, i32* @G
+ call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
+ store i32 3, i32* @G
+ br label %loop
+}
+
+define void @widen_into_preheader(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
+; CHECK-LABEL: @widen_into_preheader(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: store i32 0, i32* @G
+; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2:%.*]]
+; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ]
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: store i32 1, i32* @G
+; CHECK-NEXT: store i32 2, i32* @G
+; CHECK-NEXT: store i32 3, i32* @G
+; CHECK-NEXT: br label [[LOOP]]
+;
+entry:
+ store i32 0, i32* @G
+ call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
+ br label %loop
+
+loop:
+ store i32 1, i32* @G
+ call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"(i32 1) ]
+ store i32 2, i32* @G
+ call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
+ store i32 3, i32* @G
+ br label %loop
+}
+
+define void @dont_widen_over_common_exit(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
+; CHECK-LABEL: @dont_widen_over_common_exit(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: store i32 0, i32* @G
+; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"(i32 0) ]
+; CHECK-NEXT: store i32 1, i32* @G
+; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[BACKEDGE:%.*]], label [[EXIT:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: store i32 2, i32* @G
+; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_2:%.*]]) [ "deopt"(i32 2) ]
+; CHECK-NEXT: store i32 3, i32* @G
+; CHECK-NEXT: br label [[LOOP]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %loop
+
+loop:
+ store i32 0, i32* @G
+ call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
+ store i32 1, i32* @G
+ br i1 %cond_1, label %backedge, label %exit
+
+backedge:
+ store i32 2, i32* @G
+ call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
+ store i32 3, i32* @G
+ br label %loop
+
+exit:
+ ret void
+}
+
+define void @widen_over_common_exit_to_ph(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
+; CHECK-LABEL: @widen_over_common_exit_to_ph(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: store i32 0, i32* @G
+; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_2:%.*]]
+; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"(i32 0) ]
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: store i32 1, i32* @G
+; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[BACKEDGE:%.*]], label [[EXIT:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: store i32 2, i32* @G
+; CHECK-NEXT: store i32 3, i32* @G
+; CHECK-NEXT: br label [[LOOP]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ store i32 0, i32* @G
+ call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
+ br label %loop
+
+loop:
+ store i32 1, i32* @G
+ br i1 %cond_1, label %backedge, label %exit
+
+backedge:
+ store i32 2, i32* @G
+ call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
+ store i32 3, i32* @G
+ br label %loop
+
+exit:
+ ret void
+}
+
OpenPOWER on IntegriCloud