llvm/llvm/lib/Target/PowerPC/PPCFastISel.cpp

//===-- PPCFastISel.cpp - PowerPC FastISel implementation -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the PowerPC-specific support for the FastISel class. Some
// of the target-specific code is generated by tablegen in the file
// PPCGenFastISel.inc, which is #included here.
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/PPCPredicates.h"
#include "PPC.h"
#include "PPCCCState.h"
#include "PPCCallingConv.h"
#include "PPCISelLowering.h"
#include "PPCMachineFunctionInfo.h"
#include "PPCSubtarget.h"
#include "PPCTargetMachine.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/FastISel.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Operator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetMachine.h"

//===----------------------------------------------------------------------===//
//
// TBD:
//   fastLowerArguments: Handle simple cases.
//   PPCMaterializeGV: Handle TLS.
//   SelectCall: Handle function pointers.
//   SelectCall: Handle multi-register return values.
//   SelectCall: Optimize away nops for local calls.
//   processCallArgs: Handle bit-converted arguments.
//   finishCall: Handle multi-register return values.
//   PPCComputeAddress: Handle parameter references as FrameIndex's.
//   PPCEmitCmp: Handle immediate as operand 1.
//   SelectCall: Handle small byval arguments.
//   SelectIntrinsicCall: Implement.
//   SelectSelect: Implement.
//   Consider factoring isTypeLegal into the base class.
//   Implement switches and jump tables.
//
//===----------------------------------------------------------------------===//
usingnamespacellvm;

#define DEBUG_TYPE

namespace {

struct Address {};

class PPCFastISel final : public FastISel {};

} // end anonymous namespace

static std::optional<PPC::Predicate> getComparePred(CmpInst::Predicate Pred) {}

// Determine whether the type Ty is simple enough to be handled by
// fast-isel, and return its equivalent machine type in VT.
// FIXME: Copied directly from ARM -- factor into base class?
bool PPCFastISel::isTypeLegal(Type *Ty, MVT &VT) {}

// Determine whether the type Ty is simple enough to be handled by
// fast-isel as a load target, and return its equivalent machine type in VT.
bool PPCFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {}

bool PPCFastISel::isValueAvailable(const Value *V) const {}

// Given a value Obj, create an Address object Addr that represents its
// address.  Return false if we can't handle it.
bool PPCFastISel::PPCComputeAddress(const Value *Obj, Address &Addr) {}

// Fix up some addresses that can't be used directly.  For example, if
// an offset won't fit in an instruction field, we may need to move it
// into an index register.
void PPCFastISel::PPCSimplifyAddress(Address &Addr, bool &UseOffset,
                                     unsigned &IndexReg) {}

// Emit a load instruction if possible, returning true if we succeeded,
// otherwise false.  See commentary below for how the register class of
// the load is determined.
bool PPCFastISel::PPCEmitLoad(MVT VT, Register &ResultReg, Address &Addr,
                              const TargetRegisterClass *RC,
                              bool IsZExt, unsigned FP64LoadOpc) {}

// Attempt to fast-select a load instruction.
bool PPCFastISel::SelectLoad(const Instruction *I) {}

// Emit a store instruction to store SrcReg at Addr.
bool PPCFastISel::PPCEmitStore(MVT VT, unsigned SrcReg, Address &Addr) {}

// Attempt to fast-select a store instruction.
bool PPCFastISel::SelectStore(const Instruction *I) {}

// Attempt to fast-select a branch instruction.
bool PPCFastISel::SelectBranch(const Instruction *I) {}

// Attempt to emit a compare of the two source values.  Signed and unsigned
// comparisons are supported.  Return false if we can't handle it.
bool PPCFastISel::PPCEmitCmp(const Value *SrcValue1, const Value *SrcValue2,
                             bool IsZExt, unsigned DestReg,
                             const PPC::Predicate Pred) {}

// Attempt to fast-select a floating-point extend instruction.
bool PPCFastISel::SelectFPExt(const Instruction *I) {}

// Attempt to fast-select a floating-point truncate instruction.
bool PPCFastISel::SelectFPTrunc(const Instruction *I) {}

// Move an i32 or i64 value in a GPR to an f64 value in an FPR.
// FIXME: When direct register moves are implemented (see PowerISA 2.07),
// those should be used instead of moving via a stack slot when the
// subtarget permits.
// FIXME: The code here is sloppy for the 4-byte case.  Can use a 4-byte
// stack slot and 4-byte store/load sequence.  Or just sext the 4-byte
// case to 8 bytes which produces tighter code but wastes stack space.
unsigned PPCFastISel::PPCMoveToFPReg(MVT SrcVT, unsigned SrcReg,
                                     bool IsSigned) {}

// Attempt to fast-select an integer-to-floating-point conversion.
// FIXME: Once fast-isel has better support for VSX, conversions using
//        direct moves should be implemented.
bool PPCFastISel::SelectIToFP(const Instruction *I, bool IsSigned) {}

// Move the floating-point value in SrcReg into an integer destination
// register, and return the register (or zero if we can't handle it).
// FIXME: When direct register moves are implemented (see PowerISA 2.07),
// those should be used instead of moving via a stack slot when the
// subtarget permits.
unsigned PPCFastISel::PPCMoveToIntReg(const Instruction *I, MVT VT,
                                      unsigned SrcReg, bool IsSigned) {}

// Attempt to fast-select a floating-point-to-integer conversion.
// FIXME: Once fast-isel has better support for VSX, conversions using
//        direct moves should be implemented.
bool PPCFastISel::SelectFPToI(const Instruction *I, bool IsSigned) {}

// Attempt to fast-select a binary integer operation that isn't already
// handled automatically.
bool PPCFastISel::SelectBinaryIntOp(const Instruction *I, unsigned ISDOpcode) {}

// Handle arguments to a call that we're attempting to fast-select.
// Return false if the arguments are too complex for us at the moment.
bool PPCFastISel::processCallArgs(SmallVectorImpl<Value*> &Args,
                                  SmallVectorImpl<unsigned> &ArgRegs,
                                  SmallVectorImpl<MVT> &ArgVTs,
                                  SmallVectorImpl<ISD::ArgFlagsTy> &ArgFlags,
                                  SmallVectorImpl<unsigned> &RegArgs,
                                  CallingConv::ID CC,
                                  unsigned &NumBytes,
                                  bool IsVarArg) {}

// For a call that we've determined we can fast-select, finish the
// call sequence and generate a copy to obtain the return value (if any).
bool PPCFastISel::finishCall(MVT RetVT, CallLoweringInfo &CLI, unsigned &NumBytes) {}

bool PPCFastISel::fastLowerCall(CallLoweringInfo &CLI) {}

// Attempt to fast-select a return instruction.
bool PPCFastISel::SelectRet(const Instruction *I) {}

// Attempt to emit an integer extend of SrcReg into DestReg.  Both
// signed and zero extensions are supported.  Return false if we
// can't handle it.
bool PPCFastISel::PPCEmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
                                unsigned DestReg, bool IsZExt) {}

// Attempt to fast-select an indirect branch instruction.
bool PPCFastISel::SelectIndirectBr(const Instruction *I) {}

// Attempt to fast-select an integer truncate instruction.
bool PPCFastISel::SelectTrunc(const Instruction *I) {}

// Attempt to fast-select an integer extend instruction.
bool PPCFastISel::SelectIntExt(const Instruction *I) {}

// Attempt to fast-select an instruction that wasn't handled by
// the table-generated machinery.
bool PPCFastISel::fastSelectInstruction(const Instruction *I) {}

// Materialize a floating-point constant into a register, and return
// the register number (or zero if we failed to handle it).
unsigned PPCFastISel::PPCMaterializeFP(const ConstantFP *CFP, MVT VT) {}

// Materialize the address of a global value into a register, and return
// the register number (or zero if we failed to handle it).
unsigned PPCFastISel::PPCMaterializeGV(const GlobalValue *GV, MVT VT) {}

// Materialize a 32-bit integer constant into a register, and return
// the register number (or zero if we failed to handle it).
unsigned PPCFastISel::PPCMaterialize32BitInt(int64_t Imm,
                                             const TargetRegisterClass *RC) {}

// Materialize a 64-bit integer constant into a register, and return
// the register number (or zero if we failed to handle it).
unsigned PPCFastISel::PPCMaterialize64BitInt(int64_t Imm,
                                             const TargetRegisterClass *RC) {}

// Materialize an integer constant into a register, and return
// the register number (or zero if we failed to handle it).
unsigned PPCFastISel::PPCMaterializeInt(const ConstantInt *CI, MVT VT,
                                        bool UseSExt) {}

// Materialize a constant into a register, and return the register
// number (or zero if we failed to handle it).
unsigned PPCFastISel::fastMaterializeConstant(const Constant *C) {}

// Materialize the address created by an alloca into a register, and
// return the register number (or zero if we failed to handle it).
unsigned PPCFastISel::fastMaterializeAlloca(const AllocaInst *AI) {}

// Fold loads into extends when possible.
// FIXME: We can have multiple redundant extend/trunc instructions
// following a load.  The folding only picks up one.  Extend this
// to check subsequent instructions for the same pattern and remove
// them.  Thus ResultReg should be the def reg for the last redundant
// instruction in a chain, and all intervening instructions can be
// removed from parent.  Change test/CodeGen/PowerPC/fast-isel-fold.ll
// to add ELF64-NOT: rldicl to the appropriate tests when this works.
bool PPCFastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
                                      const LoadInst *LI) {}

// Attempt to lower call arguments in a faster way than done by
// the selection DAG code.
bool PPCFastISel::fastLowerArguments() {}

// Handle materializing integer constants into a register.  This is not
// automatically generated for PowerPC, so must be explicitly created here.
unsigned PPCFastISel::fastEmit_i(MVT Ty, MVT VT, unsigned Opc, uint64_t Imm) {}

// Override for ADDI and ADDI8 to set the correct register class
// on RHS operand 0.  The automatic infrastructure naively assumes
// GPRC for i32 and G8RC for i64; the concept of "no R0" is lost
// for these cases.  At the moment, none of the other automatically
// generated RI instructions require special treatment.  However, once
// SelectSelect is implemented, "isel" requires similar handling.
//
// Also be conservative about the output register class.  Avoid
// assigning R0 or X0 to the output register for GPRC and G8RC
// register classes, as any such result could be used in ADDI, etc.,
// where those regs have another meaning.
unsigned PPCFastISel::fastEmitInst_ri(unsigned MachineInstOpcode,
                                      const TargetRegisterClass *RC,
                                      unsigned Op0,
                                      uint64_t Imm) {}

// Override for instructions with one register operand to avoid use of
// R0/X0.  The automatic infrastructure isn't aware of the context so
// we must be conservative.
unsigned PPCFastISel::fastEmitInst_r(unsigned MachineInstOpcode,
                                     const TargetRegisterClass* RC,
                                     unsigned Op0) {}

// Override for instructions with two register operands to avoid use
// of R0/X0.  The automatic infrastructure isn't aware of the context
// so we must be conservative.
unsigned PPCFastISel::fastEmitInst_rr(unsigned MachineInstOpcode,
                                      const TargetRegisterClass* RC,
                                      unsigned Op0, unsigned Op1) {}

namespace llvm {
  // Create the fast instruction selector for PowerPC64 ELF.
  FastISel *PPC::createFastISel(FunctionLoweringInfo &FuncInfo,
                                const TargetLibraryInfo *LibInfo) {}
}