diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 644a73f6d1b..ae44ff07981 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -17,8 +17,15 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/Function.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; +namespace llvm { + cl::opt FSELTMP("ppc-fsel-custom-legalizer", cl::Hidden, + cl::desc("Use a custom expander for fsel on ppc")); +} + + PPC32TargetLowering::PPC32TargetLowering(TargetMachine &TM) : TargetLowering(TM) { @@ -65,6 +72,12 @@ PPC32TargetLowering::PPC32TargetLowering(TargetMachine &TM) setOperationAction(ISD::SELECT, MVT::i32, Expand); setOperationAction(ISD::SELECT, MVT::f32, Expand); setOperationAction(ISD::SELECT, MVT::f64, Expand); + + // PowerPC wants to turn select_cc of FP into fsel. + if (FSELTMP) { + setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); + } // PowerPC does not have BRCOND* which requires SetCC setOperationAction(ISD::BRCOND, MVT::Other, Expand); @@ -78,12 +91,54 @@ PPC32TargetLowering::PPC32TargetLowering(TargetMachine &TM) setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); setSetCCResultContents(ZeroOrOneSetCCResult); - addLegalFPImmediate(+0.0); // Necessary for FSEL - addLegalFPImmediate(-0.0); // + if (!FSELTMP) { + addLegalFPImmediate(+0.0); // Necessary for FSEL + addLegalFPImmediate(-0.0); // + } computeRegisterProperties(); } +/// LowerOperation - Provide custom lowering hooks for some operations. +/// +SDOperand PPC32TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { + switch (Op.getOpcode()) { + default: assert(0 && "Wasn't expecting to be able to lower this!"); + case ISD::SELECT_CC: + // Turn FP only select_cc's into fsel instructions. + if (MVT::isFloatingPoint(Op.getOperand(0).getValueType()) && + MVT::isFloatingPoint(Op.getOperand(2).getValueType())) { + ISD::CondCode CC = cast(Op.getOperand(4))->get(); + MVT::ValueType ResVT = Op.getValueType(); + MVT::ValueType CmpVT = Op.getOperand(0).getValueType(); + SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1); + SDOperand TV = Op.getOperand(2), FV = Op.getOperand(3); + + switch (CC) { + default: assert(0 && "Invalid FSEL condition"); abort(); + case ISD::SETULT: + case ISD::SETLT: + return DAG.getTargetNode(PPC::FSEL, ResVT, + DAG.getNode(ISD::SUB, CmpVT, LHS, RHS), FV,TV); + case ISD::SETUGE: + case ISD::SETGE: + return DAG.getTargetNode(PPC::FSEL, ResVT, + DAG.getNode(ISD::SUB, CmpVT, LHS, RHS), TV,FV); + case ISD::SETUGT: + case ISD::SETGT: + return DAG.getTargetNode(PPC::FSEL, ResVT, + DAG.getNode(ISD::SUB, CmpVT, RHS, LHS), FV,TV); + case ISD::SETULE: + case ISD::SETLE: + return DAG.getTargetNode(PPC::FSEL, ResVT, + DAG.getNode(ISD::SUB, CmpVT, RHS, LHS), TV,FV); + } + } + break; + } + return SDOperand(); +} + std::vector PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { // diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index 4198e2637bc..aa01934aa1e 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -24,6 +24,10 @@ namespace llvm { public: PPC32TargetLowering(TargetMachine &TM); + /// LowerOperation - Provide custom lowering hooks for some operations. + /// + virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); + /// LowerArguments - This hook must be implemented to indicate how we should /// lower the arguments for the specified function, into the specified DAG. virtual std::vector diff --git a/lib/Target/PowerPC/PPCISelPattern.cpp b/lib/Target/PowerPC/PPCISelPattern.cpp index 07529c7e017..102b4b3845d 100644 --- a/lib/Target/PowerPC/PPCISelPattern.cpp +++ b/lib/Target/PowerPC/PPCISelPattern.cpp @@ -829,6 +829,12 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) { default: Node->dump(); std::cerr << '\n'; assert(0 && "Node not handled!\n"); + case ISD::BUILTIN_OP_END+PPC::FSEL: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + Tmp3 = SelectExpr(N.getOperand(2)); + BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); + return Result; case ISD::UNDEF: if (Node->getValueType(0) == MVT::i32) BuildMI(BB, PPC::IMPLICIT_DEF_GPR, 0, Result);