// This file defines an instruction selector for the AMDIL target.
//
//===----------------------------------------------------------------------===//
+#include "AMDGPUISelLowering.h" // For AMDGPUISD
#include "AMDILDevices.h"
-#include "AMDILTargetMachine.h"
#include "AMDILUtilityFunctions.h"
#include "llvm/ADT/ValueMap.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
// make the right decision when generating code for different targets.
const AMDILSubtarget &Subtarget;
public:
- AMDILDAGToDAGISel(AMDILTargetMachine &TM AMDIL_OPT_LEVEL_DECL);
+ AMDILDAGToDAGISel(TargetMachine &TM AMDIL_OPT_LEVEL_DECL);
virtual ~AMDILDAGToDAGISel();
SDNode *Select(SDNode *N);
static bool isLocalLoad(const LoadSDNode *N);
static bool isRegionLoad(const LoadSDNode *N);
- SDNode *xformAtomicInst(SDNode *N);
+ bool SelectADDR8BitOffset(SDValue Addr, SDValue& Base, SDValue& Offset);
+ bool SelectADDRReg(SDValue Addr, SDValue& Base, SDValue& Offset);
+ bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset);
// Include the pieces autogenerated from the target description.
-#include "AMDILGenDAGISel.inc"
+#include "AMDGPUGenDAGISel.inc"
};
} // end anonymous namespace
// createAMDILISelDag - This pass converts a legalized DAG into a AMDIL-specific
// DAG, ready for instruction scheduling.
//
-FunctionPass *llvm::createAMDILISelDag(AMDILTargetMachine &TM
+FunctionPass *llvm::createAMDILISelDag(TargetMachine &TM
AMDIL_OPT_LEVEL_DECL) {
return new AMDILDAGToDAGISel(TM AMDIL_OPT_LEVEL_VAR);
}
-AMDILDAGToDAGISel::AMDILDAGToDAGISel(AMDILTargetMachine &TM
+AMDILDAGToDAGISel::AMDILDAGToDAGISel(TargetMachine &TM
AMDIL_OPT_LEVEL_DECL)
: SelectionDAGISel(TM AMDIL_OPT_LEVEL_VAR), Subtarget(TM.getSubtarget<AMDILSubtarget>())
{
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
unsigned int FI = FIN->getIndex();
EVT OpVT = N->getValueType(0);
- unsigned int NewOpc = AMDIL::MOVE_i32;
+ unsigned int NewOpc = AMDGPU::COPY;
SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
return CurDAG->SelectNodeTo(N, NewOpc, OpVT, TFI);
}
}
break;
}
- // For all atomic instructions, we need to add a constant
- // operand that stores the resource ID in the instruction
- if (Opc > AMDILISD::ADDADDR && Opc < AMDILISD::APPEND_ALLOC) {
- N = xformAtomicInst(N);
- }
return SelectCode(N);
}
return "AMDIL DAG->DAG Pattern Instruction Selection";
}
-SDNode*
-AMDILDAGToDAGISel::xformAtomicInst(SDNode *N)
-{
- uint32_t addVal = 1;
- bool addOne = false;
- // bool bitCastToInt = (N->getValueType(0) == MVT::f32);
- unsigned opc = N->getOpcode();
- switch (opc) {
- default: return N;
- case AMDILISD::ATOM_G_ADD:
- case AMDILISD::ATOM_G_AND:
- case AMDILISD::ATOM_G_MAX:
- case AMDILISD::ATOM_G_UMAX:
- case AMDILISD::ATOM_G_MIN:
- case AMDILISD::ATOM_G_UMIN:
- case AMDILISD::ATOM_G_OR:
- case AMDILISD::ATOM_G_SUB:
- case AMDILISD::ATOM_G_RSUB:
- case AMDILISD::ATOM_G_XCHG:
- case AMDILISD::ATOM_G_XOR:
- case AMDILISD::ATOM_G_ADD_NORET:
- case AMDILISD::ATOM_G_AND_NORET:
- case AMDILISD::ATOM_G_MAX_NORET:
- case AMDILISD::ATOM_G_UMAX_NORET:
- case AMDILISD::ATOM_G_MIN_NORET:
- case AMDILISD::ATOM_G_UMIN_NORET:
- case AMDILISD::ATOM_G_OR_NORET:
- case AMDILISD::ATOM_G_SUB_NORET:
- case AMDILISD::ATOM_G_RSUB_NORET:
- case AMDILISD::ATOM_G_XCHG_NORET:
- case AMDILISD::ATOM_G_XOR_NORET:
- case AMDILISD::ATOM_L_ADD:
- case AMDILISD::ATOM_L_AND:
- case AMDILISD::ATOM_L_MAX:
- case AMDILISD::ATOM_L_UMAX:
- case AMDILISD::ATOM_L_MIN:
- case AMDILISD::ATOM_L_UMIN:
- case AMDILISD::ATOM_L_OR:
- case AMDILISD::ATOM_L_SUB:
- case AMDILISD::ATOM_L_RSUB:
- case AMDILISD::ATOM_L_XCHG:
- case AMDILISD::ATOM_L_XOR:
- case AMDILISD::ATOM_L_ADD_NORET:
- case AMDILISD::ATOM_L_AND_NORET:
- case AMDILISD::ATOM_L_MAX_NORET:
- case AMDILISD::ATOM_L_UMAX_NORET:
- case AMDILISD::ATOM_L_MIN_NORET:
- case AMDILISD::ATOM_L_UMIN_NORET:
- case AMDILISD::ATOM_L_OR_NORET:
- case AMDILISD::ATOM_L_SUB_NORET:
- case AMDILISD::ATOM_L_RSUB_NORET:
- case AMDILISD::ATOM_L_XCHG_NORET:
- case AMDILISD::ATOM_L_XOR_NORET:
- case AMDILISD::ATOM_R_ADD:
- case AMDILISD::ATOM_R_AND:
- case AMDILISD::ATOM_R_MAX:
- case AMDILISD::ATOM_R_UMAX:
- case AMDILISD::ATOM_R_MIN:
- case AMDILISD::ATOM_R_UMIN:
- case AMDILISD::ATOM_R_OR:
- case AMDILISD::ATOM_R_SUB:
- case AMDILISD::ATOM_R_RSUB:
- case AMDILISD::ATOM_R_XCHG:
- case AMDILISD::ATOM_R_XOR:
- case AMDILISD::ATOM_R_ADD_NORET:
- case AMDILISD::ATOM_R_AND_NORET:
- case AMDILISD::ATOM_R_MAX_NORET:
- case AMDILISD::ATOM_R_UMAX_NORET:
- case AMDILISD::ATOM_R_MIN_NORET:
- case AMDILISD::ATOM_R_UMIN_NORET:
- case AMDILISD::ATOM_R_OR_NORET:
- case AMDILISD::ATOM_R_SUB_NORET:
- case AMDILISD::ATOM_R_RSUB_NORET:
- case AMDILISD::ATOM_R_XCHG_NORET:
- case AMDILISD::ATOM_R_XOR_NORET:
- case AMDILISD::ATOM_G_CMPXCHG:
- case AMDILISD::ATOM_G_CMPXCHG_NORET:
- case AMDILISD::ATOM_L_CMPXCHG:
- case AMDILISD::ATOM_L_CMPXCHG_NORET:
- case AMDILISD::ATOM_R_CMPXCHG:
- case AMDILISD::ATOM_R_CMPXCHG_NORET:
- break;
- case AMDILISD::ATOM_G_DEC:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_G_SUB;
- }
- break;
- case AMDILISD::ATOM_G_INC:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_G_ADD;
- }
- break;
- case AMDILISD::ATOM_G_DEC_NORET:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_G_SUB_NORET;
- }
- break;
- case AMDILISD::ATOM_G_INC_NORET:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_G_ADD_NORET;
- }
- break;
- case AMDILISD::ATOM_L_DEC:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_L_SUB;
- }
- break;
- case AMDILISD::ATOM_L_INC:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_L_ADD;
- }
- break;
- case AMDILISD::ATOM_L_DEC_NORET:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_L_SUB_NORET;
- }
- break;
- case AMDILISD::ATOM_L_INC_NORET:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_L_ADD_NORET;
- }
- break;
- case AMDILISD::ATOM_R_DEC:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_R_SUB;
- }
- break;
- case AMDILISD::ATOM_R_INC:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_R_ADD;
- }
- break;
- case AMDILISD::ATOM_R_DEC_NORET:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_R_SUB;
- }
- break;
- case AMDILISD::ATOM_R_INC_NORET:
- addOne = true;
- if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
- addVal = (uint32_t)-1;
- } else {
- opc = AMDILISD::ATOM_R_ADD_NORET;
- }
- break;
+#ifdef DEBUGTMP
+#undef INT64_C
+#endif
+#undef DEBUGTMP
+
+///==== AMDGPU Functions ====///
+
+bool AMDILDAGToDAGISel::SelectADDR8BitOffset(SDValue Addr, SDValue& Base,
+ SDValue& Offset) {
+ if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
+ Addr.getOpcode() == ISD::TargetGlobalAddress) {
+ return false;
}
- // The largest we can have is a cmpxchg w/ a return value and an output chain.
- // The cmpxchg function has 3 inputs and a single output along with an
- // output change and a target constant, giving a total of 6.
- SDValue Ops[12];
- unsigned x = 0;
- unsigned y = N->getNumOperands();
- for (x = 0; x < y; ++x) {
- Ops[x] = N->getOperand(x);
+
+
+ if (Addr.getOpcode() == ISD::ADD) {
+ bool Match = false;
+
+ // Find the base ptr and the offset
+ for (unsigned i = 0; i < Addr.getNumOperands(); i++) {
+ SDValue Arg = Addr.getOperand(i);
+ ConstantSDNode * OffsetNode = dyn_cast<ConstantSDNode>(Arg);
+ // This arg isn't a constant so it must be the base PTR.
+ if (!OffsetNode) {
+ Base = Addr.getOperand(i);
+ continue;
+ }
+ // Check if the constant argument fits in 8-bits. The offset is in bytes
+ // so we need to convert it to dwords.
+ if (isInt<8>(OffsetNode->getZExtValue() >> 2)) {
+ Match = true;
+ Offset = CurDAG->getTargetConstant(OffsetNode->getZExtValue() >> 2,
+ MVT::i32);
+ }
+ }
+ return Match;
}
- if (addOne) {
- Ops[x++] = SDValue(SelectCode(CurDAG->getConstant(addVal, MVT::i32).getNode()), 0);
+
+ // Default case, no offset
+ Base = Addr;
+ Offset = CurDAG->getTargetConstant(0, MVT::i32);
+ return true;
+}
+
+bool AMDILDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
+ SDValue &Offset)
+{
+ ConstantSDNode * IMMOffset;
+
+ if (Addr.getOpcode() == ISD::ADD
+ && (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
+ && isInt<16>(IMMOffset->getZExtValue())) {
+
+ Base = Addr.getOperand(0);
+ Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
+ return true;
+ // If the pointer address is constant, we can move it to the offset field.
+ } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr))
+ && isInt<16>(IMMOffset->getZExtValue())) {
+ Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
+ CurDAG->getEntryNode().getDebugLoc(),
+ AMDGPU::ZERO, MVT::i32);
+ Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
+ return true;
}
- Ops[x++] = CurDAG->getTargetConstant(0, MVT::i32);
- SDVTList Tys = N->getVTList();
- MemSDNode *MemNode = dyn_cast<MemSDNode>(N);
- assert(MemNode && "Atomic should be of MemSDNode type!");
- N = CurDAG->getMemIntrinsicNode(opc, N->getDebugLoc(), Tys, Ops, x,
- MemNode->getMemoryVT(), MemNode->getMemOperand()).getNode();
- return N;
+
+ // Default case, no offset
+ Base = Addr;
+ Offset = CurDAG->getTargetConstant(0, MVT::i32);
+ return true;
}
-#ifdef DEBUGTMP
-#undef INT64_C
-#endif
-#undef DEBUGTMP
+bool AMDILDAGToDAGISel::SelectADDRReg(SDValue Addr, SDValue& Base,
+ SDValue& Offset) {
+ if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
+ Addr.getOpcode() == ISD::TargetGlobalAddress ||
+ Addr.getOpcode() != ISD::ADD) {
+ return false;
+ }
+
+ Base = Addr.getOperand(0);
+ Offset = Addr.getOperand(1);
+
+ return false;
+}