blob: 6e36c2fd81b8d4e22bfb68dd3d68f7c05c074a88 [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);
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000192 bool isAlignedMemNode(const MemSDNode *N) const;
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000193}; // end HexagonDAGToDAGISel
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000194} // end anonymous namespace
195
196
197/// createHexagonISelDag - This pass converts a legalized DAG into a
198/// Hexagon-specific DAG, ready for instruction scheduling.
199///
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000200namespace llvm {
201FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM,
202 CodeGenOpt::Level OptLevel) {
Jyotsna Vermad9225242013-02-13 21:38:46 +0000203 return new HexagonDAGToDAGISel(TM, OptLevel);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000204}
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000205}
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000206
Jyotsna Vermad9225242013-02-13 21:38:46 +0000207static void initializePassOnce(PassRegistry &Registry) {
208 const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection";
209 PassInfo *PI = new PassInfo(Name, "hexagon-isel",
Craig Topper062a2ba2014-04-25 05:30:21 +0000210 &SelectionDAGISel::ID, nullptr, false, false);
Jyotsna Vermad9225242013-02-13 21:38:46 +0000211 Registry.registerPass(*PI, true);
212}
213
214void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
215 CALL_ONCE_INITIALIZATION(initializePassOnce)
216}
217
218
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000219// Intrinsics that return a a predicate.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000220static bool doesIntrinsicReturnPredicate(unsigned ID) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000221 switch (ID) {
222 default:
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000223 return false;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000224 case Intrinsic::hexagon_C2_cmpeq:
225 case Intrinsic::hexagon_C2_cmpgt:
226 case Intrinsic::hexagon_C2_cmpgtu:
227 case Intrinsic::hexagon_C2_cmpgtup:
228 case Intrinsic::hexagon_C2_cmpgtp:
229 case Intrinsic::hexagon_C2_cmpeqp:
230 case Intrinsic::hexagon_C2_bitsset:
231 case Intrinsic::hexagon_C2_bitsclr:
232 case Intrinsic::hexagon_C2_cmpeqi:
233 case Intrinsic::hexagon_C2_cmpgti:
234 case Intrinsic::hexagon_C2_cmpgtui:
235 case Intrinsic::hexagon_C2_cmpgei:
236 case Intrinsic::hexagon_C2_cmpgeui:
237 case Intrinsic::hexagon_C2_cmplt:
238 case Intrinsic::hexagon_C2_cmpltu:
239 case Intrinsic::hexagon_C2_bitsclri:
240 case Intrinsic::hexagon_C2_and:
241 case Intrinsic::hexagon_C2_or:
242 case Intrinsic::hexagon_C2_xor:
243 case Intrinsic::hexagon_C2_andn:
244 case Intrinsic::hexagon_C2_not:
245 case Intrinsic::hexagon_C2_orn:
246 case Intrinsic::hexagon_C2_pxfer_map:
247 case Intrinsic::hexagon_C2_any8:
248 case Intrinsic::hexagon_C2_all8:
249 case Intrinsic::hexagon_A2_vcmpbeq:
250 case Intrinsic::hexagon_A2_vcmpbgtu:
251 case Intrinsic::hexagon_A2_vcmpheq:
252 case Intrinsic::hexagon_A2_vcmphgt:
253 case Intrinsic::hexagon_A2_vcmphgtu:
254 case Intrinsic::hexagon_A2_vcmpweq:
255 case Intrinsic::hexagon_A2_vcmpwgt:
256 case Intrinsic::hexagon_A2_vcmpwgtu:
257 case Intrinsic::hexagon_C2_tfrrp:
258 case Intrinsic::hexagon_S2_tstbit_i:
259 case Intrinsic::hexagon_S2_tstbit_r:
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000260 return true;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000261 }
262}
263
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000264SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
265 unsigned Opcode,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000266 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000267 SDValue Chain = LD->getChain();
268 EVT LoadedVT = LD->getMemoryVT();
269 SDValue Base = LD->getBasePtr();
270 SDValue Offset = LD->getOffset();
271 SDNode *OffsetNode = Offset.getNode();
272 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
Bill Wendling4a7a4082013-06-07 06:19:56 +0000273
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000274 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000275 SDValue TargetConst = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000276 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
277 MVT::Other, Base, TargetConst,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000278 Chain);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000279 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
280 SDValue(Result_1, 0));
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000281 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
282 MemOp[0] = LD->getMemOperand();
283 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
284 const SDValue Froms[] = { SDValue(LD, 0),
285 SDValue(LD, 1),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000286 SDValue(LD, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000287 const SDValue Tos[] = { SDValue(Result_2, 0),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000288 SDValue(Result_1, 1),
289 SDValue(Result_1, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000290 ReplaceUses(Froms, Tos, 3);
291 return Result_2;
292 }
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000293
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000294 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
295 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000296 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other,
297 Base, TargetConst0, Chain);
298 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
299 SDValue(Result_1, 0));
300 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
301 Base, TargetConstVal,
302 SDValue(Result_1, 1));
303 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
304 MemOp[0] = LD->getMemOperand();
305 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
306 const SDValue Froms[] = { SDValue(LD, 0),
307 SDValue(LD, 1),
308 SDValue(LD, 2) };
309 const SDValue Tos[] = { SDValue(Result_2, 0),
310 SDValue(Result_3, 0),
311 SDValue(Result_1, 1) };
312 ReplaceUses(Froms, Tos, 3);
313 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000314}
315
316
317SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
318 unsigned Opcode,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000319 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000320 SDValue Chain = LD->getChain();
321 EVT LoadedVT = LD->getMemoryVT();
322 SDValue Base = LD->getBasePtr();
323 SDValue Offset = LD->getOffset();
324 SDNode *OffsetNode = Offset.getNode();
325 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
Bill Wendling4a7a4082013-06-07 06:19:56 +0000326
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000327 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000328 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
329 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000330 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000331 MVT::i32, MVT::Other, Base,
332 TargetConstVal, Chain);
333 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000334 MVT::i64, MVT::Other,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000335 TargetConst0,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000336 SDValue(Result_1,0));
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000337 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
338 MemOp[0] = LD->getMemOperand();
339 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
340 const SDValue Froms[] = { SDValue(LD, 0),
341 SDValue(LD, 1),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000342 SDValue(LD, 2) };
343 const SDValue Tos[] = { SDValue(Result_2, 0),
344 SDValue(Result_1, 1),
345 SDValue(Result_1, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000346 ReplaceUses(Froms, Tos, 3);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000347 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000348 }
349
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000350 // Generate an indirect load.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000351 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
352 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000353 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
354 MVT::Other, Base, TargetConst0,
355 Chain);
356 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl,
357 MVT::i64, MVT::Other,
358 TargetConst0,
359 SDValue(Result_1,0));
360 // Add offset to base.
361 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
362 Base, TargetConstVal,
363 SDValue(Result_1, 1));
364 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
365 MemOp[0] = LD->getMemOperand();
366 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
367 const SDValue Froms[] = { SDValue(LD, 0),
368 SDValue(LD, 1),
369 SDValue(LD, 2) };
370 const SDValue Tos[] = { SDValue(Result_2, 0), // Load value.
371 SDValue(Result_3, 0), // New address.
372 SDValue(Result_1, 1) };
373 ReplaceUses(Froms, Tos, 3);
374 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000375}
376
377
Andrew Trickef9de2a2013-05-25 02:42:55 +0000378SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000379 SDValue Chain = LD->getChain();
380 SDValue Base = LD->getBasePtr();
381 SDValue Offset = LD->getOffset();
382 SDNode *OffsetNode = Offset.getNode();
383 // Get the constant value.
384 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
385 EVT LoadedVT = LD->getMemoryVT();
386 unsigned Opcode = 0;
387
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000388 // Check for zero extended loads. Treat any-extend loads as zero extended
389 // loads.
390 ISD::LoadExtType ExtType = LD->getExtensionType();
391 bool IsZeroExt = (ExtType == ISD::ZEXTLOAD || ExtType == ISD::EXTLOAD);
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000392 bool HasVecOffset = false;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000393
394 // Figure out the opcode.
395 if (LoadedVT == MVT::i64) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000396 if (HII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000397 Opcode = Hexagon::L2_loadrd_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000398 else
Colin LeMahieu947cd702014-12-23 20:44:59 +0000399 Opcode = Hexagon::L2_loadrd_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000400 } else if (LoadedVT == MVT::i32) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000401 if (HII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000402 Opcode = Hexagon::L2_loadri_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000403 else
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000404 Opcode = Hexagon::L2_loadri_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000405 } else if (LoadedVT == MVT::i16) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000406 if (HII->isValidAutoIncImm(LoadedVT, Val))
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000407 Opcode = IsZeroExt ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000408 else
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000409 Opcode = IsZeroExt ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000410 } else if (LoadedVT == MVT::i8) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000411 if (HII->isValidAutoIncImm(LoadedVT, Val))
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000412 Opcode = IsZeroExt ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000413 else
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000414 Opcode = IsZeroExt ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000415 } else if (LoadedVT == MVT::v16i32 || LoadedVT == MVT::v8i64 ||
416 LoadedVT == MVT::v32i16 || LoadedVT == MVT::v64i8) {
417 HasVecOffset = true;
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000418 bool Aligned = isAlignedMemNode(LD);
419 if (HII->isValidAutoIncImm(LoadedVT, Val))
420 Opcode = Aligned ? Hexagon::V6_vL32b_pi : Hexagon::V6_vL32Ub_pi;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000421 else
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000422 Opcode = Aligned ? Hexagon::V6_vL32b_ai : Hexagon::V6_vL32Ub_ai;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000423 // 128B
424 } else if (LoadedVT == MVT::v32i32 || LoadedVT == MVT::v16i64 ||
425 LoadedVT == MVT::v64i16 || LoadedVT == MVT::v128i8) {
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000426 if (HST->useHVXOps()) {
427 bool Aligned = isAlignedMemNode(LD);
428 HasVecOffset = true;
429 if (HII->isValidAutoIncImm(LoadedVT, Val))
430 Opcode = Aligned ? Hexagon::V6_vL32b_pi_128B
431 : Hexagon::V6_vL32Ub_pi_128B;
432 else
433 Opcode = Aligned ? Hexagon::V6_vL32b_ai_128B
434 : Hexagon::V6_vL32Ub_ai_128B;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000435 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000436 } else
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000437 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000438
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000439 // For zero extended i64 loads, we need to add combine instructions.
440 if (LD->getValueType(0) == MVT::i64 && IsZeroExt)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000441 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000442 // Handle sign extended i64 loads.
443 if (LD->getValueType(0) == MVT::i64 && ExtType == ISD::SEXTLOAD)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000444 return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000445
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000446 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000447 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000448 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
449 LD->getValueType(0),
450 MVT::i32, MVT::Other, Base,
451 TargetConstVal, Chain);
452 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
453 MemOp[0] = LD->getMemOperand();
454 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000455 if (HasVecOffset) {
456 const SDValue Froms[] = { SDValue(LD, 0),
457 SDValue(LD, 2)
458 };
459 const SDValue Tos[] = { SDValue(Result, 0),
460 SDValue(Result, 2)
461 };
462 ReplaceUses(Froms, Tos, 2);
463 } else {
464 const SDValue Froms[] = { SDValue(LD, 0),
465 SDValue(LD, 1),
466 SDValue(LD, 2)
467 };
468 const SDValue Tos[] = { SDValue(Result, 0),
469 SDValue(Result, 1),
470 SDValue(Result, 2)
471 };
472 ReplaceUses(Froms, Tos, 3);
473 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000474 return Result;
475 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000476 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
477 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000478 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
479 LD->getValueType(0),
480 MVT::Other, Base, TargetConst0,
481 Chain);
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000482 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000483 Base, TargetConstVal,
484 SDValue(Result_1, 1));
485 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
486 MemOp[0] = LD->getMemOperand();
487 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
488 const SDValue Froms[] = { SDValue(LD, 0),
489 SDValue(LD, 1),
490 SDValue(LD, 2)
491 };
492 const SDValue Tos[] = { SDValue(Result_1, 0),
493 SDValue(Result_2, 0),
494 SDValue(Result_1, 1)
495 };
496 ReplaceUses(Froms, Tos, 3);
497 return Result_1;
498 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000499}
500
501
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000502MachineSDNode *HexagonDAGToDAGISel::LoadInstrForLoadIntrinsic(SDNode *IntN) {
503 if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN)
504 return nullptr;
505
506 SDLoc dl(IntN);
507 unsigned IntNo = cast<ConstantSDNode>(IntN->getOperand(1))->getZExtValue();
508
509 static std::map<unsigned,unsigned> LoadPciMap = {
510 { Intrinsic::hexagon_circ_ldb, Hexagon::L2_loadrb_pci },
511 { Intrinsic::hexagon_circ_ldub, Hexagon::L2_loadrub_pci },
512 { Intrinsic::hexagon_circ_ldh, Hexagon::L2_loadrh_pci },
513 { Intrinsic::hexagon_circ_lduh, Hexagon::L2_loadruh_pci },
514 { Intrinsic::hexagon_circ_ldw, Hexagon::L2_loadri_pci },
515 { Intrinsic::hexagon_circ_ldd, Hexagon::L2_loadrd_pci },
516 };
517 auto FLC = LoadPciMap.find(IntNo);
518 if (FLC != LoadPciMap.end()) {
519 SDNode *Mod = CurDAG->getMachineNode(Hexagon::A2_tfrrcr, dl, MVT::i32,
520 IntN->getOperand(4));
521 EVT ValTy = (IntNo == Intrinsic::hexagon_circ_ldd) ? MVT::i64 : MVT::i32;
522 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
523 // Operands: { Base, Increment, Modifier, Chain }
524 auto Inc = cast<ConstantSDNode>(IntN->getOperand(5));
525 SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), dl, MVT::i32);
526 MachineSDNode *Res = CurDAG->getMachineNode(FLC->second, dl, RTys,
527 { IntN->getOperand(2), I, SDValue(Mod,0), IntN->getOperand(0) });
528 return Res;
529 }
530
531 static std::map<unsigned,unsigned> LoadPbrMap = {
532 { Intrinsic::hexagon_brev_ldb, Hexagon::L2_loadrb_pbr },
533 { Intrinsic::hexagon_brev_ldub, Hexagon::L2_loadrub_pbr },
534 { Intrinsic::hexagon_brev_ldh, Hexagon::L2_loadrh_pbr },
535 { Intrinsic::hexagon_brev_lduh, Hexagon::L2_loadruh_pbr },
536 { Intrinsic::hexagon_brev_ldw, Hexagon::L2_loadri_pbr },
537 { Intrinsic::hexagon_brev_ldd, Hexagon::L2_loadrd_pbr },
538 };
539 auto FLB = LoadPbrMap.find(IntNo);
540 if (FLB != LoadPbrMap.end()) {
541 SDNode *Mod = CurDAG->getMachineNode(Hexagon::A2_tfrrcr, dl, MVT::i32,
542 IntN->getOperand(4));
543 EVT ValTy = (IntNo == Intrinsic::hexagon_brev_ldd) ? MVT::i64 : MVT::i32;
544 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
545 // Operands: { Base, Modifier, Chain }
546 MachineSDNode *Res = CurDAG->getMachineNode(FLB->second, dl, RTys,
547 { IntN->getOperand(2), SDValue(Mod,0), IntN->getOperand(0) });
548 return Res;
549 }
550
551 return nullptr;
552}
553
554SDNode *HexagonDAGToDAGISel::StoreInstrForLoadIntrinsic(MachineSDNode *LoadN,
555 SDNode *IntN) {
556 // The "LoadN" is just a machine load instruction. The intrinsic also
557 // involves storing it. Generate an appropriate store to the location
558 // given in the intrinsic's operand(3).
559 uint64_t F = HII->get(LoadN->getMachineOpcode()).TSFlags;
560 unsigned SizeBits = (F >> HexagonII::MemAccessSizePos) &
561 HexagonII::MemAccesSizeMask;
562 unsigned Size = 1U << (SizeBits-1);
563
564 SDLoc dl(IntN);
565 MachinePointerInfo PI;
566 SDValue TS;
567 SDValue Loc = IntN->getOperand(3);
568
569 if (Size >= 4)
570 TS = CurDAG->getStore(SDValue(LoadN,2), dl, SDValue(LoadN, 0), Loc, PI,
571 false, false, Size);
572 else
573 TS = CurDAG->getTruncStore(SDValue(LoadN,2), dl, SDValue(LoadN,0), Loc, PI,
574 MVT::getIntegerVT(Size*8), false, false, Size);
575 SDNode *StoreN = SelectStore(TS.getNode());
576
577 // Load's results are { Loaded value, Updated pointer, Chain }
578 ReplaceUses(SDValue(IntN, 0), SDValue(LoadN, 1));
579 ReplaceUses(SDValue(IntN, 1), SDValue(StoreN, 0));
580 return StoreN;
581}
582
583SDNode *HexagonDAGToDAGISel::SelectLoadOfLoadIntrinsic(LoadSDNode *N) {
584 // The intrinsics for load circ/brev perform two operations:
585 // 1. Load a value V from the specified location, using the addressing
586 // mode corresponding to the intrinsic.
587 // 2. Store V into a specified location. This location is typically a
588 // local, temporary object.
589 // In many cases, the program using these intrinsics will immediately
590 // load V again from the local object. In those cases, when certain
591 // conditions are met, the last load can be removed.
592 // This function identifies and optimizes this pattern. If the pattern
593 // cannot be optimized, it returns nullptr, which will cause the load
594 // to be selected separately from the intrinsic (which will be handled
595 // in SelectIntrinsicWChain).
596
597 SDValue Ch = N->getOperand(0);
598 SDValue Loc = N->getOperand(1);
599
600 // Assume that the load and the intrinsic are connected directly with a
601 // chain:
602 // t1: i32,ch = int.load ..., ..., ..., Loc, ... // <-- C
603 // t2: i32,ch = load t1:1, Loc, ...
604 SDNode *C = Ch.getNode();
605
606 if (C->getOpcode() != ISD::INTRINSIC_W_CHAIN)
607 return nullptr;
608
609 // The second load can only be eliminated if its extension type matches
610 // that of the load instruction corresponding to the intrinsic. The user
611 // can provide an address of an unsigned variable to store the result of
612 // a sign-extending intrinsic into (or the other way around).
613 ISD::LoadExtType IntExt;
614 switch (cast<ConstantSDNode>(C->getOperand(1))->getZExtValue()) {
615 case Intrinsic::hexagon_brev_ldub:
616 case Intrinsic::hexagon_brev_lduh:
617 case Intrinsic::hexagon_circ_ldub:
618 case Intrinsic::hexagon_circ_lduh:
619 IntExt = ISD::ZEXTLOAD;
620 break;
621 case Intrinsic::hexagon_brev_ldw:
622 case Intrinsic::hexagon_brev_ldd:
623 case Intrinsic::hexagon_circ_ldw:
624 case Intrinsic::hexagon_circ_ldd:
625 IntExt = ISD::NON_EXTLOAD;
626 break;
627 default:
628 IntExt = ISD::SEXTLOAD;
629 break;
630 }
631 if (N->getExtensionType() != IntExt)
632 return nullptr;
633
634 // Make sure the target location for the loaded value in the load intrinsic
635 // is the location from which LD (or N) is loading.
636 if (C->getNumOperands() < 4 || Loc.getNode() != C->getOperand(3).getNode())
637 return nullptr;
638
639 if (MachineSDNode *L = LoadInstrForLoadIntrinsic(C)) {
640 SDNode *S = StoreInstrForLoadIntrinsic(L, C);
641 SDValue F[] = { SDValue(N,0), SDValue(N,1), SDValue(C,0), SDValue(C,1) };
642 SDValue T[] = { SDValue(L,0), SDValue(S,0), SDValue(L,1), SDValue(S,0) };
643 ReplaceUses(F, T, array_lengthof(T));
644 // This transformation will leave the intrinsic dead. If it remains in
645 // the DAG, the selection code will see it again, but without the load,
646 // and it will generate a store that is normally required for it.
647 CurDAG->RemoveDeadNodes();
648 return L;
649 }
650
651 return nullptr;
652}
653
654
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000655SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000656 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000657 LoadSDNode *LD = cast<LoadSDNode>(N);
658 ISD::MemIndexedMode AM = LD->getAddressingMode();
659
660 // Handle indexed loads.
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000661 if (AM != ISD::UNINDEXED)
662 return SelectIndexedLoad(LD, dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000663
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000664 // Handle patterns using circ/brev load intrinsics.
665 if (SDNode *LI = SelectLoadOfLoadIntrinsic(LD))
666 return LI;
667
668 return SelectCode(LD);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000669}
670
671
Andrew Trickef9de2a2013-05-25 02:42:55 +0000672SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000673 SDValue Chain = ST->getChain();
674 SDValue Base = ST->getBasePtr();
675 SDValue Offset = ST->getOffset();
676 SDValue Value = ST->getValue();
677 SDNode *OffsetNode = Offset.getNode();
678 // Get the constant value.
679 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
680 EVT StoredVT = ST->getMemoryVT();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000681 EVT ValueVT = Value.getValueType();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000682
683 // Offset value must be within representable range
684 // and must have correct alignment properties.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000685 if (HII->isValidAutoIncImm(StoredVT, Val)) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000686 unsigned Opcode = 0;
687
688 // Figure out the post inc version of opcode.
Colin LeMahieu9a3cd3f2014-12-29 20:00:43 +0000689 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi;
690 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi;
691 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi;
Colin LeMahieu3d34afb2014-12-29 19:42:14 +0000692 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000693 else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 ||
694 StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8) {
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000695 if (isAlignedMemNode(ST))
696 Opcode = Hexagon::V6_vS32b_pi;
697 else
698 Opcode = Hexagon::V6_vS32Ub_pi;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000699 }
700 // 128B
701 else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 ||
702 StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8) {
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000703 if (HST->useHVXOps())
704 Opcode = isAlignedMemNode(ST) ? Hexagon::V6_vS32b_pi_128B
705 : Hexagon::V6_vS32Ub_pi_128B;
706 } else
707 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000708
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000709 if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) {
710 assert(StoredVT.getSizeInBits() < 64 && "Not a truncating store");
711 Value = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg,
712 dl, MVT::i32, Value);
713 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000714 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, dl, MVT::i32), Value,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000715 Chain};
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000716 // Build post increment store.
717 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +0000718 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000719 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
720 MemOp[0] = ST->getMemOperand();
721 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
722
723 ReplaceUses(ST, Result);
724 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
725 return Result;
726 }
727
728 // Note: Order of operands matches the def of instruction:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000729 // def S2_storerd_io
730 // : STInst<(outs), (ins IntRegs:$base, imm:$offset, DoubleRegs:$src1), ...
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000731 // and it differs for POST_ST* for instance.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000732 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, dl, MVT::i32), Value,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000733 Chain};
734 unsigned Opcode = 0;
735
736 // Figure out the opcode.
Colin LeMahieubda31b42014-12-29 20:44:51 +0000737 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
738 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
739 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
740 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000741 else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 ||
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000742 StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8) {
743 if (isAlignedMemNode(ST))
744 Opcode = Hexagon::V6_vS32b_ai;
745 else
746 Opcode = Hexagon::V6_vS32Ub_ai;
747 }
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000748 // 128B
749 else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 ||
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000750 StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8) {
751 if (isAlignedMemNode(ST))
752 Opcode = Hexagon::V6_vS32b_ai_128B;
753 else
754 Opcode = Hexagon::V6_vS32Ub_ai_128B;
755 }
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000756 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000757
758 // Build regular store.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000759 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Michael Liaob53d8962013-04-19 22:22:57 +0000760 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000761 // Build splitted incriment instruction.
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000762 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000763 Base,
764 TargetConstVal,
765 SDValue(Result_1, 0));
766 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
767 MemOp[0] = ST->getMemOperand();
768 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
769
770 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
771 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
772 return Result_2;
773}
774
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000775SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000776 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000777 StoreSDNode *ST = cast<StoreSDNode>(N);
778 ISD::MemIndexedMode AM = ST->getAddressingMode();
779
780 // Handle indexed stores.
781 if (AM != ISD::UNINDEXED) {
782 return SelectIndexedStore(ST, dl);
783 }
Sirish Pandec92c3162012-05-03 16:18:50 +0000784
Colin LeMahieu2efa2d02015-03-09 21:48:13 +0000785 return SelectCode(ST);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000786}
787
788SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000789 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000790
791 //
792 // %conv.i = sext i32 %tmp1 to i64
793 // %conv2.i = sext i32 %add to i64
794 // %mul.i = mul nsw i64 %conv2.i, %conv.i
795 //
796 // --- match with the following ---
797 //
798 // %mul.i = mpy (%tmp1, %add)
799 //
800
801 if (N->getValueType(0) == MVT::i64) {
802 // Shifting a i64 signed multiply.
803 SDValue MulOp0 = N->getOperand(0);
804 SDValue MulOp1 = N->getOperand(1);
805
806 SDValue OP0;
807 SDValue OP1;
808
809 // Handle sign_extend and sextload.
810 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
811 SDValue Sext0 = MulOp0.getOperand(0);
812 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000813 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000814 }
815
816 OP0 = Sext0;
817 } else if (MulOp0.getOpcode() == ISD::LOAD) {
818 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
819 if (LD->getMemoryVT() != MVT::i32 ||
820 LD->getExtensionType() != ISD::SEXTLOAD ||
821 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000822 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000823 }
824
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000825 SDValue Chain = LD->getChain();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000826 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000827 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000828 MVT::Other,
829 LD->getBasePtr(), TargetConst0,
830 Chain), 0);
831 } else {
832 return SelectCode(N);
833 }
834
835 // Same goes for the second operand.
836 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
837 SDValue Sext1 = MulOp1.getOperand(0);
838 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
839 return SelectCode(N);
840 }
841
842 OP1 = Sext1;
843 } else if (MulOp1.getOpcode() == ISD::LOAD) {
844 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
845 if (LD->getMemoryVT() != MVT::i32 ||
846 LD->getExtensionType() != ISD::SEXTLOAD ||
847 LD->getAddressingMode() != ISD::UNINDEXED) {
848 return SelectCode(N);
849 }
850
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000851 SDValue Chain = LD->getChain();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000852 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000853 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000854 MVT::Other,
855 LD->getBasePtr(), TargetConst0,
856 Chain), 0);
857 } else {
858 return SelectCode(N);
859 }
860
861 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +0000862 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000863 OP0, OP1);
864 ReplaceUses(N, Result);
865 return Result;
866 }
867
868 return SelectCode(N);
869}
870
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000871SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000872 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000873 if (N->getValueType(0) == MVT::i32) {
874 SDValue Shl_0 = N->getOperand(0);
875 SDValue Shl_1 = N->getOperand(1);
876 // RHS is const.
877 if (Shl_1.getOpcode() == ISD::Constant) {
878 if (Shl_0.getOpcode() == ISD::MUL) {
879 SDValue Mul_0 = Shl_0.getOperand(0); // Val
880 SDValue Mul_1 = Shl_0.getOperand(1); // Const
881 // RHS of mul is const.
882 if (Mul_1.getOpcode() == ISD::Constant) {
883 int32_t ShlConst =
884 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
885 int32_t MulConst =
886 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
887 int32_t ValConst = MulConst << ShlConst;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000888 SDValue Val = CurDAG->getTargetConstant(ValConst, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000889 MVT::i32);
890 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
891 if (isInt<9>(CN->getSExtValue())) {
892 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000893 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000894 MVT::i32, Mul_0, Val);
895 ReplaceUses(N, Result);
896 return Result;
897 }
898
899 }
900 } else if (Shl_0.getOpcode() == ISD::SUB) {
901 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
902 SDValue Sub_1 = Shl_0.getOperand(1); // Val
903 if (Sub_0.getOpcode() == ISD::Constant) {
904 int32_t SubConst =
905 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
906 if (SubConst == 0) {
907 if (Sub_1.getOpcode() == ISD::SHL) {
908 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
909 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
910 if (Shl2_1.getOpcode() == ISD::Constant) {
911 int32_t ShlConst =
912 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
913 int32_t Shl2Const =
914 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
915 int32_t ValConst = 1 << (ShlConst+Shl2Const);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000916 SDValue Val = CurDAG->getTargetConstant(-ValConst, dl,
917 MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000918 if (ConstantSDNode *CN =
919 dyn_cast<ConstantSDNode>(Val.getNode()))
920 if (isInt<9>(CN->getSExtValue())) {
921 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000922 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000923 Shl2_0, Val);
924 ReplaceUses(N, Result);
925 return Result;
926 }
927 }
928 }
929 }
930 }
931 }
932 }
933 }
934 return SelectCode(N);
935}
936
937
938//
939// If there is an zero_extend followed an intrinsic in DAG (this means - the
940// result of the intrinsic is predicate); convert the zero_extend to
941// transfer instruction.
942//
943// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
944// converted into a MUX as predicate registers defined as 1 bit in the
945// compiler. Architecture defines them as 8-bit registers.
946// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
947//
948SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000949 SDLoc dl(N);
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000950
951 SDValue Op0 = N->getOperand(0);
952 EVT OpVT = Op0.getValueType();
953 unsigned OpBW = OpVT.getSizeInBits();
954
955 // Special handling for zero-extending a vector of booleans.
956 if (OpVT.isVector() && OpVT.getVectorElementType() == MVT::i1 && OpBW <= 64) {
957 SDNode *Mask = CurDAG->getMachineNode(Hexagon::C2_mask, dl, MVT::i64, Op0);
958 unsigned NE = OpVT.getVectorNumElements();
959 EVT ExVT = N->getValueType(0);
960 unsigned ES = ExVT.getVectorElementType().getSizeInBits();
961 uint64_t MV = 0, Bit = 1;
962 for (unsigned i = 0; i < NE; ++i) {
963 MV |= Bit;
964 Bit <<= ES;
965 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000966 SDValue Ones = CurDAG->getTargetConstant(MV, dl, MVT::i64);
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000967 SDNode *OnesReg = CurDAG->getMachineNode(Hexagon::CONST64_Int_Real, dl,
968 MVT::i64, Ones);
969 if (ExVT.getSizeInBits() == 32) {
970 SDNode *And = CurDAG->getMachineNode(Hexagon::A2_andp, dl, MVT::i64,
971 SDValue(Mask,0), SDValue(OnesReg,0));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000972 SDValue SubR = CurDAG->getTargetConstant(Hexagon::subreg_loreg, dl,
973 MVT::i32);
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000974 return CurDAG->getMachineNode(Hexagon::EXTRACT_SUBREG, dl, ExVT,
975 SDValue(And,0), SubR);
976 }
977 return CurDAG->getMachineNode(Hexagon::A2_andp, dl, ExVT,
978 SDValue(Mask,0), SDValue(OnesReg,0));
979 }
980
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000981 SDNode *IsIntrinsic = N->getOperand(0).getNode();
982 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
983 unsigned ID =
984 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
985 if (doesIntrinsicReturnPredicate(ID)) {
986 // Now we need to differentiate target data types.
987 if (N->getValueType(0) == MVT::i64) {
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +0000988 // Convert the zero_extend to Rs = Pd followed by A2_combinew(0,Rs).
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000989 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu30dcb232014-12-09 18:16:49 +0000990 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000991 MVT::i32,
992 SDValue(IsIntrinsic, 0));
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000993 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000994 MVT::i32,
995 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000996 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000997 MVT::i64, MVT::Other,
998 SDValue(Result_2, 0),
999 SDValue(Result_1, 0));
1000 ReplaceUses(N, Result_3);
1001 return Result_3;
1002 }
1003 if (N->getValueType(0) == MVT::i32) {
1004 // Convert the zero_extend to Rs = Pd
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001005 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001006 MVT::i32,
1007 SDValue(IsIntrinsic, 0));
1008 ReplaceUses(N, RsPd);
1009 return RsPd;
1010 }
Craig Toppere55c5562012-02-07 02:50:20 +00001011 llvm_unreachable("Unexpected value type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001012 }
1013 }
1014 return SelectCode(N);
1015}
1016
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +00001017
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001018//
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +00001019// Handling intrinsics for circular load and bitreverse load.
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +00001020//
1021SDNode *HexagonDAGToDAGISel::SelectIntrinsicWChain(SDNode *N) {
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +00001022 if (MachineSDNode *L = LoadInstrForLoadIntrinsic(N))
1023 return StoreInstrForLoadIntrinsic(L, N);
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +00001024 return SelectCode(N);
1025}
1026
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001027SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001028 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1029 unsigned Bits;
1030 switch (IID) {
1031 case Intrinsic::hexagon_S2_vsplatrb:
1032 Bits = 8;
1033 break;
1034 case Intrinsic::hexagon_S2_vsplatrh:
1035 Bits = 16;
1036 break;
1037 default:
1038 return SelectCode(N);
1039 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001040
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001041 SDValue const &V = N->getOperand(1);
1042 SDValue U;
1043 if (isValueExtension(V, Bits, U)) {
1044 SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
1045 N->getOperand(0), U);
1046 return SelectCode(R.getNode());
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001047 }
1048 return SelectCode(N);
1049}
1050
Sirish Pande69295b82012-05-10 20:20:25 +00001051//
1052// Map floating point constant values.
1053//
1054SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001055 SDLoc dl(N);
Sirish Pande69295b82012-05-10 20:20:25 +00001056 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1057 APFloat APF = CN->getValueAPF();
1058 if (N->getValueType(0) == MVT::f32) {
1059 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001060 CurDAG->getTargetConstantFP(APF.convertToFloat(), dl, MVT::f32));
Sirish Pande69295b82012-05-10 20:20:25 +00001061 }
1062 else if (N->getValueType(0) == MVT::f64) {
1063 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001064 CurDAG->getTargetConstantFP(APF.convertToDouble(), dl, MVT::f64));
Sirish Pande69295b82012-05-10 20:20:25 +00001065 }
1066
1067 return SelectCode(N);
1068}
1069
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001070//
1071// Map predicate true (encoded as -1 in LLVM) to a XOR.
1072//
1073SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001074 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001075 if (N->getValueType(0) == MVT::i1) {
Krzysztof Parzyszek36ccfa52015-03-18 19:07:53 +00001076 SDNode* Result = 0;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001077 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
Krzysztof Parzyszek7a9cd802015-03-18 18:50:06 +00001078 if (Val == -1) {
Krzysztof Parzyszek36ccfa52015-03-18 19:07:53 +00001079 Result = CurDAG->getMachineNode(Hexagon::TFR_PdTrue, dl, MVT::i1);
1080 } else if (Val == 0) {
1081 Result = CurDAG->getMachineNode(Hexagon::TFR_PdFalse, dl, MVT::i1);
1082 }
1083 if (Result) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001084 ReplaceUses(N, Result);
1085 return Result;
1086 }
1087 }
1088
1089 return SelectCode(N);
1090}
1091
1092
1093//
1094// Map add followed by a asr -> asr +=.
1095//
1096SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001097 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001098 if (N->getValueType(0) != MVT::i32) {
1099 return SelectCode(N);
1100 }
1101 // Identify nodes of the form: add(asr(...)).
1102 SDNode* Src1 = N->getOperand(0).getNode();
1103 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1104 || Src1->getValueType(0) != MVT::i32) {
1105 return SelectCode(N);
1106 }
1107
1108 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1109 // Rd and Rd' are assigned to the same register
Colin LeMahieu0f850bd2014-12-19 20:29:29 +00001110 SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001111 N->getOperand(1),
1112 Src1->getOperand(0),
1113 Src1->getOperand(1));
1114 ReplaceUses(N, Result);
1115
1116 return Result;
1117}
1118
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001119//
1120// Map the following, where possible.
1121// AND/FABS -> clrbit
1122// OR -> setbit
1123// XOR/FNEG ->toggle_bit.
1124//
1125SDNode *HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
1126 SDLoc dl(N);
1127 EVT ValueVT = N->getValueType(0);
1128
1129 // We handle only 32 and 64-bit bit ops.
1130 if (!(ValueVT == MVT::i32 || ValueVT == MVT::i64 ||
1131 ValueVT == MVT::f32 || ValueVT == MVT::f64))
1132 return SelectCode(N);
1133
1134 // We handly only fabs and fneg for V5.
1135 unsigned Opc = N->getOpcode();
Eric Christopher23a7d1e2015-03-21 03:12:59 +00001136 if ((Opc == ISD::FABS || Opc == ISD::FNEG) && !HST->hasV5TOps())
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001137 return SelectCode(N);
1138
1139 int64_t Val = 0;
1140 if (Opc != ISD::FABS && Opc != ISD::FNEG) {
1141 if (N->getOperand(1).getOpcode() == ISD::Constant)
1142 Val = cast<ConstantSDNode>((N)->getOperand(1))->getSExtValue();
1143 else
1144 return SelectCode(N);
1145 }
1146
1147 if (Opc == ISD::AND) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001148 // Check if this is a bit-clearing AND, if not select code the usual way.
1149 if ((ValueVT == MVT::i32 && isPowerOf2_32(~Val)) ||
1150 (ValueVT == MVT::i64 && isPowerOf2_64(~Val)))
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001151 Val = ~Val;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001152 else
1153 return SelectCode(N);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001154 }
1155
1156 // If OR or AND is being fed by shl, srl and, sra don't do this change,
1157 // because Hexagon provide |= &= on shl, srl, and sra.
1158 // Traverse the DAG to see if there is shl, srl and sra.
1159 if (Opc == ISD::OR || Opc == ISD::AND) {
1160 switch (N->getOperand(0)->getOpcode()) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001161 default:
1162 break;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001163 case ISD::SRA:
1164 case ISD::SRL:
1165 case ISD::SHL:
1166 return SelectCode(N);
1167 }
1168 }
1169
1170 // Make sure it's power of 2.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001171 unsigned BitPos = 0;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001172 if (Opc != ISD::FABS && Opc != ISD::FNEG) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001173 if ((ValueVT == MVT::i32 && !isPowerOf2_32(Val)) ||
1174 (ValueVT == MVT::i64 && !isPowerOf2_64(Val)))
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001175 return SelectCode(N);
1176
1177 // Get the bit position.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001178 BitPos = countTrailingZeros(uint64_t(Val));
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001179 } else {
1180 // For fabs and fneg, it's always the 31st bit.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001181 BitPos = 31;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001182 }
1183
1184 unsigned BitOpc = 0;
1185 // Set the right opcode for bitwise operations.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001186 switch (Opc) {
1187 default:
1188 llvm_unreachable("Only bit-wise/abs/neg operations are allowed.");
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001189 case ISD::AND:
1190 case ISD::FABS:
1191 BitOpc = Hexagon::S2_clrbit_i;
1192 break;
1193 case ISD::OR:
1194 BitOpc = Hexagon::S2_setbit_i;
1195 break;
1196 case ISD::XOR:
1197 case ISD::FNEG:
1198 BitOpc = Hexagon::S2_togglebit_i;
1199 break;
1200 }
1201
1202 SDNode *Result;
1203 // Get the right SDVal for the opcode.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001204 SDValue SDVal = CurDAG->getTargetConstant(BitPos, dl, MVT::i32);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001205
1206 if (ValueVT == MVT::i32 || ValueVT == MVT::f32) {
1207 Result = CurDAG->getMachineNode(BitOpc, dl, ValueVT,
1208 N->getOperand(0), SDVal);
1209 } else {
1210 // 64-bit gymnastic to use REG_SEQUENCE. But it's worth it.
1211 EVT SubValueVT;
1212 if (ValueVT == MVT::i64)
1213 SubValueVT = MVT::i32;
1214 else
1215 SubValueVT = MVT::f32;
1216
1217 SDNode *Reg = N->getOperand(0).getNode();
1218 SDValue RegClass = CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001219 dl, MVT::i64);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001220
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001221 SDValue SubregHiIdx = CurDAG->getTargetConstant(Hexagon::subreg_hireg, dl,
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001222 MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001223 SDValue SubregLoIdx = CurDAG->getTargetConstant(Hexagon::subreg_loreg, dl,
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001224 MVT::i32);
1225
1226 SDValue SubregHI = CurDAG->getTargetExtractSubreg(Hexagon::subreg_hireg, dl,
1227 MVT::i32, SDValue(Reg, 0));
1228
1229 SDValue SubregLO = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg, dl,
1230 MVT::i32, SDValue(Reg, 0));
1231
1232 // Clear/set/toggle hi or lo registers depending on the bit position.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001233 if (SubValueVT != MVT::f32 && BitPos < 32) {
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001234 SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
1235 SubregLO, SDVal);
1236 const SDValue Ops[] = { RegClass, SubregHI, SubregHiIdx,
1237 SDValue(Result0, 0), SubregLoIdx };
1238 Result = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
1239 dl, ValueVT, Ops);
1240 } else {
1241 if (Opc != ISD::FABS && Opc != ISD::FNEG)
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001242 SDVal = CurDAG->getTargetConstant(BitPos-32, dl, MVT::i32);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001243 SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
1244 SubregHI, SDVal);
1245 const SDValue Ops[] = { RegClass, SDValue(Result0, 0), SubregHiIdx,
1246 SubregLO, SubregLoIdx };
1247 Result = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
1248 dl, ValueVT, Ops);
1249 }
1250 }
1251
1252 ReplaceUses(N, Result);
1253 return Result;
1254}
1255
1256
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001257SDNode *HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) {
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001258 MachineFrameInfo *MFI = MF->getFrameInfo();
1259 const HexagonFrameLowering *HFI = HST->getFrameLowering();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001260 int FX = cast<FrameIndexSDNode>(N)->getIndex();
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001261 unsigned StkA = HFI->getStackAlignment();
1262 unsigned MaxA = MFI->getMaxAlignment();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001263 SDValue FI = CurDAG->getTargetFrameIndex(FX, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001264 SDLoc DL(N);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001265 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001266 SDNode *R = 0;
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001267
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001268 // Use TFR_FI when:
1269 // - the object is fixed, or
1270 // - there are no objects with higher-than-default alignment, or
1271 // - there are no dynamically allocated objects.
1272 // Otherwise, use TFR_FIA.
1273 if (FX < 0 || MaxA <= StkA || !MFI->hasVarSizedObjects()) {
1274 R = CurDAG->getMachineNode(Hexagon::TFR_FI, DL, MVT::i32, FI, Zero);
1275 } else {
1276 auto &HMFI = *MF->getInfo<HexagonMachineFunctionInfo>();
1277 unsigned AR = HMFI.getStackAlignBaseVReg();
1278 SDValue CH = CurDAG->getEntryNode();
1279 SDValue Ops[] = { CurDAG->getCopyFromReg(CH, DL, AR, MVT::i32), FI, Zero };
1280 R = CurDAG->getMachineNode(Hexagon::TFR_FIA, DL, MVT::i32, Ops);
1281 }
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001282
1283 if (N->getHasDebugValue())
1284 CurDAG->TransferDbgValues(SDValue(N, 0), SDValue(R, 0));
1285 return R;
1286}
1287
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001288
1289SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
Tim Northover31d093c2013-09-22 08:21:56 +00001290 if (N->isMachineOpcode()) {
1291 N->setNodeId(-1);
Craig Topper062a2ba2014-04-25 05:30:21 +00001292 return nullptr; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00001293 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001294
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001295 switch (N->getOpcode()) {
1296 case ISD::Constant:
1297 return SelectConstant(N);
1298
Sirish Pande69295b82012-05-10 20:20:25 +00001299 case ISD::ConstantFP:
1300 return SelectConstantFP(N);
1301
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001302 case ISD::FrameIndex:
1303 return SelectFrameIndex(N);
1304
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001305 case ISD::ADD:
1306 return SelectAdd(N);
1307
1308 case ISD::SHL:
1309 return SelectSHL(N);
1310
1311 case ISD::LOAD:
1312 return SelectLoad(N);
1313
1314 case ISD::STORE:
1315 return SelectStore(N);
1316
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001317 case ISD::MUL:
1318 return SelectMul(N);
1319
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001320 case ISD::AND:
1321 case ISD::OR:
1322 case ISD::XOR:
1323 case ISD::FABS:
1324 case ISD::FNEG:
1325 return SelectBitOp(N);
1326
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001327 case ISD::ZERO_EXTEND:
1328 return SelectZeroExtend(N);
1329
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +00001330 case ISD::INTRINSIC_W_CHAIN:
1331 return SelectIntrinsicWChain(N);
1332
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001333 case ISD::INTRINSIC_WO_CHAIN:
1334 return SelectIntrinsicWOChain(N);
1335 }
1336
1337 return SelectCode(N);
1338}
1339
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001340bool HexagonDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00001341SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001342 std::vector<SDValue> &OutOps) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001343 SDValue Inp = Op, Res;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001344
Daniel Sanders60f1db02015-03-13 12:45:09 +00001345 switch (ConstraintID) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001346 default:
1347 return true;
Daniel Sanders49f643c2015-03-17 14:37:39 +00001348 case InlineAsm::Constraint_i:
1349 case InlineAsm::Constraint_o: // Offsetable.
1350 case InlineAsm::Constraint_v: // Not offsetable.
1351 case InlineAsm::Constraint_m: // Memory.
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001352 if (SelectAddrFI(Inp, Res))
1353 OutOps.push_back(Res);
1354 else
1355 OutOps.push_back(Inp);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001356 break;
1357 }
1358
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001359 OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));
Jyotsna Vermad9225242013-02-13 21:38:46 +00001360 return false;
1361}
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001362
Colin LeMahieu79ec0652015-06-12 19:57:32 +00001363
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001364void HexagonDAGToDAGISel::PreprocessISelDAG() {
1365 SelectionDAG &DAG = *CurDAG;
1366 std::vector<SDNode*> Nodes;
Pete Cooper7e64ef02015-07-14 23:43:29 +00001367 for (SDNode &Node : DAG.allnodes())
1368 Nodes.push_back(&Node);
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001369
1370 // Simplify: (or (select c x 0) z) -> (select c (or x z) z)
1371 // (or (select c 0 y) z) -> (select c z (or y z))
1372 // This may not be the right thing for all targets, so do it here.
1373 for (auto I: Nodes) {
1374 if (I->getOpcode() != ISD::OR)
1375 continue;
1376
1377 auto IsZero = [] (const SDValue &V) -> bool {
1378 if (ConstantSDNode *SC = dyn_cast<ConstantSDNode>(V.getNode()))
1379 return SC->isNullValue();
1380 return false;
1381 };
1382 auto IsSelect0 = [IsZero] (const SDValue &Op) -> bool {
1383 if (Op.getOpcode() != ISD::SELECT)
1384 return false;
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +00001385 return IsZero(Op.getOperand(1)) || IsZero(Op.getOperand(2));
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001386 };
1387
1388 SDValue N0 = I->getOperand(0), N1 = I->getOperand(1);
1389 EVT VT = I->getValueType(0);
1390 bool SelN0 = IsSelect0(N0);
1391 SDValue SOp = SelN0 ? N0 : N1;
1392 SDValue VOp = SelN0 ? N1 : N0;
1393
1394 if (SOp.getOpcode() == ISD::SELECT && SOp.getNode()->hasOneUse()) {
1395 SDValue SC = SOp.getOperand(0);
1396 SDValue SX = SOp.getOperand(1);
1397 SDValue SY = SOp.getOperand(2);
1398 SDLoc DLS = SOp;
1399 if (IsZero(SY)) {
1400 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SX, VOp);
1401 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, NewOr, VOp);
1402 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1403 } else if (IsZero(SX)) {
1404 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SY, VOp);
1405 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, VOp, NewOr);
1406 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1407 }
1408 }
1409 }
1410}
1411
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001412void HexagonDAGToDAGISel::EmitFunctionEntryCode() {
1413 auto &HST = static_cast<const HexagonSubtarget&>(MF->getSubtarget());
1414 auto &HFI = *HST.getFrameLowering();
1415 if (!HFI.needsAligna(*MF))
1416 return;
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001417
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001418 MachineFrameInfo *MFI = MF->getFrameInfo();
Duncan P. N. Exon Smitha72c6e22015-10-20 00:46:39 +00001419 MachineBasicBlock *EntryBB = &MF->front();
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001420 unsigned AR = FuncInfo->CreateReg(MVT::i32);
1421 unsigned MaxA = MFI->getMaxAlignment();
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001422 BuildMI(EntryBB, DebugLoc(), HII->get(Hexagon::ALIGNA), AR)
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001423 .addImm(MaxA);
1424 MF->getInfo<HexagonMachineFunctionInfo>()->setStackAlignBaseVReg(AR);
1425}
1426
1427// Match a frame index that can be used in an addressing mode.
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001428bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) {
1429 if (N.getOpcode() != ISD::FrameIndex)
1430 return false;
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001431 auto &HFI = *HST->getFrameLowering();
1432 MachineFrameInfo *MFI = MF->getFrameInfo();
1433 int FX = cast<FrameIndexSDNode>(N)->getIndex();
1434 if (!MFI->isFixedObjectIndex(FX) && HFI.needsAligna(*MF))
1435 return false;
1436 R = CurDAG->getTargetFrameIndex(FX, MVT::i32);
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001437 return true;
1438}
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001439
Colin LeMahieu987b0942015-02-04 20:38:01 +00001440inline bool HexagonDAGToDAGISel::SelectAddrGA(SDValue &N, SDValue &R) {
1441 return SelectGlobalAddress(N, R, false);
1442}
1443
Colin LeMahieu51491352015-02-04 22:36:28 +00001444inline bool HexagonDAGToDAGISel::SelectAddrGP(SDValue &N, SDValue &R) {
1445 return SelectGlobalAddress(N, R, true);
1446}
1447
Colin LeMahieu987b0942015-02-04 20:38:01 +00001448bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
1449 bool UseGP) {
1450 switch (N.getOpcode()) {
1451 case ISD::ADD: {
1452 SDValue N0 = N.getOperand(0);
1453 SDValue N1 = N.getOperand(1);
1454 unsigned GAOpc = N0.getOpcode();
1455 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1456 return false;
1457 if (!UseGP && GAOpc != HexagonISD::CONST32)
1458 return false;
1459 if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) {
1460 SDValue Addr = N0.getOperand(0);
1461 if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Addr)) {
1462 if (GA->getOpcode() == ISD::TargetGlobalAddress) {
1463 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1464 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),
1465 N.getValueType(), NewOff);
1466 return true;
1467 }
1468 }
1469 }
1470 break;
1471 }
1472 case HexagonISD::CONST32:
1473 // The operand(0) of CONST32 is TargetGlobalAddress, which is what we
1474 // want in the instruction.
1475 if (!UseGP)
1476 R = N.getOperand(0);
1477 return !UseGP;
1478 case HexagonISD::CONST32_GP:
1479 if (UseGP)
1480 R = N.getOperand(0);
1481 return UseGP;
1482 default:
1483 return false;
1484 }
1485
1486 return false;
1487}
1488
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001489bool HexagonDAGToDAGISel::isValueExtension(const SDValue &Val,
1490 unsigned FromBits, SDValue &Src) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001491 unsigned Opc = Val.getOpcode();
1492 switch (Opc) {
1493 case ISD::SIGN_EXTEND:
1494 case ISD::ZERO_EXTEND:
1495 case ISD::ANY_EXTEND: {
1496 SDValue const &Op0 = Val.getOperand(0);
1497 EVT T = Op0.getValueType();
1498 if (T.isInteger() && T.getSizeInBits() == FromBits) {
1499 Src = Op0;
1500 return true;
1501 }
1502 break;
1503 }
1504 case ISD::SIGN_EXTEND_INREG:
1505 case ISD::AssertSext:
1506 case ISD::AssertZext:
1507 if (Val.getOperand(0).getValueType().isInteger()) {
1508 VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
1509 if (T->getVT().getSizeInBits() == FromBits) {
1510 Src = Val.getOperand(0);
1511 return true;
1512 }
1513 }
1514 break;
1515 case ISD::AND: {
1516 // Check if this is an AND with "FromBits" of lower bits set to 1.
1517 uint64_t FromMask = (1 << FromBits) - 1;
1518 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1519 if (C->getZExtValue() == FromMask) {
1520 Src = Val.getOperand(1);
1521 return true;
1522 }
1523 }
1524 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1525 if (C->getZExtValue() == FromMask) {
1526 Src = Val.getOperand(0);
1527 return true;
1528 }
1529 }
1530 break;
1531 }
1532 case ISD::OR:
1533 case ISD::XOR: {
1534 // OR/XOR with the lower "FromBits" bits set to 0.
1535 uint64_t FromMask = (1 << FromBits) - 1;
1536 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1537 if ((C->getZExtValue() & FromMask) == 0) {
1538 Src = Val.getOperand(1);
1539 return true;
1540 }
1541 }
1542 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1543 if ((C->getZExtValue() & FromMask) == 0) {
1544 Src = Val.getOperand(0);
1545 return true;
1546 }
1547 }
1548 }
1549 default:
1550 break;
1551 }
1552 return false;
1553}
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +00001554
1555bool HexagonDAGToDAGISel::isAlignedMemNode(const MemSDNode *N) const {
1556 return N->getAlignment() >= N->getMemoryVT().getStoreSize();
1557}