| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -passes=bpf-ir-peephole -mtriple=bpf-pc-linux -S %s | FileCheck %s |
| ; Source: |
| ; #define AA 40 |
| ; struct t { |
| ; char a[20]; |
| ; }; |
| ; void foo(ptr); |
| ; |
| ; int test1() { |
| ; const int a = 8; |
| ; char tmp[AA + sizeof(struct t) + a]; |
| ; foo(tmp); |
| ; return 0; |
| ; } |
| ; |
| ; int test2(int b) { |
| ; const int a = 8; |
| ; char tmp[a + b]; |
| ; foo(tmp); |
| ; return 0; |
| ; } |
| ; Compilation flag: |
| ; clang -target bpf -O2 -S -emit-llvm t.c -Xclang -disable-llvm-passes |
| |
| source_filename = "t.c" |
| target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" |
| target triple = "bpf" |
| |
| ; Function Attrs: nounwind |
| define dso_local i32 @test1() { |
| ; CHECK-LABEL: @test1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align 8 |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[A]]) |
| ; CHECK-NEXT: store i32 8, ptr [[A]], align 4 |
| ; CHECK-NEXT: [[VLA:%.*]] = alloca i8, i64 68, align 1 |
| ; CHECK-NEXT: call void @foo(ptr [[VLA]]) |
| ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[A]]) |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| entry: |
| %a = alloca i32, align 4 |
| %saved_stack = alloca ptr, align 8 |
| call void @llvm.lifetime.start.p0(i64 4, ptr %a) |
| store i32 8, ptr %a, align 4 |
| %0 = call ptr @llvm.stacksave() |
| store ptr %0, ptr %saved_stack, align 8 |
| %vla = alloca i8, i64 68, align 1 |
| call void @foo(ptr %vla) |
| %1 = load ptr, ptr %saved_stack, align 8 |
| call void @llvm.stackrestore(ptr %1) |
| call void @llvm.lifetime.end.p0(i64 4, ptr %a) |
| ret i32 0 |
| } |
| |
| declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) |
| |
| declare ptr @llvm.stacksave() |
| |
| declare dso_local void @foo(ptr) |
| |
| declare void @llvm.stackrestore(ptr) |
| |
| declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) |
| |
| define dso_local i32 @test2(i32 %b) { |
| ; CHECK-LABEL: @test2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align 8 |
| ; CHECK-NEXT: [[__VLA_EXPR0:%.*]] = alloca i64, align 8 |
| ; CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[A]]) |
| ; CHECK-NEXT: store i32 8, ptr [[A]], align 4 |
| ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 |
| ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 8, [[TMP1]] |
| ; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[ADD]] to i64 |
| ; CHECK-NEXT: [[VLA:%.*]] = alloca i8, i64 [[TMP2]], align 1 |
| ; CHECK-NEXT: store i64 [[TMP2]], ptr [[__VLA_EXPR0]], align 8 |
| ; CHECK-NEXT: call void @foo(ptr [[VLA]]) |
| ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[A]]) |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| entry: |
| %b.addr = alloca i32, align 4 |
| %a = alloca i32, align 4 |
| %saved_stack = alloca ptr, align 8 |
| %__vla_expr0 = alloca i64, align 8 |
| store i32 %b, ptr %b.addr, align 4 |
| call void @llvm.lifetime.start.p0(i64 4, ptr %a) |
| store i32 8, ptr %a, align 4 |
| %0 = load i32, ptr %b.addr, align 4 |
| %add = add nsw i32 8, %0 |
| %1 = zext i32 %add to i64 |
| %2 = call ptr @llvm.stacksave() |
| store ptr %2, ptr %saved_stack, align 8 |
| %vla = alloca i8, i64 %1, align 1 |
| store i64 %1, ptr %__vla_expr0, align 8 |
| call void @foo(ptr %vla) |
| %3 = load ptr, ptr %saved_stack, align 8 |
| call void @llvm.stackrestore(ptr %3) |
| call void @llvm.lifetime.end.p0(i64 4, ptr %a) |
| ret i32 0 |
| } |