From 83e6c9925e86cc6d89cf31ae536ec8eee20e72eb Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 4 Oct 2006 06:57:07 +0000 Subject: [PATCH] Pattern match min/max nodes when we have sse. This implements CodeGen/X86/scalar_sse_minmax.ll git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30719 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 66 ++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 6ab7c98b4a0..bb7c669284b 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -386,6 +386,7 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) // We have target-specific dag combine patterns for the following nodes: setTargetDAGCombine(ISD::VECTOR_SHUFFLE); + setTargetDAGCombine(ISD::SELECT); computeRegisterProperties(); @@ -5355,6 +5356,69 @@ static SDOperand PerformShuffleCombine(SDNode *N, SelectionDAG &DAG, } } +/// PerformSELECTCombine - Do target-specific dag combines on SELECT nodes. +static SDOperand PerformSELECTCombine(SDNode *N, SelectionDAG &DAG, + const X86Subtarget *Subtarget) { + SDOperand Cond = N->getOperand(0); + + // If we have SSE[12] support, try to form min/max nodes. + if (Subtarget->hasSSE2() && + (N->getValueType(0) == MVT::f32 || N->getValueType(0) == MVT::f64)) { + if (Cond.getOpcode() == ISD::SETCC) { + // Get the LHS/RHS of the select. + SDOperand LHS = N->getOperand(1); + SDOperand RHS = N->getOperand(2); + ISD::CondCode CC = cast(Cond.getOperand(2))->get(); + + unsigned IntNo = 0; + if (LHS == Cond.getOperand(0) && RHS == Cond.getOperand(1)) { + // (X olt Y) ? X : Y -> min + if (CC == ISD::SETOLT || CC == ISD::SETLT) + IntNo = LHS.getValueType() == MVT::f32 ? Intrinsic::x86_sse_min_ss : + Intrinsic::x86_sse2_min_sd; + // (X uge Y) ? X : Y -> max + if (CC == ISD::SETUGE || CC == ISD::SETGE) + IntNo = LHS.getValueType() == MVT::f32 ? Intrinsic::x86_sse_max_ss : + Intrinsic::x86_sse2_max_sd; + // TODO: Handle more cases if unsafe math! + } else if (LHS == Cond.getOperand(1) && RHS == Cond.getOperand(0)) { + // (X uge Y) ? Y : X -> min + if (CC == ISD::SETUGE || CC == ISD::SETGE) + IntNo = LHS.getValueType() == MVT::f32 ? Intrinsic::x86_sse_min_ss : + Intrinsic::x86_sse2_min_sd; + // (X olt Y) ? Y : X -> max + if (CC == ISD::SETOLT || CC == ISD::SETLT) + IntNo = LHS.getValueType() == MVT::f32 ? Intrinsic::x86_sse_max_ss : + Intrinsic::x86_sse2_max_sd; + // TODO: Handle more cases if unsafe math! + } + + // minss/maxss take a v4f32 operand. + if (IntNo) { + if (LHS.getValueType() == MVT::f32) { + LHS = DAG.getNode(ISD::SCALAR_TO_VECTOR, MVT::v4f32, LHS); + RHS = DAG.getNode(ISD::SCALAR_TO_VECTOR, MVT::v4f32, RHS); + } else { + LHS = DAG.getNode(ISD::SCALAR_TO_VECTOR, MVT::v2f64, LHS); + RHS = DAG.getNode(ISD::SCALAR_TO_VECTOR, MVT::v2f64, RHS); + } + + MVT::ValueType PtrTy = Subtarget->is64Bit() ? MVT::i64 : MVT::i32; + SDOperand IntNoN = DAG.getConstant(IntNo, PtrTy); + + SDOperand Val = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, LHS.getValueType(), + IntNoN, LHS, RHS); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, N->getValueType(0), Val, + DAG.getConstant(0, PtrTy)); + } + } + + } + + return SDOperand(); +} + + SDOperand X86TargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { TargetMachine &TM = getTargetMachine(); @@ -5363,6 +5427,8 @@ SDOperand X86TargetLowering::PerformDAGCombine(SDNode *N, default: break; case ISD::VECTOR_SHUFFLE: return PerformShuffleCombine(N, DAG, Subtarget); + case ISD::SELECT: + return PerformSELECTCombine(N, DAG, Subtarget); } return SDOperand();