| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: opt < %s -passes='logical-sroa' -S | FileCheck %s --check-prefixes=CHECK |
| |
| declare void @llvm.lifetime.start.p0(ptr nocapture) |
| declare void @llvm.lifetime.end.p0(ptr nocapture) |
| declare ptr @llvm.structured.alloca.p0() |
| declare ptr @llvm.structured.gep.p0(ptr, ...) |
| declare void @foo(ptr) |
| |
| ; The alloca ptr is escaping, we cannot know if splitting is safe. |
| define i32 @test_simple_escape() { |
| ; CHECK-LABEL: define i32 @test_simple_escape() { |
| ; CHECK-NEXT: [[ENTRY:.*:]] |
| ; CHECK-NEXT: [[TMP:%.*]] = call elementtype({ i32, i32 }) ptr @llvm.structured.alloca.p0() |
| ; CHECK-NEXT: [[PTR0:%.*]] = call ptr (ptr, ...) @llvm.structured.gep.p0(ptr elementtype({ i32, i32 }) [[TMP]], i32 0) |
| ; CHECK-NEXT: [[PTR1:%.*]] = call ptr (ptr, ...) @llvm.structured.gep.p0(ptr elementtype({ i32, i32 }) [[TMP]], i32 1) |
| ; CHECK-NEXT: store i32 0, ptr [[PTR0]], align 4 |
| ; CHECK-NEXT: store i32 1, ptr [[PTR1]], align 4 |
| ; CHECK-NEXT: call void @foo(ptr [[TMP]]) |
| ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[PTR0]], align 4 |
| ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[PTR1]], align 4 |
| ; CHECK-NEXT: [[RES:%.*]] = add i32 [[A]], [[B]] |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %tmp = call elementtype({ i32, i32 }) ptr @llvm.structured.alloca.p0() |
| |
| %ptr0 = call ptr (ptr, ...) @llvm.structured.gep.p0(ptr elementtype({ i32, i32 }) %tmp, i32 0) |
| %ptr1 = call ptr (ptr, ...) @llvm.structured.gep.p0(ptr elementtype({ i32, i32 }) %tmp, i32 1) |
| |
| store i32 0, ptr %ptr0 |
| store i32 1, ptr %ptr1 |
| |
| call void @foo(ptr %tmp) |
| |
| %a = load i32, ptr %ptr0 |
| %b = load i32, ptr %ptr1 |
| %res = add i32 %a, %b |
| ret i32 %res |
| } |
| |
| define i32 @test_derived_escape() { |
| ; CHECK-LABEL: define i32 @test_derived_escape() { |
| ; CHECK-NEXT: [[ENTRY:.*:]] |
| ; CHECK-NEXT: [[TMP:%.*]] = call elementtype({ i32, i32 }) ptr @llvm.structured.alloca.p0() |
| ; CHECK-NEXT: [[PTR0:%.*]] = call ptr (ptr, ...) @llvm.structured.gep.p0(ptr elementtype({ i32, i32 }) [[TMP]], i32 0) |
| ; CHECK-NEXT: [[PTR1:%.*]] = call ptr (ptr, ...) @llvm.structured.gep.p0(ptr elementtype({ i32, i32 }) [[TMP]], i32 1) |
| ; CHECK-NEXT: store i32 0, ptr [[PTR0]], align 4 |
| ; CHECK-NEXT: store i32 1, ptr [[PTR1]], align 4 |
| ; CHECK-NEXT: call void @foo(ptr [[PTR0]]) |
| ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[PTR0]], align 4 |
| ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[PTR1]], align 4 |
| ; CHECK-NEXT: [[RES:%.*]] = add i32 [[A]], [[B]] |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %tmp = call elementtype({ i32, i32 }) ptr @llvm.structured.alloca.p0() |
| |
| %ptr0 = call ptr (ptr, ...) @llvm.structured.gep.p0(ptr elementtype({ i32, i32 }) %tmp, i32 0) |
| %ptr1 = call ptr (ptr, ...) @llvm.structured.gep.p0(ptr elementtype({ i32, i32 }) %tmp, i32 1) |
| |
| store i32 0, ptr %ptr0 |
| store i32 1, ptr %ptr1 |
| |
| call void @foo(ptr %ptr0) |
| |
| %a = load i32, ptr %ptr0 |
| %b = load i32, ptr %ptr1 |
| %res = add i32 %a, %b |
| ret i32 %res |
| } |
| |
| ; A normal ptradd/gep is used, we cannot know if splitting this alloca is safe. |
| define i32 @test_normal_gep() { |
| ; CHECK-LABEL: define i32 @test_normal_gep() { |
| ; CHECK-NEXT: [[ENTRY:.*:]] |
| ; CHECK-NEXT: [[TMP:%.*]] = call elementtype({ i32, i32 }) ptr @llvm.structured.alloca.p0() |
| ; CHECK-NEXT: [[PTR0:%.*]] = call ptr (ptr, ...) @llvm.structured.gep.p0(ptr elementtype({ i32, i32 }) [[TMP]], i32 0) |
| ; CHECK-NEXT: [[PTR1:%.*]] = getelementptr i8, ptr [[PTR0]], i32 4 |
| ; CHECK-NEXT: store i32 0, ptr [[PTR0]], align 4 |
| ; CHECK-NEXT: store i32 1, ptr [[PTR1]], align 4 |
| ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[PTR0]], align 4 |
| ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[PTR1]], align 4 |
| ; CHECK-NEXT: [[RES:%.*]] = add i32 [[A]], [[B]] |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %tmp = call elementtype({ i32, i32 }) ptr @llvm.structured.alloca.p0() |
| |
| %ptr0 = call ptr (ptr, ...) @llvm.structured.gep.p0(ptr elementtype({ i32, i32 }) %tmp, i32 0) |
| %ptr1 = getelementptr i8, ptr %ptr0, i32 4 |
| |
| store i32 0, ptr %ptr0 |
| store i32 1, ptr %ptr1 |
| |
| %a = load i32, ptr %ptr0 |
| %b = load i32, ptr %ptr1 |
| %res = add i32 %a, %b |
| ret i32 %res |
| } |