X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparcV8%2FSparcV8ISelDAGToDAG.cpp;h=c2741059b03a01ced677a102ed51f37b9e37fb6b;hb=6184f9ca5eff6f7f55264d447638b7a27b806c9c;hp=62062185201d0eefc1e6633d12b9c70a13bfa206;hpb=44ea7b1a6cc96121f9a558902742e19fa876d847;p=oota-llvm.git diff --git a/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp b/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp index 62062185201..c2741059b03 100644 --- a/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp +++ b/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp @@ -33,30 +33,76 @@ using namespace llvm; namespace V8ISD { enum { FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END, - CMPICC, // Compare two GPR operands, set icc. - CMPFCC, // Compare two FP operands, set fcc. - BRICC, // Branch to dest on icc condition - BRFCC, // Branch to dest on fcc condition + CMPICC, // Compare two GPR operands, set icc. + CMPFCC, // Compare two FP operands, set fcc. + BRICC, // Branch to dest on icc condition + BRFCC, // Branch to dest on fcc condition + SELECT_ICC, // Select between two values using the current ICC flags. + SELECT_FCC, // Select between two values using the current FCC flags. - Hi, Lo, // Hi/Lo operations, typically on a global address. + Hi, Lo, // Hi/Lo operations, typically on a global address. - FTOI, // FP to Int within a FP register. - ITOF, // Int to FP within a FP register. - - SELECT_ICC, // Select between two values using the current ICC flags. - SELECT_FCC, // Select between two values using the current FCC flags. - - CALL, // A V8 call instruction. - RET_FLAG, // Return with a flag operand. + FTOI, // FP to Int within a FP register. + ITOF, // Int to FP within a FP register. + + CALL, // A V8 call instruction. + RET_FLAG, // Return with a flag operand. }; } +/// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC +/// condition. +static V8CC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { + switch (CC) { + default: assert(0 && "Unknown integer condition code!"); + case ISD::SETEQ: return V8CC::ICC_E; + case ISD::SETNE: return V8CC::ICC_NE; + case ISD::SETLT: return V8CC::ICC_L; + case ISD::SETGT: return V8CC::ICC_G; + case ISD::SETLE: return V8CC::ICC_LE; + case ISD::SETGE: return V8CC::ICC_GE; + case ISD::SETULT: return V8CC::ICC_CS; + case ISD::SETULE: return V8CC::ICC_LEU; + case ISD::SETUGT: return V8CC::ICC_GU; + case ISD::SETUGE: return V8CC::ICC_CC; + } +} + +/// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC +/// FCC condition. +static V8CC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { + switch (CC) { + default: assert(0 && "Unknown fp condition code!"); + case ISD::SETEQ: return V8CC::FCC_E; + case ISD::SETNE: return V8CC::FCC_NE; + case ISD::SETLT: return V8CC::FCC_L; + case ISD::SETGT: return V8CC::FCC_G; + case ISD::SETLE: return V8CC::FCC_LE; + case ISD::SETGE: return V8CC::FCC_GE; + case ISD::SETULT: return V8CC::FCC_UL; + case ISD::SETULE: return V8CC::FCC_ULE; + case ISD::SETUGT: return V8CC::FCC_UG; + case ISD::SETUGE: return V8CC::FCC_UGE; + case ISD::SETUO: return V8CC::FCC_U; + case ISD::SETO: return V8CC::FCC_O; + case ISD::SETONE: return V8CC::FCC_LG; + case ISD::SETUEQ: return V8CC::FCC_UE; + } +} + namespace { class SparcV8TargetLowering : public TargetLowering { int VarArgsFrameOffset; // Frame offset to start of varargs area. public: SparcV8TargetLowering(TargetMachine &TM); virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); + + /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to + /// be zero. Op is expected to be a target specific node. Used by DAG + /// combiner. + virtual bool isMaskedValueZeroForTargetNode(const SDOperand &Op, + uint64_t Mask) const; + virtual std::vector LowerArguments(Function &F, SelectionDAG &DAG); virtual std::pair @@ -166,10 +212,17 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM) setOperationAction(ISD::VAEND , MVT::Other, Expand); setOperationAction(ISD::STACKSAVE , MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand); - setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand); + setOperationAction(ISD::ConstantFP, MVT::f64, Expand); + setOperationAction(ISD::ConstantFP, MVT::f32, Expand); + setStackPointerRegisterToSaveRestore(V8::O6); + if (TM.getSubtarget().isV9()) { + setOperationAction(ISD::CTPOP, MVT::i32, Legal); + } + computeRegisterProperties(); } @@ -180,17 +233,34 @@ const char *SparcV8TargetLowering::getTargetNodeName(unsigned Opcode) const { case V8ISD::CMPFCC: return "V8ISD::CMPFCC"; case V8ISD::BRICC: return "V8ISD::BRICC"; case V8ISD::BRFCC: return "V8ISD::BRFCC"; + case V8ISD::SELECT_ICC: return "V8ISD::SELECT_ICC"; + case V8ISD::SELECT_FCC: return "V8ISD::SELECT_FCC"; case V8ISD::Hi: return "V8ISD::Hi"; case V8ISD::Lo: return "V8ISD::Lo"; case V8ISD::FTOI: return "V8ISD::FTOI"; case V8ISD::ITOF: return "V8ISD::ITOF"; - case V8ISD::SELECT_ICC: return "V8ISD::SELECT_ICC"; - case V8ISD::SELECT_FCC: return "V8ISD::SELECT_FCC"; case V8ISD::CALL: return "V8ISD::CALL"; case V8ISD::RET_FLAG: return "V8ISD::RET_FLAG"; } } +/// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to +/// be zero. Op is expected to be a target specific node. Used by DAG +/// combiner. +bool SparcV8TargetLowering:: +isMaskedValueZeroForTargetNode(const SDOperand &Op, uint64_t Mask) const { + switch (Op.getOpcode()) { + default: return false; + case V8ISD::SELECT_ICC: + case V8ISD::SELECT_FCC: + assert(MVT::isInteger(Op.getValueType()) && "Not an integer select!"); + // These operations are masked zero if both the left and the right are zero. + return MaskedValueIsZero(Op.getOperand(0), Mask) && + MaskedValueIsZero(Op.getOperand(1), Mask); + } +} + + /// LowerArguments - V8 uses a very simple ABI, where all values are passed in /// either one or two GPRs, including FP values. TODO: we should pass FP values /// in FP registers for fastcc functions. @@ -284,7 +354,8 @@ SparcV8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { if (CurArgReg < ArgRegEnd) ++CurArgReg; if (CurArgReg < ArgRegEnd) ++CurArgReg; ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT)); - } else if (CurArgReg == ArgRegEnd && ObjectVT == MVT::f64 && + } else if (/* FIXME: Apparently this isn't safe?? */ + 0 && CurArgReg == ArgRegEnd && ObjectVT == MVT::f64 && ((CurArgReg-ArgRegs) & 1) == 0) { // If this is a double argument and the whole thing lives on the stack, // and the argument is aligned, load the double straight from the stack. @@ -587,6 +658,28 @@ LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, abort(); } +// Look at LHS/RHS/CC and see if they are a lowered V8 setcc instruction. If so +// set LHS/RHS and V8CC to the LHS/RHS of the setcc and V8CC to the condition. +static void LookThroughSetCC(SDOperand &LHS, SDOperand &RHS, + ISD::CondCode CC, unsigned &V8CC) { + if (isa(RHS) && cast(RHS)->getValue() == 0 && + CC == ISD::SETNE && + ((LHS.getOpcode() == V8ISD::SELECT_ICC && + LHS.getOperand(3).getOpcode() == V8ISD::CMPICC) || + (LHS.getOpcode() == V8ISD::SELECT_FCC && + LHS.getOperand(3).getOpcode() == V8ISD::CMPFCC)) && + isa(LHS.getOperand(0)) && + isa(LHS.getOperand(1)) && + cast(LHS.getOperand(0))->getValue() == 1 && + cast(LHS.getOperand(1))->getValue() == 0) { + SDOperand CMPCC = LHS.getOperand(3); + V8CC = cast(LHS.getOperand(2))->getValue(); + LHS = CMPCC.getOperand(0); + RHS = CMPCC.getOperand(1); + } +} + + SDOperand SparcV8TargetLowering:: LowerOperation(SDOperand Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { @@ -600,7 +693,8 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) { } case ISD::ConstantPool: { Constant *C = cast(Op)->get(); - SDOperand CP = DAG.getTargetConstantPool(C, MVT::i32); + SDOperand CP = DAG.getTargetConstantPool(C, MVT::i32, + cast(Op)->getAlignment()); SDOperand Hi = DAG.getNode(V8ISD::Hi, MVT::i32, CP); SDOperand Lo = DAG.getNode(V8ISD::Lo, MVT::i32, CP); return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi); @@ -618,12 +712,18 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) { } case ISD::BR_CC: { SDOperand Chain = Op.getOperand(0); - SDOperand CC = Op.getOperand(1); + ISD::CondCode CC = cast(Op.getOperand(1))->get(); SDOperand LHS = Op.getOperand(2); SDOperand RHS = Op.getOperand(3); SDOperand Dest = Op.getOperand(4); + unsigned Opc, V8CC = ~0U; + + // If this is a br_cc of a "setcc", and if the setcc got lowered into + // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. + LookThroughSetCC(LHS, RHS, CC, V8CC); // Get the condition flag. + SDOperand CompareFlag; if (LHS.getValueType() == MVT::i32) { std::vector VTs; VTs.push_back(MVT::i32); @@ -631,22 +731,30 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) { std::vector Ops; Ops.push_back(LHS); Ops.push_back(RHS); - SDOperand Cond = DAG.getNode(V8ISD::CMPICC, VTs, Ops).getValue(1); - return DAG.getNode(V8ISD::BRICC, MVT::Other, Chain, Dest, CC, Cond); + CompareFlag = DAG.getNode(V8ISD::CMPICC, VTs, Ops).getValue(1); + if (V8CC == ~0U) V8CC = IntCondCCodeToICC(CC); + Opc = V8ISD::BRICC; } else { - SDOperand Cond = DAG.getNode(V8ISD::CMPFCC, MVT::Flag, LHS, RHS); - return DAG.getNode(V8ISD::BRFCC, MVT::Other, Chain, Dest, CC, Cond); + CompareFlag = DAG.getNode(V8ISD::CMPFCC, MVT::Flag, LHS, RHS); + if (V8CC == ~0U) V8CC = FPCondCCodeToFCC(CC); + Opc = V8ISD::BRFCC; } + return DAG.getNode(Opc, MVT::Other, Chain, Dest, + DAG.getConstant(V8CC, MVT::i32), CompareFlag); } case ISD::SELECT_CC: { SDOperand LHS = Op.getOperand(0); SDOperand RHS = Op.getOperand(1); - unsigned CC = cast(Op.getOperand(4))->get(); + ISD::CondCode CC = cast(Op.getOperand(4))->get(); SDOperand TrueVal = Op.getOperand(2); SDOperand FalseVal = Op.getOperand(3); + unsigned Opc, V8CC = ~0U; + + // If this is a select_cc of a "setcc", and if the setcc got lowered into + // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. + LookThroughSetCC(LHS, RHS, CC, V8CC); SDOperand CompareFlag; - unsigned Opc; if (LHS.getValueType() == MVT::i32) { std::vector VTs; VTs.push_back(LHS.getValueType()); // subcc returns a value @@ -656,12 +764,14 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) { Ops.push_back(RHS); CompareFlag = DAG.getNode(V8ISD::CMPICC, VTs, Ops).getValue(1); Opc = V8ISD::SELECT_ICC; + if (V8CC == ~0U) V8CC = IntCondCCodeToICC(CC); } else { CompareFlag = DAG.getNode(V8ISD::CMPFCC, MVT::Flag, LHS, RHS); Opc = V8ISD::SELECT_FCC; + if (V8CC == ~0U) V8CC = FPCondCCodeToFCC(CC); } return DAG.getNode(Opc, TrueVal.getValueType(), TrueVal, FalseVal, - DAG.getConstant(CC, MVT::i32), CompareFlag); + DAG.getConstant(V8CC, MVT::i32), CompareFlag); } case ISD::VASTART: { // vastart just stores the address of the VarArgsFrameIndex slot into the @@ -708,50 +818,23 @@ MachineBasicBlock * SparcV8TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI, MachineBasicBlock *BB) { unsigned BROpcode; + unsigned CC; // Figure out the conditional branch opcode to use for this select_cc. switch (MI->getOpcode()) { default: assert(0 && "Unknown SELECT_CC!"); case V8::SELECT_CC_Int_ICC: case V8::SELECT_CC_FP_ICC: case V8::SELECT_CC_DFP_ICC: - // Integer compare. - switch ((ISD::CondCode)MI->getOperand(3).getImmedValue()) { - default: assert(0 && "Unknown integer condition code!"); - case ISD::SETEQ: BROpcode = V8::BE; break; - case ISD::SETNE: BROpcode = V8::BNE; break; - case ISD::SETLT: BROpcode = V8::BL; break; - case ISD::SETGT: BROpcode = V8::BG; break; - case ISD::SETLE: BROpcode = V8::BLE; break; - case ISD::SETGE: BROpcode = V8::BGE; break; - case ISD::SETULT: BROpcode = V8::BCS; break; - case ISD::SETULE: BROpcode = V8::BLEU; break; - case ISD::SETUGT: BROpcode = V8::BGU; break; - case ISD::SETUGE: BROpcode = V8::BCC; break; - } + BROpcode = V8::BCOND; break; case V8::SELECT_CC_Int_FCC: case V8::SELECT_CC_FP_FCC: case V8::SELECT_CC_DFP_FCC: - // FP compare. - switch ((ISD::CondCode)MI->getOperand(3).getImmedValue()) { - default: assert(0 && "Unknown fp condition code!"); - case ISD::SETEQ: BROpcode = V8::FBE; break; - case ISD::SETNE: BROpcode = V8::FBNE; break; - case ISD::SETLT: BROpcode = V8::FBL; break; - case ISD::SETGT: BROpcode = V8::FBG; break; - case ISD::SETLE: BROpcode = V8::FBLE; break; - case ISD::SETGE: BROpcode = V8::FBGE; break; - case ISD::SETULT: BROpcode = V8::FBUL; break; - case ISD::SETULE: BROpcode = V8::FBULE; break; - case ISD::SETUGT: BROpcode = V8::FBUG; break; - case ISD::SETUGE: BROpcode = V8::FBUGE; break; - case ISD::SETUO: BROpcode = V8::FBU; break; - case ISD::SETO: BROpcode = V8::FBO; break; - case ISD::SETONE: BROpcode = V8::FBLG; break; - case ISD::SETUEQ: BROpcode = V8::FBUE; break; - } + BROpcode = V8::FBCOND; break; } + + CC = (V8CC::CondCodes)MI->getOperand(3).getImmedValue(); // To "insert" a SELECT_CC instruction, we actually have to insert the diamond // control-flow pattern. The incoming instruction knows the destination vreg @@ -769,7 +852,7 @@ SparcV8TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI, MachineBasicBlock *thisMBB = BB; MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); - BuildMI(BB, BROpcode, 1).addMBB(sinkMBB); + BuildMI(BB, BROpcode, 2).addMBB(sinkMBB).addImm(CC); MachineFunction *F = BB->getParent(); F->getBasicBlockList().insert(It, copy0MBB); F->getBasicBlockList().insert(It, sinkMBB); @@ -808,9 +891,15 @@ SparcV8TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI, namespace { class SparcV8DAGToDAGISel : public SelectionDAGISel { SparcV8TargetLowering V8Lowering; + + /// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can + /// make the right decision when generating code for different targets. + const SparcV8Subtarget &Subtarget; public: SparcV8DAGToDAGISel(TargetMachine &TM) - : SelectionDAGISel(V8Lowering), V8Lowering(TM) {} + : SelectionDAGISel(V8Lowering), V8Lowering(TM), + Subtarget(TM.getSubtarget()) { + } SDOperand Select(SDOperand Op);