From: Tom Stellard Date: Wed, 18 Jul 2012 15:59:14 +0000 (-0400) Subject: radeon/llvm: Move LowerSELECT_CC into R600ISelLowering X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=47d1b0a80990dda4e14073f667f0c2b939dfb925;p=mesa.git radeon/llvm: Move LowerSELECT_CC into R600ISelLowering SI will handle SELECT_CC different from R600, so we need to move it out of the shared instruction selector. --- diff --git a/src/gallium/drivers/radeon/AMDGPUISelLowering.cpp b/src/gallium/drivers/radeon/AMDGPUISelLowering.cpp index b3d27f762e6..96b0d755687 100644 --- a/src/gallium/drivers/radeon/AMDGPUISelLowering.cpp +++ b/src/gallium/drivers/radeon/AMDGPUISelLowering.cpp @@ -24,9 +24,6 @@ AMDGPUTargetLowering::AMDGPUTargetLowering(TargetMachine &TM) : // We need to custom lower some of the intrinsics setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); - setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); - setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); - // Library functions. These default to Expand, but we have instructions // for them. setOperationAction(ISD::FCEIL, MVT::f32, Legal); @@ -44,7 +41,6 @@ SDValue AMDGPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) switch (Op.getOpcode()) { default: return AMDILTargetLowering::LowerOperation(Op, DAG); case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); - case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); case ISD::UDIVREM: return LowerUDIVREM(Op, DAG); } } @@ -126,112 +122,6 @@ SDValue AMDGPUTargetLowering::LowerIntrinsicLRP(SDValue Op, OneSubAC); } -SDValue AMDGPUTargetLowering::LowerSELECT_CC(SDValue Op, - SelectionDAG &DAG) const -{ - DebugLoc DL = Op.getDebugLoc(); - EVT VT = Op.getValueType(); - - SDValue LHS = Op.getOperand(0); - SDValue RHS = Op.getOperand(1); - SDValue True = Op.getOperand(2); - SDValue False = Op.getOperand(3); - SDValue CC = Op.getOperand(4); - ISD::CondCode CCOpcode = cast(CC)->get(); - SDValue Temp; - - // LHS and RHS are guaranteed to be the same value type - EVT CompareVT = LHS.getValueType(); - - // We need all the operands of SELECT_CC to have the same value type, so if - // necessary we need to convert LHS and RHS to be the same type True and - // False. True and False are guaranteed to have the same type as this - // SELECT_CC node. - - if (CompareVT != VT) { - ISD::NodeType ConversionOp = ISD::DELETED_NODE; - if (VT == MVT::f32 && CompareVT == MVT::i32) { - if (isUnsignedIntSetCC(CCOpcode)) { - ConversionOp = ISD::UINT_TO_FP; - } else { - ConversionOp = ISD::SINT_TO_FP; - } - } else if (VT == MVT::i32 && CompareVT == MVT::f32) { - ConversionOp = ISD::FP_TO_SINT; - } else { - // I don't think there will be any other type pairings. - assert(!"Unhandled operand type parings in SELECT_CC"); - } - // XXX Check the value of LHS and RHS and avoid creating sequences like - // (FTOI (ITOF)) - LHS = DAG.getNode(ConversionOp, DL, VT, LHS); - RHS = DAG.getNode(ConversionOp, DL, VT, RHS); - } - - // If True is a hardware TRUE value and False is a hardware FALSE value or - // vice-versa we can handle this with a native instruction (SET* instructions). - if ((isHWTrueValue(True) && isHWFalseValue(False))) { - return DAG.getNode(ISD::SELECT_CC, DL, VT, LHS, RHS, True, False, CC); - } - - // XXX If True is a hardware TRUE value and False is a hardware FALSE value, - // we can handle this with a native instruction, but we need to swap true - // and false and change the conditional. - if (isHWTrueValue(False) && isHWFalseValue(True)) { - } - - // XXX Check if we can lower this to a SELECT or if it is supported by a native - // operation. (The code below does this but we don't have the Instruction - // selection patterns to do this yet. -#if 0 - if (isZero(LHS) || isZero(RHS)) { - SDValue Cond = (isZero(LHS) ? RHS : LHS); - bool SwapTF = false; - switch (CCOpcode) { - case ISD::SETOEQ: - case ISD::SETUEQ: - case ISD::SETEQ: - SwapTF = true; - // Fall through - case ISD::SETONE: - case ISD::SETUNE: - case ISD::SETNE: - // We can lower to select - if (SwapTF) { - Temp = True; - True = False; - False = Temp; - } - // CNDE - return DAG.getNode(ISD::SELECT, DL, VT, Cond, True, False); - default: - // Supported by a native operation (CNDGE, CNDGT) - return DAG.getNode(ISD::SELECT_CC, DL, VT, LHS, RHS, True, False, CC); - } - } -#endif - - // If we make it this for it means we have no native instructions to handle - // this SELECT_CC, so we must lower it. - SDValue HWTrue, HWFalse; - - if (VT == MVT::f32) { - HWTrue = DAG.getConstantFP(1.0f, VT); - HWFalse = DAG.getConstantFP(0.0f, VT); - } else if (VT == MVT::i32) { - HWTrue = DAG.getConstant(-1, VT); - HWFalse = DAG.getConstant(0, VT); - } - else { - assert(!"Unhandled value type in LowerSELECT_CC"); - } - - // Lower this unsupported SELECT_CC into a combination of two supported - // SELECT_CC operations. - SDValue Cond = DAG.getNode(ISD::SELECT_CC, DL, VT, LHS, RHS, HWTrue, HWFalse, CC); - - return DAG.getNode(ISD::SELECT, DL, VT, Cond, True, False); -} SDValue AMDGPUTargetLowering::LowerUDIVREM(SDValue Op, diff --git a/src/gallium/drivers/radeon/AMDGPUISelLowering.h b/src/gallium/drivers/radeon/AMDGPUISelLowering.h index 72342c99614..3e6f9ccaced 100644 --- a/src/gallium/drivers/radeon/AMDGPUISelLowering.h +++ b/src/gallium/drivers/radeon/AMDGPUISelLowering.h @@ -23,7 +23,6 @@ class AMDGPUTargetLowering : public AMDILTargetLowering { private: SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerUDIVREM(SDValue Op, SelectionDAG &DAG) const; protected: diff --git a/src/gallium/drivers/radeon/R600ISelLowering.cpp b/src/gallium/drivers/radeon/R600ISelLowering.cpp index ee4fea88f5f..b903b5b58bb 100644 --- a/src/gallium/drivers/radeon/R600ISelLowering.cpp +++ b/src/gallium/drivers/radeon/R600ISelLowering.cpp @@ -35,6 +35,9 @@ R600TargetLowering::R600TargetLowering(TargetMachine &TM) : setOperationAction(ISD::ROTL, MVT::i32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); + setSchedulingPreference(Sched::VLIW); } @@ -269,6 +272,7 @@ SDValue R600TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const switch (Op.getOpcode()) { default: return AMDGPUTargetLowering::LowerOperation(Op, DAG); case ISD::ROTL: return LowerROTL(Op, DAG); + case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); } } @@ -284,3 +288,109 @@ SDValue R600TargetLowering::LowerROTL(SDValue Op, SelectionDAG &DAG) const DAG.getConstant(32, MVT::i32), Op.getOperand(1))); } + +SDValue R600TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const +{ + DebugLoc DL = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + SDValue True = Op.getOperand(2); + SDValue False = Op.getOperand(3); + SDValue CC = Op.getOperand(4); + ISD::CondCode CCOpcode = cast(CC)->get(); + SDValue Temp; + + // LHS and RHS are guaranteed to be the same value type + EVT CompareVT = LHS.getValueType(); + + // We need all the operands of SELECT_CC to have the same value type, so if + // necessary we need to convert LHS and RHS to be the same type True and + // False. True and False are guaranteed to have the same type as this + // SELECT_CC node. + + if (CompareVT != VT) { + ISD::NodeType ConversionOp = ISD::DELETED_NODE; + if (VT == MVT::f32 && CompareVT == MVT::i32) { + if (isUnsignedIntSetCC(CCOpcode)) { + ConversionOp = ISD::UINT_TO_FP; + } else { + ConversionOp = ISD::SINT_TO_FP; + } + } else if (VT == MVT::i32 && CompareVT == MVT::f32) { + ConversionOp = ISD::FP_TO_SINT; + } else { + // I don't think there will be any other type pairings. + assert(!"Unhandled operand type parings in SELECT_CC"); + } + // XXX Check the value of LHS and RHS and avoid creating sequences like + // (FTOI (ITOF)) + LHS = DAG.getNode(ConversionOp, DL, VT, LHS); + RHS = DAG.getNode(ConversionOp, DL, VT, RHS); + } + + // If True is a hardware TRUE value and False is a hardware FALSE value or + // vice-versa we can handle this with a native instruction (SET* instructions). + if ((isHWTrueValue(True) && isHWFalseValue(False))) { + return DAG.getNode(ISD::SELECT_CC, DL, VT, LHS, RHS, True, False, CC); + } + + // XXX If True is a hardware TRUE value and False is a hardware FALSE value, + // we can handle this with a native instruction, but we need to swap true + // and false and change the conditional. + if (isHWTrueValue(False) && isHWFalseValue(True)) { + } + + // XXX Check if we can lower this to a SELECT or if it is supported by a native + // operation. (The code below does this but we don't have the Instruction + // selection patterns to do this yet. +#if 0 + if (isZero(LHS) || isZero(RHS)) { + SDValue Cond = (isZero(LHS) ? RHS : LHS); + bool SwapTF = false; + switch (CCOpcode) { + case ISD::SETOEQ: + case ISD::SETUEQ: + case ISD::SETEQ: + SwapTF = true; + // Fall through + case ISD::SETONE: + case ISD::SETUNE: + case ISD::SETNE: + // We can lower to select + if (SwapTF) { + Temp = True; + True = False; + False = Temp; + } + // CNDE + return DAG.getNode(ISD::SELECT, DL, VT, Cond, True, False); + default: + // Supported by a native operation (CNDGE, CNDGT) + return DAG.getNode(ISD::SELECT_CC, DL, VT, LHS, RHS, True, False, CC); + } + } +#endif + + // If we make it this for it means we have no native instructions to handle + // this SELECT_CC, so we must lower it. + SDValue HWTrue, HWFalse; + + if (VT == MVT::f32) { + HWTrue = DAG.getConstantFP(1.0f, VT); + HWFalse = DAG.getConstantFP(0.0f, VT); + } else if (VT == MVT::i32) { + HWTrue = DAG.getConstant(-1, VT); + HWFalse = DAG.getConstant(0, VT); + } + else { + assert(!"Unhandled value type in LowerSELECT_CC"); + } + + // Lower this unsupported SELECT_CC into a combination of two supported + // SELECT_CC operations. + SDValue Cond = DAG.getNode(ISD::SELECT_CC, DL, VT, LHS, RHS, HWTrue, HWFalse, CC); + + return DAG.getNode(ISD::SELECT, DL, VT, Cond, True, False); +} diff --git a/src/gallium/drivers/radeon/R600ISelLowering.h b/src/gallium/drivers/radeon/R600ISelLowering.h index 7b91373187a..7c4157374b6 100644 --- a/src/gallium/drivers/radeon/R600ISelLowering.h +++ b/src/gallium/drivers/radeon/R600ISelLowering.h @@ -41,6 +41,8 @@ private: /// LowerROTL - Lower ROTL opcode to BITALIGN SDValue LowerROTL(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; + }; } // End namespace llvm;