diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -324,6 +324,18 @@ if (TFI->hasFP(MF) || TT.isOSDarwin()) markSuperRegs(Reserved, AArch64::W29); + if (MF.getSubtarget().isWindowsArm64EC()) { + // x13, x14, x23, x24, x28, and v16-v31 are clobbered by asynchronous + // signals, so we can't ever use them. + markSuperRegs(Reserved, AArch64::W13); + markSuperRegs(Reserved, AArch64::W14); + markSuperRegs(Reserved, AArch64::W23); + markSuperRegs(Reserved, AArch64::W24); + markSuperRegs(Reserved, AArch64::W28); + for (unsigned i = AArch64::B15; i <= AArch64::B31; ++i) + markSuperRegs(Reserved, i); + } + for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) { if (MF.getSubtarget().isXRegisterReserved(i)) markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i)); diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -247,6 +247,7 @@ bool isTargetWindows() const { return TargetTriple.isOSWindows(); } bool isTargetAndroid() const { return TargetTriple.isAndroid(); } bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); } + bool isWindowsArm64EC() const { return TargetTriple.isWindowsArm64EC(); } bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); } bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } diff --git a/llvm/test/CodeGen/AArch64/arm64ec-reservedregs.ll b/llvm/test/CodeGen/AArch64/arm64ec-reservedregs.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/arm64ec-reservedregs.ll @@ -0,0 +1,98 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64-pc-windows-msvc_arm64ec < %s | FileCheck %s + +; Make sure we're reserving all the registers that are supposed to be +; reserved. Integer regs x13, x15, x23, x24, x28. Float regs v15-v31. +; We confirm this by ensuring that we spill if and only if none of the +; unreserved registers are available. + +define i32 @no_int_regs(i32 %x) nounwind { +; CHECK-LABEL: no_int_regs: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: stp x30, x29, [sp, #-80]! // 16-byte Folded Spill +; CHECK-NEXT: str x27, [sp, #16] // 8-byte Folded Spill +; CHECK-NEXT: stp x26, x25, [sp, #32] // 16-byte Folded Spill +; CHECK-NEXT: stp x22, x21, [sp, #48] // 16-byte Folded Spill +; CHECK-NEXT: stp x20, x19, [sp, #64] // 16-byte Folded Spill +; CHECK-NEXT: str w0, [sp, #28] // 4-byte Folded Spill +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: ldp x20, x19, [sp, #64] // 16-byte Folded Reload +; CHECK-NEXT: ldp x22, x21, [sp, #48] // 16-byte Folded Reload +; CHECK-NEXT: ldp x26, x25, [sp, #32] // 16-byte Folded Reload +; CHECK-NEXT: ldr w0, [sp, #28] // 4-byte Folded Reload +; CHECK-NEXT: ldr x27, [sp, #16] // 8-byte Folded Reload +; CHECK-NEXT: ldp x30, x29, [sp], #80 // 16-byte Folded Reload +; CHECK-NEXT: ret +entry: + tail call void asm sideeffect "", "~{x0},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x15},~{x16},~{x17},~{x19},~{x20},~{x21},~{x22},~{x25},~{x26},~{x27},~{fp},~{lr}"() + ret i32 %x +} + +define i32 @one_int_reg(i32 %x) nounwind { +; CHECK-LABEL: one_int_reg: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: stp x30, x29, [sp, #-80]! // 16-byte Folded Spill +; CHECK-NEXT: str x27, [sp, #16] // 8-byte Folded Spill +; CHECK-NEXT: mov w30, w0 +; CHECK-NEXT: stp x26, x25, [sp, #32] // 16-byte Folded Spill +; CHECK-NEXT: stp x22, x21, [sp, #48] // 16-byte Folded Spill +; CHECK-NEXT: stp x20, x19, [sp, #64] // 16-byte Folded Spill +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: ldp x20, x19, [sp, #64] // 16-byte Folded Reload +; CHECK-NEXT: mov w0, w30 +; CHECK-NEXT: ldp x22, x21, [sp, #48] // 16-byte Folded Reload +; CHECK-NEXT: ldp x26, x25, [sp, #32] // 16-byte Folded Reload +; CHECK-NEXT: ldr x27, [sp, #16] // 8-byte Folded Reload +; CHECK-NEXT: ldp x30, x29, [sp], #80 // 16-byte Folded Reload +; CHECK-NEXT: ret +entry: + tail call void asm sideeffect "", "~{x0},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x15},~{x16},~{x17},~{x19},~{x20},~{x21},~{x22},~{x25},~{x26},~{x27},~{fp}"() + ret i32 %x +} + +define float @no_float_regs(float %x) nounwind { +; CHECK-LABEL: no_float_regs: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #80 +; CHECK-NEXT: stp d15, d14, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: stp d13, d12, [sp, #32] // 16-byte Folded Spill +; CHECK-NEXT: stp d11, d10, [sp, #48] // 16-byte Folded Spill +; CHECK-NEXT: stp d9, d8, [sp, #64] // 16-byte Folded Spill +; CHECK-NEXT: str s0, [sp, #12] // 4-byte Folded Spill +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: ldp d9, d8, [sp, #64] // 16-byte Folded Reload +; CHECK-NEXT: ldp d11, d10, [sp, #48] // 16-byte Folded Reload +; CHECK-NEXT: ldp d13, d12, [sp, #32] // 16-byte Folded Reload +; CHECK-NEXT: ldp d15, d14, [sp, #16] // 16-byte Folded Reload +; CHECK-NEXT: ldr s0, [sp, #12] // 4-byte Folded Reload +; CHECK-NEXT: add sp, sp, #80 +; CHECK-NEXT: ret +entry: + tail call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15}"() + ret float %x +} + +define float @one_float_reg(float %x) nounwind { +; CHECK-LABEL: one_float_reg: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: stp d15, d14, [sp, #-64]! // 16-byte Folded Spill +; CHECK-NEXT: stp d13, d12, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: fmov s7, s0 +; CHECK-NEXT: stp d11, d10, [sp, #32] // 16-byte Folded Spill +; CHECK-NEXT: stp d9, d8, [sp, #48] // 16-byte Folded Spill +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: ldp d9, d8, [sp, #48] // 16-byte Folded Reload +; CHECK-NEXT: fmov s0, s7 +; CHECK-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload +; CHECK-NEXT: ldp d13, d12, [sp, #16] // 16-byte Folded Reload +; CHECK-NEXT: ldp d15, d14, [sp], #64 // 16-byte Folded Reload +; CHECK-NEXT: ret +entry: + tail call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15}"() + ret float %x +} + diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -34,7 +34,7 @@ r'(?:[ \t]+.cfi_startproc\n)?' # drop optional cfi noise r'(?P.*?)\n' # This list is incomplete - r'.Lfunc_end[0-9]+:\n', + r'(.Lfunc_end[0-9]+:\n|[ \t]*\/\/ -- End function\n)', flags=(re.M | re.S)) ASM_FUNCTION_AMDGPU_RE = re.compile(