#define MO_FLAG_NEG (1 << 1)
#define MO_FLAG_ABS (1 << 2)
#define MO_FLAG_MASK (1 << 3)
+#define MO_FLAG_PUSH (1 << 4)
+
+#define OPCODE_IS_ZERO_INT 0x00000045
+#define OPCODE_IS_NOT_ZERO_INT 0x00000042
+#define OPCODE_IS_ZERO 0x00000020
+#define OPCODE_IS_NOT_ZERO 0x00000023
namespace llvm {
{
unsigned numOperands = MI.getNumExplicitOperands();
+ if(MI.findFirstPredOperandIdx() > -1)
+ numOperands--;
// Some instructions are just place holder instructions that represent
// operations that the GPU does automatically. They should be ignored.
return;
}
+ if(MI.getOpcode() == AMDGPU::PRED_X)
+ numOperands = 2;
+
// XXX Check if instruction writes a result
if (numOperands < 1) {
return;
void R600CodeEmitter::EmitDst(const MachineOperand & MO)
{
- if (MO.isReg()) {
+ if (MO.isReg() && MO.getReg() != AMDGPU::PREDICATE_BIT) {
// Emit the destination register index (1 byte)
EmitByte(getHWReg(MO.getReg()));
EmitByte(0);
}
- // XXX: Emit predicate (1 byte)
- EmitByte(0);
+ // XXX: Emit push modifier
+ if(MI.getOperand(1).getTargetFlags() & MO_FLAG_PUSH) {
+ EmitByte(1);
+ } else {
+ EmitByte(0);
+ }
+
+ // XXX: Emit predicate (1 byte)
+ int predidx = MI.findFirstPredOperandIdx();
+ if (predidx > -1)
+ switch(MI.getOperand(predidx).getReg()) {
+ case AMDGPU::PRED_SEL_ZERO:
+ EmitByte(2);
+ break;
+ case AMDGPU::PRED_SEL_ONE:
+ EmitByte(3);
+ break;
+ default:
+ EmitByte(0);
+ break;
+ }
+ else {
+ EmitByte(0);
+ }
+
// XXX: Emit bank swizzle. (1 byte) Do we need this? It looks like
// r600_asm.c sets it.
def NEG_ONE : R600Reg<"-1.0">;
def PV_X : R600Reg<"pv.x">;
def ALU_LITERAL_X : R600Reg<"literal.x">;
+def PREDICATE_BIT : R600Reg<"PredicateBit">;
+def PRED_SEL_OFF: R600Reg<"Pred_sel_off">;
+def PRED_SEL_ZERO : R600Reg<"Pred_sel_zero">;
+def PRED_SEL_ONE : R600Reg<"Pred_sel_one">;
def R600_CReg32 : RegisterClass <"AMDGPU", [f32, i32], 32, (add
$creg_list)>;
R600_CReg32,
ZERO, HALF, ONE, ONE_INT, PV_X, ALU_LITERAL_X, NEG_ONE, NEG_HALF)>;
+def R600_Predicate : RegisterClass <"AMDGPU", [i32], 32, (add
+ PRED_SEL_OFF, PRED_SEL_ZERO, PRED_SEL_ONE)>;
+
+def R600_Predicate_Bit: RegisterClass <"AMDGPU", [i32], 32, (add
+ PREDICATE_BIT)>;
+
def R600_Reg128 : RegisterClass<"AMDGPU", [v4f32, v4i32], 128, (add
$t128_string)>
{
MI->getOperand(0).addTargetFlag(MO_FLAG_CLAMP);
BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::MOV))
.addOperand(MI->getOperand(0))
- .addOperand(MI->getOperand(1));
+ .addOperand(MI->getOperand(1))
+ .addReg(AMDGPU::PRED_SEL_OFF);
break;
case AMDGPU::FABS_R600:
MI->getOperand(1).addTargetFlag(MO_FLAG_ABS);
BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::MOV))
.addOperand(MI->getOperand(0))
- .addOperand(MI->getOperand(1));
+ .addOperand(MI->getOperand(1))
+ .addReg(AMDGPU::PRED_SEL_OFF);
break;
case AMDGPU::FNEG_R600:
MI->getOperand(1).addTargetFlag(MO_FLAG_NEG);
BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::MOV))
.addOperand(MI->getOperand(0))
- .addOperand(MI->getOperand(1));
+ .addOperand(MI->getOperand(1))
+ .addReg(AMDGPU::PRED_SEL_OFF);
break;
case AMDGPU::R600_LOAD_CONST:
// this way and it didn't produce the correct results.
BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::MOV), ShiftValue)
.addReg(AMDGPU::ALU_LITERAL_X)
+ .addReg(AMDGPU::PRED_SEL_OFF)
.addImm(2);
BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::LSHR_eg), NewAddr)
.addOperand(MI->getOperand(1))
- .addReg(ShiftValue);
+ .addReg(ShiftValue)
+ .addReg(AMDGPU::PRED_SEL_OFF);
BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(MI->getOpcode()))
.addOperand(MI->getOperand(0))
.addReg(NewAddr);
#include "AMDGPUSubtarget.h"
#include "R600RegisterInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "AMDILUtilityFunctions.h"
#define GET_INSTRINFO_CTOR
#include "AMDGPUGenDFAPacketizer.inc"
BuildMI(MBB, MI, DL, get(AMDGPU::MOV))
.addReg(RI.getSubReg(DestReg, subRegMap[i]), RegState::Define)
.addReg(RI.getSubReg(SrcReg, subRegMap[i]))
+ .addReg(0) // PREDICATE_BIT
.addReg(DestReg, RegState::Define | RegState::Implicit);
}
} else {
&& !AMDGPU::R600_Reg128RegClass.contains(SrcReg));
BuildMI(MBB, MI, DL, get(AMDGPU::MOV), DestReg)
- .addReg(SrcReg, getKillRegState(KillSrc));
+ .addReg(SrcReg, getKillRegState(KillSrc))
+ .addReg(0); // PREDICATE_BIT
}
}
MachineInstrBuilder(MI).addReg(DstReg, RegState::Define);
MachineInstrBuilder(MI).addReg(AMDGPU::ALU_LITERAL_X);
MachineInstrBuilder(MI).addImm(Imm);
+ MachineInstrBuilder(MI).addReg(0); // PREDICATE_BIT
return MI;
}
const InstrItineraryData *II = TM->getInstrItineraryData();
return TM->getSubtarget<AMDGPUSubtarget>().createDFAPacketizer(II);
}
+
+bool
+R600InstrInfo::isPredicated(const MachineInstr *MI) const
+{
+ int idx = MI->findFirstPredOperandIdx();
+ if (idx < 0)
+ return false;
+
+ MI->dump();
+ unsigned Reg = MI->getOperand(idx).getReg();
+ switch (Reg) {
+ default: return false;
+ case AMDGPU::PRED_SEL_ONE:
+ case AMDGPU::PRED_SEL_ZERO:
+ case AMDGPU::PREDICATE_BIT:
+ return true;
+ }
+}
+
+bool
+R600InstrInfo::isPredicable(MachineInstr *MI) const
+{
+ return AMDGPUInstrInfo::isPredicable(MI);
+}
DFAPacketizer *CreateTargetScheduleState(const TargetMachine *TM,
const ScheduleDAG *DAG) const;
+ bool isPredicated(const MachineInstr *MI) const;
+
+ bool isPredicable(MachineInstr *MI) const;
};
} // End llvm namespace
}
+def R600_Pred : PredicateOperand<i32, (ops R600_Predicate),
+ (ops PRED_SEL_OFF)>;
+
class R600_1OP <bits<32> inst, string opName, list<dag> pattern,
InstrItinClass itin = AnyALU> :
InstR600 <inst,
(outs R600_Reg32:$dst),
- (ins R600_Reg32:$src, variable_ops),
- !strconcat(opName, " $dst, $src"),
+ (ins R600_Reg32:$src, R600_Pred:$p, variable_ops),
+ !strconcat(opName, " $dst, $src ($p)"),
pattern,
itin
>;
InstrItinClass itin = AnyALU> :
InstR600 <inst,
(outs R600_Reg32:$dst),
- (ins R600_Reg32:$src0, R600_Reg32:$src1, variable_ops),
+ (ins R600_Reg32:$src0, R600_Reg32:$src1,R600_Pred:$p, variable_ops),
!strconcat(opName, " $dst, $src0, $src1"),
pattern,
itin
InstrItinClass itin = AnyALU> :
InstR600 <inst,
(outs R600_Reg32:$dst),
- (ins R600_Reg32:$src0, R600_Reg32:$src1, R600_Reg32:$src2, variable_ops),
+ (ins R600_Reg32:$src0, R600_Reg32:$src1, R600_Reg32:$src2,R600_Pred:$p, variable_ops),
!strconcat(opName, " $dst, $src0, $src1, $src2"),
pattern,
itin>{
let Op3 = 1;
}
+
+
+def PRED_X : AMDGPUInst <(outs R600_Predicate_Bit:$dst),
+ (ins R600_Reg32:$src0, i32imm:$src1),
+ "PRED $dst, $src0, $src1",
+ []>
+{
+ let DisableEncoding = "$src0";
+ field bits<32> Inst;
+ bits<32> src1;
+
+ let Inst = src1;
+}
+
+
+
class R600_REDUCTION <bits<32> inst, dag ins, string asm, list<dag> pattern,
InstrItinClass itin = VecALU> :
InstR600 <inst,
class MOV_IMM <ValueType vt, Operand immType> : InstR600 <0x19,
(outs R600_Reg32:$dst),
- (ins R600_Reg32:$alu_literal, immType:$imm),
+ (ins R600_Reg32:$alu_literal, R600_Pred:$p, immType:$imm),
"MOV_IMM $dst, $imm",
[], AnyALU
>;
Reserved.set(AMDGPU::NEG_ONE);
Reserved.set(AMDGPU::PV_X);
Reserved.set(AMDGPU::ALU_LITERAL_X);
+ Reserved.set(AMDGPU::PREDICATE_BIT);
+ Reserved.set(AMDGPU::PRED_SEL_OFF);
+ Reserved.set(AMDGPU::PRED_SEL_ZERO);
+ Reserved.set(AMDGPU::PRED_SEL_ONE);
for (TargetRegisterClass::iterator I = AMDGPU::R600_CReg32RegClass.begin(),
E = AMDGPU::R600_CReg32RegClass.end(); I != E; ++I) {
case AMDGPU::HALF:
case AMDGPU::NEG_HALF: return 252;
case AMDGPU::ALU_LITERAL_X: return 253;
+ case AMDGPU::PREDICATE_BIT:
+ case AMDGPU::PRED_SEL_OFF:
+ case AMDGPU::PRED_SEL_ZERO:
+ case AMDGPU::PRED_SEL_ONE:
+ return 0;
default: return getHWRegIndexGen(reg);
}
}
case AMDGPU::HALF:
case AMDGPU::NEG_HALF:
case AMDGPU::ALU_LITERAL_X:
+ case AMDGPU::PREDICATE_BIT:
+ case AMDGPU::PRED_SEL_OFF:
+ case AMDGPU::PRED_SEL_ZERO:
+ case AMDGPU::PRED_SEL_ONE:
return 0;
default: return getHWRegChanGen(reg);
}