| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals | |
| ; RUN: opt -S -sroa-skip-mem2reg -passes='sroa<preserve-cfg>' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG | |
| ; RUN: opt -S -sroa-skip-mem2reg -passes='sroa<modify-cfg>' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG | |
| %pair = type { i32, i32 } | |
| define void @store_to_phi(i1 %cond, i32 %value) { | |
| ; CHECK-LABEL: @store_to_phi( | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] | |
| ; CHECK: left: | |
| ; CHECK-NEXT: store i32 [[VALUE:%.*]], ptr [[A]], align 4 | |
| ; CHECK-NEXT: br label [[MERGE:%.*]] | |
| ; CHECK: right: | |
| ; CHECK-NEXT: store i32 [[VALUE]], ptr [[B]], align 4 | |
| ; CHECK-NEXT: br label [[MERGE]] | |
| ; CHECK: merge: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| %a = alloca i32, align 4 | |
| %b = alloca i32, align 4 | |
| br i1 %cond, label %left, label %right | |
| left: | |
| br label %merge | |
| right: | |
| br label %merge | |
| merge: | |
| %ptr = phi ptr [ %a, %left ], [ %b, %right ] | |
| store i32 %value, ptr %ptr, align 4 | |
| ret void | |
| } | |
| define void @store_to_phi_alloca_and_argument(i1 %cond, i32 %value, ptr %other) { | |
| ; CHECK-LABEL: @store_to_phi_alloca_and_argument( | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] | |
| ; CHECK: left: | |
| ; CHECK-NEXT: store i32 [[VALUE:%.*]], ptr [[A]], align 4 | |
| ; CHECK-NEXT: br label [[MERGE:%.*]] | |
| ; CHECK: right: | |
| ; CHECK-NEXT: store i32 [[VALUE]], ptr [[OTHER:%.*]], align 4 | |
| ; CHECK-NEXT: br label [[MERGE]] | |
| ; CHECK: merge: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| %a = alloca i32, align 4 | |
| br i1 %cond, label %left, label %right | |
| left: | |
| br label %merge | |
| right: | |
| br label %merge | |
| merge: | |
| %ptr = phi ptr [ %a, %left ], [ %other, %right ] | |
| store i32 %value, ptr %ptr, align 4 | |
| ret void | |
| } | |
| define void @store_to_phi_split_edge(i1 %cond, i1 %other_cond, i32 %value) { | |
| ; CHECK-PRESERVE-CFG-LABEL: @store_to_phi_split_edge( | |
| ; CHECK-PRESERVE-CFG-NEXT: entry: | |
| ; CHECK-PRESERVE-CFG-NEXT: [[A:%.*]] = alloca i32, align 4 | |
| ; CHECK-PRESERVE-CFG-NEXT: [[B:%.*]] = alloca i32, align 4 | |
| ; CHECK-PRESERVE-CFG-NEXT: br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] | |
| ; CHECK-PRESERVE-CFG: left: | |
| ; CHECK-PRESERVE-CFG-NEXT: br label [[MERGE:%.*]] | |
| ; CHECK-PRESERVE-CFG: right: | |
| ; CHECK-PRESERVE-CFG-NEXT: br i1 [[OTHER_COND:%.*]], label [[MERGE]], label [[EXIT:%.*]] | |
| ; CHECK-PRESERVE-CFG: merge: | |
| ; CHECK-PRESERVE-CFG-NEXT: [[PTR:%.*]] = phi ptr [ [[A]], [[LEFT]] ], [ [[B]], [[RIGHT]] ] | |
| ; CHECK-PRESERVE-CFG-NEXT: store i32 [[VALUE:%.*]], ptr [[PTR]], align 4 | |
| ; CHECK-PRESERVE-CFG-NEXT: br label [[EXIT]] | |
| ; CHECK-PRESERVE-CFG: exit: | |
| ; CHECK-PRESERVE-CFG-NEXT: ret void | |
| ; | |
| ; CHECK-MODIFY-CFG-LABEL: @store_to_phi_split_edge( | |
| ; CHECK-MODIFY-CFG-NEXT: entry: | |
| ; CHECK-MODIFY-CFG-NEXT: [[A:%.*]] = alloca i32, align 4 | |
| ; CHECK-MODIFY-CFG-NEXT: [[B:%.*]] = alloca i32, align 4 | |
| ; CHECK-MODIFY-CFG-NEXT: br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] | |
| ; CHECK-MODIFY-CFG: left: | |
| ; CHECK-MODIFY-CFG-NEXT: store i32 [[VALUE:%.*]], ptr [[A]], align 4 | |
| ; CHECK-MODIFY-CFG-NEXT: br label [[MERGE:%.*]] | |
| ; CHECK-MODIFY-CFG: right: | |
| ; CHECK-MODIFY-CFG-NEXT: br i1 [[OTHER_COND:%.*]], label [[MERGE_SROA_STORE:%.*]], label [[EXIT:%.*]] | |
| ; CHECK-MODIFY-CFG: merge.sroa.store: | |
| ; CHECK-MODIFY-CFG-NEXT: store i32 [[VALUE]], ptr [[B]], align 4 | |
| ; CHECK-MODIFY-CFG-NEXT: br label [[MERGE]] | |
| ; CHECK-MODIFY-CFG: merge: | |
| ; CHECK-MODIFY-CFG-NEXT: br label [[EXIT]] | |
| ; CHECK-MODIFY-CFG: exit: | |
| ; CHECK-MODIFY-CFG-NEXT: ret void | |
| ; | |
| entry: | |
| %a = alloca i32, align 4 | |
| %b = alloca i32, align 4 | |
| br i1 %cond, label %left, label %right | |
| left: | |
| br label %merge | |
| right: | |
| br i1 %other_cond, label %merge, label %exit | |
| merge: | |
| %ptr = phi ptr [ %a, %left ], [ %b, %right ] | |
| store i32 %value, ptr %ptr, align 4 | |
| br label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @store_to_phi_value_phi(i1 %cond) { | |
| ; CHECK-LABEL: @store_to_phi_value_phi( | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] | |
| ; CHECK: left: | |
| ; CHECK-NEXT: br label [[MERGE:%.*]] | |
| ; CHECK: right: | |
| ; CHECK-NEXT: br label [[MERGE]] | |
| ; CHECK: merge: | |
| ; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[A]], [[LEFT]] ], [ [[B]], [[RIGHT]] ] | |
| ; CHECK-NEXT: [[VALUE:%.*]] = phi i32 [ 1, [[LEFT]] ], [ 2, [[RIGHT]] ] | |
| ; CHECK-NEXT: store i32 [[VALUE]], ptr [[PTR]], align 4 | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| %a = alloca i32, align 4 | |
| %b = alloca i32, align 4 | |
| br i1 %cond, label %left, label %right | |
| left: | |
| br label %merge | |
| right: | |
| br label %merge | |
| merge: | |
| %ptr = phi ptr [ %a, %left ], [ %b, %right ] | |
| %value = phi i32 [ 1, %left ], [ 2, %right ] | |
| store i32 %value, ptr %ptr, align 4 | |
| ret void | |
| } | |
| define void @store_to_phi_of_geps(i1 %cond, i32 %value) { | |
| ; CHECK-LABEL: @store_to_phi_of_geps( | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: [[B_SROA_0:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] | |
| ; CHECK: left: | |
| ; CHECK-NEXT: store i32 [[VALUE:%.*]], ptr [[A_SROA_0]], align 4 | |
| ; CHECK-NEXT: br label [[MERGE:%.*]] | |
| ; CHECK: right: | |
| ; CHECK-NEXT: store i32 [[VALUE]], ptr [[B_SROA_0]], align 4 | |
| ; CHECK-NEXT: br label [[MERGE]] | |
| ; CHECK: merge: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| %a = alloca %pair, align 4 | |
| %b = alloca %pair, align 4 | |
| br i1 %cond, label %left, label %right | |
| left: | |
| br label %merge | |
| right: | |
| br label %merge | |
| merge: | |
| %ptr = phi ptr [ %a, %left ], [ %b, %right ] | |
| %field = getelementptr inbounds %pair, ptr %ptr, i32 0, i32 1 | |
| store i32 %value, ptr %field, align 4 | |
| ret void | |
| } | |
| define void @store_atomic_to_phi(i1 %cond, i32 %value, ptr %other) { | |
| ; CHECK-LABEL: @store_atomic_to_phi( | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] | |
| ; CHECK: left: | |
| ; CHECK-NEXT: store i32 [[VALUE:%.*]], ptr [[A]], align 4 | |
| ; CHECK-NEXT: br label [[MERGE:%.*]] | |
| ; CHECK: right: | |
| ; CHECK-NEXT: store atomic i32 [[VALUE]], ptr [[OTHER:%.*]] seq_cst, align 4 | |
| ; CHECK-NEXT: br label [[MERGE]] | |
| ; CHECK: merge: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| %a = alloca i32, align 4 | |
| br i1 %cond, label %left, label %right | |
| left: | |
| br label %merge | |
| right: | |
| br label %merge | |
| merge: | |
| %ptr = phi ptr [ %a, %left ], [ %other, %right ] | |
| store atomic i32 %value, ptr %ptr seq_cst, align 4 | |
| ret void | |
| } | |
| define void @store_atomic_volatile_to_phi(i1 %cond, i32 %value, ptr %other) { | |
| ; CHECK-LABEL: @store_atomic_volatile_to_phi( | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 | |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] | |
| ; CHECK: left: | |
| ; CHECK-NEXT: br label [[MERGE:%.*]] | |
| ; CHECK: right: | |
| ; CHECK-NEXT: br label [[MERGE]] | |
| ; CHECK: merge: | |
| ; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[A]], [[LEFT]] ], [ [[OTHER:%.*]], [[RIGHT]] ] | |
| ; CHECK-NEXT: store atomic volatile i32 [[VALUE:%.*]], ptr [[PTR]] seq_cst, align 4 | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| %a = alloca i32, align 4 | |
| br i1 %cond, label %left, label %right | |
| left: | |
| br label %merge | |
| right: | |
| br label %merge | |
| merge: | |
| %ptr = phi ptr [ %a, %left ], [ %other, %right ] | |
| store atomic volatile i32 %value, ptr %ptr seq_cst, align 4 | |
| ret void | |
| } |