radeon/llvm: add support for CUBE ALU instruction

Signed-off-by: Vadim Girlin <vadimgirlin@gmail.com>
This commit is contained in:
Vadim Girlin
2012-05-07 13:10:09 +04:00
parent 996fa375ec
commit e98e209528
5 changed files with 63 additions and 21 deletions
@@ -54,6 +54,7 @@ let TargetPrefix = "AMDGPU", isTarget = 1 in {
def int_AMDGPU_imin : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
def int_AMDGPU_umax : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
def int_AMDGPU_umin : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
def int_AMDGPU_cube : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], []>;
}
let TargetPrefix = "TGSI", isTarget = 1 in {
+11
View File
@@ -98,6 +98,17 @@ bool llvm::isReductionOp(unsigned opcode)
}
}
bool llvm::isCubeOp(unsigned opcode)
{
switch(opcode) {
default: return false;
case AMDIL::CUBE_r600:
case AMDIL::CUBE_eg:
return true;
}
}
bool llvm::isFCOp(unsigned opcode)
{
switch(opcode) {
+1
View File
@@ -29,6 +29,7 @@ bool isPlaceHolderOpcode(unsigned opcode);
bool isTransOp(unsigned opcode);
bool isTexOp(unsigned opcode);
bool isReductionOp(unsigned opcode);
bool isCubeOp(unsigned opcode);
bool isFCOp(unsigned opcode);
/* XXX: Move these to AMDGPUInstrInfo.h */
+38 -20
View File
@@ -44,8 +44,9 @@ namespace {
const R600RegisterInfo * TRI;
bool evergreenEncoding;
bool isCube;
bool isReduction;
unsigned reductionElement;
unsigned currentElement;
bool isLast;
unsigned section_start;
@@ -53,7 +54,7 @@ namespace {
public:
R600CodeEmitter(formatted_raw_ostream &OS) : MachineFunctionPass(ID),
_OS(OS), TM(NULL), evergreenEncoding(false), isReduction(false),
_OS(OS), TM(NULL), evergreenEncoding(false), isCube(false), isReduction(false),
isLast(true) { }
const char *getPassName() const { return "AMDGPU Machine Code Emitter"; }
@@ -65,7 +66,7 @@ namespace {
private:
void emitALUInstr(MachineInstr &MI);
void emitSrc(const MachineOperand & MO);
void emitSrc(const MachineOperand & MO, int chan_override = -1);
void emitDst(const MachineOperand & MO);
void emitALU(MachineInstr &MI, unsigned numSrc);
void emitTexInstr(MachineInstr &MI);
@@ -176,11 +177,19 @@ bool R600CodeEmitter::runOnMachineFunction(MachineFunction &MF) {
} else if (isReductionOp(MI.getOpcode())) {
isReduction = true;
isLast = false;
for (reductionElement = 0; reductionElement < 4; reductionElement++) {
isLast = (reductionElement == 3);
for (currentElement = 0; currentElement < 4; currentElement++) {
isLast = (currentElement == 3);
emitALUInstr(MI);
}
isReduction = false;
} else if (isCubeOp(MI.getOpcode())) {
isCube = true;
isLast = false;
for (currentElement = 0; currentElement < 4; currentElement++) {
isLast = (currentElement == 3);
emitALUInstr(MI);
}
isCube = false;
} else if (MI.getOpcode() == AMDIL::RETURN ||
MI.getOpcode() == AMDIL::BUNDLE ||
MI.getOpcode() == AMDIL::KILL) {
@@ -307,18 +316,25 @@ void R600CodeEmitter::emitALUInstr(MachineInstr &MI)
/* Emit instruction type */
emitByte(0);
unsigned int opIndex;
for (opIndex = 1; opIndex < numOperands; opIndex++) {
/* Literal constants are always stored as the last operand. */
if (MI.getOperand(opIndex).isImm() || MI.getOperand(opIndex).isFPImm()) {
break;
if (isCube) {
static const int cube_src_swz[] = {2, 2, 0, 1};
emitSrc(MI.getOperand(1), cube_src_swz[currentElement]);
emitSrc(MI.getOperand(1), cube_src_swz[3-currentElement]);
emitNullBytes(SRC_BYTE_COUNT);
} else {
unsigned int opIndex;
for (opIndex = 1; opIndex < numOperands; opIndex++) {
/* Literal constants are always stored as the last operand. */
if (MI.getOperand(opIndex).isImm() || MI.getOperand(opIndex).isFPImm()) {
break;
}
emitSrc(MI.getOperand(opIndex));
}
emitSrc(MI.getOperand(opIndex));
}
/* Emit zeros for unused sources */
for ( ; opIndex < 4; opIndex++) {
emitNullBytes(SRC_BYTE_COUNT);
for ( ; opIndex < 4; opIndex++) {
emitNullBytes(SRC_BYTE_COUNT);
}
}
emitDst(dstOp);
@@ -326,7 +342,7 @@ void R600CodeEmitter::emitALUInstr(MachineInstr &MI)
emitALU(MI, numOperands - 1);
}
void R600CodeEmitter::emitSrc(const MachineOperand & MO)
void R600CodeEmitter::emitSrc(const MachineOperand & MO, int chan_override /* = -1 */)
{
uint32_t value = 0;
/* Emit the source select (2 bytes). For GPRs, this is the register index.
@@ -352,8 +368,10 @@ void R600CodeEmitter::emitSrc(const MachineOperand & MO)
}
/* Emit the source channel (1 byte) */
if (isReduction) {
emitByte(reductionElement);
if (chan_override != -1) {
emitByte(chan_override);
} else if (isReduction) {
emitByte(currentElement);
} else if (MO.isReg()) {
emitByte(TRI->getHWRegChan(MO.getReg()));
} else {
@@ -395,8 +413,8 @@ void R600CodeEmitter::emitDst(const MachineOperand & MO)
emitByte(getHWReg(MO.getReg()));
/* Emit the element of the destination register (1 byte)*/
if (isReduction) {
emitByte(reductionElement);
if (isReduction || isCube) {
emitByte(currentElement);
} else {
emitByte(TRI->getHWRegChan(MO.getReg()));
}
@@ -409,7 +427,7 @@ void R600CodeEmitter::emitDst(const MachineOperand & MO)
}
/* Emit writemask (1 byte). */
if ((isReduction && reductionElement != TRI->getHWRegChan(MO.getReg()))
if ((isReduction && currentElement != TRI->getHWRegChan(MO.getReg()))
|| MO.getTargetFlags() & MO_FLAG_MASK) {
emitByte(0);
} else {
+12 -1
View File
@@ -92,7 +92,7 @@ class R600_3OP <bits<32> inst, string opName, list<dag> pattern,
}
class R600_REDUCTION <bits<32> inst, dag ins, string asm, list<dag> pattern,
InstrItinClass itin = AnyALU> :
InstrItinClass itin = VecALU> :
InstR600 <inst,
(outs R600_Reg32:$dst),
ins,
@@ -537,6 +537,15 @@ class DOT4_Common <bits<32> inst> : R600_REDUCTION <
[(set R600_Reg32:$dst, (int_AMDGPU_dp4 R600_Reg128:$src0, R600_Reg128:$src1))]
>;
class CUBE_Common <bits<32> inst> : InstR600 <
inst,
(outs R600_Reg128:$dst),
(ins R600_Reg128:$src),
"CUBE $dst $src",
[(set R600_Reg128:$dst, (int_AMDGPU_cube R600_Reg128:$src))],
VecALU
>;
class EXP_IEEE_Common <bits<32> inst> : R600_1OP <
inst, "EXP_IEEE",
[]> {
@@ -681,6 +690,7 @@ let Gen = AMDGPUGen.R600 in {
def CNDGT_r600 : CNDGT_Common<0x19>;
def CNDGE_r600 : CNDGE_Common<0x1A>;
def DOT4_r600 : DOT4_Common<0x50>;
def CUBE_r600 : CUBE_Common<0x52>;
def EXP_IEEE_r600 : EXP_IEEE_Common<0x61>;
def LOG_CLAMPED_r600 : LOG_CLAMPED_Common<0x62>;
def LOG_IEEE_r600 : LOG_IEEE_Common<0x63>;
@@ -887,6 +897,7 @@ let Gen = AMDGPUGen.EG_CAYMAN in {
def RECIP_UINT_eg : RECIP_UINT_Common<0x94>;
def INT_TO_FLT_eg : INT_TO_FLT_Common<0x9B>;
def DOT4_eg : DOT4_Common<0xBE>;
def CUBE_eg : CUBE_Common<0xC0>;
} // End AMDGPUGen.EG_CAYMAN