diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 7199fac9b110b6..a4f0444ff2a645 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -17367,25 +17367,36 @@ SDValue PPCTargetLowering::LowerFRAMEADDR(SDValue Op, return FrameAddr; } -// FIXME? Maybe this could be a TableGen attribute on some registers and -// this table could be generated automatically from RegInfo. -Register PPCTargetLowering::getRegisterByName(const char* RegName, LLT VT, +#define GET_REGISTER_MATCHER +#include "PPCGenAsmMatcher.inc" + +Register PPCTargetLowering::getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const { - bool isPPC64 = Subtarget.isPPC64(); + bool IsPPC64 = Subtarget.isPPC64(); - bool is64Bit = isPPC64 && VT == LLT::scalar(64); - if (!is64Bit && VT != LLT::scalar(32)) + bool Is64Bit = IsPPC64 && VT == LLT::scalar(64); + if (!Is64Bit && VT != LLT::scalar(32)) report_fatal_error("Invalid register global variable type"); - Register Reg = StringSwitch(RegName) - .Case("r1", is64Bit ? PPC::X1 : PPC::R1) - .Case("r2", isPPC64 ? Register() : PPC::R2) - .Case("r13", (is64Bit ? PPC::X13 : PPC::R13)) - .Default(Register()); - - if (Reg) - return Reg; - report_fatal_error("Invalid register name global variable"); + Register Reg = MatchRegisterName(RegName); + if (!Reg) + report_fatal_error( + Twine("Invalid global name register \"" + StringRef(RegName) + "\".")); + + // FIXME: These registers are not flagged as reserved and we can generate + // code for `-O0` but not for `-O2`. Need followup investigation as to why. + if ((IsPPC64 && Reg == PPC::R2) || Reg == PPC::R0) + report_fatal_error(Twine("Trying to reserve an invalid register \"" + + StringRef(RegName) + "\".")); + + // Convert GPR to GP8R register for 64bit. + if (Is64Bit && StringRef(RegName).starts_with_insensitive("r")) + Reg = Reg.id() - PPC::R0 + PPC::X0; + + if (Subtarget.getRegisterInfo()->getReservedRegs(MF).test(Reg)) + report_fatal_error(Twine("Trying to obtain a reserved register \"" + + StringRef(RegName) + "\".")); + return Reg; } bool PPCTargetLowering::isAccessedAsGotIndirect(SDValue GA) const { diff --git a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r0.ll b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r0.ll index 11cb72296e2c43..c6b9498a680f4d 100644 --- a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r0.ll +++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r0.ll @@ -1,11 +1,9 @@ -; RUN: not --crash llc < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s -; RUN: not --crash llc < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s -; RUN: not --crash llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s +; RUN: not --crash llc -O0 < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s +; RUN: not --crash llc -O0 < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s define i32 @get_reg() nounwind { entry: -; FIXME: Include an allocatable-specific error message -; CHECK: Invalid register name global variable +; CHECK: Trying to reserve an invalid register "r0". %reg = call i32 @llvm.read_register.i32(metadata !0) ret i32 %reg } diff --git a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r1-64.ll b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r1-64.ll index 080b1982c88cbf..96dbddd5bf1578 100644 --- a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r1-64.ll +++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r1-64.ll @@ -1,12 +1,10 @@ -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s +; RUN: not --crash llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s define i64 @get_reg() nounwind { +; CHECK: Trying to obtain a reserved register "r1". entry: %reg = call i64 @llvm.read_register.i64(metadata !0) ret i64 %reg - -; CHECK-LABEL: get_reg -; CHECK: mr 3, 1 } declare i64 @llvm.read_register.i64(metadata) nounwind diff --git a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r1.ll b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r1.ll index 6edd787e445e46..5980d09bc9c906 100644 --- a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r1.ll +++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r1.ll @@ -1,14 +1,11 @@ -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s +; RUN: not --crash llc < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s +; RUN: not --crash llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s define i32 @get_reg() nounwind { +; CHECK: Trying to obtain a reserved register "r1". entry: %reg = call i32 @llvm.read_register.i32(metadata !0) ret i32 %reg - -; CHECK-LABEL: @get_reg -; CHECK: mr 3, 1 - } declare i32 @llvm.read_register.i32(metadata) nounwind diff --git a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r13-64.ll b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r13-64.ll index 4d73fb3e81869c..8bd4d899f72609 100644 --- a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r13-64.ll +++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r13-64.ll @@ -1,13 +1,10 @@ -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s +; RUN: not --crash llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s define i64 @get_reg() nounwind { +; CHECK: Trying to obtain a reserved register "r13". entry: %reg = call i64 @llvm.read_register.i64(metadata !0) ret i64 %reg - -; CHECK-LABEL: @get_reg -; CHECK: mr 3, 13 - } declare i64 @llvm.read_register.i64(metadata) nounwind diff --git a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r13.ll b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r13.ll index a7b778147980ac..2185a8a6cd5379 100644 --- a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r13.ll +++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r13.ll @@ -1,13 +1,11 @@ -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s +; RUN: not --crash llc < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s +; RUN: not --crash llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s define i32 @get_reg() nounwind { +; CHECK: Trying to obtain a reserved register "r13". entry: %reg = call i32 @llvm.read_register.i32(metadata !0) ret i32 %reg - -; CHECK-LABEL: @get_reg -; CHECK: mr 3, 13 } declare i32 @llvm.read_register.i32(metadata) nounwind diff --git a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll index 3df778f445c733..fdf7ea2711d827 100644 --- a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll +++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll @@ -1,10 +1,8 @@ ; RUN: not --crash llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s -; RUN: not --crash llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s define i64 @get_reg() nounwind { entry: -; FIXME: Include an allocatable-specific error message -; CHECK: Invalid register name global variable +; CHECK: Trying to reserve an invalid register "r2". %reg = call i64 @llvm.read_register.i64(metadata !0) ret i64 %reg } diff --git a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r2.ll b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r2.ll index ca79f857548ebe..58c782901f3eb6 100644 --- a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r2.ll +++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r2.ll @@ -1,15 +1,12 @@ -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s +; RUN: not --crash llc < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s ; RUN: not --crash llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s --check-prefix=CHECK-NOTPPC32 define i32 @get_reg() nounwind { entry: -; FIXME: Include an allocatable-specific error message -; CHECK-NOTPPC32: Invalid register name global variable +; CHECK-NOTPPC32: Trying to reserve an invalid register "r2". +; CHECK: Trying to obtain a reserved register "r2". %reg = call i32 @llvm.read_register.i32(metadata !0) ret i32 %reg - -; CHECK-LABEL: @get_reg -; CHECK: mr 3, 2 } declare i32 @llvm.read_register.i32(metadata) nounwind diff --git a/llvm/test/CodeGen/PowerPC/named-reg-alloc.ll b/llvm/test/CodeGen/PowerPC/named-reg-alloc.ll new file mode 100644 index 00000000000000..38d22475ead910 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc.ll @@ -0,0 +1,144 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -O0 -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s +; RUN: llc -O0 -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s --check-prefix=CHECK64 + +@mVal = dso_local global i32 15, align 4 +@myGVal = dso_local global i32 0, align 4 + +define dso_local void @testSetIntReg(i32 noundef signext %xx) { +; CHECK-LABEL: testSetIntReg: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mr 5, 3 +; CHECK-NEXT: blr +; +; CHECK64-LABEL: testSetIntReg: +; CHECK64: # %bb.0: # %entry +; CHECK64-NEXT: mr 5, 3 +; CHECK64-NEXT: blr +entry: + tail call void @llvm.write_register.i32(metadata !0, i32 %xx) + ret void +} + +declare void @llvm.write_register.i32(metadata, i32) + +define dso_local signext range(i32 0, 2) i32 @testCmpReg() { +; CHECK-LABEL: testCmpReg: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lis 3, mVal@ha +; CHECK-NEXT: lwz 3, mVal@l(3) +; CHECK-NEXT: xori 3, 3, 15 +; CHECK-NEXT: cntlzw 3, 3 +; CHECK-NEXT: srwi 3, 3, 5 +; CHECK-NEXT: blr +; +; CHECK64-LABEL: testCmpReg: +; CHECK64: # %bb.0: # %entry +; CHECK64-NEXT: addis 3, 2, mVal@toc@ha +; CHECK64-NEXT: addi 3, 3, mVal@toc@l +; CHECK64-NEXT: lwz 3, 0(3) +; CHECK64-NEXT: xori 3, 3, 15 +; CHECK64-NEXT: cntlzw 3, 3 +; CHECK64-NEXT: srwi 3, 3, 5 +; CHECK64-NEXT: extsw 3, 3 +; CHECK64-NEXT: blr +entry: + tail call void @llvm.write_register.i32(metadata !0, i32 15) + %0 = load i32, ptr @mVal, align 4 + %1 = tail call i32 @llvm.read_register.i32(metadata !0) + %cmp = icmp eq i32 %0, %1 + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +declare i32 @llvm.read_register.i32(metadata) + +define dso_local void @testSetIntReg2(i32 noundef signext %xx) { +; CHECK-LABEL: testSetIntReg2: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stwu 1, -48(1) +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: .cfi_offset r23, -36 +; CHECK-NEXT: stw 23, 12(1) # 4-byte Folded Spill +; CHECK-NEXT: mr 23, 3 +; CHECK-NEXT: lwz 23, 12(1) # 4-byte Folded Reload +; CHECK-NEXT: addi 1, 1, 48 +; CHECK-NEXT: blr +; +; CHECK64-LABEL: testSetIntReg2: +; CHECK64: # %bb.0: # %entry +; CHECK64-NEXT: std 23, -72(1) # 8-byte Folded Spill +; CHECK64-NEXT: mr 23, 3 +; CHECK64-NEXT: ld 23, -72(1) # 8-byte Folded Reload +; CHECK64-NEXT: blr +entry: + tail call void @llvm.write_register.i32(metadata !1, i32 %xx) + ret void +} + +define dso_local signext i32 @testReturnReg() { +; CHECK-LABEL: testReturnReg: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stwu 1, -48(1) +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: .cfi_offset r23, -36 +; CHECK-NEXT: stw 23, 12(1) # 4-byte Folded Spill +; CHECK-NEXT: li 23, 125 +; CHECK-NEXT: mr 3, 23 +; CHECK-NEXT: lwz 23, 12(1) # 4-byte Folded Reload +; CHECK-NEXT: addi 1, 1, 48 +; CHECK-NEXT: blr +; +; CHECK64-LABEL: testReturnReg: +; CHECK64: # %bb.0: # %entry +; CHECK64-NEXT: std 23, -72(1) # 8-byte Folded Spill +; CHECK64-NEXT: li 23, 125 +; CHECK64-NEXT: extsw 3, 23 +; CHECK64-NEXT: ld 23, -72(1) # 8-byte Folded Reload +; CHECK64-NEXT: blr +entry: + tail call void @llvm.write_register.i32(metadata !1, i32 125) + %0 = tail call i32 @llvm.read_register.i32(metadata !1) + ret i32 %0 +} + +define dso_local void @testViaASM(i32 noundef signext %xx) { +; CHECK-LABEL: testViaASM: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stwu 1, -64(1) +; CHECK-NEXT: .cfi_def_cfa_offset 64 +; CHECK-NEXT: .cfi_offset r20, -48 +; CHECK-NEXT: stw 20, 16(1) # 4-byte Folded Spill +; CHECK-NEXT: mr 20, 3 +; CHECK-NEXT: #APP +; CHECK-NEXT: addi 3, 1, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lis 4, myGVal@ha +; CHECK-NEXT: stw 3, myGVal@l(4) +; CHECK-NEXT: lwz 20, 16(1) # 4-byte Folded Reload +; CHECK-NEXT: addi 1, 1, 64 +; CHECK-NEXT: blr +; +; CHECK64-LABEL: testViaASM: +; CHECK64: # %bb.0: # %entry +; CHECK64-NEXT: std 20, -96(1) # 8-byte Folded Spill +; CHECK64-NEXT: mr 20, 3 +; CHECK64-NEXT: #APP +; CHECK64-NEXT: addi 3, 1, 1 +; CHECK64-NEXT: #NO_APP +; CHECK64-NEXT: addis 4, 2, myGVal@toc@ha +; CHECK64-NEXT: addi 4, 4, myGVal@toc@l +; CHECK64-NEXT: stw 3, 0(4) +; CHECK64-NEXT: ld 20, -96(1) # 8-byte Folded Reload +; CHECK64-NEXT: blr +entry: + tail call void @llvm.write_register.i32(metadata !2, i32 %xx) + %0 = tail call i32 @llvm.read_register.i32(metadata !2) + %1 = tail call i32 asm "addi $0, $2, $2", "=r,{r20},K"(i32 %0, i32 1) + store i32 %1, ptr @myGVal, align 4 + ret void +} + +!0 = !{!"r5"} +!1 = !{!"r23"} +!2 = !{!"r20"}