radeon/llvm: Add custom SDNodes for MAX
authorTom Stellard <thomas.stellard@amd.com>
Thu, 17 May 2012 11:35:15 +0000 (07:35 -0400)
committerTom Stellard <thomas.stellard@amd.com>
Thu, 17 May 2012 18:48:09 +0000 (14:48 -0400)
We now lower the various intrinsics for max to SDNodes and then use
tablegen patterns to lower the SDNodes to instructions.

src/gallium/drivers/radeon/AMDGPUGenInstrEnums.pl
src/gallium/drivers/radeon/AMDGPUISelLowering.cpp
src/gallium/drivers/radeon/AMDGPUISelLowering.h
src/gallium/drivers/radeon/AMDGPUInstrInfo.td [new file with mode: 0644]
src/gallium/drivers/radeon/AMDIL.td
src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp
src/gallium/drivers/radeon/AMDILISelLowering.h
src/gallium/drivers/radeon/AMDILInstructions.td
src/gallium/drivers/radeon/R600Instructions.td
src/gallium/drivers/radeon/SIInstructions.td

index 130eaac72bc31f2b575f88b1e092f62945824331..ddff39912cdf27056f7b9b931aa8e06b306b7053 100644 (file)
@@ -34,7 +34,6 @@ use strict;
 my @F32_MULTICLASSES = qw {
   UnaryIntrinsicFloat
   UnaryIntrinsicFloatScalar
-  BinaryIntrinsicFloat
   TernaryIntrinsicFloat
   BinaryOpMCFloat
 };
@@ -58,7 +57,7 @@ my $FILE_TYPE = $ARGV[0];
 
 open AMDIL, '<', 'AMDILInstructions.td';
 
-my @INST_ENUMS = ('NONE', 'FEQ', 'FGE', 'FLT', 'FNE', 'MOVE_f32', 'MOVE_i32', 'FTOI', 'ITOF', 'CMOVLOG_f32', 'UGT', 'IGE', 'INE', 'UGE', 'IEQ', 'BINARY_OR_i32', 'BINARY_NOT_i32');
+my @INST_ENUMS = ('NONE', 'FEQ', 'FGE', 'FLT', 'FNE', 'MOVE_f32', 'MOVE_i32', 'FTOI', 'ITOF', 'CMOVLOG_f32', 'UGT', 'IGE', 'INE', 'UGE', 'IEQ', 'BINARY_OR_i32', 'BINARY_NOT_i32', 'MIN_f32');
 
 while (<AMDIL>) {
   if ($_ =~ /defm\s+([A-Z_]+)\s+:\s+([A-Za-z0-9]+)</) {
index 8d4207f24d4dc17ea0b8dee67b0a8a031ef141ce..9d1042e8164822b9c6b003925453cc5d7dc219a5 100644 (file)
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "AMDGPUISelLowering.h"
+#include "AMDILIntrinsicInfo.h"
 #include "AMDGPUUtil.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 
@@ -20,6 +21,38 @@ using namespace llvm;
 AMDGPUTargetLowering::AMDGPUTargetLowering(TargetMachine &TM) :
   AMDILTargetLowering(TM)
 {
+  // We need to custom lower some of the intrinsics
+  setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
+}
+
+SDValue AMDGPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
+    const
+{
+  switch (Op.getOpcode()) {
+  default: return AMDILTargetLowering::LowerOperation(Op, DAG);
+  case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
+  }
+}
+
+SDValue AMDGPUTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
+    SelectionDAG &DAG) const
+{
+  unsigned IntrinsicID = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
+  DebugLoc DL = Op.getDebugLoc();
+  EVT VT = Op.getValueType();
+
+  switch (IntrinsicID) {
+    default: return Op;
+    case AMDGPUIntrinsic::AMDIL_max:
+      return DAG.getNode(AMDGPUISD::FMAX, DL, VT, Op.getOperand(1),
+                                                  Op.getOperand(2));
+    case AMDGPUIntrinsic::AMDGPU_imax:
+      return DAG.getNode(AMDGPUISD::SMAX, DL, VT, Op.getOperand(1),
+                                                  Op.getOperand(2));
+    case AMDGPUIntrinsic::AMDGPU_umax:
+      return DAG.getNode(AMDGPUISD::UMAX, DL, VT, Op.getOperand(1),
+                                                  Op.getOperand(2));
+  }
 }
 
 void AMDGPUTargetLowering::addLiveIn(MachineInstr * MI,
@@ -29,3 +62,15 @@ void AMDGPUTargetLowering::addLiveIn(MachineInstr * MI,
   AMDGPU::utilAddLiveIn(MF, MRI, TII, reg, MI->getOperand(0).getReg());
 }
 
+#define NODE_NAME_CASE(node) case AMDGPUISD::node: return #node;
+
+const char* AMDGPUTargetLowering::getTargetNodeName(unsigned Opcode) const
+{
+  switch (Opcode) {
+  default: return AMDILTargetLowering::getTargetNodeName(Opcode);
+
+  NODE_NAME_CASE(FMAX)
+  NODE_NAME_CASE(SMAX)
+  NODE_NAME_CASE(UMAX)
+  }
+}
index 16adf1b32bbdbb6ec6289e7c5a1b0b521848af37..b67f30bc9761b74b7b8b4cbce57e2cbe202b7097 100644 (file)
@@ -21,6 +21,9 @@ namespace llvm {
 
 class AMDGPUTargetLowering : public AMDILTargetLowering
 {
+private:
+  SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
+
 protected:
 
   /// addLiveIn - This functions adds reg to the live in list of the entry block
@@ -36,8 +39,26 @@ protected:
 public:
   AMDGPUTargetLowering(TargetMachine &TM);
 
+  virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
+  virtual const char* getTargetNodeName(unsigned Opcode) const;
+
 };
 
+namespace AMDGPUISD
+{
+
+enum
+{
+  AMDGPU_FIRST = AMDILISD::LAST_NON_MEMORY_OPCODE,
+  FMAX,
+  SMAX,
+  UMAX,
+  LAST_AMDGPU_ISD_NUMBER
+};
+
+
+} // End namespace AMDGPUISD
+
 } // End namespace llvm
 
 #endif // AMDGPUISELLOWERING_H
diff --git a/src/gallium/drivers/radeon/AMDGPUInstrInfo.td b/src/gallium/drivers/radeon/AMDGPUInstrInfo.td
new file mode 100644 (file)
index 0000000..abb1ebe
--- /dev/null
@@ -0,0 +1,31 @@
+//===-- AMDGPUInstrInfo.td - AMDGPU DAG nodes --------------*- tablegen -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains DAG node defintions for the AMDGPU target.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// AMDGPU DAG Nodes
+//
+
+// out = max(a, b) a and b are floats
+def AMDGPUfmax : SDNode<"AMDGPUISD::FMAX", SDTFPBinOp,
+  [SDNPCommutative, SDNPAssociative]
+>;
+
+// out = max(a, b) a and b are signed ints
+def AMDGPUsmax : SDNode<"AMDGPUISD::SMAX", SDTIntBinOp,
+  [SDNPCommutative, SDNPAssociative]
+>;
+
+// out = max(a, b) a and b are unsigned ints
+def AMDGPUumax : SDNode<"AMDGPUISD::UMAX", SDTIntBinOp,
+  [SDNPCommutative, SDNPAssociative]
+>;
index deee290fad55bf02f6ccdbaecb7f928bb3955137..28d4182ddc6e2a7e2ea337dbcf85299d9515c980 100644 (file)
@@ -14,6 +14,7 @@ include "AMDILVersion.td"
 include "R600Schedule.td"
 include "SISchedule.td"
 include "Processors.td"
+include "AMDGPUInstrInfo.td"
 include "AMDGPUIntrinsics.td"
 include "AMDGPURegisterInfo.td"
 include "AMDGPUInstructions.td"
index b8898828dd62b287b46745c608257a412c2b6ea7..a96cc9507a3a3661842f57daff5d2cf318bf567d 100644 (file)
@@ -10,6 +10,7 @@
 // This file defines an instruction selector for the AMDIL target.
 //
 //===----------------------------------------------------------------------===//
+#include "AMDGPUISelLowering.h" // For AMDGPUISD
 #include "AMDILDevices.h"
 #include "AMDILTargetMachine.h"
 #include "AMDILUtilityFunctions.h"
index 302f0cb6909a657c23c5797ec7374724b1c8bca7..84639152257469a6b7b3c3829d83cd2939ab9f94 100644 (file)
@@ -94,6 +94,7 @@ namespace llvm
       LOOP_ZERO,
       LOOP_CMP,
       ADDADDR,
+      LAST_NON_MEMORY_OPCODE,
       // ATOMIC Operations
       // Global Memory
       ATOM_G_ADD = ISD::FIRST_TARGET_MEMORY_OPCODE,
index db56e2121b3623942056772278b17b2e8ebcd606..f03ec6bd9006cd58ca14d475686d9d8c04e7610c 100644 (file)
@@ -261,7 +261,6 @@ defm POW : BinaryIntrinsicFloat<IL_OP_POW, int_AMDIL_pow>;
 let hasIEEEFlag = 1 in {
   let mayLoad = 0, mayStore=0 in {
 defm MIN  : BinaryIntrinsicFloat<IL_OP_MIN, int_AMDIL_min>;
-defm MAX  : BinaryIntrinsicFloat<IL_OP_MAX, int_AMDIL_max>;
 defm MAD  : TernaryIntrinsicFloat<IL_OP_MAD, int_AMDIL_mad>;
   }
 defm MOD  : BinaryOpMCf32<IL_OP_MOD, frem>;
index fda6b27dd57437f76e19046990a8d9a4e144d829..ca2af739a4a1ce6a0fcc49ea87031602f6279a6b 100644 (file)
@@ -261,9 +261,8 @@ def MUL_IEEE : R600_2OP <
 
 def MAX : R600_2OP <
   0x3, "MAX",
-  [(set R600_Reg32:$dst, (int_AMDIL_max R600_Reg32:$src0, R600_Reg32:$src1))]> {
-  let AMDILOp = AMDILInst.MAX_f32;
-}
+  [(set R600_Reg32:$dst, (AMDGPUfmax R600_Reg32:$src0, R600_Reg32:$src1))]
+>;
 
 def MIN : R600_2OP <
   0x4, "MIN",
@@ -370,7 +369,7 @@ def SUB_INT : R600_2OP <
 
 def MAX_INT : R600_2OP <
   0x36, "MAX_INT",
-  [(set R600_Reg32:$dst, (int_AMDGPU_imax R600_Reg32:$src0, R600_Reg32:$src1))]>;
+  [(set R600_Reg32:$dst, (AMDGPUsmax R600_Reg32:$src0, R600_Reg32:$src1))]>;
 
 def MIN_INT : R600_2OP <
   0x37, "MIN_INT",
@@ -378,7 +377,7 @@ def MIN_INT : R600_2OP <
 
 def MAX_UINT : R600_2OP <
   0x38, "MAX_UINT",
-  [(set R600_Reg32:$dst, (int_AMDGPU_umax R600_Reg32:$src0, R600_Reg32:$src1))]>;
+  [(set R600_Reg32:$dst, (AMDGPUsmax R600_Reg32:$src0, R600_Reg32:$src1))]>;
 
 def MIN_UINT : R600_2OP <
   0x39, "MIN_UINT",
index 313728f044fefb67c00830c78466c1fb60511d88..4efc093e3748e5dfb19d972db8d7452532e6c62a 100644 (file)
@@ -606,8 +606,9 @@ defm V_MUL_F32 : VOP2_32 <0x00000008, "V_MUL_F32", []>;
 //defm V_MUL_HI_U32_U24 : VOP2_32 <0x0000000c, "V_MUL_HI_U32_U24", []>;
 defm V_MIN_LEGACY_F32 : VOP2_32 <0x0000000d, "V_MIN_LEGACY_F32", []>;
 
-defm V_MAX_LEGACY_F32 : VOP2_32 <0x0000000e, "V_MAX_LEGACY_F32", [],
-                                 AMDILInst.MAX_f32>;
+defm V_MAX_LEGACY_F32 : VOP2_32 <0x0000000e, "V_MAX_LEGACY_F32",
+  [(set VReg_32:$dst, (AMDGPUfmax AllReg_32:$src0, VReg_32:$src1))]
+>;
 defm V_MIN_F32 : VOP2_32 <0x0000000f, "V_MIN_F32", []>;
 defm V_MAX_F32 : VOP2_32 <0x00000010, "V_MAX_F32", []>;
 defm V_MIN_I32 : VOP2_32 <0x00000011, "V_MIN_I32", []>;