#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "MCTargetDesc/PPCPredicates.h"
#include "PPC.h"
#include "PPCISelLowering.h"
#include "PPCMachineFunctionInfo.h"
#include "PPCSubtarget.h"
#include "PPCTargetMachine.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGenTypes/MachineValueType.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/IntrinsicsPowerPC.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iterator>
#include <limits>
#include <memory>
#include <new>
#include <tuple>
#include <utility>
usingnamespacellvm;
#define DEBUG_TYPE …
#define PASS_NAME …
STATISTIC(NumSextSetcc,
"Number of (sext(setcc)) nodes expanded into GPR sequence.");
STATISTIC(NumZextSetcc,
"Number of (zext(setcc)) nodes expanded into GPR sequence.");
STATISTIC(SignExtensionsAdded,
"Number of sign extensions for compare inputs added.");
STATISTIC(ZeroExtensionsAdded,
"Number of zero extensions for compare inputs added.");
STATISTIC(NumLogicOpsOnComparison,
"Number of logical ops on i1 values calculated in GPR.");
STATISTIC(OmittedForNonExtendUses,
"Number of compares not eliminated as they have non-extending uses.");
STATISTIC(NumP9Setb,
"Number of compares lowered to setb.");
cl::opt<bool> ANDIGlueBug("expose-ppc-andi-glue-bug",
cl::desc("expose the ANDI glue bug on PPC"), cl::Hidden);
static cl::opt<bool>
UseBitPermRewriter("ppc-use-bit-perm-rewriter", cl::init(true),
cl::desc("use aggressive ppc isel for bit permutations"),
cl::Hidden);
static cl::opt<bool> BPermRewriterNoMasking(
"ppc-bit-perm-rewriter-stress-rotates",
cl::desc("stress rotate selection in aggressive ppc isel for "
"bit permutations"),
cl::Hidden);
static cl::opt<bool> EnableBranchHint(
"ppc-use-branch-hint", cl::init(true),
cl::desc("Enable static hinting of branches on ppc"),
cl::Hidden);
static cl::opt<bool> EnableTLSOpt(
"ppc-tls-opt", cl::init(true),
cl::desc("Enable tls optimization peephole"),
cl::Hidden);
enum ICmpInGPRType { … };
static cl::opt<ICmpInGPRType> CmpInGPR(
"ppc-gpr-icmps", cl::Hidden, cl::init(ICGPR_All),
cl::desc("Specify the types of comparisons to emit GPR-only code for."),
cl::values(clEnumValN(ICGPR_None, "none", "Do not modify integer comparisons."),
clEnumValN(ICGPR_All, "all", "All possible int comparisons in GPRs."),
clEnumValN(ICGPR_I32, "i32", "Only i32 comparisons in GPRs."),
clEnumValN(ICGPR_I64, "i64", "Only i64 comparisons in GPRs."),
clEnumValN(ICGPR_NonExtIn, "nonextin",
"Only comparisons where inputs don't need [sz]ext."),
clEnumValN(ICGPR_Zext, "zext", "Only comparisons with zext result."),
clEnumValN(ICGPR_ZextI32, "zexti32",
"Only i32 comparisons with zext result."),
clEnumValN(ICGPR_ZextI64, "zexti64",
"Only i64 comparisons with zext result."),
clEnumValN(ICGPR_Sext, "sext", "Only comparisons with sext result."),
clEnumValN(ICGPR_SextI32, "sexti32",
"Only i32 comparisons with sext result."),
clEnumValN(ICGPR_SextI64, "sexti64",
"Only i64 comparisons with sext result.")));
namespace {
class PPCDAGToDAGISel : public SelectionDAGISel { … };
class PPCDAGToDAGISelLegacy : public SelectionDAGISelLegacy { … };
}
char PPCDAGToDAGISelLegacy::ID = …;
INITIALIZE_PASS(…)
SDNode *PPCDAGToDAGISel::getGlobalBaseReg() { … }
static bool hasTocDataAttr(SDValue Val) { … }
static CodeModel::Model getCodeModel(const PPCSubtarget &Subtarget,
const TargetMachine &TM,
const SDNode *Node) { … }
static bool isInt32Immediate(SDNode *N, unsigned &Imm) { … }
static bool isInt64Immediate(SDNode *N, uint64_t &Imm) { … }
static bool isInt32Immediate(SDValue N, unsigned &Imm) { … }
static bool isInt64Immediate(SDValue N, uint64_t &Imm) { … }
static unsigned getBranchHint(unsigned PCC,
const FunctionLoweringInfo &FuncInfo,
const SDValue &DestMBB) { … }
static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { … }
void PPCDAGToDAGISel::selectFrameIndex(SDNode *SN, SDNode *N, uint64_t Offset) { … }
bool PPCDAGToDAGISel::isRotateAndMask(SDNode *N, unsigned Mask,
bool isShiftMask, unsigned &SH,
unsigned &MB, unsigned &ME) { … }
static bool isThreadPointerAcquisitionNode(SDValue Base, SelectionDAG *CurDAG) { … }
static bool canOptimizeTLSDFormToXForm(SelectionDAG *CurDAG, SDValue Base) { … }
bool PPCDAGToDAGISel::tryTLSXFormStore(StoreSDNode *ST) { … }
bool PPCDAGToDAGISel::tryTLSXFormLoad(LoadSDNode *LD) { … }
bool PPCDAGToDAGISel::tryBitfieldInsert(SDNode *N) { … }
static unsigned allUsesTruncate(SelectionDAG *CurDAG, SDNode *N) { … }
static int findContiguousZerosAtLeast(uint64_t Imm, unsigned Num) { … }
static SDNode *selectI64ImmDirect(SelectionDAG *CurDAG, const SDLoc &dl,
uint64_t Imm, unsigned &InstCnt) { … }
static SDNode *selectI64ImmDirectPrefix(SelectionDAG *CurDAG, const SDLoc &dl,
uint64_t Imm, unsigned &InstCnt) { … }
static SDNode *selectI64Imm(SelectionDAG *CurDAG, const SDLoc &dl, uint64_t Imm,
unsigned *InstCnt = nullptr) { … }
static SDNode *selectI64Imm(SelectionDAG *CurDAG, SDNode *N) { … }
namespace {
class BitPermutationSelector { … };
class IntegerCompareEliminator { … };
SDNode *IntegerCompareEliminator::tryEXTEND(SDNode *N) { … }
SDNode *IntegerCompareEliminator::tryLogicOpOfCompares(SDNode *N) { … }
SDValue IntegerCompareEliminator::computeLogicOpInGPR(SDValue LogicOp) { … }
SDValue IntegerCompareEliminator::signExtendInputIfNeeded(SDValue Input) { … }
SDValue IntegerCompareEliminator::zeroExtendInputIfNeeded(SDValue Input) { … }
SDValue IntegerCompareEliminator::addExtOrTrunc(SDValue NatWidthRes,
ExtOrTruncConversion Conv) { … }
SDValue
IntegerCompareEliminator::getCompoundZeroComparisonInGPR(SDValue LHS, SDLoc dl,
ZeroCompare CmpTy) { … }
SDValue
IntegerCompareEliminator::get32BitZExtCompare(SDValue LHS, SDValue RHS,
ISD::CondCode CC,
int64_t RHSValue, SDLoc dl) { … }
SDValue
IntegerCompareEliminator::get32BitSExtCompare(SDValue LHS, SDValue RHS,
ISD::CondCode CC,
int64_t RHSValue, SDLoc dl) { … }
SDValue
IntegerCompareEliminator::get64BitZExtCompare(SDValue LHS, SDValue RHS,
ISD::CondCode CC,
int64_t RHSValue, SDLoc dl) { … }
SDValue
IntegerCompareEliminator::get64BitSExtCompare(SDValue LHS, SDValue RHS,
ISD::CondCode CC,
int64_t RHSValue, SDLoc dl) { … }
static bool allUsesExtend(SDValue Compare, SelectionDAG *CurDAG) { … }
SDValue IntegerCompareEliminator::getSETCCInGPR(SDValue Compare,
SetccInGPROpts ConvOpts) { … }
}
bool PPCDAGToDAGISel::tryIntCompareInGPR(SDNode *N) { … }
bool PPCDAGToDAGISel::tryBitPermutation(SDNode *N) { … }
SDValue PPCDAGToDAGISel::SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC,
const SDLoc &dl, SDValue Chain) { … }
static PPC::Predicate getPredicateForSetCC(ISD::CondCode CC, const EVT &VT,
const PPCSubtarget *Subtarget) { … }
static unsigned getCRIdxForSetCC(ISD::CondCode CC, bool &Invert) { … }
static unsigned int getVCmpInst(MVT VecVT, ISD::CondCode CC,
bool HasVSX, bool &Swap, bool &Negate) { … }
bool PPCDAGToDAGISel::trySETCC(SDNode *N) { … }
bool PPCDAGToDAGISel::isOffsetMultipleOf(SDNode *N, unsigned Val) const { … }
void PPCDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) { … }
static bool mayUseP9Setb(SDNode *N, const ISD::CondCode &CC, SelectionDAG *DAG,
bool &NeedSwapOps, bool &IsUnCmp) { … }
static bool isSWTestOp(SDValue N) { … }
bool PPCDAGToDAGISel::tryFoldSWTestBRCC(SDNode *N) { … }
bool PPCDAGToDAGISel::trySelectLoopCountIntrinsic(SDNode *N) { … }
bool PPCDAGToDAGISel::tryAsSingleRLWINM(SDNode *N) { … }
bool PPCDAGToDAGISel::tryAsSingleRLWINM8(SDNode *N) { … }
bool PPCDAGToDAGISel::tryAsPairOfRLDICL(SDNode *N) { … }
bool PPCDAGToDAGISel::tryAsSingleRLWIMI(SDNode *N) { … }
bool PPCDAGToDAGISel::tryAsSingleRLDCL(SDNode *N) { … }
bool PPCDAGToDAGISel::tryAsSingleRLDICL(SDNode *N) { … }
bool PPCDAGToDAGISel::tryAsSingleRLDICR(SDNode *N) { … }
bool PPCDAGToDAGISel::tryAsSingleRLDIMI(SDNode *N) { … }
void PPCDAGToDAGISel::Select(SDNode *N) { … }
SDValue PPCDAGToDAGISel::combineToCMPB(SDNode *N) { … }
void PPCDAGToDAGISel::foldBoolExts(SDValue &Res, SDNode *&N) { … }
void PPCDAGToDAGISel::PreprocessISelDAG() { … }
void PPCDAGToDAGISel::PostprocessISelDAG() { … }
bool PPCDAGToDAGISel::AllUsersSelectZero(SDNode *N) { … }
void PPCDAGToDAGISel::SwapAllSelectUsers(SDNode *N) { … }
void PPCDAGToDAGISel::PeepholeCROps() { … }
static bool PeepholePPC64ZExtGather(SDValue Op32,
SmallPtrSetImpl<SDNode *> &ToPromote) { … }
void PPCDAGToDAGISel::PeepholePPC64ZExt() { … }
static bool isVSXSwap(SDValue N) { … }
static bool isLaneInsensitive(SDValue N) { … }
static void reduceVSXSwap(SDNode *N, SelectionDAG *DAG) { … }
static bool hasAIXSmallTLSAttr(SDValue Val) { … }
static bool isEligibleToFoldADDIForFasterLocalAccesses(SelectionDAG *DAG,
SDValue ADDIToFold) { … }
static void foldADDIForFasterLocalAccesses(SDNode *N, SelectionDAG *DAG) { … }
void PPCDAGToDAGISel::PeepholePPC64() { … }
FunctionPass *llvm::createPPCISelDag(PPCTargetMachine &TM,
CodeGenOptLevel OptLevel) { … }