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