1//===-- LanaiISelLowering.cpp - Lanai DAG Lowering Implementation ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the LanaiTargetLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "LanaiISelLowering.h"
14#include "LanaiCondCode.h"
15#include "LanaiMachineFunctionInfo.h"
16#include "LanaiSubtarget.h"
17#include "LanaiTargetObjectFile.h"
18#include "MCTargetDesc/LanaiBaseInfo.h"
19#include "llvm/ADT/APInt.h"
20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/ADT/StringSwitch.h"
24#include "llvm/CodeGen/CallingConvLower.h"
25#include "llvm/CodeGen/MachineFrameInfo.h"
26#include "llvm/CodeGen/MachineFunction.h"
27#include "llvm/CodeGen/MachineMemOperand.h"
28#include "llvm/CodeGen/MachineRegisterInfo.h"
29#include "llvm/CodeGen/SelectionDAG.h"
30#include "llvm/CodeGen/SelectionDAGNodes.h"
31#include "llvm/CodeGen/TargetCallingConv.h"
32#include "llvm/CodeGen/ValueTypes.h"
33#include "llvm/CodeGenTypes/MachineValueType.h"
34#include "llvm/IR/CallingConv.h"
35#include "llvm/IR/DerivedTypes.h"
36#include "llvm/IR/Function.h"
37#include "llvm/IR/GlobalValue.h"
38#include "llvm/Support/Casting.h"
39#include "llvm/Support/CodeGen.h"
40#include "llvm/Support/CommandLine.h"
41#include "llvm/Support/Debug.h"
42#include "llvm/Support/ErrorHandling.h"
43#include "llvm/Support/KnownBits.h"
44#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/raw_ostream.h"
46#include "llvm/Target/TargetMachine.h"
47#include <cassert>
48#include <cmath>
49#include <cstdint>
50#include <cstdlib>
51#include <utility>
52
53#define DEBUG_TYPE "lanai-lower"
54
55using namespace llvm;
56
57// Limit on number of instructions the lowered multiplication may have before a
58// call to the library function should be generated instead. The threshold is
59// currently set to 14 as this was the smallest threshold that resulted in all
60// constant multiplications being lowered. A threshold of 5 covered all cases
61// except for one multiplication which required 14. mulsi3 requires 16
62// instructions (including the prologue and epilogue but excluding instructions
63// at call site). Until we can inline mulsi3, generating at most 14 instructions
64// will be faster than invoking mulsi3.
65static cl::opt<int> LanaiLowerConstantMulThreshold(
66 "lanai-constant-mul-threshold", cl::Hidden,
67 cl::desc("Maximum number of instruction to generate when lowering constant "
68 "multiplication instead of calling library function [default=14]"),
69 cl::init(Val: 14));
70
71LanaiTargetLowering::LanaiTargetLowering(const TargetMachine &TM,
72 const LanaiSubtarget &STI)
73 : TargetLowering(TM, STI) {
74 // Set up the register classes.
75 addRegisterClass(VT: MVT::i32, RC: &Lanai::GPRRegClass);
76
77 // Compute derived properties from the register classes
78 TRI = STI.getRegisterInfo();
79 computeRegisterProperties(TRI);
80
81 setStackPointerRegisterToSaveRestore(Lanai::SP);
82
83 setOperationAction(Op: ISD::BR_CC, VT: MVT::i32, Action: Custom);
84 setOperationAction(Op: ISD::BR_JT, VT: MVT::Other, Action: Expand);
85 setOperationAction(Op: ISD::BRCOND, VT: MVT::Other, Action: Expand);
86 setOperationAction(Op: ISD::SETCC, VT: MVT::i32, Action: Custom);
87 setOperationAction(Op: ISD::SELECT, VT: MVT::i32, Action: Expand);
88 setOperationAction(Op: ISD::SELECT_CC, VT: MVT::i32, Action: Custom);
89
90 setOperationAction(Op: ISD::GlobalAddress, VT: MVT::i32, Action: Custom);
91 setOperationAction(Op: ISD::BlockAddress, VT: MVT::i32, Action: Custom);
92 setOperationAction(Op: ISD::JumpTable, VT: MVT::i32, Action: Custom);
93 setOperationAction(Op: ISD::ConstantPool, VT: MVT::i32, Action: Custom);
94
95 setOperationAction(Op: ISD::DYNAMIC_STACKALLOC, VT: MVT::i32, Action: Custom);
96 setOperationAction(Op: ISD::STACKSAVE, VT: MVT::Other, Action: Expand);
97 setOperationAction(Op: ISD::STACKRESTORE, VT: MVT::Other, Action: Expand);
98
99 setOperationAction(Op: ISD::VASTART, VT: MVT::Other, Action: Custom);
100 setOperationAction(Op: ISD::VAARG, VT: MVT::Other, Action: Expand);
101 setOperationAction(Op: ISD::VACOPY, VT: MVT::Other, Action: Expand);
102 setOperationAction(Op: ISD::VAEND, VT: MVT::Other, Action: Expand);
103
104 setOperationAction(Op: ISD::SDIV, VT: MVT::i32, Action: Expand);
105 setOperationAction(Op: ISD::UDIV, VT: MVT::i32, Action: Expand);
106 setOperationAction(Op: ISD::SDIVREM, VT: MVT::i32, Action: Expand);
107 setOperationAction(Op: ISD::UDIVREM, VT: MVT::i32, Action: Expand);
108 setOperationAction(Op: ISD::SREM, VT: MVT::i32, Action: Expand);
109 setOperationAction(Op: ISD::UREM, VT: MVT::i32, Action: Expand);
110
111 setOperationAction(Op: ISD::MUL, VT: MVT::i32, Action: Custom);
112 setOperationAction(Op: ISD::MULHU, VT: MVT::i32, Action: Expand);
113 setOperationAction(Op: ISD::MULHS, VT: MVT::i32, Action: Expand);
114 setOperationAction(Op: ISD::UMUL_LOHI, VT: MVT::i32, Action: Expand);
115 setOperationAction(Op: ISD::SMUL_LOHI, VT: MVT::i32, Action: Expand);
116
117 setOperationAction(Op: ISD::ROTR, VT: MVT::i32, Action: Expand);
118 setOperationAction(Op: ISD::ROTL, VT: MVT::i32, Action: Expand);
119 setOperationAction(Op: ISD::SHL_PARTS, VT: MVT::i32, Action: Custom);
120 setOperationAction(Op: ISD::SRL_PARTS, VT: MVT::i32, Action: Custom);
121 setOperationAction(Op: ISD::SRA_PARTS, VT: MVT::i32, Action: Expand);
122
123 setOperationAction(Op: ISD::BSWAP, VT: MVT::i32, Action: Expand);
124 setOperationAction(Op: ISD::CTPOP, VT: MVT::i32, Action: Legal);
125 setOperationAction(Op: ISD::CTLZ, VT: MVT::i32, Action: Legal);
126 setOperationAction(Op: ISD::CTTZ, VT: MVT::i32, Action: Legal);
127
128 setOperationAction(Op: ISD::SIGN_EXTEND_INREG, VT: MVT::i1, Action: Expand);
129 setOperationAction(Op: ISD::SIGN_EXTEND_INREG, VT: MVT::i8, Action: Expand);
130 setOperationAction(Op: ISD::SIGN_EXTEND_INREG, VT: MVT::i16, Action: Expand);
131
132 // Extended load operations for i1 types must be promoted
133 for (MVT VT : MVT::integer_valuetypes()) {
134 setLoadExtAction(ExtType: ISD::EXTLOAD, ValVT: VT, MemVT: MVT::i1, Action: Promote);
135 setLoadExtAction(ExtType: ISD::ZEXTLOAD, ValVT: VT, MemVT: MVT::i1, Action: Promote);
136 setLoadExtAction(ExtType: ISD::SEXTLOAD, ValVT: VT, MemVT: MVT::i1, Action: Promote);
137 }
138
139 setTargetDAGCombine({ISD::ADD, ISD::SUB, ISD::AND, ISD::OR, ISD::XOR});
140
141 // Function alignments
142 setMinFunctionAlignment(Align(4));
143 setPrefFunctionAlignment(Align(4));
144
145 setJumpIsExpensive(true);
146
147 // TODO: Setting the minimum jump table entries needed before a
148 // switch is transformed to a jump table to 100 to avoid creating jump tables
149 // as this was causing bad performance compared to a large group of if
150 // statements. Re-evaluate this on new benchmarks.
151 setMinimumJumpTableEntries(100);
152
153 MaxStoresPerMemset = 16; // For @llvm.memset -> sequence of stores
154 MaxStoresPerMemsetOptSize = 8;
155 MaxStoresPerMemcpy = 16; // For @llvm.memcpy -> sequence of stores
156 MaxStoresPerMemcpyOptSize = 8;
157 MaxStoresPerMemmove = 16; // For @llvm.memmove -> sequence of stores
158 MaxStoresPerMemmoveOptSize = 8;
159
160 // Booleans always contain 0 or 1.
161 setBooleanContents(ZeroOrOneBooleanContent);
162
163 setMaxAtomicSizeInBitsSupported(0);
164}
165
166SDValue LanaiTargetLowering::LowerOperation(SDValue Op,
167 SelectionDAG &DAG) const {
168 switch (Op.getOpcode()) {
169 case ISD::MUL:
170 return LowerMUL(Op, DAG);
171 case ISD::BR_CC:
172 return LowerBR_CC(Op, DAG);
173 case ISD::ConstantPool:
174 return LowerConstantPool(Op, DAG);
175 case ISD::GlobalAddress:
176 return LowerGlobalAddress(Op, DAG);
177 case ISD::BlockAddress:
178 return LowerBlockAddress(Op, DAG);
179 case ISD::JumpTable:
180 return LowerJumpTable(Op, DAG);
181 case ISD::SELECT_CC:
182 return LowerSELECT_CC(Op, DAG);
183 case ISD::SETCC:
184 return LowerSETCC(Op, DAG);
185 case ISD::SHL_PARTS:
186 return LowerSHL_PARTS(Op, DAG);
187 case ISD::SRL_PARTS:
188 return LowerSRL_PARTS(Op, DAG);
189 case ISD::VASTART:
190 return LowerVASTART(Op, DAG);
191 case ISD::DYNAMIC_STACKALLOC:
192 return LowerDYNAMIC_STACKALLOC(Op, DAG);
193 case ISD::RETURNADDR:
194 return LowerRETURNADDR(Op, DAG);
195 case ISD::FRAMEADDR:
196 return LowerFRAMEADDR(Op, DAG);
197 default:
198 llvm_unreachable("unimplemented operand");
199 }
200}
201
202//===----------------------------------------------------------------------===//
203// Lanai Inline Assembly Support
204//===----------------------------------------------------------------------===//
205
206Register LanaiTargetLowering::getRegisterByName(
207 const char *RegName, LLT /*VT*/,
208 const MachineFunction & /*MF*/) const {
209 // Only unallocatable registers should be matched here.
210 Register Reg = StringSwitch<Register>(RegName)
211 .Case(S: "pc", Value: Lanai::PC)
212 .Case(S: "sp", Value: Lanai::SP)
213 .Case(S: "fp", Value: Lanai::FP)
214 .Case(S: "rr1", Value: Lanai::RR1)
215 .Case(S: "r10", Value: Lanai::R10)
216 .Case(S: "rr2", Value: Lanai::RR2)
217 .Case(S: "r11", Value: Lanai::R11)
218 .Case(S: "rca", Value: Lanai::RCA)
219 .Default(Value: Register());
220 return Reg;
221}
222
223std::pair<unsigned, const TargetRegisterClass *>
224LanaiTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
225 StringRef Constraint,
226 MVT VT) const {
227 if (Constraint.size() == 1)
228 // GCC Constraint Letters
229 switch (Constraint[0]) {
230 case 'r': // GENERAL_REGS
231 return std::make_pair(x: 0U, y: &Lanai::GPRRegClass);
232 default:
233 break;
234 }
235
236 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
237}
238
239// Examine constraint type and operand type and determine a weight value.
240// This object must already have been set up with the operand type
241// and the current alternative constraint selected.
242TargetLowering::ConstraintWeight
243LanaiTargetLowering::getSingleConstraintMatchWeight(
244 AsmOperandInfo &Info, const char *Constraint) const {
245 ConstraintWeight Weight = CW_Invalid;
246 Value *CallOperandVal = Info.CallOperandVal;
247 // If we don't have a value, we can't do a match,
248 // but allow it at the lowest weight.
249 if (CallOperandVal == nullptr)
250 return CW_Default;
251 // Look at the constraint type.
252 switch (*Constraint) {
253 case 'I': // signed 16 bit immediate
254 case 'J': // integer zero
255 case 'K': // unsigned 16 bit immediate
256 case 'L': // immediate in the range 0 to 31
257 case 'M': // signed 32 bit immediate where lower 16 bits are 0
258 case 'N': // signed 26 bit immediate
259 case 'O': // integer zero
260 if (isa<ConstantInt>(Val: CallOperandVal))
261 Weight = CW_Constant;
262 break;
263 default:
264 Weight = TargetLowering::getSingleConstraintMatchWeight(info&: Info, constraint: Constraint);
265 break;
266 }
267 return Weight;
268}
269
270// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
271// vector. If it is invalid, don't add anything to Ops.
272void LanaiTargetLowering::LowerAsmOperandForConstraint(
273 SDValue Op, StringRef Constraint, std::vector<SDValue> &Ops,
274 SelectionDAG &DAG) const {
275 SDValue Result;
276
277 // Only support length 1 constraints for now.
278 if (Constraint.size() > 1)
279 return;
280
281 char ConstraintLetter = Constraint[0];
282 switch (ConstraintLetter) {
283 case 'I': // Signed 16 bit constant
284 // If this fails, the parent routine will give an error
285 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val&: Op)) {
286 if (isInt<16>(x: C->getSExtValue())) {
287 Result = DAG.getTargetConstant(Val: C->getSExtValue(), DL: SDLoc(C),
288 VT: Op.getValueType());
289 break;
290 }
291 }
292 return;
293 case 'J': // integer zero
294 case 'O':
295 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val&: Op)) {
296 if (C->getZExtValue() == 0) {
297 Result = DAG.getTargetConstant(Val: 0, DL: SDLoc(C), VT: Op.getValueType());
298 break;
299 }
300 }
301 return;
302 case 'K': // unsigned 16 bit immediate
303 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val&: Op)) {
304 if (isUInt<16>(x: C->getZExtValue())) {
305 Result = DAG.getTargetConstant(Val: C->getSExtValue(), DL: SDLoc(C),
306 VT: Op.getValueType());
307 break;
308 }
309 }
310 return;
311 case 'L': // immediate in the range 0 to 31
312 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val&: Op)) {
313 if (C->getZExtValue() <= 31) {
314 Result = DAG.getTargetConstant(Val: C->getZExtValue(), DL: SDLoc(C),
315 VT: Op.getValueType());
316 break;
317 }
318 }
319 return;
320 case 'M': // signed 32 bit immediate where lower 16 bits are 0
321 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val&: Op)) {
322 int64_t Val = C->getSExtValue();
323 if ((isInt<32>(x: Val)) && ((Val & 0xffff) == 0)) {
324 Result = DAG.getTargetConstant(Val, DL: SDLoc(C), VT: Op.getValueType());
325 break;
326 }
327 }
328 return;
329 case 'N': // signed 26 bit immediate
330 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val&: Op)) {
331 int64_t Val = C->getSExtValue();
332 if ((Val >= -33554432) && (Val <= 33554431)) {
333 Result = DAG.getTargetConstant(Val, DL: SDLoc(C), VT: Op.getValueType());
334 break;
335 }
336 }
337 return;
338 default:
339 break; // This will fall through to the generic implementation
340 }
341
342 if (Result.getNode()) {
343 Ops.push_back(x: Result);
344 return;
345 }
346
347 TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
348}
349
350//===----------------------------------------------------------------------===//
351// Calling Convention Implementation
352//===----------------------------------------------------------------------===//
353
354#define GET_CALLING_CONV_IMPL
355#include "LanaiGenCallingConv.inc"
356
357static bool CC_Lanai32_VarArg(unsigned ValNo, MVT ValVT, MVT LocVT,
358 CCValAssign::LocInfo LocInfo,
359 ISD::ArgFlagsTy ArgFlags, Type *OrigTy,
360 CCState &State) {
361 // Handle fixed arguments with default CC.
362 // Note: Both the default and fast CC handle VarArg the same and hence the
363 // calling convention of the function is not considered here.
364 if (!ArgFlags.isVarArg())
365 return CC_Lanai32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, OrigTy, State);
366
367 // Promote i8/i16 args to i32
368 if (LocVT == MVT::i8 || LocVT == MVT::i16) {
369 LocVT = MVT::i32;
370 if (ArgFlags.isSExt())
371 LocInfo = CCValAssign::SExt;
372 else if (ArgFlags.isZExt())
373 LocInfo = CCValAssign::ZExt;
374 else
375 LocInfo = CCValAssign::AExt;
376 }
377
378 // VarArgs get passed on stack
379 unsigned Offset = State.AllocateStack(Size: 4, Alignment: Align(4));
380 State.addLoc(V: CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, HTP: LocInfo));
381 return false;
382}
383
384SDValue LanaiTargetLowering::LowerFormalArguments(
385 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
386 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
387 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
388 switch (CallConv) {
389 case CallingConv::C:
390 case CallingConv::Fast:
391 return LowerCCCArguments(Chain, CallConv, IsVarArg, Ins, DL, DAG, InVals);
392 default:
393 report_fatal_error(reason: "Unsupported calling convention");
394 }
395}
396
397SDValue LanaiTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
398 SmallVectorImpl<SDValue> &InVals) const {
399 SelectionDAG &DAG = CLI.DAG;
400 SDLoc &DL = CLI.DL;
401 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
402 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
403 SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
404 SDValue Chain = CLI.Chain;
405 SDValue Callee = CLI.Callee;
406 bool &IsTailCall = CLI.IsTailCall;
407 CallingConv::ID CallConv = CLI.CallConv;
408 bool IsVarArg = CLI.IsVarArg;
409
410 // Lanai target does not yet support tail call optimization.
411 IsTailCall = false;
412
413 switch (CallConv) {
414 case CallingConv::Fast:
415 case CallingConv::C:
416 return LowerCCCCallTo(Chain, Callee, CallConv, IsVarArg, IsTailCall, Outs,
417 OutVals, Ins, dl: DL, DAG, InVals);
418 default:
419 report_fatal_error(reason: "Unsupported calling convention");
420 }
421}
422
423// LowerCCCArguments - transform physical registers into virtual registers and
424// generate load operations for arguments places on the stack.
425SDValue LanaiTargetLowering::LowerCCCArguments(
426 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
427 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
428 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
429 MachineFunction &MF = DAG.getMachineFunction();
430 MachineFrameInfo &MFI = MF.getFrameInfo();
431 MachineRegisterInfo &RegInfo = MF.getRegInfo();
432 LanaiMachineFunctionInfo *LanaiMFI = MF.getInfo<LanaiMachineFunctionInfo>();
433
434 // Assign locations to all of the incoming arguments.
435 SmallVector<CCValAssign, 16> ArgLocs;
436 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
437 *DAG.getContext());
438 if (CallConv == CallingConv::Fast) {
439 CCInfo.AnalyzeFormalArguments(Ins, Fn: CC_Lanai32_Fast);
440 } else {
441 CCInfo.AnalyzeFormalArguments(Ins, Fn: CC_Lanai32);
442 }
443
444 for (const CCValAssign &VA : ArgLocs) {
445 if (VA.isRegLoc()) {
446 // Arguments passed in registers
447 EVT RegVT = VA.getLocVT();
448 switch (RegVT.getSimpleVT().SimpleTy) {
449 case MVT::i32: {
450 Register VReg = RegInfo.createVirtualRegister(RegClass: &Lanai::GPRRegClass);
451 RegInfo.addLiveIn(Reg: VA.getLocReg(), vreg: VReg);
452 SDValue ArgValue = DAG.getCopyFromReg(Chain, dl: DL, Reg: VReg, VT: RegVT);
453
454 // If this is an 8/16-bit value, it is really passed promoted to 32
455 // bits. Insert an assert[sz]ext to capture this, then truncate to the
456 // right size.
457 if (VA.getLocInfo() == CCValAssign::SExt)
458 ArgValue = DAG.getNode(Opcode: ISD::AssertSext, DL, VT: RegVT, N1: ArgValue,
459 N2: DAG.getValueType(VA.getValVT()));
460 else if (VA.getLocInfo() == CCValAssign::ZExt)
461 ArgValue = DAG.getNode(Opcode: ISD::AssertZext, DL, VT: RegVT, N1: ArgValue,
462 N2: DAG.getValueType(VA.getValVT()));
463
464 if (VA.getLocInfo() != CCValAssign::Full)
465 ArgValue = DAG.getNode(Opcode: ISD::TRUNCATE, DL, VT: VA.getValVT(), Operand: ArgValue);
466
467 InVals.push_back(Elt: ArgValue);
468 break;
469 }
470 default:
471 LLVM_DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: "
472 << RegVT << "\n");
473 llvm_unreachable("unhandled argument type");
474 }
475 } else {
476 // Only arguments passed on the stack should make it here.
477 assert(VA.isMemLoc());
478 // Load the argument to a virtual register
479 unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8;
480 // Check that the argument fits in stack slot
481 if (ObjSize > 4) {
482 errs() << "LowerFormalArguments Unhandled argument type: "
483 << VA.getLocVT() << "\n";
484 }
485 // Create the frame index object for this incoming parameter...
486 int FI = MFI.CreateFixedObject(Size: ObjSize, SPOffset: VA.getLocMemOffset(), IsImmutable: true);
487
488 // Create the SelectionDAG nodes corresponding to a load
489 // from this parameter
490 SDValue FIN = DAG.getFrameIndex(FI, VT: MVT::i32);
491 InVals.push_back(Elt: DAG.getLoad(
492 VT: VA.getLocVT(), dl: DL, Chain, Ptr: FIN,
493 PtrInfo: MachinePointerInfo::getFixedStack(MF&: DAG.getMachineFunction(), FI)));
494 }
495 }
496
497 // The Lanai ABI for returning structs by value requires that we copy
498 // the sret argument into rv for the return. Save the argument into
499 // a virtual register so that we can access it from the return points.
500 if (MF.getFunction().hasStructRetAttr()) {
501 Register Reg = LanaiMFI->getSRetReturnReg();
502 if (!Reg) {
503 Reg = MF.getRegInfo().createVirtualRegister(RegClass: getRegClassFor(VT: MVT::i32));
504 LanaiMFI->setSRetReturnReg(Reg);
505 }
506 SDValue Copy = DAG.getCopyToReg(Chain: DAG.getEntryNode(), dl: DL, Reg, N: InVals[0]);
507 Chain = DAG.getNode(Opcode: ISD::TokenFactor, DL, VT: MVT::Other, N1: Copy, N2: Chain);
508 }
509
510 if (IsVarArg) {
511 // Record the frame index of the first variable argument
512 // which is a value necessary to VASTART.
513 int FI = MFI.CreateFixedObject(Size: 4, SPOffset: CCInfo.getStackSize(), IsImmutable: true);
514 LanaiMFI->setVarArgsFrameIndex(FI);
515 }
516
517 return Chain;
518}
519
520bool LanaiTargetLowering::CanLowerReturn(
521 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
522 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
523 const Type *RetTy) const {
524 SmallVector<CCValAssign, 16> RVLocs;
525 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
526
527 return CCInfo.CheckReturn(Outs, Fn: RetCC_Lanai32);
528}
529
530SDValue
531LanaiTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
532 bool IsVarArg,
533 const SmallVectorImpl<ISD::OutputArg> &Outs,
534 const SmallVectorImpl<SDValue> &OutVals,
535 const SDLoc &DL, SelectionDAG &DAG) const {
536 // CCValAssign - represent the assignment of the return value to a location
537 SmallVector<CCValAssign, 16> RVLocs;
538
539 // CCState - Info about the registers and stack slot.
540 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
541 *DAG.getContext());
542
543 // Analize return values.
544 CCInfo.AnalyzeReturn(Outs, Fn: RetCC_Lanai32);
545
546 SDValue Glue;
547 SmallVector<SDValue, 4> RetOps(1, Chain);
548
549 // Copy the result values into the output registers.
550 for (unsigned i = 0; i != RVLocs.size(); ++i) {
551 CCValAssign &VA = RVLocs[i];
552 assert(VA.isRegLoc() && "Can only return in registers!");
553
554 Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: VA.getLocReg(), N: OutVals[i], Glue);
555
556 // Guarantee that all emitted copies are stuck together with flags.
557 Glue = Chain.getValue(R: 1);
558 RetOps.push_back(Elt: DAG.getRegister(Reg: VA.getLocReg(), VT: VA.getLocVT()));
559 }
560
561 // The Lanai ABI for returning structs by value requires that we copy
562 // the sret argument into rv for the return. We saved the argument into
563 // a virtual register in the entry block, so now we copy the value out
564 // and into rv.
565 if (DAG.getMachineFunction().getFunction().hasStructRetAttr()) {
566 MachineFunction &MF = DAG.getMachineFunction();
567 LanaiMachineFunctionInfo *LanaiMFI = MF.getInfo<LanaiMachineFunctionInfo>();
568 Register Reg = LanaiMFI->getSRetReturnReg();
569 assert(Reg &&
570 "SRetReturnReg should have been set in LowerFormalArguments().");
571 SDValue Val =
572 DAG.getCopyFromReg(Chain, dl: DL, Reg, VT: getPointerTy(DL: DAG.getDataLayout()));
573
574 Chain = DAG.getCopyToReg(Chain, dl: DL, Reg: Lanai::RV, N: Val, Glue);
575 Glue = Chain.getValue(R: 1);
576 RetOps.push_back(
577 Elt: DAG.getRegister(Reg: Lanai::RV, VT: getPointerTy(DL: DAG.getDataLayout())));
578 }
579
580 RetOps[0] = Chain; // Update chain
581
582 unsigned Opc = LanaiISD::RET_GLUE;
583 if (Glue.getNode())
584 RetOps.push_back(Elt: Glue);
585
586 // Return Void
587 return DAG.getNode(Opcode: Opc, DL, VT: MVT::Other,
588 Ops: ArrayRef<SDValue>(&RetOps[0], RetOps.size()));
589}
590
591// LowerCCCCallTo - functions arguments are copied from virtual regs to
592// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
593SDValue LanaiTargetLowering::LowerCCCCallTo(
594 SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool IsVarArg,
595 bool /*IsTailCall*/, const SmallVectorImpl<ISD::OutputArg> &Outs,
596 const SmallVectorImpl<SDValue> &OutVals,
597 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
598 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
599 // Analyze operands of the call, assigning locations to each operand.
600 SmallVector<CCValAssign, 16> ArgLocs;
601 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
602 *DAG.getContext());
603 GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Val&: Callee);
604 MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
605
606 if (IsVarArg) {
607 CCInfo.AnalyzeCallOperands(Outs, Fn: CC_Lanai32_VarArg);
608 } else {
609 if (CallConv == CallingConv::Fast)
610 CCInfo.AnalyzeCallOperands(Outs, Fn: CC_Lanai32_Fast);
611 else
612 CCInfo.AnalyzeCallOperands(Outs, Fn: CC_Lanai32);
613 }
614
615 // Get a count of how many bytes are to be pushed on the stack.
616 unsigned NumBytes = CCInfo.getStackSize();
617
618 // Create local copies for byval args.
619 SmallVector<SDValue, 8> ByValArgs;
620 for (unsigned I = 0, E = Outs.size(); I != E; ++I) {
621 ISD::ArgFlagsTy Flags = Outs[I].Flags;
622 if (!Flags.isByVal())
623 continue;
624
625 SDValue Arg = OutVals[I];
626 unsigned Size = Flags.getByValSize();
627 Align Alignment = Flags.getNonZeroByValAlign();
628
629 int FI = MFI.CreateStackObject(Size, Alignment, isSpillSlot: false);
630 SDValue FIPtr = DAG.getFrameIndex(FI, VT: getPointerTy(DL: DAG.getDataLayout()));
631 SDValue SizeNode = DAG.getConstant(Val: Size, DL, VT: MVT::i32);
632
633 Chain = DAG.getMemcpy(Chain, dl: DL, Dst: FIPtr, Src: Arg, Size: SizeNode, DstAlign: Alignment, SrcAlign: Alignment,
634 /*IsVolatile=*/isVol: false,
635 /*AlwaysInline=*/false,
636 /*CI=*/nullptr, OverrideTailCall: std::nullopt, DstPtrInfo: MachinePointerInfo(),
637 SrcPtrInfo: MachinePointerInfo());
638 ByValArgs.push_back(Elt: FIPtr);
639 }
640
641 Chain = DAG.getCALLSEQ_START(Chain, InSize: NumBytes, OutSize: 0, DL);
642
643 SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
644 SmallVector<SDValue, 12> MemOpChains;
645 SDValue StackPtr;
646
647 // Walk the register/memloc assignments, inserting copies/loads.
648 for (unsigned I = 0, J = 0, E = ArgLocs.size(); I != E; ++I) {
649 CCValAssign &VA = ArgLocs[I];
650 SDValue Arg = OutVals[I];
651 ISD::ArgFlagsTy Flags = Outs[I].Flags;
652
653 // Promote the value if needed.
654 switch (VA.getLocInfo()) {
655 case CCValAssign::Full:
656 break;
657 case CCValAssign::SExt:
658 Arg = DAG.getNode(Opcode: ISD::SIGN_EXTEND, DL, VT: VA.getLocVT(), Operand: Arg);
659 break;
660 case CCValAssign::ZExt:
661 Arg = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL, VT: VA.getLocVT(), Operand: Arg);
662 break;
663 case CCValAssign::AExt:
664 Arg = DAG.getNode(Opcode: ISD::ANY_EXTEND, DL, VT: VA.getLocVT(), Operand: Arg);
665 break;
666 default:
667 llvm_unreachable("Unknown loc info!");
668 }
669
670 // Use local copy if it is a byval arg.
671 if (Flags.isByVal())
672 Arg = ByValArgs[J++];
673
674 // Arguments that can be passed on register must be kept at RegsToPass
675 // vector
676 if (VA.isRegLoc()) {
677 RegsToPass.push_back(Elt: std::make_pair(x: VA.getLocReg(), y&: Arg));
678 } else {
679 assert(VA.isMemLoc());
680
681 if (StackPtr.getNode() == nullptr)
682 StackPtr = DAG.getCopyFromReg(Chain, dl: DL, Reg: Lanai::SP,
683 VT: getPointerTy(DL: DAG.getDataLayout()));
684
685 SDValue PtrOff =
686 DAG.getNode(Opcode: ISD::ADD, DL, VT: getPointerTy(DL: DAG.getDataLayout()), N1: StackPtr,
687 N2: DAG.getIntPtrConstant(Val: VA.getLocMemOffset(), DL));
688
689 MemOpChains.push_back(
690 Elt: DAG.getStore(Chain, dl: DL, Val: Arg, Ptr: PtrOff, PtrInfo: MachinePointerInfo()));
691 }
692 }
693
694 // Transform all store nodes into one single node because all store nodes are
695 // independent of each other.
696 if (!MemOpChains.empty())
697 Chain = DAG.getNode(Opcode: ISD::TokenFactor, DL, VT: MVT::Other,
698 Ops: ArrayRef<SDValue>(&MemOpChains[0], MemOpChains.size()));
699
700 SDValue InGlue;
701
702 // Build a sequence of copy-to-reg nodes chained together with token chain and
703 // flag operands which copy the outgoing args into registers. The InGlue in
704 // necessary since all emitted instructions must be stuck together.
705 for (const auto &[Reg, N] : RegsToPass) {
706 Chain = DAG.getCopyToReg(Chain, dl: DL, Reg, N, Glue: InGlue);
707 InGlue = Chain.getValue(R: 1);
708 }
709
710 // If the callee is a GlobalAddress node (quite common, every direct call is)
711 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
712 // Likewise ExternalSymbol -> TargetExternalSymbol.
713 uint8_t OpFlag = LanaiII::MO_NO_FLAG;
714 if (G) {
715 Callee = DAG.getTargetGlobalAddress(
716 GV: G->getGlobal(), DL, VT: getPointerTy(DL: DAG.getDataLayout()), offset: 0, TargetFlags: OpFlag);
717 } else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Val&: Callee)) {
718 Callee = DAG.getTargetExternalSymbol(
719 Sym: E->getSymbol(), VT: getPointerTy(DL: DAG.getDataLayout()), TargetFlags: OpFlag);
720 }
721
722 // Returns a chain & a flag for retval copy to use.
723 SDVTList NodeTys = DAG.getVTList(VT1: MVT::Other, VT2: MVT::Glue);
724 SmallVector<SDValue, 8> Ops;
725 Ops.push_back(Elt: Chain);
726 Ops.push_back(Elt: Callee);
727
728 // Add a register mask operand representing the call-preserved registers.
729 // TODO: Should return-twice functions be handled?
730 const uint32_t *Mask =
731 TRI->getCallPreservedMask(MF: DAG.getMachineFunction(), CallConv);
732 assert(Mask && "Missing call preserved mask for calling convention");
733 Ops.push_back(Elt: DAG.getRegisterMask(RegMask: Mask));
734
735 // Add argument registers to the end of the list so that they are
736 // known live into the call.
737 for (const auto &[Reg, N] : RegsToPass)
738 Ops.push_back(Elt: DAG.getRegister(Reg, VT: N.getValueType()));
739
740 if (InGlue.getNode())
741 Ops.push_back(Elt: InGlue);
742
743 Chain = DAG.getNode(Opcode: LanaiISD::CALL, DL, VTList: NodeTys,
744 Ops: ArrayRef<SDValue>(&Ops[0], Ops.size()));
745 InGlue = Chain.getValue(R: 1);
746
747 // Create the CALLSEQ_END node.
748 Chain = DAG.getCALLSEQ_END(Chain, Size1: NumBytes, Size2: 0, Glue: InGlue, DL);
749 InGlue = Chain.getValue(R: 1);
750
751 // Handle result values, copying them out of physregs into vregs that we
752 // return.
753 return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG,
754 InVals);
755}
756
757// LowerCallResult - Lower the result values of a call into the
758// appropriate copies out of appropriate physical registers.
759SDValue LanaiTargetLowering::LowerCallResult(
760 SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
761 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
762 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
763 // Assign locations to each value returned by this call.
764 SmallVector<CCValAssign, 16> RVLocs;
765 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
766 *DAG.getContext());
767
768 CCInfo.AnalyzeCallResult(Ins, Fn: RetCC_Lanai32);
769
770 // Copy all of the result registers out of their specified physreg.
771 for (unsigned I = 0; I != RVLocs.size(); ++I) {
772 Chain = DAG.getCopyFromReg(Chain, dl: DL, Reg: RVLocs[I].getLocReg(),
773 VT: RVLocs[I].getValVT(), Glue: InGlue)
774 .getValue(R: 1);
775 InGlue = Chain.getValue(R: 2);
776 InVals.push_back(Elt: Chain.getValue(R: 0));
777 }
778
779 return Chain;
780}
781
782//===----------------------------------------------------------------------===//
783// Custom Lowerings
784//===----------------------------------------------------------------------===//
785
786static LPCC::CondCode IntCondCCodeToICC(SDValue CC, const SDLoc &DL,
787 SDValue &RHS, SelectionDAG &DAG) {
788 ISD::CondCode SetCCOpcode = cast<CondCodeSDNode>(Val&: CC)->get();
789
790 // For integer, only the SETEQ, SETNE, SETLT, SETLE, SETGT, SETGE, SETULT,
791 // SETULE, SETUGT, and SETUGE opcodes are used (see CodeGen/ISDOpcodes.h)
792 // and Lanai only supports integer comparisons, so only provide definitions
793 // for them.
794 switch (SetCCOpcode) {
795 case ISD::SETEQ:
796 return LPCC::ICC_EQ;
797 case ISD::SETGT:
798 if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(Val&: RHS))
799 if (RHSC->getZExtValue() == 0xFFFFFFFF) {
800 // X > -1 -> X >= 0 -> is_plus(X)
801 RHS = DAG.getConstant(Val: 0, DL, VT: RHS.getValueType());
802 return LPCC::ICC_PL;
803 }
804 return LPCC::ICC_GT;
805 case ISD::SETUGT:
806 return LPCC::ICC_UGT;
807 case ISD::SETLT:
808 if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(Val&: RHS))
809 if (RHSC->getZExtValue() == 0)
810 // X < 0 -> is_minus(X)
811 return LPCC::ICC_MI;
812 return LPCC::ICC_LT;
813 case ISD::SETULT:
814 return LPCC::ICC_ULT;
815 case ISD::SETLE:
816 if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(Val&: RHS))
817 if (RHSC->getZExtValue() == 0xFFFFFFFF) {
818 // X <= -1 -> X < 0 -> is_minus(X)
819 RHS = DAG.getConstant(Val: 0, DL, VT: RHS.getValueType());
820 return LPCC::ICC_MI;
821 }
822 return LPCC::ICC_LE;
823 case ISD::SETULE:
824 return LPCC::ICC_ULE;
825 case ISD::SETGE:
826 if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(Val&: RHS))
827 if (RHSC->getZExtValue() == 0)
828 // X >= 0 -> is_plus(X)
829 return LPCC::ICC_PL;
830 return LPCC::ICC_GE;
831 case ISD::SETUGE:
832 return LPCC::ICC_UGE;
833 case ISD::SETNE:
834 return LPCC::ICC_NE;
835 case ISD::SETONE:
836 case ISD::SETUNE:
837 case ISD::SETOGE:
838 case ISD::SETOLE:
839 case ISD::SETOLT:
840 case ISD::SETOGT:
841 case ISD::SETOEQ:
842 case ISD::SETUEQ:
843 case ISD::SETO:
844 case ISD::SETUO:
845 llvm_unreachable("Unsupported comparison.");
846 default:
847 llvm_unreachable("Unknown integer condition code!");
848 }
849}
850
851SDValue LanaiTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
852 SDValue Chain = Op.getOperand(i: 0);
853 SDValue Cond = Op.getOperand(i: 1);
854 SDValue LHS = Op.getOperand(i: 2);
855 SDValue RHS = Op.getOperand(i: 3);
856 SDValue Dest = Op.getOperand(i: 4);
857 SDLoc DL(Op);
858
859 LPCC::CondCode CC = IntCondCCodeToICC(CC: Cond, DL, RHS, DAG);
860 SDValue TargetCC = DAG.getConstant(Val: CC, DL, VT: MVT::i32);
861 SDValue Glue = DAG.getNode(Opcode: LanaiISD::SET_FLAG, DL, VT: MVT::Glue, N1: LHS, N2: RHS);
862
863 return DAG.getNode(Opcode: LanaiISD::BR_CC, DL, VT: Op.getValueType(), N1: Chain, N2: Dest,
864 N3: TargetCC, N4: Glue);
865}
866
867SDValue LanaiTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
868 EVT VT = Op->getValueType(ResNo: 0);
869 if (VT != MVT::i32)
870 return SDValue();
871
872 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val: Op->getOperand(Num: 1));
873 if (!C)
874 return SDValue();
875
876 int64_t MulAmt = C->getSExtValue();
877 int32_t HighestOne = -1;
878 uint32_t NonzeroEntries = 0;
879 int SignedDigit[32] = {0};
880
881 // Convert to non-adjacent form (NAF) signed-digit representation.
882 // NAF is a signed-digit form where no adjacent digits are non-zero. It is the
883 // minimal Hamming weight representation of a number (on average 1/3 of the
884 // digits will be non-zero vs 1/2 for regular binary representation). And as
885 // the non-zero digits will be the only digits contributing to the instruction
886 // count, this is desirable. The next loop converts it to NAF (following the
887 // approach in 'Guide to Elliptic Curve Cryptography' [ISBN: 038795273X]) by
888 // choosing the non-zero coefficients such that the resulting quotient is
889 // divisible by 2 which will cause the next coefficient to be zero.
890 int64_t E = std::abs(i: MulAmt);
891 int S = (MulAmt < 0 ? -1 : 1);
892 int I = 0;
893 while (E > 0) {
894 int ZI = 0;
895 if (E % 2 == 1) {
896 ZI = 2 - (E % 4);
897 if (ZI != 0)
898 ++NonzeroEntries;
899 }
900 SignedDigit[I] = S * ZI;
901 if (SignedDigit[I] == 1)
902 HighestOne = I;
903 E = (E - ZI) / 2;
904 ++I;
905 }
906
907 // Compute number of instructions required. Due to differences in lowering
908 // between the different processors this count is not exact.
909 // Start by assuming a shift and a add/sub for every non-zero entry (hence
910 // every non-zero entry requires 1 shift and 1 add/sub except for the first
911 // entry).
912 int32_t InstrRequired = 2 * NonzeroEntries - 1;
913 // Correct possible over-adding due to shift by 0 (which is not emitted).
914 if (std::abs(i: MulAmt) % 2 == 1)
915 --InstrRequired;
916 // Return if the form generated would exceed the instruction threshold.
917 if (InstrRequired > LanaiLowerConstantMulThreshold)
918 return SDValue();
919
920 SDValue Res;
921 SDLoc DL(Op);
922 SDValue V = Op->getOperand(Num: 0);
923
924 // Initialize the running sum. Set the running sum to the maximal shifted
925 // positive value (i.e., largest i such that zi == 1 and MulAmt has V<<i as a
926 // term NAF).
927 if (HighestOne == -1)
928 Res = DAG.getConstant(Val: 0, DL, VT: MVT::i32);
929 else {
930 Res = DAG.getNode(Opcode: ISD::SHL, DL, VT, N1: V,
931 N2: DAG.getConstant(Val: HighestOne, DL, VT: MVT::i32));
932 SignedDigit[HighestOne] = 0;
933 }
934
935 // Assemble multiplication from shift, add, sub using NAF form and running
936 // sum.
937 for (unsigned int I = 0; I < std::size(SignedDigit); ++I) {
938 if (SignedDigit[I] == 0)
939 continue;
940
941 // Shifted multiplicand (v<<i).
942 SDValue Op =
943 DAG.getNode(Opcode: ISD::SHL, DL, VT, N1: V, N2: DAG.getConstant(Val: I, DL, VT: MVT::i32));
944 if (SignedDigit[I] == 1)
945 Res = DAG.getNode(Opcode: ISD::ADD, DL, VT, N1: Res, N2: Op);
946 else if (SignedDigit[I] == -1)
947 Res = DAG.getNode(Opcode: ISD::SUB, DL, VT, N1: Res, N2: Op);
948 }
949 return Res;
950}
951
952SDValue LanaiTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
953 SDValue LHS = Op.getOperand(i: 0);
954 SDValue RHS = Op.getOperand(i: 1);
955 SDValue Cond = Op.getOperand(i: 2);
956 SDLoc DL(Op);
957
958 LPCC::CondCode CC = IntCondCCodeToICC(CC: Cond, DL, RHS, DAG);
959 SDValue TargetCC = DAG.getConstant(Val: CC, DL, VT: MVT::i32);
960 SDValue Glue = DAG.getNode(Opcode: LanaiISD::SET_FLAG, DL, VT: MVT::Glue, N1: LHS, N2: RHS);
961
962 return DAG.getNode(Opcode: LanaiISD::SETCC, DL, VT: Op.getValueType(), N1: TargetCC, N2: Glue);
963}
964
965SDValue LanaiTargetLowering::LowerSELECT_CC(SDValue Op,
966 SelectionDAG &DAG) const {
967 SDValue LHS = Op.getOperand(i: 0);
968 SDValue RHS = Op.getOperand(i: 1);
969 SDValue TrueV = Op.getOperand(i: 2);
970 SDValue FalseV = Op.getOperand(i: 3);
971 SDValue Cond = Op.getOperand(i: 4);
972 SDLoc DL(Op);
973
974 LPCC::CondCode CC = IntCondCCodeToICC(CC: Cond, DL, RHS, DAG);
975 SDValue TargetCC = DAG.getConstant(Val: CC, DL, VT: MVT::i32);
976 SDValue Glue = DAG.getNode(Opcode: LanaiISD::SET_FLAG, DL, VT: MVT::Glue, N1: LHS, N2: RHS);
977
978 return DAG.getNode(Opcode: LanaiISD::SELECT_CC, DL, VT: Op.getValueType(), N1: TrueV, N2: FalseV,
979 N3: TargetCC, N4: Glue);
980}
981
982SDValue LanaiTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
983 MachineFunction &MF = DAG.getMachineFunction();
984 LanaiMachineFunctionInfo *FuncInfo = MF.getInfo<LanaiMachineFunctionInfo>();
985
986 SDLoc DL(Op);
987 SDValue FI = DAG.getFrameIndex(FI: FuncInfo->getVarArgsFrameIndex(),
988 VT: getPointerTy(DL: DAG.getDataLayout()));
989
990 // vastart just stores the address of the VarArgsFrameIndex slot into the
991 // memory location argument.
992 const Value *SV = cast<SrcValueSDNode>(Val: Op.getOperand(i: 2))->getValue();
993 return DAG.getStore(Chain: Op.getOperand(i: 0), dl: DL, Val: FI, Ptr: Op.getOperand(i: 1),
994 PtrInfo: MachinePointerInfo(SV));
995}
996
997SDValue LanaiTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
998 SelectionDAG &DAG) const {
999 SDValue Chain = Op.getOperand(i: 0);
1000 SDValue Size = Op.getOperand(i: 1);
1001 SDLoc DL(Op);
1002
1003 Register SPReg = getStackPointerRegisterToSaveRestore();
1004
1005 // Get a reference to the stack pointer.
1006 SDValue StackPointer = DAG.getCopyFromReg(Chain, dl: DL, Reg: SPReg, VT: MVT::i32);
1007
1008 // Subtract the dynamic size from the actual stack size to
1009 // obtain the new stack size.
1010 SDValue Sub = DAG.getNode(Opcode: ISD::SUB, DL, VT: MVT::i32, N1: StackPointer, N2: Size);
1011
1012 // For Lanai, the outgoing memory arguments area should be on top of the
1013 // alloca area on the stack i.e., the outgoing memory arguments should be
1014 // at a lower address than the alloca area. Move the alloca area down the
1015 // stack by adding back the space reserved for outgoing arguments to SP
1016 // here.
1017 //
1018 // We do not know what the size of the outgoing args is at this point.
1019 // So, we add a pseudo instruction ADJDYNALLOC that will adjust the
1020 // stack pointer. We replace this instruction with on that has the correct,
1021 // known offset in emitPrologue().
1022 SDValue ArgAdjust = DAG.getNode(Opcode: LanaiISD::ADJDYNALLOC, DL, VT: MVT::i32, Operand: Sub);
1023
1024 // The Sub result contains the new stack start address, so it
1025 // must be placed in the stack pointer register.
1026 SDValue CopyChain = DAG.getCopyToReg(Chain, dl: DL, Reg: SPReg, N: Sub);
1027
1028 SDValue Ops[2] = {ArgAdjust, CopyChain};
1029 return DAG.getMergeValues(Ops, dl: DL);
1030}
1031
1032SDValue LanaiTargetLowering::LowerRETURNADDR(SDValue Op,
1033 SelectionDAG &DAG) const {
1034 MachineFunction &MF = DAG.getMachineFunction();
1035 MachineFrameInfo &MFI = MF.getFrameInfo();
1036 MFI.setReturnAddressIsTaken(true);
1037
1038 EVT VT = Op.getValueType();
1039 SDLoc DL(Op);
1040 unsigned Depth = Op.getConstantOperandVal(i: 0);
1041 if (Depth) {
1042 SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
1043 const unsigned Offset = -4;
1044 SDValue Ptr = DAG.getNode(Opcode: ISD::ADD, DL, VT, N1: FrameAddr,
1045 N2: DAG.getIntPtrConstant(Val: Offset, DL));
1046 return DAG.getLoad(VT, dl: DL, Chain: DAG.getEntryNode(), Ptr, PtrInfo: MachinePointerInfo());
1047 }
1048
1049 // Return the link register, which contains the return address.
1050 // Mark it an implicit live-in.
1051 Register Reg = MF.addLiveIn(PReg: TRI->getRARegister(), RC: getRegClassFor(VT: MVT::i32));
1052 return DAG.getCopyFromReg(Chain: DAG.getEntryNode(), dl: DL, Reg, VT);
1053}
1054
1055SDValue LanaiTargetLowering::LowerFRAMEADDR(SDValue Op,
1056 SelectionDAG &DAG) const {
1057 MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
1058 MFI.setFrameAddressIsTaken(true);
1059
1060 EVT VT = Op.getValueType();
1061 SDLoc DL(Op);
1062 SDValue FrameAddr = DAG.getCopyFromReg(Chain: DAG.getEntryNode(), dl: DL, Reg: Lanai::FP, VT);
1063 unsigned Depth = Op.getConstantOperandVal(i: 0);
1064 while (Depth--) {
1065 const unsigned Offset = -8;
1066 SDValue Ptr = DAG.getNode(Opcode: ISD::ADD, DL, VT, N1: FrameAddr,
1067 N2: DAG.getIntPtrConstant(Val: Offset, DL));
1068 FrameAddr =
1069 DAG.getLoad(VT, dl: DL, Chain: DAG.getEntryNode(), Ptr, PtrInfo: MachinePointerInfo());
1070 }
1071 return FrameAddr;
1072}
1073
1074SDValue LanaiTargetLowering::LowerConstantPool(SDValue Op,
1075 SelectionDAG &DAG) const {
1076 SDLoc DL(Op);
1077 ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Val&: Op);
1078 const Constant *C = N->getConstVal();
1079 const LanaiTargetObjectFile *TLOF =
1080 static_cast<const LanaiTargetObjectFile *>(
1081 getTargetMachine().getObjFileLowering());
1082
1083 // If the code model is small or constant will be placed in the small section,
1084 // then assume address will fit in 21-bits.
1085 if (getTargetMachine().getCodeModel() == CodeModel::Small ||
1086 TLOF->isConstantInSmallSection(DL: DAG.getDataLayout(), CN: C)) {
1087 SDValue Small = DAG.getTargetConstantPool(
1088 C, VT: MVT::i32, Align: N->getAlign(), Offset: N->getOffset(), TargetFlags: LanaiII::MO_NO_FLAG);
1089 return DAG.getNode(Opcode: ISD::OR, DL, VT: MVT::i32,
1090 N1: DAG.getRegister(Reg: Lanai::R0, VT: MVT::i32),
1091 N2: DAG.getNode(Opcode: LanaiISD::SMALL, DL, VT: MVT::i32, Operand: Small));
1092 } else {
1093 uint8_t OpFlagHi = LanaiII::MO_ABS_HI;
1094 uint8_t OpFlagLo = LanaiII::MO_ABS_LO;
1095
1096 SDValue Hi = DAG.getTargetConstantPool(C, VT: MVT::i32, Align: N->getAlign(),
1097 Offset: N->getOffset(), TargetFlags: OpFlagHi);
1098 SDValue Lo = DAG.getTargetConstantPool(C, VT: MVT::i32, Align: N->getAlign(),
1099 Offset: N->getOffset(), TargetFlags: OpFlagLo);
1100 Hi = DAG.getNode(Opcode: LanaiISD::HI, DL, VT: MVT::i32, Operand: Hi);
1101 Lo = DAG.getNode(Opcode: LanaiISD::LO, DL, VT: MVT::i32, Operand: Lo);
1102 SDValue Result = DAG.getNode(Opcode: ISD::OR, DL, VT: MVT::i32, N1: Hi, N2: Lo);
1103 return Result;
1104 }
1105}
1106
1107SDValue LanaiTargetLowering::LowerGlobalAddress(SDValue Op,
1108 SelectionDAG &DAG) const {
1109 SDLoc DL(Op);
1110 const GlobalValue *GV = cast<GlobalAddressSDNode>(Val&: Op)->getGlobal();
1111 int64_t Offset = cast<GlobalAddressSDNode>(Val&: Op)->getOffset();
1112
1113 const LanaiTargetObjectFile *TLOF =
1114 static_cast<const LanaiTargetObjectFile *>(
1115 getTargetMachine().getObjFileLowering());
1116
1117 // If the code model is small or global variable will be placed in the small
1118 // section, then assume address will fit in 21-bits.
1119 const GlobalObject *GO = GV->getAliaseeObject();
1120 if (TLOF->isGlobalInSmallSection(GO, TM: getTargetMachine())) {
1121 SDValue Small = DAG.getTargetGlobalAddress(
1122 GV, DL, VT: getPointerTy(DL: DAG.getDataLayout()), offset: Offset, TargetFlags: LanaiII::MO_NO_FLAG);
1123 return DAG.getNode(Opcode: ISD::OR, DL, VT: MVT::i32,
1124 N1: DAG.getRegister(Reg: Lanai::R0, VT: MVT::i32),
1125 N2: DAG.getNode(Opcode: LanaiISD::SMALL, DL, VT: MVT::i32, Operand: Small));
1126 } else {
1127 uint8_t OpFlagHi = LanaiII::MO_ABS_HI;
1128 uint8_t OpFlagLo = LanaiII::MO_ABS_LO;
1129
1130 // Create the TargetGlobalAddress node, folding in the constant offset.
1131 SDValue Hi = DAG.getTargetGlobalAddress(
1132 GV, DL, VT: getPointerTy(DL: DAG.getDataLayout()), offset: Offset, TargetFlags: OpFlagHi);
1133 SDValue Lo = DAG.getTargetGlobalAddress(
1134 GV, DL, VT: getPointerTy(DL: DAG.getDataLayout()), offset: Offset, TargetFlags: OpFlagLo);
1135 Hi = DAG.getNode(Opcode: LanaiISD::HI, DL, VT: MVT::i32, Operand: Hi);
1136 Lo = DAG.getNode(Opcode: LanaiISD::LO, DL, VT: MVT::i32, Operand: Lo);
1137 return DAG.getNode(Opcode: ISD::OR, DL, VT: MVT::i32, N1: Hi, N2: Lo);
1138 }
1139}
1140
1141SDValue LanaiTargetLowering::LowerBlockAddress(SDValue Op,
1142 SelectionDAG &DAG) const {
1143 SDLoc DL(Op);
1144 const BlockAddress *BA = cast<BlockAddressSDNode>(Val&: Op)->getBlockAddress();
1145
1146 uint8_t OpFlagHi = LanaiII::MO_ABS_HI;
1147 uint8_t OpFlagLo = LanaiII::MO_ABS_LO;
1148
1149 SDValue Hi = DAG.getBlockAddress(BA, VT: MVT::i32, Offset: true, isTarget: OpFlagHi);
1150 SDValue Lo = DAG.getBlockAddress(BA, VT: MVT::i32, Offset: true, isTarget: OpFlagLo);
1151 Hi = DAG.getNode(Opcode: LanaiISD::HI, DL, VT: MVT::i32, Operand: Hi);
1152 Lo = DAG.getNode(Opcode: LanaiISD::LO, DL, VT: MVT::i32, Operand: Lo);
1153 SDValue Result = DAG.getNode(Opcode: ISD::OR, DL, VT: MVT::i32, N1: Hi, N2: Lo);
1154 return Result;
1155}
1156
1157SDValue LanaiTargetLowering::LowerJumpTable(SDValue Op,
1158 SelectionDAG &DAG) const {
1159 SDLoc DL(Op);
1160 JumpTableSDNode *JT = cast<JumpTableSDNode>(Val&: Op);
1161
1162 // If the code model is small assume address will fit in 21-bits.
1163 if (getTargetMachine().getCodeModel() == CodeModel::Small) {
1164 SDValue Small = DAG.getTargetJumpTable(
1165 JTI: JT->getIndex(), VT: getPointerTy(DL: DAG.getDataLayout()), TargetFlags: LanaiII::MO_NO_FLAG);
1166 return DAG.getNode(Opcode: ISD::OR, DL, VT: MVT::i32,
1167 N1: DAG.getRegister(Reg: Lanai::R0, VT: MVT::i32),
1168 N2: DAG.getNode(Opcode: LanaiISD::SMALL, DL, VT: MVT::i32, Operand: Small));
1169 } else {
1170 uint8_t OpFlagHi = LanaiII::MO_ABS_HI;
1171 uint8_t OpFlagLo = LanaiII::MO_ABS_LO;
1172
1173 SDValue Hi = DAG.getTargetJumpTable(
1174 JTI: JT->getIndex(), VT: getPointerTy(DL: DAG.getDataLayout()), TargetFlags: OpFlagHi);
1175 SDValue Lo = DAG.getTargetJumpTable(
1176 JTI: JT->getIndex(), VT: getPointerTy(DL: DAG.getDataLayout()), TargetFlags: OpFlagLo);
1177 Hi = DAG.getNode(Opcode: LanaiISD::HI, DL, VT: MVT::i32, Operand: Hi);
1178 Lo = DAG.getNode(Opcode: LanaiISD::LO, DL, VT: MVT::i32, Operand: Lo);
1179 SDValue Result = DAG.getNode(Opcode: ISD::OR, DL, VT: MVT::i32, N1: Hi, N2: Lo);
1180 return Result;
1181 }
1182}
1183
1184SDValue LanaiTargetLowering::LowerSHL_PARTS(SDValue Op,
1185 SelectionDAG &DAG) const {
1186 EVT VT = Op.getValueType();
1187 unsigned VTBits = VT.getSizeInBits();
1188 SDLoc dl(Op);
1189 assert(Op.getNumOperands() == 3 && "Unexpected SHL!");
1190 SDValue ShOpLo = Op.getOperand(i: 0);
1191 SDValue ShOpHi = Op.getOperand(i: 1);
1192 SDValue ShAmt = Op.getOperand(i: 2);
1193
1194 // Performs the following for (ShOpLo + (ShOpHi << 32)) << ShAmt:
1195 // LoBitsForHi = (ShAmt == 0) ? 0 : (ShOpLo >> (32-ShAmt))
1196 // HiBitsForHi = ShOpHi << ShAmt
1197 // Hi = (ShAmt >= 32) ? (ShOpLo << (ShAmt-32)) : (LoBitsForHi | HiBitsForHi)
1198 // Lo = (ShAmt >= 32) ? 0 : (ShOpLo << ShAmt)
1199 // return (Hi << 32) | Lo;
1200
1201 SDValue RevShAmt = DAG.getNode(Opcode: ISD::SUB, DL: dl, VT: MVT::i32,
1202 N1: DAG.getConstant(Val: VTBits, DL: dl, VT: MVT::i32), N2: ShAmt);
1203 SDValue LoBitsForHi = DAG.getNode(Opcode: ISD::SRL, DL: dl, VT, N1: ShOpLo, N2: RevShAmt);
1204
1205 // If ShAmt == 0, we just calculated "(SRL ShOpLo, 32)" which is "undef". We
1206 // wanted 0, so CSEL it directly.
1207 SDValue Zero = DAG.getConstant(Val: 0, DL: dl, VT: MVT::i32);
1208 SDValue SetCC = DAG.getSetCC(DL: dl, VT: MVT::i32, LHS: ShAmt, RHS: Zero, Cond: ISD::SETEQ);
1209 LoBitsForHi = DAG.getSelect(DL: dl, VT: MVT::i32, Cond: SetCC, LHS: Zero, RHS: LoBitsForHi);
1210
1211 SDValue ExtraShAmt = DAG.getNode(Opcode: ISD::SUB, DL: dl, VT: MVT::i32, N1: ShAmt,
1212 N2: DAG.getConstant(Val: VTBits, DL: dl, VT: MVT::i32));
1213 SDValue HiBitsForHi = DAG.getNode(Opcode: ISD::SHL, DL: dl, VT, N1: ShOpHi, N2: ShAmt);
1214 SDValue HiForNormalShift =
1215 DAG.getNode(Opcode: ISD::OR, DL: dl, VT, N1: LoBitsForHi, N2: HiBitsForHi);
1216
1217 SDValue HiForBigShift = DAG.getNode(Opcode: ISD::SHL, DL: dl, VT, N1: ShOpLo, N2: ExtraShAmt);
1218
1219 SetCC = DAG.getSetCC(DL: dl, VT: MVT::i32, LHS: ExtraShAmt, RHS: Zero, Cond: ISD::SETGE);
1220 SDValue Hi =
1221 DAG.getSelect(DL: dl, VT: MVT::i32, Cond: SetCC, LHS: HiForBigShift, RHS: HiForNormalShift);
1222
1223 // Lanai shifts of larger than register sizes are wrapped rather than
1224 // clamped, so we can't just emit "lo << b" if b is too big.
1225 SDValue LoForNormalShift = DAG.getNode(Opcode: ISD::SHL, DL: dl, VT, N1: ShOpLo, N2: ShAmt);
1226 SDValue Lo = DAG.getSelect(
1227 DL: dl, VT: MVT::i32, Cond: SetCC, LHS: DAG.getConstant(Val: 0, DL: dl, VT: MVT::i32), RHS: LoForNormalShift);
1228
1229 SDValue Ops[2] = {Lo, Hi};
1230 return DAG.getMergeValues(Ops, dl);
1231}
1232
1233SDValue LanaiTargetLowering::LowerSRL_PARTS(SDValue Op,
1234 SelectionDAG &DAG) const {
1235 MVT VT = Op.getSimpleValueType();
1236 unsigned VTBits = VT.getSizeInBits();
1237 SDLoc dl(Op);
1238 SDValue ShOpLo = Op.getOperand(i: 0);
1239 SDValue ShOpHi = Op.getOperand(i: 1);
1240 SDValue ShAmt = Op.getOperand(i: 2);
1241
1242 // Performs the following for a >> b:
1243 // unsigned r_high = a_high >> b;
1244 // r_high = (32 - b <= 0) ? 0 : r_high;
1245 //
1246 // unsigned r_low = a_low >> b;
1247 // r_low = (32 - b <= 0) ? r_high : r_low;
1248 // r_low = (b == 0) ? r_low : r_low | (a_high << (32 - b));
1249 // return (unsigned long long)r_high << 32 | r_low;
1250 // Note: This takes advantage of Lanai's shift behavior to avoid needing to
1251 // mask the shift amount.
1252
1253 SDValue Zero = DAG.getConstant(Val: 0, DL: dl, VT: MVT::i32);
1254 SDValue NegatedPlus32 = DAG.getNode(
1255 Opcode: ISD::SUB, DL: dl, VT: MVT::i32, N1: DAG.getConstant(Val: VTBits, DL: dl, VT: MVT::i32), N2: ShAmt);
1256 SDValue SetCC = DAG.getSetCC(DL: dl, VT: MVT::i32, LHS: NegatedPlus32, RHS: Zero, Cond: ISD::SETLE);
1257
1258 SDValue Hi = DAG.getNode(Opcode: ISD::SRL, DL: dl, VT: MVT::i32, N1: ShOpHi, N2: ShAmt);
1259 Hi = DAG.getSelect(DL: dl, VT: MVT::i32, Cond: SetCC, LHS: Zero, RHS: Hi);
1260
1261 SDValue Lo = DAG.getNode(Opcode: ISD::SRL, DL: dl, VT: MVT::i32, N1: ShOpLo, N2: ShAmt);
1262 Lo = DAG.getSelect(DL: dl, VT: MVT::i32, Cond: SetCC, LHS: Hi, RHS: Lo);
1263 SDValue CarryBits =
1264 DAG.getNode(Opcode: ISD::SHL, DL: dl, VT: MVT::i32, N1: ShOpHi, N2: NegatedPlus32);
1265 SDValue ShiftIsZero = DAG.getSetCC(DL: dl, VT: MVT::i32, LHS: ShAmt, RHS: Zero, Cond: ISD::SETEQ);
1266 Lo = DAG.getSelect(DL: dl, VT: MVT::i32, Cond: ShiftIsZero, LHS: Lo,
1267 RHS: DAG.getNode(Opcode: ISD::OR, DL: dl, VT: MVT::i32, N1: Lo, N2: CarryBits));
1268
1269 SDValue Ops[2] = {Lo, Hi};
1270 return DAG.getMergeValues(Ops, dl);
1271}
1272
1273// Helper function that checks if N is a null or all ones constant.
1274static inline bool isZeroOrAllOnes(SDValue N, bool AllOnes) {
1275 return AllOnes ? isAllOnesConstant(V: N) : isNullConstant(V: N);
1276}
1277
1278// Return true if N is conditionally 0 or all ones.
1279// Detects these expressions where cc is an i1 value:
1280//
1281// (select cc 0, y) [AllOnes=0]
1282// (select cc y, 0) [AllOnes=0]
1283// (zext cc) [AllOnes=0]
1284// (sext cc) [AllOnes=0/1]
1285// (select cc -1, y) [AllOnes=1]
1286// (select cc y, -1) [AllOnes=1]
1287//
1288// * AllOnes determines whether to check for an all zero (AllOnes false) or an
1289// all ones operand (AllOnes true).
1290// * Invert is set when N is the all zero/ones constant when CC is false.
1291// * OtherOp is set to the alternative value of N.
1292//
1293// For example, for (select cc X, Y) and AllOnes = 0 if:
1294// * X = 0, Invert = False and OtherOp = Y
1295// * Y = 0, Invert = True and OtherOp = X
1296static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC,
1297 bool &Invert, SDValue &OtherOp,
1298 SelectionDAG &DAG) {
1299 switch (N->getOpcode()) {
1300 default:
1301 return false;
1302 case ISD::SELECT: {
1303 CC = N->getOperand(Num: 0);
1304 SDValue N1 = N->getOperand(Num: 1);
1305 SDValue N2 = N->getOperand(Num: 2);
1306 if (isZeroOrAllOnes(N: N1, AllOnes)) {
1307 Invert = false;
1308 OtherOp = N2;
1309 return true;
1310 }
1311 if (isZeroOrAllOnes(N: N2, AllOnes)) {
1312 Invert = true;
1313 OtherOp = N1;
1314 return true;
1315 }
1316 return false;
1317 }
1318 case ISD::ZERO_EXTEND: {
1319 // (zext cc) can never be the all ones value.
1320 if (AllOnes)
1321 return false;
1322 CC = N->getOperand(Num: 0);
1323 if (CC.getValueType() != MVT::i1)
1324 return false;
1325 SDLoc dl(N);
1326 EVT VT = N->getValueType(ResNo: 0);
1327 OtherOp = DAG.getConstant(Val: 1, DL: dl, VT);
1328 Invert = true;
1329 return true;
1330 }
1331 case ISD::SIGN_EXTEND: {
1332 CC = N->getOperand(Num: 0);
1333 if (CC.getValueType() != MVT::i1)
1334 return false;
1335 SDLoc dl(N);
1336 EVT VT = N->getValueType(ResNo: 0);
1337 Invert = !AllOnes;
1338 if (AllOnes)
1339 // When looking for an AllOnes constant, N is an sext, and the 'other'
1340 // value is 0.
1341 OtherOp = DAG.getConstant(Val: 0, DL: dl, VT);
1342 else
1343 OtherOp = DAG.getAllOnesConstant(DL: dl, VT);
1344 return true;
1345 }
1346 }
1347}
1348
1349// Combine a constant select operand into its use:
1350//
1351// (add (select cc, 0, c), x) -> (select cc, x, (add, x, c))
1352// (sub x, (select cc, 0, c)) -> (select cc, x, (sub, x, c))
1353// (and (select cc, -1, c), x) -> (select cc, x, (and, x, c)) [AllOnes=1]
1354// (or (select cc, 0, c), x) -> (select cc, x, (or, x, c))
1355// (xor (select cc, 0, c), x) -> (select cc, x, (xor, x, c))
1356//
1357// The transform is rejected if the select doesn't have a constant operand that
1358// is null, or all ones when AllOnes is set.
1359//
1360// Also recognize sext/zext from i1:
1361//
1362// (add (zext cc), x) -> (select cc (add x, 1), x)
1363// (add (sext cc), x) -> (select cc (add x, -1), x)
1364//
1365// These transformations eventually create predicated instructions.
1366static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp,
1367 TargetLowering::DAGCombinerInfo &DCI,
1368 bool AllOnes) {
1369 SelectionDAG &DAG = DCI.DAG;
1370 EVT VT = N->getValueType(ResNo: 0);
1371 SDValue NonConstantVal;
1372 SDValue CCOp;
1373 bool SwapSelectOps;
1374 if (!isConditionalZeroOrAllOnes(N: Slct.getNode(), AllOnes, CC&: CCOp, Invert&: SwapSelectOps,
1375 OtherOp&: NonConstantVal, DAG))
1376 return SDValue();
1377
1378 // Slct is now know to be the desired identity constant when CC is true.
1379 SDValue TrueVal = OtherOp;
1380 SDValue FalseVal =
1381 DAG.getNode(Opcode: N->getOpcode(), DL: SDLoc(N), VT, N1: OtherOp, N2: NonConstantVal);
1382 // Unless SwapSelectOps says CC should be false.
1383 if (SwapSelectOps)
1384 std::swap(a&: TrueVal, b&: FalseVal);
1385
1386 return DAG.getNode(Opcode: ISD::SELECT, DL: SDLoc(N), VT, N1: CCOp, N2: TrueVal, N3: FalseVal);
1387}
1388
1389// Attempt combineSelectAndUse on each operand of a commutative operator N.
1390static SDValue
1391combineSelectAndUseCommutative(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
1392 bool AllOnes) {
1393 SDValue N0 = N->getOperand(Num: 0);
1394 SDValue N1 = N->getOperand(Num: 1);
1395 if (N0.getNode()->hasOneUse())
1396 if (SDValue Result = combineSelectAndUse(N, Slct: N0, OtherOp: N1, DCI, AllOnes))
1397 return Result;
1398 if (N1.getNode()->hasOneUse())
1399 if (SDValue Result = combineSelectAndUse(N, Slct: N1, OtherOp: N0, DCI, AllOnes))
1400 return Result;
1401 return SDValue();
1402}
1403
1404// PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
1405static SDValue PerformSUBCombine(SDNode *N,
1406 TargetLowering::DAGCombinerInfo &DCI) {
1407 SDValue N0 = N->getOperand(Num: 0);
1408 SDValue N1 = N->getOperand(Num: 1);
1409
1410 // fold (sub x, (select cc, 0, c)) -> (select cc, x, (sub, x, c))
1411 if (N1.getNode()->hasOneUse())
1412 if (SDValue Result = combineSelectAndUse(N, Slct: N1, OtherOp: N0, DCI, /*AllOnes=*/false))
1413 return Result;
1414
1415 return SDValue();
1416}
1417
1418SDValue LanaiTargetLowering::PerformDAGCombine(SDNode *N,
1419 DAGCombinerInfo &DCI) const {
1420 switch (N->getOpcode()) {
1421 default:
1422 break;
1423 case ISD::ADD:
1424 case ISD::OR:
1425 case ISD::XOR:
1426 return combineSelectAndUseCommutative(N, DCI, /*AllOnes=*/false);
1427 case ISD::AND:
1428 return combineSelectAndUseCommutative(N, DCI, /*AllOnes=*/true);
1429 case ISD::SUB:
1430 return PerformSUBCombine(N, DCI);
1431 }
1432
1433 return SDValue();
1434}
1435
1436void LanaiTargetLowering::computeKnownBitsForTargetNode(
1437 const SDValue Op, KnownBits &Known, const APInt &DemandedElts,
1438 const SelectionDAG &DAG, unsigned Depth) const {
1439 unsigned BitWidth = Known.getBitWidth();
1440 switch (Op.getOpcode()) {
1441 default:
1442 break;
1443 case LanaiISD::SETCC:
1444 Known = KnownBits(BitWidth);
1445 Known.Zero.setBits(loBit: 1, hiBit: BitWidth);
1446 break;
1447 case LanaiISD::SELECT_CC:
1448 KnownBits Known2;
1449 Known = DAG.computeKnownBits(Op: Op->getOperand(Num: 0), Depth: Depth + 1);
1450 Known2 = DAG.computeKnownBits(Op: Op->getOperand(Num: 1), Depth: Depth + 1);
1451 Known = Known.intersectWith(RHS: Known2);
1452 break;
1453 }
1454}
1455