summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Stellard <thomas.stellard@amd.com>2014-12-11 16:19:16 -0500
committerTom Stellard <thomas.stellard@amd.com>2014-12-16 12:35:18 -0500
commit1e3aecfb8ba4367ac22863a6b3f11b9feea4f4d7 (patch)
tree144cfaad129831e0693a6536c83de5f12585a275
parent070faa158c043e2e1e067312e52c64883961598d (diff)
R600/SI: Use RegisterOperands to specify which operands can accept immediates
There are some operands which can take either immediates or registers and we were previously using different register class to distinguish between operands that could take immediates and those that could not. This patch switches to using RegisterOperands which should simplify the backend by reducing the number of register classes and also make it easier to implement the assembler.
-rw-r--r--lib/Target/R600/AMDGPUISelDAGToDAG.cpp4
-rw-r--r--lib/Target/R600/MCTargetDesc/AMDGPUMCTargetDesc.cpp1
-rw-r--r--lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp16
-rw-r--r--lib/Target/R600/SIDefines.h19
-rw-r--r--lib/Target/R600/SIISelLowering.cpp6
-rw-r--r--lib/Target/R600/SIInstrInfo.cpp4
-rw-r--r--lib/Target/R600/SIInstrInfo.td22
-rw-r--r--lib/Target/R600/SIRegisterInfo.cpp33
-rw-r--r--lib/Target/R600/SIRegisterInfo.h16
-rw-r--r--lib/Target/R600/SIRegisterInfo.td34
-rw-r--r--test/CodeGen/R600/srl.ll2
-rw-r--r--test/CodeGen/R600/sub.ll2
-rw-r--r--test/CodeGen/R600/xor.ll2
13 files changed, 88 insertions, 73 deletions
diff --git a/lib/Target/R600/AMDGPUISelDAGToDAG.cpp b/lib/Target/R600/AMDGPUISelDAGToDAG.cpp
index ad5a5417ee3..10c5b47c097 100644
--- a/lib/Target/R600/AMDGPUISelDAGToDAG.cpp
+++ b/lib/Target/R600/AMDGPUISelDAGToDAG.cpp
@@ -1083,7 +1083,9 @@ SDNode *AMDGPUDAGToDAGISel::SelectAddrSpaceCast(SDNode *N) {
if (DestSize > SrcSize) {
assert(SrcSize == 32 && DestSize == 64);
- SDValue RC = CurDAG->getTargetConstant(AMDGPU::VSrc_64RegClassID, MVT::i32);
+ // FIXME: This is probably wrong, we should never be defining
+ // a register class with both VGPRs and SGPRs
+ SDValue RC = CurDAG->getTargetConstant(AMDGPU::VS_64RegClassID, MVT::i32);
const SDValue Ops[] = {
RC,
diff --git a/lib/Target/R600/MCTargetDesc/AMDGPUMCTargetDesc.cpp b/lib/Target/R600/MCTargetDesc/AMDGPUMCTargetDesc.cpp
index 8731055c461..bbcce0205ee 100644
--- a/lib/Target/R600/MCTargetDesc/AMDGPUMCTargetDesc.cpp
+++ b/lib/Target/R600/MCTargetDesc/AMDGPUMCTargetDesc.cpp
@@ -14,6 +14,7 @@
#include "AMDGPUMCTargetDesc.h"
#include "AMDGPUMCAsmInfo.h"
+#include "SIDefines.h"
#include "InstPrinter/AMDGPUInstPrinter.h"
#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
diff --git a/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp b/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp
index 999fd0dbc9a..3189952e8c1 100644
--- a/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp
+++ b/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp
@@ -86,12 +86,16 @@ MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII,
bool SIMCCodeEmitter::isSrcOperand(const MCInstrDesc &Desc,
unsigned OpNo) const {
unsigned RegClass = Desc.OpInfo[OpNo].RegClass;
- return (AMDGPU::SSrc_32RegClassID == RegClass) ||
- (AMDGPU::SSrc_64RegClassID == RegClass) ||
- (AMDGPU::VSrc_32RegClassID == RegClass) ||
- (AMDGPU::VSrc_64RegClassID == RegClass) ||
- (AMDGPU::VCSrc_32RegClassID == RegClass) ||
- (AMDGPU::VCSrc_64RegClassID == RegClass);
+ unsigned OpType = Desc.OpInfo[OpNo].OperandType;
+
+ return (OpType == AMDGPU::OPERAND_REG_IMM32 &&
+ (AMDGPU::SReg_32RegClassID == RegClass ||
+ AMDGPU::SReg_64RegClassID == RegClass ||
+ AMDGPU::VS_32RegClassID == RegClass ||
+ AMDGPU::VS_64RegClassID == RegClass)) ||
+ (OpType == AMDGPU::OPERAND_REG_INLINE_C &&
+ (AMDGPU::VS_32RegClassID == RegClass ||
+ (AMDGPU::VS_64RegClassID == RegClass)));
}
uint32_t SIMCCodeEmitter::getLitEncoding(const MCOperand &MO) const {
diff --git a/lib/Target/R600/SIDefines.h b/lib/Target/R600/SIDefines.h
index 759ed1bba1a..09322e5b1a2 100644
--- a/lib/Target/R600/SIDefines.h
+++ b/lib/Target/R600/SIDefines.h
@@ -8,6 +8,8 @@
/// \file
//===----------------------------------------------------------------------===//
+#include "llvm/MC/MCInstrDesc.h"
+
#ifndef LLVM_LIB_TARGET_R600_SIDEFINES_H
#define LLVM_LIB_TARGET_R600_SIDEFINES_H
@@ -37,6 +39,23 @@ enum {
};
}
+namespace llvm {
+namespace AMDGPU {
+ enum OperandType {
+ /// Operand with an SGPR or 32-bit immediate
+ OPERAND_SSRC = llvm::MCOI::OPERAND_FIRST_TARGET,
+ /// Operand with SGPR, VGPR, or 32-bit immediate
+ OPERAND_VSRC,
+ /// Operand with SGPR, VGPR, or inline constant
+ OPERAND_VCSRC,
+ /// Operand with register or 32-bit immediate
+ OPERAND_REG_IMM32,
+ /// Operand with register or inline constant
+ OPERAND_REG_INLINE_C
+ };
+}
+}
+
namespace SIInstrFlags {
enum Flags {
// First 4 bits are the instruction encoding
diff --git a/lib/Target/R600/SIISelLowering.cpp b/lib/Target/R600/SIISelLowering.cpp
index 19a84234852..78ea49f7972 100644
--- a/lib/Target/R600/SIISelLowering.cpp
+++ b/lib/Target/R600/SIISelLowering.cpp
@@ -1560,10 +1560,8 @@ SDValue SITargetLowering::PerformDAGCombine(SDNode *N,
static bool isVSrc(unsigned RegClass) {
switch(RegClass) {
default: return false;
- case AMDGPU::VSrc_32RegClassID:
- case AMDGPU::VCSrc_32RegClassID:
- case AMDGPU::VSrc_64RegClassID:
- case AMDGPU::VCSrc_64RegClassID:
+ case AMDGPU::VS_32RegClassID:
+ case AMDGPU::VS_64RegClassID:
return true;
}
}
diff --git a/lib/Target/R600/SIInstrInfo.cpp b/lib/Target/R600/SIInstrInfo.cpp
index 32b29a574e5..c0fb68edb7c 100644
--- a/lib/Target/R600/SIInstrInfo.cpp
+++ b/lib/Target/R600/SIInstrInfo.cpp
@@ -966,9 +966,9 @@ bool SIInstrInfo::isImmOperandLegal(const MachineInstr *MI, unsigned OpNo,
return false;
if (isLiteralConstant(MO))
- return RI.regClassCanUseLiteralConstant(OpInfo.RegClass);
+ return RI.opCanUseLiteralConstant(OpInfo.OperandType);
- return RI.regClassCanUseInlineConstant(OpInfo.RegClass);
+ return RI.opCanUseInlineConstant(OpInfo.OperandType);
}
bool SIInstrInfo::canFoldOffset(unsigned OffsetSize, unsigned AS) const {
diff --git a/lib/Target/R600/SIInstrInfo.td b/lib/Target/R600/SIInstrInfo.td
index 27a63c01d2b..aa40378b10d 100644
--- a/lib/Target/R600/SIInstrInfo.td
+++ b/lib/Target/R600/SIInstrInfo.td
@@ -487,7 +487,7 @@ multiclass SOP2_64_32 <sop2 op, string opName, list<dag> pattern> {
}
-class SOPC_Helper <bits<7> op, RegisterClass rc, ValueType vt,
+class SOPC_Helper <bits<7> op, RegisterOperand rc, ValueType vt,
string opName, PatLeaf cond> : SOPC <
op, (outs SCCReg:$dst), (ins rc:$src0, rc:$src1),
opName#" $dst, $src0, $src1", []>;
@@ -613,7 +613,7 @@ class getVALUDstForVT<ValueType VT> {
// Returns the register class to use for source 0 of VOP[12C]
// instructions for the given VT.
class getVOPSrc0ForVT<ValueType VT> {
- RegisterClass ret = !if(!eq(VT.Size, 32), VSrc_32, VSrc_64);
+ RegisterOperand ret = !if(!eq(VT.Size, 32), VSrc_32, VSrc_64);
}
// Returns the register class to use for source 1 of VOP[12C] for the
@@ -625,7 +625,7 @@ class getVOPSrc1ForVT<ValueType VT> {
// Returns the register class to use for sources of VOP3 instructions for the
// given VT.
class getVOP3SrcForVT<ValueType VT> {
- RegisterClass ret = !if(!eq(VT.Size, 32), VCSrc_32, VCSrc_64);
+ RegisterOperand ret = !if(!eq(VT.Size, 32), VCSrc_32, VCSrc_64);
}
// Returns 1 if the source arguments have modifiers, 0 if they do not.
@@ -635,15 +635,15 @@ class hasModifiers<ValueType SrcVT> {
}
// Returns the input arguments for VOP[12C] instructions for the given SrcVT.
-class getIns32 <RegisterClass Src0RC, RegisterClass Src1RC, int NumSrcArgs> {
+class getIns32 <RegisterOperand Src0RC, RegisterClass Src1RC, int NumSrcArgs> {
dag ret = !if(!eq(NumSrcArgs, 1), (ins Src0RC:$src0), // VOP1
!if(!eq(NumSrcArgs, 2), (ins Src0RC:$src0, Src1RC:$src1), // VOP2
(ins)));
}
// Returns the input arguments for VOP3 instructions for the given SrcVT.
-class getIns64 <RegisterClass Src0RC, RegisterClass Src1RC,
- RegisterClass Src2RC, int NumSrcArgs,
+class getIns64 <RegisterOperand Src0RC, RegisterOperand Src1RC,
+ RegisterOperand Src2RC, int NumSrcArgs,
bit HasModifiers> {
dag ret =
@@ -714,11 +714,11 @@ class VOPProfile <list<ValueType> _ArgVT> {
field ValueType Src1VT = ArgVT[2];
field ValueType Src2VT = ArgVT[3];
field RegisterClass DstRC = getVALUDstForVT<DstVT>.ret;
- field RegisterClass Src0RC32 = getVOPSrc0ForVT<Src0VT>.ret;
+ field RegisterOperand Src0RC32 = getVOPSrc0ForVT<Src0VT>.ret;
field RegisterClass Src1RC32 = getVOPSrc1ForVT<Src1VT>.ret;
- field RegisterClass Src0RC64 = getVOP3SrcForVT<Src0VT>.ret;
- field RegisterClass Src1RC64 = getVOP3SrcForVT<Src1VT>.ret;
- field RegisterClass Src2RC64 = getVOP3SrcForVT<Src2VT>.ret;
+ field RegisterOperand Src0RC64 = getVOP3SrcForVT<Src0VT>.ret;
+ field RegisterOperand Src1RC64 = getVOP3SrcForVT<Src1VT>.ret;
+ field RegisterOperand Src2RC64 = getVOP3SrcForVT<Src2VT>.ret;
field int NumSrcArgs = getNumSrcArgs<Src1VT, Src2VT>.ret;
field bit HasModifiers = hasModifiers<Src0VT>.ret;
@@ -1178,7 +1178,7 @@ class VOP3InstVI <bits<10> op, string opName, VOPProfile P,
P.NumSrcArgs, P.HasModifiers
>;
-multiclass VOP3b_Helper <vop op, RegisterClass vrc, RegisterClass arc,
+multiclass VOP3b_Helper <vop op, RegisterClass vrc, RegisterOperand arc,
string opName, list<dag> pattern> :
VOP3b_2_m <
op, (outs vrc:$vdst, SReg_64:$sdst),
diff --git a/lib/Target/R600/SIRegisterInfo.cpp b/lib/Target/R600/SIRegisterInfo.cpp
index 5dc0f755f14..4ef6673f77f 100644
--- a/lib/Target/R600/SIRegisterInfo.cpp
+++ b/lib/Target/R600/SIRegisterInfo.cpp
@@ -390,40 +390,17 @@ unsigned SIRegisterInfo::getPhysRegSubReg(unsigned Reg,
return SubRC->getRegister(Index + Channel);
}
-bool SIRegisterInfo::regClassCanUseLiteralConstant(int RCID) const {
- switch (RCID) {
- default: return false;
- case AMDGPU::SSrc_32RegClassID:
- case AMDGPU::SSrc_64RegClassID:
- case AMDGPU::VSrc_32RegClassID:
- case AMDGPU::VSrc_64RegClassID:
- return true;
- }
+bool SIRegisterInfo::opCanUseLiteralConstant(unsigned OpType) const {
+ return OpType == AMDGPU::OPERAND_REG_IMM32;
}
-bool SIRegisterInfo::regClassCanUseLiteralConstant(
- const TargetRegisterClass *RC) const {
- return regClassCanUseLiteralConstant(RC->getID());
-}
-
-bool SIRegisterInfo::regClassCanUseInlineConstant(int RCID) const {
- if (regClassCanUseLiteralConstant(RCID))
+bool SIRegisterInfo::opCanUseInlineConstant(unsigned OpType) const {
+ if (opCanUseLiteralConstant(OpType))
return true;
- switch (RCID) {
- default: return false;
- case AMDGPU::VCSrc_32RegClassID:
- case AMDGPU::VCSrc_64RegClassID:
- return true;
- }
-}
-
-bool SIRegisterInfo::regClassCanUseInlineConstant(
- const TargetRegisterClass *RC) const {
- return regClassCanUseInlineConstant(RC->getID());
+ return OpType == AMDGPU::OPERAND_REG_INLINE_C;
}
-
unsigned SIRegisterInfo::getPreloadedValue(const MachineFunction &MF,
enum PreloadedValue Value) const {
diff --git a/lib/Target/R600/SIRegisterInfo.h b/lib/Target/R600/SIRegisterInfo.h
index c7e54dbf0ec..0f11687af8d 100644
--- a/lib/Target/R600/SIRegisterInfo.h
+++ b/lib/Target/R600/SIRegisterInfo.h
@@ -80,22 +80,14 @@ struct SIRegisterInfo : public AMDGPURegisterInfo {
unsigned getPhysRegSubReg(unsigned Reg, const TargetRegisterClass *SubRC,
unsigned Channel) const;
- /// \returns True if operands defined with this register class can accept
+ /// \returns True if operands defined with this operand type can accept
/// a literal constant (i.e. any 32-bit immediate).
- bool regClassCanUseLiteralConstant(int RCID) const;
+ bool opCanUseLiteralConstant(unsigned OpType) const;
- /// \returns True if operands defined with this register class can accept
- /// a literal constant (i.e. any 32-bit immediate).
- bool regClassCanUseLiteralConstant(const TargetRegisterClass *RC) const;
-
- /// \returns True if operands defined with this register class can accept
+ /// \returns True if operands defined with this operand type can accept
/// an inline constant. i.e. An integer value in the range (-16, 64) or
/// -4.0f, -2.0f, -1.0f, -0.5f, 0.0f, 0.5f, 1.0f, 2.0f, 4.0f.
- bool regClassCanUseInlineConstant(int RCID) const;
-
- /// \returns True if operands defined with this register class can accept
- /// a literal constant. i.e. A value in the range (-16, 64).
- bool regClassCanUseInlineConstant(const TargetRegisterClass *RC) const;
+ bool opCanUseInlineConstant(unsigned OpType) const;
enum PreloadedValue {
TGID_X,
diff --git a/lib/Target/R600/SIRegisterInfo.td b/lib/Target/R600/SIRegisterInfo.td
index 45c2b414a3e..f938ed60f28 100644
--- a/lib/Target/R600/SIRegisterInfo.td
+++ b/lib/Target/R600/SIRegisterInfo.td
@@ -217,25 +217,47 @@ def VReg_1 : RegisterClass<"AMDGPU", [i1], 32, (add VGPR_32)>;
// SSrc_* Operands with an SGPR or a 32-bit immediate
//===----------------------------------------------------------------------===//
-def SSrc_32 : RegisterClass<"AMDGPU", [i32, f32], 32, (add SReg_32)>;
+def SSrc_32 : RegisterOperand<SReg_32> {
+ let OperandNamespace = "AMDGPU";
+ let OperandType = "OPERAND_REG_IMM32";
+}
-def SSrc_64 : RegisterClass<"AMDGPU", [i64, f64, i1], 64, (add SReg_64)>;
+def SSrc_64 : RegisterOperand<SReg_64> {
+ let OperandNamespace = "AMDGPU";
+ let OperandType = "OPERAND_REG_IMM32";
+}
//===----------------------------------------------------------------------===//
// VSrc_* Operands with an SGPR, VGPR or a 32-bit immediate
//===----------------------------------------------------------------------===//
-def VSrc_32 : RegisterClass<"AMDGPU", [i32, f32], 32, (add VReg_32, SReg_32)>;
+def VS_32 : RegisterClass<"AMDGPU", [i32, f32], 32, (add VReg_32, SReg_32)>;
+
+def VS_64 : RegisterClass<"AMDGPU", [i64, f64], 64, (add VReg_64, SReg_64)>;
+
+def VSrc_32 : RegisterOperand<VS_32> {
+ let OperandNamespace = "AMDGPU";
+ let OperandType = "OPERAND_REG_IMM32";
+}
-def VSrc_64 : RegisterClass<"AMDGPU", [i64, f64], 64, (add VReg_64, SReg_64)>;
+def VSrc_64 : RegisterOperand<VS_64> {
+ let OperandNamespace = "AMDGPU";
+ let OperandType = "OPERAND_REG_IMM32";
+}
//===----------------------------------------------------------------------===//
// VCSrc_* Operands with an SGPR, VGPR or an inline constant
//===----------------------------------------------------------------------===//
-def VCSrc_32 : RegisterClass<"AMDGPU", [i32, f32], 32, (add VReg_32, SReg_32)>;
+def VCSrc_32 : RegisterOperand<VS_32> {
+ let OperandNamespace = "AMDGPU";
+ let OperandType = "OPERAND_REG_INLINE_C";
+}
-def VCSrc_64 : RegisterClass<"AMDGPU", [i64, f64], 64, (add VReg_64, SReg_64)>;
+def VCSrc_64 : RegisterOperand<VS_64> {
+ let OperandNamespace = "AMDGPU";
+ let OperandType = "OPERAND_REG_INLINE_C";
+}
//===----------------------------------------------------------------------===//
// SGPR and VGPR register classes
diff --git a/test/CodeGen/R600/srl.ll b/test/CodeGen/R600/srl.ll
index bb68cbf6edf..3b19c15a877 100644
--- a/test/CodeGen/R600/srl.ll
+++ b/test/CodeGen/R600/srl.ll
@@ -2,7 +2,7 @@
; RUN: llc -march=r600 -mcpu=redwood < %s | FileCheck -check-prefix=EG -check-prefix=FUNC %s
; FUNC-LABEL: {{^}}lshr_i32:
-; SI: v_lshr_b32_e32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
+; SI: v_lshrrev_b32_e32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
; EG: LSHR {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
define void @lshr_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) {
%b_ptr = getelementptr i32 addrspace(1)* %in, i32 1
diff --git a/test/CodeGen/R600/sub.ll b/test/CodeGen/R600/sub.ll
index 1f129a61fd4..5d7bc00bb6f 100644
--- a/test/CodeGen/R600/sub.ll
+++ b/test/CodeGen/R600/sub.ll
@@ -7,7 +7,7 @@ declare i32 @llvm.r600.read.tidig.x() readnone
; FUNC-LABEL: {{^}}test_sub_i32:
; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
-; SI: v_sub_i32_e32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
+; SI: v_subrev_i32_e32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
define void @test_sub_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) {
%b_ptr = getelementptr i32 addrspace(1)* %in, i32 1
%a = load i32 addrspace(1)* %in
diff --git a/test/CodeGen/R600/xor.ll b/test/CodeGen/R600/xor.ll
index bf98e7df86a..d6816c85287 100644
--- a/test/CodeGen/R600/xor.ll
+++ b/test/CodeGen/R600/xor.ll
@@ -59,7 +59,7 @@ define void @xor_i1(float addrspace(1)* %out, float addrspace(1)* %in0, float ad
; FUNC-LABEL: {{^}}v_xor_i1:
; SI: buffer_load_ubyte [[A:v[0-9]+]]
; SI: buffer_load_ubyte [[B:v[0-9]+]]
-; SI: v_xor_b32_e32 [[XOR:v[0-9]+]], [[B]], [[A]]
+; SI: v_xor_b32_e32 [[XOR:v[0-9]+]], [[A]], [[B]]
; SI: v_and_b32_e32 [[RESULT:v[0-9]+]], 1, [[XOR]]
; SI: buffer_store_byte [[RESULT]]
define void @v_xor_i1(i1 addrspace(1)* %out, i1 addrspace(1)* %in0, i1 addrspace(1)* %in1) {