blob: b0e04cf128ebea8688e051f7d91df543699a85f2 [file] [log] [blame]
Jia Liub22310f2012-02-18 12:03:15 +00001//===-- HexagonISelDAGToDAG.cpp - A dag to dag inst selector for Hexagon --===//
Tony Linthicum1213a7a2011-12-12 21:14:40 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the Hexagon target.
11//
12//===----------------------------------------------------------------------===//
13
Chandler Carruthed0881b2012-12-03 16:50:05 +000014#include "Hexagon.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000015#include "HexagonISelLowering.h"
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +000016#include "HexagonMachineFunctionInfo.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000017#include "HexagonTargetMachine.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000018#include "llvm/ADT/DenseMap.h"
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +000019#include "llvm/CodeGen/FunctionLoweringInfo.h"
20#include "llvm/CodeGen/MachineInstrBuilder.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000021#include "llvm/CodeGen/SelectionDAGISel.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000022#include "llvm/IR/Intrinsics.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000023#include "llvm/Support/CommandLine.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000024#include "llvm/Support/Compiler.h"
25#include "llvm/Support/Debug.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000026using namespace llvm;
27
Chandler Carruth84e68b22014-04-22 02:41:26 +000028#define DEBUG_TYPE "hexagon-isel"
29
Jyotsna Vermad9225242013-02-13 21:38:46 +000030static
31cl::opt<unsigned>
32MaxNumOfUsesForConstExtenders("ga-max-num-uses-for-constant-extenders",
33 cl::Hidden, cl::init(2),
34 cl::desc("Maximum number of uses of a global address such that we still us a"
35 "constant extended instruction"));
Tony Linthicum1213a7a2011-12-12 21:14:40 +000036
37//===----------------------------------------------------------------------===//
38// Instruction Selector Implementation
39//===----------------------------------------------------------------------===//
40
Jyotsna Vermad9225242013-02-13 21:38:46 +000041namespace llvm {
42 void initializeHexagonDAGToDAGISelPass(PassRegistry&);
43}
44
Tony Linthicum1213a7a2011-12-12 21:14:40 +000045//===--------------------------------------------------------------------===//
46/// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine
47/// instructions for SelectionDAG operations.
48///
49namespace {
50class HexagonDAGToDAGISel : public SelectionDAGISel {
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +000051 const HexagonTargetMachine &HTM;
Eric Christopher23a7d1e2015-03-21 03:12:59 +000052 const HexagonSubtarget *HST;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +000053 const HexagonInstrInfo *HII;
54 const HexagonRegisterInfo *HRI;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000055public:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +000056 explicit HexagonDAGToDAGISel(HexagonTargetMachine &tm,
Jyotsna Vermad9225242013-02-13 21:38:46 +000057 CodeGenOpt::Level OptLevel)
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +000058 : SelectionDAGISel(tm, OptLevel), HTM(tm), HST(nullptr), HII(nullptr),
59 HRI(nullptr) {
Jyotsna Vermad9225242013-02-13 21:38:46 +000060 initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry());
Tony Linthicum1213a7a2011-12-12 21:14:40 +000061 }
Eric Christopher23a7d1e2015-03-21 03:12:59 +000062
63 bool runOnMachineFunction(MachineFunction &MF) override {
64 // Reset the subtarget each time through.
65 HST = &MF.getSubtarget<HexagonSubtarget>();
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +000066 HII = HST->getInstrInfo();
67 HRI = HST->getRegisterInfo();
Eric Christopher23a7d1e2015-03-21 03:12:59 +000068 SelectionDAGISel::runOnMachineFunction(MF);
69 return true;
70 }
71
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +000072 virtual void PreprocessISelDAG() override;
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +000073 virtual void EmitFunctionEntryCode() override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000074
Craig Topper906c2cd2014-04-29 07:58:16 +000075 SDNode *Select(SDNode *N) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000076
77 // Complex Pattern Selectors.
Colin LeMahieu987b0942015-02-04 20:38:01 +000078 inline bool SelectAddrGA(SDValue &N, SDValue &R);
Colin LeMahieu51491352015-02-04 22:36:28 +000079 inline bool SelectAddrGP(SDValue &N, SDValue &R);
Colin LeMahieu987b0942015-02-04 20:38:01 +000080 bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP);
Colin LeMahieuc7522f32015-01-14 23:07:36 +000081 bool SelectAddrFI(SDValue &N, SDValue &R);
82
Craig Topper906c2cd2014-04-29 07:58:16 +000083 const char *getPassName() const override {
Tony Linthicum1213a7a2011-12-12 21:14:40 +000084 return "Hexagon DAG->DAG Pattern Instruction Selection";
85 }
86
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +000087 // Generate a machine instruction node corresponding to the circ/brev
88 // load intrinsic.
89 MachineSDNode *LoadInstrForLoadIntrinsic(SDNode *IntN);
90 // Given the circ/brev load intrinsic and the already generated machine
91 // instruction, generate the appropriate store (that is a part of the
92 // intrinsic's functionality).
93 SDNode *StoreInstrForLoadIntrinsic(MachineSDNode *LoadN, SDNode *IntN);
94
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +000095 SDNode *SelectFrameIndex(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000096 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
97 /// inline asm expressions.
Craig Topper906c2cd2014-04-29 07:58:16 +000098 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
Daniel Sanders60f1db02015-03-13 12:45:09 +000099 unsigned ConstraintID,
Craig Topper906c2cd2014-04-29 07:58:16 +0000100 std::vector<SDValue> &OutOps) override;
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000101 SDNode *SelectLoadOfLoadIntrinsic(LoadSDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000102 SDNode *SelectLoad(SDNode *N);
Andrew Trickef9de2a2013-05-25 02:42:55 +0000103 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl);
104 SDNode *SelectIndexedLoad(LoadSDNode *LD, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000105 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000106 SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000107 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000108 SDLoc dl);
109 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, SDLoc dl);
110 SDNode *SelectIndexedStore(StoreSDNode *ST, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000111 SDNode *SelectStore(SDNode *N);
112 SDNode *SelectSHL(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000113 SDNode *SelectMul(SDNode *N);
114 SDNode *SelectZeroExtend(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000115 SDNode *SelectIntrinsicWChain(SDNode *N);
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +0000116 SDNode *SelectIntrinsicWOChain(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000117 SDNode *SelectConstant(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000118 SDNode *SelectConstantFP(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000119 SDNode *SelectAdd(SDNode *N);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +0000120 SDNode *SelectBitOp(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000121
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000122 // XformMskToBitPosU5Imm - Returns the bit position which
123 // the single bit 32 bit mask represents.
124 // Used in Clr and Set bit immediate memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000125 SDValue XformMskToBitPosU5Imm(uint32_t Imm, SDLoc DL) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000126 int32_t bitPos;
127 bitPos = Log2_32(Imm);
128 assert(bitPos >= 0 && bitPos < 32 &&
129 "Constant out of range for 32 BitPos Memops");
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000130 return CurDAG->getTargetConstant(bitPos, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000131 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000132
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000133 // XformMskToBitPosU4Imm - Returns the bit position which the single-bit
134 // 16 bit mask represents. Used in Clr and Set bit immediate memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000135 SDValue XformMskToBitPosU4Imm(uint16_t Imm, SDLoc DL) {
136 return XformMskToBitPosU5Imm(Imm, DL);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000137 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000138
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000139 // XformMskToBitPosU3Imm - Returns the bit position which the single-bit
140 // 8 bit mask represents. Used in Clr and Set bit immediate memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000141 SDValue XformMskToBitPosU3Imm(uint8_t Imm, SDLoc DL) {
142 return XformMskToBitPosU5Imm(Imm, DL);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000143 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000144
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000145 // Return true if there is exactly one bit set in V, i.e., if V is one of the
146 // following integers: 2^0, 2^1, ..., 2^31.
147 bool ImmIsSingleBit(uint32_t v) const {
148 return isPowerOf2_32(v);
149 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000150
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000151 // XformM5ToU5Imm - Return a target constant with the specified value, of
152 // type i32 where the negative literal is transformed into a positive literal
153 // for use in -= memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000154 inline SDValue XformM5ToU5Imm(signed Imm, SDLoc DL) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000155 assert((Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
156 return CurDAG->getTargetConstant(-Imm, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000157 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000158
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000159 // XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
160 // [1..128], used in cmpb.gtu instructions.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000161 inline SDValue XformU7ToU7M1Imm(signed Imm, SDLoc DL) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000162 assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op");
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000163 return CurDAG->getTargetConstant(Imm - 1, DL, MVT::i8);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000164 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000165
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000166 // XformS8ToS8M1Imm - Return a target constant decremented by 1.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000167 inline SDValue XformSToSM1Imm(signed Imm, SDLoc DL) {
168 return CurDAG->getTargetConstant(Imm - 1, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000169 }
Jyotsna Verma60316252013-02-05 19:20:45 +0000170
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000171 // XformU8ToU8M1Imm - Return a target constant decremented by 1.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000172 inline SDValue XformUToUM1Imm(unsigned Imm, SDLoc DL) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000173 assert((Imm >= 1) && "Cannot decrement unsigned int less than 1");
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000174 return CurDAG->getTargetConstant(Imm - 1, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000175 }
Jyotsna Verma89c84822013-04-23 19:15:55 +0000176
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000177 // XformSToSM2Imm - Return a target constant decremented by 2.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000178 inline SDValue XformSToSM2Imm(unsigned Imm, SDLoc DL) {
179 return CurDAG->getTargetConstant(Imm - 2, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000180 }
Jyotsna Verma89c84822013-04-23 19:15:55 +0000181
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000182 // XformSToSM3Imm - Return a target constant decremented by 3.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000183 inline SDValue XformSToSM3Imm(unsigned Imm, SDLoc DL) {
184 return CurDAG->getTargetConstant(Imm - 3, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000185 }
Colin LeMahieu19ed07c2015-01-28 18:29:11 +0000186
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000187 // Include the pieces autogenerated from the target description.
188 #include "HexagonGenDAGISel.inc"
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +0000189
190private:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000191 bool isValueExtension(const SDValue &Val, unsigned FromBits, SDValue &Src);
192}; // end HexagonDAGToDAGISel
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000193} // end anonymous namespace
194
195
196/// createHexagonISelDag - This pass converts a legalized DAG into a
197/// Hexagon-specific DAG, ready for instruction scheduling.
198///
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000199namespace llvm {
200FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM,
201 CodeGenOpt::Level OptLevel) {
Jyotsna Vermad9225242013-02-13 21:38:46 +0000202 return new HexagonDAGToDAGISel(TM, OptLevel);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000203}
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000204}
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000205
Jyotsna Vermad9225242013-02-13 21:38:46 +0000206static void initializePassOnce(PassRegistry &Registry) {
207 const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection";
208 PassInfo *PI = new PassInfo(Name, "hexagon-isel",
Craig Topper062a2ba2014-04-25 05:30:21 +0000209 &SelectionDAGISel::ID, nullptr, false, false);
Jyotsna Vermad9225242013-02-13 21:38:46 +0000210 Registry.registerPass(*PI, true);
211}
212
213void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
214 CALL_ONCE_INITIALIZATION(initializePassOnce)
215}
216
217
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000218// Intrinsics that return a a predicate.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000219static bool doesIntrinsicReturnPredicate(unsigned ID) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000220 switch (ID) {
221 default:
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000222 return false;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000223 case Intrinsic::hexagon_C2_cmpeq:
224 case Intrinsic::hexagon_C2_cmpgt:
225 case Intrinsic::hexagon_C2_cmpgtu:
226 case Intrinsic::hexagon_C2_cmpgtup:
227 case Intrinsic::hexagon_C2_cmpgtp:
228 case Intrinsic::hexagon_C2_cmpeqp:
229 case Intrinsic::hexagon_C2_bitsset:
230 case Intrinsic::hexagon_C2_bitsclr:
231 case Intrinsic::hexagon_C2_cmpeqi:
232 case Intrinsic::hexagon_C2_cmpgti:
233 case Intrinsic::hexagon_C2_cmpgtui:
234 case Intrinsic::hexagon_C2_cmpgei:
235 case Intrinsic::hexagon_C2_cmpgeui:
236 case Intrinsic::hexagon_C2_cmplt:
237 case Intrinsic::hexagon_C2_cmpltu:
238 case Intrinsic::hexagon_C2_bitsclri:
239 case Intrinsic::hexagon_C2_and:
240 case Intrinsic::hexagon_C2_or:
241 case Intrinsic::hexagon_C2_xor:
242 case Intrinsic::hexagon_C2_andn:
243 case Intrinsic::hexagon_C2_not:
244 case Intrinsic::hexagon_C2_orn:
245 case Intrinsic::hexagon_C2_pxfer_map:
246 case Intrinsic::hexagon_C2_any8:
247 case Intrinsic::hexagon_C2_all8:
248 case Intrinsic::hexagon_A2_vcmpbeq:
249 case Intrinsic::hexagon_A2_vcmpbgtu:
250 case Intrinsic::hexagon_A2_vcmpheq:
251 case Intrinsic::hexagon_A2_vcmphgt:
252 case Intrinsic::hexagon_A2_vcmphgtu:
253 case Intrinsic::hexagon_A2_vcmpweq:
254 case Intrinsic::hexagon_A2_vcmpwgt:
255 case Intrinsic::hexagon_A2_vcmpwgtu:
256 case Intrinsic::hexagon_C2_tfrrp:
257 case Intrinsic::hexagon_S2_tstbit_i:
258 case Intrinsic::hexagon_S2_tstbit_r:
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000259 return true;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000260 }
261}
262
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000263SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
264 unsigned Opcode,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000265 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000266 SDValue Chain = LD->getChain();
267 EVT LoadedVT = LD->getMemoryVT();
268 SDValue Base = LD->getBasePtr();
269 SDValue Offset = LD->getOffset();
270 SDNode *OffsetNode = Offset.getNode();
271 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
Bill Wendling4a7a4082013-06-07 06:19:56 +0000272
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000273 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000274 SDValue TargetConst = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000275 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
276 MVT::Other, Base, TargetConst,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000277 Chain);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000278 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
279 SDValue(Result_1, 0));
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000280 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
281 MemOp[0] = LD->getMemOperand();
282 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
283 const SDValue Froms[] = { SDValue(LD, 0),
284 SDValue(LD, 1),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000285 SDValue(LD, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000286 const SDValue Tos[] = { SDValue(Result_2, 0),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000287 SDValue(Result_1, 1),
288 SDValue(Result_1, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000289 ReplaceUses(Froms, Tos, 3);
290 return Result_2;
291 }
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000292
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000293 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
294 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000295 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other,
296 Base, TargetConst0, Chain);
297 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
298 SDValue(Result_1, 0));
299 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
300 Base, TargetConstVal,
301 SDValue(Result_1, 1));
302 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
303 MemOp[0] = LD->getMemOperand();
304 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
305 const SDValue Froms[] = { SDValue(LD, 0),
306 SDValue(LD, 1),
307 SDValue(LD, 2) };
308 const SDValue Tos[] = { SDValue(Result_2, 0),
309 SDValue(Result_3, 0),
310 SDValue(Result_1, 1) };
311 ReplaceUses(Froms, Tos, 3);
312 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000313}
314
315
316SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
317 unsigned Opcode,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000318 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000319 SDValue Chain = LD->getChain();
320 EVT LoadedVT = LD->getMemoryVT();
321 SDValue Base = LD->getBasePtr();
322 SDValue Offset = LD->getOffset();
323 SDNode *OffsetNode = Offset.getNode();
324 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
Bill Wendling4a7a4082013-06-07 06:19:56 +0000325
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000326 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000327 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
328 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000329 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000330 MVT::i32, MVT::Other, Base,
331 TargetConstVal, Chain);
332 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000333 MVT::i64, MVT::Other,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000334 TargetConst0,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000335 SDValue(Result_1,0));
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000336 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
337 MemOp[0] = LD->getMemOperand();
338 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
339 const SDValue Froms[] = { SDValue(LD, 0),
340 SDValue(LD, 1),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000341 SDValue(LD, 2) };
342 const SDValue Tos[] = { SDValue(Result_2, 0),
343 SDValue(Result_1, 1),
344 SDValue(Result_1, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000345 ReplaceUses(Froms, Tos, 3);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000346 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000347 }
348
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000349 // Generate an indirect load.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000350 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
351 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000352 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
353 MVT::Other, Base, TargetConst0,
354 Chain);
355 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl,
356 MVT::i64, MVT::Other,
357 TargetConst0,
358 SDValue(Result_1,0));
359 // Add offset to base.
360 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
361 Base, TargetConstVal,
362 SDValue(Result_1, 1));
363 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
364 MemOp[0] = LD->getMemOperand();
365 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
366 const SDValue Froms[] = { SDValue(LD, 0),
367 SDValue(LD, 1),
368 SDValue(LD, 2) };
369 const SDValue Tos[] = { SDValue(Result_2, 0), // Load value.
370 SDValue(Result_3, 0), // New address.
371 SDValue(Result_1, 1) };
372 ReplaceUses(Froms, Tos, 3);
373 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000374}
375
376
Andrew Trickef9de2a2013-05-25 02:42:55 +0000377SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000378 SDValue Chain = LD->getChain();
379 SDValue Base = LD->getBasePtr();
380 SDValue Offset = LD->getOffset();
381 SDNode *OffsetNode = Offset.getNode();
382 // Get the constant value.
383 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
384 EVT LoadedVT = LD->getMemoryVT();
385 unsigned Opcode = 0;
386
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000387 // Check for zero extended loads. Treat any-extend loads as zero extended
388 // loads.
389 ISD::LoadExtType ExtType = LD->getExtensionType();
390 bool IsZeroExt = (ExtType == ISD::ZEXTLOAD || ExtType == ISD::EXTLOAD);
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000391 bool HasVecOffset = false;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000392
393 // Figure out the opcode.
394 if (LoadedVT == MVT::i64) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000395 if (HII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000396 Opcode = Hexagon::L2_loadrd_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000397 else
Colin LeMahieu947cd702014-12-23 20:44:59 +0000398 Opcode = Hexagon::L2_loadrd_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000399 } else if (LoadedVT == MVT::i32) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000400 if (HII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000401 Opcode = Hexagon::L2_loadri_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000402 else
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000403 Opcode = Hexagon::L2_loadri_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000404 } else if (LoadedVT == MVT::i16) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000405 if (HII->isValidAutoIncImm(LoadedVT, Val))
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000406 Opcode = IsZeroExt ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000407 else
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000408 Opcode = IsZeroExt ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000409 } else if (LoadedVT == MVT::i8) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000410 if (HII->isValidAutoIncImm(LoadedVT, Val))
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000411 Opcode = IsZeroExt ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000412 else
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000413 Opcode = IsZeroExt ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000414 } else if (LoadedVT == MVT::v16i32 || LoadedVT == MVT::v8i64 ||
415 LoadedVT == MVT::v32i16 || LoadedVT == MVT::v64i8) {
416 HasVecOffset = true;
417 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
418 Opcode = Hexagon::V6_vL32b_pi;
419 }
420 else
421 Opcode = Hexagon::V6_vL32b_ai;
422 // 128B
423 } else if (LoadedVT == MVT::v32i32 || LoadedVT == MVT::v16i64 ||
424 LoadedVT == MVT::v64i16 || LoadedVT == MVT::v128i8) {
425 HasVecOffset = true;
426 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
427 Opcode = Hexagon::V6_vL32b_pi_128B;
428 }
429 else
430 Opcode = Hexagon::V6_vL32b_ai_128B;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000431 } else
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000432 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000433
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000434 // For zero extended i64 loads, we need to add combine instructions.
435 if (LD->getValueType(0) == MVT::i64 && IsZeroExt)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000436 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000437 // Handle sign extended i64 loads.
438 if (LD->getValueType(0) == MVT::i64 && ExtType == ISD::SEXTLOAD)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000439 return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000440
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000441 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000442 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000443 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
444 LD->getValueType(0),
445 MVT::i32, MVT::Other, Base,
446 TargetConstVal, Chain);
447 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
448 MemOp[0] = LD->getMemOperand();
449 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000450 if (HasVecOffset) {
451 const SDValue Froms[] = { SDValue(LD, 0),
452 SDValue(LD, 2)
453 };
454 const SDValue Tos[] = { SDValue(Result, 0),
455 SDValue(Result, 2)
456 };
457 ReplaceUses(Froms, Tos, 2);
458 } else {
459 const SDValue Froms[] = { SDValue(LD, 0),
460 SDValue(LD, 1),
461 SDValue(LD, 2)
462 };
463 const SDValue Tos[] = { SDValue(Result, 0),
464 SDValue(Result, 1),
465 SDValue(Result, 2)
466 };
467 ReplaceUses(Froms, Tos, 3);
468 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000469 return Result;
470 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000471 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
472 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000473 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
474 LD->getValueType(0),
475 MVT::Other, Base, TargetConst0,
476 Chain);
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000477 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000478 Base, TargetConstVal,
479 SDValue(Result_1, 1));
480 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
481 MemOp[0] = LD->getMemOperand();
482 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
483 const SDValue Froms[] = { SDValue(LD, 0),
484 SDValue(LD, 1),
485 SDValue(LD, 2)
486 };
487 const SDValue Tos[] = { SDValue(Result_1, 0),
488 SDValue(Result_2, 0),
489 SDValue(Result_1, 1)
490 };
491 ReplaceUses(Froms, Tos, 3);
492 return Result_1;
493 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000494}
495
496
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000497MachineSDNode *HexagonDAGToDAGISel::LoadInstrForLoadIntrinsic(SDNode *IntN) {
498 if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN)
499 return nullptr;
500
501 SDLoc dl(IntN);
502 unsigned IntNo = cast<ConstantSDNode>(IntN->getOperand(1))->getZExtValue();
503
504 static std::map<unsigned,unsigned> LoadPciMap = {
505 { Intrinsic::hexagon_circ_ldb, Hexagon::L2_loadrb_pci },
506 { Intrinsic::hexagon_circ_ldub, Hexagon::L2_loadrub_pci },
507 { Intrinsic::hexagon_circ_ldh, Hexagon::L2_loadrh_pci },
508 { Intrinsic::hexagon_circ_lduh, Hexagon::L2_loadruh_pci },
509 { Intrinsic::hexagon_circ_ldw, Hexagon::L2_loadri_pci },
510 { Intrinsic::hexagon_circ_ldd, Hexagon::L2_loadrd_pci },
511 };
512 auto FLC = LoadPciMap.find(IntNo);
513 if (FLC != LoadPciMap.end()) {
514 SDNode *Mod = CurDAG->getMachineNode(Hexagon::A2_tfrrcr, dl, MVT::i32,
515 IntN->getOperand(4));
516 EVT ValTy = (IntNo == Intrinsic::hexagon_circ_ldd) ? MVT::i64 : MVT::i32;
517 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
518 // Operands: { Base, Increment, Modifier, Chain }
519 auto Inc = cast<ConstantSDNode>(IntN->getOperand(5));
520 SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), dl, MVT::i32);
521 MachineSDNode *Res = CurDAG->getMachineNode(FLC->second, dl, RTys,
522 { IntN->getOperand(2), I, SDValue(Mod,0), IntN->getOperand(0) });
523 return Res;
524 }
525
526 static std::map<unsigned,unsigned> LoadPbrMap = {
527 { Intrinsic::hexagon_brev_ldb, Hexagon::L2_loadrb_pbr },
528 { Intrinsic::hexagon_brev_ldub, Hexagon::L2_loadrub_pbr },
529 { Intrinsic::hexagon_brev_ldh, Hexagon::L2_loadrh_pbr },
530 { Intrinsic::hexagon_brev_lduh, Hexagon::L2_loadruh_pbr },
531 { Intrinsic::hexagon_brev_ldw, Hexagon::L2_loadri_pbr },
532 { Intrinsic::hexagon_brev_ldd, Hexagon::L2_loadrd_pbr },
533 };
534 auto FLB = LoadPbrMap.find(IntNo);
535 if (FLB != LoadPbrMap.end()) {
536 SDNode *Mod = CurDAG->getMachineNode(Hexagon::A2_tfrrcr, dl, MVT::i32,
537 IntN->getOperand(4));
538 EVT ValTy = (IntNo == Intrinsic::hexagon_brev_ldd) ? MVT::i64 : MVT::i32;
539 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
540 // Operands: { Base, Modifier, Chain }
541 MachineSDNode *Res = CurDAG->getMachineNode(FLB->second, dl, RTys,
542 { IntN->getOperand(2), SDValue(Mod,0), IntN->getOperand(0) });
543 return Res;
544 }
545
546 return nullptr;
547}
548
549SDNode *HexagonDAGToDAGISel::StoreInstrForLoadIntrinsic(MachineSDNode *LoadN,
550 SDNode *IntN) {
551 // The "LoadN" is just a machine load instruction. The intrinsic also
552 // involves storing it. Generate an appropriate store to the location
553 // given in the intrinsic's operand(3).
554 uint64_t F = HII->get(LoadN->getMachineOpcode()).TSFlags;
555 unsigned SizeBits = (F >> HexagonII::MemAccessSizePos) &
556 HexagonII::MemAccesSizeMask;
557 unsigned Size = 1U << (SizeBits-1);
558
559 SDLoc dl(IntN);
560 MachinePointerInfo PI;
561 SDValue TS;
562 SDValue Loc = IntN->getOperand(3);
563
564 if (Size >= 4)
565 TS = CurDAG->getStore(SDValue(LoadN,2), dl, SDValue(LoadN, 0), Loc, PI,
566 false, false, Size);
567 else
568 TS = CurDAG->getTruncStore(SDValue(LoadN,2), dl, SDValue(LoadN,0), Loc, PI,
569 MVT::getIntegerVT(Size*8), false, false, Size);
570 SDNode *StoreN = SelectStore(TS.getNode());
571
572 // Load's results are { Loaded value, Updated pointer, Chain }
573 ReplaceUses(SDValue(IntN, 0), SDValue(LoadN, 1));
574 ReplaceUses(SDValue(IntN, 1), SDValue(StoreN, 0));
575 return StoreN;
576}
577
578SDNode *HexagonDAGToDAGISel::SelectLoadOfLoadIntrinsic(LoadSDNode *N) {
579 // The intrinsics for load circ/brev perform two operations:
580 // 1. Load a value V from the specified location, using the addressing
581 // mode corresponding to the intrinsic.
582 // 2. Store V into a specified location. This location is typically a
583 // local, temporary object.
584 // In many cases, the program using these intrinsics will immediately
585 // load V again from the local object. In those cases, when certain
586 // conditions are met, the last load can be removed.
587 // This function identifies and optimizes this pattern. If the pattern
588 // cannot be optimized, it returns nullptr, which will cause the load
589 // to be selected separately from the intrinsic (which will be handled
590 // in SelectIntrinsicWChain).
591
592 SDValue Ch = N->getOperand(0);
593 SDValue Loc = N->getOperand(1);
594
595 // Assume that the load and the intrinsic are connected directly with a
596 // chain:
597 // t1: i32,ch = int.load ..., ..., ..., Loc, ... // <-- C
598 // t2: i32,ch = load t1:1, Loc, ...
599 SDNode *C = Ch.getNode();
600
601 if (C->getOpcode() != ISD::INTRINSIC_W_CHAIN)
602 return nullptr;
603
604 // The second load can only be eliminated if its extension type matches
605 // that of the load instruction corresponding to the intrinsic. The user
606 // can provide an address of an unsigned variable to store the result of
607 // a sign-extending intrinsic into (or the other way around).
608 ISD::LoadExtType IntExt;
609 switch (cast<ConstantSDNode>(C->getOperand(1))->getZExtValue()) {
610 case Intrinsic::hexagon_brev_ldub:
611 case Intrinsic::hexagon_brev_lduh:
612 case Intrinsic::hexagon_circ_ldub:
613 case Intrinsic::hexagon_circ_lduh:
614 IntExt = ISD::ZEXTLOAD;
615 break;
616 case Intrinsic::hexagon_brev_ldw:
617 case Intrinsic::hexagon_brev_ldd:
618 case Intrinsic::hexagon_circ_ldw:
619 case Intrinsic::hexagon_circ_ldd:
620 IntExt = ISD::NON_EXTLOAD;
621 break;
622 default:
623 IntExt = ISD::SEXTLOAD;
624 break;
625 }
626 if (N->getExtensionType() != IntExt)
627 return nullptr;
628
629 // Make sure the target location for the loaded value in the load intrinsic
630 // is the location from which LD (or N) is loading.
631 if (C->getNumOperands() < 4 || Loc.getNode() != C->getOperand(3).getNode())
632 return nullptr;
633
634 if (MachineSDNode *L = LoadInstrForLoadIntrinsic(C)) {
635 SDNode *S = StoreInstrForLoadIntrinsic(L, C);
636 SDValue F[] = { SDValue(N,0), SDValue(N,1), SDValue(C,0), SDValue(C,1) };
637 SDValue T[] = { SDValue(L,0), SDValue(S,0), SDValue(L,1), SDValue(S,0) };
638 ReplaceUses(F, T, array_lengthof(T));
639 // This transformation will leave the intrinsic dead. If it remains in
640 // the DAG, the selection code will see it again, but without the load,
641 // and it will generate a store that is normally required for it.
642 CurDAG->RemoveDeadNodes();
643 return L;
644 }
645
646 return nullptr;
647}
648
649
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000650SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000651 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000652 LoadSDNode *LD = cast<LoadSDNode>(N);
653 ISD::MemIndexedMode AM = LD->getAddressingMode();
654
655 // Handle indexed loads.
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000656 if (AM != ISD::UNINDEXED)
657 return SelectIndexedLoad(LD, dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000658
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000659 // Handle patterns using circ/brev load intrinsics.
660 if (SDNode *LI = SelectLoadOfLoadIntrinsic(LD))
661 return LI;
662
663 return SelectCode(LD);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000664}
665
666
Andrew Trickef9de2a2013-05-25 02:42:55 +0000667SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000668 SDValue Chain = ST->getChain();
669 SDValue Base = ST->getBasePtr();
670 SDValue Offset = ST->getOffset();
671 SDValue Value = ST->getValue();
672 SDNode *OffsetNode = Offset.getNode();
673 // Get the constant value.
674 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
675 EVT StoredVT = ST->getMemoryVT();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000676 EVT ValueVT = Value.getValueType();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000677
678 // Offset value must be within representable range
679 // and must have correct alignment properties.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000680 if (HII->isValidAutoIncImm(StoredVT, Val)) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000681 unsigned Opcode = 0;
682
683 // Figure out the post inc version of opcode.
Colin LeMahieu9a3cd3f2014-12-29 20:00:43 +0000684 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi;
685 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi;
686 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi;
Colin LeMahieu3d34afb2014-12-29 19:42:14 +0000687 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000688 else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 ||
689 StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8) {
690 Opcode = Hexagon::V6_vS32b_pi;
691 }
692 // 128B
693 else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 ||
694 StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8) {
695 Opcode = Hexagon::V6_vS32b_pi_128B;
696 } else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000697
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000698 if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) {
699 assert(StoredVT.getSizeInBits() < 64 && "Not a truncating store");
700 Value = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg,
701 dl, MVT::i32, Value);
702 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000703 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, dl, MVT::i32), Value,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000704 Chain};
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000705 // Build post increment store.
706 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +0000707 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000708 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
709 MemOp[0] = ST->getMemOperand();
710 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
711
712 ReplaceUses(ST, Result);
713 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
714 return Result;
715 }
716
717 // Note: Order of operands matches the def of instruction:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000718 // def S2_storerd_io
719 // : STInst<(outs), (ins IntRegs:$base, imm:$offset, DoubleRegs:$src1), ...
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000720 // and it differs for POST_ST* for instance.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000721 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, dl, MVT::i32), Value,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000722 Chain};
723 unsigned Opcode = 0;
724
725 // Figure out the opcode.
Colin LeMahieubda31b42014-12-29 20:44:51 +0000726 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
727 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
728 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
729 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000730 else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 ||
731 StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8)
732 Opcode = Hexagon::V6_vS32b_ai;
733 // 128B
734 else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 ||
735 StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8)
736 Opcode = Hexagon::V6_vS32b_ai_128B;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000737 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000738
739 // Build regular store.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000740 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Michael Liaob53d8962013-04-19 22:22:57 +0000741 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000742 // Build splitted incriment instruction.
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000743 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000744 Base,
745 TargetConstVal,
746 SDValue(Result_1, 0));
747 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
748 MemOp[0] = ST->getMemOperand();
749 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
750
751 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
752 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
753 return Result_2;
754}
755
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000756SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000757 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000758 StoreSDNode *ST = cast<StoreSDNode>(N);
759 ISD::MemIndexedMode AM = ST->getAddressingMode();
760
761 // Handle indexed stores.
762 if (AM != ISD::UNINDEXED) {
763 return SelectIndexedStore(ST, dl);
764 }
Sirish Pandec92c3162012-05-03 16:18:50 +0000765
Colin LeMahieu2efa2d02015-03-09 21:48:13 +0000766 return SelectCode(ST);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000767}
768
769SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000770 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000771
772 //
773 // %conv.i = sext i32 %tmp1 to i64
774 // %conv2.i = sext i32 %add to i64
775 // %mul.i = mul nsw i64 %conv2.i, %conv.i
776 //
777 // --- match with the following ---
778 //
779 // %mul.i = mpy (%tmp1, %add)
780 //
781
782 if (N->getValueType(0) == MVT::i64) {
783 // Shifting a i64 signed multiply.
784 SDValue MulOp0 = N->getOperand(0);
785 SDValue MulOp1 = N->getOperand(1);
786
787 SDValue OP0;
788 SDValue OP1;
789
790 // Handle sign_extend and sextload.
791 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
792 SDValue Sext0 = MulOp0.getOperand(0);
793 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000794 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000795 }
796
797 OP0 = Sext0;
798 } else if (MulOp0.getOpcode() == ISD::LOAD) {
799 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
800 if (LD->getMemoryVT() != MVT::i32 ||
801 LD->getExtensionType() != ISD::SEXTLOAD ||
802 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000803 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000804 }
805
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000806 SDValue Chain = LD->getChain();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000807 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000808 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000809 MVT::Other,
810 LD->getBasePtr(), TargetConst0,
811 Chain), 0);
812 } else {
813 return SelectCode(N);
814 }
815
816 // Same goes for the second operand.
817 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
818 SDValue Sext1 = MulOp1.getOperand(0);
819 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
820 return SelectCode(N);
821 }
822
823 OP1 = Sext1;
824 } else if (MulOp1.getOpcode() == ISD::LOAD) {
825 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
826 if (LD->getMemoryVT() != MVT::i32 ||
827 LD->getExtensionType() != ISD::SEXTLOAD ||
828 LD->getAddressingMode() != ISD::UNINDEXED) {
829 return SelectCode(N);
830 }
831
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000832 SDValue Chain = LD->getChain();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000833 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000834 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000835 MVT::Other,
836 LD->getBasePtr(), TargetConst0,
837 Chain), 0);
838 } else {
839 return SelectCode(N);
840 }
841
842 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +0000843 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000844 OP0, OP1);
845 ReplaceUses(N, Result);
846 return Result;
847 }
848
849 return SelectCode(N);
850}
851
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000852SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000853 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000854 if (N->getValueType(0) == MVT::i32) {
855 SDValue Shl_0 = N->getOperand(0);
856 SDValue Shl_1 = N->getOperand(1);
857 // RHS is const.
858 if (Shl_1.getOpcode() == ISD::Constant) {
859 if (Shl_0.getOpcode() == ISD::MUL) {
860 SDValue Mul_0 = Shl_0.getOperand(0); // Val
861 SDValue Mul_1 = Shl_0.getOperand(1); // Const
862 // RHS of mul is const.
863 if (Mul_1.getOpcode() == ISD::Constant) {
864 int32_t ShlConst =
865 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
866 int32_t MulConst =
867 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
868 int32_t ValConst = MulConst << ShlConst;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000869 SDValue Val = CurDAG->getTargetConstant(ValConst, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000870 MVT::i32);
871 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
872 if (isInt<9>(CN->getSExtValue())) {
873 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000874 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000875 MVT::i32, Mul_0, Val);
876 ReplaceUses(N, Result);
877 return Result;
878 }
879
880 }
881 } else if (Shl_0.getOpcode() == ISD::SUB) {
882 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
883 SDValue Sub_1 = Shl_0.getOperand(1); // Val
884 if (Sub_0.getOpcode() == ISD::Constant) {
885 int32_t SubConst =
886 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
887 if (SubConst == 0) {
888 if (Sub_1.getOpcode() == ISD::SHL) {
889 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
890 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
891 if (Shl2_1.getOpcode() == ISD::Constant) {
892 int32_t ShlConst =
893 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
894 int32_t Shl2Const =
895 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
896 int32_t ValConst = 1 << (ShlConst+Shl2Const);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000897 SDValue Val = CurDAG->getTargetConstant(-ValConst, dl,
898 MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000899 if (ConstantSDNode *CN =
900 dyn_cast<ConstantSDNode>(Val.getNode()))
901 if (isInt<9>(CN->getSExtValue())) {
902 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000903 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000904 Shl2_0, Val);
905 ReplaceUses(N, Result);
906 return Result;
907 }
908 }
909 }
910 }
911 }
912 }
913 }
914 }
915 return SelectCode(N);
916}
917
918
919//
920// If there is an zero_extend followed an intrinsic in DAG (this means - the
921// result of the intrinsic is predicate); convert the zero_extend to
922// transfer instruction.
923//
924// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
925// converted into a MUX as predicate registers defined as 1 bit in the
926// compiler. Architecture defines them as 8-bit registers.
927// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
928//
929SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000930 SDLoc dl(N);
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000931
932 SDValue Op0 = N->getOperand(0);
933 EVT OpVT = Op0.getValueType();
934 unsigned OpBW = OpVT.getSizeInBits();
935
936 // Special handling for zero-extending a vector of booleans.
937 if (OpVT.isVector() && OpVT.getVectorElementType() == MVT::i1 && OpBW <= 64) {
938 SDNode *Mask = CurDAG->getMachineNode(Hexagon::C2_mask, dl, MVT::i64, Op0);
939 unsigned NE = OpVT.getVectorNumElements();
940 EVT ExVT = N->getValueType(0);
941 unsigned ES = ExVT.getVectorElementType().getSizeInBits();
942 uint64_t MV = 0, Bit = 1;
943 for (unsigned i = 0; i < NE; ++i) {
944 MV |= Bit;
945 Bit <<= ES;
946 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000947 SDValue Ones = CurDAG->getTargetConstant(MV, dl, MVT::i64);
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000948 SDNode *OnesReg = CurDAG->getMachineNode(Hexagon::CONST64_Int_Real, dl,
949 MVT::i64, Ones);
950 if (ExVT.getSizeInBits() == 32) {
951 SDNode *And = CurDAG->getMachineNode(Hexagon::A2_andp, dl, MVT::i64,
952 SDValue(Mask,0), SDValue(OnesReg,0));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000953 SDValue SubR = CurDAG->getTargetConstant(Hexagon::subreg_loreg, dl,
954 MVT::i32);
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000955 return CurDAG->getMachineNode(Hexagon::EXTRACT_SUBREG, dl, ExVT,
956 SDValue(And,0), SubR);
957 }
958 return CurDAG->getMachineNode(Hexagon::A2_andp, dl, ExVT,
959 SDValue(Mask,0), SDValue(OnesReg,0));
960 }
961
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000962 SDNode *IsIntrinsic = N->getOperand(0).getNode();
963 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
964 unsigned ID =
965 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
966 if (doesIntrinsicReturnPredicate(ID)) {
967 // Now we need to differentiate target data types.
968 if (N->getValueType(0) == MVT::i64) {
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +0000969 // Convert the zero_extend to Rs = Pd followed by A2_combinew(0,Rs).
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000970 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu30dcb232014-12-09 18:16:49 +0000971 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000972 MVT::i32,
973 SDValue(IsIntrinsic, 0));
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000974 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000975 MVT::i32,
976 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000977 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000978 MVT::i64, MVT::Other,
979 SDValue(Result_2, 0),
980 SDValue(Result_1, 0));
981 ReplaceUses(N, Result_3);
982 return Result_3;
983 }
984 if (N->getValueType(0) == MVT::i32) {
985 // Convert the zero_extend to Rs = Pd
Colin LeMahieu30dcb232014-12-09 18:16:49 +0000986 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000987 MVT::i32,
988 SDValue(IsIntrinsic, 0));
989 ReplaceUses(N, RsPd);
990 return RsPd;
991 }
Craig Toppere55c5562012-02-07 02:50:20 +0000992 llvm_unreachable("Unexpected value type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000993 }
994 }
995 return SelectCode(N);
996}
997
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000998
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000999//
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +00001000// Handling intrinsics for circular load and bitreverse load.
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +00001001//
1002SDNode *HexagonDAGToDAGISel::SelectIntrinsicWChain(SDNode *N) {
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +00001003 if (MachineSDNode *L = LoadInstrForLoadIntrinsic(N))
1004 return StoreInstrForLoadIntrinsic(L, N);
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +00001005 return SelectCode(N);
1006}
1007
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001008SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001009 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1010 unsigned Bits;
1011 switch (IID) {
1012 case Intrinsic::hexagon_S2_vsplatrb:
1013 Bits = 8;
1014 break;
1015 case Intrinsic::hexagon_S2_vsplatrh:
1016 Bits = 16;
1017 break;
1018 default:
1019 return SelectCode(N);
1020 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001021
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001022 SDValue const &V = N->getOperand(1);
1023 SDValue U;
1024 if (isValueExtension(V, Bits, U)) {
1025 SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
1026 N->getOperand(0), U);
1027 return SelectCode(R.getNode());
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001028 }
1029 return SelectCode(N);
1030}
1031
Sirish Pande69295b82012-05-10 20:20:25 +00001032//
1033// Map floating point constant values.
1034//
1035SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001036 SDLoc dl(N);
Sirish Pande69295b82012-05-10 20:20:25 +00001037 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1038 APFloat APF = CN->getValueAPF();
1039 if (N->getValueType(0) == MVT::f32) {
1040 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001041 CurDAG->getTargetConstantFP(APF.convertToFloat(), dl, MVT::f32));
Sirish Pande69295b82012-05-10 20:20:25 +00001042 }
1043 else if (N->getValueType(0) == MVT::f64) {
1044 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001045 CurDAG->getTargetConstantFP(APF.convertToDouble(), dl, MVT::f64));
Sirish Pande69295b82012-05-10 20:20:25 +00001046 }
1047
1048 return SelectCode(N);
1049}
1050
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001051//
1052// Map predicate true (encoded as -1 in LLVM) to a XOR.
1053//
1054SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001055 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001056 if (N->getValueType(0) == MVT::i1) {
Krzysztof Parzyszek36ccfa52015-03-18 19:07:53 +00001057 SDNode* Result = 0;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001058 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
Krzysztof Parzyszek7a9cd802015-03-18 18:50:06 +00001059 if (Val == -1) {
Krzysztof Parzyszek36ccfa52015-03-18 19:07:53 +00001060 Result = CurDAG->getMachineNode(Hexagon::TFR_PdTrue, dl, MVT::i1);
1061 } else if (Val == 0) {
1062 Result = CurDAG->getMachineNode(Hexagon::TFR_PdFalse, dl, MVT::i1);
1063 }
1064 if (Result) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001065 ReplaceUses(N, Result);
1066 return Result;
1067 }
1068 }
1069
1070 return SelectCode(N);
1071}
1072
1073
1074//
1075// Map add followed by a asr -> asr +=.
1076//
1077SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001078 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001079 if (N->getValueType(0) != MVT::i32) {
1080 return SelectCode(N);
1081 }
1082 // Identify nodes of the form: add(asr(...)).
1083 SDNode* Src1 = N->getOperand(0).getNode();
1084 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1085 || Src1->getValueType(0) != MVT::i32) {
1086 return SelectCode(N);
1087 }
1088
1089 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1090 // Rd and Rd' are assigned to the same register
Colin LeMahieu0f850bd2014-12-19 20:29:29 +00001091 SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001092 N->getOperand(1),
1093 Src1->getOperand(0),
1094 Src1->getOperand(1));
1095 ReplaceUses(N, Result);
1096
1097 return Result;
1098}
1099
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001100//
1101// Map the following, where possible.
1102// AND/FABS -> clrbit
1103// OR -> setbit
1104// XOR/FNEG ->toggle_bit.
1105//
1106SDNode *HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
1107 SDLoc dl(N);
1108 EVT ValueVT = N->getValueType(0);
1109
1110 // We handle only 32 and 64-bit bit ops.
1111 if (!(ValueVT == MVT::i32 || ValueVT == MVT::i64 ||
1112 ValueVT == MVT::f32 || ValueVT == MVT::f64))
1113 return SelectCode(N);
1114
1115 // We handly only fabs and fneg for V5.
1116 unsigned Opc = N->getOpcode();
Eric Christopher23a7d1e2015-03-21 03:12:59 +00001117 if ((Opc == ISD::FABS || Opc == ISD::FNEG) && !HST->hasV5TOps())
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001118 return SelectCode(N);
1119
1120 int64_t Val = 0;
1121 if (Opc != ISD::FABS && Opc != ISD::FNEG) {
1122 if (N->getOperand(1).getOpcode() == ISD::Constant)
1123 Val = cast<ConstantSDNode>((N)->getOperand(1))->getSExtValue();
1124 else
1125 return SelectCode(N);
1126 }
1127
1128 if (Opc == ISD::AND) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001129 // Check if this is a bit-clearing AND, if not select code the usual way.
1130 if ((ValueVT == MVT::i32 && isPowerOf2_32(~Val)) ||
1131 (ValueVT == MVT::i64 && isPowerOf2_64(~Val)))
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001132 Val = ~Val;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001133 else
1134 return SelectCode(N);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001135 }
1136
1137 // If OR or AND is being fed by shl, srl and, sra don't do this change,
1138 // because Hexagon provide |= &= on shl, srl, and sra.
1139 // Traverse the DAG to see if there is shl, srl and sra.
1140 if (Opc == ISD::OR || Opc == ISD::AND) {
1141 switch (N->getOperand(0)->getOpcode()) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001142 default:
1143 break;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001144 case ISD::SRA:
1145 case ISD::SRL:
1146 case ISD::SHL:
1147 return SelectCode(N);
1148 }
1149 }
1150
1151 // Make sure it's power of 2.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001152 unsigned BitPos = 0;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001153 if (Opc != ISD::FABS && Opc != ISD::FNEG) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001154 if ((ValueVT == MVT::i32 && !isPowerOf2_32(Val)) ||
1155 (ValueVT == MVT::i64 && !isPowerOf2_64(Val)))
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001156 return SelectCode(N);
1157
1158 // Get the bit position.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001159 BitPos = countTrailingZeros(uint64_t(Val));
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001160 } else {
1161 // For fabs and fneg, it's always the 31st bit.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001162 BitPos = 31;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001163 }
1164
1165 unsigned BitOpc = 0;
1166 // Set the right opcode for bitwise operations.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001167 switch (Opc) {
1168 default:
1169 llvm_unreachable("Only bit-wise/abs/neg operations are allowed.");
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001170 case ISD::AND:
1171 case ISD::FABS:
1172 BitOpc = Hexagon::S2_clrbit_i;
1173 break;
1174 case ISD::OR:
1175 BitOpc = Hexagon::S2_setbit_i;
1176 break;
1177 case ISD::XOR:
1178 case ISD::FNEG:
1179 BitOpc = Hexagon::S2_togglebit_i;
1180 break;
1181 }
1182
1183 SDNode *Result;
1184 // Get the right SDVal for the opcode.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001185 SDValue SDVal = CurDAG->getTargetConstant(BitPos, dl, MVT::i32);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001186
1187 if (ValueVT == MVT::i32 || ValueVT == MVT::f32) {
1188 Result = CurDAG->getMachineNode(BitOpc, dl, ValueVT,
1189 N->getOperand(0), SDVal);
1190 } else {
1191 // 64-bit gymnastic to use REG_SEQUENCE. But it's worth it.
1192 EVT SubValueVT;
1193 if (ValueVT == MVT::i64)
1194 SubValueVT = MVT::i32;
1195 else
1196 SubValueVT = MVT::f32;
1197
1198 SDNode *Reg = N->getOperand(0).getNode();
1199 SDValue RegClass = CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001200 dl, MVT::i64);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001201
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001202 SDValue SubregHiIdx = CurDAG->getTargetConstant(Hexagon::subreg_hireg, dl,
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001203 MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001204 SDValue SubregLoIdx = CurDAG->getTargetConstant(Hexagon::subreg_loreg, dl,
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001205 MVT::i32);
1206
1207 SDValue SubregHI = CurDAG->getTargetExtractSubreg(Hexagon::subreg_hireg, dl,
1208 MVT::i32, SDValue(Reg, 0));
1209
1210 SDValue SubregLO = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg, dl,
1211 MVT::i32, SDValue(Reg, 0));
1212
1213 // Clear/set/toggle hi or lo registers depending on the bit position.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001214 if (SubValueVT != MVT::f32 && BitPos < 32) {
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001215 SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
1216 SubregLO, SDVal);
1217 const SDValue Ops[] = { RegClass, SubregHI, SubregHiIdx,
1218 SDValue(Result0, 0), SubregLoIdx };
1219 Result = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
1220 dl, ValueVT, Ops);
1221 } else {
1222 if (Opc != ISD::FABS && Opc != ISD::FNEG)
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001223 SDVal = CurDAG->getTargetConstant(BitPos-32, dl, MVT::i32);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001224 SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
1225 SubregHI, SDVal);
1226 const SDValue Ops[] = { RegClass, SDValue(Result0, 0), SubregHiIdx,
1227 SubregLO, SubregLoIdx };
1228 Result = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
1229 dl, ValueVT, Ops);
1230 }
1231 }
1232
1233 ReplaceUses(N, Result);
1234 return Result;
1235}
1236
1237
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001238SDNode *HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) {
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001239 MachineFrameInfo *MFI = MF->getFrameInfo();
1240 const HexagonFrameLowering *HFI = HST->getFrameLowering();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001241 int FX = cast<FrameIndexSDNode>(N)->getIndex();
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001242 unsigned StkA = HFI->getStackAlignment();
1243 unsigned MaxA = MFI->getMaxAlignment();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001244 SDValue FI = CurDAG->getTargetFrameIndex(FX, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001245 SDLoc DL(N);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001246 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001247 SDNode *R = 0;
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001248
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001249 // Use TFR_FI when:
1250 // - the object is fixed, or
1251 // - there are no objects with higher-than-default alignment, or
1252 // - there are no dynamically allocated objects.
1253 // Otherwise, use TFR_FIA.
1254 if (FX < 0 || MaxA <= StkA || !MFI->hasVarSizedObjects()) {
1255 R = CurDAG->getMachineNode(Hexagon::TFR_FI, DL, MVT::i32, FI, Zero);
1256 } else {
1257 auto &HMFI = *MF->getInfo<HexagonMachineFunctionInfo>();
1258 unsigned AR = HMFI.getStackAlignBaseVReg();
1259 SDValue CH = CurDAG->getEntryNode();
1260 SDValue Ops[] = { CurDAG->getCopyFromReg(CH, DL, AR, MVT::i32), FI, Zero };
1261 R = CurDAG->getMachineNode(Hexagon::TFR_FIA, DL, MVT::i32, Ops);
1262 }
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001263
1264 if (N->getHasDebugValue())
1265 CurDAG->TransferDbgValues(SDValue(N, 0), SDValue(R, 0));
1266 return R;
1267}
1268
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001269
1270SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
Tim Northover31d093c2013-09-22 08:21:56 +00001271 if (N->isMachineOpcode()) {
1272 N->setNodeId(-1);
Craig Topper062a2ba2014-04-25 05:30:21 +00001273 return nullptr; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00001274 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001275
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001276 switch (N->getOpcode()) {
1277 case ISD::Constant:
1278 return SelectConstant(N);
1279
Sirish Pande69295b82012-05-10 20:20:25 +00001280 case ISD::ConstantFP:
1281 return SelectConstantFP(N);
1282
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001283 case ISD::FrameIndex:
1284 return SelectFrameIndex(N);
1285
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001286 case ISD::ADD:
1287 return SelectAdd(N);
1288
1289 case ISD::SHL:
1290 return SelectSHL(N);
1291
1292 case ISD::LOAD:
1293 return SelectLoad(N);
1294
1295 case ISD::STORE:
1296 return SelectStore(N);
1297
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001298 case ISD::MUL:
1299 return SelectMul(N);
1300
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001301 case ISD::AND:
1302 case ISD::OR:
1303 case ISD::XOR:
1304 case ISD::FABS:
1305 case ISD::FNEG:
1306 return SelectBitOp(N);
1307
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001308 case ISD::ZERO_EXTEND:
1309 return SelectZeroExtend(N);
1310
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +00001311 case ISD::INTRINSIC_W_CHAIN:
1312 return SelectIntrinsicWChain(N);
1313
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001314 case ISD::INTRINSIC_WO_CHAIN:
1315 return SelectIntrinsicWOChain(N);
1316 }
1317
1318 return SelectCode(N);
1319}
1320
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001321bool HexagonDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00001322SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001323 std::vector<SDValue> &OutOps) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001324 SDValue Inp = Op, Res;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001325
Daniel Sanders60f1db02015-03-13 12:45:09 +00001326 switch (ConstraintID) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001327 default:
1328 return true;
Daniel Sanders49f643c2015-03-17 14:37:39 +00001329 case InlineAsm::Constraint_i:
1330 case InlineAsm::Constraint_o: // Offsetable.
1331 case InlineAsm::Constraint_v: // Not offsetable.
1332 case InlineAsm::Constraint_m: // Memory.
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001333 if (SelectAddrFI(Inp, Res))
1334 OutOps.push_back(Res);
1335 else
1336 OutOps.push_back(Inp);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001337 break;
1338 }
1339
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001340 OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));
Jyotsna Vermad9225242013-02-13 21:38:46 +00001341 return false;
1342}
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001343
Colin LeMahieu79ec0652015-06-12 19:57:32 +00001344
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001345void HexagonDAGToDAGISel::PreprocessISelDAG() {
1346 SelectionDAG &DAG = *CurDAG;
1347 std::vector<SDNode*> Nodes;
Pete Cooper7e64ef02015-07-14 23:43:29 +00001348 for (SDNode &Node : DAG.allnodes())
1349 Nodes.push_back(&Node);
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001350
1351 // Simplify: (or (select c x 0) z) -> (select c (or x z) z)
1352 // (or (select c 0 y) z) -> (select c z (or y z))
1353 // This may not be the right thing for all targets, so do it here.
1354 for (auto I: Nodes) {
1355 if (I->getOpcode() != ISD::OR)
1356 continue;
1357
1358 auto IsZero = [] (const SDValue &V) -> bool {
1359 if (ConstantSDNode *SC = dyn_cast<ConstantSDNode>(V.getNode()))
1360 return SC->isNullValue();
1361 return false;
1362 };
1363 auto IsSelect0 = [IsZero] (const SDValue &Op) -> bool {
1364 if (Op.getOpcode() != ISD::SELECT)
1365 return false;
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +00001366 return IsZero(Op.getOperand(1)) || IsZero(Op.getOperand(2));
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001367 };
1368
1369 SDValue N0 = I->getOperand(0), N1 = I->getOperand(1);
1370 EVT VT = I->getValueType(0);
1371 bool SelN0 = IsSelect0(N0);
1372 SDValue SOp = SelN0 ? N0 : N1;
1373 SDValue VOp = SelN0 ? N1 : N0;
1374
1375 if (SOp.getOpcode() == ISD::SELECT && SOp.getNode()->hasOneUse()) {
1376 SDValue SC = SOp.getOperand(0);
1377 SDValue SX = SOp.getOperand(1);
1378 SDValue SY = SOp.getOperand(2);
1379 SDLoc DLS = SOp;
1380 if (IsZero(SY)) {
1381 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SX, VOp);
1382 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, NewOr, VOp);
1383 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1384 } else if (IsZero(SX)) {
1385 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SY, VOp);
1386 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, VOp, NewOr);
1387 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1388 }
1389 }
1390 }
1391}
1392
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001393void HexagonDAGToDAGISel::EmitFunctionEntryCode() {
1394 auto &HST = static_cast<const HexagonSubtarget&>(MF->getSubtarget());
1395 auto &HFI = *HST.getFrameLowering();
1396 if (!HFI.needsAligna(*MF))
1397 return;
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001398
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001399 MachineFrameInfo *MFI = MF->getFrameInfo();
Duncan P. N. Exon Smitha72c6e22015-10-20 00:46:39 +00001400 MachineBasicBlock *EntryBB = &MF->front();
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001401 unsigned AR = FuncInfo->CreateReg(MVT::i32);
1402 unsigned MaxA = MFI->getMaxAlignment();
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001403 BuildMI(EntryBB, DebugLoc(), HII->get(Hexagon::ALIGNA), AR)
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001404 .addImm(MaxA);
1405 MF->getInfo<HexagonMachineFunctionInfo>()->setStackAlignBaseVReg(AR);
1406}
1407
1408// Match a frame index that can be used in an addressing mode.
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001409bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) {
1410 if (N.getOpcode() != ISD::FrameIndex)
1411 return false;
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001412 auto &HFI = *HST->getFrameLowering();
1413 MachineFrameInfo *MFI = MF->getFrameInfo();
1414 int FX = cast<FrameIndexSDNode>(N)->getIndex();
1415 if (!MFI->isFixedObjectIndex(FX) && HFI.needsAligna(*MF))
1416 return false;
1417 R = CurDAG->getTargetFrameIndex(FX, MVT::i32);
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001418 return true;
1419}
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001420
Colin LeMahieu987b0942015-02-04 20:38:01 +00001421inline bool HexagonDAGToDAGISel::SelectAddrGA(SDValue &N, SDValue &R) {
1422 return SelectGlobalAddress(N, R, false);
1423}
1424
Colin LeMahieu51491352015-02-04 22:36:28 +00001425inline bool HexagonDAGToDAGISel::SelectAddrGP(SDValue &N, SDValue &R) {
1426 return SelectGlobalAddress(N, R, true);
1427}
1428
Colin LeMahieu987b0942015-02-04 20:38:01 +00001429bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
1430 bool UseGP) {
1431 switch (N.getOpcode()) {
1432 case ISD::ADD: {
1433 SDValue N0 = N.getOperand(0);
1434 SDValue N1 = N.getOperand(1);
1435 unsigned GAOpc = N0.getOpcode();
1436 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1437 return false;
1438 if (!UseGP && GAOpc != HexagonISD::CONST32)
1439 return false;
1440 if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) {
1441 SDValue Addr = N0.getOperand(0);
1442 if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Addr)) {
1443 if (GA->getOpcode() == ISD::TargetGlobalAddress) {
1444 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1445 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),
1446 N.getValueType(), NewOff);
1447 return true;
1448 }
1449 }
1450 }
1451 break;
1452 }
1453 case HexagonISD::CONST32:
1454 // The operand(0) of CONST32 is TargetGlobalAddress, which is what we
1455 // want in the instruction.
1456 if (!UseGP)
1457 R = N.getOperand(0);
1458 return !UseGP;
1459 case HexagonISD::CONST32_GP:
1460 if (UseGP)
1461 R = N.getOperand(0);
1462 return UseGP;
1463 default:
1464 return false;
1465 }
1466
1467 return false;
1468}
1469
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001470bool HexagonDAGToDAGISel::isValueExtension(const SDValue &Val,
1471 unsigned FromBits, SDValue &Src) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001472 unsigned Opc = Val.getOpcode();
1473 switch (Opc) {
1474 case ISD::SIGN_EXTEND:
1475 case ISD::ZERO_EXTEND:
1476 case ISD::ANY_EXTEND: {
1477 SDValue const &Op0 = Val.getOperand(0);
1478 EVT T = Op0.getValueType();
1479 if (T.isInteger() && T.getSizeInBits() == FromBits) {
1480 Src = Op0;
1481 return true;
1482 }
1483 break;
1484 }
1485 case ISD::SIGN_EXTEND_INREG:
1486 case ISD::AssertSext:
1487 case ISD::AssertZext:
1488 if (Val.getOperand(0).getValueType().isInteger()) {
1489 VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
1490 if (T->getVT().getSizeInBits() == FromBits) {
1491 Src = Val.getOperand(0);
1492 return true;
1493 }
1494 }
1495 break;
1496 case ISD::AND: {
1497 // Check if this is an AND with "FromBits" of lower bits set to 1.
1498 uint64_t FromMask = (1 << FromBits) - 1;
1499 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1500 if (C->getZExtValue() == FromMask) {
1501 Src = Val.getOperand(1);
1502 return true;
1503 }
1504 }
1505 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1506 if (C->getZExtValue() == FromMask) {
1507 Src = Val.getOperand(0);
1508 return true;
1509 }
1510 }
1511 break;
1512 }
1513 case ISD::OR:
1514 case ISD::XOR: {
1515 // OR/XOR with the lower "FromBits" bits set to 0.
1516 uint64_t FromMask = (1 << FromBits) - 1;
1517 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1518 if ((C->getZExtValue() & FromMask) == 0) {
1519 Src = Val.getOperand(1);
1520 return true;
1521 }
1522 }
1523 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1524 if ((C->getZExtValue() & FromMask) == 0) {
1525 Src = Val.getOperand(0);
1526 return true;
1527 }
1528 }
1529 }
1530 default:
1531 break;
1532 }
1533 return false;
1534}