| ; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp,+relax,+c \ |
| ; RUN: < %s | FileCheck %s --check-prefixes=CHECK |
| ; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp,+relax,+c \ |
| ; RUN: < %s | FileCheck %s --check-prefixes=CHECK |
| ; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp,+relax,+zcmt \ |
| ; RUN: < %s | FileCheck %s --check-prefixes=CHECK |
| ; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp,-relax,+c \ |
| ; RUN: < %s | FileCheck %s --check-prefixes=NORELAX |
| ; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp,+relax,-c \ |
| ; RUN: < %s | FileCheck %s --check-prefixes=NOZCA |
| ; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp,+relax,+c \ |
| ; RUN: -riscv-landing-pad-label=1 < %s | FileCheck %s --check-prefixes=LABEL1 |
| |
| ; Verify that object file output does not have R_RISCV_RELAX on the setjmp call. |
| ; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp,+relax,+c \ |
| ; RUN: -filetype=obj -o - < %s | llvm-readobj -r - | FileCheck %s --check-prefix=RELOC |
| ; setjmp call: R_RISCV_CALL_PLT followed by regular_func (no R_RISCV_RELAX in between) |
| ; regular_func call: R_RISCV_CALL_PLT followed by R_RISCV_RELAX |
| ; RELOC: R_RISCV_CALL_PLT setjmp |
| ; RELOC-NEXT: R_RISCV_CALL_PLT regular_func |
| ; RELOC-NEXT: R_RISCV_RELAX |
| |
| ; Test that returns_twice calls (e.g., setjmp) are wrapped with .option push/exact/pop |
| ; when Zicfilp + relax are enabled, to prevent LPAD misalignment. |
| |
| declare i32 @setjmp(ptr) returns_twice |
| declare i32 @regular_func(ptr) |
| |
| define i32 @test_setjmp() { |
| ; CHECK-LABEL: test_setjmp: |
| ; CHECK: .p2align 2 |
| ; CHECK-NEXT: .option push |
| ; CHECK-NEXT: .option exact |
| ; CHECK-NEXT: call setjmp |
| ; CHECK-NEXT: .option pop |
| ; CHECK-NEXT: lpad 0 |
| ; |
| ; Without relax, only .p2align 2 is needed. |
| ; NORELAX-LABEL: test_setjmp: |
| ; NORELAX-NOT: .option push |
| ; NORELAX-NOT: .option exact |
| ; NORELAX: .p2align 2 |
| ; NORELAX-NEXT: call setjmp |
| ; NORELAX-NEXT: lpad 0 |
| ; |
| ; Without Zca, no .p2align or .option push/exact needed (no compressed calls). |
| ; NOZCA-LABEL: test_setjmp: |
| ; NOZCA-NOT: .p2align 2 |
| ; NOZCA-NOT: .option push |
| ; NOZCA-NOT: .option exact |
| ; NOZCA: call setjmp |
| ; NOZCA-NEXT: lpad 0 |
| ; |
| ; With -riscv-landing-pad-label=1, lpad uses label 1. |
| ; LABEL1-LABEL: test_setjmp: |
| ; LABEL1: call setjmp |
| ; LABEL1: lpad 1 |
| %buf = alloca [1 x i32], align 4 |
| %call = call i32 @setjmp(ptr %buf) |
| ret i32 %call |
| } |
| |
| ; Regular calls should not be affected. |
| define i32 @test_regular_call() { |
| ; CHECK-LABEL: test_regular_call: |
| ; CHECK-NOT: .option exact |
| ; CHECK: call regular_func |
| %buf = alloca [1 x i32], align 4 |
| %call = call i32 @regular_func(ptr %buf) |
| ret i32 %call |
| } |
| |
| ; Indirect calls with returns_twice attribute also get the same treatment. |
| define i32 @test_indirect_returns_twice(ptr %fptr) { |
| ; CHECK-LABEL: test_indirect_returns_twice: |
| ; CHECK: .p2align 2 |
| ; CHECK-NEXT: .option push |
| ; CHECK-NEXT: .option exact |
| ; CHECK-NEXT: jalr |
| ; CHECK-NEXT: .option pop |
| ; CHECK-NEXT: lpad 0 |
| ; |
| ; Without relax, only .p2align 2 is needed (no .option push/exact). |
| ; NORELAX-LABEL: test_indirect_returns_twice: |
| ; NORELAX-NOT: .option push |
| ; NORELAX-NOT: .option exact |
| ; NORELAX: .p2align 2 |
| ; NORELAX-NEXT: jalr |
| ; NORELAX-NEXT: lpad 0 |
| ; |
| ; Without Zca, no .p2align or .option push/exact needed. |
| ; NOZCA-LABEL: test_indirect_returns_twice: |
| ; NOZCA-NOT: .p2align 2 |
| ; NOZCA-NOT: .option push |
| ; NOZCA-NOT: .option exact |
| ; NOZCA: jalr |
| ; NOZCA-NEXT: lpad 0 |
| ; |
| ; With -riscv-landing-pad-label=1, lpad uses label 1. |
| ; LABEL1-LABEL: test_indirect_returns_twice: |
| ; LABEL1: jalr |
| ; LABEL1: lpad 1 |
| %buf = alloca [1 x i32], align 4 |
| %call = call i32 %fptr(ptr %buf) #0 |
| ret i32 %call |
| } |
| |
| attributes #0 = { returns_twice } |
| |
| !llvm.module.flags = !{!0, !1} |
| !0 = !{i32 8, !"cf-protection-branch", i32 1} |
| !1 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} |