diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/VE/VEISelDAGToDAG.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Target/VE/VEISelDAGToDAG.cpp | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/VE/VEISelDAGToDAG.cpp b/contrib/llvm-project/llvm/lib/Target/VE/VEISelDAGToDAG.cpp index 43030993efb9..f3d067d55fdb 100644 --- a/contrib/llvm-project/llvm/lib/Target/VE/VEISelDAGToDAG.cpp +++ b/contrib/llvm-project/llvm/lib/Target/VE/VEISelDAGToDAG.cpp @@ -23,6 +23,105 @@ using namespace llvm; // Instruction Selector Implementation //===----------------------------------------------------------------------===// +/// Convert a DAG integer condition code to a VE ICC condition. +inline static VECC::CondCode intCondCode2Icc(ISD::CondCode CC) { + switch (CC) { + default: + llvm_unreachable("Unknown integer condition code!"); + case ISD::SETEQ: + return VECC::CC_IEQ; + case ISD::SETNE: + return VECC::CC_INE; + case ISD::SETLT: + return VECC::CC_IL; + case ISD::SETGT: + return VECC::CC_IG; + case ISD::SETLE: + return VECC::CC_ILE; + case ISD::SETGE: + return VECC::CC_IGE; + case ISD::SETULT: + return VECC::CC_IL; + case ISD::SETULE: + return VECC::CC_ILE; + case ISD::SETUGT: + return VECC::CC_IG; + case ISD::SETUGE: + return VECC::CC_IGE; + } +} + +/// Convert a DAG floating point condition code to a VE FCC condition. +inline static VECC::CondCode fpCondCode2Fcc(ISD::CondCode CC) { + switch (CC) { + default: + llvm_unreachable("Unknown fp condition code!"); + case ISD::SETFALSE: + return VECC::CC_AF; + case ISD::SETEQ: + case ISD::SETOEQ: + return VECC::CC_EQ; + case ISD::SETNE: + case ISD::SETONE: + return VECC::CC_NE; + case ISD::SETLT: + case ISD::SETOLT: + return VECC::CC_L; + case ISD::SETGT: + case ISD::SETOGT: + return VECC::CC_G; + case ISD::SETLE: + case ISD::SETOLE: + return VECC::CC_LE; + case ISD::SETGE: + case ISD::SETOGE: + return VECC::CC_GE; + case ISD::SETO: + return VECC::CC_NUM; + case ISD::SETUO: + return VECC::CC_NAN; + case ISD::SETUEQ: + return VECC::CC_EQNAN; + case ISD::SETUNE: + return VECC::CC_NENAN; + case ISD::SETULT: + return VECC::CC_LNAN; + case ISD::SETUGT: + return VECC::CC_GNAN; + case ISD::SETULE: + return VECC::CC_LENAN; + case ISD::SETUGE: + return VECC::CC_GENAN; + case ISD::SETTRUE: + return VECC::CC_AT; + } +} + +/// getImmVal - get immediate representation of integer value +inline static uint64_t getImmVal(const ConstantSDNode *N) { + return N->getSExtValue(); +} + +/// getFpImmVal - get immediate representation of floating point value +inline static uint64_t getFpImmVal(const ConstantFPSDNode *N) { + const APInt &Imm = N->getValueAPF().bitcastToAPInt(); + uint64_t Val = Imm.getZExtValue(); + if (Imm.getBitWidth() == 32) { + // Immediate value of float place places at higher bits on VE. + Val <<= 32; + } + return Val; +} + +/// convMImmVal - Convert a mimm integer immediate value to target immediate. +inline static uint64_t convMImmVal(uint64_t Val) { + if (Val == 0) + return 0; // (0)1 + if (Val & (1UL << 63)) + return countLeadingOnes(Val); // (m)1 + return countLeadingZeros(Val) | 0x40; // (m)0 +} + //===--------------------------------------------------------------------===// /// VEDAGToDAGISel - VE specific code to select VE machine /// instructions for SelectionDAG operations. @@ -43,15 +142,172 @@ public: void Select(SDNode *N) override; + // Complex Pattern Selectors. + bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); + bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); + bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); + bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); + bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset); + StringRef getPassName() const override { return "VE DAG->DAG Pattern Instruction Selection"; } // Include the pieces autogenerated from the target description. #include "VEGenDAGISel.inc" + +private: + SDNode *getGlobalBaseReg(); + + bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index); + bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset); }; } // end anonymous namespace +bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index, + SDValue &Offset) { + if (Addr.getOpcode() == ISD::FrameIndex) + return false; + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress || + Addr.getOpcode() == ISD::TargetGlobalTLSAddress) + return false; // direct calls. + + SDValue LHS, RHS; + if (matchADDRri(Addr, LHS, RHS)) { + if (matchADDRrr(LHS, Base, Index)) { + Offset = RHS; + return true; + } + // Return false to try selectADDRrii. + return false; + } + if (matchADDRrr(Addr, LHS, RHS)) { + if (matchADDRri(RHS, Index, Offset)) { + Base = LHS; + return true; + } + if (matchADDRri(LHS, Base, Offset)) { + Index = RHS; + return true; + } + Base = LHS; + Index = RHS; + Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); + return true; + } + return false; // Let the reg+imm(=0) pattern catch this! +} + +bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index, + SDValue &Offset) { + if (matchADDRri(Addr, Base, Offset)) { + Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); + return true; + } + + Base = Addr; + Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); + Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); + return true; +} + +bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index, + SDValue &Offset) { + // Prefer ADDRrii. + return false; +} + +bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index, + SDValue &Offset) { + if (dyn_cast<FrameIndexSDNode>(Addr)) { + return false; + } + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress || + Addr.getOpcode() == ISD::TargetGlobalTLSAddress) + return false; // direct calls. + + if (ConstantSDNode *CN = cast<ConstantSDNode>(Addr)) { + if (isInt<32>(CN->getSExtValue())) { + Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); + Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); + Offset = + CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); + return true; + } + } + return false; +} + +bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base, + SDValue &Offset) { + if (matchADDRri(Addr, Base, Offset)) + return true; + + Base = Addr; + Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); + return true; +} + +bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) { + if (dyn_cast<FrameIndexSDNode>(Addr)) + return false; + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress || + Addr.getOpcode() == ISD::TargetGlobalTLSAddress) + return false; // direct calls. + + if (Addr.getOpcode() == ISD::ADD) { + ; // Nothing to do here. + } else if (Addr.getOpcode() == ISD::OR) { + // We want to look through a transform in InstCombine and DAGCombiner that + // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'. + if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1))) + return false; + } else { + return false; + } + + if (Addr.getOperand(0).getOpcode() == VEISD::Lo || + Addr.getOperand(1).getOpcode() == VEISD::Lo) + return false; // Let the LEASL patterns catch this! + + Base = Addr.getOperand(0); + Index = Addr.getOperand(1); + return true; +} + +bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) { + auto AddrTy = Addr->getValueType(0); + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy); + Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); + return true; + } + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress || + Addr.getOpcode() == ISD::TargetGlobalTLSAddress) + return false; // direct calls. + + if (CurDAG->isBaseWithConstantOffset(Addr)) { + ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1)); + if (isInt<32>(CN->getSExtValue())) { + if (FrameIndexSDNode *FIN = + dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { + // Constant offset from frame ref. + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy); + } else { + Base = Addr.getOperand(0); + } + Offset = + CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); + return true; + } + } + return false; +} + void VEDAGToDAGISel::Select(SDNode *N) { SDLoc dl(N); if (N->isMachineOpcode()) { @@ -59,9 +315,22 @@ void VEDAGToDAGISel::Select(SDNode *N) { return; // Already selected. } + switch (N->getOpcode()) { + case VEISD::GLOBAL_BASE_REG: + ReplaceNode(N, getGlobalBaseReg()); + return; + } + SelectCode(N); } +SDNode *VEDAGToDAGISel::getGlobalBaseReg() { + Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF); + return CurDAG + ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout())) + .getNode(); +} + /// createVEISelDag - This pass converts a legalized DAG into a /// VE-specific DAG, ready for instruction scheduling. /// |