-//==-- HexagonISelDAGToDAG.cpp - A dag to dag inst selector for Hexagon ----==//
+//===-- HexagonISelDAGToDAG.cpp - A dag to dag inst selector for Hexagon --===//
//
// The LLVM Compiler Infrastructure
//
//
//===----------------------------------------------------------------------===//
-#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<unsigned>
+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.
class HexagonDAGToDAGISel : public SelectionDAGISel {
/// Subtarget - Keep a pointer to the Hexagon Subtarget around so that we can
/// make the right decision when generating code for different targets.
- const HexagonSubtarget &Subtarget;
+ const HexagonSubtarget *Subtarget;
// Keep a reference to HexagonTargetMachine.
- HexagonTargetMachine& TM;
- const HexagonInstrInfo *TII;
-
+ const HexagonTargetMachine& TM;
+ DenseMap<const GlobalValue *, unsigned> GlobalAddressUseCountMap;
public:
- explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine)
- : SelectionDAGISel(targetmachine),
- Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()),
- TM(targetmachine),
- TII(static_cast<const HexagonInstrInfo*>(TM.getInstrInfo())) {
-
+ explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine,
+ CodeGenOpt::Level OptLevel)
+ : SelectionDAGISel(targetmachine, OptLevel), TM(targetmachine) {
+ initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry());
}
+ bool hasNumUsesBelowThresGA(SDNode *N) const;
- SDNode *Select(SDNode *N);
+ SDNode *Select(SDNode *N) override;
// 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);
bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2);
bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2);
- virtual const char *getPassName() const {
+ // Complex Pattern Selectors.
+ inline bool SelectAddrGA(SDValue &N, SDValue &R);
+ inline bool SelectAddrGP(SDValue &N, SDValue &R);
+ bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP);
+ bool SelectAddrFI(SDValue &N, SDValue &R);
+
+ const char *getPassName() const override {
return "Hexagon DAG->DAG Pattern Instruction Selection";
}
+ bool runOnMachineFunction(MachineFunction &MF) override {
+ Subtarget = &MF.getSubtarget<HexagonSubtarget>();
+ return SelectionDAGISel::runOnMachineFunction(MF);
+ }
+
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
/// inline asm expressions.
- virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
- char ConstraintCode,
- std::vector<SDValue> &OutOps);
+ bool SelectInlineAsmMemoryOperand(const SDValue &Op,
+ char ConstraintCode,
+ std::vector<SDValue> &OutOps) override;
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);
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);
+}
+
+// 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;
+}
- // Include the pieces autogenerated from the target description.
+// 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);
+}
+
+// XformSToSM2Imm - Return a target constant decremented by 2.
+inline SDValue XformSToSM2Imm(unsigned Imm) {
+ return CurDAG->getTargetConstant(Imm - 2, MVT::i32);
+}
+
+// XformSToSM3Imm - Return a target constant decremented by 3.
+inline SDValue XformSToSM3Imm(unsigned Imm) {
+ return CurDAG->getTargetConstant(Imm - 3, MVT::i32);
+}
+
+// Include the pieces autogenerated from the target description.
#include "HexagonGenDAGISel.inc"
+
+private:
+ bool isValueExtension(SDValue const &Val, unsigned FromBits, SDValue &Src);
};
} // end anonymous namespace
/// 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<ConstantSDNode>(S);
}
}
-
-// Intrinsics that have predicate operands.
-static unsigned doesIntrinsicContainPredicate(unsigned ID)
-{
- switch (ID) {
- default:
- return 0;
- case Intrinsic::hexagon_C2_tfrpr:
- return Hexagon::TFR_RsPd;
- case Intrinsic::hexagon_C2_and:
- return Hexagon::AND_pp;
- case Intrinsic::hexagon_C2_xor:
- return Hexagon::XOR_pp;
- case Intrinsic::hexagon_C2_or:
- return Hexagon::OR_pp;
- case Intrinsic::hexagon_C2_not:
- return Hexagon::NOT_p;
- case Intrinsic::hexagon_C2_any8:
- return Hexagon::ANY_pp;
- case Intrinsic::hexagon_C2_all8:
- return Hexagon::ALL_pp;
- case Intrinsic::hexagon_C2_vitpack:
- return Hexagon::VITPACK_pp;
- case Intrinsic::hexagon_C2_mask:
- return Hexagon::MASK_p;
- case Intrinsic::hexagon_C2_mux:
- return Hexagon::MUX_rr;
-
- // Mapping hexagon_C2_muxir to MUX_pri. This is pretty weird - but
- // that's how it's mapped in q6protos.h.
- case Intrinsic::hexagon_C2_muxir:
- return Hexagon::MUX_ri;
-
- // Mapping hexagon_C2_muxri to MUX_pir. This is pretty weird - but
- // that's how it's mapped in q6protos.h.
- case Intrinsic::hexagon_C2_muxri:
- return Hexagon::MUX_ir;
-
- case Intrinsic::hexagon_C2_muxii:
- return Hexagon::MUX_ii;
- case Intrinsic::hexagon_C2_vmux:
- return Hexagon::VMUX_prr64;
- case Intrinsic::hexagon_S2_valignrb:
- return Hexagon::VALIGN_rrp;
- case Intrinsic::hexagon_S2_vsplicerb:
- return Hexagon::VSPLICE_rrp;
- }
-}
-
-
static bool OffsetFitsS11(EVT MemType, int64_t Offset) {
if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) {
return true;
// 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;
EVT LoadedVT = LD->getMemoryVT();
int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) {
- MVT PointerTy = TLI.getPointerTy();
+ MVT PointerTy = getTargetLowering()->getPointerTy();
const GlobalValue* GV =
cast<GlobalAddressSDNode>(Base)->getGlobal();
SDValue TargAddr =
dl, PointerTy,
TargAddr);
// Figure out base + offset opcode
- if (LoadedVT == MVT::i64) Opcode = Hexagon::LDrid_indexed;
- 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");
+ if (LoadedVT == MVT::i64) Opcode = Hexagon::L2_loadrd_io;
+ else if (LoadedVT == MVT::i32) Opcode = Hexagon::L2_loadri_io;
+ else if (LoadedVT == MVT::i16) Opcode = Hexagon::L2_loadrh_io;
+ else if (LoadedVT == MVT::i8) Opcode = Hexagon::L2_loadrb_io;
+ else llvm_unreachable("unknown memory type");
// Build indexed load.
SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy);
SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
unsigned Opcode,
- DebugLoc dl)
+ SDLoc dl)
{
SDValue Chain = LD->getChain();
EVT LoadedVT = LD->getMemoryVT();
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 = Subtarget->getInstrInfo();
if (TII->isValidAutoIncImm(LoadedVT, Val)) {
SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32);
SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
MVT::Other, Base, TargetConst,
Chain);
- SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, MVT::i64,
+ SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
SDValue(Result_1, 0));
MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
MemOp[0] = LD->getMemOperand();
};
ReplaceUses(Froms, Tos, 3);
return Result_2;
- }
+ }
SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
MVT::Other, Base, TargetConst0,
Chain);
- SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl,
+ SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl,
MVT::i64, SDValue(Result_1, 0));
- SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl,
+ SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl,
MVT::i32, Base, TargetConstVal,
SDValue(Result_1, 1));
MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
unsigned Opcode,
- DebugLoc dl)
+ SDLoc dl)
{
SDValue Chain = LD->getChain();
EVT LoadedVT = LD->getMemoryVT();
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 = Subtarget->getInstrInfo();
if (TII->isValidAutoIncImm(LoadedVT, Val)) {
SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
MVT::i32, MVT::Other, Base,
TargetConstVal, Chain);
- SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
+ SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
TargetConst0);
- SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
+ SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
MVT::i64, MVT::Other,
SDValue(Result_2,0),
SDValue(Result_1,0));
SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
MVT::Other,
Base, TargetConst0, Chain);
- SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
+ SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
TargetConst0);
- SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
+ SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
MVT::i64, MVT::Other,
SDValue(Result_2,0),
SDValue(Result_1,0));
// Add offset to base.
- SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
+ SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Base, TargetConstVal,
SDValue(Result_1, 1));
MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
}
-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();
bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD);
// Figure out the opcode.
+ const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
if (LoadedVT == MVT::i64) {
if (TII->isValidAutoIncImm(LoadedVT, Val))
- Opcode = Hexagon::POST_LDrid;
+ Opcode = Hexagon::L2_loadrd_pi;
else
- Opcode = Hexagon::LDrid;
+ Opcode = Hexagon::L2_loadrd_io;
} else if (LoadedVT == MVT::i32) {
if (TII->isValidAutoIncImm(LoadedVT, Val))
- Opcode = Hexagon::POST_LDriw;
+ Opcode = Hexagon::L2_loadri_pi;
else
- Opcode = Hexagon::LDriw;
+ Opcode = Hexagon::L2_loadri_io;
} else if (LoadedVT == MVT::i16) {
if (TII->isValidAutoIncImm(LoadedVT, Val))
- Opcode = zextval ? Hexagon::POST_LDriuh : Hexagon::POST_LDrih;
+ Opcode = zextval ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi;
else
- Opcode = zextval ? Hexagon::LDriuh : Hexagon::LDrih;
+ Opcode = zextval ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io;
} else if (LoadedVT == MVT::i8) {
if (TII->isValidAutoIncImm(LoadedVT, Val))
- Opcode = zextval ? Hexagon::POST_LDriub : Hexagon::POST_LDrib;
+ Opcode = zextval ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi;
else
- Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib;
+ Opcode = zextval ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io;
} 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 &&
LD->getValueType(0),
MVT::Other, Base, TargetConst0,
Chain);
- SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
+ SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Base, TargetConstVal,
SDValue(Result_1, 1));
MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
SDNode *result;
- DebugLoc dl = N->getDebugLoc();
+ SDLoc dl(N);
LoadSDNode *LD = cast<LoadSDNode>(N);
ISD::MemIndexedMode AM = LD->getAddressingMode();
}
-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();
// Offset value must be within representable range
// and must have correct alignment properties.
+ const HexagonInstrInfo *TII = Subtarget->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.
- if (StoredVT == MVT::i64) Opcode = Hexagon::POST_STdri;
- 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");
+ if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi;
+ else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi;
+ else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi;
+ else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi;
+ 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<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
unsigned Opcode = 0;
// Figure out the opcode.
- if (StoredVT == MVT::i64) Opcode = Hexagon::STrid;
- else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw;
- else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih;
- else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib;
- else assert (0 && "unknown memory type");
+ if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
+ else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
+ else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
+ else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
+ 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,
+ SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Base,
TargetConstVal,
SDValue(Result_1, 0));
SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST,
- DebugLoc dl) {
+ SDLoc dl) {
SDValue Chain = ST->getChain();
SDNode* Const32 = ST->getBasePtr().getNode();
SDValue Value = ST->getValue();
EVT StoredVT = ST->getMemoryVT();
int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) {
- MVT PointerTy = TLI.getPointerTy();
+ MVT PointerTy = getTargetLowering()->getPointerTy();
const GlobalValue* GV =
cast<GlobalAddressSDNode>(Base)->getGlobal();
SDValue TargAddr =
TargAddr);
// Figure out base + offset opcode
- if (StoredVT == MVT::i64) Opcode = Hexagon::STrid_indexed;
- 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");
+ if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
+ else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
+ else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
+ else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
+ 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<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
- DebugLoc dl = N->getDebugLoc();
+ SDLoc dl(N);
StoreSDNode *ST = cast<StoreSDNode>(N);
ISD::MemIndexedMode AM = ST->getAddressingMode();
if (AM != ISD::UNINDEXED) {
return SelectIndexedStore(ST, dl);
}
-
+
return SelectBaseOffsetStore(ST, dl);
}
SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
- DebugLoc dl = N->getDebugLoc();
+ SDLoc dl(N);
//
// %conv.i = sext i32 %tmp1 to i64
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;
if (LD->getMemoryVT() != MVT::i32 ||
LD->getExtensionType() != ISD::SEXTLOAD ||
LD->getAddressingMode() != ISD::UNINDEXED) {
- SelectCode(N);
+ return SelectCode(N);
}
SDValue Chain = LD->getChain();
SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
- OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
+ OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
MVT::Other,
LD->getBasePtr(), TargetConst0,
Chain), 0);
SDValue Chain = LD->getChain();
SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
- OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
+ OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
MVT::Other,
LD->getBasePtr(), TargetConst0,
Chain), 0);
}
// Generate a mpy instruction.
- SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY64, dl, MVT::i64,
+ SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64,
OP0, OP1);
ReplaceUses(N, Result);
return Result;
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);
if (N000 == N2 &&
N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
- SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl,
+ SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
MVT::i32, N000);
- SDNode *Result = CurDAG->getMachineNode(Hexagon::MAXw_rr, dl,
+ SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_max, dl,
MVT::i32,
SDValue(SextNode, 0),
N1);
if (N000 == N2 &&
N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
- SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl,
+ SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
MVT::i32, N000);
- SDNode *Result = CurDAG->getMachineNode(Hexagon::MINw_rr, dl,
+ SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_min, dl,
MVT::i32,
SDValue(SextNode, 0),
N1);
SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) {
- DebugLoc dl = N->getDebugLoc();
+ SDLoc dl(N);
SDValue Shift = N->getOperand(0);
//
SDValue Chain = LD->getChain();
SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
- OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
+ OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
MVT::Other,
LD->getBasePtr(),
TargetConst0, Chain), 0);
SDValue Chain = LD->getChain();
SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
- OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
+ OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
MVT::Other,
LD->getBasePtr(),
TargetConst0, Chain), 0);
}
// Generate a mpy instruction.
- SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY, dl, MVT::i32,
+ SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpy_up, dl, MVT::i32,
OP0, OP1);
ReplaceUses(N, Result);
return Result;
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);
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
if (isInt<9>(CN->getSExtValue())) {
SDNode* Result =
- CurDAG->getMachineNode(Hexagon::MPYI_ri, dl,
+ CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
MVT::i32, Mul_0, Val);
ReplaceUses(N, Result);
return Result;
dyn_cast<ConstantSDNode>(Val.getNode()))
if (isInt<9>(CN->getSExtValue())) {
SDNode* Result =
- CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, MVT::i32,
+ CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32,
Shl2_0, Val);
ReplaceUses(N, Result);
return Result;
// 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 =
if (N->getValueType(0) == MVT::i64) {
// Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs).
SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
- SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl,
+ SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
MVT::i32,
SDValue(IsIntrinsic, 0));
- SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl,
+ SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl,
MVT::i32,
TargetConst0);
- SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
+ SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
MVT::i64, MVT::Other,
SDValue(Result_2, 0),
SDValue(Result_1, 0));
}
if (N->getValueType(0) == MVT::i32) {
// Convert the zero_extend to Rs = Pd
- SDNode* RsPd = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl,
+ SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
MVT::i32,
SDValue(IsIntrinsic, 0));
ReplaceUses(N, RsPd);
return SelectCode(N);
}
-
//
// Checking for intrinsics which have predicate registers as operand(s)
// and lowering to the actual intrinsic.
//
SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
- DebugLoc dl = N->getDebugLoc();
- unsigned ID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
- unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID);
-
- // We are concerned with only those intrinsics that have predicate registers
- // as at least one of the operands.
- if (IntrinsicWithPred) {
- SmallVector<SDValue, 8> Ops;
- const MCInstrDesc &MCID = TII->get(IntrinsicWithPred);
- const TargetRegisterInfo *TRI = TM.getRegisterInfo();
-
- // Iterate over all the operands of the intrinsics.
- // For PredRegs, do the transfer.
- // For Double/Int Regs, just preserve the value
- // 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);
-
- if (RC == Hexagon::IntRegsRegisterClass ||
- RC == Hexagon::DoubleRegsRegisterClass) {
- Ops.push_back(SDValue(Arg, 0));
- } else if (RC == Hexagon::PredRegsRegisterClass) {
- // Do the transfer.
- 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<ConstantSDNode>(Arg) != NULL)) {
- // This is immediate operand. Lower it here making sure that we DO have
- // const SDNode for immediate value.
- int32_t Val = cast<ConstantSDNode>(Arg)->getSExtValue();
- SDValue SDVal = CurDAG->getTargetConstant(Val, MVT::i32);
- Ops.push_back(SDVal);
- } else {
- llvm_unreachable("Unimplemented");
- }
- }
- EVT ReturnValueVT = N->getValueType(0);
- SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl,
- ReturnValueVT,
- Ops.data(), Ops.size());
- ReplaceUses(N, Result);
- return Result;
+ unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
+ unsigned Bits;
+ switch (IID) {
+ case Intrinsic::hexagon_S2_vsplatrb:
+ Bits = 8;
+ break;
+ case Intrinsic::hexagon_S2_vsplatrh:
+ Bits = 16;
+ break;
+ default:
+ return SelectCode(N);
+ }
+
+ SDValue const &V = N->getOperand(1);
+ SDValue U;
+ if (isValueExtension(V, Bits, U)) {
+ SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
+ N->getOperand(0), U);
+ return SelectCode(R.getNode());
}
return SelectCode(N);
}
+//
+// Map floating point constant values.
+//
+SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
+ SDLoc dl(N);
+ ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(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<ConstantSDNode>(N)->getSExtValue();
if (Val == -1) {
// Create the IntReg = 1 node.
SDNode* IntRegTFR =
- CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
+ CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
CurDAG->getTargetConstant(0, MVT::i32));
// Pd = IntReg
- SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1,
+ SDNode* Pd = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::i1,
SDValue(IntRegTFR, 0));
// not(Pd)
- SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_p, dl, MVT::i1,
+ SDNode* NotPd = CurDAG->getMachineNode(Hexagon::C2_not, dl, MVT::i1,
SDValue(Pd, 0));
// xor(not(Pd))
- Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1,
+ Result = CurDAG->getMachineNode(Hexagon::C2_xor, dl, MVT::i1,
SDValue(Pd, 0), SDValue(NotPd, 0));
// We have just built:
// 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);
}
// Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
// Rd and Rd' are assigned to the same register
- SDNode* Result = CurDAG->getMachineNode(Hexagon::ASR_rr_acc, dl, MVT::i32,
+ SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32,
N->getOperand(1),
Src1->getOperand(0),
Src1->getOperand(1));
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);
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<GlobalAddressSDNode>(N);
+ DenseMap<const GlobalValue *, unsigned>::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<ConstantSDNode>(N1);
+ GlobalAddressSDNode *GA =
+ dyn_cast<GlobalAddressSDNode>(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;
+}
+
+bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) {
+ if (N.getOpcode() != ISD::FrameIndex)
+ return false;
+ FrameIndexSDNode *FX = cast<FrameIndexSDNode>(N);
+ R = CurDAG->getTargetFrameIndex(FX->getIndex(), MVT::i32);
+ return true;
+}
+
+inline bool HexagonDAGToDAGISel::SelectAddrGA(SDValue &N, SDValue &R) {
+ return SelectGlobalAddress(N, R, false);
+}
+
+inline bool HexagonDAGToDAGISel::SelectAddrGP(SDValue &N, SDValue &R) {
+ return SelectGlobalAddress(N, R, true);
+}
+
+bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
+ bool UseGP) {
+ switch (N.getOpcode()) {
+ case ISD::ADD: {
+ SDValue N0 = N.getOperand(0);
+ SDValue N1 = N.getOperand(1);
+ unsigned GAOpc = N0.getOpcode();
+ if (UseGP && GAOpc != HexagonISD::CONST32_GP)
+ return false;
+ if (!UseGP && GAOpc != HexagonISD::CONST32)
+ return false;
+ if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) {
+ SDValue Addr = N0.getOperand(0);
+ if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Addr)) {
+ if (GA->getOpcode() == ISD::TargetGlobalAddress) {
+ uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
+ R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),
+ N.getValueType(), NewOff);
+ return true;
+ }
+ }
+ }
+ break;
+ }
+ case HexagonISD::CONST32:
+ // The operand(0) of CONST32 is TargetGlobalAddress, which is what we
+ // want in the instruction.
+ if (!UseGP)
+ R = N.getOperand(0);
+ return !UseGP;
+ case HexagonISD::CONST32_GP:
+ if (UseGP)
+ R = N.getOperand(0);
+ return UseGP;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+bool HexagonDAGToDAGISel::isValueExtension(SDValue const &Val,
+ unsigned FromBits, SDValue &Src) {
+ unsigned Opc = Val.getOpcode();
+ switch (Opc) {
+ case ISD::SIGN_EXTEND:
+ case ISD::ZERO_EXTEND:
+ case ISD::ANY_EXTEND: {
+ SDValue const &Op0 = Val.getOperand(0);
+ EVT T = Op0.getValueType();
+ if (T.isInteger() && T.getSizeInBits() == FromBits) {
+ Src = Op0;
+ return true;
+ }
+ break;
+ }
+ case ISD::SIGN_EXTEND_INREG:
+ case ISD::AssertSext:
+ case ISD::AssertZext:
+ if (Val.getOperand(0).getValueType().isInteger()) {
+ VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
+ if (T->getVT().getSizeInBits() == FromBits) {
+ Src = Val.getOperand(0);
+ return true;
+ }
+ }
+ break;
+ case ISD::AND: {
+ // Check if this is an AND with "FromBits" of lower bits set to 1.
+ uint64_t FromMask = (1 << FromBits) - 1;
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
+ if (C->getZExtValue() == FromMask) {
+ Src = Val.getOperand(1);
+ return true;
+ }
+ }
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
+ if (C->getZExtValue() == FromMask) {
+ Src = Val.getOperand(0);
+ return true;
+ }
+ }
+ break;
+ }
+ case ISD::OR:
+ case ISD::XOR: {
+ // OR/XOR with the lower "FromBits" bits set to 0.
+ uint64_t FromMask = (1 << FromBits) - 1;
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
+ if ((C->getZExtValue() & FromMask) == 0) {
+ Src = Val.getOperand(1);
+ return true;
+ }
+ }
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
+ if ((C->getZExtValue() & FromMask) == 0) {
+ Src = Val.getOperand(0);
+ return true;
+ }
+ }
+ }
+ default:
+ break;
+ }
+ return false;
+}