blob: a0da945e75727ad7990ed0807916deb0c4cb7feb [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 Parzyszeka29622a2015-03-12 16:44:50 +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 Parzyszeka29622a2015-03-12 16:44:50 +000087 SDNode *SelectFrameIndex(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000088 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
89 /// inline asm expressions.
Craig Topper906c2cd2014-04-29 07:58:16 +000090 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
Daniel Sanders60f1db02015-03-13 12:45:09 +000091 unsigned ConstraintID,
Craig Topper906c2cd2014-04-29 07:58:16 +000092 std::vector<SDValue> &OutOps) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000093 SDNode *SelectLoad(SDNode *N);
Andrew Trickef9de2a2013-05-25 02:42:55 +000094 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl);
95 SDNode *SelectIndexedLoad(LoadSDNode *LD, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000096 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +000097 SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000098 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +000099 SDLoc dl);
100 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, SDLoc dl);
101 SDNode *SelectIndexedStore(StoreSDNode *ST, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000102 SDNode *SelectStore(SDNode *N);
103 SDNode *SelectSHL(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000104 SDNode *SelectMul(SDNode *N);
105 SDNode *SelectZeroExtend(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000106 SDNode *SelectIntrinsicWChain(SDNode *N);
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +0000107 SDNode *SelectIntrinsicWOChain(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000108 SDNode *SelectConstant(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000109 SDNode *SelectConstantFP(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000110 SDNode *SelectAdd(SDNode *N);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +0000111 SDNode *SelectBitOp(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000112
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000113 // XformMskToBitPosU5Imm - Returns the bit position which
114 // the single bit 32 bit mask represents.
115 // Used in Clr and Set bit immediate memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000116 SDValue XformMskToBitPosU5Imm(uint32_t Imm, SDLoc DL) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000117 int32_t bitPos;
118 bitPos = Log2_32(Imm);
119 assert(bitPos >= 0 && bitPos < 32 &&
120 "Constant out of range for 32 BitPos Memops");
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000121 return CurDAG->getTargetConstant(bitPos, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000122 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000123
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000124 // XformMskToBitPosU4Imm - Returns the bit position which the single-bit
125 // 16 bit mask represents. Used in Clr and Set bit immediate memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000126 SDValue XformMskToBitPosU4Imm(uint16_t Imm, SDLoc DL) {
127 return XformMskToBitPosU5Imm(Imm, DL);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000128 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000129
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000130 // XformMskToBitPosU3Imm - Returns the bit position which the single-bit
131 // 8 bit mask represents. Used in Clr and Set bit immediate memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000132 SDValue XformMskToBitPosU3Imm(uint8_t Imm, SDLoc DL) {
133 return XformMskToBitPosU5Imm(Imm, DL);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000134 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000135
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000136 // Return true if there is exactly one bit set in V, i.e., if V is one of the
137 // following integers: 2^0, 2^1, ..., 2^31.
138 bool ImmIsSingleBit(uint32_t v) const {
139 return isPowerOf2_32(v);
140 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000141
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000142 // XformM5ToU5Imm - Return a target constant with the specified value, of
143 // type i32 where the negative literal is transformed into a positive literal
144 // for use in -= memops.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000145 inline SDValue XformM5ToU5Imm(signed Imm, SDLoc DL) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000146 assert((Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
147 return CurDAG->getTargetConstant(-Imm, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000148 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000149
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000150 // XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
151 // [1..128], used in cmpb.gtu instructions.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000152 inline SDValue XformU7ToU7M1Imm(signed Imm, SDLoc DL) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000153 assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op");
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000154 return CurDAG->getTargetConstant(Imm - 1, DL, MVT::i8);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000155 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000156
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000157 // XformS8ToS8M1Imm - Return a target constant decremented by 1.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000158 inline SDValue XformSToSM1Imm(signed Imm, SDLoc DL) {
159 return CurDAG->getTargetConstant(Imm - 1, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000160 }
Jyotsna Verma60316252013-02-05 19:20:45 +0000161
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000162 // XformU8ToU8M1Imm - Return a target constant decremented by 1.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000163 inline SDValue XformUToUM1Imm(unsigned Imm, SDLoc DL) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000164 assert((Imm >= 1) && "Cannot decrement unsigned int less than 1");
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000165 return CurDAG->getTargetConstant(Imm - 1, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000166 }
Jyotsna Verma89c84822013-04-23 19:15:55 +0000167
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000168 // XformSToSM2Imm - Return a target constant decremented by 2.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000169 inline SDValue XformSToSM2Imm(unsigned Imm, SDLoc DL) {
170 return CurDAG->getTargetConstant(Imm - 2, 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 // XformSToSM3Imm - Return a target constant decremented by 3.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000174 inline SDValue XformSToSM3Imm(unsigned Imm, SDLoc DL) {
175 return CurDAG->getTargetConstant(Imm - 3, DL, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000176 }
Colin LeMahieu19ed07c2015-01-28 18:29:11 +0000177
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000178 // Include the pieces autogenerated from the target description.
179 #include "HexagonGenDAGISel.inc"
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +0000180
181private:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000182 bool isValueExtension(const SDValue &Val, unsigned FromBits, SDValue &Src);
183}; // end HexagonDAGToDAGISel
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000184} // end anonymous namespace
185
186
187/// createHexagonISelDag - This pass converts a legalized DAG into a
188/// Hexagon-specific DAG, ready for instruction scheduling.
189///
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000190namespace llvm {
191FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM,
192 CodeGenOpt::Level OptLevel) {
Jyotsna Vermad9225242013-02-13 21:38:46 +0000193 return new HexagonDAGToDAGISel(TM, OptLevel);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000194}
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000195}
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000196
Jyotsna Vermad9225242013-02-13 21:38:46 +0000197static void initializePassOnce(PassRegistry &Registry) {
198 const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection";
199 PassInfo *PI = new PassInfo(Name, "hexagon-isel",
Craig Topper062a2ba2014-04-25 05:30:21 +0000200 &SelectionDAGISel::ID, nullptr, false, false);
Jyotsna Vermad9225242013-02-13 21:38:46 +0000201 Registry.registerPass(*PI, true);
202}
203
204void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
205 CALL_ONCE_INITIALIZATION(initializePassOnce)
206}
207
208
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000209// Intrinsics that return a a predicate.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000210static bool doesIntrinsicReturnPredicate(unsigned ID) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000211 switch (ID) {
212 default:
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000213 return false;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000214 case Intrinsic::hexagon_C2_cmpeq:
215 case Intrinsic::hexagon_C2_cmpgt:
216 case Intrinsic::hexagon_C2_cmpgtu:
217 case Intrinsic::hexagon_C2_cmpgtup:
218 case Intrinsic::hexagon_C2_cmpgtp:
219 case Intrinsic::hexagon_C2_cmpeqp:
220 case Intrinsic::hexagon_C2_bitsset:
221 case Intrinsic::hexagon_C2_bitsclr:
222 case Intrinsic::hexagon_C2_cmpeqi:
223 case Intrinsic::hexagon_C2_cmpgti:
224 case Intrinsic::hexagon_C2_cmpgtui:
225 case Intrinsic::hexagon_C2_cmpgei:
226 case Intrinsic::hexagon_C2_cmpgeui:
227 case Intrinsic::hexagon_C2_cmplt:
228 case Intrinsic::hexagon_C2_cmpltu:
229 case Intrinsic::hexagon_C2_bitsclri:
230 case Intrinsic::hexagon_C2_and:
231 case Intrinsic::hexagon_C2_or:
232 case Intrinsic::hexagon_C2_xor:
233 case Intrinsic::hexagon_C2_andn:
234 case Intrinsic::hexagon_C2_not:
235 case Intrinsic::hexagon_C2_orn:
236 case Intrinsic::hexagon_C2_pxfer_map:
237 case Intrinsic::hexagon_C2_any8:
238 case Intrinsic::hexagon_C2_all8:
239 case Intrinsic::hexagon_A2_vcmpbeq:
240 case Intrinsic::hexagon_A2_vcmpbgtu:
241 case Intrinsic::hexagon_A2_vcmpheq:
242 case Intrinsic::hexagon_A2_vcmphgt:
243 case Intrinsic::hexagon_A2_vcmphgtu:
244 case Intrinsic::hexagon_A2_vcmpweq:
245 case Intrinsic::hexagon_A2_vcmpwgt:
246 case Intrinsic::hexagon_A2_vcmpwgtu:
247 case Intrinsic::hexagon_C2_tfrrp:
248 case Intrinsic::hexagon_S2_tstbit_i:
249 case Intrinsic::hexagon_S2_tstbit_r:
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000250 return true;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000251 }
252}
253
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000254SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
255 unsigned Opcode,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000256 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000257 SDValue Chain = LD->getChain();
258 EVT LoadedVT = LD->getMemoryVT();
259 SDValue Base = LD->getBasePtr();
260 SDValue Offset = LD->getOffset();
261 SDNode *OffsetNode = Offset.getNode();
262 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
Bill Wendling4a7a4082013-06-07 06:19:56 +0000263
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000264 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000265 SDValue TargetConst = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000266 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
267 MVT::Other, Base, TargetConst,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000268 Chain);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000269 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
270 SDValue(Result_1, 0));
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000271 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
272 MemOp[0] = LD->getMemOperand();
273 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
274 const SDValue Froms[] = { SDValue(LD, 0),
275 SDValue(LD, 1),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000276 SDValue(LD, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000277 const SDValue Tos[] = { SDValue(Result_2, 0),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000278 SDValue(Result_1, 1),
279 SDValue(Result_1, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000280 ReplaceUses(Froms, Tos, 3);
281 return Result_2;
282 }
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000283
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000284 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
285 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000286 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other,
287 Base, TargetConst0, Chain);
288 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
289 SDValue(Result_1, 0));
290 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
291 Base, TargetConstVal,
292 SDValue(Result_1, 1));
293 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
294 MemOp[0] = LD->getMemOperand();
295 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
296 const SDValue Froms[] = { SDValue(LD, 0),
297 SDValue(LD, 1),
298 SDValue(LD, 2) };
299 const SDValue Tos[] = { SDValue(Result_2, 0),
300 SDValue(Result_3, 0),
301 SDValue(Result_1, 1) };
302 ReplaceUses(Froms, Tos, 3);
303 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000304}
305
306
307SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
308 unsigned Opcode,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000309 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000310 SDValue Chain = LD->getChain();
311 EVT LoadedVT = LD->getMemoryVT();
312 SDValue Base = LD->getBasePtr();
313 SDValue Offset = LD->getOffset();
314 SDNode *OffsetNode = Offset.getNode();
315 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
Bill Wendling4a7a4082013-06-07 06:19:56 +0000316
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000317 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000318 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
319 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000320 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000321 MVT::i32, MVT::Other, Base,
322 TargetConstVal, Chain);
323 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000324 MVT::i64, MVT::Other,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000325 TargetConst0,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000326 SDValue(Result_1,0));
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000327 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
328 MemOp[0] = LD->getMemOperand();
329 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
330 const SDValue Froms[] = { SDValue(LD, 0),
331 SDValue(LD, 1),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000332 SDValue(LD, 2) };
333 const SDValue Tos[] = { SDValue(Result_2, 0),
334 SDValue(Result_1, 1),
335 SDValue(Result_1, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000336 ReplaceUses(Froms, Tos, 3);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000337 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000338 }
339
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000340 // Generate an indirect load.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000341 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
342 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000343 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
344 MVT::Other, Base, TargetConst0,
345 Chain);
346 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl,
347 MVT::i64, MVT::Other,
348 TargetConst0,
349 SDValue(Result_1,0));
350 // Add offset to base.
351 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
352 Base, TargetConstVal,
353 SDValue(Result_1, 1));
354 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
355 MemOp[0] = LD->getMemOperand();
356 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
357 const SDValue Froms[] = { SDValue(LD, 0),
358 SDValue(LD, 1),
359 SDValue(LD, 2) };
360 const SDValue Tos[] = { SDValue(Result_2, 0), // Load value.
361 SDValue(Result_3, 0), // New address.
362 SDValue(Result_1, 1) };
363 ReplaceUses(Froms, Tos, 3);
364 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000365}
366
367
Andrew Trickef9de2a2013-05-25 02:42:55 +0000368SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000369 SDValue Chain = LD->getChain();
370 SDValue Base = LD->getBasePtr();
371 SDValue Offset = LD->getOffset();
372 SDNode *OffsetNode = Offset.getNode();
373 // Get the constant value.
374 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
375 EVT LoadedVT = LD->getMemoryVT();
376 unsigned Opcode = 0;
377
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000378 // Check for zero extended loads. Treat any-extend loads as zero extended
379 // loads.
380 ISD::LoadExtType ExtType = LD->getExtensionType();
381 bool IsZeroExt = (ExtType == ISD::ZEXTLOAD || ExtType == ISD::EXTLOAD);
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000382 bool HasVecOffset = false;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000383
384 // Figure out the opcode.
385 if (LoadedVT == MVT::i64) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000386 if (HII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000387 Opcode = Hexagon::L2_loadrd_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000388 else
Colin LeMahieu947cd702014-12-23 20:44:59 +0000389 Opcode = Hexagon::L2_loadrd_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000390 } else if (LoadedVT == MVT::i32) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000391 if (HII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000392 Opcode = Hexagon::L2_loadri_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000393 else
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000394 Opcode = Hexagon::L2_loadri_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000395 } else if (LoadedVT == MVT::i16) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000396 if (HII->isValidAutoIncImm(LoadedVT, Val))
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000397 Opcode = IsZeroExt ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000398 else
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000399 Opcode = IsZeroExt ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000400 } else if (LoadedVT == MVT::i8) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000401 if (HII->isValidAutoIncImm(LoadedVT, Val))
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000402 Opcode = IsZeroExt ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000403 else
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000404 Opcode = IsZeroExt ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000405 } else if (LoadedVT == MVT::v16i32 || LoadedVT == MVT::v8i64 ||
406 LoadedVT == MVT::v32i16 || LoadedVT == MVT::v64i8) {
407 HasVecOffset = true;
408 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
409 Opcode = Hexagon::V6_vL32b_pi;
410 }
411 else
412 Opcode = Hexagon::V6_vL32b_ai;
413 // 128B
414 } else if (LoadedVT == MVT::v32i32 || LoadedVT == MVT::v16i64 ||
415 LoadedVT == MVT::v64i16 || LoadedVT == MVT::v128i8) {
416 HasVecOffset = true;
417 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
418 Opcode = Hexagon::V6_vL32b_pi_128B;
419 }
420 else
421 Opcode = Hexagon::V6_vL32b_ai_128B;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000422 } else
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000423 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000424
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000425 // For zero extended i64 loads, we need to add combine instructions.
426 if (LD->getValueType(0) == MVT::i64 && IsZeroExt)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000427 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000428 // Handle sign extended i64 loads.
429 if (LD->getValueType(0) == MVT::i64 && ExtType == ISD::SEXTLOAD)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000430 return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000431
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000432 if (HII->isValidAutoIncImm(LoadedVT, Val)) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000433 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000434 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
435 LD->getValueType(0),
436 MVT::i32, MVT::Other, Base,
437 TargetConstVal, Chain);
438 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
439 MemOp[0] = LD->getMemOperand();
440 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000441 if (HasVecOffset) {
442 const SDValue Froms[] = { SDValue(LD, 0),
443 SDValue(LD, 2)
444 };
445 const SDValue Tos[] = { SDValue(Result, 0),
446 SDValue(Result, 2)
447 };
448 ReplaceUses(Froms, Tos, 2);
449 } else {
450 const SDValue Froms[] = { SDValue(LD, 0),
451 SDValue(LD, 1),
452 SDValue(LD, 2)
453 };
454 const SDValue Tos[] = { SDValue(Result, 0),
455 SDValue(Result, 1),
456 SDValue(Result, 2)
457 };
458 ReplaceUses(Froms, Tos, 3);
459 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000460 return Result;
461 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000462 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
463 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000464 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
465 LD->getValueType(0),
466 MVT::Other, Base, TargetConst0,
467 Chain);
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000468 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000469 Base, TargetConstVal,
470 SDValue(Result_1, 1));
471 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
472 MemOp[0] = LD->getMemOperand();
473 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
474 const SDValue Froms[] = { SDValue(LD, 0),
475 SDValue(LD, 1),
476 SDValue(LD, 2)
477 };
478 const SDValue Tos[] = { SDValue(Result_1, 0),
479 SDValue(Result_2, 0),
480 SDValue(Result_1, 1)
481 };
482 ReplaceUses(Froms, Tos, 3);
483 return Result_1;
484 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000485}
486
487
488SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
489 SDNode *result;
Andrew Trickef9de2a2013-05-25 02:42:55 +0000490 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000491 LoadSDNode *LD = cast<LoadSDNode>(N);
492 ISD::MemIndexedMode AM = LD->getAddressingMode();
493
494 // Handle indexed loads.
495 if (AM != ISD::UNINDEXED) {
496 result = SelectIndexedLoad(LD, dl);
497 } else {
Colin LeMahieu2efa2d02015-03-09 21:48:13 +0000498 result = SelectCode(LD);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000499 }
500
501 return result;
502}
503
504
Andrew Trickef9de2a2013-05-25 02:42:55 +0000505SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000506 SDValue Chain = ST->getChain();
507 SDValue Base = ST->getBasePtr();
508 SDValue Offset = ST->getOffset();
509 SDValue Value = ST->getValue();
510 SDNode *OffsetNode = Offset.getNode();
511 // Get the constant value.
512 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
513 EVT StoredVT = ST->getMemoryVT();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000514 EVT ValueVT = Value.getValueType();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000515
516 // Offset value must be within representable range
517 // and must have correct alignment properties.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000518 if (HII->isValidAutoIncImm(StoredVT, Val)) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000519 unsigned Opcode = 0;
520
521 // Figure out the post inc version of opcode.
Colin LeMahieu9a3cd3f2014-12-29 20:00:43 +0000522 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi;
523 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi;
524 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi;
Colin LeMahieu3d34afb2014-12-29 19:42:14 +0000525 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000526 else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 ||
527 StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8) {
528 Opcode = Hexagon::V6_vS32b_pi;
529 }
530 // 128B
531 else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 ||
532 StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8) {
533 Opcode = Hexagon::V6_vS32b_pi_128B;
534 } else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000535
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000536 if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) {
537 assert(StoredVT.getSizeInBits() < 64 && "Not a truncating store");
538 Value = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg,
539 dl, MVT::i32, Value);
540 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000541 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, dl, MVT::i32), Value,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000542 Chain};
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000543 // Build post increment store.
544 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +0000545 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000546 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
547 MemOp[0] = ST->getMemOperand();
548 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
549
550 ReplaceUses(ST, Result);
551 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
552 return Result;
553 }
554
555 // Note: Order of operands matches the def of instruction:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000556 // def S2_storerd_io
557 // : STInst<(outs), (ins IntRegs:$base, imm:$offset, DoubleRegs:$src1), ...
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000558 // and it differs for POST_ST* for instance.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000559 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, dl, MVT::i32), Value,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000560 Chain};
561 unsigned Opcode = 0;
562
563 // Figure out the opcode.
Colin LeMahieubda31b42014-12-29 20:44:51 +0000564 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
565 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
566 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
567 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +0000568 else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 ||
569 StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8)
570 Opcode = Hexagon::V6_vS32b_ai;
571 // 128B
572 else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 ||
573 StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8)
574 Opcode = Hexagon::V6_vS32b_ai_128B;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000575 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000576
577 // Build regular store.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000578 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
Michael Liaob53d8962013-04-19 22:22:57 +0000579 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000580 // Build splitted incriment instruction.
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000581 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000582 Base,
583 TargetConstVal,
584 SDValue(Result_1, 0));
585 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
586 MemOp[0] = ST->getMemOperand();
587 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
588
589 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
590 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
591 return Result_2;
592}
593
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000594SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000595 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000596 StoreSDNode *ST = cast<StoreSDNode>(N);
597 ISD::MemIndexedMode AM = ST->getAddressingMode();
598
599 // Handle indexed stores.
600 if (AM != ISD::UNINDEXED) {
601 return SelectIndexedStore(ST, dl);
602 }
Sirish Pandec92c3162012-05-03 16:18:50 +0000603
Colin LeMahieu2efa2d02015-03-09 21:48:13 +0000604 return SelectCode(ST);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000605}
606
607SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000608 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000609
610 //
611 // %conv.i = sext i32 %tmp1 to i64
612 // %conv2.i = sext i32 %add to i64
613 // %mul.i = mul nsw i64 %conv2.i, %conv.i
614 //
615 // --- match with the following ---
616 //
617 // %mul.i = mpy (%tmp1, %add)
618 //
619
620 if (N->getValueType(0) == MVT::i64) {
621 // Shifting a i64 signed multiply.
622 SDValue MulOp0 = N->getOperand(0);
623 SDValue MulOp1 = N->getOperand(1);
624
625 SDValue OP0;
626 SDValue OP1;
627
628 // Handle sign_extend and sextload.
629 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
630 SDValue Sext0 = MulOp0.getOperand(0);
631 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000632 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000633 }
634
635 OP0 = Sext0;
636 } else if (MulOp0.getOpcode() == ISD::LOAD) {
637 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
638 if (LD->getMemoryVT() != MVT::i32 ||
639 LD->getExtensionType() != ISD::SEXTLOAD ||
640 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000641 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000642 }
643
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000644 SDValue Chain = LD->getChain();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000645 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000646 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000647 MVT::Other,
648 LD->getBasePtr(), TargetConst0,
649 Chain), 0);
650 } else {
651 return SelectCode(N);
652 }
653
654 // Same goes for the second operand.
655 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
656 SDValue Sext1 = MulOp1.getOperand(0);
657 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
658 return SelectCode(N);
659 }
660
661 OP1 = Sext1;
662 } else if (MulOp1.getOpcode() == ISD::LOAD) {
663 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
664 if (LD->getMemoryVT() != MVT::i32 ||
665 LD->getExtensionType() != ISD::SEXTLOAD ||
666 LD->getAddressingMode() != ISD::UNINDEXED) {
667 return SelectCode(N);
668 }
669
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000670 SDValue Chain = LD->getChain();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000671 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000672 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000673 MVT::Other,
674 LD->getBasePtr(), TargetConst0,
675 Chain), 0);
676 } else {
677 return SelectCode(N);
678 }
679
680 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +0000681 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000682 OP0, OP1);
683 ReplaceUses(N, Result);
684 return Result;
685 }
686
687 return SelectCode(N);
688}
689
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000690SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000691 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000692 if (N->getValueType(0) == MVT::i32) {
693 SDValue Shl_0 = N->getOperand(0);
694 SDValue Shl_1 = N->getOperand(1);
695 // RHS is const.
696 if (Shl_1.getOpcode() == ISD::Constant) {
697 if (Shl_0.getOpcode() == ISD::MUL) {
698 SDValue Mul_0 = Shl_0.getOperand(0); // Val
699 SDValue Mul_1 = Shl_0.getOperand(1); // Const
700 // RHS of mul is const.
701 if (Mul_1.getOpcode() == ISD::Constant) {
702 int32_t ShlConst =
703 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
704 int32_t MulConst =
705 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
706 int32_t ValConst = MulConst << ShlConst;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000707 SDValue Val = CurDAG->getTargetConstant(ValConst, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000708 MVT::i32);
709 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
710 if (isInt<9>(CN->getSExtValue())) {
711 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000712 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000713 MVT::i32, Mul_0, Val);
714 ReplaceUses(N, Result);
715 return Result;
716 }
717
718 }
719 } else if (Shl_0.getOpcode() == ISD::SUB) {
720 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
721 SDValue Sub_1 = Shl_0.getOperand(1); // Val
722 if (Sub_0.getOpcode() == ISD::Constant) {
723 int32_t SubConst =
724 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
725 if (SubConst == 0) {
726 if (Sub_1.getOpcode() == ISD::SHL) {
727 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
728 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
729 if (Shl2_1.getOpcode() == ISD::Constant) {
730 int32_t ShlConst =
731 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
732 int32_t Shl2Const =
733 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
734 int32_t ValConst = 1 << (ShlConst+Shl2Const);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000735 SDValue Val = CurDAG->getTargetConstant(-ValConst, dl,
736 MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000737 if (ConstantSDNode *CN =
738 dyn_cast<ConstantSDNode>(Val.getNode()))
739 if (isInt<9>(CN->getSExtValue())) {
740 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000741 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000742 Shl2_0, Val);
743 ReplaceUses(N, Result);
744 return Result;
745 }
746 }
747 }
748 }
749 }
750 }
751 }
752 }
753 return SelectCode(N);
754}
755
756
757//
758// If there is an zero_extend followed an intrinsic in DAG (this means - the
759// result of the intrinsic is predicate); convert the zero_extend to
760// transfer instruction.
761//
762// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
763// converted into a MUX as predicate registers defined as 1 bit in the
764// compiler. Architecture defines them as 8-bit registers.
765// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
766//
767SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000768 SDLoc dl(N);
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000769
770 SDValue Op0 = N->getOperand(0);
771 EVT OpVT = Op0.getValueType();
772 unsigned OpBW = OpVT.getSizeInBits();
773
774 // Special handling for zero-extending a vector of booleans.
775 if (OpVT.isVector() && OpVT.getVectorElementType() == MVT::i1 && OpBW <= 64) {
776 SDNode *Mask = CurDAG->getMachineNode(Hexagon::C2_mask, dl, MVT::i64, Op0);
777 unsigned NE = OpVT.getVectorNumElements();
778 EVT ExVT = N->getValueType(0);
779 unsigned ES = ExVT.getVectorElementType().getSizeInBits();
780 uint64_t MV = 0, Bit = 1;
781 for (unsigned i = 0; i < NE; ++i) {
782 MV |= Bit;
783 Bit <<= ES;
784 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000785 SDValue Ones = CurDAG->getTargetConstant(MV, dl, MVT::i64);
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000786 SDNode *OnesReg = CurDAG->getMachineNode(Hexagon::CONST64_Int_Real, dl,
787 MVT::i64, Ones);
788 if (ExVT.getSizeInBits() == 32) {
789 SDNode *And = CurDAG->getMachineNode(Hexagon::A2_andp, dl, MVT::i64,
790 SDValue(Mask,0), SDValue(OnesReg,0));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000791 SDValue SubR = CurDAG->getTargetConstant(Hexagon::subreg_loreg, dl,
792 MVT::i32);
Krzysztof Parzyszek42113342015-03-19 16:33:08 +0000793 return CurDAG->getMachineNode(Hexagon::EXTRACT_SUBREG, dl, ExVT,
794 SDValue(And,0), SubR);
795 }
796 return CurDAG->getMachineNode(Hexagon::A2_andp, dl, ExVT,
797 SDValue(Mask,0), SDValue(OnesReg,0));
798 }
799
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000800 SDNode *IsIntrinsic = N->getOperand(0).getNode();
801 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
802 unsigned ID =
803 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
804 if (doesIntrinsicReturnPredicate(ID)) {
805 // Now we need to differentiate target data types.
806 if (N->getValueType(0) == MVT::i64) {
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +0000807 // Convert the zero_extend to Rs = Pd followed by A2_combinew(0,Rs).
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000808 SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
Colin LeMahieu30dcb232014-12-09 18:16:49 +0000809 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000810 MVT::i32,
811 SDValue(IsIntrinsic, 0));
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000812 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000813 MVT::i32,
814 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000815 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000816 MVT::i64, MVT::Other,
817 SDValue(Result_2, 0),
818 SDValue(Result_1, 0));
819 ReplaceUses(N, Result_3);
820 return Result_3;
821 }
822 if (N->getValueType(0) == MVT::i32) {
823 // Convert the zero_extend to Rs = Pd
Colin LeMahieu30dcb232014-12-09 18:16:49 +0000824 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000825 MVT::i32,
826 SDValue(IsIntrinsic, 0));
827 ReplaceUses(N, RsPd);
828 return RsPd;
829 }
Craig Toppere55c5562012-02-07 02:50:20 +0000830 llvm_unreachable("Unexpected value type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000831 }
832 }
833 return SelectCode(N);
834}
835
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000836//
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +0000837// Checking for intrinsics circular load/store, and bitreverse load/store
838// instrisics in order to select the correct lowered operation.
839//
840SDNode *HexagonDAGToDAGISel::SelectIntrinsicWChain(SDNode *N) {
841 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
842 if (IntNo == Intrinsic::hexagon_circ_ldd ||
843 IntNo == Intrinsic::hexagon_circ_ldw ||
844 IntNo == Intrinsic::hexagon_circ_lduh ||
845 IntNo == Intrinsic::hexagon_circ_ldh ||
846 IntNo == Intrinsic::hexagon_circ_ldub ||
847 IntNo == Intrinsic::hexagon_circ_ldb) {
848 SDLoc dl(N);
849 SDValue Chain = N->getOperand(0);
850 SDValue Base = N->getOperand(2);
851 SDValue Load = N->getOperand(3);
852 SDValue ModifierExpr = N->getOperand(4);
853 SDValue Offset = N->getOperand(5);
854
855 // We need to add the rerurn type for the load. This intrinsic has
856 // two return types, one for the load and one for the post-increment.
857 // Only the *_ld instructions push the extra return type, and bump the
858 // result node operand number correspondingly.
859 std::vector<EVT> ResTys;
860 unsigned opc;
861 unsigned memsize, align;
862 MVT MvtSize = MVT::i32;
863
864 if (IntNo == Intrinsic::hexagon_circ_ldd) {
865 ResTys.push_back(MVT::i32);
866 ResTys.push_back(MVT::i64);
867 opc = Hexagon::L2_loadrd_pci_pseudo;
868 memsize = 8;
869 align = 8;
870 } else if (IntNo == Intrinsic::hexagon_circ_ldw) {
871 ResTys.push_back(MVT::i32);
872 ResTys.push_back(MVT::i32);
873 opc = Hexagon::L2_loadri_pci_pseudo;
874 memsize = 4;
875 align = 4;
876 } else if (IntNo == Intrinsic::hexagon_circ_ldh) {
877 ResTys.push_back(MVT::i32);
878 ResTys.push_back(MVT::i32);
879 opc = Hexagon::L2_loadrh_pci_pseudo;
880 memsize = 2;
881 align = 2;
882 MvtSize = MVT::i16;
883 } else if (IntNo == Intrinsic::hexagon_circ_lduh) {
884 ResTys.push_back(MVT::i32);
885 ResTys.push_back(MVT::i32);
886 opc = Hexagon::L2_loadruh_pci_pseudo;
887 memsize = 2;
888 align = 2;
889 MvtSize = MVT::i16;
890 } else if (IntNo == Intrinsic::hexagon_circ_ldb) {
891 ResTys.push_back(MVT::i32);
892 ResTys.push_back(MVT::i32);
893 opc = Hexagon::L2_loadrb_pci_pseudo;
894 memsize = 1;
895 align = 1;
896 MvtSize = MVT::i8;
897 } else if (IntNo == Intrinsic::hexagon_circ_ldub) {
898 ResTys.push_back(MVT::i32);
899 ResTys.push_back(MVT::i32);
900 opc = Hexagon::L2_loadrub_pci_pseudo;
901 memsize = 1;
902 align = 1;
903 MvtSize = MVT::i8;
904 } else
905 llvm_unreachable("no opc");
906
907 ResTys.push_back(MVT::Other);
908
909 // Copy over the arguments, which are the same mostly.
910 SmallVector<SDValue, 5> Ops;
911 Ops.push_back(Base);
912 Ops.push_back(Load);
913 Ops.push_back(ModifierExpr);
914 int32_t Val = cast<ConstantSDNode>(Offset.getNode())->getSExtValue();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000915 Ops.push_back(CurDAG->getTargetConstant(Val, dl, MVT::i32));
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +0000916 Ops.push_back(Chain);
917 SDNode* Result = CurDAG->getMachineNode(opc, dl, ResTys, Ops);
918
919 SDValue ST;
920 MachineMemOperand *Mem =
921 MF->getMachineMemOperand(MachinePointerInfo(),
922 MachineMemOperand::MOStore, memsize, align);
923 if (MvtSize != MVT::i32)
924 ST = CurDAG->getTruncStore(Chain, dl, SDValue(Result, 1), Load,
925 MvtSize, Mem);
926 else
927 ST = CurDAG->getStore(Chain, dl, SDValue(Result, 1), Load, Mem);
928
929 SDNode* Store = SelectStore(ST.getNode());
930
931 const SDValue Froms[] = { SDValue(N, 0),
932 SDValue(N, 1) };
933 const SDValue Tos[] = { SDValue(Result, 0),
934 SDValue(Store, 0) };
935 ReplaceUses(Froms, Tos, 2);
936 return Result;
937 }
938
939 if (IntNo == Intrinsic::hexagon_brev_ldd ||
940 IntNo == Intrinsic::hexagon_brev_ldw ||
941 IntNo == Intrinsic::hexagon_brev_ldh ||
942 IntNo == Intrinsic::hexagon_brev_lduh ||
943 IntNo == Intrinsic::hexagon_brev_ldb ||
944 IntNo == Intrinsic::hexagon_brev_ldub) {
945 SDLoc dl(N);
946 SDValue Chain = N->getOperand(0);
947 SDValue Base = N->getOperand(2);
948 SDValue Load = N->getOperand(3);
949 SDValue ModifierExpr = N->getOperand(4);
950
951 // We need to add the rerurn type for the load. This intrinsic has
952 // two return types, one for the load and one for the post-increment.
953 std::vector<EVT> ResTys;
954 unsigned opc;
955 unsigned memsize, align;
956 MVT MvtSize = MVT::i32;
957
958 if (IntNo == Intrinsic::hexagon_brev_ldd) {
959 ResTys.push_back(MVT::i32);
960 ResTys.push_back(MVT::i64);
961 opc = Hexagon::L2_loadrd_pbr_pseudo;
962 memsize = 8;
963 align = 8;
964 } else if (IntNo == Intrinsic::hexagon_brev_ldw) {
965 ResTys.push_back(MVT::i32);
966 ResTys.push_back(MVT::i32);
967 opc = Hexagon::L2_loadri_pbr_pseudo;
968 memsize = 4;
969 align = 4;
970 } else if (IntNo == Intrinsic::hexagon_brev_ldh) {
971 ResTys.push_back(MVT::i32);
972 ResTys.push_back(MVT::i32);
973 opc = Hexagon::L2_loadrh_pbr_pseudo;
974 memsize = 2;
975 align = 2;
976 MvtSize = MVT::i16;
977 } else if (IntNo == Intrinsic::hexagon_brev_lduh) {
978 ResTys.push_back(MVT::i32);
979 ResTys.push_back(MVT::i32);
980 opc = Hexagon::L2_loadruh_pbr_pseudo;
981 memsize = 2;
982 align = 2;
983 MvtSize = MVT::i16;
984 } else if (IntNo == Intrinsic::hexagon_brev_ldb) {
985 ResTys.push_back(MVT::i32);
986 ResTys.push_back(MVT::i32);
987 opc = Hexagon::L2_loadrb_pbr_pseudo;
988 memsize = 1;
989 align = 1;
990 MvtSize = MVT::i8;
991 } else if (IntNo == Intrinsic::hexagon_brev_ldub) {
992 ResTys.push_back(MVT::i32);
993 ResTys.push_back(MVT::i32);
994 opc = Hexagon::L2_loadrub_pbr_pseudo;
995 memsize = 1;
996 align = 1;
997 MvtSize = MVT::i8;
998 } else
999 llvm_unreachable("no opc");
1000
1001 ResTys.push_back(MVT::Other);
1002
1003 // Copy over the arguments, which are the same mostly.
1004 SmallVector<SDValue, 4> Ops;
1005 Ops.push_back(Base);
1006 Ops.push_back(Load);
1007 Ops.push_back(ModifierExpr);
1008 Ops.push_back(Chain);
1009 SDNode* Result = CurDAG->getMachineNode(opc, dl, ResTys, Ops);
1010 SDValue ST;
1011 MachineMemOperand *Mem =
1012 MF->getMachineMemOperand(MachinePointerInfo(),
1013 MachineMemOperand::MOStore, memsize, align);
1014 if (MvtSize != MVT::i32)
1015 ST = CurDAG->getTruncStore(Chain, dl, SDValue(Result, 1), Load,
1016 MvtSize, Mem);
1017 else
1018 ST = CurDAG->getStore(Chain, dl, SDValue(Result, 1), Load, Mem);
1019
1020 SDNode* Store = SelectStore(ST.getNode());
1021
1022 const SDValue Froms[] = { SDValue(N, 0),
1023 SDValue(N, 1) };
1024 const SDValue Tos[] = { SDValue(Result, 0),
1025 SDValue(Store, 0) };
1026 ReplaceUses(Froms, Tos, 2);
1027 return Result;
1028 }
1029
1030 return SelectCode(N);
1031}
1032
1033//
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001034// Checking for intrinsics which have predicate registers as operand(s)
1035// and lowering to the actual intrinsic.
1036//
1037SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001038 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1039 unsigned Bits;
1040 switch (IID) {
1041 case Intrinsic::hexagon_S2_vsplatrb:
1042 Bits = 8;
1043 break;
1044 case Intrinsic::hexagon_S2_vsplatrh:
1045 Bits = 16;
1046 break;
1047 default:
1048 return SelectCode(N);
1049 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001050
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001051 SDValue const &V = N->getOperand(1);
1052 SDValue U;
1053 if (isValueExtension(V, Bits, U)) {
1054 SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
1055 N->getOperand(0), U);
1056 return SelectCode(R.getNode());
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001057 }
1058 return SelectCode(N);
1059}
1060
Sirish Pande69295b82012-05-10 20:20:25 +00001061//
1062// Map floating point constant values.
1063//
1064SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001065 SDLoc dl(N);
Sirish Pande69295b82012-05-10 20:20:25 +00001066 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1067 APFloat APF = CN->getValueAPF();
1068 if (N->getValueType(0) == MVT::f32) {
1069 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001070 CurDAG->getTargetConstantFP(APF.convertToFloat(), dl, MVT::f32));
Sirish Pande69295b82012-05-10 20:20:25 +00001071 }
1072 else if (N->getValueType(0) == MVT::f64) {
1073 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001074 CurDAG->getTargetConstantFP(APF.convertToDouble(), dl, MVT::f64));
Sirish Pande69295b82012-05-10 20:20:25 +00001075 }
1076
1077 return SelectCode(N);
1078}
1079
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001080//
1081// Map predicate true (encoded as -1 in LLVM) to a XOR.
1082//
1083SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001084 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001085 if (N->getValueType(0) == MVT::i1) {
Krzysztof Parzyszek36ccfa52015-03-18 19:07:53 +00001086 SDNode* Result = 0;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001087 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
Krzysztof Parzyszek7a9cd802015-03-18 18:50:06 +00001088 if (Val == -1) {
Krzysztof Parzyszek36ccfa52015-03-18 19:07:53 +00001089 Result = CurDAG->getMachineNode(Hexagon::TFR_PdTrue, dl, MVT::i1);
1090 } else if (Val == 0) {
1091 Result = CurDAG->getMachineNode(Hexagon::TFR_PdFalse, dl, MVT::i1);
1092 }
1093 if (Result) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001094 ReplaceUses(N, Result);
1095 return Result;
1096 }
1097 }
1098
1099 return SelectCode(N);
1100}
1101
1102
1103//
1104// Map add followed by a asr -> asr +=.
1105//
1106SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001107 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001108 if (N->getValueType(0) != MVT::i32) {
1109 return SelectCode(N);
1110 }
1111 // Identify nodes of the form: add(asr(...)).
1112 SDNode* Src1 = N->getOperand(0).getNode();
1113 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1114 || Src1->getValueType(0) != MVT::i32) {
1115 return SelectCode(N);
1116 }
1117
1118 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1119 // Rd and Rd' are assigned to the same register
Colin LeMahieu0f850bd2014-12-19 20:29:29 +00001120 SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001121 N->getOperand(1),
1122 Src1->getOperand(0),
1123 Src1->getOperand(1));
1124 ReplaceUses(N, Result);
1125
1126 return Result;
1127}
1128
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001129//
1130// Map the following, where possible.
1131// AND/FABS -> clrbit
1132// OR -> setbit
1133// XOR/FNEG ->toggle_bit.
1134//
1135SDNode *HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
1136 SDLoc dl(N);
1137 EVT ValueVT = N->getValueType(0);
1138
1139 // We handle only 32 and 64-bit bit ops.
1140 if (!(ValueVT == MVT::i32 || ValueVT == MVT::i64 ||
1141 ValueVT == MVT::f32 || ValueVT == MVT::f64))
1142 return SelectCode(N);
1143
1144 // We handly only fabs and fneg for V5.
1145 unsigned Opc = N->getOpcode();
Eric Christopher23a7d1e2015-03-21 03:12:59 +00001146 if ((Opc == ISD::FABS || Opc == ISD::FNEG) && !HST->hasV5TOps())
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001147 return SelectCode(N);
1148
1149 int64_t Val = 0;
1150 if (Opc != ISD::FABS && Opc != ISD::FNEG) {
1151 if (N->getOperand(1).getOpcode() == ISD::Constant)
1152 Val = cast<ConstantSDNode>((N)->getOperand(1))->getSExtValue();
1153 else
1154 return SelectCode(N);
1155 }
1156
1157 if (Opc == ISD::AND) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001158 // Check if this is a bit-clearing AND, if not select code the usual way.
1159 if ((ValueVT == MVT::i32 && isPowerOf2_32(~Val)) ||
1160 (ValueVT == MVT::i64 && isPowerOf2_64(~Val)))
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001161 Val = ~Val;
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001162 else
1163 return SelectCode(N);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001164 }
1165
1166 // If OR or AND is being fed by shl, srl and, sra don't do this change,
1167 // because Hexagon provide |= &= on shl, srl, and sra.
1168 // Traverse the DAG to see if there is shl, srl and sra.
1169 if (Opc == ISD::OR || Opc == ISD::AND) {
1170 switch (N->getOperand(0)->getOpcode()) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001171 default:
1172 break;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001173 case ISD::SRA:
1174 case ISD::SRL:
1175 case ISD::SHL:
1176 return SelectCode(N);
1177 }
1178 }
1179
1180 // Make sure it's power of 2.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001181 unsigned BitPos = 0;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001182 if (Opc != ISD::FABS && Opc != ISD::FNEG) {
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001183 if ((ValueVT == MVT::i32 && !isPowerOf2_32(Val)) ||
1184 (ValueVT == MVT::i64 && !isPowerOf2_64(Val)))
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001185 return SelectCode(N);
1186
1187 // Get the bit position.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001188 BitPos = countTrailingZeros(uint64_t(Val));
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001189 } else {
1190 // For fabs and fneg, it's always the 31st bit.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001191 BitPos = 31;
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001192 }
1193
1194 unsigned BitOpc = 0;
1195 // Set the right opcode for bitwise operations.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001196 switch (Opc) {
1197 default:
1198 llvm_unreachable("Only bit-wise/abs/neg operations are allowed.");
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001199 case ISD::AND:
1200 case ISD::FABS:
1201 BitOpc = Hexagon::S2_clrbit_i;
1202 break;
1203 case ISD::OR:
1204 BitOpc = Hexagon::S2_setbit_i;
1205 break;
1206 case ISD::XOR:
1207 case ISD::FNEG:
1208 BitOpc = Hexagon::S2_togglebit_i;
1209 break;
1210 }
1211
1212 SDNode *Result;
1213 // Get the right SDVal for the opcode.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001214 SDValue SDVal = CurDAG->getTargetConstant(BitPos, dl, MVT::i32);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001215
1216 if (ValueVT == MVT::i32 || ValueVT == MVT::f32) {
1217 Result = CurDAG->getMachineNode(BitOpc, dl, ValueVT,
1218 N->getOperand(0), SDVal);
1219 } else {
1220 // 64-bit gymnastic to use REG_SEQUENCE. But it's worth it.
1221 EVT SubValueVT;
1222 if (ValueVT == MVT::i64)
1223 SubValueVT = MVT::i32;
1224 else
1225 SubValueVT = MVT::f32;
1226
1227 SDNode *Reg = N->getOperand(0).getNode();
1228 SDValue RegClass = CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001229 dl, MVT::i64);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001230
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001231 SDValue SubregHiIdx = CurDAG->getTargetConstant(Hexagon::subreg_hireg, dl,
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001232 MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001233 SDValue SubregLoIdx = CurDAG->getTargetConstant(Hexagon::subreg_loreg, dl,
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001234 MVT::i32);
1235
1236 SDValue SubregHI = CurDAG->getTargetExtractSubreg(Hexagon::subreg_hireg, dl,
1237 MVT::i32, SDValue(Reg, 0));
1238
1239 SDValue SubregLO = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg, dl,
1240 MVT::i32, SDValue(Reg, 0));
1241
1242 // Clear/set/toggle hi or lo registers depending on the bit position.
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001243 if (SubValueVT != MVT::f32 && BitPos < 32) {
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001244 SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
1245 SubregLO, SDVal);
1246 const SDValue Ops[] = { RegClass, SubregHI, SubregHiIdx,
1247 SDValue(Result0, 0), SubregLoIdx };
1248 Result = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
1249 dl, ValueVT, Ops);
1250 } else {
1251 if (Opc != ISD::FABS && Opc != ISD::FNEG)
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001252 SDVal = CurDAG->getTargetConstant(BitPos-32, dl, MVT::i32);
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001253 SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
1254 SubregHI, SDVal);
1255 const SDValue Ops[] = { RegClass, SDValue(Result0, 0), SubregHiIdx,
1256 SubregLO, SubregLoIdx };
1257 Result = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
1258 dl, ValueVT, Ops);
1259 }
1260 }
1261
1262 ReplaceUses(N, Result);
1263 return Result;
1264}
1265
1266
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001267SDNode *HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) {
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001268 MachineFrameInfo *MFI = MF->getFrameInfo();
1269 const HexagonFrameLowering *HFI = HST->getFrameLowering();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001270 int FX = cast<FrameIndexSDNode>(N)->getIndex();
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001271 unsigned StkA = HFI->getStackAlignment();
1272 unsigned MaxA = MFI->getMaxAlignment();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001273 SDValue FI = CurDAG->getTargetFrameIndex(FX, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001274 SDLoc DL(N);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001275 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001276 SDNode *R = 0;
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001277
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001278 // Use TFR_FI when:
1279 // - the object is fixed, or
1280 // - there are no objects with higher-than-default alignment, or
1281 // - there are no dynamically allocated objects.
1282 // Otherwise, use TFR_FIA.
1283 if (FX < 0 || MaxA <= StkA || !MFI->hasVarSizedObjects()) {
1284 R = CurDAG->getMachineNode(Hexagon::TFR_FI, DL, MVT::i32, FI, Zero);
1285 } else {
1286 auto &HMFI = *MF->getInfo<HexagonMachineFunctionInfo>();
1287 unsigned AR = HMFI.getStackAlignBaseVReg();
1288 SDValue CH = CurDAG->getEntryNode();
1289 SDValue Ops[] = { CurDAG->getCopyFromReg(CH, DL, AR, MVT::i32), FI, Zero };
1290 R = CurDAG->getMachineNode(Hexagon::TFR_FIA, DL, MVT::i32, Ops);
1291 }
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001292
1293 if (N->getHasDebugValue())
1294 CurDAG->TransferDbgValues(SDValue(N, 0), SDValue(R, 0));
1295 return R;
1296}
1297
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001298
1299SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
Tim Northover31d093c2013-09-22 08:21:56 +00001300 if (N->isMachineOpcode()) {
1301 N->setNodeId(-1);
Craig Topper062a2ba2014-04-25 05:30:21 +00001302 return nullptr; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00001303 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001304
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001305 switch (N->getOpcode()) {
1306 case ISD::Constant:
1307 return SelectConstant(N);
1308
Sirish Pande69295b82012-05-10 20:20:25 +00001309 case ISD::ConstantFP:
1310 return SelectConstantFP(N);
1311
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001312 case ISD::FrameIndex:
1313 return SelectFrameIndex(N);
1314
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001315 case ISD::ADD:
1316 return SelectAdd(N);
1317
1318 case ISD::SHL:
1319 return SelectSHL(N);
1320
1321 case ISD::LOAD:
1322 return SelectLoad(N);
1323
1324 case ISD::STORE:
1325 return SelectStore(N);
1326
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001327 case ISD::MUL:
1328 return SelectMul(N);
1329
Krzysztof Parzyszek8c1cab92015-03-18 00:43:46 +00001330 case ISD::AND:
1331 case ISD::OR:
1332 case ISD::XOR:
1333 case ISD::FABS:
1334 case ISD::FNEG:
1335 return SelectBitOp(N);
1336
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001337 case ISD::ZERO_EXTEND:
1338 return SelectZeroExtend(N);
1339
Krzysztof Parzyszek47ab1f22015-03-18 16:23:44 +00001340 case ISD::INTRINSIC_W_CHAIN:
1341 return SelectIntrinsicWChain(N);
1342
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001343 case ISD::INTRINSIC_WO_CHAIN:
1344 return SelectIntrinsicWOChain(N);
1345 }
1346
1347 return SelectCode(N);
1348}
1349
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001350bool HexagonDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00001351SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001352 std::vector<SDValue> &OutOps) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001353 SDValue Inp = Op, Res;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001354
Daniel Sanders60f1db02015-03-13 12:45:09 +00001355 switch (ConstraintID) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001356 default:
1357 return true;
Daniel Sanders49f643c2015-03-17 14:37:39 +00001358 case InlineAsm::Constraint_i:
1359 case InlineAsm::Constraint_o: // Offsetable.
1360 case InlineAsm::Constraint_v: // Not offsetable.
1361 case InlineAsm::Constraint_m: // Memory.
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001362 if (SelectAddrFI(Inp, Res))
1363 OutOps.push_back(Res);
1364 else
1365 OutOps.push_back(Inp);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001366 break;
1367 }
1368
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001369 OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));
Jyotsna Vermad9225242013-02-13 21:38:46 +00001370 return false;
1371}
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001372
Colin LeMahieu79ec0652015-06-12 19:57:32 +00001373
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001374void HexagonDAGToDAGISel::PreprocessISelDAG() {
1375 SelectionDAG &DAG = *CurDAG;
1376 std::vector<SDNode*> Nodes;
Pete Cooper7e64ef02015-07-14 23:43:29 +00001377 for (SDNode &Node : DAG.allnodes())
1378 Nodes.push_back(&Node);
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001379
1380 // Simplify: (or (select c x 0) z) -> (select c (or x z) z)
1381 // (or (select c 0 y) z) -> (select c z (or y z))
1382 // This may not be the right thing for all targets, so do it here.
1383 for (auto I: Nodes) {
1384 if (I->getOpcode() != ISD::OR)
1385 continue;
1386
1387 auto IsZero = [] (const SDValue &V) -> bool {
1388 if (ConstantSDNode *SC = dyn_cast<ConstantSDNode>(V.getNode()))
1389 return SC->isNullValue();
1390 return false;
1391 };
1392 auto IsSelect0 = [IsZero] (const SDValue &Op) -> bool {
1393 if (Op.getOpcode() != ISD::SELECT)
1394 return false;
1395 return IsZero(Op.getOperand(1)) || IsZero(Op.getOperand(2));
1396 };
1397
1398 SDValue N0 = I->getOperand(0), N1 = I->getOperand(1);
1399 EVT VT = I->getValueType(0);
1400 bool SelN0 = IsSelect0(N0);
1401 SDValue SOp = SelN0 ? N0 : N1;
1402 SDValue VOp = SelN0 ? N1 : N0;
1403
1404 if (SOp.getOpcode() == ISD::SELECT && SOp.getNode()->hasOneUse()) {
1405 SDValue SC = SOp.getOperand(0);
1406 SDValue SX = SOp.getOperand(1);
1407 SDValue SY = SOp.getOperand(2);
1408 SDLoc DLS = SOp;
1409 if (IsZero(SY)) {
1410 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SX, VOp);
1411 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, NewOr, VOp);
1412 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1413 } else if (IsZero(SX)) {
1414 SDValue NewOr = DAG.getNode(ISD::OR, DLS, VT, SY, VOp);
1415 SDValue NewSel = DAG.getNode(ISD::SELECT, DLS, VT, SC, VOp, NewOr);
1416 DAG.ReplaceAllUsesWith(I, NewSel.getNode());
1417 }
1418 }
1419 }
1420}
1421
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001422void HexagonDAGToDAGISel::EmitFunctionEntryCode() {
1423 auto &HST = static_cast<const HexagonSubtarget&>(MF->getSubtarget());
1424 auto &HFI = *HST.getFrameLowering();
1425 if (!HFI.needsAligna(*MF))
1426 return;
Krzysztof Parzyszekae14e7b2015-03-17 21:47:16 +00001427
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001428 MachineFrameInfo *MFI = MF->getFrameInfo();
Duncan P. N. Exon Smitha72c6e22015-10-20 00:46:39 +00001429 MachineBasicBlock *EntryBB = &MF->front();
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001430 unsigned AR = FuncInfo->CreateReg(MVT::i32);
1431 unsigned MaxA = MFI->getMaxAlignment();
Krzysztof Parzyszek08ff8882015-11-26 18:38:27 +00001432 BuildMI(EntryBB, DebugLoc(), HII->get(Hexagon::ALIGNA), AR)
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001433 .addImm(MaxA);
1434 MF->getInfo<HexagonMachineFunctionInfo>()->setStackAlignBaseVReg(AR);
1435}
1436
1437// Match a frame index that can be used in an addressing mode.
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001438bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) {
1439 if (N.getOpcode() != ISD::FrameIndex)
1440 return false;
Krzysztof Parzyszek4fa2a9f2015-04-22 16:43:53 +00001441 auto &HFI = *HST->getFrameLowering();
1442 MachineFrameInfo *MFI = MF->getFrameInfo();
1443 int FX = cast<FrameIndexSDNode>(N)->getIndex();
1444 if (!MFI->isFixedObjectIndex(FX) && HFI.needsAligna(*MF))
1445 return false;
1446 R = CurDAG->getTargetFrameIndex(FX, MVT::i32);
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001447 return true;
1448}
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001449
Colin LeMahieu987b0942015-02-04 20:38:01 +00001450inline bool HexagonDAGToDAGISel::SelectAddrGA(SDValue &N, SDValue &R) {
1451 return SelectGlobalAddress(N, R, false);
1452}
1453
Colin LeMahieu51491352015-02-04 22:36:28 +00001454inline bool HexagonDAGToDAGISel::SelectAddrGP(SDValue &N, SDValue &R) {
1455 return SelectGlobalAddress(N, R, true);
1456}
1457
Colin LeMahieu987b0942015-02-04 20:38:01 +00001458bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
1459 bool UseGP) {
1460 switch (N.getOpcode()) {
1461 case ISD::ADD: {
1462 SDValue N0 = N.getOperand(0);
1463 SDValue N1 = N.getOperand(1);
1464 unsigned GAOpc = N0.getOpcode();
1465 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1466 return false;
1467 if (!UseGP && GAOpc != HexagonISD::CONST32)
1468 return false;
1469 if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) {
1470 SDValue Addr = N0.getOperand(0);
1471 if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Addr)) {
1472 if (GA->getOpcode() == ISD::TargetGlobalAddress) {
1473 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1474 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),
1475 N.getValueType(), NewOff);
1476 return true;
1477 }
1478 }
1479 }
1480 break;
1481 }
1482 case HexagonISD::CONST32:
1483 // The operand(0) of CONST32 is TargetGlobalAddress, which is what we
1484 // want in the instruction.
1485 if (!UseGP)
1486 R = N.getOperand(0);
1487 return !UseGP;
1488 case HexagonISD::CONST32_GP:
1489 if (UseGP)
1490 R = N.getOperand(0);
1491 return UseGP;
1492 default:
1493 return false;
1494 }
1495
1496 return false;
1497}
1498
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001499bool HexagonDAGToDAGISel::isValueExtension(const SDValue &Val,
1500 unsigned FromBits, SDValue &Src) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001501 unsigned Opc = Val.getOpcode();
1502 switch (Opc) {
1503 case ISD::SIGN_EXTEND:
1504 case ISD::ZERO_EXTEND:
1505 case ISD::ANY_EXTEND: {
1506 SDValue const &Op0 = Val.getOperand(0);
1507 EVT T = Op0.getValueType();
1508 if (T.isInteger() && T.getSizeInBits() == FromBits) {
1509 Src = Op0;
1510 return true;
1511 }
1512 break;
1513 }
1514 case ISD::SIGN_EXTEND_INREG:
1515 case ISD::AssertSext:
1516 case ISD::AssertZext:
1517 if (Val.getOperand(0).getValueType().isInteger()) {
1518 VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
1519 if (T->getVT().getSizeInBits() == FromBits) {
1520 Src = Val.getOperand(0);
1521 return true;
1522 }
1523 }
1524 break;
1525 case ISD::AND: {
1526 // Check if this is an AND with "FromBits" of lower bits set to 1.
1527 uint64_t FromMask = (1 << FromBits) - 1;
1528 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1529 if (C->getZExtValue() == FromMask) {
1530 Src = Val.getOperand(1);
1531 return true;
1532 }
1533 }
1534 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1535 if (C->getZExtValue() == FromMask) {
1536 Src = Val.getOperand(0);
1537 return true;
1538 }
1539 }
1540 break;
1541 }
1542 case ISD::OR:
1543 case ISD::XOR: {
1544 // OR/XOR with the lower "FromBits" bits set to 0.
1545 uint64_t FromMask = (1 << FromBits) - 1;
1546 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1547 if ((C->getZExtValue() & FromMask) == 0) {
1548 Src = Val.getOperand(1);
1549 return true;
1550 }
1551 }
1552 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1553 if ((C->getZExtValue() & FromMask) == 0) {
1554 Src = Val.getOperand(0);
1555 return true;
1556 }
1557 }
1558 }
1559 default:
1560 break;
1561 }
1562 return false;
1563}