X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FTarget%2FHexagon%2FHexagonISelDAGToDAG.cpp;h=687f097351dab6132d49901e8a23c602092cd6e0;hp=05bb4b224fc94255a1aa860d32712837896f4776;hb=c848b1bbcf88ab5d8318d990612fb1fda206ea3d;hpb=71d56462a1bc885c97321eff2fc4b481fd3bf452 diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index 05bb4b224fc..687f097351d 100644 --- a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -11,21 +11,34 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "hexagon-isel" +#include "Hexagon.h" #include "HexagonISelLowering.h" #include "HexagonTargetMachine.h" -#include "llvm/Intrinsics.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" - using namespace llvm; +#define DEBUG_TYPE "hexagon-isel" + +static +cl::opt +MaxNumOfUsesForConstExtenders("ga-max-num-uses-for-constant-extenders", + cl::Hidden, cl::init(2), + cl::desc("Maximum number of uses of a global address such that we still us a" + "constant extended instruction")); //===----------------------------------------------------------------------===// // Instruction Selector Implementation //===----------------------------------------------------------------------===// +namespace llvm { + void initializeHexagonDAGToDAGISelPass(PassRegistry&); +} + //===--------------------------------------------------------------------===// /// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine /// instructions for SelectionDAG operations. @@ -37,21 +50,24 @@ class HexagonDAGToDAGISel : public SelectionDAGISel { const HexagonSubtarget &Subtarget; // Keep a reference to HexagonTargetMachine. - HexagonTargetMachine& TM; - const HexagonInstrInfo *TII; - + const HexagonTargetMachine& TM; + DenseMap GlobalAddressUseCountMap; public: - explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine) - : SelectionDAGISel(targetmachine), + explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine, + CodeGenOpt::Level OptLevel) + : SelectionDAGISel(targetmachine, OptLevel), Subtarget(targetmachine.getSubtarget()), - TM(targetmachine), - TII(static_cast(TM.getInstrInfo())) { - + TM(targetmachine) { + initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry()); } + bool hasNumUsesBelowThresGA(SDNode *N) const; SDNode *Select(SDNode *N); // Complex Pattern Selectors. + inline bool foldGlobalAddress(SDValue &N, SDValue &R); + inline bool foldGlobalAddressGP(SDValue &N, SDValue &R); + bool foldGlobalAddressImpl(SDValue &N, SDValue &R, bool ShouldLookForGP); bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2); bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2); bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2); @@ -75,14 +91,14 @@ public: bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset); SDNode *SelectLoad(SDNode *N); - SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl); - SDNode *SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl); + SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl); + SDNode *SelectIndexedLoad(LoadSDNode *LD, SDLoc dl); SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode, - DebugLoc dl); + SDLoc dl); SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode, - DebugLoc dl); - SDNode *SelectBaseOffsetStore(StoreSDNode *ST, DebugLoc dl); - SDNode *SelectIndexedStore(StoreSDNode *ST, DebugLoc dl); + SDLoc dl); + SDNode *SelectBaseOffsetStore(StoreSDNode *ST, SDLoc dl); + SDNode *SelectIndexedStore(StoreSDNode *ST, SDLoc dl); SDNode *SelectStore(SDNode *N); SDNode *SelectSHL(SDNode *N); SDNode *SelectSelect(SDNode *N); @@ -90,10 +106,71 @@ public: SDNode *SelectMul(SDNode *N); SDNode *SelectZeroExtend(SDNode *N); SDNode *SelectIntrinsicWOChain(SDNode *N); + SDNode *SelectIntrinsicWChain(SDNode *N); SDNode *SelectConstant(SDNode *N); + SDNode *SelectConstantFP(SDNode *N); SDNode *SelectAdd(SDNode *N); + bool isConstExtProfitable(SDNode *N) const; + +// XformMskToBitPosU5Imm - Returns the bit position which +// the single bit 32 bit mask represents. +// Used in Clr and Set bit immediate memops. +SDValue XformMskToBitPosU5Imm(uint32_t Imm) { + int32_t bitPos; + bitPos = Log2_32(Imm); + assert(bitPos >= 0 && bitPos < 32 && + "Constant out of range for 32 BitPos Memops"); + return CurDAG->getTargetConstant(bitPos, MVT::i32); +} - // Include the pieces autogenerated from the target description. +// XformMskToBitPosU4Imm - Returns the bit position which the single bit 16 bit +// mask represents. Used in Clr and Set bit immediate memops. +SDValue XformMskToBitPosU4Imm(uint16_t Imm) { + return XformMskToBitPosU5Imm(Imm); +} + +// XformMskToBitPosU3Imm - Returns the bit position which the single bit 8 bit +// mask represents. Used in Clr and Set bit immediate memops. +SDValue XformMskToBitPosU3Imm(uint8_t Imm) { + return XformMskToBitPosU5Imm(Imm); +} + +// Return true if there is exactly one bit set in V, i.e., if V is one of the +// following integers: 2^0, 2^1, ..., 2^31. +bool ImmIsSingleBit(uint32_t v) const { + uint32_t c = CountPopulation_64(v); + // Only return true if we counted 1 bit. + return c == 1; +} + +// XformM5ToU5Imm - Return a target constant with the specified value, of type +// i32 where the negative literal is transformed into a positive literal for +// use in -= memops. +inline SDValue XformM5ToU5Imm(signed Imm) { + assert( (Imm >= -31 && Imm <= -1) && "Constant out of range for Memops"); + return CurDAG->getTargetConstant( - Imm, MVT::i32); +} + + +// XformU7ToU7M1Imm - Return a target constant decremented by 1, in range +// [1..128], used in cmpb.gtu instructions. +inline SDValue XformU7ToU7M1Imm(signed Imm) { + assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op"); + return CurDAG->getTargetConstant(Imm - 1, MVT::i8); +} + +// XformS8ToS8M1Imm - Return a target constant decremented by 1. +inline SDValue XformSToSM1Imm(signed Imm) { + return CurDAG->getTargetConstant(Imm - 1, MVT::i32); +} + +// XformU8ToU8M1Imm - Return a target constant decremented by 1. +inline SDValue XformUToUM1Imm(unsigned Imm) { + assert((Imm >= 1) && "Cannot decrement unsigned int less than 1"); + return CurDAG->getTargetConstant(Imm - 1, MVT::i32); +} + +// Include the pieces autogenerated from the target description. #include "HexagonGenDAGISel.inc" }; } // end anonymous namespace @@ -102,10 +179,23 @@ public: /// createHexagonISelDag - This pass converts a legalized DAG into a /// Hexagon-specific DAG, ready for instruction scheduling. /// -FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM) { - return new HexagonDAGToDAGISel(TM); +FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM, + CodeGenOpt::Level OptLevel) { + return new HexagonDAGToDAGISel(TM, OptLevel); +} + +static void initializePassOnce(PassRegistry &Registry) { + const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection"; + PassInfo *PI = new PassInfo(Name, "hexagon-isel", + &SelectionDAGISel::ID, nullptr, false, false); + Registry.registerPass(*PI, true); +} + +void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) { + CALL_ONCE_INITIALIZATION(initializePassOnce) } + static bool IsS11_0_Offset(SDNode * S) { ConstantSDNode *N = cast(S); @@ -294,7 +384,7 @@ static bool OffsetFitsS11(EVT MemType, int64_t Offset) { // lowering for GlobalAddress nodes has already turned it into a // CONST32. // -SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) { +SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl) { SDValue Chain = LD->getChain(); SDNode* Const32 = LD->getBasePtr().getNode(); unsigned Opcode = 0; @@ -305,7 +395,7 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) { EVT LoadedVT = LD->getMemoryVT(); int64_t Offset = cast(Base)->getOffset(); if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) { - MVT PointerTy = TLI.getPointerTy(); + MVT PointerTy = getTargetLowering()->getPointerTy(); const GlobalValue* GV = cast(Base)->getGlobal(); SDValue TargAddr = @@ -318,7 +408,7 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) { else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed; else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed; else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed; - else assert (0 && "unknown memory type"); + else llvm_unreachable("unknown memory type"); // Build indexed load. SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy); @@ -342,7 +432,7 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) { SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode, - DebugLoc dl) + SDLoc dl) { SDValue Chain = LD->getChain(); EVT LoadedVT = LD->getMemoryVT(); @@ -353,8 +443,11 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, SDValue N1 = LD->getOperand(1); SDValue CPTmpN1_0; SDValue CPTmpN1_1; + if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && N1.getNode()->getValueType(0) == MVT::i32) { + const HexagonInstrInfo *TII = + static_cast(TM.getInstrInfo()); if (TII->isValidAutoIncImm(LoadedVT, Val)) { SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32); SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, @@ -406,7 +499,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode, - DebugLoc dl) + SDLoc dl) { SDValue Chain = LD->getChain(); EVT LoadedVT = LD->getMemoryVT(); @@ -417,8 +510,11 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, SDValue N1 = LD->getOperand(1); SDValue CPTmpN1_0; SDValue CPTmpN1_1; + if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && N1.getNode()->getValueType(0) == MVT::i32) { + const HexagonInstrInfo *TII = + static_cast(TM.getInstrInfo()); if (TII->isValidAutoIncImm(LoadedVT, Val)) { SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); @@ -481,7 +577,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, } -SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl) { +SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) { SDValue Chain = LD->getChain(); SDValue Base = LD->getBasePtr(); SDValue Offset = LD->getOffset(); @@ -495,6 +591,8 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl) { bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD); // Figure out the opcode. + const HexagonInstrInfo *TII = + static_cast(TM.getInstrInfo()); if (LoadedVT == MVT::i64) { if (TII->isValidAutoIncImm(LoadedVT, Val)) Opcode = Hexagon::POST_LDrid; @@ -516,7 +614,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl) { else Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib; } else - assert (0 && "unknown memory type"); + llvm_unreachable("unknown memory type"); // For zero ext i64 loads, we need to add combine instructions. if (LD->getValueType(0) == MVT::i64 && @@ -576,7 +674,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl) { SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) { SDNode *result; - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); LoadSDNode *LD = cast(N); ISD::MemIndexedMode AM = LD->getAddressingMode(); @@ -591,7 +689,7 @@ SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) { } -SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { +SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) { SDValue Chain = ST->getChain(); SDValue Base = ST->getBasePtr(); SDValue Offset = ST->getOffset(); @@ -603,9 +701,11 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { // Offset value must be within representable range // and must have correct alignment properties. + const HexagonInstrInfo *TII = + static_cast(TM.getInstrInfo()); if (TII->isValidAutoIncImm(StoredVT, Val)) { - SDValue Ops[] = { Value, Base, - CurDAG->getTargetConstant(Val, MVT::i32), Chain}; + SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value, + Chain}; unsigned Opcode = 0; // Figure out the post inc version of opcode. @@ -613,11 +713,11 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { else if (StoredVT == MVT::i32) Opcode = Hexagon::POST_STwri; else if (StoredVT == MVT::i16) Opcode = Hexagon::POST_SThri; else if (StoredVT == MVT::i8) Opcode = Hexagon::POST_STbri; - else assert (0 && "unknown memory type"); + else llvm_unreachable("unknown memory type"); // Build post increment store. SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32, - MVT::Other, Ops, 4); + MVT::Other, Ops); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); MemOp[0] = ST->getMemOperand(); cast(Result)->setMemRefs(MemOp, MemOp + 1); @@ -636,15 +736,14 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { // Figure out the opcode. if (StoredVT == MVT::i64) Opcode = Hexagon::STrid; - else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw; + else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih; else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib; - else assert (0 && "unknown memory type"); + else llvm_unreachable("unknown memory type"); // Build regular store. SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); - SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops, - 4); + SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops); // Build splitted incriment instruction. SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, Base, @@ -661,7 +760,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST, - DebugLoc dl) { + SDLoc dl) { SDValue Chain = ST->getChain(); SDNode* Const32 = ST->getBasePtr().getNode(); SDValue Value = ST->getValue(); @@ -679,7 +778,7 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST, EVT StoredVT = ST->getMemoryVT(); int64_t Offset = cast(Base)->getOffset(); if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) { - MVT PointerTy = TLI.getPointerTy(); + MVT PointerTy = getTargetLowering()->getPointerTy(); const GlobalValue* GV = cast(Base)->getGlobal(); SDValue TargAddr = @@ -693,14 +792,14 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST, else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed; else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed; - else assert (0 && "unknown memory type"); + else llvm_unreachable("unknown memory type"); SDValue Ops[] = {SDValue(NewBase,0), CurDAG->getTargetConstant(Offset,PointerTy), Value, Chain}; // build indexed store SDNode* Result = CurDAG->getMachineNode(Opcode, dl, - MVT::Other, Ops, 4); + MVT::Other, Ops); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); MemOp[0] = ST->getMemOperand(); cast(Result)->setMemRefs(MemOp, MemOp + 1); @@ -715,7 +814,7 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST, SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); StoreSDNode *ST = cast(N); ISD::MemIndexedMode AM = ST->getAddressingMode(); @@ -728,7 +827,7 @@ SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) { } SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); // // %conv.i = sext i32 %tmp1 to i64 @@ -752,7 +851,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) { SDValue Sext0 = MulOp0.getOperand(0); if (Sext0.getNode()->getValueType(0) != MVT::i32) { - SelectCode(N); + return SelectCode(N); } OP0 = Sext0; @@ -761,7 +860,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { if (LD->getMemoryVT() != MVT::i32 || LD->getExtensionType() != ISD::SEXTLOAD || LD->getAddressingMode() != ISD::UNINDEXED) { - SelectCode(N); + return SelectCode(N); } SDValue Chain = LD->getChain(); @@ -812,7 +911,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); SDValue N0 = N->getOperand(0); if (N0.getOpcode() == ISD::SETCC) { SDValue N00 = N0.getOperand(0); @@ -879,7 +978,7 @@ SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) { SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); SDValue Shift = N->getOperand(0); // @@ -992,7 +1091,7 @@ SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); if (N->getValueType(0) == MVT::i32) { SDValue Shl_0 = N->getOperand(0); SDValue Shl_1 = N->getOperand(1); @@ -1068,7 +1167,7 @@ SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) { // We want to preserve all the lower 8-bits and, not just 1 LSB bit. // SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); SDNode *IsIntrinsic = N->getOperand(0).getNode(); if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) { unsigned ID = @@ -1111,7 +1210,7 @@ SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { // and lowering to the actual intrinsic. // SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); unsigned ID = cast(N->getOperand(0))->getZExtValue(); unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID); @@ -1119,6 +1218,8 @@ SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { // as at least one of the operands. if (IntrinsicWithPred) { SmallVector Ops; + const HexagonInstrInfo *TII = + static_cast(TM.getInstrInfo()); const MCInstrDesc &MCID = TII->get(IntrinsicWithPred); const TargetRegisterInfo *TRI = TM.getRegisterInfo(); @@ -1128,7 +1229,7 @@ SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { // For immediates, lower it. for (unsigned i = 1; i < N->getNumOperands(); ++i) { SDNode *Arg = N->getOperand(i).getNode(); - const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI); + const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI, *MF); if (RC == &Hexagon::IntRegsRegClass || RC == &Hexagon::DoubleRegsRegClass) { @@ -1138,7 +1239,7 @@ SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { SDNode *PdRs = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, SDValue(Arg, 0)); Ops.push_back(SDValue(PdRs,0)); - } else if (RC == NULL && (dyn_cast(Arg) != NULL)) { + } else if (!RC && (dyn_cast(Arg) != nullptr)) { // This is immediate operand. Lower it here making sure that we DO have // const SDNode for immediate value. int32_t Val = cast(Arg)->getSExtValue(); @@ -1150,20 +1251,38 @@ SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { } EVT ReturnValueVT = N->getValueType(0); SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl, - ReturnValueVT, - Ops.data(), Ops.size()); + ReturnValueVT, Ops); ReplaceUses(N, Result); return Result; } return SelectCode(N); } +// +// Map floating point constant values. +// +SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) { + SDLoc dl(N); + ConstantFPSDNode *CN = dyn_cast(N); + APFloat APF = CN->getValueAPF(); + if (N->getValueType(0) == MVT::f32) { + return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32, + CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32)); + } + else if (N->getValueType(0) == MVT::f64) { + return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64, + CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64)); + } + + return SelectCode(N); +} + // // Map predicate true (encoded as -1 in LLVM) to a XOR. // SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); if (N->getValueType(0) == MVT::i1) { SDNode* Result; int32_t Val = cast(N)->getSExtValue(); @@ -1202,7 +1321,7 @@ SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) { // Map add followed by a asr -> asr +=. // SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + SDLoc dl(N); if (N->getValueType(0) != MVT::i32) { return SelectCode(N); } @@ -1226,14 +1345,19 @@ SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) { SDNode *HexagonDAGToDAGISel::Select(SDNode *N) { - if (N->isMachineOpcode()) - return NULL; // Already selected. + if (N->isMachineOpcode()) { + N->setNodeId(-1); + return nullptr; // Already selected. + } switch (N->getOpcode()) { case ISD::Constant: return SelectConstant(N); + case ISD::ConstantFP: + return SelectConstantFP(N); + case ISD::ADD: return SelectAdd(N); @@ -1483,3 +1607,79 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, OutOps.push_back(Op1); return false; } + +bool HexagonDAGToDAGISel::isConstExtProfitable(SDNode *N) const { + unsigned UseCount = 0; + for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) { + UseCount++; + } + + return (UseCount <= 1); + +} + +//===--------------------------------------------------------------------===// +// Return 'true' if use count of the global address is below threshold. +//===--------------------------------------------------------------------===// +bool HexagonDAGToDAGISel::hasNumUsesBelowThresGA(SDNode *N) const { + assert(N->getOpcode() == ISD::TargetGlobalAddress && + "Expecting a target global address"); + + // Always try to fold the address. + if (TM.getOptLevel() == CodeGenOpt::Aggressive) + return true; + + GlobalAddressSDNode *GA = cast(N); + DenseMap::const_iterator GI = + GlobalAddressUseCountMap.find(GA->getGlobal()); + + if (GI == GlobalAddressUseCountMap.end()) + return false; + + return GI->second <= MaxNumOfUsesForConstExtenders; +} + +//===--------------------------------------------------------------------===// +// Return true if the non-GP-relative global address can be folded. +//===--------------------------------------------------------------------===// +inline bool HexagonDAGToDAGISel::foldGlobalAddress(SDValue &N, SDValue &R) { + return foldGlobalAddressImpl(N, R, false); +} + +//===--------------------------------------------------------------------===// +// Return true if the GP-relative global address can be folded. +//===--------------------------------------------------------------------===// +inline bool HexagonDAGToDAGISel::foldGlobalAddressGP(SDValue &N, SDValue &R) { + return foldGlobalAddressImpl(N, R, true); +} + +//===--------------------------------------------------------------------===// +// Fold offset of the global address if number of uses are below threshold. +//===--------------------------------------------------------------------===// +bool HexagonDAGToDAGISel::foldGlobalAddressImpl(SDValue &N, SDValue &R, + bool ShouldLookForGP) { + if (N.getOpcode() == ISD::ADD) { + SDValue N0 = N.getOperand(0); + SDValue N1 = N.getOperand(1); + if ((ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32_GP)) || + (!ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32))) { + ConstantSDNode *Const = dyn_cast(N1); + GlobalAddressSDNode *GA = + dyn_cast(N0.getOperand(0)); + + if (Const && GA && + (GA->getOpcode() == ISD::TargetGlobalAddress)) { + if ((N0.getOpcode() == HexagonISD::CONST32) && + !hasNumUsesBelowThresGA(GA)) + return false; + R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), + SDLoc(Const), + N.getValueType(), + GA->getOffset() + + (uint64_t)Const->getSExtValue()); + return true; + } + } + } + return false; +}