blob: 795faf97af474a297830dfbdd5fe53ffd4846d13 [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"
16#include "HexagonTargetMachine.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000017#include "llvm/ADT/DenseMap.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000018#include "llvm/CodeGen/SelectionDAGISel.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000019#include "llvm/IR/Intrinsics.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000020#include "llvm/Support/CommandLine.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000021#include "llvm/Support/Compiler.h"
22#include "llvm/Support/Debug.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000023using namespace llvm;
24
Chandler Carruth84e68b22014-04-22 02:41:26 +000025#define DEBUG_TYPE "hexagon-isel"
26
Jyotsna Vermad9225242013-02-13 21:38:46 +000027static
28cl::opt<unsigned>
29MaxNumOfUsesForConstExtenders("ga-max-num-uses-for-constant-extenders",
30 cl::Hidden, cl::init(2),
31 cl::desc("Maximum number of uses of a global address such that we still us a"
32 "constant extended instruction"));
Tony Linthicum1213a7a2011-12-12 21:14:40 +000033
34//===----------------------------------------------------------------------===//
35// Instruction Selector Implementation
36//===----------------------------------------------------------------------===//
37
Jyotsna Vermad9225242013-02-13 21:38:46 +000038namespace llvm {
39 void initializeHexagonDAGToDAGISelPass(PassRegistry&);
40}
41
Tony Linthicum1213a7a2011-12-12 21:14:40 +000042//===--------------------------------------------------------------------===//
43/// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine
44/// instructions for SelectionDAG operations.
45///
46namespace {
47class HexagonDAGToDAGISel : public SelectionDAGISel {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +000048 const HexagonTargetMachine& HTM;
49 const HexagonSubtarget &HST;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000050public:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +000051 explicit HexagonDAGToDAGISel(HexagonTargetMachine &tm,
Jyotsna Vermad9225242013-02-13 21:38:46 +000052 CodeGenOpt::Level OptLevel)
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +000053 : SelectionDAGISel(tm, OptLevel), HTM(tm),
54 HST(tm.getSubtarget<HexagonSubtarget>()) {
Jyotsna Vermad9225242013-02-13 21:38:46 +000055 initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry());
Tony Linthicum1213a7a2011-12-12 21:14:40 +000056 }
57
Craig Topper906c2cd2014-04-29 07:58:16 +000058 SDNode *Select(SDNode *N) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000059
60 // Complex Pattern Selectors.
Colin LeMahieu987b0942015-02-04 20:38:01 +000061 inline bool SelectAddrGA(SDValue &N, SDValue &R);
Colin LeMahieu51491352015-02-04 22:36:28 +000062 inline bool SelectAddrGP(SDValue &N, SDValue &R);
Colin LeMahieu987b0942015-02-04 20:38:01 +000063 bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP);
Colin LeMahieuc7522f32015-01-14 23:07:36 +000064 bool SelectAddrFI(SDValue &N, SDValue &R);
65
Craig Topper906c2cd2014-04-29 07:58:16 +000066 const char *getPassName() const override {
Tony Linthicum1213a7a2011-12-12 21:14:40 +000067 return "Hexagon DAG->DAG Pattern Instruction Selection";
68 }
69
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +000070 SDNode *SelectFrameIndex(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000071 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
72 /// inline asm expressions.
Craig Topper906c2cd2014-04-29 07:58:16 +000073 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
Daniel Sanders41c072e2015-03-12 11:00:48 +000074 unsigned ConstraintID,
Craig Topper906c2cd2014-04-29 07:58:16 +000075 std::vector<SDValue> &OutOps) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000076 SDNode *SelectLoad(SDNode *N);
Andrew Trickef9de2a2013-05-25 02:42:55 +000077 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl);
78 SDNode *SelectIndexedLoad(LoadSDNode *LD, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000079 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +000080 SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000081 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +000082 SDLoc dl);
83 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, SDLoc dl);
84 SDNode *SelectIndexedStore(StoreSDNode *ST, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000085 SDNode *SelectStore(SDNode *N);
86 SDNode *SelectSHL(SDNode *N);
87 SDNode *SelectSelect(SDNode *N);
88 SDNode *SelectTruncate(SDNode *N);
89 SDNode *SelectMul(SDNode *N);
90 SDNode *SelectZeroExtend(SDNode *N);
91 SDNode *SelectIntrinsicWOChain(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +000092 SDNode *SelectIntrinsicWChain(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000093 SDNode *SelectConstant(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +000094 SDNode *SelectConstantFP(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000095 SDNode *SelectAdd(SDNode *N);
96
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +000097 // XformMskToBitPosU5Imm - Returns the bit position which
98 // the single bit 32 bit mask represents.
99 // Used in Clr and Set bit immediate memops.
100 SDValue XformMskToBitPosU5Imm(uint32_t Imm) {
101 int32_t bitPos;
102 bitPos = Log2_32(Imm);
103 assert(bitPos >= 0 && bitPos < 32 &&
104 "Constant out of range for 32 BitPos Memops");
105 return CurDAG->getTargetConstant(bitPos, MVT::i32);
106 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000107
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000108 // XformMskToBitPosU4Imm - Returns the bit position which the single-bit
109 // 16 bit mask represents. Used in Clr and Set bit immediate memops.
110 SDValue XformMskToBitPosU4Imm(uint16_t Imm) {
111 return XformMskToBitPosU5Imm(Imm);
112 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000113
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000114 // XformMskToBitPosU3Imm - Returns the bit position which the single-bit
115 // 8 bit mask represents. Used in Clr and Set bit immediate memops.
116 SDValue XformMskToBitPosU3Imm(uint8_t Imm) {
117 return XformMskToBitPosU5Imm(Imm);
118 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000119
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000120 // Return true if there is exactly one bit set in V, i.e., if V is one of the
121 // following integers: 2^0, 2^1, ..., 2^31.
122 bool ImmIsSingleBit(uint32_t v) const {
123 return isPowerOf2_32(v);
124 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000125
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000126 // XformM5ToU5Imm - Return a target constant with the specified value, of
127 // type i32 where the negative literal is transformed into a positive literal
128 // for use in -= memops.
129 inline SDValue XformM5ToU5Imm(signed Imm) {
130 assert( (Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
131 return CurDAG->getTargetConstant( - Imm, MVT::i32);
132 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000133
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000134 // XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
135 // [1..128], used in cmpb.gtu instructions.
136 inline SDValue XformU7ToU7M1Imm(signed Imm) {
137 assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op");
138 return CurDAG->getTargetConstant(Imm - 1, MVT::i8);
139 }
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000140
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000141 // XformS8ToS8M1Imm - Return a target constant decremented by 1.
142 inline SDValue XformSToSM1Imm(signed Imm) {
143 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
144 }
Jyotsna Verma60316252013-02-05 19:20:45 +0000145
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000146 // XformU8ToU8M1Imm - Return a target constant decremented by 1.
147 inline SDValue XformUToUM1Imm(unsigned Imm) {
148 assert((Imm >= 1) && "Cannot decrement unsigned int less than 1");
149 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
150 }
Jyotsna Verma89c84822013-04-23 19:15:55 +0000151
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000152 // XformSToSM2Imm - Return a target constant decremented by 2.
153 inline SDValue XformSToSM2Imm(unsigned Imm) {
154 return CurDAG->getTargetConstant(Imm - 2, MVT::i32);
155 }
Jyotsna Verma89c84822013-04-23 19:15:55 +0000156
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000157 // XformSToSM3Imm - Return a target constant decremented by 3.
158 inline SDValue XformSToSM3Imm(unsigned Imm) {
159 return CurDAG->getTargetConstant(Imm - 3, MVT::i32);
160 }
Colin LeMahieu19ed07c2015-01-28 18:29:11 +0000161
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000162 // Include the pieces autogenerated from the target description.
163 #include "HexagonGenDAGISel.inc"
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +0000164
165private:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000166 bool isValueExtension(const SDValue &Val, unsigned FromBits, SDValue &Src);
167}; // end HexagonDAGToDAGISel
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000168} // end anonymous namespace
169
170
171/// createHexagonISelDag - This pass converts a legalized DAG into a
172/// Hexagon-specific DAG, ready for instruction scheduling.
173///
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000174namespace llvm {
175FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM,
176 CodeGenOpt::Level OptLevel) {
Jyotsna Vermad9225242013-02-13 21:38:46 +0000177 return new HexagonDAGToDAGISel(TM, OptLevel);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000178}
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000179}
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000180
Jyotsna Vermad9225242013-02-13 21:38:46 +0000181static void initializePassOnce(PassRegistry &Registry) {
182 const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection";
183 PassInfo *PI = new PassInfo(Name, "hexagon-isel",
Craig Topper062a2ba2014-04-25 05:30:21 +0000184 &SelectionDAGISel::ID, nullptr, false, false);
Jyotsna Vermad9225242013-02-13 21:38:46 +0000185 Registry.registerPass(*PI, true);
186}
187
188void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
189 CALL_ONCE_INITIALIZATION(initializePassOnce)
190}
191
192
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000193// Intrinsics that return a a predicate.
194static unsigned doesIntrinsicReturnPredicate(unsigned ID)
195{
196 switch (ID) {
197 default:
198 return 0;
199 case Intrinsic::hexagon_C2_cmpeq:
200 case Intrinsic::hexagon_C2_cmpgt:
201 case Intrinsic::hexagon_C2_cmpgtu:
202 case Intrinsic::hexagon_C2_cmpgtup:
203 case Intrinsic::hexagon_C2_cmpgtp:
204 case Intrinsic::hexagon_C2_cmpeqp:
205 case Intrinsic::hexagon_C2_bitsset:
206 case Intrinsic::hexagon_C2_bitsclr:
207 case Intrinsic::hexagon_C2_cmpeqi:
208 case Intrinsic::hexagon_C2_cmpgti:
209 case Intrinsic::hexagon_C2_cmpgtui:
210 case Intrinsic::hexagon_C2_cmpgei:
211 case Intrinsic::hexagon_C2_cmpgeui:
212 case Intrinsic::hexagon_C2_cmplt:
213 case Intrinsic::hexagon_C2_cmpltu:
214 case Intrinsic::hexagon_C2_bitsclri:
215 case Intrinsic::hexagon_C2_and:
216 case Intrinsic::hexagon_C2_or:
217 case Intrinsic::hexagon_C2_xor:
218 case Intrinsic::hexagon_C2_andn:
219 case Intrinsic::hexagon_C2_not:
220 case Intrinsic::hexagon_C2_orn:
221 case Intrinsic::hexagon_C2_pxfer_map:
222 case Intrinsic::hexagon_C2_any8:
223 case Intrinsic::hexagon_C2_all8:
224 case Intrinsic::hexagon_A2_vcmpbeq:
225 case Intrinsic::hexagon_A2_vcmpbgtu:
226 case Intrinsic::hexagon_A2_vcmpheq:
227 case Intrinsic::hexagon_A2_vcmphgt:
228 case Intrinsic::hexagon_A2_vcmphgtu:
229 case Intrinsic::hexagon_A2_vcmpweq:
230 case Intrinsic::hexagon_A2_vcmpwgt:
231 case Intrinsic::hexagon_A2_vcmpwgtu:
232 case Intrinsic::hexagon_C2_tfrrp:
233 case Intrinsic::hexagon_S2_tstbit_i:
234 case Intrinsic::hexagon_S2_tstbit_r:
235 return 1;
236 }
237}
238
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000239SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
240 unsigned Opcode,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000241 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000242 SDValue Chain = LD->getChain();
243 EVT LoadedVT = LD->getMemoryVT();
244 SDValue Base = LD->getBasePtr();
245 SDValue Offset = LD->getOffset();
246 SDNode *OffsetNode = Offset.getNode();
247 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
Bill Wendling4a7a4082013-06-07 06:19:56 +0000248
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000249 const HexagonInstrInfo &TII = *HST.getInstrInfo();
250 if (TII.isValidAutoIncImm(LoadedVT, Val)) {
251 SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32);
252 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
253 MVT::Other, Base, TargetConst,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000254 Chain);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000255 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
256 SDValue(Result_1, 0));
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000257 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
258 MemOp[0] = LD->getMemOperand();
259 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
260 const SDValue Froms[] = { SDValue(LD, 0),
261 SDValue(LD, 1),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000262 SDValue(LD, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000263 const SDValue Tos[] = { SDValue(Result_2, 0),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000264 SDValue(Result_1, 1),
265 SDValue(Result_1, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000266 ReplaceUses(Froms, Tos, 3);
267 return Result_2;
268 }
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000269
270 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
271 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
272 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other,
273 Base, TargetConst0, Chain);
274 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
275 SDValue(Result_1, 0));
276 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
277 Base, TargetConstVal,
278 SDValue(Result_1, 1));
279 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
280 MemOp[0] = LD->getMemOperand();
281 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
282 const SDValue Froms[] = { SDValue(LD, 0),
283 SDValue(LD, 1),
284 SDValue(LD, 2) };
285 const SDValue Tos[] = { SDValue(Result_2, 0),
286 SDValue(Result_3, 0),
287 SDValue(Result_1, 1) };
288 ReplaceUses(Froms, Tos, 3);
289 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000290}
291
292
293SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
294 unsigned Opcode,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000295 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000296 SDValue Chain = LD->getChain();
297 EVT LoadedVT = LD->getMemoryVT();
298 SDValue Base = LD->getBasePtr();
299 SDValue Offset = LD->getOffset();
300 SDNode *OffsetNode = Offset.getNode();
301 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
Bill Wendling4a7a4082013-06-07 06:19:56 +0000302
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000303 const HexagonInstrInfo &TII = *HST.getInstrInfo();
304 if (TII.isValidAutoIncImm(LoadedVT, Val)) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000305 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000306 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000307 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000308 MVT::i32, MVT::Other, Base,
309 TargetConstVal, Chain);
310 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000311 MVT::i64, MVT::Other,
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000312 TargetConst0,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000313 SDValue(Result_1,0));
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000314 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
315 MemOp[0] = LD->getMemOperand();
316 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
317 const SDValue Froms[] = { SDValue(LD, 0),
318 SDValue(LD, 1),
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000319 SDValue(LD, 2) };
320 const SDValue Tos[] = { SDValue(Result_2, 0),
321 SDValue(Result_1, 1),
322 SDValue(Result_1, 2) };
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000323 ReplaceUses(Froms, Tos, 3);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000324 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000325 }
326
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000327 // Generate an indirect load.
328 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
329 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
330 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
331 MVT::Other, Base, TargetConst0,
332 Chain);
333 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A4_combineir, dl,
334 MVT::i64, MVT::Other,
335 TargetConst0,
336 SDValue(Result_1,0));
337 // Add offset to base.
338 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
339 Base, TargetConstVal,
340 SDValue(Result_1, 1));
341 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
342 MemOp[0] = LD->getMemOperand();
343 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
344 const SDValue Froms[] = { SDValue(LD, 0),
345 SDValue(LD, 1),
346 SDValue(LD, 2) };
347 const SDValue Tos[] = { SDValue(Result_2, 0), // Load value.
348 SDValue(Result_3, 0), // New address.
349 SDValue(Result_1, 1) };
350 ReplaceUses(Froms, Tos, 3);
351 return Result_2;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000352}
353
354
Andrew Trickef9de2a2013-05-25 02:42:55 +0000355SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000356 SDValue Chain = LD->getChain();
357 SDValue Base = LD->getBasePtr();
358 SDValue Offset = LD->getOffset();
359 SDNode *OffsetNode = Offset.getNode();
360 // Get the constant value.
361 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
362 EVT LoadedVT = LD->getMemoryVT();
363 unsigned Opcode = 0;
364
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000365 // Check for zero extended loads. Treat any-extend loads as zero extended
366 // loads.
367 ISD::LoadExtType ExtType = LD->getExtensionType();
368 bool IsZeroExt = (ExtType == ISD::ZEXTLOAD || ExtType == ISD::EXTLOAD);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000369
370 // Figure out the opcode.
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000371 const HexagonInstrInfo &TII = *HST.getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000372 if (LoadedVT == MVT::i64) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000373 if (TII.isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000374 Opcode = Hexagon::L2_loadrd_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000375 else
Colin LeMahieu947cd702014-12-23 20:44:59 +0000376 Opcode = Hexagon::L2_loadrd_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000377 } else if (LoadedVT == MVT::i32) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000378 if (TII.isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000379 Opcode = Hexagon::L2_loadri_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000380 else
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000381 Opcode = Hexagon::L2_loadri_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000382 } else if (LoadedVT == MVT::i16) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000383 if (TII.isValidAutoIncImm(LoadedVT, Val))
384 Opcode = IsZeroExt ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000385 else
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000386 Opcode = IsZeroExt ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000387 } else if (LoadedVT == MVT::i8) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000388 if (TII.isValidAutoIncImm(LoadedVT, Val))
389 Opcode = IsZeroExt ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000390 else
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000391 Opcode = IsZeroExt ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000392 } else
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000393 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000394
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000395 // For zero extended i64 loads, we need to add combine instructions.
396 if (LD->getValueType(0) == MVT::i64 && IsZeroExt)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000397 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000398 // Handle sign extended i64 loads.
399 if (LD->getValueType(0) == MVT::i64 && ExtType == ISD::SEXTLOAD)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000400 return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000401
402 if (TII.isValidAutoIncImm(LoadedVT, Val)) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000403 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
404 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
405 LD->getValueType(0),
406 MVT::i32, MVT::Other, Base,
407 TargetConstVal, Chain);
408 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
409 MemOp[0] = LD->getMemOperand();
410 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
411 const SDValue Froms[] = { SDValue(LD, 0),
412 SDValue(LD, 1),
413 SDValue(LD, 2)
414 };
415 const SDValue Tos[] = { SDValue(Result, 0),
416 SDValue(Result, 1),
417 SDValue(Result, 2)
418 };
419 ReplaceUses(Froms, Tos, 3);
420 return Result;
421 } else {
422 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
423 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
424 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
425 LD->getValueType(0),
426 MVT::Other, Base, TargetConst0,
427 Chain);
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000428 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000429 Base, TargetConstVal,
430 SDValue(Result_1, 1));
431 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
432 MemOp[0] = LD->getMemOperand();
433 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
434 const SDValue Froms[] = { SDValue(LD, 0),
435 SDValue(LD, 1),
436 SDValue(LD, 2)
437 };
438 const SDValue Tos[] = { SDValue(Result_1, 0),
439 SDValue(Result_2, 0),
440 SDValue(Result_1, 1)
441 };
442 ReplaceUses(Froms, Tos, 3);
443 return Result_1;
444 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000445}
446
447
448SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
449 SDNode *result;
Andrew Trickef9de2a2013-05-25 02:42:55 +0000450 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000451 LoadSDNode *LD = cast<LoadSDNode>(N);
452 ISD::MemIndexedMode AM = LD->getAddressingMode();
453
454 // Handle indexed loads.
455 if (AM != ISD::UNINDEXED) {
456 result = SelectIndexedLoad(LD, dl);
457 } else {
Colin LeMahieu2efa2d02015-03-09 21:48:13 +0000458 result = SelectCode(LD);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000459 }
460
461 return result;
462}
463
464
Andrew Trickef9de2a2013-05-25 02:42:55 +0000465SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000466 SDValue Chain = ST->getChain();
467 SDValue Base = ST->getBasePtr();
468 SDValue Offset = ST->getOffset();
469 SDValue Value = ST->getValue();
470 SDNode *OffsetNode = Offset.getNode();
471 // Get the constant value.
472 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
473 EVT StoredVT = ST->getMemoryVT();
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000474 EVT ValueVT = Value.getValueType();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000475
476 // Offset value must be within representable range
477 // and must have correct alignment properties.
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000478 const HexagonInstrInfo &TII = *HST.getInstrInfo();
479 if (TII.isValidAutoIncImm(StoredVT, Val)) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000480 unsigned Opcode = 0;
481
482 // Figure out the post inc version of opcode.
Colin LeMahieu9a3cd3f2014-12-29 20:00:43 +0000483 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi;
484 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi;
485 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi;
Colin LeMahieu3d34afb2014-12-29 19:42:14 +0000486 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000487 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000488
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000489 if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) {
490 assert(StoredVT.getSizeInBits() < 64 && "Not a truncating store");
491 Value = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg,
492 dl, MVT::i32, Value);
493 }
494 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value,
495 Chain};
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000496 // Build post increment store.
497 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +0000498 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000499 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
500 MemOp[0] = ST->getMemOperand();
501 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
502
503 ReplaceUses(ST, Result);
504 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
505 return Result;
506 }
507
508 // Note: Order of operands matches the def of instruction:
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +0000509 // def S2_storerd_io
510 // : STInst<(outs), (ins IntRegs:$base, imm:$offset, DoubleRegs:$src1), ...
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000511 // and it differs for POST_ST* for instance.
512 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value,
513 Chain};
514 unsigned Opcode = 0;
515
516 // Figure out the opcode.
Colin LeMahieubda31b42014-12-29 20:44:51 +0000517 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
518 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
519 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
520 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000521 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000522
523 // Build regular store.
524 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
Michael Liaob53d8962013-04-19 22:22:57 +0000525 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000526 // Build splitted incriment instruction.
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000527 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000528 Base,
529 TargetConstVal,
530 SDValue(Result_1, 0));
531 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
532 MemOp[0] = ST->getMemOperand();
533 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
534
535 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
536 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
537 return Result_2;
538}
539
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000540SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000541 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000542 StoreSDNode *ST = cast<StoreSDNode>(N);
543 ISD::MemIndexedMode AM = ST->getAddressingMode();
544
545 // Handle indexed stores.
546 if (AM != ISD::UNINDEXED) {
547 return SelectIndexedStore(ST, dl);
548 }
Sirish Pandec92c3162012-05-03 16:18:50 +0000549
Colin LeMahieu2efa2d02015-03-09 21:48:13 +0000550 return SelectCode(ST);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000551}
552
553SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000554 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000555
556 //
557 // %conv.i = sext i32 %tmp1 to i64
558 // %conv2.i = sext i32 %add to i64
559 // %mul.i = mul nsw i64 %conv2.i, %conv.i
560 //
561 // --- match with the following ---
562 //
563 // %mul.i = mpy (%tmp1, %add)
564 //
565
566 if (N->getValueType(0) == MVT::i64) {
567 // Shifting a i64 signed multiply.
568 SDValue MulOp0 = N->getOperand(0);
569 SDValue MulOp1 = N->getOperand(1);
570
571 SDValue OP0;
572 SDValue OP1;
573
574 // Handle sign_extend and sextload.
575 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
576 SDValue Sext0 = MulOp0.getOperand(0);
577 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000578 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000579 }
580
581 OP0 = Sext0;
582 } else if (MulOp0.getOpcode() == ISD::LOAD) {
583 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
584 if (LD->getMemoryVT() != MVT::i32 ||
585 LD->getExtensionType() != ISD::SEXTLOAD ||
586 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000587 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000588 }
589
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000590 SDValue Chain = LD->getChain();
591 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000592 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000593 MVT::Other,
594 LD->getBasePtr(), TargetConst0,
595 Chain), 0);
596 } else {
597 return SelectCode(N);
598 }
599
600 // Same goes for the second operand.
601 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
602 SDValue Sext1 = MulOp1.getOperand(0);
603 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
604 return SelectCode(N);
605 }
606
607 OP1 = Sext1;
608 } else if (MulOp1.getOpcode() == ISD::LOAD) {
609 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
610 if (LD->getMemoryVT() != MVT::i32 ||
611 LD->getExtensionType() != ISD::SEXTLOAD ||
612 LD->getAddressingMode() != ISD::UNINDEXED) {
613 return SelectCode(N);
614 }
615
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000616 SDValue Chain = LD->getChain();
617 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000618 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000619 MVT::Other,
620 LD->getBasePtr(), TargetConst0,
621 Chain), 0);
622 } else {
623 return SelectCode(N);
624 }
625
626 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +0000627 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000628 OP0, OP1);
629 ReplaceUses(N, Result);
630 return Result;
631 }
632
633 return SelectCode(N);
634}
635
636
637SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000638 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000639 SDValue N0 = N->getOperand(0);
640 if (N0.getOpcode() == ISD::SETCC) {
641 SDValue N00 = N0.getOperand(0);
642 if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) {
643 SDValue N000 = N00.getOperand(0);
644 SDValue N001 = N00.getOperand(1);
645 if (cast<VTSDNode>(N001)->getVT() == MVT::i16) {
646 SDValue N01 = N0.getOperand(1);
647 SDValue N02 = N0.getOperand(2);
648
649 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
650 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1,
651 // IntRegs:i32:$src2)
652 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
653 // Pattern complexity = 9 cost = 1 size = 0.
654 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) {
655 SDValue N1 = N->getOperand(1);
656 if (N01 == N1) {
657 SDValue N2 = N->getOperand(2);
658 if (N000 == N2 &&
659 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
660 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
Colin LeMahieu310991c2014-11-21 21:54:59 +0000661 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000662 MVT::i32, N000);
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000663 SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_max, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000664 MVT::i32,
665 SDValue(SextNode, 0),
666 N1);
667 ReplaceUses(N, Result);
668 return Result;
669 }
670 }
671 }
672
673 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
674 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1,
675 // IntRegs:i32:$src2)
676 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
677 // Pattern complexity = 9 cost = 1 size = 0.
678 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) {
679 SDValue N1 = N->getOperand(1);
680 if (N01 == N1) {
681 SDValue N2 = N->getOperand(2);
682 if (N000 == N2 &&
683 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
684 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
Colin LeMahieu310991c2014-11-21 21:54:59 +0000685 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000686 MVT::i32, N000);
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000687 SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_min, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000688 MVT::i32,
689 SDValue(SextNode, 0),
690 N1);
691 ReplaceUses(N, Result);
692 return Result;
693 }
694 }
695 }
696 }
697 }
698 }
699
700 return SelectCode(N);
701}
702
703
704SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000705 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000706 SDValue Shift = N->getOperand(0);
707
708 //
709 // %conv.i = sext i32 %tmp1 to i64
710 // %conv2.i = sext i32 %add to i64
711 // %mul.i = mul nsw i64 %conv2.i, %conv.i
712 // %shr5.i = lshr i64 %mul.i, 32
713 // %conv3.i = trunc i64 %shr5.i to i32
714 //
715 // --- match with the following ---
716 //
717 // %conv3.i = mpy (%tmp1, %add)
718 //
719 // Trunc to i32.
720 if (N->getValueType(0) == MVT::i32) {
721 // Trunc from i64.
722 if (Shift.getNode()->getValueType(0) == MVT::i64) {
723 // Trunc child is logical shift right.
724 if (Shift.getOpcode() != ISD::SRL) {
725 return SelectCode(N);
726 }
727
728 SDValue ShiftOp0 = Shift.getOperand(0);
729 SDValue ShiftOp1 = Shift.getOperand(1);
730
731 // Shift by const 32
732 if (ShiftOp1.getOpcode() != ISD::Constant) {
733 return SelectCode(N);
734 }
735
736 int32_t ShiftConst =
737 cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue();
738 if (ShiftConst != 32) {
739 return SelectCode(N);
740 }
741
742 // Shifting a i64 signed multiply
743 SDValue Mul = ShiftOp0;
744 if (Mul.getOpcode() != ISD::MUL) {
745 return SelectCode(N);
746 }
747
748 SDValue MulOp0 = Mul.getOperand(0);
749 SDValue MulOp1 = Mul.getOperand(1);
750
751 SDValue OP0;
752 SDValue OP1;
753
754 // Handle sign_extend and sextload
755 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
756 SDValue Sext0 = MulOp0.getOperand(0);
757 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
758 return SelectCode(N);
759 }
760
761 OP0 = Sext0;
762 } else if (MulOp0.getOpcode() == ISD::LOAD) {
763 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
764 if (LD->getMemoryVT() != MVT::i32 ||
765 LD->getExtensionType() != ISD::SEXTLOAD ||
766 LD->getAddressingMode() != ISD::UNINDEXED) {
767 return SelectCode(N);
768 }
769
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000770 SDValue Chain = LD->getChain();
771 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000772 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000773 MVT::Other,
774 LD->getBasePtr(),
775 TargetConst0, Chain), 0);
776 } else {
777 return SelectCode(N);
778 }
779
780 // Same goes for the second operand.
781 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
782 SDValue Sext1 = MulOp1.getOperand(0);
783 if (Sext1.getNode()->getValueType(0) != MVT::i32)
784 return SelectCode(N);
785
786 OP1 = Sext1;
787 } else if (MulOp1.getOpcode() == ISD::LOAD) {
788 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
789 if (LD->getMemoryVT() != MVT::i32 ||
790 LD->getExtensionType() != ISD::SEXTLOAD ||
791 LD->getAddressingMode() != ISD::UNINDEXED) {
792 return SelectCode(N);
793 }
794
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000795 SDValue Chain = LD->getChain();
796 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000797 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000798 MVT::Other,
799 LD->getBasePtr(),
800 TargetConst0, Chain), 0);
801 } else {
802 return SelectCode(N);
803 }
804
805 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +0000806 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpy_up, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000807 OP0, OP1);
808 ReplaceUses(N, Result);
809 return Result;
810 }
811 }
812
813 return SelectCode(N);
814}
815
816
817SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000818 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000819 if (N->getValueType(0) == MVT::i32) {
820 SDValue Shl_0 = N->getOperand(0);
821 SDValue Shl_1 = N->getOperand(1);
822 // RHS is const.
823 if (Shl_1.getOpcode() == ISD::Constant) {
824 if (Shl_0.getOpcode() == ISD::MUL) {
825 SDValue Mul_0 = Shl_0.getOperand(0); // Val
826 SDValue Mul_1 = Shl_0.getOperand(1); // Const
827 // RHS of mul is const.
828 if (Mul_1.getOpcode() == ISD::Constant) {
829 int32_t ShlConst =
830 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
831 int32_t MulConst =
832 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
833 int32_t ValConst = MulConst << ShlConst;
834 SDValue Val = CurDAG->getTargetConstant(ValConst,
835 MVT::i32);
836 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
837 if (isInt<9>(CN->getSExtValue())) {
838 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000839 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000840 MVT::i32, Mul_0, Val);
841 ReplaceUses(N, Result);
842 return Result;
843 }
844
845 }
846 } else if (Shl_0.getOpcode() == ISD::SUB) {
847 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
848 SDValue Sub_1 = Shl_0.getOperand(1); // Val
849 if (Sub_0.getOpcode() == ISD::Constant) {
850 int32_t SubConst =
851 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
852 if (SubConst == 0) {
853 if (Sub_1.getOpcode() == ISD::SHL) {
854 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
855 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
856 if (Shl2_1.getOpcode() == ISD::Constant) {
857 int32_t ShlConst =
858 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
859 int32_t Shl2Const =
860 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
861 int32_t ValConst = 1 << (ShlConst+Shl2Const);
862 SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32);
863 if (ConstantSDNode *CN =
864 dyn_cast<ConstantSDNode>(Val.getNode()))
865 if (isInt<9>(CN->getSExtValue())) {
866 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000867 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000868 Shl2_0, Val);
869 ReplaceUses(N, Result);
870 return Result;
871 }
872 }
873 }
874 }
875 }
876 }
877 }
878 }
879 return SelectCode(N);
880}
881
882
883//
884// If there is an zero_extend followed an intrinsic in DAG (this means - the
885// result of the intrinsic is predicate); convert the zero_extend to
886// transfer instruction.
887//
888// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
889// converted into a MUX as predicate registers defined as 1 bit in the
890// compiler. Architecture defines them as 8-bit registers.
891// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
892//
893SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000894 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000895 SDNode *IsIntrinsic = N->getOperand(0).getNode();
896 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
897 unsigned ID =
898 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
899 if (doesIntrinsicReturnPredicate(ID)) {
900 // Now we need to differentiate target data types.
901 if (N->getValueType(0) == MVT::i64) {
902 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs).
903 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu30dcb232014-12-09 18:16:49 +0000904 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000905 MVT::i32,
906 SDValue(IsIntrinsic, 0));
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000907 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000908 MVT::i32,
909 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000910 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000911 MVT::i64, MVT::Other,
912 SDValue(Result_2, 0),
913 SDValue(Result_1, 0));
914 ReplaceUses(N, Result_3);
915 return Result_3;
916 }
917 if (N->getValueType(0) == MVT::i32) {
918 // Convert the zero_extend to Rs = Pd
Colin LeMahieu30dcb232014-12-09 18:16:49 +0000919 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000920 MVT::i32,
921 SDValue(IsIntrinsic, 0));
922 ReplaceUses(N, RsPd);
923 return RsPd;
924 }
Craig Toppere55c5562012-02-07 02:50:20 +0000925 llvm_unreachable("Unexpected value type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000926 }
927 }
928 return SelectCode(N);
929}
930
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000931//
932// Checking for intrinsics which have predicate registers as operand(s)
933// and lowering to the actual intrinsic.
934//
935SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +0000936 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
937 unsigned Bits;
938 switch (IID) {
939 case Intrinsic::hexagon_S2_vsplatrb:
940 Bits = 8;
941 break;
942 case Intrinsic::hexagon_S2_vsplatrh:
943 Bits = 16;
944 break;
945 default:
946 return SelectCode(N);
947 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000948
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +0000949 SDValue const &V = N->getOperand(1);
950 SDValue U;
951 if (isValueExtension(V, Bits, U)) {
952 SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
953 N->getOperand(0), U);
954 return SelectCode(R.getNode());
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000955 }
956 return SelectCode(N);
957}
958
Sirish Pande69295b82012-05-10 20:20:25 +0000959//
960// Map floating point constant values.
961//
962SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000963 SDLoc dl(N);
Sirish Pande69295b82012-05-10 20:20:25 +0000964 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
965 APFloat APF = CN->getValueAPF();
966 if (N->getValueType(0) == MVT::f32) {
967 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
968 CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32));
969 }
970 else if (N->getValueType(0) == MVT::f64) {
971 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
972 CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64));
973 }
974
975 return SelectCode(N);
976}
977
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000978//
979// Map predicate true (encoded as -1 in LLVM) to a XOR.
980//
981SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000982 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000983 if (N->getValueType(0) == MVT::i1) {
984 SDNode* Result;
985 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
986 if (Val == -1) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000987 // Create the IntReg = 1 node.
988 SDNode* IntRegTFR =
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000989 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000990 CurDAG->getTargetConstant(0, MVT::i32));
991
992 // Pd = IntReg
Colin LeMahieu30dcb232014-12-09 18:16:49 +0000993 SDNode* Pd = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000994 SDValue(IntRegTFR, 0));
995
996 // not(Pd)
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000997 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::C2_not, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000998 SDValue(Pd, 0));
999
1000 // xor(not(Pd))
Colin LeMahieu5cf56322014-12-08 23:55:43 +00001001 Result = CurDAG->getMachineNode(Hexagon::C2_xor, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001002 SDValue(Pd, 0), SDValue(NotPd, 0));
1003
1004 // We have just built:
1005 // Rs = Pd
1006 // Pd = xor(not(Pd), Pd)
1007
1008 ReplaceUses(N, Result);
1009 return Result;
1010 }
1011 }
1012
1013 return SelectCode(N);
1014}
1015
1016
1017//
1018// Map add followed by a asr -> asr +=.
1019//
1020SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001021 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001022 if (N->getValueType(0) != MVT::i32) {
1023 return SelectCode(N);
1024 }
1025 // Identify nodes of the form: add(asr(...)).
1026 SDNode* Src1 = N->getOperand(0).getNode();
1027 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1028 || Src1->getValueType(0) != MVT::i32) {
1029 return SelectCode(N);
1030 }
1031
1032 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1033 // Rd and Rd' are assigned to the same register
Colin LeMahieu0f850bd2014-12-19 20:29:29 +00001034 SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001035 N->getOperand(1),
1036 Src1->getOperand(0),
1037 Src1->getOperand(1));
1038 ReplaceUses(N, Result);
1039
1040 return Result;
1041}
1042
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001043SDNode *HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) {
1044 int FX = cast<FrameIndexSDNode>(N)->getIndex();
1045 SDValue FI = CurDAG->getTargetFrameIndex(FX, MVT::i32);
1046 SDValue Zero = CurDAG->getTargetConstant(0, MVT::i32);
1047 SDLoc DL(N);
1048
1049 SDNode *R = CurDAG->getMachineNode(Hexagon::TFR_FI, DL, MVT::i32, FI, Zero);
1050
1051 if (N->getHasDebugValue())
1052 CurDAG->TransferDbgValues(SDValue(N, 0), SDValue(R, 0));
1053 return R;
1054}
1055
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001056
1057SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
Tim Northover31d093c2013-09-22 08:21:56 +00001058 if (N->isMachineOpcode()) {
1059 N->setNodeId(-1);
Craig Topper062a2ba2014-04-25 05:30:21 +00001060 return nullptr; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00001061 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001062
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001063 switch (N->getOpcode()) {
1064 case ISD::Constant:
1065 return SelectConstant(N);
1066
Sirish Pande69295b82012-05-10 20:20:25 +00001067 case ISD::ConstantFP:
1068 return SelectConstantFP(N);
1069
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001070 case ISD::FrameIndex:
1071 return SelectFrameIndex(N);
1072
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001073 case ISD::ADD:
1074 return SelectAdd(N);
1075
1076 case ISD::SHL:
1077 return SelectSHL(N);
1078
1079 case ISD::LOAD:
1080 return SelectLoad(N);
1081
1082 case ISD::STORE:
1083 return SelectStore(N);
1084
1085 case ISD::SELECT:
1086 return SelectSelect(N);
1087
1088 case ISD::TRUNCATE:
1089 return SelectTruncate(N);
1090
1091 case ISD::MUL:
1092 return SelectMul(N);
1093
1094 case ISD::ZERO_EXTEND:
1095 return SelectZeroExtend(N);
1096
1097 case ISD::INTRINSIC_WO_CHAIN:
1098 return SelectIntrinsicWOChain(N);
1099 }
1100
1101 return SelectCode(N);
1102}
1103
1104
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001105bool HexagonDAGToDAGISel::
Daniel Sanders41c072e2015-03-12 11:00:48 +00001106SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001107 std::vector<SDValue> &OutOps) {
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001108 SDValue Inp = Op, Res;
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001109
Daniel Sanders41c072e2015-03-12 11:00:48 +00001110 switch (ConstraintID) {
1111 case InlineAsm::Constraint_o: // Offsetable.
1112 case InlineAsm::Constraint_v: // Not offsetable.
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001113 default:
1114 return true;
Daniel Sanders41c072e2015-03-12 11:00:48 +00001115 case InlineAsm::Constraint_m: // Memory.
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001116 if (SelectAddrFI(Inp, Res))
1117 OutOps.push_back(Res);
1118 else
1119 OutOps.push_back(Inp);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001120 break;
1121 }
1122
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001123 OutOps.push_back(CurDAG->getTargetConstant(0, MVT::i32));
Jyotsna Vermad9225242013-02-13 21:38:46 +00001124 return false;
1125}
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001126
1127bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) {
1128 if (N.getOpcode() != ISD::FrameIndex)
1129 return false;
1130 FrameIndexSDNode *FX = cast<FrameIndexSDNode>(N);
1131 R = CurDAG->getTargetFrameIndex(FX->getIndex(), MVT::i32);
1132 return true;
1133}
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001134
Colin LeMahieu987b0942015-02-04 20:38:01 +00001135inline bool HexagonDAGToDAGISel::SelectAddrGA(SDValue &N, SDValue &R) {
1136 return SelectGlobalAddress(N, R, false);
1137}
1138
Colin LeMahieu51491352015-02-04 22:36:28 +00001139inline bool HexagonDAGToDAGISel::SelectAddrGP(SDValue &N, SDValue &R) {
1140 return SelectGlobalAddress(N, R, true);
1141}
1142
Colin LeMahieu987b0942015-02-04 20:38:01 +00001143bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
1144 bool UseGP) {
1145 switch (N.getOpcode()) {
1146 case ISD::ADD: {
1147 SDValue N0 = N.getOperand(0);
1148 SDValue N1 = N.getOperand(1);
1149 unsigned GAOpc = N0.getOpcode();
1150 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1151 return false;
1152 if (!UseGP && GAOpc != HexagonISD::CONST32)
1153 return false;
1154 if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) {
1155 SDValue Addr = N0.getOperand(0);
1156 if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Addr)) {
1157 if (GA->getOpcode() == ISD::TargetGlobalAddress) {
1158 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1159 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),
1160 N.getValueType(), NewOff);
1161 return true;
1162 }
1163 }
1164 }
1165 break;
1166 }
1167 case HexagonISD::CONST32:
1168 // The operand(0) of CONST32 is TargetGlobalAddress, which is what we
1169 // want in the instruction.
1170 if (!UseGP)
1171 R = N.getOperand(0);
1172 return !UseGP;
1173 case HexagonISD::CONST32_GP:
1174 if (UseGP)
1175 R = N.getOperand(0);
1176 return UseGP;
1177 default:
1178 return false;
1179 }
1180
1181 return false;
1182}
1183
Krzysztof Parzyszeka29622a2015-03-12 16:44:50 +00001184bool HexagonDAGToDAGISel::isValueExtension(const SDValue &Val,
1185 unsigned FromBits, SDValue &Src) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001186 unsigned Opc = Val.getOpcode();
1187 switch (Opc) {
1188 case ISD::SIGN_EXTEND:
1189 case ISD::ZERO_EXTEND:
1190 case ISD::ANY_EXTEND: {
1191 SDValue const &Op0 = Val.getOperand(0);
1192 EVT T = Op0.getValueType();
1193 if (T.isInteger() && T.getSizeInBits() == FromBits) {
1194 Src = Op0;
1195 return true;
1196 }
1197 break;
1198 }
1199 case ISD::SIGN_EXTEND_INREG:
1200 case ISD::AssertSext:
1201 case ISD::AssertZext:
1202 if (Val.getOperand(0).getValueType().isInteger()) {
1203 VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
1204 if (T->getVT().getSizeInBits() == FromBits) {
1205 Src = Val.getOperand(0);
1206 return true;
1207 }
1208 }
1209 break;
1210 case ISD::AND: {
1211 // Check if this is an AND with "FromBits" of lower bits set to 1.
1212 uint64_t FromMask = (1 << FromBits) - 1;
1213 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1214 if (C->getZExtValue() == FromMask) {
1215 Src = Val.getOperand(1);
1216 return true;
1217 }
1218 }
1219 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1220 if (C->getZExtValue() == FromMask) {
1221 Src = Val.getOperand(0);
1222 return true;
1223 }
1224 }
1225 break;
1226 }
1227 case ISD::OR:
1228 case ISD::XOR: {
1229 // OR/XOR with the lower "FromBits" bits set to 0.
1230 uint64_t FromMask = (1 << FromBits) - 1;
1231 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1232 if ((C->getZExtValue() & FromMask) == 0) {
1233 Src = Val.getOperand(1);
1234 return true;
1235 }
1236 }
1237 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1238 if ((C->getZExtValue() & FromMask) == 0) {
1239 Src = Val.getOperand(0);
1240 return true;
1241 }
1242 }
1243 }
1244 default:
1245 break;
1246 }
1247 return false;
1248}