[PowerPC] Add global named register support
authorHal Finkel <hfinkel@anl.gov>
Sun, 11 May 2014 19:29:11 +0000 (19:29 +0000)
committerHal Finkel <hfinkel@anl.gov>
Sun, 11 May 2014 19:29:11 +0000 (19:29 +0000)
Support for the intrinsics that read from and write to global named registers
is added for r1, r2 and r13 (depending on the subtarget).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208509 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LangRef.rst
lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/PowerPC/PPCISelLowering.h
test/CodeGen/PowerPC/named-reg-alloc-r0.ll [new file with mode: 0644]
test/CodeGen/PowerPC/named-reg-alloc-r1-64.ll [new file with mode: 0644]
test/CodeGen/PowerPC/named-reg-alloc-r1.ll [new file with mode: 0644]
test/CodeGen/PowerPC/named-reg-alloc-r13-64.ll [new file with mode: 0644]
test/CodeGen/PowerPC/named-reg-alloc-r13.ll [new file with mode: 0644]
test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll [new file with mode: 0644]
test/CodeGen/PowerPC/named-reg-alloc-r2.ll [new file with mode: 0644]

index 77433ab14223252d3c31d96a57ae19861afd1a1a..54b606d037af5c38fe4c6e60aaa3db959622deb8 100644 (file)
@@ -6848,7 +6848,7 @@ register in surrounding code, including inline assembly. Because of that,
 allocatable registers are not supported.
 
 Warning: So far it only works with the stack pointer on selected
-architectures (ARM, ARM64, x86_64 and AArch64). Significant amount of
+architectures (ARM, ARM64, AArch64, PowerPC and x86_64). Significant amount of
 work is needed to support other registers and even more so, allocatable
 registers.
 
index e5fa0d6a24ff9ede7561854f75bffee00cd9faed..2fd5e1061a123470b8a8f247568e62658913985e 100644 (file)
@@ -18,6 +18,7 @@
 #include "PPCTargetMachine.h"
 #include "PPCTargetObjectFile.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -8757,6 +8758,30 @@ 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.
+unsigned PPCTargetLowering::getRegisterByName(const char* RegName,
+                                              EVT VT) const {
+  bool isPPC64 = PPCSubTarget.isPPC64();
+  bool isDarwinABI = PPCSubTarget.isDarwinABI();
+
+  if ((isPPC64 && VT != MVT::i64 && VT != MVT::i32) ||
+      (!isPPC64 && VT != MVT::i32))
+    report_fatal_error("Invalid register global variable type");
+
+  bool is64Bit = isPPC64 && VT == MVT::i64;
+  unsigned Reg = StringSwitch<unsigned>(RegName)
+                   .Case("r1", is64Bit ? PPC::X1 : PPC::R1)
+                   .Case("r2", isDarwinABI ? 0 : (is64Bit ? PPC::X2 : PPC::R2))
+                   .Case("r13", (!isPPC64 && isDarwinABI) ? 0 :
+                                  (is64Bit ? PPC::X13 : PPC::R13))
+                   .Default(0);
+
+  if (Reg)
+    return Reg;
+  report_fatal_error("Invalid register name global variable");
+}
+
 bool
 PPCTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
   // The PowerPC target isn't yet aware of offsets.
index f05f5dd6a6801353fd35985fe6c07d3ed73a063a..98bdf266438b5dbabb5570e2b778e0209eea72f2 100644 (file)
@@ -398,6 +398,8 @@ namespace llvm {
 
     SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
 
+    unsigned getRegisterByName(const char* RegName, EVT VT) const override;
+
     void computeMaskedBitsForTargetNode(const SDValue Op,
                                         APInt &KnownZero,
                                         APInt &KnownOne,
diff --git a/test/CodeGen/PowerPC/named-reg-alloc-r0.ll b/test/CodeGen/PowerPC/named-reg-alloc-r0.ll
new file mode 100644 (file)
index 0000000..e683f99
--- /dev/null
@@ -0,0 +1,15 @@
+; RUN: not llc < %s -mtriple=powerpc-apple-darwin 2>&1 | FileCheck %s
+; RUN: not llc < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s
+; RUN: not 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
+        %reg = call i32 @llvm.read_register.i32(metadata !0)
+  ret i32 %reg
+}
+
+declare i32 @llvm.read_register.i32(metadata) nounwind
+
+!0 = metadata !{metadata !"r0\00"}
diff --git a/test/CodeGen/PowerPC/named-reg-alloc-r1-64.ll b/test/CodeGen/PowerPC/named-reg-alloc-r1-64.ll
new file mode 100644 (file)
index 0000000..b047f9f
--- /dev/null
@@ -0,0 +1,18 @@
+; RUN: llc < %s -mtriple=powerpc64-apple-darwin 2>&1 | FileCheck %s --check-prefix=CHECK-DARWIN
+; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s
+
+define i64 @get_reg() nounwind {
+entry:
+  %reg = call i64 @llvm.read_register.i64(metadata !0)
+  ret i64 %reg
+
+; CHECK-LABEL: @get_reg
+; CHECK: mr 3, 1
+
+; CHECK-DARWIN-LABEL: @get_reg
+; CHECK-DARWIN: mr r3, r1
+}
+
+declare i64 @llvm.read_register.i64(metadata) nounwind
+
+!0 = metadata !{metadata !"r1\00"}
diff --git a/test/CodeGen/PowerPC/named-reg-alloc-r1.ll b/test/CodeGen/PowerPC/named-reg-alloc-r1.ll
new file mode 100644 (file)
index 0000000..9d0eb34
--- /dev/null
@@ -0,0 +1,20 @@
+; RUN: llc < %s -mtriple=powerpc-apple-darwin 2>&1 | FileCheck %s --check-prefix=CHECK-DARWIN
+; RUN: llc < %s -mtriple=powerpc64-apple-darwin 2>&1 | FileCheck %s --check-prefix=CHECK-DARWIN
+; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s
+; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s
+
+define i32 @get_reg() nounwind {
+entry:
+  %reg = call i32 @llvm.read_register.i32(metadata !0)
+  ret i32 %reg
+
+; CHECK-LABEL: @get_reg
+; CHECK: mr 3, 1
+
+; CHECK-DARWIN-LABEL: @get_reg
+; CHECK-DARWIN: mr r3, r1
+}
+
+declare i32 @llvm.read_register.i32(metadata) nounwind
+
+!0 = metadata !{metadata !"r1\00"}
diff --git a/test/CodeGen/PowerPC/named-reg-alloc-r13-64.ll b/test/CodeGen/PowerPC/named-reg-alloc-r13-64.ll
new file mode 100644 (file)
index 0000000..df5085b
--- /dev/null
@@ -0,0 +1,18 @@
+; RUN: llc < %s -mtriple=powerpc64-apple-darwin 2>&1 | FileCheck %s --check-prefix=CHECK-DARWIN
+; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s
+
+define i64 @get_reg() nounwind {
+entry:
+  %reg = call i64 @llvm.read_register.i64(metadata !0)
+  ret i64 %reg
+
+; CHECK-LABEL: @get_reg
+; CHECK: mr 3, 13
+
+; CHECK-DARWIN-LABEL: @get_reg
+; CHECK-DARWIN: mr r3, r13
+}
+
+declare i64 @llvm.read_register.i64(metadata) nounwind
+
+!0 = metadata !{metadata !"r13\00"}
diff --git a/test/CodeGen/PowerPC/named-reg-alloc-r13.ll b/test/CodeGen/PowerPC/named-reg-alloc-r13.ll
new file mode 100644 (file)
index 0000000..900ebb2
--- /dev/null
@@ -0,0 +1,18 @@
+; RUN: not llc < %s -mtriple=powerpc-apple-darwin 2>&1 | FileCheck %s --check-prefix=CHECK-DARWIN
+; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s
+; RUN: 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-DARWIN: Invalid register name global variable
+        %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
+
+!0 = metadata !{metadata !"r13\00"}
diff --git a/test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll b/test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll
new file mode 100644 (file)
index 0000000..0da33fa
--- /dev/null
@@ -0,0 +1,17 @@
+; RUN: not llc < %s -mtriple=powerpc64-apple-darwin 2>&1 | FileCheck %s --check-prefix=CHECK-DARWIN
+; RUN: 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-DARWIN: Invalid register name global variable
+        %reg = call i64 @llvm.read_register.i64(metadata !0)
+  ret i64 %reg
+
+; CHECK-LABEL: @get_reg
+; CHECK: mr 3, 2
+}
+
+declare i64 @llvm.read_register.i64(metadata) nounwind
+
+!0 = metadata !{metadata !"r2\00"}
diff --git a/test/CodeGen/PowerPC/named-reg-alloc-r2.ll b/test/CodeGen/PowerPC/named-reg-alloc-r2.ll
new file mode 100644 (file)
index 0000000..51e7e3e
--- /dev/null
@@ -0,0 +1,18 @@
+; RUN: not llc < %s -mtriple=powerpc-apple-darwin 2>&1 | FileCheck %s --check-prefix=CHECK-DARWIN
+; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu 2>&1 | FileCheck %s
+; RUN: 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-DARWIN: Invalid register name global variable
+        %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
+
+!0 = metadata !{metadata !"r2\00"}