# RUN: llc -mtriple=riscv32 -x mir -run-pass=machine-outliner -simplify-mir -verify-machineinstrs < %s \ # RUN: | FileCheck -check-prefixes=OUTLINED,RV32I-MO %s # RUN: llc -mtriple=riscv64 -x mir -run-pass=machine-outliner -simplify-mir -verify-machineinstrs < %s \ # RUN: | FileCheck -check-prefixes=OUTLINED,RV64I-MO %s # Combined tests for outlining with CFI instructions on RISC-V: # 1) All CFIs present in candidate: outline as tail-call and keep CFIs. # 2) Partial CFIs in function (extra outside candidate): do not outline. # 3) CFIs present but candidate is not a tail-call: do not outline. --- | define void @funcA(i32 %a, i32 %b) nounwind { ret void } define void @funcB(i32 %a, i32 %b) nounwind { ret void } define void @funcC(i32 %a, i32 %b) nounwind { ret void } define void @funcD(i32 %a, i32 %b) nounwind { ret void } define void @funcE(i32 %a, i32 %b) nounwind { ret void } define void @funcF(i32 %a, i32 %b) nounwind { ret void } ... # Case 1: All CFIs present; expect outlining and CFIs retained in outlined body. --- name: funcA tracksRegLiveness: true body: | bb.0: liveins: $x10, $x11 ; RV32I-MO-LABEL: name: funcA ; RV32I-MO: liveins: $x10, $x11 ; RV32I-MO-NEXT: {{ $}} ; RV32I-MO-NEXT: PseudoTAIL target-flags(riscv-call) @OUTLINED_FUNCTION_0, implicit $x2, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit $x2, implicit $x10, implicit $x11 ; ; RV64I-MO-LABEL: name: funcA ; RV64I-MO: liveins: $x10, $x11 ; RV64I-MO-NEXT: {{ $}} ; RV64I-MO-NEXT: PseudoTAIL target-flags(riscv-call) @OUTLINED_FUNCTION_0, implicit $x2, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit $x2, implicit $x10, implicit $x11 $x10 = ORI $x10, 1023 CFI_INSTRUCTION offset $x1, 0 $x11 = ORI $x11, 1023 CFI_INSTRUCTION offset $x1, -4 $x12 = ADDI $x10, 17 CFI_INSTRUCTION offset $x1, -8 $x11 = AND $x12, $x11 CFI_INSTRUCTION offset $x1, -12 $x10 = SUB $x10, $x11 PseudoRET ... --- name: funcB tracksRegLiveness: true body: | bb.0: liveins: $x10, $x11 ; RV32I-MO-LABEL: name: funcB ; RV32I-MO: liveins: $x10, $x11 ; RV32I-MO-NEXT: {{ $}} ; RV32I-MO-NEXT: PseudoTAIL target-flags(riscv-call) @OUTLINED_FUNCTION_0, implicit $x2, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit $x2, implicit $x10, implicit $x11 ; ; RV64I-MO-LABEL: name: funcB ; RV64I-MO: liveins: $x10, $x11 ; RV64I-MO-NEXT: {{ $}} ; RV64I-MO-NEXT: PseudoTAIL target-flags(riscv-call) @OUTLINED_FUNCTION_0, implicit $x2, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit $x2, implicit $x10, implicit $x11 $x10 = ORI $x10, 1023 CFI_INSTRUCTION offset $x1, 0 $x11 = ORI $x11, 1023 CFI_INSTRUCTION offset $x1, -4 $x12 = ADDI $x10, 17 CFI_INSTRUCTION offset $x1, -8 $x11 = AND $x12, $x11 CFI_INSTRUCTION offset $x1, -12 $x10 = SUB $x10, $x11 PseudoRET ... # Case 2: Partial CFIs (extra CFI outside candidate in funcD); expect no outlining. --- name: funcC tracksRegLiveness: true body: | bb.0: liveins: $x10, $x11 ; RV32I-MO-LABEL: name: funcC ; RV32I-MO: liveins: $x10, $x11 ; RV32I-MO-NEXT: {{ $}} ; RV32I-MO-NEXT: PseudoTAIL target-flags(riscv-call) @OUTLINED_FUNCTION_0, implicit $x2, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit $x2, implicit $x10, implicit $x11 ; ; RV64I-MO-LABEL: name: funcC ; RV64I-MO: liveins: $x10, $x11 ; RV64I-MO-NEXT: {{ $}} ; RV64I-MO-NEXT: PseudoTAIL target-flags(riscv-call) @OUTLINED_FUNCTION_0, implicit $x2, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit $x2, implicit $x10, implicit $x11 $x10 = ORI $x10, 1023 CFI_INSTRUCTION offset $x1, 0 $x11 = ORI $x11, 1023 CFI_INSTRUCTION offset $x1, -4 $x12 = ADDI $x10, 17 CFI_INSTRUCTION offset $x1, -8 $x11 = AND $x12, $x11 CFI_INSTRUCTION offset $x1, -12 $x10 = SUB $x10, $x11 PseudoRET ... --- name: funcD tracksRegLiveness: true body: | bb.0: liveins: $x10, $x11 ; RV32I-MO-LABEL: name: funcD ; RV32I-MO: liveins: $x10, $x11 ; RV32I-MO-NEXT: {{ $}} ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, -16 ; RV32I-MO-NEXT: $x10 = ORI $x10, 1023 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, 0 ; RV32I-MO-NEXT: $x11 = ORI $x11, 1023 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, -4 ; RV32I-MO-NEXT: $x12 = ADDI $x10, 17 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, -8 ; RV32I-MO-NEXT: $x11 = AND $x12, $x11 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, -12 ; RV32I-MO-NEXT: $x10 = SUB $x10, $x11 ; RV32I-MO-NEXT: PseudoRET ; ; RV64I-MO-LABEL: name: funcD ; RV64I-MO: liveins: $x10, $x11 ; RV64I-MO-NEXT: {{ $}} ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, -16 ; RV64I-MO-NEXT: $x10 = ORI $x10, 1023 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, 0 ; RV64I-MO-NEXT: $x11 = ORI $x11, 1023 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, -4 ; RV64I-MO-NEXT: $x12 = ADDI $x10, 17 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, -8 ; RV64I-MO-NEXT: $x11 = AND $x12, $x11 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, -12 ; RV64I-MO-NEXT: $x10 = SUB $x10, $x11 ; RV64I-MO-NEXT: PseudoRET CFI_INSTRUCTION offset $x1, -16 $x10 = ORI $x10, 1023 CFI_INSTRUCTION offset $x1, 0 $x11 = ORI $x11, 1023 CFI_INSTRUCTION offset $x1, -4 $x12 = ADDI $x10, 17 CFI_INSTRUCTION offset $x1, -8 $x11 = AND $x12, $x11 CFI_INSTRUCTION offset $x1, -12 $x10 = SUB $x10, $x11 PseudoRET ... # Case 3: CFIs present but candidate is not a tail-call; expect no outlining. --- name: funcE tracksRegLiveness: true body: | bb.0: liveins: $x10, $x11 ; RV32I-MO-LABEL: name: funcE ; RV32I-MO: liveins: $x10, $x11 ; RV32I-MO-NEXT: {{ $}} ; RV32I-MO-NEXT: $x10 = ORI $x10, 1023 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, 0 ; RV32I-MO-NEXT: $x11 = ORI $x11, 1023 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, -4 ; RV32I-MO-NEXT: $x12 = ADDI $x10, 17 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, -8 ; RV32I-MO-NEXT: $x11 = AND $x12, $x11 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, -12 ; RV32I-MO-NEXT: $x10 = SUB $x10, $x11 ; RV32I-MO-NEXT: $x10 = ADDI $x10, 1 ; RV32I-MO-NEXT: PseudoRET ; ; RV64I-MO-LABEL: name: funcE ; RV64I-MO: liveins: $x10, $x11 ; RV64I-MO-NEXT: {{ $}} ; RV64I-MO-NEXT: $x10 = ORI $x10, 1023 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, 0 ; RV64I-MO-NEXT: $x11 = ORI $x11, 1023 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, -4 ; RV64I-MO-NEXT: $x12 = ADDI $x10, 17 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, -8 ; RV64I-MO-NEXT: $x11 = AND $x12, $x11 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, -12 ; RV64I-MO-NEXT: $x10 = SUB $x10, $x11 ; RV64I-MO-NEXT: $x10 = ADDI $x10, 1 ; RV64I-MO-NEXT: PseudoRET $x10 = ORI $x10, 1023 CFI_INSTRUCTION offset $x1, 0 $x11 = ORI $x11, 1023 CFI_INSTRUCTION offset $x1, -4 $x12 = ADDI $x10, 17 CFI_INSTRUCTION offset $x1, -8 $x11 = AND $x12, $x11 CFI_INSTRUCTION offset $x1, -12 $x10 = SUB $x10, $x11 $x10 = ADDI $x10, 1 PseudoRET ... --- name: funcF tracksRegLiveness: true body: | bb.0: liveins: $x10, $x11 ; RV32I-MO-LABEL: name: funcF ; RV32I-MO: liveins: $x10, $x11 ; RV32I-MO-NEXT: {{ $}} ; RV32I-MO-NEXT: $x10 = ORI $x10, 1023 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, 0 ; RV32I-MO-NEXT: $x11 = ORI $x11, 1023 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, -4 ; RV32I-MO-NEXT: $x12 = ADDI $x10, 17 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, -8 ; RV32I-MO-NEXT: $x11 = AND $x12, $x11 ; RV32I-MO-NEXT: CFI_INSTRUCTION offset $x1, -12 ; RV32I-MO-NEXT: $x10 = SUB $x10, $x11 ; RV32I-MO-NEXT: $x10 = ADDI $x10, 2 ; RV32I-MO-NEXT: PseudoRET ; ; RV64I-MO-LABEL: name: funcF ; RV64I-MO: liveins: $x10, $x11 ; RV64I-MO-NEXT: {{ $}} ; RV64I-MO-NEXT: $x10 = ORI $x10, 1023 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, 0 ; RV64I-MO-NEXT: $x11 = ORI $x11, 1023 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, -4 ; RV64I-MO-NEXT: $x12 = ADDI $x10, 17 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, -8 ; RV64I-MO-NEXT: $x11 = AND $x12, $x11 ; RV64I-MO-NEXT: CFI_INSTRUCTION offset $x1, -12 ; RV64I-MO-NEXT: $x10 = SUB $x10, $x11 ; RV64I-MO-NEXT: $x10 = ADDI $x10, 2 ; RV64I-MO-NEXT: PseudoRET $x10 = ORI $x10, 1023 CFI_INSTRUCTION offset $x1, 0 $x11 = ORI $x11, 1023 CFI_INSTRUCTION offset $x1, -4 $x12 = ADDI $x10, 17 CFI_INSTRUCTION offset $x1, -8 $x11 = AND $x12, $x11 CFI_INSTRUCTION offset $x1, -12 $x10 = SUB $x10, $x11 $x10 = ADDI $x10, 2 PseudoRET ... # OUTLINED-LABEL: name: OUTLINED_FUNCTION_0 # OUTLINED: liveins: $x11, $x10 # OUTLINED-NEXT: {{ $}} # OUTLINED-NEXT: $x10 = ORI $x10, 1023 # OUTLINED-NEXT: CFI_INSTRUCTION offset $x1, 0 # OUTLINED-NEXT: $x11 = ORI $x11, 1023 # OUTLINED-NEXT: CFI_INSTRUCTION offset $x1, -4 # OUTLINED-NEXT: $x12 = ADDI $x10, 17 # OUTLINED-NEXT: CFI_INSTRUCTION offset $x1, -8 # OUTLINED-NEXT: $x11 = AND $x12, $x11 # OUTLINED-NEXT: CFI_INSTRUCTION offset $x1, -12 # OUTLINED-NEXT: $x10 = SUB $x10, $x11 # OUTLINED-NEXT: PseudoRET