blob: f22e17c296dc9ecdff4b22812fe0f51067067e02 [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"
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +000018#include "llvm/CodeGen/FunctionLoweringInfo.h"
19#include "llvm/CodeGen/MachineInstrBuilder.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000020#include "llvm/CodeGen/SelectionDAGISel.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000021#include "llvm/IR/Intrinsics.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000022#include "llvm/Support/CommandLine.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000023#include "llvm/Support/Debug.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000024using namespace llvm;
25
Chandler Carruth84e68b22014-04-22 02:41:26 +000026#define DEBUG_TYPE "hexagon-isel"
27
Jyotsna Vermad9225242013-02-13 21:38:46 +000028static
29cl::opt<unsigned>
30MaxNumOfUsesForConstExtenders("ga-max-num-uses-for-constant-extenders",
31 cl::Hidden, cl::init(2),
32 cl::desc("Maximum number of uses of a global address such that we still us a"
33 "constant extended instruction"));
Tony Linthicum1213a7a2011-12-12 21:14:40 +000034
35//===----------------------------------------------------------------------===//
36// Instruction Selector Implementation
37//===----------------------------------------------------------------------===//
38
Jyotsna Vermad9225242013-02-13 21:38:46 +000039namespace llvm {
40 void initializeHexagonDAGToDAGISelPass(PassRegistry&);
41}
42
Tony Linthicum1213a7a2011-12-12 21:14:40 +000043//===--------------------------------------------------------------------===//
44/// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine
45/// instructions for SelectionDAG operations.
46///
47namespace {
48class HexagonDAGToDAGISel : public SelectionDAGISel {
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +000049 const HexagonTargetMachine &HTM;
Eric Christopher23a7d1e2015-03-21 03:12:59 +000050 const HexagonSubtarget *HST;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +000051 const HexagonInstrInfo *HII;
52 const HexagonRegisterInfo *HRI;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000053public:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +000054 explicit HexagonDAGToDAGISel(HexagonTargetMachine &tm,
Jyotsna Vermad9225242013-02-13 21:38:46 +000055 CodeGenOpt::Level OptLevel)
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +000056 : SelectionDAGISel(tm, OptLevel), HTM(tm), HST(nullptr), HII(nullptr),
57 HRI(nullptr) {
Jyotsna Vermad9225242013-02-13 21:38:46 +000058 initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry());
Tony Linthicum1213a7a2011-12-12 21:14:40 +000059 }
Eric Christopher23a7d1e2015-03-21 03:12:59 +000060
61 bool runOnMachineFunction(MachineFunction &MF) override {
62 // Reset the subtarget each time through.
63 HST = &MF.getSubtarget<HexagonSubtarget>();
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +000064 HII = HST->getInstrInfo();
65 HRI = HST->getRegisterInfo();
Eric Christopher23a7d1e2015-03-21 03:12:59 +000066 SelectionDAGISel::runOnMachineFunction(MF);
67 return true;
68 }
69
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +000070 virtual void PreprocessISelDAG() override;
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +000071 virtual void EmitFunctionEntryCode() override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000072
Justin Bognerec37a022016-05-12 21:46:18 +000073 void Select(SDNode *N) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000074
75 // Complex Pattern Selectors.
Colin LeMahieu987b0942015-02-04 20:38:01 +000076 inline bool SelectAddrGA(SDValue &N, SDValue &R);
Colin LeMahieu51491352015-02-04 22:36:28 +000077 inline bool SelectAddrGP(SDValue &N, SDValue &R);
Colin LeMahieu987b0942015-02-04 20:38:01 +000078 bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP);
Colin LeMahieuc7522f32015-01-14 23:07:36 +000079 bool SelectAddrFI(SDValue &N, SDValue &R);
80
Craig Topper906c2cd2014-04-29 07:58:16 +000081 const char *getPassName() const override {
Tony Linthicum1213a7a2011-12-12 21:14:40 +000082 return "Hexagon DAG->DAG Pattern Instruction Selection";
83 }
84
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +000085 // Generate a machine instruction node corresponding to the circ/brev
86 // load intrinsic.
87 MachineSDNode *LoadInstrForLoadIntrinsic(SDNode *IntN);
88 // Given the circ/brev load intrinsic and the already generated machine
89 // instruction, generate the appropriate store (that is a part of the
90 // intrinsic's functionality).
91 SDNode *StoreInstrForLoadIntrinsic(MachineSDNode *LoadN, SDNode *IntN);
92
Justin Bognerec37a022016-05-12 21:46:18 +000093 void SelectFrameIndex(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000094 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
95 /// inline asm expressions.
Craig Topper906c2cd2014-04-29 07:58:16 +000096 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
Daniel Sanders60f1db02015-03-13 12:45:09 +000097 unsigned ConstraintID,
Craig Topper906c2cd2014-04-29 07:58:16 +000098 std::vector<SDValue> &OutOps) override;
Justin Bognerec37a022016-05-12 21:46:18 +000099 bool tryLoadOfLoadIntrinsic(LoadSDNode *N);
100 void SelectLoad(SDNode *N);
101 void SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl);
102 void SelectIndexedLoad(LoadSDNode *LD, SDLoc dl);
103 void SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode, SDLoc dl);
104 void SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode, SDLoc dl);
105 void SelectBaseOffsetStore(StoreSDNode *ST, SDLoc dl);
106 void SelectIndexedStore(StoreSDNode *ST, SDLoc dl);
107 void SelectStore(SDNode *N);
108 void SelectSHL(SDNode *N);
109 void SelectMul(SDNode *N);
110 void SelectZeroExtend(SDNode *N);
111 void SelectIntrinsicWChain(SDNode *N);
112 void SelectIntrinsicWOChain(SDNode *N);
113 void SelectConstant(SDNode *N);
114 void SelectConstantFP(SDNode *N);
115 void SelectAdd(SDNode *N);
116 void SelectBitOp(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000117
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000118 // XformMskToBitPosU5Imm - Returns the bit position which
119 // the single bit 32 bit mask represents.
120 // Used in Clr and Set bit immediate memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000121 SDValue XformMskToBitPosU5Imm(uint32_t Imm, SDLoc DL) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000122 int32_t bitPos;
123 bitPos = Log2_32(Imm);
124 assert(bitPos >= 0 && bitPos < 32 &&
125 "Constant out of range for 32 BitPos Memops");
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000126 return CurDAG->getTargetConstant(bitPos, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000127 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000128
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000129 // XformMskToBitPosU4Imm - Returns the bit position which the single-bit
130 // 16 bit mask represents. Used in Clr and Set bit immediate memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000131 SDValue XformMskToBitPosU4Imm(uint16_t Imm, SDLoc DL) {
132 return XformMskToBitPosU5Imm(Imm, DL);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000133 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000134
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000135 // XformMskToBitPosU3Imm - Returns the bit position which the single-bit
136 // 8 bit mask represents. Used in Clr and Set bit immediate memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000137 SDValue XformMskToBitPosU3Imm(uint8_t Imm, SDLoc DL) {
138 return XformMskToBitPosU5Imm(Imm, DL);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000139 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000140
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000141 // Return true if there is exactly one bit set in V, i.e., if V is one of the
142 // following integers: 2^0, 2^1, ..., 2^31.
143 bool ImmIsSingleBit(uint32_t v) const {
144 return isPowerOf2_32(v);
145 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000146
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000147 // XformM5ToU5Imm - Return a target constant with the specified value, of
148 // type i32 where the negative literal is transformed into a positive literal
149 // for use in -= memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000150 inline SDValue XformM5ToU5Imm(signed Imm, SDLoc DL) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000151 assert((Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
152 return CurDAG->getTargetConstant(-Imm, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000153 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000154
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000155 // XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
156 // [1..128], used in cmpb.gtu instructions.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000157 inline SDValue XformU7ToU7M1Imm(signed Imm, SDLoc DL) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000158 assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op");
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000159 return CurDAG->getTargetConstant(Imm - 1, DL, MVT::i8);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000160 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000161
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000162 // XformS8ToS8M1Imm - Return a target constant decremented by 1.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000163 inline SDValue XformSToSM1Imm(signed Imm, SDLoc DL) {
164 return CurDAG->getTargetConstant(Imm - 1, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000165 }
Jyotsna Verma60316252013-02-05 19:20:45 +0000166
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000167 // XformU8ToU8M1Imm - Return a target constant decremented by 1.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000168 inline SDValue XformUToUM1Imm(unsigned Imm, SDLoc DL) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000169 assert((Imm >= 1) && "Cannot decrement unsigned int less than 1");
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000170 return CurDAG->getTargetConstant(Imm - 1, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000171 }
Jyotsna Verma89c84822013-04-23 19:15:55 +0000172
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000173 // XformSToSM2Imm - Return a target constant decremented by 2.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000174 inline SDValue XformSToSM2Imm(unsigned Imm, SDLoc DL) {
175 return CurDAG->getTargetConstant(Imm - 2, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000176 }
Jyotsna Verma89c84822013-04-23 19:15:55 +0000177
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000178 // XformSToSM3Imm - Return a target constant decremented by 3.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000179 inline SDValue XformSToSM3Imm(unsigned Imm, SDLoc DL) {
180 return CurDAG->getTargetConstant(Imm - 3, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000181 }
Colin LeMahieu19ed07c2015-01-28 18:29:11 +0000182
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000183 // Include the pieces autogenerated from the target description.
184 #include "HexagonGenDAGISel.inc"
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +0000185
186private:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000187 bool isValueExtension(const SDValue &Val, unsigned FromBits, SDValue &Src);
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000188 bool isAlignedMemNode(const MemSDNode *N) const;
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000189}; // end HexagonDAGToDAGISel
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000190} // end anonymous namespace
191
192
193/// createHexagonISelDag - This pass converts a legalized DAG into a
194/// Hexagon-specific DAG, ready for instruction scheduling.
195///
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000196namespace llvm {
197FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM,
198 CodeGenOpt::Level OptLevel) {
Jyotsna Vermad9225242013-02-13 21:38:46 +0000199 return new HexagonDAGToDAGISel(TM, OptLevel);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000200}
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000201}
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000202
Jyotsna Vermad9225242013-02-13 21:38:46 +0000203static void initializePassOnce(PassRegistry &Registry) {
204 const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection";
205 PassInfo *PI = new PassInfo(Name, "hexagon-isel",
Craig Topper062a2ba2014-04-25 05:30:21 +0000206 &SelectionDAGISel::ID, nullptr, false, false);
Jyotsna Vermad9225242013-02-13 21:38:46 +0000207 Registry.registerPass(*PI, true);
208}
209
210void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
211 CALL_ONCE_INITIALIZATION(initializePassOnce)
212}
213
214
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000215// Intrinsics that return a a predicate.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000216static bool doesIntrinsicReturnPredicate(unsigned ID) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000217 switch (ID) {
218 default:
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000219 return false;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000220 case Intrinsic::hexagon_C2_cmpeq:
221 case Intrinsic::hexagon_C2_cmpgt:
222 case Intrinsic::hexagon_C2_cmpgtu:
223 case Intrinsic::hexagon_C2_cmpgtup:
224 case Intrinsic::hexagon_C2_cmpgtp:
225 case Intrinsic::hexagon_C2_cmpeqp:
226 case Intrinsic::hexagon_C2_bitsset:
227 case Intrinsic::hexagon_C2_bitsclr:
228 case Intrinsic::hexagon_C2_cmpeqi:
229 case Intrinsic::hexagon_C2_cmpgti:
230 case Intrinsic::hexagon_C2_cmpgtui:
231 case Intrinsic::hexagon_C2_cmpgei:
232 case Intrinsic::hexagon_C2_cmpgeui:
233 case Intrinsic::hexagon_C2_cmplt:
234 case Intrinsic::hexagon_C2_cmpltu:
235 case Intrinsic::hexagon_C2_bitsclri:
236 case Intrinsic::hexagon_C2_and:
237 case Intrinsic::hexagon_C2_or:
238 case Intrinsic::hexagon_C2_xor:
239 case Intrinsic::hexagon_C2_andn:
240 case Intrinsic::hexagon_C2_not:
241 case Intrinsic::hexagon_C2_orn:
242 case Intrinsic::hexagon_C2_pxfer_map:
243 case Intrinsic::hexagon_C2_any8:
244 case Intrinsic::hexagon_C2_all8:
245 case Intrinsic::hexagon_A2_vcmpbeq:
246 case Intrinsic::hexagon_A2_vcmpbgtu:
247 case Intrinsic::hexagon_A2_vcmpheq:
248 case Intrinsic::hexagon_A2_vcmphgt:
249 case Intrinsic::hexagon_A2_vcmphgtu:
250 case Intrinsic::hexagon_A2_vcmpweq:
251 case Intrinsic::hexagon_A2_vcmpwgt:
252 case Intrinsic::hexagon_A2_vcmpwgtu:
253 case Intrinsic::hexagon_C2_tfrrp:
254 case Intrinsic::hexagon_S2_tstbit_i:
255 case Intrinsic::hexagon_S2_tstbit_r:
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000256 return true;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000257 }
258}
259
Justin Bognerec37a022016-05-12 21:46:18 +0000260void HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
261 unsigned Opcode,
262 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000263 SDValue Chain = LD->getChain();
264 EVT LoadedVT = LD->getMemoryVT();
265 SDValue Base = LD->getBasePtr();
266 SDValue Offset = LD->getOffset();
267 SDNode *OffsetNode = Offset.getNode();
268 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
Bill Wendling4a7a4082013-06-07 06:19:56 +0000269
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000270 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000271 SDValue TargetConst = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000272 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
273 MVT::Other, Base, TargetConst,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000274 Chain);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000275 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
276 SDValue(Result_1, 0));
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000277 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
278 MemOp[0] = LD->getMemOperand();
279 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
280 const SDValue Froms[] = { SDValue(LD, 0),
281 SDValue(LD, 1),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000282 SDValue(LD, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000283 const SDValue Tos[] = { SDValue(Result_2, 0),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000284 SDValue(Result_1, 1),
285 SDValue(Result_1, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000286 ReplaceUses(Froms, Tos, 3);
Justin Bognerec37a022016-05-12 21:46:18 +0000287 CurDAG->RemoveDeadNode(LD);
288 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000289 }
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000290
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000291 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
292 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000293 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other,
294 Base, TargetConst0, Chain);
295 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
296 SDValue(Result_1, 0));
297 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
298 Base, TargetConstVal,
299 SDValue(Result_1, 1));
300 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
301 MemOp[0] = LD->getMemOperand();
302 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
303 const SDValue Froms[] = { SDValue(LD, 0),
304 SDValue(LD, 1),
305 SDValue(LD, 2) };
306 const SDValue Tos[] = { SDValue(Result_2, 0),
307 SDValue(Result_3, 0),
308 SDValue(Result_1, 1) };
309 ReplaceUses(Froms, Tos, 3);
Justin Bognerec37a022016-05-12 21:46:18 +0000310 CurDAG->RemoveDeadNode(LD);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000311}
312
Justin Bognerec37a022016-05-12 21:46:18 +0000313void HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
314 unsigned Opcode,
315 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000316 SDValue Chain = LD->getChain();
317 EVT LoadedVT = LD->getMemoryVT();
318 SDValue Base = LD->getBasePtr();
319 SDValue Offset = LD->getOffset();
320 SDNode *OffsetNode = Offset.getNode();
321 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
Bill Wendling4a7a4082013-06-07 06:19:56 +0000322
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000323 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000324 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
325 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000326 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000327 MVT::i32, MVT::Other, Base,
328 TargetConstVal, Chain);
329 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000330 MVT::i64, MVT::Other,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000331 TargetConst0,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000332 SDValue(Result_1,0));
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000333 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
334 MemOp[0] = LD->getMemOperand();
335 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
336 const SDValue Froms[] = { SDValue(LD, 0),
337 SDValue(LD, 1),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000338 SDValue(LD, 2) };
339 const SDValue Tos[] = { SDValue(Result_2, 0),
340 SDValue(Result_1, 1),
341 SDValue(Result_1, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000342 ReplaceUses(Froms, Tos, 3);
Justin Bognerec37a022016-05-12 21:46:18 +0000343 CurDAG->RemoveDeadNode(LD);
344 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000345 }
346
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000347 // Generate an indirect load.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000348 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
349 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000350 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
351 MVT::Other, Base, TargetConst0,
352 Chain);
353 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl,
354 MVT::i64, MVT::Other,
355 TargetConst0,
356 SDValue(Result_1,0));
357 // Add offset to base.
358 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
359 Base, TargetConstVal,
360 SDValue(Result_1, 1));
361 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
362 MemOp[0] = LD->getMemOperand();
363 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
364 const SDValue Froms[] = { SDValue(LD, 0),
365 SDValue(LD, 1),
366 SDValue(LD, 2) };
367 const SDValue Tos[] = { SDValue(Result_2, 0), // Load value.
368 SDValue(Result_3, 0), // New address.
369 SDValue(Result_1, 1) };
370 ReplaceUses(Froms, Tos, 3);
Justin Bognerec37a022016-05-12 21:46:18 +0000371 CurDAG->RemoveDeadNode(LD);
372 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000373}
374
375
Justin Bognerec37a022016-05-12 21:46:18 +0000376void HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000377 SDValue Chain = LD->getChain();
378 SDValue Base = LD->getBasePtr();
379 SDValue Offset = LD->getOffset();
380 SDNode *OffsetNode = Offset.getNode();
381 // Get the constant value.
382 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
383 EVT LoadedVT = LD->getMemoryVT();
384 unsigned Opcode = 0;
385
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000386 // Check for zero extended loads. Treat any-extend loads as zero extended
387 // loads.
388 ISD::LoadExtType ExtType = LD->getExtensionType();
389 bool IsZeroExt = (ExtType == ISD::ZEXTLOAD || ExtType == ISD::EXTLOAD);
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000390 bool HasVecOffset = false;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000391
392 // Figure out the opcode.
393 if (LoadedVT == MVT::i64) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000394 if (HII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000395 Opcode = Hexagon::L2_loadrd_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000396 else
Colin LeMahieu947cd702014-12-23 20:44:59 +0000397 Opcode = Hexagon::L2_loadrd_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000398 } else if (LoadedVT == MVT::i32) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000399 if (HII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000400 Opcode = Hexagon::L2_loadri_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000401 else
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000402 Opcode = Hexagon::L2_loadri_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000403 } else if (LoadedVT == MVT::i16) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000404 if (HII->isValidAutoIncImm(LoadedVT, Val))
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000405 Opcode = IsZeroExt ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000406 else
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000407 Opcode = IsZeroExt ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000408 } else if (LoadedVT == MVT::i8) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000409 if (HII->isValidAutoIncImm(LoadedVT, Val))
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000410 Opcode = IsZeroExt ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000411 else
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000412 Opcode = IsZeroExt ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000413 } else if (LoadedVT == MVT::v16i32 || LoadedVT == MVT::v8i64 ||
414 LoadedVT == MVT::v32i16 || LoadedVT == MVT::v64i8) {
415 HasVecOffset = true;
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000416 bool Aligned = isAlignedMemNode(LD);
417 if (HII->isValidAutoIncImm(LoadedVT, Val))
418 Opcode = Aligned ? Hexagon::V6_vL32b_pi : Hexagon::V6_vL32Ub_pi;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000419 else
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000420 Opcode = Aligned ? Hexagon::V6_vL32b_ai : Hexagon::V6_vL32Ub_ai;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000421 // 128B
422 } else if (LoadedVT == MVT::v32i32 || LoadedVT == MVT::v16i64 ||
423 LoadedVT == MVT::v64i16 || LoadedVT == MVT::v128i8) {
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000424 if (HST->useHVXOps()) {
425 bool Aligned = isAlignedMemNode(LD);
426 HasVecOffset = true;
427 if (HII->isValidAutoIncImm(LoadedVT, Val))
428 Opcode = Aligned ? Hexagon::V6_vL32b_pi_128B
429 : Hexagon::V6_vL32Ub_pi_128B;
430 else
431 Opcode = Aligned ? Hexagon::V6_vL32b_ai_128B
432 : Hexagon::V6_vL32Ub_ai_128B;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000433 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000434 } else
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000435 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000436
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000437 // For zero extended i64 loads, we need to add combine instructions.
Justin Bognerec37a022016-05-12 21:46:18 +0000438 if (LD->getValueType(0) == MVT::i64 && IsZeroExt) {
439 SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
440 return;
441 }
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000442 // Handle sign extended i64 loads.
Justin Bognerec37a022016-05-12 21:46:18 +0000443 if (LD->getValueType(0) == MVT::i64 && ExtType == ISD::SEXTLOAD) {
444 SelectIndexedLoadSignExtend64(LD, Opcode, dl);
445 return;
446 }
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000447
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000448 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000449 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000450 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
451 LD->getValueType(0),
452 MVT::i32, MVT::Other, Base,
453 TargetConstVal, Chain);
454 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
455 MemOp[0] = LD->getMemOperand();
456 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000457 if (HasVecOffset) {
458 const SDValue Froms[] = { SDValue(LD, 0),
459 SDValue(LD, 2)
460 };
461 const SDValue Tos[] = { SDValue(Result, 0),
462 SDValue(Result, 2)
463 };
464 ReplaceUses(Froms, Tos, 2);
465 } else {
466 const SDValue Froms[] = { SDValue(LD, 0),
467 SDValue(LD, 1),
468 SDValue(LD, 2)
469 };
470 const SDValue Tos[] = { SDValue(Result, 0),
471 SDValue(Result, 1),
472 SDValue(Result, 2)
473 };
474 ReplaceUses(Froms, Tos, 3);
475 }
Justin Bognerec37a022016-05-12 21:46:18 +0000476 CurDAG->RemoveDeadNode(LD);
477 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000478 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000479 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
480 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000481 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
482 LD->getValueType(0),
483 MVT::Other, Base, TargetConst0,
484 Chain);
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000485 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000486 Base, TargetConstVal,
487 SDValue(Result_1, 1));
488 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
489 MemOp[0] = LD->getMemOperand();
490 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
491 const SDValue Froms[] = { SDValue(LD, 0),
492 SDValue(LD, 1),
493 SDValue(LD, 2)
494 };
495 const SDValue Tos[] = { SDValue(Result_1, 0),
496 SDValue(Result_2, 0),
497 SDValue(Result_1, 1)
498 };
499 ReplaceUses(Froms, Tos, 3);
Justin Bognerec37a022016-05-12 21:46:18 +0000500 CurDAG->RemoveDeadNode(LD);
501 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000502 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000503}
504
505
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000506MachineSDNode *HexagonDAGToDAGISel::LoadInstrForLoadIntrinsic(SDNode *IntN) {
507 if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN)
508 return nullptr;
509
510 SDLoc dl(IntN);
511 unsigned IntNo = cast<ConstantSDNode>(IntN->getOperand(1))->getZExtValue();
512
513 static std::map<unsigned,unsigned> LoadPciMap = {
514 { Intrinsic::hexagon_circ_ldb, Hexagon::L2_loadrb_pci },
515 { Intrinsic::hexagon_circ_ldub, Hexagon::L2_loadrub_pci },
516 { Intrinsic::hexagon_circ_ldh, Hexagon::L2_loadrh_pci },
517 { Intrinsic::hexagon_circ_lduh, Hexagon::L2_loadruh_pci },
518 { Intrinsic::hexagon_circ_ldw, Hexagon::L2_loadri_pci },
519 { Intrinsic::hexagon_circ_ldd, Hexagon::L2_loadrd_pci },
520 };
521 auto FLC = LoadPciMap.find(IntNo);
522 if (FLC != LoadPciMap.end()) {
523 SDNode *Mod = CurDAG->getMachineNode(Hexagon::A2_tfrrcr, dl, MVT::i32,
524 IntN->getOperand(4));
525 EVT ValTy = (IntNo == Intrinsic::hexagon_circ_ldd) ? MVT::i64 : MVT::i32;
526 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
527 // Operands: { Base, Increment, Modifier, Chain }
528 auto Inc = cast<ConstantSDNode>(IntN->getOperand(5));
529 SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), dl, MVT::i32);
530 MachineSDNode *Res = CurDAG->getMachineNode(FLC->second, dl, RTys,
531 { IntN->getOperand(2), I, SDValue(Mod,0), IntN->getOperand(0) });
532 return Res;
533 }
534
535 static std::map<unsigned,unsigned> LoadPbrMap = {
536 { Intrinsic::hexagon_brev_ldb, Hexagon::L2_loadrb_pbr },
537 { Intrinsic::hexagon_brev_ldub, Hexagon::L2_loadrub_pbr },
538 { Intrinsic::hexagon_brev_ldh, Hexagon::L2_loadrh_pbr },
539 { Intrinsic::hexagon_brev_lduh, Hexagon::L2_loadruh_pbr },
540 { Intrinsic::hexagon_brev_ldw, Hexagon::L2_loadri_pbr },
541 { Intrinsic::hexagon_brev_ldd, Hexagon::L2_loadrd_pbr },
542 };
543 auto FLB = LoadPbrMap.find(IntNo);
544 if (FLB != LoadPbrMap.end()) {
545 SDNode *Mod = CurDAG->getMachineNode(Hexagon::A2_tfrrcr, dl, MVT::i32,
546 IntN->getOperand(4));
547 EVT ValTy = (IntNo == Intrinsic::hexagon_brev_ldd) ? MVT::i64 : MVT::i32;
548 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
549 // Operands: { Base, Modifier, Chain }
550 MachineSDNode *Res = CurDAG->getMachineNode(FLB->second, dl, RTys,
551 { IntN->getOperand(2), SDValue(Mod,0), IntN->getOperand(0) });
552 return Res;
553 }
554
555 return nullptr;
556}
557
558SDNode *HexagonDAGToDAGISel::StoreInstrForLoadIntrinsic(MachineSDNode *LoadN,
559 SDNode *IntN) {
560 // The "LoadN" is just a machine load instruction. The intrinsic also
561 // involves storing it. Generate an appropriate store to the location
562 // given in the intrinsic's operand(3).
563 uint64_t F = HII->get(LoadN->getMachineOpcode()).TSFlags;
564 unsigned SizeBits = (F >> HexagonII::MemAccessSizePos) &
565 HexagonII::MemAccesSizeMask;
566 unsigned Size = 1U << (SizeBits-1);
567
568 SDLoc dl(IntN);
569 MachinePointerInfo PI;
570 SDValue TS;
571 SDValue Loc = IntN->getOperand(3);
572
573 if (Size >= 4)
574 TS = CurDAG->getStore(SDValue(LoadN,2), dl, SDValue(LoadN, 0), Loc, PI,
575 false, false, Size);
576 else
577 TS = CurDAG->getTruncStore(SDValue(LoadN,2), dl, SDValue(LoadN,0), Loc, PI,
578 MVT::getIntegerVT(Size*8), false, false, Size);
Justin Bognerdcb7a822016-05-10 20:31:53 +0000579
580 SDNode *StoreN;
581 {
582 HandleSDNode Handle(TS);
583 SelectStore(TS.getNode());
584 StoreN = Handle.getValue().getNode();
585 }
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000586
587 // Load's results are { Loaded value, Updated pointer, Chain }
588 ReplaceUses(SDValue(IntN, 0), SDValue(LoadN, 1));
589 ReplaceUses(SDValue(IntN, 1), SDValue(StoreN, 0));
590 return StoreN;
591}
592
Justin Bognerec37a022016-05-12 21:46:18 +0000593bool HexagonDAGToDAGISel::tryLoadOfLoadIntrinsic(LoadSDNode *N) {
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000594 // The intrinsics for load circ/brev perform two operations:
595 // 1. Load a value V from the specified location, using the addressing
596 // mode corresponding to the intrinsic.
597 // 2. Store V into a specified location. This location is typically a
598 // local, temporary object.
599 // In many cases, the program using these intrinsics will immediately
600 // load V again from the local object. In those cases, when certain
601 // conditions are met, the last load can be removed.
602 // This function identifies and optimizes this pattern. If the pattern
603 // cannot be optimized, it returns nullptr, which will cause the load
604 // to be selected separately from the intrinsic (which will be handled
605 // in SelectIntrinsicWChain).
606
607 SDValue Ch = N->getOperand(0);
608 SDValue Loc = N->getOperand(1);
609
610 // Assume that the load and the intrinsic are connected directly with a
611 // chain:
612 // t1: i32,ch = int.load ..., ..., ..., Loc, ... // <-- C
613 // t2: i32,ch = load t1:1, Loc, ...
614 SDNode *C = Ch.getNode();
615
616 if (C->getOpcode() != ISD::INTRINSIC_W_CHAIN)
Justin Bognerec37a022016-05-12 21:46:18 +0000617 return false;
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000618
619 // The second load can only be eliminated if its extension type matches
620 // that of the load instruction corresponding to the intrinsic. The user
621 // can provide an address of an unsigned variable to store the result of
622 // a sign-extending intrinsic into (or the other way around).
623 ISD::LoadExtType IntExt;
624 switch (cast<ConstantSDNode>(C->getOperand(1))->getZExtValue()) {
625 case Intrinsic::hexagon_brev_ldub:
626 case Intrinsic::hexagon_brev_lduh:
627 case Intrinsic::hexagon_circ_ldub:
628 case Intrinsic::hexagon_circ_lduh:
629 IntExt = ISD::ZEXTLOAD;
630 break;
631 case Intrinsic::hexagon_brev_ldw:
632 case Intrinsic::hexagon_brev_ldd:
633 case Intrinsic::hexagon_circ_ldw:
634 case Intrinsic::hexagon_circ_ldd:
635 IntExt = ISD::NON_EXTLOAD;
636 break;
637 default:
638 IntExt = ISD::SEXTLOAD;
639 break;
640 }
641 if (N->getExtensionType() != IntExt)
Justin Bognerec37a022016-05-12 21:46:18 +0000642 return false;
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000643
644 // Make sure the target location for the loaded value in the load intrinsic
645 // is the location from which LD (or N) is loading.
646 if (C->getNumOperands() < 4 || Loc.getNode() != C->getOperand(3).getNode())
Justin Bognerec37a022016-05-12 21:46:18 +0000647 return false;
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000648
649 if (MachineSDNode *L = LoadInstrForLoadIntrinsic(C)) {
650 SDNode *S = StoreInstrForLoadIntrinsic(L, C);
651 SDValue F[] = { SDValue(N,0), SDValue(N,1), SDValue(C,0), SDValue(C,1) };
652 SDValue T[] = { SDValue(L,0), SDValue(S,0), SDValue(L,1), SDValue(S,0) };
653 ReplaceUses(F, T, array_lengthof(T));
654 // This transformation will leave the intrinsic dead. If it remains in
655 // the DAG, the selection code will see it again, but without the load,
656 // and it will generate a store that is normally required for it.
Krzysztof Parzyszek0f791f42016-05-13 18:48:15 +0000657 CurDAG->RemoveDeadNode(C);
Justin Bognerec37a022016-05-12 21:46:18 +0000658 return true;
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000659 }
660
Justin Bognerec37a022016-05-12 21:46:18 +0000661 return false;
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000662}
663
664
Justin Bognerec37a022016-05-12 21:46:18 +0000665void HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000666 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000667 LoadSDNode *LD = cast<LoadSDNode>(N);
668 ISD::MemIndexedMode AM = LD->getAddressingMode();
669
670 // Handle indexed loads.
Justin Bognerec37a022016-05-12 21:46:18 +0000671 if (AM != ISD::UNINDEXED) {
672 SelectIndexedLoad(LD, dl);
673 return;
674 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000675
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000676 // Handle patterns using circ/brev load intrinsics.
Justin Bognerec37a022016-05-12 21:46:18 +0000677 if (tryLoadOfLoadIntrinsic(LD))
678 return;
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +0000679
Justin Bognerec37a022016-05-12 21:46:18 +0000680 SelectCode(LD);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000681}
682
683
Justin Bognerec37a022016-05-12 21:46:18 +0000684void HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000685 SDValue Chain = ST->getChain();
686 SDValue Base = ST->getBasePtr();
687 SDValue Offset = ST->getOffset();
688 SDValue Value = ST->getValue();
689 SDNode *OffsetNode = Offset.getNode();
690 // Get the constant value.
691 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
692 EVT StoredVT = ST->getMemoryVT();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000693 EVT ValueVT = Value.getValueType();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000694
695 // Offset value must be within representable range
696 // and must have correct alignment properties.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000697 if (HII->isValidAutoIncImm(StoredVT, Val)) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000698 unsigned Opcode = 0;
699
700 // Figure out the post inc version of opcode.
Colin LeMahieu9a3cd3f2014-12-29 20:00:43 +0000701 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi;
702 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi;
703 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi;
Colin LeMahieu3d34afb2014-12-29 19:42:14 +0000704 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000705 else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 ||
706 StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8) {
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000707 if (isAlignedMemNode(ST))
708 Opcode = Hexagon::V6_vS32b_pi;
709 else
710 Opcode = Hexagon::V6_vS32Ub_pi;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000711 }
712 // 128B
713 else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 ||
714 StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8) {
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000715 if (HST->useHVXOps())
716 Opcode = isAlignedMemNode(ST) ? Hexagon::V6_vS32b_pi_128B
717 : Hexagon::V6_vS32Ub_pi_128B;
718 } else
719 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000720
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000721 if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) {
722 assert(StoredVT.getSizeInBits() < 64 && "Not a truncating store");
723 Value = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg,
724 dl, MVT::i32, Value);
725 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000726 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, dl, MVT::i32), Value,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000727 Chain};
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000728 // Build post increment store.
729 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +0000730 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000731 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
732 MemOp[0] = ST->getMemOperand();
733 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
734
735 ReplaceUses(ST, Result);
736 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
Justin Bognerdcb7a822016-05-10 20:31:53 +0000737 CurDAG->RemoveDeadNode(ST);
Justin Bognerec37a022016-05-12 21:46:18 +0000738 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000739 }
740
741 // Note: Order of operands matches the def of instruction:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000742 // def S2_storerd_io
743 // : STInst<(outs), (ins IntRegs:$base, imm:$offset, DoubleRegs:$src1), ...
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000744 // and it differs for POST_ST* for instance.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000745 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, dl, MVT::i32), Value,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000746 Chain};
747 unsigned Opcode = 0;
748
749 // Figure out the opcode.
Colin LeMahieubda31b42014-12-29 20:44:51 +0000750 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
751 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
752 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
753 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000754 else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 ||
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000755 StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8) {
756 if (isAlignedMemNode(ST))
757 Opcode = Hexagon::V6_vS32b_ai;
758 else
759 Opcode = Hexagon::V6_vS32Ub_ai;
760 }
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000761 // 128B
762 else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 ||
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +0000763 StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8) {
764 if (isAlignedMemNode(ST))
765 Opcode = Hexagon::V6_vS32b_ai_128B;
766 else
767 Opcode = Hexagon::V6_vS32Ub_ai_128B;
768 }
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000769 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000770
771 // Build regular store.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000772 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Michael Liaob53d8962013-04-19 22:22:57 +0000773 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000774 // Build splitted incriment instruction.
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000775 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000776 Base,
777 TargetConstVal,
778 SDValue(Result_1, 0));
779 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
780 MemOp[0] = ST->getMemOperand();
781 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
782
783 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
784 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
Justin Bognerdcb7a822016-05-10 20:31:53 +0000785 CurDAG->RemoveDeadNode(ST);
Justin Bognerec37a022016-05-12 21:46:18 +0000786 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000787}
788
Justin Bognerec37a022016-05-12 21:46:18 +0000789void HexagonDAGToDAGISel::SelectStore(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000790 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000791 StoreSDNode *ST = cast<StoreSDNode>(N);
792 ISD::MemIndexedMode AM = ST->getAddressingMode();
793
794 // Handle indexed stores.
795 if (AM != ISD::UNINDEXED) {
Justin Bognerec37a022016-05-12 21:46:18 +0000796 SelectIndexedStore(ST, dl);
797 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000798 }
Sirish Pandec92c3162012-05-03 16:18:50 +0000799
Justin Bognerec37a022016-05-12 21:46:18 +0000800 SelectCode(ST);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000801}
802
Justin Bognerec37a022016-05-12 21:46:18 +0000803void HexagonDAGToDAGISel::SelectMul(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000804 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000805
806 //
807 // %conv.i = sext i32 %tmp1 to i64
808 // %conv2.i = sext i32 %add to i64
809 // %mul.i = mul nsw i64 %conv2.i, %conv.i
810 //
811 // --- match with the following ---
812 //
813 // %mul.i = mpy (%tmp1, %add)
814 //
815
816 if (N->getValueType(0) == MVT::i64) {
817 // Shifting a i64 signed multiply.
818 SDValue MulOp0 = N->getOperand(0);
819 SDValue MulOp1 = N->getOperand(1);
820
821 SDValue OP0;
822 SDValue OP1;
823
824 // Handle sign_extend and sextload.
825 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
826 SDValue Sext0 = MulOp0.getOperand(0);
827 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Justin Bognerec37a022016-05-12 21:46:18 +0000828 SelectCode(N);
829 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000830 }
831
832 OP0 = Sext0;
833 } else if (MulOp0.getOpcode() == ISD::LOAD) {
834 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
835 if (LD->getMemoryVT() != MVT::i32 ||
836 LD->getExtensionType() != ISD::SEXTLOAD ||
837 LD->getAddressingMode() != ISD::UNINDEXED) {
Justin Bognerec37a022016-05-12 21:46:18 +0000838 SelectCode(N);
839 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000840 }
841
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000842 SDValue Chain = LD->getChain();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000843 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000844 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000845 MVT::Other,
846 LD->getBasePtr(), TargetConst0,
847 Chain), 0);
848 } else {
Justin Bognerec37a022016-05-12 21:46:18 +0000849 SelectCode(N);
850 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000851 }
852
853 // Same goes for the second operand.
854 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
855 SDValue Sext1 = MulOp1.getOperand(0);
856 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
Justin Bognerec37a022016-05-12 21:46:18 +0000857 SelectCode(N);
858 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000859 }
860
861 OP1 = Sext1;
862 } else if (MulOp1.getOpcode() == ISD::LOAD) {
863 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
864 if (LD->getMemoryVT() != MVT::i32 ||
865 LD->getExtensionType() != ISD::SEXTLOAD ||
866 LD->getAddressingMode() != ISD::UNINDEXED) {
Justin Bognerec37a022016-05-12 21:46:18 +0000867 SelectCode(N);
868 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000869 }
870
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000871 SDValue Chain = LD->getChain();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000872 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000873 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000874 MVT::Other,
875 LD->getBasePtr(), TargetConst0,
876 Chain), 0);
877 } else {
Justin Bognerec37a022016-05-12 21:46:18 +0000878 SelectCode(N);
879 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000880 }
881
882 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +0000883 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000884 OP0, OP1);
Justin Bognerec37a022016-05-12 21:46:18 +0000885 ReplaceNode(N, Result);
886 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000887 }
888
Justin Bognerec37a022016-05-12 21:46:18 +0000889 SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000890}
891
Justin Bognerec37a022016-05-12 21:46:18 +0000892void HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000893 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000894 if (N->getValueType(0) == MVT::i32) {
895 SDValue Shl_0 = N->getOperand(0);
896 SDValue Shl_1 = N->getOperand(1);
897 // RHS is const.
898 if (Shl_1.getOpcode() == ISD::Constant) {
899 if (Shl_0.getOpcode() == ISD::MUL) {
900 SDValue Mul_0 = Shl_0.getOperand(0); // Val
901 SDValue Mul_1 = Shl_0.getOperand(1); // Const
902 // RHS of mul is const.
903 if (Mul_1.getOpcode() == ISD::Constant) {
904 int32_t ShlConst =
905 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
906 int32_t MulConst =
907 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
908 int32_t ValConst = MulConst << ShlConst;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000909 SDValue Val = CurDAG->getTargetConstant(ValConst, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000910 MVT::i32);
911 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
912 if (isInt<9>(CN->getSExtValue())) {
913 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000914 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000915 MVT::i32, Mul_0, Val);
Justin Bognerec37a022016-05-12 21:46:18 +0000916 ReplaceNode(N, Result);
917 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000918 }
919
920 }
921 } else if (Shl_0.getOpcode() == ISD::SUB) {
922 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
923 SDValue Sub_1 = Shl_0.getOperand(1); // Val
924 if (Sub_0.getOpcode() == ISD::Constant) {
925 int32_t SubConst =
926 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
927 if (SubConst == 0) {
928 if (Sub_1.getOpcode() == ISD::SHL) {
929 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
930 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
931 if (Shl2_1.getOpcode() == ISD::Constant) {
932 int32_t ShlConst =
933 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
934 int32_t Shl2Const =
935 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
936 int32_t ValConst = 1 << (ShlConst+Shl2Const);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000937 SDValue Val = CurDAG->getTargetConstant(-ValConst, dl,
938 MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000939 if (ConstantSDNode *CN =
940 dyn_cast<ConstantSDNode>(Val.getNode()))
941 if (isInt<9>(CN->getSExtValue())) {
942 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000943 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000944 Shl2_0, Val);
Justin Bognerec37a022016-05-12 21:46:18 +0000945 ReplaceNode(N, Result);
946 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000947 }
948 }
949 }
950 }
951 }
952 }
953 }
954 }
Justin Bognerec37a022016-05-12 21:46:18 +0000955 SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000956}
957
958
959//
960// If there is an zero_extend followed an intrinsic in DAG (this means - the
961// result of the intrinsic is predicate); convert the zero_extend to
962// transfer instruction.
963//
964// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
965// converted into a MUX as predicate registers defined as 1 bit in the
966// compiler. Architecture defines them as 8-bit registers.
967// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
968//
Justin Bognerec37a022016-05-12 21:46:18 +0000969void HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000970 SDLoc dl(N);
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000971
972 SDValue Op0 = N->getOperand(0);
973 EVT OpVT = Op0.getValueType();
974 unsigned OpBW = OpVT.getSizeInBits();
975
976 // Special handling for zero-extending a vector of booleans.
977 if (OpVT.isVector() && OpVT.getVectorElementType() == MVT::i1 && OpBW <= 64) {
978 SDNode *Mask = CurDAG->getMachineNode(Hexagon::C2_mask, dl, MVT::i64, Op0);
979 unsigned NE = OpVT.getVectorNumElements();
980 EVT ExVT = N->getValueType(0);
981 unsigned ES = ExVT.getVectorElementType().getSizeInBits();
982 uint64_t MV = 0, Bit = 1;
983 for (unsigned i = 0; i < NE; ++i) {
984 MV |= Bit;
985 Bit <<= ES;
986 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000987 SDValue Ones = CurDAG->getTargetConstant(MV, dl, MVT::i64);
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000988 SDNode *OnesReg = CurDAG->getMachineNode(Hexagon::CONST64_Int_Real, dl,
989 MVT::i64, Ones);
990 if (ExVT.getSizeInBits() == 32) {
991 SDNode *And = CurDAG->getMachineNode(Hexagon::A2_andp, dl, MVT::i64,
992 SDValue(Mask,0), SDValue(OnesReg,0));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000993 SDValue SubR = CurDAG->getTargetConstant(Hexagon::subreg_loreg, dl,
994 MVT::i32);
Justin Bognerec37a022016-05-12 21:46:18 +0000995 ReplaceNode(N, CurDAG->getMachineNode(Hexagon::EXTRACT_SUBREG, dl, ExVT,
996 SDValue(And, 0), SubR));
997 return;
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000998 }
Justin Bognerec37a022016-05-12 21:46:18 +0000999 ReplaceNode(N,
1000 CurDAG->getMachineNode(Hexagon::A2_andp, dl, ExVT,
1001 SDValue(Mask, 0), SDValue(OnesReg, 0)));
1002 return;
Krzysztof Parzyszek42113342015-03-19 16:33:08 +00001003 }
1004
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001005 SDNode *IsIntrinsic = N->getOperand(0).getNode();
1006 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
1007 unsigned ID =
1008 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
1009 if (doesIntrinsicReturnPredicate(ID)) {
1010 // Now we need to differentiate target data types.
1011 if (N->getValueType(0) == MVT::i64) {
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001012 // Convert the zero_extend to Rs = Pd followed by A2_combinew(0,Rs).
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001013 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001014 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001015 MVT::i32,
1016 SDValue(IsIntrinsic, 0));
Colin LeMahieu4af437f2014-12-09 20:23:30 +00001017 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001018 MVT::i32,
1019 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +00001020 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001021 MVT::i64, MVT::Other,
1022 SDValue(Result_2, 0),
1023 SDValue(Result_1, 0));
Justin Bognerec37a022016-05-12 21:46:18 +00001024 ReplaceNode(N, Result_3);
1025 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001026 }
1027 if (N->getValueType(0) == MVT::i32) {
1028 // Convert the zero_extend to Rs = Pd
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001029 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001030 MVT::i32,
1031 SDValue(IsIntrinsic, 0));
Justin Bognerec37a022016-05-12 21:46:18 +00001032 ReplaceNode(N, RsPd);
1033 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001034 }
Craig Toppere55c5562012-02-07 02:50:20 +00001035 llvm_unreachable("Unexpected value type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001036 }
1037 }
Justin Bognerec37a022016-05-12 21:46:18 +00001038 SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001039}
1040
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +00001041
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001042//
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +00001043// Handling intrinsics for circular load and bitreverse load.
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +00001044//
Justin Bognerec37a022016-05-12 21:46:18 +00001045void HexagonDAGToDAGISel::SelectIntrinsicWChain(SDNode *N) {
1046 if (MachineSDNode *L = LoadInstrForLoadIntrinsic(N)) {
1047 StoreInstrForLoadIntrinsic(L, N);
Krzysztof Parzyszek0f791f42016-05-13 18:48:15 +00001048 CurDAG->RemoveDeadNode(N);
Justin Bognerec37a022016-05-12 21:46:18 +00001049 return;
1050 }
1051 SelectCode(N);
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +00001052}
1053
Justin Bognerec37a022016-05-12 21:46:18 +00001054void HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001055 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1056 unsigned Bits;
1057 switch (IID) {
1058 case Intrinsic::hexagon_S2_vsplatrb:
1059 Bits = 8;
1060 break;
1061 case Intrinsic::hexagon_S2_vsplatrh:
1062 Bits = 16;
1063 break;
1064 default:
Justin Bognerec37a022016-05-12 21:46:18 +00001065 SelectCode(N);
1066 return;
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001067 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001068
Krzysztof Parzyszeke60e5fe2016-05-12 17:21:40 +00001069 SDValue V = N->getOperand(1);
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001070 SDValue U;
1071 if (isValueExtension(V, Bits, U)) {
1072 SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
Krzysztof Parzyszeke60e5fe2016-05-12 17:21:40 +00001073 N->getOperand(0), U);
Justin Bognerd82025b2016-05-12 21:24:23 +00001074 ReplaceNode(N, R.getNode());
Justin Bognerec37a022016-05-12 21:46:18 +00001075 SelectCode(R.getNode());
1076 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001077 }
Justin Bognerec37a022016-05-12 21:46:18 +00001078 SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001079}
1080
Sirish Pande69295b82012-05-10 20:20:25 +00001081//
1082// Map floating point constant values.
1083//
Justin Bognerec37a022016-05-12 21:46:18 +00001084void HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001085 SDLoc dl(N);
Sirish Pande69295b82012-05-10 20:20:25 +00001086 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1087 APFloat APF = CN->getValueAPF();
1088 if (N->getValueType(0) == MVT::f32) {
Justin Bognerec37a022016-05-12 21:46:18 +00001089 ReplaceNode(
1090 N, CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
1091 CurDAG->getTargetConstantFP(
1092 APF.convertToFloat(), dl, MVT::f32)));
1093 return;
Sirish Pande69295b82012-05-10 20:20:25 +00001094 }
1095 else if (N->getValueType(0) == MVT::f64) {
Justin Bognerec37a022016-05-12 21:46:18 +00001096 ReplaceNode(
1097 N, CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
1098 CurDAG->getTargetConstantFP(
1099 APF.convertToDouble(), dl, MVT::f64)));
1100 return;
Sirish Pande69295b82012-05-10 20:20:25 +00001101 }
1102
Justin Bognerec37a022016-05-12 21:46:18 +00001103 SelectCode(N);
Sirish Pande69295b82012-05-10 20:20:25 +00001104}
1105
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001106//
1107// Map predicate true (encoded as -1 in LLVM) to a XOR.
1108//
Justin Bognerec37a022016-05-12 21:46:18 +00001109void HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001110 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001111 if (N->getValueType(0) == MVT::i1) {
Krzysztof Parzyszek36ccfa52015-03-18 19:07:53 +00001112 SDNode* Result = 0;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001113 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
Krzysztof Parzyszek7a9cd802015-03-18 18:50:06 +00001114 if (Val == -1) {
Krzysztof Parzyszek36ccfa52015-03-18 19:07:53 +00001115 Result = CurDAG->getMachineNode(Hexagon::TFR_PdTrue, dl, MVT::i1);
1116 } else if (Val == 0) {
1117 Result = CurDAG->getMachineNode(Hexagon::TFR_PdFalse, dl, MVT::i1);
1118 }
1119 if (Result) {
Justin Bognerec37a022016-05-12 21:46:18 +00001120 ReplaceNode(N, Result);
1121 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001122 }
1123 }
1124
Justin Bognerec37a022016-05-12 21:46:18 +00001125 SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001126}
1127
1128
1129//
1130// Map add followed by a asr -> asr +=.
1131//
Justin Bognerec37a022016-05-12 21:46:18 +00001132void HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001133 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001134 if (N->getValueType(0) != MVT::i32) {
Justin Bognerec37a022016-05-12 21:46:18 +00001135 SelectCode(N);
1136 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001137 }
1138 // Identify nodes of the form: add(asr(...)).
1139 SDNode* Src1 = N->getOperand(0).getNode();
1140 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1141 || Src1->getValueType(0) != MVT::i32) {
Justin Bognerec37a022016-05-12 21:46:18 +00001142 SelectCode(N);
1143 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001144 }
1145
1146 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1147 // Rd and Rd' are assigned to the same register
Colin LeMahieu0f850bd2014-12-19 20:29:29 +00001148 SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001149 N->getOperand(1),
1150 Src1->getOperand(0),
1151 Src1->getOperand(1));
Justin Bognerec37a022016-05-12 21:46:18 +00001152 ReplaceNode(N, Result);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001153}
1154
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001155//
1156// Map the following, where possible.
1157// AND/FABS -> clrbit
1158// OR -> setbit
1159// XOR/FNEG ->toggle_bit.
1160//
Justin Bognerec37a022016-05-12 21:46:18 +00001161void HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001162 SDLoc dl(N);
1163 EVT ValueVT = N->getValueType(0);
1164
1165 // We handle only 32 and 64-bit bit ops.
1166 if (!(ValueVT == MVT::i32 || ValueVT == MVT::i64 ||
Justin Bognerec37a022016-05-12 21:46:18 +00001167 ValueVT == MVT::f32 || ValueVT == MVT::f64)) {
1168 SelectCode(N);
1169 return;
1170 }
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001171
1172 // We handly only fabs and fneg for V5.
1173 unsigned Opc = N->getOpcode();
Justin Bognerec37a022016-05-12 21:46:18 +00001174 if ((Opc == ISD::FABS || Opc == ISD::FNEG) && !HST->hasV5TOps()) {
1175 SelectCode(N);
1176 return;
1177 }
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001178
1179 int64_t Val = 0;
1180 if (Opc != ISD::FABS && Opc != ISD::FNEG) {
1181 if (N->getOperand(1).getOpcode() == ISD::Constant)
1182 Val = cast<ConstantSDNode>((N)->getOperand(1))->getSExtValue();
Justin Bognerec37a022016-05-12 21:46:18 +00001183 else {
1184 SelectCode(N);
1185 return;
1186 }
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001187 }
1188
1189 if (Opc == ISD::AND) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001190 // Check if this is a bit-clearing AND, if not select code the usual way.
1191 if ((ValueVT == MVT::i32 && isPowerOf2_32(~Val)) ||
1192 (ValueVT == MVT::i64 && isPowerOf2_64(~Val)))
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001193 Val = ~Val;
Justin Bognerec37a022016-05-12 21:46:18 +00001194 else {
1195 SelectCode(N);
1196 return;
1197 }
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001198 }
1199
1200 // If OR or AND is being fed by shl, srl and, sra don't do this change,
1201 // because Hexagon provide |= &= on shl, srl, and sra.
1202 // Traverse the DAG to see if there is shl, srl and sra.
1203 if (Opc == ISD::OR || Opc == ISD::AND) {
1204 switch (N->getOperand(0)->getOpcode()) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001205 default:
1206 break;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001207 case ISD::SRA:
1208 case ISD::SRL:
1209 case ISD::SHL:
Justin Bognerec37a022016-05-12 21:46:18 +00001210 SelectCode(N);
1211 return;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001212 }
1213 }
1214
1215 // Make sure it's power of 2.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001216 unsigned BitPos = 0;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001217 if (Opc != ISD::FABS && Opc != ISD::FNEG) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001218 if ((ValueVT == MVT::i32 && !isPowerOf2_32(Val)) ||
Justin Bognerec37a022016-05-12 21:46:18 +00001219 (ValueVT == MVT::i64 && !isPowerOf2_64(Val))) {
1220 SelectCode(N);
1221 return;
1222 }
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001223
1224 // Get the bit position.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001225 BitPos = countTrailingZeros(uint64_t(Val));
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001226 } else {
1227 // For fabs and fneg, it's always the 31st bit.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001228 BitPos = 31;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001229 }
1230
1231 unsigned BitOpc = 0;
1232 // Set the right opcode for bitwise operations.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001233 switch (Opc) {
1234 default:
1235 llvm_unreachable("Only bit-wise/abs/neg operations are allowed.");
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001236 case ISD::AND:
1237 case ISD::FABS:
1238 BitOpc = Hexagon::S2_clrbit_i;
1239 break;
1240 case ISD::OR:
1241 BitOpc = Hexagon::S2_setbit_i;
1242 break;
1243 case ISD::XOR:
1244 case ISD::FNEG:
1245 BitOpc = Hexagon::S2_togglebit_i;
1246 break;
1247 }
1248
1249 SDNode *Result;
1250 // Get the right SDVal for the opcode.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001251 SDValue SDVal = CurDAG->getTargetConstant(BitPos, dl, MVT::i32);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001252
1253 if (ValueVT == MVT::i32 || ValueVT == MVT::f32) {
1254 Result = CurDAG->getMachineNode(BitOpc, dl, ValueVT,
1255 N->getOperand(0), SDVal);
1256 } else {
1257 // 64-bit gymnastic to use REG_SEQUENCE. But it's worth it.
1258 EVT SubValueVT;
1259 if (ValueVT == MVT::i64)
1260 SubValueVT = MVT::i32;
1261 else
1262 SubValueVT = MVT::f32;
1263
1264 SDNode *Reg = N->getOperand(0).getNode();
1265 SDValue RegClass = CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001266 dl, MVT::i64);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001267
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001268 SDValue SubregHiIdx = CurDAG->getTargetConstant(Hexagon::subreg_hireg, dl,
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001269 MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001270 SDValue SubregLoIdx = CurDAG->getTargetConstant(Hexagon::subreg_loreg, dl,
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001271 MVT::i32);
1272
1273 SDValue SubregHI = CurDAG->getTargetExtractSubreg(Hexagon::subreg_hireg, dl,
1274 MVT::i32, SDValue(Reg, 0));
1275
1276 SDValue SubregLO = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg, dl,
1277 MVT::i32, SDValue(Reg, 0));
1278
1279 // Clear/set/toggle hi or lo registers depending on the bit position.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001280 if (SubValueVT != MVT::f32 && BitPos < 32) {
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001281 SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
1282 SubregLO, SDVal);
1283 const SDValue Ops[] = { RegClass, SubregHI, SubregHiIdx,
1284 SDValue(Result0, 0), SubregLoIdx };
1285 Result = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
1286 dl, ValueVT, Ops);
1287 } else {
1288 if (Opc != ISD::FABS && Opc != ISD::FNEG)
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001289 SDVal = CurDAG->getTargetConstant(BitPos-32, dl, MVT::i32);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001290 SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
1291 SubregHI, SDVal);
1292 const SDValue Ops[] = { RegClass, SDValue(Result0, 0), SubregHiIdx,
1293 SubregLO, SubregLoIdx };
1294 Result = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
1295 dl, ValueVT, Ops);
1296 }
1297 }
1298
Justin Bognerec37a022016-05-12 21:46:18 +00001299 ReplaceNode(N, Result);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001300}
1301
1302
Justin Bognerec37a022016-05-12 21:46:18 +00001303void HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) {
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001304 MachineFrameInfo *MFI = MF->getFrameInfo();
1305 const HexagonFrameLowering *HFI = HST->getFrameLowering();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001306 int FX = cast<FrameIndexSDNode>(N)->getIndex();
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001307 unsigned StkA = HFI->getStackAlignment();
1308 unsigned MaxA = MFI->getMaxAlignment();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001309 SDValue FI = CurDAG->getTargetFrameIndex(FX, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001310 SDLoc DL(N);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001311 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001312 SDNode *R = 0;
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001313
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001314 // Use TFR_FI when:
1315 // - the object is fixed, or
1316 // - there are no objects with higher-than-default alignment, or
1317 // - there are no dynamically allocated objects.
1318 // Otherwise, use TFR_FIA.
1319 if (FX < 0 || MaxA <= StkA || !MFI->hasVarSizedObjects()) {
1320 R = CurDAG->getMachineNode(Hexagon::TFR_FI, DL, MVT::i32, FI, Zero);
1321 } else {
1322 auto &HMFI = *MF->getInfo<HexagonMachineFunctionInfo>();
1323 unsigned AR = HMFI.getStackAlignBaseVReg();
1324 SDValue CH = CurDAG->getEntryNode();
1325 SDValue Ops[] = { CurDAG->getCopyFromReg(CH, DL, AR, MVT::i32), FI, Zero };
1326 R = CurDAG->getMachineNode(Hexagon::TFR_FIA, DL, MVT::i32, Ops);
1327 }
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001328
1329 if (N->getHasDebugValue())
1330 CurDAG->TransferDbgValues(SDValue(N, 0), SDValue(R, 0));
Justin Bognerec37a022016-05-12 21:46:18 +00001331 ReplaceNode(N, R);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001332}
1333
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001334
Justin Bognerec37a022016-05-12 21:46:18 +00001335void HexagonDAGToDAGISel::Select(SDNode *N) {
Tim Northover31d093c2013-09-22 08:21:56 +00001336 if (N->isMachineOpcode()) {
1337 N->setNodeId(-1);
Justin Bognerec37a022016-05-12 21:46:18 +00001338 return; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00001339 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001340
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001341 switch (N->getOpcode()) {
1342 case ISD::Constant:
Justin Bognerec37a022016-05-12 21:46:18 +00001343 SelectConstant(N);
1344 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001345
Sirish Pande69295b82012-05-10 20:20:25 +00001346 case ISD::ConstantFP:
Justin Bognerec37a022016-05-12 21:46:18 +00001347 SelectConstantFP(N);
1348 return;
Sirish Pande69295b82012-05-10 20:20:25 +00001349
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001350 case ISD::FrameIndex:
Justin Bognerec37a022016-05-12 21:46:18 +00001351 SelectFrameIndex(N);
1352 return;
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001353
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001354 case ISD::ADD:
Justin Bognerec37a022016-05-12 21:46:18 +00001355 SelectAdd(N);
1356 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001357
1358 case ISD::SHL:
Justin Bognerec37a022016-05-12 21:46:18 +00001359 SelectSHL(N);
1360 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001361
1362 case ISD::LOAD:
Justin Bognerec37a022016-05-12 21:46:18 +00001363 SelectLoad(N);
1364 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001365
1366 case ISD::STORE:
Justin Bognerec37a022016-05-12 21:46:18 +00001367 SelectStore(N);
1368 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001369
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001370 case ISD::MUL:
Justin Bognerec37a022016-05-12 21:46:18 +00001371 SelectMul(N);
1372 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001373
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001374 case ISD::AND:
1375 case ISD::OR:
1376 case ISD::XOR:
1377 case ISD::FABS:
1378 case ISD::FNEG:
Justin Bognerec37a022016-05-12 21:46:18 +00001379 SelectBitOp(N);
1380 return;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001381
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001382 case ISD::ZERO_EXTEND:
Justin Bognerec37a022016-05-12 21:46:18 +00001383 SelectZeroExtend(N);
1384 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001385
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +00001386 case ISD::INTRINSIC_W_CHAIN:
Justin Bognerec37a022016-05-12 21:46:18 +00001387 SelectIntrinsicWChain(N);
1388 return;
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +00001389
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001390 case ISD::INTRINSIC_WO_CHAIN:
Justin Bognerec37a022016-05-12 21:46:18 +00001391 SelectIntrinsicWOChain(N);
1392 return;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001393 }
1394
Justin Bognerec37a022016-05-12 21:46:18 +00001395 SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001396}
1397
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001398bool HexagonDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00001399SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001400 std::vector<SDValue> &OutOps) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001401 SDValue Inp = Op, Res;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001402
Daniel Sanders60f1db02015-03-13 12:45:09 +00001403 switch (ConstraintID) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001404 default:
1405 return true;
Daniel Sanders49f643c2015-03-17 14:37:39 +00001406 case InlineAsm::Constraint_i:
1407 case InlineAsm::Constraint_o: // Offsetable.
1408 case InlineAsm::Constraint_v: // Not offsetable.
1409 case InlineAsm::Constraint_m: // Memory.
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001410 if (SelectAddrFI(Inp, Res))
1411 OutOps.push_back(Res);
1412 else
1413 OutOps.push_back(Inp);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001414 break;
1415 }
1416
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001417 OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));
Jyotsna Vermad9225242013-02-13 21:38:46 +00001418 return false;
1419}
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001420
Colin LeMahieu79ec0652015-06-12 19:57:32 +00001421
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001422void HexagonDAGToDAGISel::PreprocessISelDAG() {
1423 SelectionDAG &DAG = *CurDAG;
1424 std::vector<SDNode*> Nodes;
Pete Cooper7e64ef02015-07-14 23:43:29 +00001425 for (SDNode &Node : DAG.allnodes())
1426 Nodes.push_back(&Node);
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001427
1428 // Simplify: (or (select c x 0) z) -> (select c (or x z) z)
1429 // (or (select c 0 y) z) -> (select c z (or y z))
1430 // This may not be the right thing for all targets, so do it here.
1431 for (auto I: Nodes) {
1432 if (I->getOpcode() != ISD::OR)
1433 continue;
1434
1435 auto IsZero = [] (const SDValue &V) -> bool {
1436 if (ConstantSDNode *SC = dyn_cast<ConstantSDNode>(V.getNode()))
1437 return SC->isNullValue();
1438 return false;
1439 };
1440 auto IsSelect0 = [IsZero] (const SDValue &Op) -> bool {
1441 if (Op.getOpcode() != ISD::SELECT)
1442 return false;
Krzysztof Parzyszek7d5b4db2016-02-12 17:01:51 +00001443 return IsZero(Op.getOperand(1)) || IsZero(Op.getOperand(2));
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001444 };
1445
1446 SDValue N0 = I->getOperand(0), N1 = I->getOperand(1);
1447 EVT VT = I->getValueType(0);
1448 bool SelN0 = IsSelect0(N0);
1449 SDValue SOp = SelN0 ? N0 : N1;
1450 SDValue VOp = SelN0 ? N1 : N0;
1451
1452 if (SOp.getOpcode() == ISD::SELECT && SOp.getNode()->hasOneUse()) {
1453 SDValue SC = SOp.getOperand(0);
1454 SDValue SX = SOp.getOperand(1);
1455 SDValue SY = SOp.getOperand(2);
1456 SDLoc DLS = SOp;
1457 if (IsZero(SY)) {
1458 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SX, VOp);
1459 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, NewOr, VOp);
1460 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1461 } else if (IsZero(SX)) {
1462 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SY, VOp);
1463 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, VOp, NewOr);
1464 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1465 }
1466 }
1467 }
1468}
1469
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001470void HexagonDAGToDAGISel::EmitFunctionEntryCode() {
1471 auto &HST = static_cast<const HexagonSubtarget&>(MF->getSubtarget());
1472 auto &HFI = *HST.getFrameLowering();
1473 if (!HFI.needsAligna(*MF))
1474 return;
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001475
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001476 MachineFrameInfo *MFI = MF->getFrameInfo();
Duncan P. N. Exon Smitha72c6e22015-10-20 00:46:39 +00001477 MachineBasicBlock *EntryBB = &MF->front();
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001478 unsigned AR = FuncInfo->CreateReg(MVT::i32);
1479 unsigned MaxA = MFI->getMaxAlignment();
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001480 BuildMI(EntryBB, DebugLoc(), HII->get(Hexagon::ALIGNA), AR)
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001481 .addImm(MaxA);
1482 MF->getInfo<HexagonMachineFunctionInfo>()->setStackAlignBaseVReg(AR);
1483}
1484
1485// Match a frame index that can be used in an addressing mode.
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001486bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) {
1487 if (N.getOpcode() != ISD::FrameIndex)
1488 return false;
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001489 auto &HFI = *HST->getFrameLowering();
1490 MachineFrameInfo *MFI = MF->getFrameInfo();
1491 int FX = cast<FrameIndexSDNode>(N)->getIndex();
1492 if (!MFI->isFixedObjectIndex(FX) && HFI.needsAligna(*MF))
1493 return false;
1494 R = CurDAG->getTargetFrameIndex(FX, MVT::i32);
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001495 return true;
1496}
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001497
Colin LeMahieu987b0942015-02-04 20:38:01 +00001498inline bool HexagonDAGToDAGISel::SelectAddrGA(SDValue &N, SDValue &R) {
1499 return SelectGlobalAddress(N, R, false);
1500}
1501
Colin LeMahieu51491352015-02-04 22:36:28 +00001502inline bool HexagonDAGToDAGISel::SelectAddrGP(SDValue &N, SDValue &R) {
1503 return SelectGlobalAddress(N, R, true);
1504}
1505
Colin LeMahieu987b0942015-02-04 20:38:01 +00001506bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
1507 bool UseGP) {
1508 switch (N.getOpcode()) {
1509 case ISD::ADD: {
1510 SDValue N0 = N.getOperand(0);
1511 SDValue N1 = N.getOperand(1);
1512 unsigned GAOpc = N0.getOpcode();
1513 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1514 return false;
1515 if (!UseGP && GAOpc != HexagonISD::CONST32)
1516 return false;
1517 if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) {
1518 SDValue Addr = N0.getOperand(0);
1519 if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Addr)) {
1520 if (GA->getOpcode() == ISD::TargetGlobalAddress) {
1521 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1522 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),
1523 N.getValueType(), NewOff);
1524 return true;
1525 }
1526 }
1527 }
1528 break;
1529 }
1530 case HexagonISD::CONST32:
1531 // The operand(0) of CONST32 is TargetGlobalAddress, which is what we
1532 // want in the instruction.
1533 if (!UseGP)
1534 R = N.getOperand(0);
1535 return !UseGP;
1536 case HexagonISD::CONST32_GP:
1537 if (UseGP)
1538 R = N.getOperand(0);
1539 return UseGP;
1540 default:
1541 return false;
1542 }
1543
1544 return false;
1545}
1546
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001547bool HexagonDAGToDAGISel::isValueExtension(const SDValue &Val,
1548 unsigned FromBits, SDValue &Src) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001549 unsigned Opc = Val.getOpcode();
1550 switch (Opc) {
1551 case ISD::SIGN_EXTEND:
1552 case ISD::ZERO_EXTEND:
1553 case ISD::ANY_EXTEND: {
1554 SDValue const &Op0 = Val.getOperand(0);
1555 EVT T = Op0.getValueType();
1556 if (T.isInteger() && T.getSizeInBits() == FromBits) {
1557 Src = Op0;
1558 return true;
1559 }
1560 break;
1561 }
1562 case ISD::SIGN_EXTEND_INREG:
1563 case ISD::AssertSext:
1564 case ISD::AssertZext:
1565 if (Val.getOperand(0).getValueType().isInteger()) {
1566 VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
1567 if (T->getVT().getSizeInBits() == FromBits) {
1568 Src = Val.getOperand(0);
1569 return true;
1570 }
1571 }
1572 break;
1573 case ISD::AND: {
1574 // Check if this is an AND with "FromBits" of lower bits set to 1.
1575 uint64_t FromMask = (1 << FromBits) - 1;
1576 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1577 if (C->getZExtValue() == FromMask) {
1578 Src = Val.getOperand(1);
1579 return true;
1580 }
1581 }
1582 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1583 if (C->getZExtValue() == FromMask) {
1584 Src = Val.getOperand(0);
1585 return true;
1586 }
1587 }
1588 break;
1589 }
1590 case ISD::OR:
1591 case ISD::XOR: {
1592 // OR/XOR with the lower "FromBits" bits set to 0.
1593 uint64_t FromMask = (1 << FromBits) - 1;
1594 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1595 if ((C->getZExtValue() & FromMask) == 0) {
1596 Src = Val.getOperand(1);
1597 return true;
1598 }
1599 }
1600 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1601 if ((C->getZExtValue() & FromMask) == 0) {
1602 Src = Val.getOperand(0);
1603 return true;
1604 }
1605 }
1606 }
1607 default:
1608 break;
1609 }
1610 return false;
1611}
Krzysztof Parzyszek2d65ea72016-03-28 15:43:03 +00001612
1613bool HexagonDAGToDAGISel::isAlignedMemNode(const MemSDNode *N) const {
1614 return N->getAlignment() >= N->getMemoryVT().getStoreSize();
1615}