| ; RUN: opt < %s -basicaa -gvn -enable-load-pre -S | FileCheck %s |
| target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" |
| |
| declare void @llvm.experimental.guard(i1, ...) |
| |
| ; This is a motivating example on why we prohibit hoisting through guards. |
| ; In the bottom block, we check that the index is within bounds and only access |
| ; the element in this case and deoptimize otherwise. If we hoist the load to a |
| ; place above the guard, it will may lead to out-of-bound array access. |
| define i32 @test_motivation(i32* %p, i32* %q, i1 %C, i32 %index, i32 %len) { |
| ; CHECK-LABEL: @test_motivation( |
| block1: |
| %el1 = getelementptr inbounds i32, i32* %q, i32 %index |
| %el2 = getelementptr inbounds i32, i32* %p, i32 %index |
| br i1 %C, label %block2, label %block3 |
| |
| block2: |
| |
| ; CHECK: block2: |
| ; CHECK-NEXT: br |
| ; CHECK-NOT: load |
| ; CHECK-NOT: sge |
| ; CHECK-NOT: slt |
| ; CHECK-NOT: and |
| br label %block4 |
| |
| block3: |
| store i32 0, i32* %el1 |
| br label %block4 |
| |
| block4: |
| |
| ; CHECK: block4: |
| ; CHECK: %cond1 = icmp sge i32 %index, 0 |
| ; CHECK-NEXT: %cond2 = icmp slt i32 %index, %len |
| ; CHECK-NEXT: %in.bounds = and i1 %cond1, %cond2 |
| ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %in.bounds) |
| ; CHECK-NEXT: %PRE = load i32, i32* %P2 |
| ; CHECK: ret i32 %PRE |
| |
| %P2 = phi i32* [%el2, %block3], [%el1, %block2] |
| %cond1 = icmp sge i32 %index, 0 |
| %cond2 = icmp slt i32 %index, %len |
| %in.bounds = and i1 %cond1, %cond2 |
| call void (i1, ...) @llvm.experimental.guard(i1 %in.bounds) [ "deopt"() ] |
| %PRE = load i32, i32* %P2 |
| ret i32 %PRE |
| } |
| |
| ; Guard in load's block that is above the load should prohibit the PRE. |
| define i32 @test_guard_01(i32* %p, i32* %q, i1 %C, i1 %G) { |
| ; CHECK-LABEL: @test_guard_01( |
| block1: |
| br i1 %C, label %block2, label %block3 |
| |
| block2: |
| |
| ; CHECK: block2: |
| ; CHECK-NEXT: br |
| ; CHECK-NOT: load |
| |
| br label %block4 |
| |
| block3: |
| store i32 0, i32* %p |
| br label %block4 |
| |
| block4: |
| |
| ; CHECK: block4: |
| ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %G) |
| ; CHECK-NEXT: load |
| ; CHECK: ret i32 |
| |
| %P2 = phi i32* [%p, %block3], [%q, %block2] |
| call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ] |
| %PRE = load i32, i32* %P2 |
| ret i32 %PRE |
| } |
| |
| ; Guard in load's block that is below the load should not prohibit the PRE. |
| define i32 @test_guard_02(i32* %p, i32* %q, i1 %C, i1 %G) { |
| ; CHECK-LABEL: @test_guard_02( |
| block1: |
| br i1 %C, label %block2, label %block3 |
| |
| block2: |
| |
| ; CHECK: block2: |
| ; CHECK-NEXT: load i32, i32* %q |
| |
| br label %block4 |
| |
| block3: |
| store i32 0, i32* %p |
| br label %block4 |
| |
| block4: |
| |
| ; CHECK: block4: |
| ; CHECK-NEXT: phi i32 [ |
| ; CHECK-NEXT: phi i32* [ |
| ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %G) |
| ; CHECK-NOT: load |
| ; CHECK: ret i32 |
| |
| %P2 = phi i32* [%p, %block3], [%q, %block2] |
| %PRE = load i32, i32* %P2 |
| call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ] |
| ret i32 %PRE |
| } |
| |
| ; Guard above the load's block should prevent PRE from hoisting through it. |
| define i32 @test_guard_03(i32* %p, i32* %q, i1 %C, i1 %G) { |
| ; CHECK-LABEL: @test_guard_03( |
| block1: |
| br i1 %C, label %block2, label %block3 |
| |
| block2: |
| |
| ; CHECK: block2: |
| ; CHECK-NEXT: br |
| ; CHECK-NOT: load |
| |
| br label %block4 |
| |
| block3: |
| store i32 0, i32* %p |
| br label %block4 |
| |
| block4: |
| |
| ; CHECK: block4: |
| ; CHECK-NEXT: phi i32* |
| ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %G) |
| ; CHECK-NEXT: load |
| ; CHECK-NEXT: ret i32 |
| |
| %P2 = phi i32* [%p, %block3], [%q, %block2] |
| call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ] |
| br label %block5 |
| |
| block5: |
| %PRE = load i32, i32* %P2 |
| ret i32 %PRE |
| } |