radeon/llvm: Fix VTX_READ patterns
authorTom Stellard <thomas.stellard@amd.com>
Fri, 1 Jun 2012 18:49:03 +0000 (14:49 -0400)
committerTom Stellard <thomas.stellard@amd.com>
Fri, 1 Jun 2012 20:52:26 +0000 (16:52 -0400)
The VTX_READ instructions were using the ADDRParam ComplexPattern which
allows a load instruction's offset to be a register, but VTX_READ
instructions can only handle an immediate offset.

Also, the load_param pattern fragment had an erroneous return true;
statement that was causing it to match the wrong load instructions.

src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp
src/gallium/drivers/radeon/R600CodeEmitter.cpp
src/gallium/drivers/radeon/R600Instructions.td

index b14a360c3ccdd91410ee8a57c0e898a010578e5e..d7b08b0aa772afc0d88ec979f991ea0428a94f1c 100644 (file)
@@ -69,6 +69,7 @@ private:
 
   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 "AMDGPUGenDAGISel.inc"
@@ -556,6 +557,34 @@ bool AMDILDAGToDAGISel::SelectADDR8BitOffset(SDValue Addr, SDValue& Base,
   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(),
+                                  AMDIL::ZERO, MVT::i32);
+    Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
+    return true;
+  }
+
+  // Default case, no offset
+  Base = Addr;
+  Offset = CurDAG->getTargetConstant(0, MVT::i32);
+  return true;
+}
+
 bool AMDILDAGToDAGISel::SelectADDRReg(SDValue Addr, SDValue& Base,
                                       SDValue& Offset) {
   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
index 8715f1133e87a113885ee4ace7007115cf325528..f75c2f51bdc6470e19a0617a26144baa19cfe20b 100644 (file)
@@ -255,7 +255,7 @@ bool R600CodeEmitter::runOnMachineFunction(MachineFunction &MF) {
                 emitByte(0);
 
                 // offset
-                emitTwoBytes(0);
+                emitTwoBytes(MI.getOperand(2).getImm());
 
                 // endian
                 emitByte(0);
index e12ebab60c92a8b67daffa689d53b0241b7b3eb1..921d56500604aaabf5ce86a5168da7d5e3b28a4b 100644 (file)
@@ -51,6 +51,7 @@ def MEMrr : Operand<iPTR> {
 
 def ADDRParam : ComplexPattern<i32, 2, "SelectADDRParam", [], []>;
 def ADDRDWord : ComplexPattern<i32, 1, "SelectADDRDWord", [], []>;
+def ADDRVTX_READ : ComplexPattern<i32, 2, "SelectADDRVTX_READ", [], []>;
 
 class R600_ALU {
 
@@ -225,7 +226,6 @@ def store_global : PatFrag<(ops node:$value, node:$ptr),
 def load_param : PatFrag<(ops node:$ptr),
                          (load node:$ptr),
                           [{
-                           return true;
                            const Value *Src = cast<LoadSDNode>(N)->getSrcValue();
                            if (Src) {
                                 PointerType * PT = dyn_cast<PointerType>(Src->getType());
@@ -804,11 +804,11 @@ class VTX_READ_eg <int buffer_id, list<dag> pattern> : InstR600ISA <
 >;
 
 def VTX_READ_PARAM_eg : VTX_READ_eg <0,
-  [(set (i32 R600_TReg32_X:$dst), (load_param ADDRParam:$ptr))]
+  [(set (i32 R600_TReg32_X:$dst), (load_param ADDRVTX_READ:$ptr))]
 >;
 
 def VTX_READ_GLOBAL_eg : VTX_READ_eg <1,
-  [(set (i32 R600_TReg32_X:$dst), (global_load ADDRParam:$ptr))]
+  [(set (i32 R600_TReg32_X:$dst), (global_load ADDRVTX_READ:$ptr))]
 >;
 
 } // End isEG Predicate