diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp | 61 | ||||
-rw-r--r-- | lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h | 10 | ||||
-rw-r--r-- | lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp | 64 | ||||
-rw-r--r-- | lib/Target/AMDGPU/R600Defines.h | 51 | ||||
-rw-r--r-- | lib/Target/AMDGPU/R600InstrInfo.cpp | 109 | ||||
-rw-r--r-- | lib/Target/AMDGPU/R600InstrInfo.h | 10 | ||||
-rw-r--r-- | lib/Target/AMDGPU/R600Instructions.td | 263 | ||||
-rw-r--r-- | lib/Target/AMDGPU/R600RegisterInfo.td | 4 |
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 |