summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Stellard <thomas.stellard@amd.com>2012-10-08 15:37:39 +0200
committerTom Stellard <thomas.stellard@amd.com>2012-10-17 19:20:27 +0000
commit831c5c82f3fc1899e51d1bd976587f4c2b4ef84f (patch)
treea511a6903b658af6636aafc5eed9eab58b470ec5
parentfbadea4f5104ea7da8eedf7d134ec513ba94f4e9 (diff)
R600: Use native operands for R600_1OP instructions
-rw-r--r--lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp61
-rw-r--r--lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h10
-rw-r--r--lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp64
-rw-r--r--lib/Target/AMDGPU/R600Defines.h51
-rw-r--r--lib/Target/AMDGPU/R600InstrInfo.cpp109
-rw-r--r--lib/Target/AMDGPU/R600InstrInfo.h10
-rw-r--r--lib/Target/AMDGPU/R600Instructions.td263
-rw-r--r--lib/Target/AMDGPU/R600RegisterInfo.td4
8 files changed, 444 insertions, 128 deletions
diff --git a/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp b/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
index 5e302553477..7e761d52408 100644
--- a/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
+++ b/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
@@ -44,4 +44,65 @@ void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
printOperand(MI, OpNo, O);
}
+void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O, StringRef Asm) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ assert(Op.isImm());
+ if (Op.getImm() == 1) {
+ O << Asm;
+ }
+}
+
+void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ printIfSet(MI, OpNo, O, "|");
+}
+
+void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ printIfSet(MI, OpNo, O, "_SAT");
+}
+
+void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ printIfSet(MI, OpNo, O, " *");
+}
+
+void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ printIfSet(MI, OpNo, O, "-");
+}
+
+void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ switch (MI->getOperand(OpNo).getImm()) {
+ default: break;
+ case 1:
+ O << " * 2.0";
+ break;
+ case 2:
+ O << " * 4.0";
+ break;
+ case 3:
+ O << " / 2.0";
+ break;
+ }
+}
+
+void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ if (Op.getImm() != 0) {
+ O << " + " + Op.getImm();
+ }
+}
+
+void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ if (Op.getImm() == 0) {
+ O << " (MASKED)";
+ }
+}
+
#include "AMDGPUGenAsmWriter.inc"
diff --git a/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h b/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h
index b4efa5538ae..b4feb6fb3f9 100644
--- a/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h
+++ b/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h
@@ -33,8 +33,14 @@ private:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
// void printUnsignedImm(const MCInst *MI, int OpNo, raw_ostream &O);
void printMemOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
-
-
+ void printIfSet(const MCInst *MI, unsigned OpNo, raw_ostream &O, StringRef Asm);
+ void printAbs(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printClamp(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printLast(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printNeg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printOMOD(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printRel(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printWrite(const MCInst *MI, unsigned OpNo, raw_ostream &O);
};
} // End namespace llvm
diff --git a/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp b/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp
index dd2a511fa8a..a9d04408542 100644
--- a/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp
+++ b/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp
@@ -191,20 +191,6 @@ void R600MCCodeEmitter::EmitALUInstr(const MCInst &MI,
const MCInstrDesc &MCDesc = MCII.get(MI.getOpcode());
unsigned NumOperands = MI.getNumOperands();
- if(MCDesc.findFirstPredOperandIdx() > -1)
- NumOperands--;
-
- if (GET_FLAG_OPERAND_IDX(MCDesc.TSFlags) != 0)
- NumOperands--;
-
- if(MI.getOpcode() == AMDGPU::PRED_X)
- NumOperands = 2;
-
- // XXX Check if instruction writes a result
- if (NumOperands < 1) {
- return;
- }
-
// Emit instruction type
EmitByte(INSTR_ALU, OS);
@@ -219,6 +205,40 @@ void R600MCCodeEmitter::EmitALUInstr(const MCInst &MI,
InstWord01 |= ISAOpCode << 1;
}
+ if (HAS_NATIVE_OPERANDS(MCDesc.TSFlags)) {
+ unsigned SrcIdx = 0;
+ for (unsigned int OpIdx = 1; OpIdx < NumOperands; ++OpIdx) {
+ if (MI.getOperand(OpIdx).isImm() || MI.getOperand(OpIdx).isFPImm() ||
+ OpIdx == (unsigned)MCDesc.findFirstPredOperandIdx()) {
+ continue;
+ }
+ EmitSrcISA(MI, OpIdx, InstWord01, OS);
+ SrcIdx++;
+ }
+
+ // Emit zeros for unused sources
+ for ( ; SrcIdx < 3; SrcIdx++) {
+ EmitNullBytes(SRC_BYTE_COUNT - 6, OS);
+ }
+
+ Emit(InstWord01, OS);
+ return;
+ }
+
+ if(MCDesc.findFirstPredOperandIdx() > -1)
+ NumOperands--;
+
+ if (GET_FLAG_OPERAND_IDX(MCDesc.TSFlags) != 0)
+ NumOperands--;
+
+ if(MI.getOpcode() == AMDGPU::PRED_X)
+ NumOperands = 2;
+
+ // XXX Check if instruction writes a result
+ if (NumOperands < 1) {
+ return;
+ }
+
unsigned int OpIndex;
for (OpIndex = 1; OpIndex < NumOperands; OpIndex++) {
// Literal constants are always stored as the last operand.
@@ -383,6 +403,13 @@ void R600MCCodeEmitter::EmitSrcISA(const MCInst &MI, unsigned OpIdx,
EmitTwoBytes(0, OS);
}
+ // Emit the literal value, if applicable (4 bytes).
+ Emit(InlineConstant.i, OS);
+
+ if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags)) {
+ return;
+ }
+
// source channel
uint64_t sourceChannelValue = getHWRegChan(MO.getReg());
if (OpIdx == 1)
@@ -414,9 +441,6 @@ void R600MCCodeEmitter::EmitSrcISA(const MCInst &MI, unsigned OpIdx,
// XXX: relative addressing mode
// XXX: kc_bank
- // Emit the literal value, if applicable (4 bytes).
- Emit(InlineConstant.i, OS);
-
}
void R600MCCodeEmitter::EmitTexInstr(const MCInst &MI,
@@ -612,7 +636,11 @@ uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI,
const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixup) const {
if (MO.isReg()) {
- return getHWReg(MO.getReg());
+ if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags)) {
+ return MRI.getEncodingValue(MO.getReg());
+ } else {
+ return getHWReg(MO.getReg());
+ }
} else if (MO.isImm()) {
return MO.getImm();
} else {
diff --git a/lib/Target/AMDGPU/R600Defines.h b/lib/Target/AMDGPU/R600Defines.h
index 8191c6a64a7..a17d1341304 100644
--- a/lib/Target/AMDGPU/R600Defines.h
+++ b/lib/Target/AMDGPU/R600Defines.h
@@ -19,27 +19,58 @@
#define MO_FLAG_MASK (1 << 3)
#define MO_FLAG_PUSH (1 << 4)
#define MO_FLAG_NOT_LAST (1 << 5)
-#define NUM_MO_FLAGS 6
+#define MO_FLAG_LAST (1 << 6)
+#define NUM_MO_FLAGS 7
// Helper for finding getting the operand index for the instruction flags
// operand.
#define GET_FLAG_OPERAND_IDX(Flags) (((Flags) >> 7) & 0x3)
namespace R600_InstFlag {
- enum TIF {
- TRANS_ONLY = (1 << 0),
- TEX = (1 << 1),
- REDUCTION = (1 << 2),
- FC = (1 << 3),
- TRIG = (1 << 4),
- OP3 = (1 << 5),
- VECTOR = (1 << 6)
+ enum TIF {
+ TRANS_ONLY = (1 << 0),
+ TEX = (1 << 1),
+ REDUCTION = (1 << 2),
+ FC = (1 << 3),
+ TRIG = (1 << 4),
+ OP3 = (1 << 5),
+ VECTOR = (1 << 6),
//FlagOperand bits 7, 8
- };
+ NATIVE_OPERANDS = (1 << 9),
+ OP1 = (1 << 10),
+ OP2 = (1 << 11)
+ };
}
+#define HAS_NATIVE_OPERANDS(Flags) ((Flags) & R600_InstFlag::NATIVE_OPERANDS)
+
// Defines for extracting register infomation from register encoding
#define HW_REG_MASK 0x1ff
#define HW_CHAN_SHIFT 9
+namespace R600Operands {
+ enum Ops {
+ DST,
+ WRITE,
+ OMOD,
+ DST_REL,
+ CLAMP,
+ SRC0,
+ SRC0_NEG,
+ SRC0_REL,
+ SRC0_ABS,
+ SRC1,
+ SRC1_NEG,
+ SRC1_REL,
+ SRC1_ABS,
+ SRC2,
+ SRC2_NEG,
+ SRC2_REL,
+ LAST,
+ PRED_SEL,
+ IMM,
+ COUNT
+ };
+}
+
#endif // R600DEFINES_H_
diff --git a/lib/Target/AMDGPU/R600InstrInfo.cpp b/lib/Target/AMDGPU/R600InstrInfo.cpp
index f1da5c23902..7205b1b7536 100644
--- a/lib/Target/AMDGPU/R600InstrInfo.cpp
+++ b/lib/Target/AMDGPU/R600InstrInfo.cpp
@@ -475,6 +475,34 @@ unsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
return 2;
}
+int R600InstrInfo::getOperandIdx(const MachineInstr &MI,
+ R600Operands::Ops Op) const
+{
+ const static int OpTable[3][R600Operands::COUNT] = {
+// W C S S S S S S S S
+// R O D L S R R R S R R R S R R L P
+// D I M R A R C C C C C C C R C C A R I
+// S T O E M C 0 0 0 C 1 1 1 C 2 2 S E M
+// T E D L P 0 N R A 1 N R A 2 N R T D M
+ {0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,-1, 9,10,11},
+ {0, 1, 2, 3, 4 ,5 ,6 ,7, 8, 9,10,11,12,-1,-1,-1,13,14,15},
+ {0, 1, 2, 3, 4, 5, 6, 7,-1, 8, 9,10,-1,11,12,13,14,15,16}
+ };
+ unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
+ unsigned OpTableIdx;
+ if (TargetFlags & R600_InstFlag::OP1) {
+ OpTableIdx = 0;
+ } else if (TargetFlags & R600_InstFlag::OP2) {
+ OpTableIdx = 1;
+ } else {
+ assert((TargetFlags & R600_InstFlag::OP3) && "OP1, OP2, or OP3 not defined "
+ "for this instruction");
+ OpTableIdx = 2;
+ }
+
+ return OpTable[OpTableIdx][Op];
+}
+
//===----------------------------------------------------------------------===//
// Instruction flag getters/setters
//===----------------------------------------------------------------------===//
@@ -484,11 +512,56 @@ bool R600InstrInfo::hasFlagOperand(const MachineInstr &MI) const
return GET_FLAG_OPERAND_IDX(get(MI.getOpcode()).TSFlags) != 0;
}
-MachineOperand &R600InstrInfo::getFlagOp(MachineInstr *MI) const
+MachineOperand &R600InstrInfo::getFlagOp(MachineInstr *MI, unsigned SrcIdx,
+ unsigned Flag) const
{
- unsigned FlagIndex = GET_FLAG_OPERAND_IDX(get(MI->getOpcode()).TSFlags);
- assert(FlagIndex != 0 &&
+ unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
+ int FlagIndex = 0;
+ if (Flag != 0) {
+ // If we pass something other than the default value of Flag to this
+ // function, it means we are want to set a flag on an instruction
+ // that uses native encoding.
+ assert(HAS_NATIVE_OPERANDS(TargetFlags));
+ bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;
+ switch (Flag) {
+ case MO_FLAG_CLAMP:
+ FlagIndex = getOperandIdx(*MI, R600Operands::CLAMP);
+ break;
+ case MO_FLAG_MASK:
+ FlagIndex = getOperandIdx(*MI, R600Operands::WRITE);
+ break;
+ case MO_FLAG_NOT_LAST:
+ case MO_FLAG_LAST:
+ FlagIndex = getOperandIdx(*MI, R600Operands::LAST);
+ break;
+ case MO_FLAG_NEG:
+ switch (SrcIdx) {
+ case 0: FlagIndex = getOperandIdx(*MI, R600Operands::SRC0_NEG); break;
+ case 1: FlagIndex = getOperandIdx(*MI, R600Operands::SRC1_NEG); break;
+ case 2: FlagIndex = getOperandIdx(*MI, R600Operands::SRC2_NEG); break;
+ }
+ break;
+
+ case MO_FLAG_ABS:
+ assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "
+ "instructions.");
+ switch (SrcIdx) {
+ case 0: FlagIndex = getOperandIdx(*MI, R600Operands::SRC0_ABS); break;
+ case 1: FlagIndex = getOperandIdx(*MI, R600Operands::SRC1_ABS); break;
+ }
+ break;
+
+ default:
+ FlagIndex = -1;
+ break;
+ }
+ assert(FlagIndex != -1 && "Flag not supported for this instruction");
+ } else {
+ FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags);
+ assert(FlagIndex != 0 &&
"Instruction flags not supported for this instruction");
+ }
+
MachineOperand &FlagOp = MI->getOperand(FlagIndex);
assert(FlagOp.isImm());
return FlagOp;
@@ -497,15 +570,33 @@ MachineOperand &R600InstrInfo::getFlagOp(MachineInstr *MI) const
void R600InstrInfo::addFlag(MachineInstr *MI, unsigned Operand,
unsigned Flag) const
{
- MachineOperand &FlagOp = getFlagOp(MI);
- FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
+ unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
+ if (HAS_NATIVE_OPERANDS(TargetFlags)) {
+ MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
+ if (Flag == MO_FLAG_NOT_LAST) {
+ clearFlag(MI, Operand, MO_FLAG_LAST);
+ } else if (Flag == MO_FLAG_MASK) {
+ clearFlag(MI, Operand, Flag);
+ } else {
+ FlagOp.setImm(1);
+ }
+ } else {
+ MachineOperand &FlagOp = getFlagOp(MI, Operand);
+ FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
+ }
}
void R600InstrInfo::clearFlag(MachineInstr *MI, unsigned Operand,
unsigned Flag) const
{
- MachineOperand &FlagOp = getFlagOp(MI);
- unsigned InstFlags = FlagOp.getImm();
- InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand));
- FlagOp.setImm(InstFlags);
+ unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
+ if (HAS_NATIVE_OPERANDS(TargetFlags)) {
+ MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
+ FlagOp.setImm(0);
+ } else {
+ MachineOperand &FlagOp = getFlagOp(MI);
+ unsigned InstFlags = FlagOp.getImm();
+ InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand));
+ FlagOp.setImm(InstFlags);
+ }
}
diff --git a/lib/Target/AMDGPU/R600InstrInfo.h b/lib/Target/AMDGPU/R600InstrInfo.h
index 1c010756768..7c903c10845 100644
--- a/lib/Target/AMDGPU/R600InstrInfo.h
+++ b/lib/Target/AMDGPU/R600InstrInfo.h
@@ -16,6 +16,7 @@
#include "AMDIL.h"
#include "AMDGPUInstrInfo.h"
+#include "R600Defines.h"
#include "R600RegisterInfo.h"
#include <map>
@@ -109,6 +110,10 @@ namespace llvm {
virtual int getInstrLatency(const InstrItineraryData *ItinData,
SDNode *Node) const { return 1;}
+ /// getOperandIdx - Get the index of Op in the MachineInstr. Returns -1
+ /// if the Instruction does not contain the specified Op.
+ int getOperandIdx(const MachineInstr &MI, R600Operands::Ops Op) const;
+
///hasFlagOperand - Returns true if this instruction has an operand for
/// storing target flags.
bool hasFlagOperand(const MachineInstr &MI) const;
@@ -120,7 +125,10 @@ namespace llvm {
bool isFlagSet(const MachineInstr &MI, unsigned Operand, unsigned Flag) const;
///getFlagOp - Return the operand containing the flags for this instruction.
- MachineOperand &getFlagOp(MachineInstr *MI) const;
+ /// SrcIdx is the register source to set the flag on (e.g src0, src1, src2)
+ /// Flag is the flag being set.
+ MachineOperand &getFlagOp(MachineInstr *MI, unsigned SrcIdx = 0,
+ unsigned Flag = 0) const;
///clearFlag - Clear the specified flag on the instruction.
void clearFlag(MachineInstr *MI, unsigned Operand, unsigned Flag) const;
diff --git a/lib/Target/AMDGPU/R600Instructions.td b/lib/Target/AMDGPU/R600Instructions.td
index 716bfd899ea..3d997d0ea01 100644
--- a/lib/Target/AMDGPU/R600Instructions.td
+++ b/lib/Target/AMDGPU/R600Instructions.td
@@ -22,6 +22,9 @@ class InstR600 <bits<11> inst, dag outs, dag ins, string asm, list<dag> pattern,
bit Op3 = 0;
bit isVector = 0;
bits<2> FlagOperandIdx = 0;
+ bit Op1 = 0;
+ bit Op2 = 0;
+ bit HasNativeOperands = 0;
bits<11> op_code = inst;
//let Inst = inst;
@@ -39,6 +42,9 @@ class InstR600 <bits<11> inst, dag outs, dag ins, string asm, list<dag> pattern,
// instruction group
let TSFlags{6} = isVector;
let TSFlags{8-7} = FlagOperandIdx;
+ let TSFlags{9} = HasNativeOperands;
+ let TSFlags{10} = Op1;
+ let TSFlags{11} = Op2;
}
class InstR600ISA <dag outs, dag ins, string asm, list<dag> pattern> :
@@ -57,43 +63,162 @@ def MEMrr : Operand<iPTR> {
let MIOperandInfo = (ops R600_Reg32:$ptr, R600_Reg32:$index);
}
-def InstFlag : OperandWithDefaultOps <i32, (ops (i32 0))>;
+// Operands for non-registers
+
+class InstFlag<string PM = "printOperand", int Default = 0>
+ : OperandWithDefaultOps <i32, (ops (i32 Default))> {
+ let PrintMethod = PM;
+}
+
+def LITERAL : InstFlag;
+
+def WRITE : InstFlag <"printWrite", 1>;
+def OMOD : InstFlag <"printOMOD">;
+def REL : InstFlag <"printRel">;
+def CLAMP : InstFlag <"printClamp">;
+def NEG : InstFlag <"printNeg">;
+def ABS : InstFlag <"printAbs">;
+
+// XXX: The r600g finalizer in Mesa expects last to be one in most cases.
+// Once we start using the packetizer in this backend we should have this
+// default to 0.
+def LAST : InstFlag<"printLast", 1>;
def ADDRParam : ComplexPattern<i32, 2, "SelectADDRParam", [], []>;
def ADDRDWord : ComplexPattern<i32, 1, "SelectADDRDWord", [], []>;
def ADDRVTX_READ : ComplexPattern<i32, 2, "SelectADDRVTX_READ", [], []>;
-class R600_ALU {
+class R600ALU_Word0 {
+ field bits<32> Word0;
- bits<7> DST_GPR = 0;
- bits<9> SRC0_SEL = 0;
- bits<1> SRC0_NEG = 0;
- bits<9> SRC1_SEL = 0;
- bits<1> SRC1_NEG = 0;
- bits<1> CLAMP = 0;
-
+ bits<11> src0;
+ bits<1> src0_neg;
+ bits<1> src0_rel;
+ bits<11> src1;
+ bits<1> src1_rel;
+ bits<1> src1_neg;
+ bits<3> index_mode = 0;
+ bits<2> pred_sel;
+ bits<1> last;
+
+ bits<9> src0_sel = src0{8-0};
+ bits<2> src0_chan = src0{10-9};
+ bits<9> src1_sel = src1{8-0};
+ bits<2> src1_chan = src1{10-9};
+
+ let Word0{8-0} = src0_sel;
+ let Word0{9} = src0_rel;
+ let Word0{11-10} = src0_chan;
+ let Word0{12} = src0_neg;
+ let Word0{21-13} = src1_sel;
+ let Word0{22} = src1_rel;
+ let Word0{24-23} = src1_chan;
+ let Word0{25} = src1_neg;
+ let Word0{28-26} = index_mode;
+ let Word0{30-29} = pred_sel;
+ let Word0{31} = last;
+}
+
+class R600ALU_Word1_OP2 <bits<11> alu_inst> {
+ field bits<32> Word1;
+
+ bits<1> src0_abs;
+ bits<1> src1_abs;
+ bits<1> update_exec_mask = 0;
+ bits<1> update_pred = 0;
+ bits<1> write;
+ bits<2> omod;
+ bits<3> bank_swizzle = 0;
+ bits<11> dst;
+ bits<1> dst_rel;
+ bits<1> clamp;
+
+ bits<7> dst_sel = dst{6-0};
+ bits<2> dst_chan = dst{10-9};
+
+ let Word1{0} = src0_abs;
+ let Word1{1} = src1_abs;
+ let Word1{2} = update_exec_mask;
+ let Word1{3} = update_pred;
+ let Word1{4} = write;
+ let Word1{6-5} = omod;
+ let Word1{17-7} = alu_inst;
+ let Word1{20-18} = bank_swizzle;
+ let Word1{27-21} = dst_sel;
+ let Word1{28} = dst_rel;
+ let Word1{30-29} = dst_chan;
+ let Word1{31} = clamp;
}
+/*
+XXX: R600 subtarget uses a slightly different encoding than the other
+subtargets. We currently handle this in R600MCCodeEmitter, but we may
+want to use these instruction classes in the future.
+
+class R600ALU_Word1_OP2_r600 : R600ALU_Word1_OP2 {
+
+ bits<1> fog_merge;
+ bits<10> alu_inst;
+
+ let Inst{37} = fog_merge;
+ let Inst{39-38} = omod;
+ let Inst{49-40} = alu_inst;
+}
+
+class R600ALU_Word1_OP2_r700 : R600ALU_Word1_OP2 {
+
+ bits<11> alu_inst;
+
+ let Inst{38-37} = omod;
+ let Inst{49-39} = alu_inst;
+}
+*/
+
def R600_Pred : PredicateOperand<i32, (ops R600_Predicate),
(ops PRED_SEL_OFF)>;
let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
+// Class for instructions with only one source register.
+// If you add new ins to this instruction, make sure they are listed before
+// $literal, because the backend currently assumes that the last operand is
+// a literal. Also be sure to update the enum R600Op1OperandIndex::ROI in
+// R600Defines.h, R600InstrInfo::buildDefaultInstruction(),
+// and R600InstrInfo::getOperandIdx().
class R600_1OP <bits<11> inst, string opName, list<dag> pattern,
InstrItinClass itin = AnyALU> :
- InstR600 <inst,
- (outs R600_Reg32:$dst),
- (ins R600_Reg32:$src, R600_Pred:$p, variable_ops),
- !strconcat(opName, " $dst, $src $p"),
- pattern,
- itin>{
- bits<7> dst;
- bits<9> src;
- let Inst{8-0} = src;
- let Inst{49-39} = inst;
- let Inst{59-53} = dst;
- }
+ InstR600 <0,
+ (outs R600_Reg32:$dst),
+ (ins WRITE:$write, OMOD:$omod, REL:$dst_rel, CLAMP:$clamp,
+ R600_Reg32:$src0, NEG:$src0_neg, REL:$src0_rel, ABS:$src0_abs,
+ LAST:$last, R600_Pred:$pred_sel, LITERAL:$literal),
+ !strconcat(opName,
+ "$clamp $dst$write$dst_rel$omod, "
+ "$src0_neg$src0_abs$src0$src0_abs$src0_rel, "
+ "$literal $pred_sel$last"),
+ pattern,
+ itin>,
+ R600ALU_Word0,
+ R600ALU_Word1_OP2 <inst> {
+
+ let src1 = 0;
+ let src1_rel = 0;
+ let src1_neg = 0;
+ let src1_abs = 0;
+ let HasNativeOperands = 1;
+ let Op1 = 1;
+ let DisableEncoding = "$literal";
+
+ let Inst{31-0} = Word0;
+ let Inst{63-32} = Word1;
+}
+
+class R600_1OP_Helper <bits<11> inst, string opName, SDPatternOperator node,
+ InstrItinClass itin = AnyALU> :
+ R600_1OP <inst, opName,
+ [(set R600_Reg32:$dst, (node R600_Reg32:$src0))]
+>;
class R600_2OP <bits<11> inst, string opName, list<dag> pattern,
InstrItinClass itin = AnyALU> :
@@ -383,30 +508,11 @@ def SNE : R600_2OP <
COND_NE))]
>;
-def FRACT : R600_1OP <
- 0x10, "FRACT",
- [(set R600_Reg32:$dst, (AMDGPUfract R600_Reg32:$src))]
->;
-
-def TRUNC : R600_1OP <
- 0x11, "TRUNC",
- [(set R600_Reg32:$dst, (int_AMDGPU_trunc R600_Reg32:$src))]
->;
-
-def CEIL : R600_1OP <
- 0x12, "CEIL",
- [(set R600_Reg32:$dst, (fceil R600_Reg32:$src))]
->;
-
-def RNDNE : R600_1OP <
- 0x13, "RNDNE",
- [(set R600_Reg32:$dst, (frint R600_Reg32:$src))]
->;
-
-def FLOOR : R600_1OP <
- 0x14, "FLOOR",
- [(set R600_Reg32:$dst, (ffloor R600_Reg32:$src))]
->;
+def FRACT : R600_1OP_Helper <0x10, "FRACT", AMDGPUfract>;
+def TRUNC : R600_1OP_Helper <0x11, "TRUNC", int_AMDGPU_trunc>;
+def CEIL : R600_1OP_Helper <0x12, "CEIL", fceil>;
+def RNDNE : R600_1OP_Helper <0x13, "RNDNE", frint>;
+def FLOOR : R600_1OP_Helper <0x14, "FLOOR", ffloor>;
let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
@@ -482,10 +588,7 @@ def XOR_INT : R600_2OP <
[(set R600_Reg32:$dst, (xor R600_Reg32:$src0, R600_Reg32:$src1))]
>;
-def NOT_INT : R600_1OP <
- 0x33, "NOT_INT",
- [(set R600_Reg32:$dst, (not R600_Reg32:$src))]
->;
+def NOT_INT : R600_1OP_Helper <0x33, "NOT_INT", not>;
def ADD_INT : R600_2OP <
0x34, "ADD_INT",
@@ -739,39 +842,32 @@ multiclass CUBE_Common <bits<11> inst> {
}
}
} // End mayLoad = 0, mayStore = 0, hasSideEffects = 0
-class EXP_IEEE_Common <bits<11> inst> : R600_1OP <
- inst, "EXP_IEEE",
- [(set R600_Reg32:$dst, (fexp2 R600_Reg32:$src))]
+class EXP_IEEE_Common <bits<11> inst> : R600_1OP_Helper <
+ inst, "EXP_IEEE", fexp2
>;
-class FLT_TO_INT_Common <bits<11> inst> : R600_1OP <
- inst, "FLT_TO_INT",
- [(set R600_Reg32:$dst, (fp_to_sint R600_Reg32:$src))]
+class FLT_TO_INT_Common <bits<11> inst> : R600_1OP_Helper <
+ inst, "FLT_TO_INT", fp_to_sint
>;
-class INT_TO_FLT_Common <bits<11> inst> : R600_1OP <
- inst, "INT_TO_FLT",
- [(set R600_Reg32:$dst, (sint_to_fp R600_Reg32:$src))]
+class INT_TO_FLT_Common <bits<11> inst> : R600_1OP_Helper <
+ inst, "INT_TO_FLT", sint_to_fp
>;
-class FLT_TO_UINT_Common <bits<11> inst> : R600_1OP <
- inst, "FLT_TO_UINT",
- [(set R600_Reg32:$dst, (fp_to_uint R600_Reg32:$src))]
+class FLT_TO_UINT_Common <bits<11> inst> : R600_1OP_Helper <
+ inst, "FLT_TO_UINT", fp_to_uint
>;
-class UINT_TO_FLT_Common <bits<11> inst> : R600_1OP <
- inst, "UINT_TO_FLT",
- [(set R600_Reg32:$dst, (uint_to_fp R600_Reg32:$src))]
+class UINT_TO_FLT_Common <bits<11> inst> : R600_1OP_Helper <
+ inst, "UINT_TO_FLT", uint_to_fp
>;
class LOG_CLAMPED_Common <bits<11> inst> : R600_1OP <
- inst, "LOG_CLAMPED",
- []
+ inst, "LOG_CLAMPED", []
>;
-class LOG_IEEE_Common <bits<11> inst> : R600_1OP <
- inst, "LOG_IEEE",
- [(set R600_Reg32:$dst, (flog2 R600_Reg32:$src))]
+class LOG_IEEE_Common <bits<11> inst> : R600_1OP_Helper <
+ inst, "LOG_IEEE", flog2
>;
class LSHL_Common <bits<11> inst> : R600_2OP <
@@ -810,28 +906,23 @@ class MULLO_UINT_Common <bits<11> inst> : R600_2OP <
>;
class RECIP_CLAMPED_Common <bits<11> inst> : R600_1OP <
- inst, "RECIP_CLAMPED",
- []
+ inst, "RECIP_CLAMPED", []
>;
-class RECIP_IEEE_Common <bits<11> inst> : R600_1OP <
- inst, "RECIP_IEEE",
- [(set R600_Reg32:$dst, (int_AMDGPU_rcp R600_Reg32:$src))]
+class RECIP_IEEE_Common <bits<11> inst> : R600_1OP_Helper <
+ inst, "RECIP_IEEE", int_AMDGPU_rcp
>;
-class RECIP_UINT_Common <bits<11> inst> : R600_1OP <
- inst, "RECIP_INT $dst, $src",
- [(set R600_Reg32:$dst, (AMDGPUurecip R600_Reg32:$src))]
+class RECIP_UINT_Common <bits<11> inst> : R600_1OP_Helper <
+ inst, "RECIP_UINT", AMDGPUurecip
>;
-class RECIPSQRT_CLAMPED_Common <bits<11> inst> : R600_1OP <
- inst, "RECIPSQRT_CLAMPED",
- [(set R600_Reg32:$dst, (int_AMDGPU_rsq R600_Reg32:$src))]
+class RECIPSQRT_CLAMPED_Common <bits<11> inst> : R600_1OP_Helper <
+ inst, "RECIPSQRT_CLAMPED", int_AMDGPU_rsq
>;
class RECIPSQRT_IEEE_Common <bits<11> inst> : R600_1OP <
- inst, "RECIPSQRT_IEEE",
- []
+ inst, "RECIPSQRT_IEEE", []
>;
class SIN_Common <bits<11> inst> : R600_1OP <
@@ -1030,11 +1121,11 @@ let Predicates = [isEGorCayman] in {
// XXX: Lowering SELECT_CC will sometimes generate fp_to_[su]int nodes,
// which do not need to be truncated since the fp values are 0.0f or 1.0f.
// We should look into handling these cases separately.
- def : Pat<(fp_to_sint R600_Reg32:$src),
- (FLT_TO_INT_eg (TRUNC R600_Reg32:$src))>;
+ def : Pat<(fp_to_sint R600_Reg32:$src0),
+ (FLT_TO_INT_eg (TRUNC R600_Reg32:$src0))>;
- def : Pat<(fp_to_uint R600_Reg32:$src),
- (FLT_TO_UINT_eg (TRUNC R600_Reg32:$src))>;
+ def : Pat<(fp_to_uint R600_Reg32:$src0),
+ (FLT_TO_UINT_eg (TRUNC R600_Reg32:$src0))>;
def : Pat<(fsqrt R600_Reg32:$src),
(MUL R600_Reg32:$src, (RECIPSQRT_CLAMPED_eg R600_Reg32:$src))>;
diff --git a/lib/Target/AMDGPU/R600RegisterInfo.td b/lib/Target/AMDGPU/R600RegisterInfo.td
index 58c6c3564cf..c682f2bf09f 100644
--- a/lib/Target/AMDGPU/R600RegisterInfo.td
+++ b/lib/Target/AMDGPU/R600RegisterInfo.td
@@ -53,8 +53,8 @@ def ALU_LITERAL_X : R600Reg<"literal.x", 253>;
def PV_X : R600Reg<"pv.x", 254>;
def PREDICATE_BIT : R600Reg<"PredicateBit", 0>;
def PRED_SEL_OFF: R600Reg<"Pred_sel_off", 0>;
-def PRED_SEL_ZERO : R600Reg<"Pred_sel_zero", 0>;
-def PRED_SEL_ONE : R600Reg<"Pred_sel_one", 0>;
+def PRED_SEL_ZERO : R600Reg<"Pred_sel_zero", 2>;
+def PRED_SEL_ONE : R600Reg<"Pred_sel_one", 3>;
def R600_CReg32 : RegisterClass <"AMDGPU", [f32, i32], 32,
(add (interleave