| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -O3 -S | FileCheck %s |
| ; RUN: opt < %s -passes='default<O3>' -S | FileCheck %s |
| |
| ; This is based on the following most basic C++ code: |
| ; |
| ; struct S { |
| ; int* data; |
| ; int x, y, z; |
| ; }; |
| ; |
| ; S gen(S a) { |
| ; S b; |
| ; b.data = a.data; |
| ; return b; |
| ; } |
| ; |
| ; void escape0(S); |
| ; |
| ; int* foo(S a) { |
| ; S b = gen(a); |
| ; escape0(b); |
| ; return b.data; |
| ; } |
| ; |
| ; int cond(); |
| ; void sync0(); |
| ; void sync1(); |
| ; void escape0(int*); |
| ; void escape1(int*); |
| ; |
| ; int* bar(S a) { |
| ; S b = gen(a); |
| ; if(cond()) { |
| ; sync0(); |
| ; escape0(b.data); |
| ; } else { |
| ; sync1(); |
| ; escape1(b.data); |
| ; } |
| ; return b.data; |
| ; } |
| ; |
| ; There are no inttoptr casts in the original source code, nor should there be any in the optimized IR. |
| |
| target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" |
| |
| %0 = type { ptr, i32, i32, i32 } |
| |
| define dso_local void @_Z3gen1S(ptr noalias sret(%0) align 8 %arg, ptr byval(%0) align 8 %arg1) { |
| ; CHECK-LABEL: @_Z3gen1S( |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[I2:%.*]] = load ptr, ptr [[ARG1:%.*]], align 8 |
| ; CHECK-NEXT: store ptr [[I2]], ptr [[ARG:%.*]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| bb: |
| %i2 = load ptr, ptr %arg1, align 8 |
| store ptr %i2, ptr %arg, align 8 |
| ret void |
| } |
| |
| define dso_local ptr @_Z3foo1S(ptr byval(%0) align 8 %arg) { |
| ; CHECK-LABEL: @_Z3foo1S( |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[I2:%.*]] = alloca [[TMP0:%.*]], align 8 |
| ; CHECK-NEXT: [[I1_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[ARG:%.*]], align 8 |
| ; CHECK-NEXT: store ptr [[I1_SROA_0_0_COPYLOAD]], ptr [[I2]], align 8 |
| ; CHECK-NEXT: tail call void @_Z7escape01S(ptr nonnull byval([[TMP0]]) align 8 [[I2]]) |
| ; CHECK-NEXT: ret ptr [[I1_SROA_0_0_COPYLOAD]] |
| ; |
| bb: |
| %i = alloca %0, align 8 |
| %i1 = alloca %0, align 8 |
| %i2 = alloca %0, align 8 |
| call void @llvm.lifetime.start.p0(i64 24, ptr %i) |
| call void @llvm.memcpy.p0.p0.i64(ptr align 8 %i1, ptr align 8 %arg, i64 24, i1 false) |
| call void @_Z3gen1S(ptr sret(%0) align 8 %i, ptr byval(%0) align 8 %i1) |
| call void @llvm.memcpy.p0.p0.i64(ptr align 8 %i2, ptr align 8 %i, i64 24, i1 false) |
| call void @_Z7escape01S(ptr byval(%0) align 8 %i2) |
| %i9 = load ptr, ptr %i, align 8 |
| call void @llvm.lifetime.end.p0(i64 24, ptr %i) |
| ret ptr %i9 |
| } |
| |
| declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) |
| |
| declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) |
| |
| declare dso_local void @_Z7escape01S(ptr byval(%0) align 8) |
| |
| declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) |
| |
| define dso_local ptr @_Z3bar1S(ptr byval(%0) align 8 %arg) { |
| ; CHECK-LABEL: @_Z3bar1S( |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[I1_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[ARG:%.*]], align 8 |
| ; CHECK-NEXT: [[I5:%.*]] = tail call i32 @_Z4condv() |
| ; CHECK-NEXT: [[I6_NOT:%.*]] = icmp eq i32 [[I5]], 0 |
| ; CHECK-NEXT: br i1 [[I6_NOT]], label [[BB10:%.*]], label [[BB7:%.*]] |
| ; CHECK: bb7: |
| ; CHECK-NEXT: tail call void @_Z5sync0v() |
| ; CHECK-NEXT: tail call void @_Z7escape0Pi(ptr [[I1_SROA_0_0_COPYLOAD]]) |
| ; CHECK-NEXT: br label [[BB13:%.*]] |
| ; CHECK: bb10: |
| ; CHECK-NEXT: tail call void @_Z5sync1v() |
| ; CHECK-NEXT: tail call void @_Z7escape1Pi(ptr [[I1_SROA_0_0_COPYLOAD]]) |
| ; CHECK-NEXT: br label [[BB13]] |
| ; CHECK: bb13: |
| ; CHECK-NEXT: ret ptr [[I1_SROA_0_0_COPYLOAD]] |
| ; |
| bb: |
| %i = alloca %0, align 8 |
| %i1 = alloca %0, align 8 |
| call void @llvm.lifetime.start.p0(i64 24, ptr %i) |
| call void @llvm.memcpy.p0.p0.i64(ptr align 8 %i1, ptr align 8 %arg, i64 24, i1 false) |
| call void @_Z3gen1S(ptr sret(%0) align 8 %i, ptr byval(%0) align 8 %i1) |
| %i5 = call i32 @_Z4condv() |
| %i6 = icmp ne i32 %i5, 0 |
| br i1 %i6, label %bb7, label %bb10 |
| |
| bb7: |
| call void @_Z5sync0v() |
| %i9 = load ptr, ptr %i, align 8 |
| call void @_Z7escape0Pi(ptr %i9) |
| br label %bb13 |
| |
| bb10: |
| call void @_Z5sync1v() |
| %i12 = load ptr, ptr %i, align 8 |
| call void @_Z7escape1Pi(ptr %i12) |
| br label %bb13 |
| |
| bb13: |
| %i15 = load ptr, ptr %i, align 8 |
| call void @llvm.lifetime.end.p0(i64 24, ptr %i) |
| ret ptr %i15 |
| } |
| |
| declare dso_local i32 @_Z4condv() |
| declare dso_local void @_Z5sync0v() |
| declare dso_local void @_Z7escape0Pi(ptr) |
| declare dso_local void @_Z5sync1v() |
| declare dso_local void @_Z7escape1Pi(ptr) |