diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 7199fac9b110b..ab31898e262e7 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -17367,25 +17367,33 @@ 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()); + Register Reg = MatchRegisterName(RegName); + if (!Reg) + report_fatal_error( + Twine("Invalid global name register \"" + StringRef(RegName) + "\".")); + + // FIXME: Unable to generate code for `-O2` but okay for `-O0`. + // 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 (Reg) - return Reg; - report_fatal_error("Invalid register name global variable"); + 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 11cb72296e2c4..8f4351f795ec9 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 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-r2-64.ll b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll index 3df778f445c73..fdf7ea2711d82 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 ca79f857548eb..c09b8bb3f49c3 100644 --- a/llvm/test/CodeGen/PowerPC/named-reg-alloc-r2.ll +++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc-r2.ll @@ -3,11 +3,9 @@ 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". %reg = call i32 @llvm.read_register.i32(metadata !0) ret i32 %reg - ; CHECK-LABEL: @get_reg ; CHECK: mr 3, 2 } 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 0000000000000..38d22475ead91 --- /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"}