diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -1277,7 +1277,8 @@ // We would like to split the SP adjustment to reduce prologue/epilogue // as following instructions. In this way, the offset of the callee saved -// register could fit in a single store. +// register could fit in a single store. Supposed that the first sp adjust +// amount is 2032. // add sp,sp,-2032 // sw ra,2028(sp) // sw s0,2024(sp) @@ -1314,6 +1315,7 @@ // offset that stack compression instructions accept when target supports // compression instructions. if (STI.hasStdExtCOrZca()) { + // The compression extensions may support the following instructions: // riscv32: c.lwsp rd, offset[7:2] => 2^(6 + 2) // c.swsp rs2, offset[7:2] => 2^(6 + 2) // c.flwsp rd, offset[7:2] => 2^(6 + 2) @@ -1329,10 +1331,22 @@ // StackSize meets the condition (StackSize <= 2048 + RVCompressLen), // case1: Amount is 2048 - StackAlign: use addi + addi to adjust sp. // case2: Amount is RVCompressLen: use addi + addi to adjust sp. - if (StackSize <= 2047 + RVCompressLen || - (StackSize > 2048 * 2 - StackAlign && - StackSize <= 2047 * 2 + RVCompressLen) || - StackSize > 2048 * 3 - StackAlign) + auto CanCompress = [&](uint64_t CompressLen) -> bool { + if (StackSize <= 2047 + CompressLen || + (StackSize > 2048 * 2 - StackAlign && + StackSize <= 2047 * 2 + CompressLen) || + StackSize > 2048 * 3 - StackAlign) + return true; + + return false; + }; + // In the epilogue, addi sp, sp, 496 is used to recover the sp and it + // can be compressed(C.ADDI16SP, offset can be [-512, 496]), but + // addi sp, sp, 512 can not be compressed. So try to use 496 first. + const uint64_t ADDI16SPCompressLen = 496; + if (STI.is64Bit() && CanCompress(ADDI16SPCompressLen)) + return ADDI16SPCompressLen; + if (CanCompress(RVCompressLen)) return RVCompressLen; } return 2048 - StackAlign; diff --git a/llvm/test/CodeGen/RISCV/stack-inst-compress.mir b/llvm/test/CodeGen/RISCV/stack-inst-compress.mir --- a/llvm/test/CodeGen/RISCV/stack-inst-compress.mir +++ b/llvm/test/CodeGen/RISCV/stack-inst-compress.mir @@ -92,17 +92,17 @@ ; CHECK-RV64-COM-LABEL: name: _Z15stack_size_2048v ; CHECK-RV64-COM: liveins: $x1 ; CHECK-RV64-COM-NEXT: {{ $}} - ; CHECK-RV64-COM-NEXT: $x2 = frame-setup ADDI $x2, -512 - ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 512 - ; CHECK-RV64-COM-NEXT: SD killed $x1, $x2, 504 :: (store (s64) into %stack.1) + ; CHECK-RV64-COM-NEXT: $x2 = frame-setup ADDI $x2, -496 + ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 496 + ; CHECK-RV64-COM-NEXT: SD killed $x1, $x2, 488 :: (store (s64) into %stack.1) ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION offset $x1, -8 - ; CHECK-RV64-COM-NEXT: $x2 = frame-setup ADDI $x2, -1552 + ; CHECK-RV64-COM-NEXT: $x2 = frame-setup ADDI $x2, -1568 ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 2064 ; CHECK-RV64-COM-NEXT: renamable $x10 = ADDI $x2, 8 ; CHECK-RV64-COM-NEXT: PseudoCALL target-flags(riscv-call) @_Z6calleePi, csr_ilp32_lp64, implicit-def dead $x1, implicit killed $x10, implicit-def $x2 - ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADDI $x2, 1552 - ; CHECK-RV64-COM-NEXT: $x1 = LD $x2, 504 :: (load (s64) from %stack.1) - ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADDI $x2, 512 + ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADDI $x2, 1568 + ; CHECK-RV64-COM-NEXT: $x1 = LD $x2, 488 :: (load (s64) from %stack.1) + ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADDI $x2, 496 ; CHECK-RV64-COM-NEXT: PseudoRET ADJCALLSTACKDOWN 0, 0, implicit-def dead $x2, implicit $x2 renamable $x10 = ADDI %stack.0, 0 @@ -183,19 +183,19 @@ ; CHECK-RV64-COM-LABEL: name: _Z15stack_size_4096v ; CHECK-RV64-COM: liveins: $x1 ; CHECK-RV64-COM-NEXT: {{ $}} - ; CHECK-RV64-COM-NEXT: $x2 = frame-setup ADDI $x2, -512 - ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 512 - ; CHECK-RV64-COM-NEXT: SD killed $x1, $x2, 504 :: (store (s64) into %stack.1) + ; CHECK-RV64-COM-NEXT: $x2 = frame-setup ADDI $x2, -496 + ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 496 + ; CHECK-RV64-COM-NEXT: SD killed $x1, $x2, 488 :: (store (s64) into %stack.1) ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION offset $x1, -8 ; CHECK-RV64-COM-NEXT: $x2 = frame-setup ADDI $x2, -2048 - ; CHECK-RV64-COM-NEXT: $x2 = frame-setup ADDI killed $x2, -1552 + ; CHECK-RV64-COM-NEXT: $x2 = frame-setup ADDI killed $x2, -1568 ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 4112 ; CHECK-RV64-COM-NEXT: renamable $x10 = ADDI $x2, 8 ; CHECK-RV64-COM-NEXT: PseudoCALL target-flags(riscv-call) @_Z6calleePi, csr_ilp32_lp64, implicit-def dead $x1, implicit killed $x10, implicit-def $x2 ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADDI $x2, 2032 - ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADDI killed $x2, 1568 - ; CHECK-RV64-COM-NEXT: $x1 = LD $x2, 504 :: (load (s64) from %stack.1) - ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADDI $x2, 512 + ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADDI killed $x2, 1584 + ; CHECK-RV64-COM-NEXT: $x1 = LD $x2, 488 :: (load (s64) from %stack.1) + ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADDI $x2, 496 ; CHECK-RV64-COM-NEXT: PseudoRET ADJCALLSTACKDOWN 0, 0, implicit-def dead $x2, implicit $x2 renamable $x10 = ADDI %stack.0, 0 @@ -282,21 +282,21 @@ ; CHECK-RV64-COM-LABEL: name: _Z15stack_size_8192v ; CHECK-RV64-COM: liveins: $x1 ; CHECK-RV64-COM-NEXT: {{ $}} - ; CHECK-RV64-COM-NEXT: $x2 = frame-setup ADDI $x2, -512 - ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 512 - ; CHECK-RV64-COM-NEXT: SD killed $x1, $x2, 504 :: (store (s64) into %stack.1) + ; CHECK-RV64-COM-NEXT: $x2 = frame-setup ADDI $x2, -496 + ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 496 + ; CHECK-RV64-COM-NEXT: SD killed $x1, $x2, 488 :: (store (s64) into %stack.1) ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION offset $x1, -8 ; CHECK-RV64-COM-NEXT: $x10 = frame-setup LUI 2 - ; CHECK-RV64-COM-NEXT: $x10 = frame-setup ADDIW killed $x10, -496 + ; CHECK-RV64-COM-NEXT: $x10 = frame-setup ADDIW killed $x10, -480 ; CHECK-RV64-COM-NEXT: $x2 = frame-setup SUB $x2, killed $x10 ; CHECK-RV64-COM-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8208 ; CHECK-RV64-COM-NEXT: renamable $x10 = ADDI $x2, 8 ; CHECK-RV64-COM-NEXT: PseudoCALL target-flags(riscv-call) @_Z6calleePi, csr_ilp32_lp64, implicit-def dead $x1, implicit killed $x10, implicit-def $x2 ; CHECK-RV64-COM-NEXT: $x10 = frame-destroy LUI 2 - ; CHECK-RV64-COM-NEXT: $x10 = frame-destroy ADDIW killed $x10, -496 + ; CHECK-RV64-COM-NEXT: $x10 = frame-destroy ADDIW killed $x10, -480 ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADD $x2, killed $x10 - ; CHECK-RV64-COM-NEXT: $x1 = LD $x2, 504 :: (load (s64) from %stack.1) - ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADDI $x2, 512 + ; CHECK-RV64-COM-NEXT: $x1 = LD $x2, 488 :: (load (s64) from %stack.1) + ; CHECK-RV64-COM-NEXT: $x2 = frame-destroy ADDI $x2, 496 ; CHECK-RV64-COM-NEXT: PseudoRET ADJCALLSTACKDOWN 0, 0, implicit-def dead $x2, implicit $x2 renamable $x10 = ADDI %stack.0, 0