| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -inline -o - -S %s | FileCheck %s |
| ; RUN: opt -passes='cgscc(inline)' %s -S | FileCheck %s |
| ; RUN: opt -always-inline -o - -S %s | FileCheck %s |
| ; RUN: opt -passes=always-inline -o - -S %s | FileCheck %s |
| |
| declare dso_local void @foo(i8*) |
| |
| ; Not interesting to test. |
| define dso_local void @ssp(i64 %0) #0 { |
| %2 = alloca i64, align 8 |
| store i64 %0, i64* %2, align 8 |
| %3 = load i64, i64* %2, align 8 |
| %4 = alloca i8, i64 %3, align 16 |
| call void @foo(i8* %4) |
| ret void |
| } |
| |
| ; Not interesting to test. |
| define dso_local void @ssp_alwaysinline(i64 %0) #1 { |
| %2 = alloca i64, align 8 |
| store i64 %0, i64* %2, align 8 |
| %3 = load i64, i64* %2, align 8 |
| %4 = alloca i8, i64 %3, align 16 |
| call void @foo(i8* %4) |
| ret void |
| } |
| |
| ; @ssp should not be inlined due to mismatch stack protector. |
| ; @ssp_alwaysinline should be inlined due to alwaysinline. |
| define dso_local void @nossp() { |
| ; CHECK-LABEL: @nossp( |
| ; CHECK-NEXT: [[TMP1:%.*]] = alloca i64, align 8 |
| ; CHECK-NEXT: call void @ssp(i64 1024) |
| ; CHECK-NEXT: [[SAVEDSTACK:%.*]] = call i8* @llvm.stacksave() |
| ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64* [[TMP1]] to i8* |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[TMP2]]) |
| ; CHECK-NEXT: store i64 1024, i64* [[TMP1]], align 8 |
| ; CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[TMP1]], align 8 |
| ; CHECK-NEXT: [[TMP4:%.*]] = alloca i8, i64 [[TMP3]], align 16 |
| ; CHECK-NEXT: call void @foo(i8* [[TMP4]]) |
| ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i64* [[TMP1]] to i8* |
| ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[TMP5]]) |
| ; CHECK-NEXT: call void @llvm.stackrestore(i8* [[SAVEDSTACK]]) |
| ; CHECK-NEXT: ret void |
| ; |
| call void @ssp(i64 1024) |
| call void @ssp_alwaysinline(i64 1024) |
| ret void |
| } |
| |
| ; This is the same case as @nossp above. That the caller has alwaysinline is |
| ; irrelevant. Not interesting to test. |
| define dso_local void @nossp_alwaysinline() #2 { |
| call void @ssp(i64 1024) |
| call void @ssp_alwaysinline(i64 1024) |
| ret void |
| } |
| |
| ; @nossp_alwaysinline should be inlined due to alwaysinline. |
| ; @ssp should not be inlined due to mismatch stack protector. |
| ; @ssp_alwaysinline should be inlined due to alwaysinline. |
| define dso_local void @nossp_caller() { |
| ; CHECK-LABEL: @nossp_caller( |
| ; CHECK-NEXT: [[TMP1:%.*]] = alloca i64, align 8 |
| ; CHECK-NEXT: [[SAVEDSTACK:%.*]] = call i8* @llvm.stacksave() |
| ; CHECK-NEXT: call void @ssp(i64 1024) |
| ; CHECK-NEXT: [[SAVEDSTACK_I:%.*]] = call i8* @llvm.stacksave() |
| ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64* [[TMP1]] to i8* |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[TMP2]]) |
| ; CHECK-NEXT: store i64 1024, i64* [[TMP1]], align 8 |
| ; CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[TMP1]], align 8 |
| ; CHECK-NEXT: [[TMP4:%.*]] = alloca i8, i64 [[TMP3]], align 16 |
| ; CHECK-NEXT: call void @foo(i8* [[TMP4]]) |
| ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i64* [[TMP1]] to i8* |
| ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[TMP5]]) |
| ; CHECK-NEXT: call void @llvm.stackrestore(i8* [[SAVEDSTACK_I]]) |
| ; CHECK-NEXT: call void @llvm.stackrestore(i8* [[SAVEDSTACK]]) |
| ; CHECK-NEXT: ret void |
| ; |
| call void @nossp_alwaysinline() |
| ret void |
| } |
| |
| ; @nossp should not be inlined due to mismatch stack protector. |
| define dso_local void @ssp2() #0 { |
| ; CHECK-LABEL: @ssp2( |
| ; CHECK-NEXT: call void @nossp() |
| ; CHECK-NEXT: ret void |
| ; |
| call void @nossp() |
| ret void |
| } |
| |
| attributes #0 = { sspstrong } |
| attributes #1 = { sspstrong alwaysinline } |
| attributes #2 = { alwaysinline} |